kopia lustrzana https://github.com/mifi/lossless-cut
allow removing multiple segments
rodzic
2ff8689d40
commit
cf9347904b
45
src/App.jsx
45
src/App.jsx
|
@ -498,7 +498,7 @@ const App = memo(() => {
|
|||
|
||||
// const getSafeCutTime = useCallback((cutTime, next) => ffmpeg.getSafeCutTime(neighbouringFrames, cutTime, next), [neighbouringFrames]);
|
||||
|
||||
const addCutSegment = useCallback(() => {
|
||||
const addSegment = useCallback(() => {
|
||||
try {
|
||||
// Cannot add if prev seg is not finished
|
||||
if (currentCutSeg.start === undefined && currentCutSeg.end === undefined) return;
|
||||
|
@ -521,7 +521,7 @@ const App = memo(() => {
|
|||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}, [currentCutSeg.start, currentCutSeg.end, getCurrentTime, cutSegments, createIndexedSegment, setCutSegments]);
|
||||
}, [currentCutSeg.start, currentCutSeg.end, getCurrentTime, duration, cutSegments, createIndexedSegment, setCutSegments]);
|
||||
|
||||
const setCutStart = useCallback(() => {
|
||||
if (!filePath) return;
|
||||
|
@ -530,8 +530,8 @@ const App = memo(() => {
|
|||
// https://github.com/mifi/lossless-cut/issues/168
|
||||
// If current time is after the end of the current segment in the timeline,
|
||||
// add a new segment that starts at playerTime
|
||||
if (currentCutSeg.end != null && currentTime > currentCutSeg.end) {
|
||||
addCutSegment();
|
||||
if (currentCutSeg.end != null && currentTime >= currentCutSeg.end) {
|
||||
addSegment();
|
||||
} else {
|
||||
try {
|
||||
const startTime = currentTime;
|
||||
|
@ -544,7 +544,7 @@ const App = memo(() => {
|
|||
handleError(err);
|
||||
}
|
||||
}
|
||||
}, [filePath, getCurrentTime, currentCutSeg.end, addCutSegment, setCutTime]);
|
||||
}, [filePath, getCurrentTime, currentCutSeg.end, addSegment, setCutTime]);
|
||||
|
||||
const setCutEnd = useCallback(() => {
|
||||
if (!filePath) return;
|
||||
|
@ -850,20 +850,22 @@ const App = memo(() => {
|
|||
});
|
||||
}, [copyAnyAudioTrack, filePath, mainStreams, setCopyStreamIdsForPath]);
|
||||
|
||||
const removeCutSegment = useCallback((index) => {
|
||||
if (cutSegments.length === 1 && cutSegments[0].start == null && cutSegments[0].end == null) return; // Initial segment
|
||||
|
||||
if (cutSegments.length <= 1) {
|
||||
clearSegments();
|
||||
return;
|
||||
}
|
||||
|
||||
const cutSegmentsNew = [...cutSegments];
|
||||
cutSegmentsNew.splice(index, 1);
|
||||
|
||||
setCutSegments(cutSegmentsNew);
|
||||
const removeSegments = useCallback((removeSegmentIds) => {
|
||||
if (cutSegments.length === 1 && cutSegments[0].start == null && cutSegments[0].end == null) return; // We are at initial segment, nothing more we can do (it cannot be removed)
|
||||
setCutSegments((existing) => {
|
||||
const newSegments = existing.filter((seg) => !removeSegmentIds.includes(seg.segId));
|
||||
if (newSegments.length === 0) {
|
||||
clearSegments(); // when removing the last segments, we start over
|
||||
return existing;
|
||||
}
|
||||
return newSegments;
|
||||
});
|
||||
}, [clearSegments, cutSegments, setCutSegments]);
|
||||
|
||||
const removeCutSegment = useCallback((index) => {
|
||||
removeSegments([cutSegments[index].segId]);
|
||||
}, [cutSegments, removeSegments]);
|
||||
|
||||
const thumnailsRef = useRef([]);
|
||||
const thumnailsRenderingPromiseRef = useRef();
|
||||
|
||||
|
@ -1165,6 +1167,8 @@ const App = memo(() => {
|
|||
const deselectAllSegments = useCallback(() => setDeselectedSegmentIds(Object.fromEntries(cutSegments.map((s) => [s.segId, true]))), [cutSegments]);
|
||||
const selectAllSegments = useCallback(() => setDeselectedSegmentIds({}), []);
|
||||
|
||||
const removeSelectedSegments = useCallback(() => removeSegments(selectedSegmentsRaw.map((seg) => seg.segId)), [removeSegments, selectedSegmentsRaw]);
|
||||
|
||||
const selectOnlyCurrentSegment = useCallback(() => selectOnlySegment(currentCutSeg), [currentCutSeg, selectOnlySegment]);
|
||||
const toggleCurrentSegmentSelected = useCallback(() => toggleSegmentSelected(currentCutSeg), [currentCutSeg, toggleSegmentSelected]);
|
||||
|
||||
|
@ -1841,7 +1845,7 @@ const App = memo(() => {
|
|||
undo: () => cutSegmentsHistory.back(),
|
||||
redo: () => cutSegmentsHistory.forward(),
|
||||
labelCurrentSegment: () => { onLabelSegmentPress(currentSegIndexSafe); return false; },
|
||||
addSegment: () => addCutSegment(),
|
||||
addSegment,
|
||||
toggleHelp: () => { toggleHelp(); return false; },
|
||||
export: onExportPress,
|
||||
reorderSegsByStartTime,
|
||||
|
@ -1909,7 +1913,7 @@ const App = memo(() => {
|
|||
if (match) return bubble;
|
||||
|
||||
return true; // bubble the event
|
||||
}, [addCutSegment, askSetStartTimeOffset, batchFileJump, batchOpenSelectedFile, captureSnapshot, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, closeExportConfirm, concatCurrentBatch, concatDialogVisible, convertFormatBatch, createFixedDurationSegments, createNumSegments, currentSegIndexSafe, cutSegmentsHistory, deselectAllSegments, exportConfirmVisible, extractAllStreams, fillSegmentsGaps, goToTimecode, increaseRotation, invertAllCutSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, keyboardShortcutsVisible, onExportConfirm, onExportPress, onLabelSegmentPress, pause, play, removeCutSegment, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, selectAllSegments, selectOnlyCurrentSegment, setCutEnd, setCutStart, setPlaybackVolume, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleCurrentSegmentSelected, toggleHelp, toggleKeyboardShortcuts, toggleKeyframeCut, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, tryFixInvalidDuration, userHtml5ifyCurrentFile, zoomRel]);
|
||||
}, [addSegment, askSetStartTimeOffset, batchFileJump, batchOpenSelectedFile, captureSnapshot, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, closeExportConfirm, concatCurrentBatch, concatDialogVisible, convertFormatBatch, createFixedDurationSegments, createNumSegments, currentSegIndexSafe, cutSegmentsHistory, deselectAllSegments, exportConfirmVisible, extractAllStreams, fillSegmentsGaps, goToTimecode, increaseRotation, invertAllCutSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, keyboardShortcutsVisible, onExportConfirm, onExportPress, onLabelSegmentPress, pause, play, removeCutSegment, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, selectAllSegments, selectOnlyCurrentSegment, setCutEnd, setCutStart, setPlaybackVolume, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleCurrentSegmentSelected, toggleHelp, toggleKeyboardShortcuts, toggleKeyframeCut, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, tryFixInvalidDuration, userHtml5ifyCurrentFile, zoomRel]);
|
||||
|
||||
useKeyboard({ keyBindings, onKeyPress });
|
||||
|
||||
|
@ -2327,8 +2331,9 @@ const App = memo(() => {
|
|||
onLabelSegmentPress={onLabelSegmentPress}
|
||||
currentCutSeg={currentCutSeg}
|
||||
segmentAtCursor={segmentAtCursor}
|
||||
addCutSegment={addCutSegment}
|
||||
addSegment={addSegment}
|
||||
removeCutSegment={removeCutSegment}
|
||||
onRemoveSelectedPress={removeSelectedSegments}
|
||||
toggleSegmentsList={toggleSegmentsList}
|
||||
splitCurrentSegment={splitCurrentSegment}
|
||||
selectedSegmentsRaw={selectedSegmentsRaw}
|
||||
|
|
|
@ -21,7 +21,7 @@ const buttonBaseStyle = {
|
|||
const neutralButtonColor = 'rgba(255, 255, 255, 0.2)';
|
||||
|
||||
|
||||
const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCount, updateOrder, invertCutSegments, onClick, onRemovePress, onReorderPress, onLabelPress, enabled, onSelectSingleSegment, onToggleSegmentSelected, onDeselectAllSegments, onSelectSegmentsByLabel, onSelectAllSegments, jumpSegStart, jumpSegEnd, addCutSegment, onViewSegmentTagsPress }) => {
|
||||
const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCount, updateOrder, invertCutSegments, onClick, onRemovePress, onRemoveSelectedPress, onReorderPress, onLabelPress, enabled, onSelectSingleSegment, onToggleSegmentSelected, onDeselectAllSegments, onSelectSegmentsByLabel, onSelectAllSegments, jumpSegStart, jumpSegEnd, addSegment, onViewSegmentTagsPress }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const ref = useRef();
|
||||
|
@ -34,9 +34,10 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
|
|||
|
||||
{ type: 'separator' },
|
||||
|
||||
{ label: t('Add segment'), click: addCutSegment },
|
||||
{ label: t('Add segment'), click: addSegment },
|
||||
{ label: t('Label segment'), click: onLabelPress },
|
||||
{ label: t('Remove segment'), click: onRemovePress },
|
||||
{ label: t('Remove selected segments'), click: onRemoveSelectedPress },
|
||||
|
||||
{ type: 'separator' },
|
||||
|
||||
|
@ -55,7 +56,7 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
|
|||
|
||||
{ label: t('Segment tags'), click: () => onViewSegmentTagsPress(index) },
|
||||
];
|
||||
}, [invertCutSegments, t, jumpSegStart, jumpSegEnd, addCutSegment, onLabelPress, onRemovePress, onReorderPress, updateOrder, onSelectSingleSegment, seg, onSelectAllSegments, onDeselectAllSegments, onSelectSegmentsByLabel, onViewSegmentTagsPress, index]);
|
||||
}, [invertCutSegments, t, jumpSegStart, jumpSegEnd, addSegment, onLabelPress, onRemovePress, onRemoveSelectedPress, onReorderPress, updateOrder, onSelectSingleSegment, seg, onSelectAllSegments, onDeselectAllSegments, onSelectSegmentsByLabel, onViewSegmentTagsPress, index]);
|
||||
|
||||
useContextMenu(ref, contextMenuTemplate);
|
||||
|
||||
|
@ -131,7 +132,7 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
|
|||
const SegmentList = memo(({
|
||||
width, formatTimecode, apparentCutSegments, inverseCutSegments, getFrameCount, onSegClick,
|
||||
currentSegIndex,
|
||||
updateSegOrder, updateSegOrders, addCutSegment, removeCutSegment,
|
||||
updateSegOrder, updateSegOrders, addSegment, removeCutSegment, onRemoveSelectedPress,
|
||||
onLabelSegmentPress, currentCutSeg, segmentAtCursor, toggleSegmentsList, splitCurrentSegment,
|
||||
selectedSegments, selectedSegmentsRaw, onSelectSingleSegment, onToggleSegmentSelected, onDeselectAllSegments, onSelectAllSegments, onSelectSegmentsByLabel,
|
||||
jumpSegStart, jumpSegEnd, onViewSegmentTagsPress,
|
||||
|
@ -189,7 +190,7 @@ const SegmentList = memo(({
|
|||
style={{ ...buttonBaseStyle, background: neutralButtonColor }}
|
||||
role="button"
|
||||
title={t('Add segment')}
|
||||
onClick={addCutSegment}
|
||||
onClick={addSegment}
|
||||
/>
|
||||
|
||||
<FaMinus
|
||||
|
@ -268,7 +269,8 @@ const SegmentList = memo(({
|
|||
index={index}
|
||||
enabled={enabled}
|
||||
onClick={onSegClick}
|
||||
addCutSegment={addCutSegment}
|
||||
addSegment={addSegment}
|
||||
onRemoveSelectedPress={onRemoveSelectedPress}
|
||||
onRemovePress={() => removeCutSegment(index)}
|
||||
onReorderPress={() => onReorderSegsPress(index)}
|
||||
onLabelPress={() => onLabelSegmentPress(index)}
|
||||
|
|
Ładowanie…
Reference in New Issue