1
0
mirror of https://github.com/mifi/lossless-cut.git synced 2024-11-22 02:12:30 +01:00

allow relative timeline seek #2056

This commit is contained in:
Mikael Finstad 2024-08-06 00:55:49 +02:00
parent 8a6dd62d6d
commit 6a98e3315b
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26
2 changed files with 29 additions and 13 deletions

View File

@ -79,7 +79,7 @@ import { formatDuration, parseDuration } from './util/duration';
import { adjustRate } from './util/rate-calculator';
import { askExtractFramesAsImages } from './dialogs/extractFrames';
import { askForHtml5ifySpeed } from './dialogs/html5ify';
import { askForOutDir, askForImportChapters, promptTimeOffset, askForFileOpenAction, confirmExtractAllStreamsDialog, showCleanupFilesDialog, showDiskFull, showExportFailedDialog, showConcatFailedDialog, openYouTubeChaptersDialog, showRefuseToOverwrite, openDirToast, openExportFinishedToast, openConcatFinishedToast, showOpenDialog, showMuxNotSupported } from './dialogs';
import { askForOutDir, askForImportChapters, promptTimecode, askForFileOpenAction, confirmExtractAllStreamsDialog, showCleanupFilesDialog, showDiskFull, showExportFailedDialog, showConcatFailedDialog, openYouTubeChaptersDialog, showRefuseToOverwrite, openDirToast, openExportFinishedToast, openConcatFinishedToast, showOpenDialog, showMuxNotSupported } from './dialogs';
import { openSendReportDialog } from './reporting';
import { fallbackLng } from './i18n';
import { createSegment, getCleanCutSegments, findSegmentsAtCursor, sortSegments, convertSegmentsToChapters, hasAnySegmentOverlap, isDurationValid, playOnlyCurrentSegment, getSegmentTags } from './segments';
@ -1736,17 +1736,20 @@ function App() {
const goToTimecode = useCallback(async () => {
if (!filePath) return;
const timecode = await promptTimeOffset({
const timecode = await promptTimecode({
initialValue: formatTimecode({ seconds: commandedTimeRef.current }),
title: i18n.t('Seek to timecode'),
text: i18n.t('Use + and - for relative seek'),
allowRelative: true,
inputPlaceholder: timecodePlaceholder,
parseTimecode,
});
if (timecode === undefined) return;
userSeekAbs(timecode);
}, [filePath, formatTimecode, parseTimecode, timecodePlaceholder, userSeekAbs]);
if (timecode.relDirection != null) seekRel(timecode.duration * timecode.relDirection);
else userSeekAbs(timecode.duration);
}, [filePath, formatTimecode, parseTimecode, seekRel, timecodePlaceholder, userSeekAbs]);
const goToTimecodeDirect = useCallback(async ({ time: timeStr }: { time: string }) => {
if (!filePath) return;
@ -1819,7 +1822,7 @@ function App() {
}, [customOutDir, filePath, html5ifyAndLoad, hasVideo, hasAudio, rememberConvertToSupportedFormat, setWorking]);
const askStartTimeOffset = useCallback(async () => {
const newStartTimeOffset = await promptTimeOffset({
const newStartTimeOffset = await promptTimecode({
initialValue: startTimeOffset !== undefined ? formatTimecode({ seconds: startTimeOffset }) : undefined,
title: i18n.t('Set custom start time offset'),
text: i18n.t('Instead of video apparently starting at 0, you can offset by a specified value. This only applies to the preview inside LosslessCut and does not modify the file in any way. (Useful for viewing/cutting videos according to timecodes)'),
@ -1827,9 +1830,9 @@ function App() {
parseTimecode,
});
if (newStartTimeOffset === undefined) return;
if (newStartTimeOffset === undefined || newStartTimeOffset.duration < 0) return;
setStartTimeOffset(newStartTimeOffset);
setStartTimeOffset(newStartTimeOffset.duration);
}, [formatTimecode, parseTimecode, startTimeOffset, timecodePlaceholder]);
const toggleKeyboardShortcuts = useCallback(() => setKeyboardShortcutsVisible((v) => !v), []);

View File

@ -18,8 +18,10 @@ import { ParseTimecode, SegmentBase } from '../types';
const { dialog, shell } = window.require('@electron/remote');
export async function promptTimeOffset({ initialValue, title, text, inputPlaceholder, parseTimecode }: { initialValue?: string | undefined, title: string, text?: string | undefined, inputPlaceholder: string, parseTimecode: ParseTimecode }) {
const { value } = await Swal.fire({
export async function promptTimecode({ initialValue, title, text, inputPlaceholder, parseTimecode, allowRelative = false }: {
initialValue?: string | undefined, title: string, text?: string | undefined, inputPlaceholder: string, parseTimecode: ParseTimecode, allowRelative?: boolean,
}) {
const { value } = await Swal.fire<string>({
title,
text,
input: 'text',
@ -35,11 +37,22 @@ export async function promptTimeOffset({ initialValue, title, text, inputPlaceho
return undefined;
}
const duration = parseTimecode(value);
// Invalid, try again
if (duration === undefined) return promptTimeOffset({ initialValue: value, title, text, inputPlaceholder, parseTimecode });
let relDirection: number | undefined;
if (allowRelative) {
if (value.startsWith('-')) relDirection = -1;
else if (value.startsWith('+')) relDirection = 1;
}
return duration;
const value2 = allowRelative ? value.replace(/^[+-]/, '') : value;
const duration = parseTimecode(value2);
// Invalid, try again
if (duration === undefined) return promptTimecode({ initialValue: value, title, text, inputPlaceholder, parseTimecode, allowRelative });
return {
duration,
relDirection,
};
}
// https://github.com/mifi/lossless-cut/issues/1495