diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 52e4db4..f1882cd 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -49,8 +49,8 @@ const initialState: State = { viewport: { start: 0, end: 0 }, overviewPeaks: from([]), waveformPeaks: from([]), - selectionCanvas: { start: 0, end: 0 }, - viewportCanvas: { start: 0, end: 0 }, + selectionCanvas: { x1: 0, x2: 0 }, + viewportCanvas: { x1: 0, x2: 0 }, position: { currentTime: 0, frame: 0, percent: 0 }, audioSrc: '', videoSrc: '', diff --git a/frontend/src/AppState.test.ts b/frontend/src/AppState.test.ts index 275eddf..fc295a9 100644 --- a/frontend/src/AppState.test.ts +++ b/frontend/src/AppState.test.ts @@ -9,8 +9,8 @@ const initialState: State = { viewport: { start: 0, end: 441000 }, overviewPeaks: from([]), waveformPeaks: from([]), - selectionCanvas: { start: 0, end: 0 }, - viewportCanvas: { start: 0, end: CanvasLogicalWidth }, + selectionCanvas: { x1: 0, x2: 0 }, + viewportCanvas: { x1: 0, x2: CanvasLogicalWidth }, position: { currentTime: 0, frame: 0, percent: 0 }, audioSrc: '', videoSrc: '', diff --git a/frontend/src/AppState.tsx b/frontend/src/AppState.tsx index c49f600..a5ca426 100644 --- a/frontend/src/AppState.tsx +++ b/frontend/src/AppState.tsx @@ -1,7 +1,7 @@ import { MediaSet } from './generated/media_set'; import { Observable } from 'rxjs'; import { SelectionChangeEvent } from './HudCanvas'; -import { SelectionMode, CanvasLogicalWidth } from './HudCanvasState'; +import { CanvasRange, SelectionMode, CanvasLogicalWidth } from './HudCanvasState'; import { PlayState } from './Player'; import { zoomViewportIn, zoomViewportOut } from './helpers/zoom'; import frameToWaveformCanvasX from './helpers/frameToWaveformCanvasX'; @@ -15,12 +15,6 @@ export interface FrameRange { end: number; } -// TODO: rename to x1, x2 -interface CanvasRange { - start: number; - end: number; -} - interface Position { currentTime: number; frame: number; @@ -224,10 +218,10 @@ function setViewport(state: State, { viewport }: SetViewportAction): State { ...state, viewport: viewport, viewportCanvas: { - start: Math.round( + x1: Math.round( (viewport.start / mediaSet.audioFrames) * CanvasLogicalWidth ), - end: Math.round( + x2: Math.round( (viewport.end / mediaSet.audioFrames) * CanvasLogicalWidth ), }, @@ -298,10 +292,10 @@ function handleViewportChanged( const newViewport = { start: Math.round( - mediaSet.audioFrames * (canvasRange.start / CanvasLogicalWidth) + mediaSet.audioFrames * (canvasRange.x1 / CanvasLogicalWidth) ), end: Math.round( - mediaSet.audioFrames * (canvasRange.end / CanvasLogicalWidth) + mediaSet.audioFrames * (canvasRange.x2 / CanvasLogicalWidth) ), }; @@ -331,8 +325,8 @@ function handleWaveformSelectionChanged( const framesPerPixel = (viewport.end - viewport.start) / CanvasLogicalWidth; const newSelection = { - start: Math.round(viewport.start + canvasRange.start * framesPerPixel), - end: Math.round(viewport.start + canvasRange.end * framesPerPixel), + start: Math.round(viewport.start + canvasRange.x1 * framesPerPixel), + end: Math.round(viewport.start + canvasRange.x2 * framesPerPixel), }; let currentTime = state.currentTime; @@ -433,8 +427,8 @@ function selectionToWaveformCanvasRange( ); if (x1 == x2) { - return { start: 0, end: 0 }; + return { x1: 0, x2: 0 }; } - return { start: x1 || 0, end: x2 || CanvasLogicalWidth }; + return { x1: x1 || 0, x2: x2 || CanvasLogicalWidth }; } diff --git a/frontend/src/HudCanvas.tsx b/frontend/src/HudCanvas.tsx index 55a3b25..9ba32d5 100644 --- a/frontend/src/HudCanvas.tsx +++ b/frontend/src/HudCanvas.tsx @@ -4,8 +4,8 @@ import { State, SelectionMode, HoverState, - Selection, EmptySelectionAction, + CanvasRange, } from './HudCanvasState'; import constrainNumeric from './helpers/constrainNumeric'; export { EmptySelectionAction } from './HudCanvasState'; @@ -24,17 +24,17 @@ interface Props { emptySelectionAction: EmptySelectionAction; styles: Styles; position: number | null; - selection: Selection; + selection: CanvasRange; onSelectionChange: (selectionState: SelectionChangeEvent) => void; } export interface SelectionChangeEvent { - selection: Selection; + selection: CanvasRange; mode: SelectionMode; prevMode: SelectionMode; } -const emptySelection: Selection = { start: 0, end: 0 }; +const emptySelection: CanvasRange = { x1: 0, x2: 0 }; const initialState: State = { width: 0, @@ -134,9 +134,9 @@ export const HudCanvas: React.FC = ({ state.hoverState == HoverState.OverSelection ? '0.15' : '0.13'; ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`; ctx.rect( - currentSelection.start, + currentSelection.x1, borderLineWidth, - currentSelection.end - currentSelection.start, + currentSelection.x2 - currentSelection.x1, canvas.height - borderLineWidth * 2 ); ctx.fill(); @@ -146,8 +146,8 @@ export const HudCanvas: React.FC = ({ const hoverX = state.hoverX; if ( - (hoverX != 0 && hoverX < currentSelection.start) || - hoverX > currentSelection.end + (hoverX != 0 && hoverX < currentSelection.x1) || + hoverX > currentSelection.x2 ) { ctx.beginPath(); ctx.strokeStyle = hoverPositionStrokeStyle; diff --git a/frontend/src/HudCanvasState.test.ts b/frontend/src/HudCanvasState.test.ts index f375c32..a5f19ea 100644 --- a/frontend/src/HudCanvasState.test.ts +++ b/frontend/src/HudCanvasState.test.ts @@ -9,8 +9,8 @@ const initialState = { width: 5000, emptySelectionAction: EmptySelectionAction.SelectNothing, hoverX: 0, - selection: { start: 0, end: 0 }, - origSelection: { start: 0, end: 0 }, + selection: { x1: 0, x2: 0 }, + origSelection: { x1: 0, x2: 0 }, mousedownX: 0, mode: SelectionMode.Normal, prevMode: SelectionMode.Normal, @@ -24,9 +24,9 @@ describe('stateReducer', () => { it('sets the selection', () => { const state = stateReducer( { ...initialState }, - { type: 'setselection', x: 0, selection: { start: 100, end: 200 } } + { type: 'setselection', x: 0, selection: { x1: 100, x2: 200 } } ); - expect(state.selection).toEqual({ start: 100, end: 200 }); + expect(state.selection).toEqual({ x1: 100, x2: 200 }); expect(state.shouldPublish).toBeFalsy(); }); }); @@ -35,30 +35,30 @@ describe('stateReducer', () => { { name: 'entering resizing start', x: 995, - selection: { start: 1000, end: 2000 }, + selection: { x1: 1000, x2: 2000 }, wantMode: SelectionMode.ResizingStart, - wantSelection: { start: 1000, end: 2000 }, + wantSelection: { x1: 1000, x2: 2000 }, }, { name: 'entering resizing end', x: 2003, - selection: { start: 1000, end: 2000 }, + selection: { x1: 1000, x2: 2000 }, wantMode: SelectionMode.ResizingEnd, - wantSelection: { start: 1000, end: 2000 }, + wantSelection: { x1: 1000, x2: 2000 }, }, { name: 'entering dragging', x: 1500, - selection: { start: 1000, end: 2000 }, + selection: { x1: 1000, x2: 2000 }, wantMode: SelectionMode.Dragging, - wantSelection: { start: 1000, end: 2000 }, + wantSelection: { x1: 1000, x2: 2000 }, }, { name: 'entering selecting', x: 10, - selection: { start: 1000, end: 2000 }, + selection: { x1: 1000, x2: 2000 }, wantMode: SelectionMode.Selecting, - wantSelection: { start: 10, end: 10 }, + wantSelection: { x1: 10, x2: 10 }, }, ])('mousedown', ({ name, x, selection, wantMode, wantSelection }) => { test(`${name} generates the expected state`, () => { @@ -77,24 +77,24 @@ describe('stateReducer', () => { { name: 're-entering normal mode', x: 1200, - selection: { start: 1000, end: 2000 }, + selection: { x1: 1000, x2: 2000 }, emptySelectionAction: EmptySelectionAction.SelectNothing, - wantSelection: { start: 1000, end: 2000 }, + wantSelection: { x1: 1000, x2: 2000 }, }, { name: 'when nothing is selected and emptySelectionAction is SelectNothing', x: 1200, - selection: { start: 1000, end: 1000 }, + selection: { x1: 1000, x2: 1000 }, emptySelectionAction: EmptySelectionAction.SelectNothing, - wantSelection: { start: 1200, end: 1200 }, + wantSelection: { x1: 1200, x2: 1200 }, }, { // TODO: broken name: 'when nothing is selected and emptySelectionAction is SelectPrevious', x: 1200, - selection: { start: 1000, end: 2000 }, + selection: { x1: 1000, x2: 2000 }, emptySelectionAction: EmptySelectionAction.SelectPrevious, - wantSelection: { start: 1000, end: 2000 }, + wantSelection: { x1: 1000, x2: 2000 }, }, ])( 'mouseup', @@ -122,14 +122,14 @@ describe('stateReducer', () => { const state = stateReducer( { ...initialState, - selection: { start: 2000, end: 3000 }, + selection: { x1: 2000, x2: 3000 }, mode: SelectionMode.Dragging, mousedownX: 475, }, { type: 'mouseleave', x: 500 } ); expect(state.mode).toEqual(SelectionMode.Dragging); - expect(state.selection).toEqual({ start: 2000, end: 3000 }); + expect(state.selection).toEqual({ x1: 2000, x2: 3000 }); expect(state.mousedownX).toEqual(475); expect(state.hoverX).toEqual(0); expect(state.shouldPublish).toBeFalsy(); @@ -143,7 +143,7 @@ describe('stateReducer', () => { name: 'hovering over selection start', mode: SelectionMode.Normal, x: 997, - selection: { start: 1000, end: 3000 }, + selection: { x1: 1000, x2: 3000 }, wantHoverState: HoverState.OverSelectionStart, shouldPublish: false, }, @@ -151,7 +151,7 @@ describe('stateReducer', () => { name: 'hovering over selection end', mode: SelectionMode.Normal, x: 3009, - selection: { start: 1000, end: 3000 }, + selection: { x1: 1000, x2: 3000 }, wantHoverState: HoverState.OverSelectionEnd, shouldPublish: false, }, @@ -159,7 +159,7 @@ describe('stateReducer', () => { name: 'hovering over selection', mode: SelectionMode.Normal, x: 1200, - selection: { start: 1000, end: 3000 }, + selection: { x1: 1000, x2: 3000 }, wantHoverState: HoverState.OverSelection, shouldPublish: false, }, @@ -167,7 +167,7 @@ describe('stateReducer', () => { name: 'hovering elsewhere', mode: SelectionMode.Normal, x: 300, - selection: { start: 1000, end: 3000 }, + selection: { x1: 1000, x2: 3000 }, wantHoverState: HoverState.Normal, shouldPublish: false, }, @@ -177,8 +177,8 @@ describe('stateReducer', () => { mode: SelectionMode.Selecting, x: 3005, mousedownX: 2000, - selection: { start: 2000, end: 3000 }, - wantSelection: { start: 2000, end: 3005 }, + selection: { x1: 2000, x2: 3000 }, + wantSelection: { x1: 2000, x2: 3005 }, shouldPublish: true, }, { @@ -186,8 +186,8 @@ describe('stateReducer', () => { mode: SelectionMode.Selecting, x: 1995, mousedownX: 2000, - selection: { start: 2000, end: 2002 }, - wantSelection: { start: 1995, end: 2000 }, + selection: { x1: 2000, x2: 2002 }, + wantSelection: { x1: 1995, x2: 2000 }, shouldPublish: true, }, // Dragging mode @@ -196,9 +196,9 @@ describe('stateReducer', () => { mode: SelectionMode.Dragging, x: 1220, mousedownX: 1200, - selection: { start: 1000, end: 1500 }, - origSelection: { start: 1000, end: 1500 }, - wantSelection: { start: 1020, end: 1520 }, + selection: { x1: 1000, x2: 1500 }, + origSelection: { x1: 1000, x2: 1500 }, + wantSelection: { x1: 1020, x2: 1520 }, shouldPublish: true, }, { @@ -206,9 +206,9 @@ describe('stateReducer', () => { mode: SelectionMode.Dragging, x: 30, mousedownX: 50, - selection: { start: 10, end: 210 }, - origSelection: { start: 10, end: 210 }, - wantSelection: { start: 0, end: 200 }, + selection: { x1: 10, x2: 210 }, + origSelection: { x1: 10, x2: 210 }, + wantSelection: { x1: 0, x2: 200 }, shouldPublish: true, }, { @@ -216,9 +216,9 @@ describe('stateReducer', () => { mode: SelectionMode.Dragging, x: 1400, mousedownX: 1250, - selection: { start: 4800, end: 4900 }, - origSelection: { start: 4800, end: 4900 }, - wantSelection: { start: 4900, end: 5000 }, + selection: { x1: 4800, x2: 4900 }, + origSelection: { x1: 4800, x2: 4900 }, + wantSelection: { x1: 4900, x2: 5000 }, shouldPublish: true, }, // ResizingStart mode @@ -226,18 +226,18 @@ describe('stateReducer', () => { name: 'when not crossing over', mode: SelectionMode.ResizingStart, x: 2020, - selection: { start: 2000, end: 3000 }, - origSelection: { start: 2000, end: 3000 }, - wantSelection: { start: 2020, end: 3000 }, + selection: { x1: 2000, x2: 3000 }, + origSelection: { x1: 2000, x2: 3000 }, + wantSelection: { x1: 2020, x2: 3000 }, shouldPublish: true, }, { name: 'when crossing over', mode: SelectionMode.ResizingStart, x: 2010, - selection: { start: 2000, end: 2002 }, - origSelection: { start: 2000, end: 2002 }, - wantSelection: { start: 2002, end: 2010 }, + selection: { x1: 2000, x2: 2002 }, + origSelection: { x1: 2000, x2: 2002 }, + wantSelection: { x1: 2002, x2: 2010 }, shouldPublish: true, }, // ResizingEnd mode @@ -245,18 +245,18 @@ describe('stateReducer', () => { name: 'when not crossing over', mode: SelectionMode.ResizingEnd, x: 2007, - selection: { start: 1000, end: 2000 }, - origSelection: { start: 1000, end: 2000 }, - wantSelection: { start: 1000, end: 2007 }, + selection: { x1: 1000, x2: 2000 }, + origSelection: { x1: 1000, x2: 2000 }, + wantSelection: { x1: 1000, x2: 2007 }, shouldPublish: true, }, { name: 'when crossing over', mode: SelectionMode.ResizingEnd, x: 1995, - selection: { start: 2000, end: 2002 }, - origSelection: { start: 2000, end: 2002 }, - wantSelection: { start: 1995, end: 2000 }, + selection: { x1: 2000, x2: 2002 }, + origSelection: { x1: 2000, x2: 2002 }, + wantSelection: { x1: 1995, x2: 2000 }, shouldPublish: true, }, ])( @@ -267,7 +267,7 @@ describe('stateReducer', () => { x, mousedownX = 0, selection, - origSelection = { start: 0, end: 0 }, + origSelection = { x1: 0, x2: 0 }, wantSelection = selection, wantHoverState = HoverState.Normal, shouldPublish, diff --git a/frontend/src/HudCanvasState.ts b/frontend/src/HudCanvasState.ts index aa87729..db78448 100644 --- a/frontend/src/HudCanvasState.ts +++ b/frontend/src/HudCanvasState.ts @@ -3,6 +3,11 @@ import constrainNumeric from './helpers/constrainNumeric'; export const CanvasLogicalWidth = 2000; export const CanvasLogicalHeight = 500; +export interface CanvasRange { + x1: number; + x2: number; +} + export enum HoverState { Normal, OverSelectionStart, @@ -15,11 +20,6 @@ export enum EmptySelectionAction { SelectPrevious, } -export interface Selection { - start: number; - end: number; -} - export enum SelectionMode { Normal, Selecting, @@ -32,8 +32,8 @@ export interface State { width: number; emptySelectionAction: EmptySelectionAction; hoverX: number; - selection: Selection; - origSelection: Selection; + selection: CanvasRange; + origSelection: CanvasRange; mousedownX: number; mode: SelectionMode; prevMode: SelectionMode; @@ -47,7 +47,7 @@ interface SelectionAction { x: number; // TODO: selection is only used for the setselection SelectionAction. Improve // the typing here. - selection?: Selection; + selection?: CanvasRange; } export const stateReducer = ( @@ -62,7 +62,7 @@ export const stateReducer = ( { x, type, selection: selectionToSet }: SelectionAction ): State => { let mode: SelectionMode; - let newSelection: Selection; + let newSelection: CanvasRange; let hoverX: number; let mousedownX: number; let cursorClass: string; @@ -71,7 +71,7 @@ export const stateReducer = ( switch (type) { case 'setselection': - newSelection = selectionToSet || { start: 0, end: 0 }; + newSelection = selectionToSet || { x1: 0, x2: 0 }; mousedownX = prevMousedownX; mode = SelectionMode.Normal; cursorClass = 'cursor-auto'; @@ -97,7 +97,7 @@ export const stateReducer = ( mode = SelectionMode.Dragging; cursorClass = 'cursor-move'; } else { - newSelection = { start: x, end: x }; + newSelection = { x1: x, x2: x }; mode = SelectionMode.Selecting; cursorClass = 'cursor-col-resize'; } @@ -114,10 +114,10 @@ export const stateReducer = ( hoverState = HoverState.Normal; if ( - newSelection.start == newSelection.end && + newSelection.x1 == newSelection.x2 && emptySelectionAction == EmptySelectionAction.SelectNothing ) { - newSelection = { start: x, end: x }; + newSelection = { x1: x, x2: x }; } break; @@ -161,13 +161,13 @@ export const stateReducer = ( mode = SelectionMode.Selecting; if (x < prevMousedownX) { newSelection = { - start: x, - end: prevMousedownX, + x1: x, + x2: prevMousedownX, }; } else { newSelection = { - start: prevMousedownX, - end: x, + x1: prevMousedownX, + x2: x, }; } @@ -178,15 +178,15 @@ export const stateReducer = ( cursorClass = 'cursor-move'; const diff = x - prevMousedownX; - const selectionWidth = origSelection.end - origSelection.start; + const selectionWidth = origSelection.x2 - origSelection.x1; - let start = Math.max(0, origSelection.start + diff); + let start = Math.max(0, origSelection.x1 + diff); let end = start + selectionWidth; if (end > width) { end = width; start = end - selectionWidth; } - newSelection = { start: start, end: end }; + newSelection = { x1: start, x2: end }; break; } @@ -195,10 +195,10 @@ export const stateReducer = ( cursorClass = 'cursor-col-resize'; const start = constrainNumeric(x, width); - if (start > origSelection.end) { - newSelection = { start: origSelection.end, end: start }; + if (start > origSelection.x2) { + newSelection = { x1: origSelection.x2, x2: start }; } else { - newSelection = { ...origSelection, start: start }; + newSelection = { ...origSelection, x1: start }; } break; @@ -208,13 +208,13 @@ export const stateReducer = ( cursorClass = 'cursor-col-resize'; const end = constrainNumeric(x, width); - if (end < origSelection.start) { + if (end < origSelection.x1) { newSelection = { - start: end, - end: origSelection.start, + x1: end, + x2: origSelection.x1, }; } else { - newSelection = { ...origSelection, end: x }; + newSelection = { ...origSelection, x2: x }; } break; @@ -250,14 +250,17 @@ export const stateReducer = ( const hoverOffset = 10; -const isHoveringSelectionStart = (x: number, selection: Selection): boolean => { - return x > selection.start - hoverOffset && x < selection.start + hoverOffset; +const isHoveringSelectionStart = ( + x: number, + selection: CanvasRange +): boolean => { + return x > selection.x1 - hoverOffset && x < selection.x1 + hoverOffset; }; -const isHoveringSelectionEnd = (x: number, selection: Selection): boolean => { - return x > selection.end - hoverOffset && x < selection.end + hoverOffset; +const isHoveringSelectionEnd = (x: number, selection: CanvasRange): boolean => { + return x > selection.x2 - hoverOffset && x < selection.x2 + hoverOffset; }; -const isHoveringSelection = (x: number, selection: Selection): boolean => { - return x >= selection.start && x <= selection.end; +const isHoveringSelection = (x: number, selection: CanvasRange): boolean => { + return x >= selection.x1 && x <= selection.x2; };