Skip to content

Commit

Permalink
add keyboard seek speed tuner #553
Browse files Browse the repository at this point in the history
  • Loading branch information
mifi committed Jan 23, 2021
1 parent 2eb42d2 commit 8ea08cf
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 17 deletions.
1 change: 1 addition & 0 deletions public/configStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const defaults = {
simpleMode: true,
outSegTemplate: undefined,
keyboardSeekAccFactor: 1.03,
keyboardNormalSeekSpeed: 1,
},
};

Expand Down
53 changes: 38 additions & 15 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import Timeline from './Timeline';
import RightMenu from './RightMenu';
import TimelineControls from './TimelineControls';
import ExportConfirm from './ExportConfirm';
import ValueTuner from './components/ValueTuner';
import { loadMifiLink } from './mifi';
import { primaryColor, controlsBackground, waveformColor } from './colors';
import { showMergeDialog, showOpenAndMergeDialog } from './merge/merge';
Expand Down Expand Up @@ -142,7 +143,7 @@ const App = memo(() => {
const isCustomFormatSelected = fileFormat !== detectedFileFormat;

const {
captureFormat, setCaptureFormat, customOutDir, setCustomOutDir, keyframeCut, setKeyframeCut, preserveMovData, setPreserveMovData, movFastStart, setMovFastStart, avoidNegativeTs, setAvoidNegativeTs, autoMerge, setAutoMerge, timecodeShowFrames, setTimecodeShowFrames, invertCutSegments, setInvertCutSegments, autoExportExtraStreams, setAutoExportExtraStreams, askBeforeClose, setAskBeforeClose, enableAskForImportChapters, setEnableAskForImportChapters, enableAskForFileOpenAction, setEnableAskForFileOpenAction, muted, setMuted, autoSaveProjectFile, setAutoSaveProjectFile, wheelSensitivity, setWheelSensitivity, invertTimelineScroll, setInvertTimelineScroll, language, setLanguage, ffmpegExperimental, setFfmpegExperimental, hideNotifications, setHideNotifications, autoLoadTimecode, setAutoLoadTimecode, autoDeleteMergedSegments, setAutoDeleteMergedSegments, exportConfirmEnabled, setExportConfirmEnabled, segmentsToChapters, setSegmentsToChapters, preserveMetadataOnMerge, setPreserveMetadataOnMerge, simpleMode, setSimpleMode, outSegTemplate, setOutSegTemplate, keyboardSeekAccFactor,
captureFormat, setCaptureFormat, customOutDir, setCustomOutDir, keyframeCut, setKeyframeCut, preserveMovData, setPreserveMovData, movFastStart, setMovFastStart, avoidNegativeTs, setAvoidNegativeTs, autoMerge, setAutoMerge, timecodeShowFrames, setTimecodeShowFrames, invertCutSegments, setInvertCutSegments, autoExportExtraStreams, setAutoExportExtraStreams, askBeforeClose, setAskBeforeClose, enableAskForImportChapters, setEnableAskForImportChapters, enableAskForFileOpenAction, setEnableAskForFileOpenAction, muted, setMuted, autoSaveProjectFile, setAutoSaveProjectFile, wheelSensitivity, setWheelSensitivity, invertTimelineScroll, setInvertTimelineScroll, language, setLanguage, ffmpegExperimental, setFfmpegExperimental, hideNotifications, setHideNotifications, autoLoadTimecode, setAutoLoadTimecode, autoDeleteMergedSegments, setAutoDeleteMergedSegments, exportConfirmEnabled, setExportConfirmEnabled, segmentsToChapters, setSegmentsToChapters, preserveMetadataOnMerge, setPreserveMetadataOnMerge, simpleMode, setSimpleMode, outSegTemplate, setOutSegTemplate, keyboardSeekAccFactor, setKeyboardSeekAccFactor, keyboardNormalSeekSpeed, setKeyboardNormalSeekSpeed,
} = useUserPreferences();

const outSegTemplateOrDefault = outSegTemplate || defaultOutSegTemplate;
Expand All @@ -154,7 +155,7 @@ const App = memo(() => {
// Global state
const [helpVisible, setHelpVisible] = useState(false);
const [settingsVisible, setSettingsVisible] = useState(false);
const [wheelTunerVisible, setWheelTunerVisible] = useState(false);
const [tunerVisible, setTunerVisible] = useState();
const [exportConfirmVisible, setExportConfirmVisible] = useState(false);
const [mifiLink, setMifiLink] = useState();

Expand Down Expand Up @@ -1322,11 +1323,11 @@ const App = memo(() => {
const reducePlaybackRate = () => changePlaybackRate(-1);
const increasePlaybackRate = () => changePlaybackRate(1);
function seekBackwards() {
seekRel(-1 * seekAccelerationRef.current);
seekRel(keyboardNormalSeekSpeed * seekAccelerationRef.current * -1);
seekAccelerationRef.current *= keyboardSeekAccFactor;
}
function seekForwards() {
seekRel(seekAccelerationRef.current);
seekRel(keyboardNormalSeekSpeed * seekAccelerationRef.current);
seekAccelerationRef.current *= keyboardSeekAccFactor;
}
const seekReset = () => {
Expand Down Expand Up @@ -1397,6 +1398,7 @@ const App = memo(() => {
setCutEnd, setCutStart, seekRel, seekRelPercent, shortStep, cleanupFiles, jumpSeg,
seekClosestKeyframe, zoomRel, toggleComfortZoom, splitCurrentSegment, exportConfirmVisible,
increaseRotation, jumpCutStart, jumpCutEnd, cutSegmentsHistory, keyboardSeekAccFactor,
keyboardNormalSeekSpeed,
]);

useEffect(() => {
Expand Down Expand Up @@ -1868,9 +1870,9 @@ const App = memo(() => {
/>
), [autoExportExtraStreams, setAutoExportExtraStreams]);

const onWheelTunerRequested = useCallback(() => {
const onTunerRequested = useCallback((type) => {
setSettingsVisible(false);
setWheelTunerVisible(true);
setTunerVisible(type);
}, []);

const renderSettings = useCallback(() => (
Expand Down Expand Up @@ -1908,9 +1910,9 @@ const App = memo(() => {

AutoExportToggler={AutoExportToggler}
renderCaptureFormatButton={renderCaptureFormatButton}
onWheelTunerRequested={onWheelTunerRequested}
onTunerRequested={onTunerRequested}
/>
), [changeOutDir, customOutDir, autoMerge, setAutoMerge, keyframeCut, setKeyframeCut, invertCutSegments, setInvertCutSegments, autoSaveProjectFile, setAutoSaveProjectFile, timecodeShowFrames, setTimecodeShowFrames, askBeforeClose, setAskBeforeClose, enableAskForImportChapters, setEnableAskForImportChapters, enableAskForFileOpenAction, setEnableAskForFileOpenAction, ffmpegExperimental, setFfmpegExperimental, invertTimelineScroll, setInvertTimelineScroll, language, setLanguage, hideNotifications, setHideNotifications, autoLoadTimecode, setAutoLoadTimecode, autoDeleteMergedSegments, setAutoDeleteMergedSegments, AutoExportToggler, renderCaptureFormatButton, onWheelTunerRequested]);
), [changeOutDir, customOutDir, autoMerge, setAutoMerge, keyframeCut, setKeyframeCut, invertCutSegments, setInvertCutSegments, autoSaveProjectFile, setAutoSaveProjectFile, timecodeShowFrames, setTimecodeShowFrames, askBeforeClose, setAskBeforeClose, enableAskForImportChapters, setEnableAskForImportChapters, enableAskForFileOpenAction, setEnableAskForFileOpenAction, ffmpegExperimental, setFfmpegExperimental, invertTimelineScroll, setInvertTimelineScroll, language, setLanguage, hideNotifications, setHideNotifications, autoLoadTimecode, setAutoLoadTimecode, autoDeleteMergedSegments, setAutoDeleteMergedSegments, AutoExportToggler, renderCaptureFormatButton, onTunerRequested]);

useEffect(() => {
if (!isStoreBuild) loadMifiLink().then(setMifiLink);
Expand Down Expand Up @@ -1948,6 +1950,33 @@ const App = memo(() => {

const { t } = useTranslation();

function renderTuner(type) {
const types = {
wheelSensitivity: {
title: t('Timeline trackpad/wheel sensitivity'),
value: wheelSensitivity,
setValue: setWheelSensitivity,
},
keyboardNormalSeekSpeed: {
title: t('Timeline keyboard seek speed'),
value: keyboardNormalSeekSpeed,
setValue: setKeyboardNormalSeekSpeed,
min: 0,
max: 100,
},
keyboardSeekAccFactor: {
title: t('Timeline keyboard seek acceleration'),
value: keyboardSeekAccFactor,
setValue: setKeyboardSeekAccFactor,
min: 1,
max: 2,
},
};
const { title, value, setValue, min, max } = types[type];

return <ValueTuner title={title} style={{ bottom: bottomBarHeight }} value={value} setValue={setValue} onFinished={() => setTunerVisible()} max={max} min={min} />;
}

// throw new Error('Test');

return (
Expand Down Expand Up @@ -2228,13 +2257,7 @@ const App = memo(() => {
renderSettings={renderSettings}
/>

{wheelTunerVisible && (
<div style={{ display: 'flex', alignItems: 'center', background: 'white', color: 'black', padding: 10, margin: 10, borderRadius: 10, width: '100%', maxWidth: 500, position: 'fixed', left: 0, bottom: bottomBarHeight, zIndex: 10 }}>
{t('Timeline trackpad/wheel sensitivity')}
<input style={{ flexGrow: 1 }} type="range" min="0" max="1000" step="1" value={wheelSensitivity * 1000} onChange={e => setWheelSensitivity(e.target.value / 1000)} />
<Button height={20} intent="success" onClick={() => setWheelTunerVisible(false)}>{t('Done')}</Button>
</div>
)}
{tunerVisible && renderTuner(tunerVisible)}
</div>
);
});
Expand Down
18 changes: 16 additions & 2 deletions src/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
const Settings = memo(({
changeOutDir, customOutDir, autoMerge, setAutoMerge, keyframeCut, setKeyframeCut, invertCutSegments, setInvertCutSegments,
autoSaveProjectFile, setAutoSaveProjectFile, timecodeShowFrames, setTimecodeShowFrames, askBeforeClose, setAskBeforeClose,
AutoExportToggler, renderCaptureFormatButton, onWheelTunerRequested, language, setLanguage,
AutoExportToggler, renderCaptureFormatButton, onTunerRequested, language, setLanguage,
invertTimelineScroll, setInvertTimelineScroll, ffmpegExperimental, setFfmpegExperimental,
enableAskForImportChapters, setEnableAskForImportChapters, enableAskForFileOpenAction, setEnableAskForFileOpenAction,
hideNotifications, setHideNotifications, autoLoadTimecode, setAutoLoadTimecode, autoDeleteMergedSegments, setAutoDeleteMergedSegments,
Expand Down Expand Up @@ -171,7 +171,21 @@ const Settings = memo(({
<Row>
<KeyCell>{t('Timeline trackpad/wheel sensitivity')}</KeyCell>
<Table.TextCell>
<Button onClick={onWheelTunerRequested}>{t('Change sensitivity')}</Button>
<Button onClick={() => onTunerRequested('wheelSensitivity')}>{t('Change value')}</Button>
</Table.TextCell>
</Row>

<Row>
<KeyCell>{t('Timeline keyboard seek speed')}</KeyCell>
<Table.TextCell>
<Button onClick={() => onTunerRequested('keyboardNormalSeekSpeed')}>{t('Change value')}</Button>
</Table.TextCell>
</Row>

<Row>
<KeyCell>{t('Timeline keyboard seek acceleration')}</KeyCell>
<Table.TextCell>
<Button onClick={() => onTunerRequested('keyboardSeekAccFactor')}>{t('Change value')}</Button>
</Table.TextCell>
</Row>

Expand Down
27 changes: 27 additions & 0 deletions src/components/ValueTuner.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { memo } from 'react';
import { Button } from 'evergreen-ui';
import { useTranslation } from 'react-i18next';

const ValueTuner = memo(({ style, title, value, setValue, onFinished, resolution = 1000, min = 0, max = 1 }) => {
const { t } = useTranslation();

function onChange(e) {
e.target.blur();
setValue(Math.min(Math.max(min, ((e.target.value / resolution) * (max - min)) + min)), max);
}

return (
<div style={{ background: 'white', color: 'black', padding: 10, margin: 10, borderRadius: 10, width: '100%', maxWidth: 500, position: 'fixed', left: 0, zIndex: 10, ...style }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div>{title}</div>
<div style={{ marginLeft: 10, fontWeight: 'bold' }}>{value.toFixed(2)}</div>
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<input style={{ flexGrow: 1 }} type="range" min="0" max="1000" step="1" value={((value - min) / (max - min)) * resolution} onChange={onChange} />
<Button height={20} intent="success" onClick={onFinished}>{t('Done')}</Button>
</div>
</div>
);
});

export default ValueTuner;
4 changes: 4 additions & 0 deletions src/hooks/useUserPreferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ export default () => {
useEffect(() => safeSetConfig('outSegTemplate', outSegTemplate), [outSegTemplate]);
const [keyboardSeekAccFactor, setKeyboardSeekAccFactor] = useState(configStore.get('keyboardSeekAccFactor'));
useEffect(() => safeSetConfig('keyboardSeekAccFactor', keyboardSeekAccFactor), [keyboardSeekAccFactor]);
const [keyboardNormalSeekSpeed, setKeyboardNormalSeekSpeed] = useState(configStore.get('keyboardNormalSeekSpeed'));
useEffect(() => safeSetConfig('keyboardNormalSeekSpeed', keyboardNormalSeekSpeed), [keyboardNormalSeekSpeed]);


// NOTE! This useEffect must be placed after all usages of firstUpdateRef.current (safeSetConfig)
Expand Down Expand Up @@ -144,5 +146,7 @@ export default () => {
setOutSegTemplate,
keyboardSeekAccFactor,
setKeyboardSeekAccFactor,
keyboardNormalSeekSpeed,
setKeyboardNormalSeekSpeed,
};
};

0 comments on commit 8ea08cf

Please sign in to comment.