@ -132,7 +132,7 @@ const App = memo(() => {
const [ thumbnails , setThumbnails ] = useState ( [ ] ) ;
const [ shortestFlag , setShortestFlag ] = useState ( false ) ;
const [ zoomWindowStartTime , setZoomWindowStartTime ] = useState ( 0 ) ;
const [ d isabledSegmentIds, setDisabl edSegmentIds] = useState ( { } ) ;
const [ d eselectedSegmentIds, setDeselect edSegmentIds] = useState ( { } ) ;
const [ subtitlesByStreamId , setSubtitlesByStreamId ] = useState ( { } ) ;
const [ activeSubtitleStreamIndex , setActiveSubtitleStreamIndex ] = useState ( ) ;
const [ hideCanvasPreview , setHideCanvasPreview ] = useState ( false ) ;
@ -929,7 +929,7 @@ const App = memo(() => {
setThumbnails ( [ ] ) ;
setShortestFlag ( false ) ;
setZoomWindowStartTime ( 0 ) ;
setD isabl edSegmentIds( { } ) ;
setD eselect edSegmentIds( { } ) ;
setSubtitlesByStreamId ( { } ) ;
setActiveSubtitleStreamIndex ( ) ;
setHideCanvasPreview ( false ) ;
@ -1127,31 +1127,31 @@ const App = memo(() => {
invertCutSegments ? inverseCutSegments : apparentCutSegments
) , [ invertCutSegments , inverseCutSegments , apparentCutSegments ] ) ;
const enab ledSegmentsRaw = useMemo ( ( ) => {
const s elect edSegmentsRaw = useMemo ( ( ) => {
/ / F o r i n v e r t C u t S e g m e n t s w e d o n o t s u p p o r t f i l t e r i n g
if ( invertCutSegments ) return inverseCutSegments ;
return apparentCutSegments . filter ( ( s ) => ! d isabl edSegmentIds[ s . segId ] ) ;
} , [ invertCutSegments , inverseCutSegments , apparentCutSegments , d isabl edSegmentIds] ) ;
return apparentCutSegments . filter ( ( s ) => ! d eselect edSegmentIds[ s . segId ] ) ;
} , [ invertCutSegments , inverseCutSegments , apparentCutSegments , d eselect edSegmentIds] ) ;
/ / I f u s e r h a s s e l e c t e d n o n e t o e x p o r t , i t m a k e s n o s e n s e , s o e x p o r t a l l i n s t e a d
const enab ledSegments = enab ledSegmentsRaw. length > 0 ? enab ledSegmentsRaw : inverseOrNormalSegments ;
const s elect edSegments = s elect edSegmentsRaw. length > 0 ? s elect edSegmentsRaw : inverseOrNormalSegments ;
const enab leOnlySegment = useCallback ( ( seg ) => setD isabl edSegmentIds( Object . fromEntries ( cutSegments . filter ( ( s ) => s . segId !== seg . segId ) . map ( ( s ) => [ s . segId , true ] ) ) ) , [ cutSegments ] ) ;
const toggleSegment Enabled = useCallback ( ( seg ) => setDisabl edSegmentIds( ( existing ) => ( { ... existing , [ seg . segId ] : ! existing [ seg . segId ] } ) ) , [ ] ) ;
const d isableAllSegments = useCallback ( ( ) => setDisabl edSegmentIds( Object . fromEntries ( cutSegments . map ( ( s ) => [ s . segId , true ] ) ) ) , [ cutSegments ] ) ;
const enab leAllSegments = useCallback ( ( ) => setD isabl edSegmentIds( { } ) , [ ] ) ;
const s elect OnlySegment = useCallback ( ( seg ) => setD eselect edSegmentIds( Object . fromEntries ( cutSegments . filter ( ( s ) => s . segId !== seg . segId ) . map ( ( s ) => [ s . segId , true ] ) ) ) , [ cutSegments ] ) ;
const toggleSegment Selected = useCallback ( ( seg ) => setDeselect edSegmentIds( ( existing ) => ( { ... existing , [ seg . segId ] : ! existing [ seg . segId ] } ) ) , [ ] ) ;
const d eselectAllSegments = useCallback ( ( ) => setDeselect edSegmentIds( Object . fromEntries ( cutSegments . map ( ( s ) => [ s . segId , true ] ) ) ) , [ cutSegments ] ) ;
const s elect AllSegments = useCallback ( ( ) => setD eselect edSegmentIds( { } ) , [ ] ) ;
const enab leOnlyCurrentSegment = useCallback ( ( ) => enab leOnlySegment( currentCutSeg ) , [ currentCutSeg , enab leOnlySegment] ) ;
const toggleCurrentSegment Enabled = useCallback ( ( ) => toggleSegmentEnabl ed( currentCutSeg ) , [ currentCutSeg , toggleSegment Enabl ed] ) ;
const s elect OnlyCurrentSegment = useCallback ( ( ) => s elect OnlySegment( currentCutSeg ) , [ currentCutSeg , s elect OnlySegment] ) ;
const toggleCurrentSegment Selected = useCallback ( ( ) => toggleSegmentSelect ed( currentCutSeg ) , [ currentCutSeg , toggleSegment Select ed] ) ;
const filenamifyOrNot = useCallback ( ( name ) => ( safeOutputFileName ? filenamify ( name ) : name ) . substr ( 0 , maxLabelLength ) , [ safeOutputFileName , maxLabelLength ] ) ;
const segmentsToExport = useMemo ( ( ) => {
if ( ! segmentsToChaptersOnly ) return enab ledSegments;
if ( ! segmentsToChaptersOnly ) return s elect edSegments;
/ / s e g m e n t s T o C h a p t e r s O n l y i s a s p e c i a l m o d e w h e r e a l l s e g m e n t s w i l l b e s i m p l y w r i t t e n o u t a s c h a p t e r s t o o n e f i l e : h t t p s : / / g i t h u b . c o m / m i f i / l o s s l e s s - c u t / i s s u e s / 9 9 3 # i s s u e c o m m e n t - 1 0 3 7 9 2 7 5 9 5
/ / C h a p t e r s e x p o r t m o d e : E m u l a t e a s i n g l e s e g m e n t w i t h n o c u t s ( f u l l t i m e l i n e )
return [ { start : 0 , end : getSegApparentEnd ( { } ) } ] ;
} , [ enab ledSegments, getSegApparentEnd , segmentsToChaptersOnly ] ) ;
} , [ s elect edSegments, getSegApparentEnd , segmentsToChaptersOnly ] ) ;
const areWeCutting = useMemo ( ( ) => segmentsToExport . some ( ( { start , end } ) => isCuttingStart ( start ) || isCuttingEnd ( end , duration ) ) , [ duration , segmentsToExport ] ) ;
@ -1223,7 +1223,7 @@ const App = memo(() => {
/ / S p e c i a l s e g m e n t s - t o - c h a p t e r s m o d e :
let chaptersToAdd ;
if ( segmentsToChaptersOnly ) {
const sortedSegments = sortSegments ( enab ledSegments) ;
const sortedSegments = sortSegments ( s elect edSegments) ;
if ( hasAnySegmentOverlap ( sortedSegments ) ) {
errorToast ( i18n . t ( 'Make sure you have no overlapping segments.' ) ) ;
return ;
@ -1322,7 +1322,7 @@ const App = memo(() => {
setWorking ( ) ;
setCutProgress ( ) ;
}
} , [ numStreamsToCopy , setWorking , segmentsToChaptersOnly , enab ledSegments, outSegTemplateOrDefault , generateOutSegFileNames , segmentsToExport , getOutSegError , cutMultiple , outputDir , customOutDir , fileFormat , duration , isRotationSet , effectiveRotation , copyFileStreams , allFilesMeta , keyframeCut , shortestFlag , ffmpegExperimental , preserveMovData , preserveMetadataOnMerge , movFastStart , avoidNegativeTs , customTagsByFile , customTagsByStreamId , dispositionByStreamId , detectedFps , enableSmartCut , willMerge , mainFileFormatData , mainStreams , exportExtraStreams , hideAllNotifications , segmentsToChapters , invertCutSegments , autoConcatCutSegments , isCustomFormatSelected , autoDeleteMergedSegments , filePath , nonCopiedExtraStreams , handleCutFailed ] ) ;
} , [ numStreamsToCopy , setWorking , segmentsToChaptersOnly , s elect edSegments, outSegTemplateOrDefault , generateOutSegFileNames , segmentsToExport , getOutSegError , cutMultiple , outputDir , customOutDir , fileFormat , duration , isRotationSet , effectiveRotation , copyFileStreams , allFilesMeta , keyframeCut , shortestFlag , ffmpegExperimental , preserveMovData , preserveMetadataOnMerge , movFastStart , avoidNegativeTs , customTagsByFile , customTagsByStreamId , dispositionByStreamId , detectedFps , enableSmartCut , willMerge , mainFileFormatData , mainStreams , exportExtraStreams , hideAllNotifications , segmentsToChapters , invertCutSegments , autoConcatCutSegments , isCustomFormatSelected , autoDeleteMergedSegments , filePath , nonCopiedExtraStreams , handleCutFailed ] ) ;
const onExportPress = useCallback ( async ( ) => {
if ( ! filePath || workingRef . current ) return ;
@ -1836,10 +1836,10 @@ const App = memo(() => {
toggleCaptureFormat ,
toggleStripAudio ,
setStartTimeOffset : askSetStartTimeOffset ,
disableAllSegments ,
enableAllSegments ,
enableOnlyCurrentSegment ,
toggleCurrentSegmentEnabled ,
disableAllSegments : deselectAllSegments ,
enableAllSegments : selectAllSegments ,
enableOnlyCurrentSegment : selectOnlyCurrentSegment ,
toggleCurrentSegmentEnabled : toggleCurrentSegmentSelected ,
fixInvalidDuration : tryFixInvalidDuration ,
increaseVolume : ( ) => setPlaybackVolume ( ( val ) => Math . min ( 1 , val + 0.07 ) ) ,
decreaseVolume : ( ) => setPlaybackVolume ( ( val ) => Math . max ( 0 , val - 0.07 ) ) ,
@ -1884,7 +1884,7 @@ const App = memo(() => {
if ( match ) return bubble ;
return true ; / / b u b b l e t h e e v e n t
} , [ addCutSegment , askSetStartTimeOffset , batchFileJump , batchOpenSelectedFile , captureSnapshot , changePlaybackRate , cleanupFilesDialog , clearSegments , closeBatch , closeExportConfirm , concatCurrentBatch , concatDialogVisible , convertFormatBatch , createFixedDurationSegments , createNumSegments , currentSegIndexSafe , cutSegmentsHistory , d isabl eAllSegment s, enab leAllSegments, enableOnlyCurrentSegment , exportConfirmVisible , extractAllStreams , goToTimecode , increaseRotation , invertAllCutSegments , jumpCutEnd , jumpCutStart , jumpSeg , jumpTimelineEnd , jumpTimelineStart , keyboardNormalSeekSpeed , keyboardSeekAccFactor , keyboardShortcutsVisible , onExportConfirm , onExportPress , onLabelSegmentPress , pause , play , removeCutSegment , reorderSegsByStartTime , seekClosestKeyframe , seekRel , seekRelPercent , se tCutEnd, setCutStart , setPlaybackVolume , shortStep , shuffleSegments , splitCurrentSegment , timelineToggleComfortZoom , toggleCaptureFormat , toggleCurrentSegment Enabl ed, toggleHelp , toggleKeyboardShortcuts , toggleKeyframeCut , togglePlay , toggleSegmentsList , toggleStreamsSelector , toggleStripAudio , tryFixInvalidDuration , userHtml5ifyCurrentFile , zoomRel ] ) ;
} , [ addCutSegment , askSetStartTimeOffset , batchFileJump , batchOpenSelectedFile , captureSnapshot , changePlaybackRate , cleanupFilesDialog , clearSegments , closeBatch , closeExportConfirm , concatCurrentBatch , concatDialogVisible , convertFormatBatch , createFixedDurationSegments , createNumSegments , currentSegIndexSafe , cutSegmentsHistory , d eselect AllSegments, exportConfirmVisible , extractAllStreams , goToTimecode , increaseRotation , invertAllCutSegments , jumpCutEnd , jumpCutStart , jumpSeg , jumpTimelineEnd , jumpTimelineStart , keyboardNormalSeekSpeed , keyboardSeekAccFactor , keyboardShortcutsVisible , onExportConfirm , onExportPress , onLabelSegmentPress , pause , play , removeCutSegment , reorderSegsByStartTime , seekClosestKeyframe , seekRel , seekRelPercent , se lectAllSegments, selectOnlyCurrentSegment , se tCutEnd, setCutStart , setPlaybackVolume , shortStep , shuffleSegments , splitCurrentSegment , timelineToggleComfortZoom , toggleCaptureFormat , toggleCurrentSegment Select ed, toggleHelp , toggleKeyboardShortcuts , toggleKeyframeCut , togglePlay , toggleSegmentsList , toggleStreamsSelector , toggleStripAudio , tryFixInvalidDuration , userHtml5ifyCurrentFile , zoomRel ] ) ;
useKeyboard ( { keyBindings , onKeyPress } ) ;
@ -2209,7 +2209,7 @@ const App = memo(() => {
numStreamsToCopy = { numStreamsToCopy }
numStreamsTotal = { numStreamsTotal }
setStreamsSelectorShown = { setStreamsSelectorShown }
enab ledSegments= { enab ledSegments}
s elect edSegments= { s elect edSegments}
/ >
< div style = { { flexGrow : 1 , display : 'flex' , overflowY : 'hidden' } } >
@ -2305,12 +2305,12 @@ const App = memo(() => {
removeCutSegment = { removeCutSegment }
toggleSegmentsList = { toggleSegmentsList }
splitCurrentSegment = { splitCurrentSegment }
enab ledSegmentsRaw= { enab ledSegmentsRaw}
enab ledSegments= { enab ledSegments}
on ExportSingleSegmentClick= { enable OnlySegment}
on ExportSegmentEnabledToggle= { toggleSegmentEnabl ed}
on ExportSegmentDisableAll= { disable AllSegments}
on ExportSegmentEnableAll= { enable AllSegments}
s elect edSegmentsRaw= { s elect edSegmentsRaw}
s elect edSegments= { s elect edSegments}
on SelectSingleSegment= { select OnlySegment}
on ToggleSegmentSelected= { toggleSegmentSelect ed}
on DeselectAllSegments= { deselect AllSegments}
on SelectAllSegments= { select AllSegments}
jumpSegStart = { jumpSegStart }
jumpSegEnd = { jumpSegEnd }
onViewSegmentTagsPress = { onViewSegmentTagsPress }
@ -2360,7 +2360,7 @@ const App = memo(() => {
cleanupFilesDialog = { cleanupFilesDialog }
captureSnapshot = { captureSnapshot }
onExportPress = { onExportPress }
enab ledSegments= { enab ledSegments}
s elect edSegments= { s elect edSegments}
seekAbs = { seekAbs }
currentSegIndexSafe = { currentSegIndexSafe }
cutSegments = { cutSegments }
@ -2426,7 +2426,7 @@ const App = memo(() => {
/ >
< / SideSheet >
< ExportConfirm filePath = { filePath } areWeCutting = { areWeCutting } enab ledSegments= { enab ledSegments} willMerge = { willMerge } visible = { exportConfirmVisible } onClosePress = { closeExportConfirm } onExportConfirm = { onExportConfirm } renderOutFmt = { renderOutFmt } outputDir = { outputDir } numStreamsTotal = { numStreamsTotal } numStreamsToCopy = { numStreamsToCopy } setStreamsSelectorShown = { setStreamsSelectorShown } outFormat = { fileFormat } setOutSegTemplate = { setOutSegTemplate } outSegTemplate = { outSegTemplateOrDefault } generateOutSegFileNames = { generateOutSegFileNames } currentSegIndexSafe = { currentSegIndexSafe } getOutSegError = { getOutSegError } / >
< ExportConfirm filePath = { filePath } areWeCutting = { areWeCutting } s elect edSegments= { s elect edSegments} willMerge = { willMerge } visible = { exportConfirmVisible } onClosePress = { closeExportConfirm } onExportConfirm = { onExportConfirm } renderOutFmt = { renderOutFmt } outputDir = { outputDir } numStreamsTotal = { numStreamsTotal } numStreamsToCopy = { numStreamsToCopy } setStreamsSelectorShown = { setStreamsSelectorShown } outFormat = { fileFormat } setOutSegTemplate = { setOutSegTemplate } outSegTemplate = { outSegTemplateOrDefault } generateOutSegFileNames = { generateOutSegFileNames } currentSegIndexSafe = { currentSegIndexSafe } getOutSegError = { getOutSegError } / >
< HelpSheet
visible = { helpVisible }