Repository: freeCodeCamp/freeCodeCamp
File: client/src/templates/Challenges/components/scene/scene.tsx (TypeScript)

Code before:
          // @ts-expect-error it's not a node timer
          finishTimerRef.current = setTimeout(() => {
            const endTimeStamp = sToMs(audio.finishTimestamp!); // it exists because duration is not Infinity
            const audioCurrentTime = sToMs(audioRef.current.currentTime);
            const remainingTime = endTimeStamp - audioCurrentTime;
            // For some reason, despite the setTimeout resolving at the right
            // time, the currentTime can be smaller than expected. That means
            // that if we pause now it will cut off the last part.
            if (remainingTime < 100) {
              // 100ms is arbitrary and may need to be adjusted if people still
              // notice the cut off

              resetAudio();
            } else {
              // @ts-expect-error it's not a node timer
              finishTimerRef.current = setTimeout(() => {
                resetAudio();
              }, remainingTime);
            }
          }, audioEndDelay);
        });
      }
    }, audioStartDelay);
  }, [audio, duration, isPlaying, resetAudio, sceneIsReady]);

  const playScene = useCallback(
    (eventType: 'play' | 'pause') => {
      if (eventType === 'pause') {
        handlePause();
      } else if (eventType === 'play') {
        handlePlay();
      }
    },
    [handlePause, handlePlay]
  );

  const resetAnimation = useCallback(() => {
    usedCommandsRef.current.clear();
    startClocktimeRef.current = 0;
    setCurrentTime(0);
    setShowDialogue(false);
    setDialogue(initDialogue);
    setCharacters(initCharacters);
    setBackground(initBackground);
  }, [initCharacters, initBackground]);

  const resetScene = () => {
    setIsPlaying(false);
    isPlayingSceneRef.current = false;
    pausedAtRef.current = 0;
  };

Review comment (refactor):
This is a silly name. `onNotify` is a bit more abstract, but not obviously misleading. I'll update this next week.

Code after:
              // 100ms is arbitrary and may need to be adjusted if people still
              // notice the cut off

              resetAudio();
            } else {
              // @ts-expect-error it's not a node timer
              finishTimerRef.current = setTimeout(() => {
                resetAudio();
              }, remainingTime);
            }
          }, audioEndDelay);
        });
      }
    }, audioStartDelay);
  }, [audio, duration, isPlaying, resetAudio, sceneIsReady]);

  const handlePause = useCallback(() => {
    isPlayingSceneRef.current = false;
    pausedAtRef.current = currentTime;
    pauseAudio();
    pauseAnimation();
  }, [currentTime]);

  const handleStop = useCallback(() => {
    usedCommandsRef.current.clear();
    pauseAudio();
    pauseAnimation();
    audioRef.current.currentTime = audio.startTimestamp || 0;
    setCurrentTime(0);
    setIsPlaying(false);
    isPlayingSceneRef.current = false;
    setDialogue(initDialogue);
    setCharacters(initCharacters);
    setBackground(initBackground);
  }, [audio, initCharacters, initBackground]);

  const resetAnimation = useCallback(() => {
    usedCommandsRef.current.clear();
    startClocktimeRef.current = 0;
    setCurrentTime(0);
    setDialogue(initDialogue);
    setCharacters(initCharacters);
    setBackground(initBackground);
  }, [initCharacters, initBackground]);

  const resetScene = () => {
    setIsPlaying(false);
    isPlayingSceneRef.current = false;
    pausedAtRef.current = 0;
  };