<commit_before>/** @jsx h */
import { h, Component } from 'preact';

import Menu from '../../components/Menu';
import Container from '../../components/Container';
import Error from '../../components/Error';
import Align from '../../components/Align';
import Spinner from '../../components/Spinner';
import RecordInstructions from '../../components/RecordInstructions';
import RecordCountdown from '../../components/RecordCountdown';

import Room from '../../room';
import Orb from '../../orb';
import audio from '../../audio';
import viewer from '../../viewer';
import settings from '../../settings';
import recording from '../../recording';
import createTimeline from '../../lib/timeline';
import controllers from '../../controllers';
import transition from '../../transition';
import { waitRoomColor, getRoomColor } from '../../theme/colors';
import { sleep } from '../../utils/async';
import layout from '../../room/layout';

export default class Playback extends Component {
  constructor() {
    super();

    this.state = {
    };

    this.controllersTick = this.controllersTick.bind(this);
    this.tick = this.tick.bind(this);
    this.performFinish = this.performFinish.bind(this);
    this.performStart = this.performStart.bind(this);

    this.controllerSettings = {
      pressToFinish: {
        removeOnPress: true,
        left: {
          text: 'press\nto\nrestart',
          onPress: async () => {
            await transition.enter({
              text: 'Let’s try that again...',
            });
            if (this.mounted) this.props.goto('record');
          },
        },
        right: {
          text: 'press\nto\nfinish',
          onPress: this.performFinish,
        },
      },
      pressToStart: {
        removeOnPress: true,
        right: {
          text: 'press\nto\nstart',
          onPress: this.performStart,
        },
      },
    };

    this.timeline = createTimeline([
      {
        time: 0,
        callback: () => {
          this.room.changeColor(waitRoomColor);
          this.orb2.fadeOut();
          this.orb.fadeIn();
          if (audio.totalProgress > 1) {
            controllers.update(this.controllerSettings.pressToFinish);
          }
          const round = Math.floor(audio.totalProgress / 2);
          const countdownSeconds = Math.round(audio.loopDuration - audio.time);
          this.setState({ round, countdownSeconds });
          if (round === settings.maxLayerCount) {
            this.performFinish();
            controllers.update();
          }
        },
      },
      {
        time: 1,
        callback: () => {
          this.room.changeColor(this.roomColor);
          controllers.update();
        },
      },
    ]);
  }

  componentDidMount() {
    this.mounted = true;
    const { roomIndex, hideHead } = this.props;
    recording.setup({ roomIndex, hideHead });
    this.roomColor = getRoomColor(roomIndex);
    this.asyncMount();
  }

  componentWillUnmount() {
    this.mounted = false;
  }

  setLoading(loading) {
    this.setState({ loading });
  }

  async asyncMount() {
    Room.reset();
    this.setLoading('Loading audio…');
    await audio.load({
      src: `/public/sound/room-${layout.loopIndex(recording.roomIndex)}.ogg`,
      loops: 2,
      loopOffset: 0.5,
    });
    this.setLoading();
    if (!this.mounted) return;

    viewer.switchCamera('default');
    this.room = new Room({
      recording,
      index: recording.roomIndex,
      single: true,
    });
    this.room.changeColor(waitRoomColor);

    viewer.events.on('tick', this.controllersTick);

    controllers.add();
<commit_msg>move timeline callbacks into class<commit_after>/** @jsx h */
import { h, Component } from 'preact';

import Menu from '../../components/Menu';
import Container from '../../components/Container';
import Error from '../../components/Error';
import Align from '../../components/Align';
import Spinner from '../../components/Spinner';
import RecordInstructions from '../../components/RecordInstructions';
import RecordCountdown from '../../components/RecordCountdown';

import Room from '../../room';
import Orb from '../../orb';
import audio from '../../audio';
import viewer from '../../viewer';
import settings from '../../settings';
import recording from '../../recording';
import createTimeline from '../../lib/timeline';
import controllers from '../../controllers';
import transition from '../../transition';
import { waitRoomColor, getRoomColor } from '../../theme/colors';
import { sleep } from '../../utils/async';
import layout from '../../room/layout';

export default class Playback extends Component {
  constructor() {
    super();

    this.state = {
    };

    this.controllersTick = this.controllersTick.bind(this);
    this.tick = this.tick.bind(this);
    this.performFinish = this.performFinish.bind(this);
    this.performStart = this.performStart.bind(this);
    this.onOrbLeftRoom = this.onOrbLeftRoom.bind(this);
    this.onOrbEnteredRoom = this.onOrbEnteredRoom.bind(this);

    this.controllerSettings = {
      pressToFinish: {
        removeOnPress: true,
        left: {
          text: 'press\nto\nrestart',
          onPress: async () => {
            await transition.enter({
              text: 'Let’s try that again...',
            });
            if (this.mounted) this.props.goto('record');
          },
        },
        right: {
          text: 'press\nto\nfinish',
          onPress: this.performFinish,
        },
      },
      pressToStart: {
        removeOnPress: true,
        right: {
          text: 'press\nto\nstart',
          onPress: this.performStart,
        },
      },
    };

    this.timeline = createTimeline([
      {
        time: 0,
        callback: this.onOrbLeftRoom,
      },
      {
        time: 1,
        callback: this.onOrbEnteredRoom,
      },
    ]);
  }

  componentDidMount() {
    this.mounted = true;
    const { roomIndex, hideHead } = this.props;
    recording.setup({ roomIndex, hideHead });
    this.roomColor = getRoomColor(roomIndex);
    this.asyncMount();
  }

  componentWillUnmount() {
    this.mounted = false;
  }

  onOrbLeftRoom() {
    this.room.changeColor(waitRoomColor);
    this.orb2.fadeOut();
    this.orb.fadeIn();
    if (audio.totalProgress > 1) {
      controllers.update(this.controllerSettings.pressToFinish);
    }
    const round = Math.floor(audio.totalProgress / 2);
    const countdownSeconds = Math.round(audio.loopDuration - audio.time);
    this.setState({ round, countdownSeconds });
    if (round === settings.maxLayerCount) {
      this.performFinish();
      controllers.update();
    }
  }

  onOrbEnteredRoom() {
    this.room.changeColor(this.roomColor);
    controllers.update();
  }

  setLoading(loading) {
    this.setState({ loading });
  }

  async asyncMount() {
    Room.reset();
    this.setLoading('Loading audio…');
    await audio.load({
      src: `/public/sound/room-${layout.loopIndex(recording.roomIndex)}.ogg`,
      loops: 2,
      loopOffset: 0.5,
    });
    this.setLoading();
    if (!this.mounted) return;

    viewer.switchCamera('default');
    this.room = new Room({
      recording,
      index: recording.roomIndex,
      single: true,
    });
    this.room.changeColor(waitRoomColor);

    viewer.events.on('tick', this.controllersTick);

    controllers.add();

{'fraction_non_alphanumeric': 0.1572112098427888, 'fraction_numerical': 0.0021872863978127134, 'mean_word_length': 2.342165372316126, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '946878', 'n_tokens_mistral': 2117, 'n_tokens_neox': 2103, 'n_words': 444}