Replace Selection interface with CanvasRange
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Rob Watson 2022-02-04 08:35:54 +01:00
parent b64f0b4daa
commit 3dcc1edc62
6 changed files with 107 additions and 110 deletions

View File

@ -49,8 +49,8 @@ const initialState: State = {
viewport: { start: 0, end: 0 }, viewport: { start: 0, end: 0 },
overviewPeaks: from([]), overviewPeaks: from([]),
waveformPeaks: from([]), waveformPeaks: from([]),
selectionCanvas: { start: 0, end: 0 }, selectionCanvas: { x1: 0, x2: 0 },
viewportCanvas: { start: 0, end: 0 }, viewportCanvas: { x1: 0, x2: 0 },
position: { currentTime: 0, frame: 0, percent: 0 }, position: { currentTime: 0, frame: 0, percent: 0 },
audioSrc: '', audioSrc: '',
videoSrc: '', videoSrc: '',

View File

@ -9,8 +9,8 @@ const initialState: State = {
viewport: { start: 0, end: 441000 }, viewport: { start: 0, end: 441000 },
overviewPeaks: from([]), overviewPeaks: from([]),
waveformPeaks: from([]), waveformPeaks: from([]),
selectionCanvas: { start: 0, end: 0 }, selectionCanvas: { x1: 0, x2: 0 },
viewportCanvas: { start: 0, end: CanvasLogicalWidth }, viewportCanvas: { x1: 0, x2: CanvasLogicalWidth },
position: { currentTime: 0, frame: 0, percent: 0 }, position: { currentTime: 0, frame: 0, percent: 0 },
audioSrc: '', audioSrc: '',
videoSrc: '', videoSrc: '',

View File

@ -1,7 +1,7 @@
import { MediaSet } from './generated/media_set'; import { MediaSet } from './generated/media_set';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { SelectionChangeEvent } from './HudCanvas'; import { SelectionChangeEvent } from './HudCanvas';
import { SelectionMode, CanvasLogicalWidth } from './HudCanvasState'; import { CanvasRange, SelectionMode, CanvasLogicalWidth } from './HudCanvasState';
import { PlayState } from './Player'; import { PlayState } from './Player';
import { zoomViewportIn, zoomViewportOut } from './helpers/zoom'; import { zoomViewportIn, zoomViewportOut } from './helpers/zoom';
import frameToWaveformCanvasX from './helpers/frameToWaveformCanvasX'; import frameToWaveformCanvasX from './helpers/frameToWaveformCanvasX';
@ -15,12 +15,6 @@ export interface FrameRange {
end: number; end: number;
} }
// TODO: rename to x1, x2
interface CanvasRange {
start: number;
end: number;
}
interface Position { interface Position {
currentTime: number; currentTime: number;
frame: number; frame: number;
@ -224,10 +218,10 @@ function setViewport(state: State, { viewport }: SetViewportAction): State {
...state, ...state,
viewport: viewport, viewport: viewport,
viewportCanvas: { viewportCanvas: {
start: Math.round( x1: Math.round(
(viewport.start / mediaSet.audioFrames) * CanvasLogicalWidth (viewport.start / mediaSet.audioFrames) * CanvasLogicalWidth
), ),
end: Math.round( x2: Math.round(
(viewport.end / mediaSet.audioFrames) * CanvasLogicalWidth (viewport.end / mediaSet.audioFrames) * CanvasLogicalWidth
), ),
}, },
@ -298,10 +292,10 @@ function handleViewportChanged(
const newViewport = { const newViewport = {
start: Math.round( start: Math.round(
mediaSet.audioFrames * (canvasRange.start / CanvasLogicalWidth) mediaSet.audioFrames * (canvasRange.x1 / CanvasLogicalWidth)
), ),
end: Math.round( 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 framesPerPixel = (viewport.end - viewport.start) / CanvasLogicalWidth;
const newSelection = { const newSelection = {
start: Math.round(viewport.start + canvasRange.start * framesPerPixel), start: Math.round(viewport.start + canvasRange.x1 * framesPerPixel),
end: Math.round(viewport.start + canvasRange.end * framesPerPixel), end: Math.round(viewport.start + canvasRange.x2 * framesPerPixel),
}; };
let currentTime = state.currentTime; let currentTime = state.currentTime;
@ -433,8 +427,8 @@ function selectionToWaveformCanvasRange(
); );
if (x1 == x2) { 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 };
} }

View File

@ -4,8 +4,8 @@ import {
State, State,
SelectionMode, SelectionMode,
HoverState, HoverState,
Selection,
EmptySelectionAction, EmptySelectionAction,
CanvasRange,
} from './HudCanvasState'; } from './HudCanvasState';
import constrainNumeric from './helpers/constrainNumeric'; import constrainNumeric from './helpers/constrainNumeric';
export { EmptySelectionAction } from './HudCanvasState'; export { EmptySelectionAction } from './HudCanvasState';
@ -24,17 +24,17 @@ interface Props {
emptySelectionAction: EmptySelectionAction; emptySelectionAction: EmptySelectionAction;
styles: Styles; styles: Styles;
position: number | null; position: number | null;
selection: Selection; selection: CanvasRange;
onSelectionChange: (selectionState: SelectionChangeEvent) => void; onSelectionChange: (selectionState: SelectionChangeEvent) => void;
} }
export interface SelectionChangeEvent { export interface SelectionChangeEvent {
selection: Selection; selection: CanvasRange;
mode: SelectionMode; mode: SelectionMode;
prevMode: SelectionMode; prevMode: SelectionMode;
} }
const emptySelection: Selection = { start: 0, end: 0 }; const emptySelection: CanvasRange = { x1: 0, x2: 0 };
const initialState: State = { const initialState: State = {
width: 0, width: 0,
@ -134,9 +134,9 @@ export const HudCanvas: React.FC<Props> = ({
state.hoverState == HoverState.OverSelection ? '0.15' : '0.13'; state.hoverState == HoverState.OverSelection ? '0.15' : '0.13';
ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`; ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
ctx.rect( ctx.rect(
currentSelection.start, currentSelection.x1,
borderLineWidth, borderLineWidth,
currentSelection.end - currentSelection.start, currentSelection.x2 - currentSelection.x1,
canvas.height - borderLineWidth * 2 canvas.height - borderLineWidth * 2
); );
ctx.fill(); ctx.fill();
@ -146,8 +146,8 @@ export const HudCanvas: React.FC<Props> = ({
const hoverX = state.hoverX; const hoverX = state.hoverX;
if ( if (
(hoverX != 0 && hoverX < currentSelection.start) || (hoverX != 0 && hoverX < currentSelection.x1) ||
hoverX > currentSelection.end hoverX > currentSelection.x2
) { ) {
ctx.beginPath(); ctx.beginPath();
ctx.strokeStyle = hoverPositionStrokeStyle; ctx.strokeStyle = hoverPositionStrokeStyle;

View File

@ -9,8 +9,8 @@ const initialState = {
width: 5000, width: 5000,
emptySelectionAction: EmptySelectionAction.SelectNothing, emptySelectionAction: EmptySelectionAction.SelectNothing,
hoverX: 0, hoverX: 0,
selection: { start: 0, end: 0 }, selection: { x1: 0, x2: 0 },
origSelection: { start: 0, end: 0 }, origSelection: { x1: 0, x2: 0 },
mousedownX: 0, mousedownX: 0,
mode: SelectionMode.Normal, mode: SelectionMode.Normal,
prevMode: SelectionMode.Normal, prevMode: SelectionMode.Normal,
@ -24,9 +24,9 @@ describe('stateReducer', () => {
it('sets the selection', () => { it('sets the selection', () => {
const state = stateReducer( const state = stateReducer(
{ ...initialState }, { ...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(); expect(state.shouldPublish).toBeFalsy();
}); });
}); });
@ -35,30 +35,30 @@ describe('stateReducer', () => {
{ {
name: 'entering resizing start', name: 'entering resizing start',
x: 995, x: 995,
selection: { start: 1000, end: 2000 }, selection: { x1: 1000, x2: 2000 },
wantMode: SelectionMode.ResizingStart, wantMode: SelectionMode.ResizingStart,
wantSelection: { start: 1000, end: 2000 }, wantSelection: { x1: 1000, x2: 2000 },
}, },
{ {
name: 'entering resizing end', name: 'entering resizing end',
x: 2003, x: 2003,
selection: { start: 1000, end: 2000 }, selection: { x1: 1000, x2: 2000 },
wantMode: SelectionMode.ResizingEnd, wantMode: SelectionMode.ResizingEnd,
wantSelection: { start: 1000, end: 2000 }, wantSelection: { x1: 1000, x2: 2000 },
}, },
{ {
name: 'entering dragging', name: 'entering dragging',
x: 1500, x: 1500,
selection: { start: 1000, end: 2000 }, selection: { x1: 1000, x2: 2000 },
wantMode: SelectionMode.Dragging, wantMode: SelectionMode.Dragging,
wantSelection: { start: 1000, end: 2000 }, wantSelection: { x1: 1000, x2: 2000 },
}, },
{ {
name: 'entering selecting', name: 'entering selecting',
x: 10, x: 10,
selection: { start: 1000, end: 2000 }, selection: { x1: 1000, x2: 2000 },
wantMode: SelectionMode.Selecting, wantMode: SelectionMode.Selecting,
wantSelection: { start: 10, end: 10 }, wantSelection: { x1: 10, x2: 10 },
}, },
])('mousedown', ({ name, x, selection, wantMode, wantSelection }) => { ])('mousedown', ({ name, x, selection, wantMode, wantSelection }) => {
test(`${name} generates the expected state`, () => { test(`${name} generates the expected state`, () => {
@ -77,24 +77,24 @@ describe('stateReducer', () => {
{ {
name: 're-entering normal mode', name: 're-entering normal mode',
x: 1200, x: 1200,
selection: { start: 1000, end: 2000 }, selection: { x1: 1000, x2: 2000 },
emptySelectionAction: EmptySelectionAction.SelectNothing, emptySelectionAction: EmptySelectionAction.SelectNothing,
wantSelection: { start: 1000, end: 2000 }, wantSelection: { x1: 1000, x2: 2000 },
}, },
{ {
name: 'when nothing is selected and emptySelectionAction is SelectNothing', name: 'when nothing is selected and emptySelectionAction is SelectNothing',
x: 1200, x: 1200,
selection: { start: 1000, end: 1000 }, selection: { x1: 1000, x2: 1000 },
emptySelectionAction: EmptySelectionAction.SelectNothing, emptySelectionAction: EmptySelectionAction.SelectNothing,
wantSelection: { start: 1200, end: 1200 }, wantSelection: { x1: 1200, x2: 1200 },
}, },
{ {
// TODO: broken // TODO: broken
name: 'when nothing is selected and emptySelectionAction is SelectPrevious', name: 'when nothing is selected and emptySelectionAction is SelectPrevious',
x: 1200, x: 1200,
selection: { start: 1000, end: 2000 }, selection: { x1: 1000, x2: 2000 },
emptySelectionAction: EmptySelectionAction.SelectPrevious, emptySelectionAction: EmptySelectionAction.SelectPrevious,
wantSelection: { start: 1000, end: 2000 }, wantSelection: { x1: 1000, x2: 2000 },
}, },
])( ])(
'mouseup', 'mouseup',
@ -122,14 +122,14 @@ describe('stateReducer', () => {
const state = stateReducer( const state = stateReducer(
{ {
...initialState, ...initialState,
selection: { start: 2000, end: 3000 }, selection: { x1: 2000, x2: 3000 },
mode: SelectionMode.Dragging, mode: SelectionMode.Dragging,
mousedownX: 475, mousedownX: 475,
}, },
{ type: 'mouseleave', x: 500 } { type: 'mouseleave', x: 500 }
); );
expect(state.mode).toEqual(SelectionMode.Dragging); 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.mousedownX).toEqual(475);
expect(state.hoverX).toEqual(0); expect(state.hoverX).toEqual(0);
expect(state.shouldPublish).toBeFalsy(); expect(state.shouldPublish).toBeFalsy();
@ -143,7 +143,7 @@ describe('stateReducer', () => {
name: 'hovering over selection start', name: 'hovering over selection start',
mode: SelectionMode.Normal, mode: SelectionMode.Normal,
x: 997, x: 997,
selection: { start: 1000, end: 3000 }, selection: { x1: 1000, x2: 3000 },
wantHoverState: HoverState.OverSelectionStart, wantHoverState: HoverState.OverSelectionStart,
shouldPublish: false, shouldPublish: false,
}, },
@ -151,7 +151,7 @@ describe('stateReducer', () => {
name: 'hovering over selection end', name: 'hovering over selection end',
mode: SelectionMode.Normal, mode: SelectionMode.Normal,
x: 3009, x: 3009,
selection: { start: 1000, end: 3000 }, selection: { x1: 1000, x2: 3000 },
wantHoverState: HoverState.OverSelectionEnd, wantHoverState: HoverState.OverSelectionEnd,
shouldPublish: false, shouldPublish: false,
}, },
@ -159,7 +159,7 @@ describe('stateReducer', () => {
name: 'hovering over selection', name: 'hovering over selection',
mode: SelectionMode.Normal, mode: SelectionMode.Normal,
x: 1200, x: 1200,
selection: { start: 1000, end: 3000 }, selection: { x1: 1000, x2: 3000 },
wantHoverState: HoverState.OverSelection, wantHoverState: HoverState.OverSelection,
shouldPublish: false, shouldPublish: false,
}, },
@ -167,7 +167,7 @@ describe('stateReducer', () => {
name: 'hovering elsewhere', name: 'hovering elsewhere',
mode: SelectionMode.Normal, mode: SelectionMode.Normal,
x: 300, x: 300,
selection: { start: 1000, end: 3000 }, selection: { x1: 1000, x2: 3000 },
wantHoverState: HoverState.Normal, wantHoverState: HoverState.Normal,
shouldPublish: false, shouldPublish: false,
}, },
@ -177,8 +177,8 @@ describe('stateReducer', () => {
mode: SelectionMode.Selecting, mode: SelectionMode.Selecting,
x: 3005, x: 3005,
mousedownX: 2000, mousedownX: 2000,
selection: { start: 2000, end: 3000 }, selection: { x1: 2000, x2: 3000 },
wantSelection: { start: 2000, end: 3005 }, wantSelection: { x1: 2000, x2: 3005 },
shouldPublish: true, shouldPublish: true,
}, },
{ {
@ -186,8 +186,8 @@ describe('stateReducer', () => {
mode: SelectionMode.Selecting, mode: SelectionMode.Selecting,
x: 1995, x: 1995,
mousedownX: 2000, mousedownX: 2000,
selection: { start: 2000, end: 2002 }, selection: { x1: 2000, x2: 2002 },
wantSelection: { start: 1995, end: 2000 }, wantSelection: { x1: 1995, x2: 2000 },
shouldPublish: true, shouldPublish: true,
}, },
// Dragging mode // Dragging mode
@ -196,9 +196,9 @@ describe('stateReducer', () => {
mode: SelectionMode.Dragging, mode: SelectionMode.Dragging,
x: 1220, x: 1220,
mousedownX: 1200, mousedownX: 1200,
selection: { start: 1000, end: 1500 }, selection: { x1: 1000, x2: 1500 },
origSelection: { start: 1000, end: 1500 }, origSelection: { x1: 1000, x2: 1500 },
wantSelection: { start: 1020, end: 1520 }, wantSelection: { x1: 1020, x2: 1520 },
shouldPublish: true, shouldPublish: true,
}, },
{ {
@ -206,9 +206,9 @@ describe('stateReducer', () => {
mode: SelectionMode.Dragging, mode: SelectionMode.Dragging,
x: 30, x: 30,
mousedownX: 50, mousedownX: 50,
selection: { start: 10, end: 210 }, selection: { x1: 10, x2: 210 },
origSelection: { start: 10, end: 210 }, origSelection: { x1: 10, x2: 210 },
wantSelection: { start: 0, end: 200 }, wantSelection: { x1: 0, x2: 200 },
shouldPublish: true, shouldPublish: true,
}, },
{ {
@ -216,9 +216,9 @@ describe('stateReducer', () => {
mode: SelectionMode.Dragging, mode: SelectionMode.Dragging,
x: 1400, x: 1400,
mousedownX: 1250, mousedownX: 1250,
selection: { start: 4800, end: 4900 }, selection: { x1: 4800, x2: 4900 },
origSelection: { start: 4800, end: 4900 }, origSelection: { x1: 4800, x2: 4900 },
wantSelection: { start: 4900, end: 5000 }, wantSelection: { x1: 4900, x2: 5000 },
shouldPublish: true, shouldPublish: true,
}, },
// ResizingStart mode // ResizingStart mode
@ -226,18 +226,18 @@ describe('stateReducer', () => {
name: 'when not crossing over', name: 'when not crossing over',
mode: SelectionMode.ResizingStart, mode: SelectionMode.ResizingStart,
x: 2020, x: 2020,
selection: { start: 2000, end: 3000 }, selection: { x1: 2000, x2: 3000 },
origSelection: { start: 2000, end: 3000 }, origSelection: { x1: 2000, x2: 3000 },
wantSelection: { start: 2020, end: 3000 }, wantSelection: { x1: 2020, x2: 3000 },
shouldPublish: true, shouldPublish: true,
}, },
{ {
name: 'when crossing over', name: 'when crossing over',
mode: SelectionMode.ResizingStart, mode: SelectionMode.ResizingStart,
x: 2010, x: 2010,
selection: { start: 2000, end: 2002 }, selection: { x1: 2000, x2: 2002 },
origSelection: { start: 2000, end: 2002 }, origSelection: { x1: 2000, x2: 2002 },
wantSelection: { start: 2002, end: 2010 }, wantSelection: { x1: 2002, x2: 2010 },
shouldPublish: true, shouldPublish: true,
}, },
// ResizingEnd mode // ResizingEnd mode
@ -245,18 +245,18 @@ describe('stateReducer', () => {
name: 'when not crossing over', name: 'when not crossing over',
mode: SelectionMode.ResizingEnd, mode: SelectionMode.ResizingEnd,
x: 2007, x: 2007,
selection: { start: 1000, end: 2000 }, selection: { x1: 1000, x2: 2000 },
origSelection: { start: 1000, end: 2000 }, origSelection: { x1: 1000, x2: 2000 },
wantSelection: { start: 1000, end: 2007 }, wantSelection: { x1: 1000, x2: 2007 },
shouldPublish: true, shouldPublish: true,
}, },
{ {
name: 'when crossing over', name: 'when crossing over',
mode: SelectionMode.ResizingEnd, mode: SelectionMode.ResizingEnd,
x: 1995, x: 1995,
selection: { start: 2000, end: 2002 }, selection: { x1: 2000, x2: 2002 },
origSelection: { start: 2000, end: 2002 }, origSelection: { x1: 2000, x2: 2002 },
wantSelection: { start: 1995, end: 2000 }, wantSelection: { x1: 1995, x2: 2000 },
shouldPublish: true, shouldPublish: true,
}, },
])( ])(
@ -267,7 +267,7 @@ describe('stateReducer', () => {
x, x,
mousedownX = 0, mousedownX = 0,
selection, selection,
origSelection = { start: 0, end: 0 }, origSelection = { x1: 0, x2: 0 },
wantSelection = selection, wantSelection = selection,
wantHoverState = HoverState.Normal, wantHoverState = HoverState.Normal,
shouldPublish, shouldPublish,

View File

@ -3,6 +3,11 @@ import constrainNumeric from './helpers/constrainNumeric';
export const CanvasLogicalWidth = 2000; export const CanvasLogicalWidth = 2000;
export const CanvasLogicalHeight = 500; export const CanvasLogicalHeight = 500;
export interface CanvasRange {
x1: number;
x2: number;
}
export enum HoverState { export enum HoverState {
Normal, Normal,
OverSelectionStart, OverSelectionStart,
@ -15,11 +20,6 @@ export enum EmptySelectionAction {
SelectPrevious, SelectPrevious,
} }
export interface Selection {
start: number;
end: number;
}
export enum SelectionMode { export enum SelectionMode {
Normal, Normal,
Selecting, Selecting,
@ -32,8 +32,8 @@ export interface State {
width: number; width: number;
emptySelectionAction: EmptySelectionAction; emptySelectionAction: EmptySelectionAction;
hoverX: number; hoverX: number;
selection: Selection; selection: CanvasRange;
origSelection: Selection; origSelection: CanvasRange;
mousedownX: number; mousedownX: number;
mode: SelectionMode; mode: SelectionMode;
prevMode: SelectionMode; prevMode: SelectionMode;
@ -47,7 +47,7 @@ interface SelectionAction {
x: number; x: number;
// TODO: selection is only used for the setselection SelectionAction. Improve // TODO: selection is only used for the setselection SelectionAction. Improve
// the typing here. // the typing here.
selection?: Selection; selection?: CanvasRange;
} }
export const stateReducer = ( export const stateReducer = (
@ -62,7 +62,7 @@ export const stateReducer = (
{ x, type, selection: selectionToSet }: SelectionAction { x, type, selection: selectionToSet }: SelectionAction
): State => { ): State => {
let mode: SelectionMode; let mode: SelectionMode;
let newSelection: Selection; let newSelection: CanvasRange;
let hoverX: number; let hoverX: number;
let mousedownX: number; let mousedownX: number;
let cursorClass: string; let cursorClass: string;
@ -71,7 +71,7 @@ export const stateReducer = (
switch (type) { switch (type) {
case 'setselection': case 'setselection':
newSelection = selectionToSet || { start: 0, end: 0 }; newSelection = selectionToSet || { x1: 0, x2: 0 };
mousedownX = prevMousedownX; mousedownX = prevMousedownX;
mode = SelectionMode.Normal; mode = SelectionMode.Normal;
cursorClass = 'cursor-auto'; cursorClass = 'cursor-auto';
@ -97,7 +97,7 @@ export const stateReducer = (
mode = SelectionMode.Dragging; mode = SelectionMode.Dragging;
cursorClass = 'cursor-move'; cursorClass = 'cursor-move';
} else { } else {
newSelection = { start: x, end: x }; newSelection = { x1: x, x2: x };
mode = SelectionMode.Selecting; mode = SelectionMode.Selecting;
cursorClass = 'cursor-col-resize'; cursorClass = 'cursor-col-resize';
} }
@ -114,10 +114,10 @@ export const stateReducer = (
hoverState = HoverState.Normal; hoverState = HoverState.Normal;
if ( if (
newSelection.start == newSelection.end && newSelection.x1 == newSelection.x2 &&
emptySelectionAction == EmptySelectionAction.SelectNothing emptySelectionAction == EmptySelectionAction.SelectNothing
) { ) {
newSelection = { start: x, end: x }; newSelection = { x1: x, x2: x };
} }
break; break;
@ -161,13 +161,13 @@ export const stateReducer = (
mode = SelectionMode.Selecting; mode = SelectionMode.Selecting;
if (x < prevMousedownX) { if (x < prevMousedownX) {
newSelection = { newSelection = {
start: x, x1: x,
end: prevMousedownX, x2: prevMousedownX,
}; };
} else { } else {
newSelection = { newSelection = {
start: prevMousedownX, x1: prevMousedownX,
end: x, x2: x,
}; };
} }
@ -178,15 +178,15 @@ export const stateReducer = (
cursorClass = 'cursor-move'; cursorClass = 'cursor-move';
const diff = x - prevMousedownX; 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; let end = start + selectionWidth;
if (end > width) { if (end > width) {
end = width; end = width;
start = end - selectionWidth; start = end - selectionWidth;
} }
newSelection = { start: start, end: end }; newSelection = { x1: start, x2: end };
break; break;
} }
@ -195,10 +195,10 @@ export const stateReducer = (
cursorClass = 'cursor-col-resize'; cursorClass = 'cursor-col-resize';
const start = constrainNumeric(x, width); const start = constrainNumeric(x, width);
if (start > origSelection.end) { if (start > origSelection.x2) {
newSelection = { start: origSelection.end, end: start }; newSelection = { x1: origSelection.x2, x2: start };
} else { } else {
newSelection = { ...origSelection, start: start }; newSelection = { ...origSelection, x1: start };
} }
break; break;
@ -208,13 +208,13 @@ export const stateReducer = (
cursorClass = 'cursor-col-resize'; cursorClass = 'cursor-col-resize';
const end = constrainNumeric(x, width); const end = constrainNumeric(x, width);
if (end < origSelection.start) { if (end < origSelection.x1) {
newSelection = { newSelection = {
start: end, x1: end,
end: origSelection.start, x2: origSelection.x1,
}; };
} else { } else {
newSelection = { ...origSelection, end: x }; newSelection = { ...origSelection, x2: x };
} }
break; break;
@ -250,14 +250,17 @@ export const stateReducer = (
const hoverOffset = 10; const hoverOffset = 10;
const isHoveringSelectionStart = (x: number, selection: Selection): boolean => { const isHoveringSelectionStart = (
return x > selection.start - hoverOffset && x < selection.start + hoverOffset; x: number,
selection: CanvasRange
): boolean => {
return x > selection.x1 - hoverOffset && x < selection.x1 + hoverOffset;
}; };
const isHoveringSelectionEnd = (x: number, selection: Selection): boolean => { const isHoveringSelectionEnd = (x: number, selection: CanvasRange): boolean => {
return x > selection.end - hoverOffset && x < selection.end + hoverOffset; return x > selection.x2 - hoverOffset && x < selection.x2 + hoverOffset;
}; };
const isHoveringSelection = (x: number, selection: Selection): boolean => { const isHoveringSelection = (x: number, selection: CanvasRange): boolean => {
return x >= selection.start && x <= selection.end; return x >= selection.x1 && x <= selection.x2;
}; };