All files / src/components/music/piano PianoRollPlaybackController.tsx

0% Statements 0/36
0% Branches 0/4
0% Functions 0/8
0% Lines 0/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90                                                                                                                                                                                   
import React, { useEffect, useLayoutEffect, useRef } from "react";
import API from "renderer/lib/api";
import { useAppSelector } from "store/hooks";
import {
  calculatePlaybackTrackerPosition,
  calculateDocumentWidth,
} from "./helpers";
import { StyledPianoRollPlayhead } from "./style";
 
interface PianoRollPlaybackControllerProps {
  scrollElement: HTMLDivElement | null;
  sequenceLength: number;
}
 
export const PianoRollPlaybackController = ({
  scrollElement,
  sequenceLength,
}: PianoRollPlaybackControllerProps) => {
  const playbackSequence = useAppSelector(
    (state) => state.tracker.playbackSequence,
  );
  const playbackRow = useAppSelector((state) => state.tracker.playbackRow);
  const playbackCurrentTick = useAppSelector(
    (state) => state.tracker.playbackCurrentTick,
  );
  const playbackTicksPerRow = useAppSelector(
    (state) => state.tracker.playbackTicksPerRow,
  );
  const playbackFollowScrollRevision = useAppSelector(
    (state) => state.tracker.playbackFollowScrollRevision,
  );
 
  const playheadLeft = Math.round(
    calculatePlaybackTrackerPosition(
      playbackSequence,
      playbackRow,
      playbackCurrentTick,
      playbackTicksPerRow,
    ),
  );
  const lastFollowScrollRevisionRef = useRef(playbackFollowScrollRevision);
 
  useEffect(() => {
    Iif (playbackSequence >= sequenceLength) {
      API.music.sendToMusicWindow({
        action: "position",
        position: { sequence: 0, row: 0 },
      });
    }
  }, [playbackSequence, sequenceLength]);
 
  useLayoutEffect(() => {
    Iif (playbackFollowScrollRevision === lastFollowScrollRevisionRef.current) {
      return;
    }
    lastFollowScrollRevisionRef.current = playbackFollowScrollRevision;
 
    const scrollEl = scrollElement;
    Iif (!scrollEl) {
      return;
    }
 
    const viewportWidth = scrollEl.clientWidth;
    const maxScrollLeft = Math.max(0, calculateDocumentWidth(sequenceLength));
    const nextScrollLeft = Math.max(
      0,
      Math.min(playheadLeft - viewportWidth * 0.3, maxScrollLeft),
    );
 
    Iif (Math.abs(scrollEl.scrollLeft - nextScrollLeft) < 1) {
      return;
    }
 
    scrollEl.scrollLeft = nextScrollLeft;
  }, [
    playbackFollowScrollRevision,
    playheadLeft,
    scrollElement,
    sequenceLength,
  ]);
 
  return (
    <StyledPianoRollPlayhead
      style={{
        transform: `translateX(${playheadLeft}px)`,
      }}
    />
  );
};