Disable buttons when zooming is not possible

This commit is contained in:
Rob Watson 2022-01-17 18:58:19 +01:00
parent a4e9ebca3b
commit 9ae4335b19
4 changed files with 100 additions and 9 deletions

View File

@ -16,7 +16,12 @@ import { SeekBar } from './SeekBar';
import { firstValueFrom, from, Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';
import millisFromDuration from './helpers/millisFromDuration';
import { zoomViewportIn, zoomViewportOut } from './helpers/zoom';
import {
canZoomViewportIn,
canZoomViewportOut,
zoomViewportIn,
zoomViewportOut,
} from './helpers/zoom';
import toHHMMSS from './helpers/toHHMMSS';
import framesToDuration from './helpers/framesToDuration';
import { ClockIcon, ExternalLinkIcon } from '@heroicons/react/solid';
@ -448,6 +453,8 @@ function App(): JSX.Element {
</div>
<ControlBar
playState={playState}
zoomInEnabled={canZoomViewportIn(viewport, selection, zoomFactor)}
zoomOutEnabled={canZoomViewportOut(viewport, mediaSet.audioFrames)}
onTogglePlay={togglePlay}
onClip={handleClip}
onZoomIn={handleZoomIn}

View File

@ -12,6 +12,8 @@ import {
interface Props {
playState: PlayState;
zoomInEnabled: boolean;
zoomOutEnabled: boolean;
onTogglePlay: () => void;
onClip: () => void;
onZoomIn: () => void;
@ -21,11 +23,14 @@ interface Props {
const ControlBar: React.FC<Props> = React.memo((props: Props) => {
const buttonStyle =
'bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded';
'bg-gray-600 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded';
const disabledButtonStyle =
'bg-gray-700 text-white font-bold py-2 px-4 rounded cursor-auto';
const downloadButtonStyle = props.downloadClipEnabled
? 'bg-green-700 hover:bg-green-600 text-white font-bold py-2 px-4 rounded absolute right-0'
: 'bg-gray-700 hover:cursor-not-allowed text-gray-500 font-bold py-2 px-4 rounded absolute right-0';
? 'bg-green-600 hover:bg-green-600 text-white font-bold py-2 px-4 rounded absolute right-0'
: 'bg-gray-600 hover:cursor-not-allowed text-gray-500 font-bold py-2 px-4 rounded absolute right-0';
const iconStyle = 'inline h-7 w-7 text-white-500';
@ -67,13 +72,13 @@ const ControlBar: React.FC<Props> = React.memo((props: Props) => {
<FastForwardIcon className={iconStyle} />
</button>
<button
className={buttonStyle}
className={props.zoomInEnabled ? buttonStyle : disabledButtonStyle}
onClick={(evt) => filterMouseEvent(evt, props.onZoomIn)}
>
<ZoomInIcon className={iconStyle} />
</button>
<button
className={buttonStyle}
className={props.zoomOutEnabled ? buttonStyle : disabledButtonStyle}
onClick={(evt) => filterMouseEvent(evt, props.onZoomOut)}
>
<ZoomOutIcon className={iconStyle} />

View File

@ -1,4 +1,9 @@
import { zoomViewportIn, zoomViewportOut } from './zoom';
import {
zoomViewportIn,
zoomViewportOut,
canZoomViewportIn,
canZoomViewportOut,
} from './zoom';
// zf is the zoom factor.
const zf = 2;
@ -220,3 +225,49 @@ describe('zoomViewportOut', () => {
});
});
});
describe('canZoomViewportIn', () => {
it('does now allow zooming when the viewport is inactive', () => {
const result = canZoomViewportIn(
{ start: 0, end: 0 },
{ start: 0, end: 0 },
zf
);
expect(result).toBeFalsy();
});
it('does not allow zooming past the selection', () => {
const result = canZoomViewportIn(
{ start: 1000, end: 2000 },
{ start: 1100, end: 1900 },
zf
);
expect(result).toBeFalsy();
});
it('allows zooming', () => {
const result = canZoomViewportIn(
{ start: 1000, end: 2000 },
{ start: 0, end: 100 },
zf
);
expect(result).toBeTruthy();
});
});
describe('canZoomViewportOut', () => {
it('does now allow zooming when the viewport is inactive', () => {
const result = canZoomViewportOut({ start: 0, end: 0 }, 1000);
expect(result).toBeFalsy();
});
it('does now allow zooming when already at maximum zoom', () => {
const result = canZoomViewportOut({ start: 0, end: 1000 }, 1000);
expect(result).toBeFalsy();
});
it('allows zooming', () => {
const result = canZoomViewportOut({ start: 1000, end: 2000 }, 5000);
expect(result).toBeTruthy();
});
});

View File

@ -7,7 +7,7 @@ export function zoomViewportIn(
position: number,
factor: number
): Frames {
if (viewport.start == viewport.end) {
if (!canZoomViewportIn(viewport, selection, factor)) {
return viewport;
}
@ -27,7 +27,7 @@ export function zoomViewportOut(
position: number,
factor: number
): Frames {
if (viewport.start == viewport.end) {
if (!canZoomViewportOut(viewport, numFrames)) {
return viewport;
}
@ -74,3 +74,31 @@ function zoom(
return { start: newStart, end: newEnd };
}
export function canZoomViewportIn(
viewport: Frames,
selection: Frames,
factor: number
): boolean {
if (viewport.start == viewport.end) {
return false;
}
if (selection.start != selection.end) {
const newWidth = Math.round((viewport.end - viewport.start) / factor);
return newWidth > selection.end - selection.start;
}
return true;
}
export function canZoomViewportOut(
viewport: Frames,
numFrames: number
): boolean {
if (viewport.start == viewport.end) {
return false;
}
return viewport.start > 0 || viewport.end < numFrames;
}