kopia lustrzana https://github.com/mifi/lossless-cut
add shortcut shift+j for toggling keyboard shortcut dialog #654
also allow resetting key config #726pull/982/head
rodzic
1a59be3e75
commit
c2cb1f5501
|
@ -62,6 +62,7 @@ const defaultKeyBindings = [
|
|||
|
||||
{ keys: 'e', action: 'export' },
|
||||
{ keys: 'h', action: 'toggleHelp' },
|
||||
{ keys: 'shift+/', action: 'toggleKeyboardShortcuts' },
|
||||
{ keys: 'escape', action: 'closeActiveScreen' },
|
||||
];
|
||||
|
||||
|
|
13
src/App.jsx
13
src/App.jsx
|
@ -197,7 +197,7 @@ const App = memo(() => {
|
|||
const isCustomFormatSelected = fileFormat !== detectedFileFormat;
|
||||
|
||||
const {
|
||||
captureFormat, setCaptureFormat, customOutDir, setCustomOutDir, keyframeCut, setKeyframeCut, preserveMovData, setPreserveMovData, movFastStart, setMovFastStart, avoidNegativeTs, setAvoidNegativeTs, autoMerge, setAutoMerge, timecodeFormat, setTimecodeFormat, invertCutSegments, setInvertCutSegments, autoExportExtraStreams, setAutoExportExtraStreams, askBeforeClose, setAskBeforeClose, enableAskForImportChapters, setEnableAskForImportChapters, enableAskForFileOpenAction, setEnableAskForFileOpenAction, playbackVolume, setPlaybackVolume, 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, enableTransferTimestamps, setEnableTransferTimestamps, outFormatLocked, setOutFormatLocked, safeOutputFileName, setSafeOutputFileName, enableAutoHtml5ify, setEnableAutoHtml5ify, segmentsToChaptersOnly, setSegmentsToChaptersOnly, keyBindings, setKeyBindings,
|
||||
captureFormat, setCaptureFormat, customOutDir, setCustomOutDir, keyframeCut, setKeyframeCut, preserveMovData, setPreserveMovData, movFastStart, setMovFastStart, avoidNegativeTs, setAvoidNegativeTs, autoMerge, setAutoMerge, timecodeFormat, setTimecodeFormat, invertCutSegments, setInvertCutSegments, autoExportExtraStreams, setAutoExportExtraStreams, askBeforeClose, setAskBeforeClose, enableAskForImportChapters, setEnableAskForImportChapters, enableAskForFileOpenAction, setEnableAskForFileOpenAction, playbackVolume, setPlaybackVolume, 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, enableTransferTimestamps, setEnableTransferTimestamps, outFormatLocked, setOutFormatLocked, safeOutputFileName, setSafeOutputFileName, enableAutoHtml5ify, setEnableAutoHtml5ify, segmentsToChaptersOnly, setSegmentsToChaptersOnly, keyBindings, setKeyBindings, resetKeyBindings,
|
||||
} = useUserPreferences();
|
||||
|
||||
const {
|
||||
|
@ -1626,6 +1626,8 @@ const App = memo(() => {
|
|||
setStartTimeOffset(newStartTimeOffset);
|
||||
}, [startTimeOffset]);
|
||||
|
||||
const toggleKeyboardShortcuts = useCallback(() => setKeyboardShortcutsVisible((v) => !v), []);
|
||||
|
||||
const onKeyPress = useCallback(({ action, keyup }) => {
|
||||
function seekReset() {
|
||||
seekAccelerationRef.current = 1;
|
||||
|
@ -1723,6 +1725,11 @@ const App = memo(() => {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (action === 'toggleKeyboardShortcuts') {
|
||||
toggleKeyboardShortcuts();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (concatDialogVisible || keyboardShortcutsVisible) {
|
||||
return true; // don't allow any further hotkeys
|
||||
}
|
||||
|
@ -1740,7 +1747,7 @@ const App = memo(() => {
|
|||
if (match) return bubble;
|
||||
|
||||
return true; // bubble the event
|
||||
}, [addCutSegment, askSetStartTimeOffset, batchFileJump, captureSnapshot, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, closeExportConfirm, concatCurrentBatch, concatDialogVisible, convertFormatBatch, createFixedDurationSegments, createNumSegments, currentSegIndexSafe, cutSegmentsHistory, exportConfirmVisible, extractAllStreams, goToTimecode, increaseRotation, invertAllCutSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, keyboardShortcutsVisible, onExportConfirm, onExportPress, onLabelSegmentPress, removeCutSegment, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, setCutEnd, setCutStart, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleHelp, toggleKeyframeCut, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, userHtml5ifyCurrentFile, zoomRel]);
|
||||
}, [addCutSegment, askSetStartTimeOffset, batchFileJump, captureSnapshot, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, closeExportConfirm, concatCurrentBatch, concatDialogVisible, convertFormatBatch, createFixedDurationSegments, createNumSegments, currentSegIndexSafe, cutSegmentsHistory, exportConfirmVisible, extractAllStreams, goToTimecode, increaseRotation, invertAllCutSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, keyboardShortcutsVisible, onExportConfirm, onExportPress, onLabelSegmentPress, removeCutSegment, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, setCutEnd, setCutStart, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleHelp, toggleKeyboardShortcuts, toggleKeyframeCut, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, userHtml5ifyCurrentFile, zoomRel]);
|
||||
|
||||
useKeyboard({ keyBindings, onKeyPress });
|
||||
|
||||
|
@ -2481,7 +2488,7 @@ const App = memo(() => {
|
|||
|
||||
<ConcatDialog isShown={batchFiles.length > 0 && concatDialogVisible} onHide={() => setConcatDialogVisible(false)} initialPaths={batchFilePaths} onConcat={mergeFiles} segmentsToChapters={segmentsToChapters} setSegmentsToChapters={setSegmentsToChapters} setAlwaysConcatMultipleFiles={setAlwaysConcatMultipleFiles} alwaysConcatMultipleFiles={alwaysConcatMultipleFiles} preserveMetadataOnMerge={preserveMetadataOnMerge} setPreserveMetadataOnMerge={setPreserveMetadataOnMerge} preserveMovData={preserveMovData} setPreserveMovData={setPreserveMovData} />
|
||||
|
||||
<KeyboardShortcuts isShown={keyboardShortcutsVisible} onHide={() => setKeyboardShortcutsVisible(false)} keyBindings={keyBindings} setKeyBindings={setKeyBindings} currentCutSeg={currentCutSeg} />
|
||||
<KeyboardShortcuts isShown={keyboardShortcutsVisible} onHide={() => setKeyboardShortcutsVisible(false)} keyBindings={keyBindings} setKeyBindings={setKeyBindings} currentCutSeg={currentCutSeg} resetKeyBindings={resetKeyBindings} />
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
|
|
@ -100,7 +100,7 @@ const CreateBinding = memo(({
|
|||
const rowStyle = { display: 'flex', alignItems: 'center', margin: '6px 0' };
|
||||
|
||||
const KeyboardShortcuts = memo(({
|
||||
keyBindings, setKeyBindings, currentCutSeg,
|
||||
keyBindings, setKeyBindings, resetKeyBindings, currentCutSeg,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -136,7 +136,11 @@ const KeyboardShortcuts = memo(({
|
|||
toggleHelp: {
|
||||
name: t('Show/hide help screen'),
|
||||
},
|
||||
toggleKeyboardShortcuts: {
|
||||
name: t('Keyboard & mouse shortcuts'),
|
||||
},
|
||||
|
||||
// playbackCategory
|
||||
togglePlayResetSpeed: {
|
||||
name: t('Play/pause'),
|
||||
category: playbackCategory,
|
||||
|
@ -162,6 +166,7 @@ const KeyboardShortcuts = memo(({
|
|||
category: playbackCategory,
|
||||
},
|
||||
|
||||
// seekingCategory
|
||||
seekPreviousFrame: {
|
||||
name: t('Step backward 1 frame'),
|
||||
category: seekingCategory,
|
||||
|
@ -209,6 +214,7 @@ const KeyboardShortcuts = memo(({
|
|||
category: seekingCategory,
|
||||
},
|
||||
|
||||
// segmentsAndCutpointsCategory
|
||||
addSegment: {
|
||||
name: t('Add cut segment'),
|
||||
category: segmentsAndCutpointsCategory,
|
||||
|
@ -272,6 +278,7 @@ const KeyboardShortcuts = memo(({
|
|||
category: segmentsAndCutpointsCategory,
|
||||
},
|
||||
|
||||
// streamsCategory
|
||||
toggleStreamsSelector: {
|
||||
name: t('Edit tracks / metadata tags'),
|
||||
category: streamsCategory,
|
||||
|
@ -281,6 +288,7 @@ const KeyboardShortcuts = memo(({
|
|||
category: streamsCategory,
|
||||
},
|
||||
|
||||
// zoomOperationsCategory
|
||||
timelineZoomIn: {
|
||||
name: t('Zoom in timeline'),
|
||||
category: zoomOperationsCategory,
|
||||
|
@ -294,6 +302,7 @@ const KeyboardShortcuts = memo(({
|
|||
category: zoomOperationsCategory,
|
||||
},
|
||||
|
||||
// outputCategory
|
||||
export: {
|
||||
name: t('Export segment(s)'),
|
||||
category: outputCategory,
|
||||
|
@ -315,6 +324,7 @@ const KeyboardShortcuts = memo(({
|
|||
category: outputCategory,
|
||||
},
|
||||
|
||||
// batchFilesCategory
|
||||
batchPreviousFile: {
|
||||
name: t('Previous file'),
|
||||
category: batchFilesCategory,
|
||||
|
@ -332,6 +342,7 @@ const KeyboardShortcuts = memo(({
|
|||
category: batchFilesCategory,
|
||||
},
|
||||
|
||||
// otherCategory
|
||||
toggleKeyframeCutMode: {
|
||||
name: t('Cut mode'),
|
||||
category: otherCategory,
|
||||
|
@ -380,6 +391,14 @@ const KeyboardShortcuts = memo(({
|
|||
setKeyBindings((existingBindings) => existingBindings.filter((existingBinding) => !(existingBinding.keys === keys && existingBinding.action === action)));
|
||||
}, [setKeyBindings, t]);
|
||||
|
||||
|
||||
const onResetClick = useCallback(() => {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (!window.confirm(t('Are you sure?'))) return;
|
||||
|
||||
resetKeyBindings();
|
||||
}, [resetKeyBindings, t]);
|
||||
|
||||
const onAddBindingClick = useCallback((action) => {
|
||||
setCreatingBinding(action);
|
||||
}, []);
|
||||
|
@ -448,13 +467,15 @@ const KeyboardShortcuts = memo(({
|
|||
))}
|
||||
</div>
|
||||
|
||||
<Button intent="danger" onClick={onResetClick}>{t('Reset')}</Button>
|
||||
|
||||
<CreateBinding actionsMap={actionsMap} action={creatingBinding} setCreatingBinding={setCreatingBinding} onNewKeyBindingConfirmed={onNewKeyBindingConfirmed} />
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
const KeyboardShortcutsDialog = memo(({
|
||||
isShown, onHide, keyBindings, setKeyBindings, currentCutSeg,
|
||||
isShown, onHide, keyBindings, setKeyBindings, resetKeyBindings, currentCutSeg,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -468,7 +489,7 @@ const KeyboardShortcutsDialog = memo(({
|
|||
onConfirm={onHide}
|
||||
topOffset="3vh"
|
||||
>
|
||||
{isShown ? <KeyboardShortcuts keyBindings={keyBindings} setKeyBindings={setKeyBindings} currentCutSeg={currentCutSeg} /> : <div />}
|
||||
{isShown ? <KeyboardShortcuts keyBindings={keyBindings} setKeyBindings={setKeyBindings} currentCutSeg={currentCutSeg} resetKeyBindings={resetKeyBindings} /> : <div />}
|
||||
</Dialog>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useEffect, useState, useRef, useCallback } from 'react';
|
||||
import i18n from 'i18next';
|
||||
|
||||
import { errorToast } from '../util';
|
||||
|
@ -102,6 +102,10 @@ export default () => {
|
|||
useEffect(() => safeSetConfig('segmentsToChaptersOnly', segmentsToChaptersOnly), [segmentsToChaptersOnly]);
|
||||
const [keyBindings, setKeyBindings] = useState(safeGetConfig('keyBindings'));
|
||||
useEffect(() => safeSetConfig('keyBindings', keyBindings), [keyBindings]);
|
||||
const resetKeyBindings = useCallback(() => {
|
||||
configStore.reset('keyBindings');
|
||||
setKeyBindings(safeGetConfig('keyBindings'));
|
||||
}, []);
|
||||
|
||||
// NOTE! This useEffect must be placed after all usages of firstUpdateRef.current (safeSetConfig)
|
||||
useEffect(() => {
|
||||
|
@ -182,5 +186,6 @@ export default () => {
|
|||
setSegmentsToChaptersOnly,
|
||||
keyBindings,
|
||||
setKeyBindings,
|
||||
resetKeyBindings,
|
||||
};
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue