diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3d98a5a..a53f3ac 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -181,82 +181,73 @@ function App(): JSX.Element { // handlers - const handleKeyPress = useCallback( - (evt: KeyboardEvent) => { - if (evt.code != 'Space') { - return; - } + const handleKeyPress = (evt: KeyboardEvent) => { + if (evt.code != 'Space') { + return; + } - if (audio.paused) { - handlePlay(); - } else { - handlePause(); - } - }, - [selection] - ); + if (audio.paused) { + handlePlay(); + } else { + handlePause(); + } + }; // handler called when the selection in the overview (zoom setting) is changed. - const handleOverviewSelectionChange = useCallback( - (newViewport: Frames) => { - if (mediaSet == null) { - return; - } - console.log('set new viewport', newViewport); - setViewport({ ...newViewport }); + const handleOverviewSelectionChange = (newViewport: Frames) => { + if (mediaSet == null) { + return; + } + console.log('set new viewport', newViewport); + setViewport({ ...newViewport }); - if (!audio.paused) { - return; - } + if (!audio.paused) { + return; + } - setPositionFromFrame(newViewport.start); - }, - [mediaSet, audio, video, selection] - ); + setPositionFromFrame(newViewport.start); + }; // handler called when the selection in the main waveform view is changed. - const handleWaveformSelectionChange = useCallback( - (newSelection: Frames) => { - setSelection(newSelection); + const handleWaveformSelectionChange = (newSelection: Frames) => { + setSelection(newSelection); - if (mediaSet == null) { - return; - } + if (mediaSet == null) { + return; + } - // move playback position to start of selection - const ratio = newSelection.start / mediaSet.audioFrames; - const currentTime = - (mediaSet.audioFrames / mediaSet.audioSampleRate) * ratio; - audio.currentTime = currentTime; - video.currentTime = currentTime; - }, - [mediaSet, audio, video, selection] - ); + // move playback position to start of selection + const ratio = newSelection.start / mediaSet.audioFrames; + const currentTime = + (mediaSet.audioFrames / mediaSet.audioSampleRate) * ratio; + audio.currentTime = currentTime; + video.currentTime = currentTime; + }; - const handlePlay = useCallback(() => { + const handlePlay = () => { audio.play(); video.play(); - }, [audio, video]); + }; - const handlePause = useCallback(() => { + const handlePause = () => { video.pause(); audio.pause(); if (selection.start != selection.end) { setPositionFromFrame(selection.start); } - }, [audio, video, selection]); + }; - const handleClip = useCallback(() => { + const handleClip = () => { if (!window.showSaveFilePicker) { downloadClipHTTP(); return; } downloadClipFileSystemAccessAPI(); - }, [mediaSet, selection]); + }; - const downloadClipHTTP = useCallback(() => { + const downloadClipHTTP = () => { (async function () { if (mediaSet == null) { return; @@ -285,9 +276,9 @@ function App(): JSX.Element { document.body.appendChild(form); form.submit(); })(); - }, [mediaSet, selection]); + }; - const downloadClipFileSystemAccessAPI = useCallback(() => { + const downloadClipFileSystemAccessAPI = () => { (async function () { if (mediaSet == null) { return; @@ -312,9 +303,9 @@ function App(): JSX.Element { await fileStream.close(); console.debug('closed stream'); })(); - }, [mediaSet, selection]); + }; - const handleZoomIn = useCallback(() => { + const handleZoomIn = () => { if (mediaSet == null) { return; } @@ -325,9 +316,9 @@ function App(): JSX.Element { ...viewport, end: viewport.end - Math.round((viewport.end - viewport.start) / 2), }); - }, [mediaSet, viewport]); + }; - const handleZoomOut = useCallback(() => { + const handleZoomOut = () => { if (mediaSet == null) { return; } @@ -342,7 +333,7 @@ function App(): JSX.Element { ...viewport, end: end, }); - }, [mediaSet, viewport]); + }; const setPositionFromFrame = useCallback( (frame: number) => { @@ -355,7 +346,7 @@ function App(): JSX.Element { audio.currentTime = currentTime; video.currentTime = currentTime; }, - [mediaSet, audio, video] + [mediaSet] ); // helpers diff --git a/frontend/src/HudCanvas.tsx b/frontend/src/HudCanvas.tsx index c68e549..82d9128 100644 --- a/frontend/src/HudCanvas.tsx +++ b/frontend/src/HudCanvas.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef, useCallback, MouseEvent } from 'react'; +import { useState, useEffect, useRef, MouseEvent } from 'react'; interface Styles { borderLineWidth: number; @@ -174,108 +174,102 @@ export const HudCanvas: React.FC = ({ return x; }; - const handleMouseDown = useCallback( - (evt: MouseEvent) => { - if (mode != Mode.Normal) { - return; + const handleMouseDown = (evt: MouseEvent) => { + if (mode != Mode.Normal) { + return; + } + + const x = getCanvasX(evt); + + if (isHoveringSelectionStart(x)) { + setMode(Mode.ResizingStart); + moveOffsetX.current = x; + } else if (isHoveringSelectionEnd(x)) { + setMode(Mode.ResizingEnd); + moveOffsetX.current = x; + } else if (isHoveringSelection(x)) { + setMode(Mode.Dragging); + setCursor('pointer'); + moveOffsetX.current = x; + } else { + setMode(Mode.Selecting); + setCursor('col-resize'); + moveOffsetX.current = x; + setNewSelection({ start: x, end: x }); + } + }; + + const handleMouseMove = (evt: MouseEvent) => { + const x = getCanvasX(evt); + + switch (mode) { + case Mode.Normal: { + if (isHoveringSelectionStart(x)) { + setHoverState(HoverState.OverSelectionStart); + setCursor('col-resize'); + } else if (isHoveringSelectionEnd(x)) { + setHoverState(HoverState.OverSelectionEnd); + setCursor('col-resize'); + } else if (isHoveringSelection(x)) { + setHoverState(HoverState.OverSelection); + setCursor('pointer'); + } else { + setCursor('auto'); + } + break; } + case Mode.ResizingStart: { + const diff = x - moveOffsetX.current; + const start = constrainXToCanvas(selection.start + diff); - const x = getCanvasX(evt); + if (start > selection.end) { + setNewSelection({ start: selection.end, end: start }); + break; + } - if (isHoveringSelectionStart(x)) { - setMode(Mode.ResizingStart); - moveOffsetX.current = x; - } else if (isHoveringSelectionEnd(x)) { - setMode(Mode.ResizingEnd); - moveOffsetX.current = x; - } else if (isHoveringSelection(x)) { - setMode(Mode.Dragging); - setCursor('pointer'); - moveOffsetX.current = x; - } else { - setMode(Mode.Selecting); - setCursor('col-resize'); - moveOffsetX.current = x; - setNewSelection({ start: x, end: x }); + setNewSelection({ ...selection, start: start }); + break; } - }, - [mode, selection] - ); + case Mode.ResizingEnd: { + const diff = x - moveOffsetX.current; + const end = constrainXToCanvas(selection.end + diff); - const handleMouseMove = useCallback( - (evt: MouseEvent) => { - const x = getCanvasX(evt); - - switch (mode) { - case Mode.Normal: { - if (isHoveringSelectionStart(x)) { - setHoverState(HoverState.OverSelectionStart); - setCursor('col-resize'); - } else if (isHoveringSelectionEnd(x)) { - setHoverState(HoverState.OverSelectionEnd); - setCursor('col-resize'); - } else if (isHoveringSelection(x)) { - setHoverState(HoverState.OverSelection); - setCursor('pointer'); - } else { - setCursor('auto'); - } + if (end < selection.start) { + setNewSelection({ start: Math.max(0, end), end: selection.start }); break; } - case Mode.ResizingStart: { - const diff = x - moveOffsetX.current; - const start = constrainXToCanvas(selection.start + diff); - if (start > selection.end) { - setNewSelection({ start: selection.end, end: start }); - break; - } - - setNewSelection({ ...selection, start: start }); - break; - } - case Mode.ResizingEnd: { - const diff = x - moveOffsetX.current; - const end = constrainXToCanvas(selection.end + diff); - - if (end < selection.start) { - setNewSelection({ start: Math.max(0, end), end: selection.start }); - break; - } - - setNewSelection({ ...selection, end: end }); - break; - } - case Mode.Dragging: { - const diff = x - moveOffsetX.current; - const selectionWidth = selection.end - selection.start; - let start = Math.max(0, selection.start + diff); - let end = start + selectionWidth; - if (end > width) { - end = width; - start = end - selectionWidth; - } - - setNewSelection({ start: start, end: end }); - break; - } - case Mode.Selecting: { - if (x < moveOffsetX.current) { - setNewSelection({ - start: x, - end: moveOffsetX.current, - }); - } else { - setNewSelection({ start: moveOffsetX.current, end: x }); - } - break; - } + setNewSelection({ ...selection, end: end }); + break; } - }, - [mode, selection] - ); + case Mode.Dragging: { + const diff = x - moveOffsetX.current; + const selectionWidth = selection.end - selection.start; + let start = Math.max(0, selection.start + diff); + let end = start + selectionWidth; + if (end > width) { + end = width; + start = end - selectionWidth; + } - const handleMouseUp = useCallback(() => { + setNewSelection({ start: start, end: end }); + break; + } + case Mode.Selecting: { + if (x < moveOffsetX.current) { + setNewSelection({ + start: x, + end: moveOffsetX.current, + }); + } else { + setNewSelection({ start: moveOffsetX.current, end: x }); + } + break; + } + } + }; + + const handleMouseUp = () => { if (mode == Mode.Normal) { return; } @@ -289,9 +283,9 @@ export const HudCanvas: React.FC = ({ } onSelectionChange({ ...newSelection }); - }, [mode, newSelection]); + }; - const handleEmptySelectionAction = useCallback(() => { + const handleEmptySelectionAction = () => { switch (emptySelectionAction) { case EmptySelectionAction.SelectPrevious: setNewSelection({ ...selection }); @@ -300,7 +294,7 @@ export const HudCanvas: React.FC = ({ onSelectionChange({ start: 0, end: 0 }); break; } - }, [selection]); + }; const handleMouseLeave = (_evt: MouseEvent) => { setHoverState(HoverState.Normal); diff --git a/frontend/src/Overview.tsx b/frontend/src/Overview.tsx index 7dcc689..6d45d4f 100644 --- a/frontend/src/Overview.tsx +++ b/frontend/src/Overview.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useCallback } from 'react'; +import { useState, useEffect } from 'react'; import { MediaSet } from './generated/media_set'; import { Frames, VideoPosition } from './App'; import { WaveformCanvas } from './WaveformCanvas'; @@ -60,15 +60,12 @@ export const Overview: React.FC = ({ // handlers // convert selection change from canvas pixels to frames, and trigger callback. - const handleSelectionChange = useCallback( - ({ start, end }: Selection) => { - onSelectionChange({ - start: Math.round((start / CanvasLogicalWidth) * mediaSet.audioFrames), - end: Math.round((end / CanvasLogicalWidth) * mediaSet.audioFrames), - }); - }, - [mediaSet] - ); + const handleSelectionChange = ({ start, end }: Selection) => { + onSelectionChange({ + start: Math.round((start / CanvasLogicalWidth) * mediaSet.audioFrames), + end: Math.round((end / CanvasLogicalWidth) * mediaSet.audioFrames), + }); + }; // render component diff --git a/frontend/src/Waveform.tsx b/frontend/src/Waveform.tsx index bfd10d9..7ecb579 100644 --- a/frontend/src/Waveform.tsx +++ b/frontend/src/Waveform.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState, useCallback } from 'react'; +import { useEffect, useState } from 'react'; import { Frames, VideoPosition, newRPC } from './App'; import { MediaSetServiceClientImpl, MediaSet } from './generated/media_set'; import { WaveformCanvas } from './WaveformCanvas'; @@ -93,33 +93,25 @@ export const Waveform: React.FC = ({ // handlers - const handleSelectionChange = useCallback( - (selection: Selection) => { - setSelectedPixels(selection); + const handleSelectionChange = (selection: Selection) => { + setSelectedPixels(selection); - const framesPerPixel = - (viewport.end - viewport.start) / CanvasLogicalWidth; - const selectedFrames = { - start: Math.round(viewport.start + selection.start * framesPerPixel), - end: Math.round(viewport.start + selection.end * framesPerPixel), - }; + const framesPerPixel = (viewport.end - viewport.start) / CanvasLogicalWidth; + const selectedFrames = { + start: Math.round(viewport.start + selection.start * framesPerPixel), + end: Math.round(viewport.start + selection.end * framesPerPixel), + }; - setSelectedFrames(selectedFrames); - onSelectionChange(selectedFrames); - }, - [viewport, selectedFrames] - ); + setSelectedFrames(selectedFrames); + onSelectionChange(selectedFrames); + }; // helpers - const frameToCanvasX = useCallback( - (frame: number): number => { - const pixelsPerFrame = - CanvasLogicalWidth / (viewport.end - viewport.start); - return Math.round((frame - viewport.start) * pixelsPerFrame); - }, - [viewport] - ); + const frameToCanvasX = (frame: number): number => { + const pixelsPerFrame = CanvasLogicalWidth / (viewport.end - viewport.start); + return Math.round((frame - viewport.start) * pixelsPerFrame); + }; // render component