@ -180,7 +180,7 @@ const App = memo(() => {
const allUserSettings = useUserSettingsRoot ( ) ;
const allUserSettings = useUserSettingsRoot ( ) ;
const {
const {
captureFormat , setCaptureFormat , customOutDir , setCustomOutDir , keyframeCut , setKeyframeCut , preserveMovData , setPreserveMovData , movFastStart , setMovFastStart , avoidNegativeTs , autoMerge , timecodeFormat , invertCutSegments , setInvertCutSegments , autoExportExtraStreams , askBeforeClose , enableAskForImportChapters , enableAskForFileOpenAction , playbackVolume , setPlaybackVolume , autoSaveProjectFile , wheelSensitivity , invertTimelineScroll , language , ffmpegExperimental , hideNotifications , autoLoadTimecode , autoDeleteMergedSegments , exportConfirmEnabled , setExportConfirmEnabled , segmentsToChapters , setSegmentsToChapters , preserveMetadataOnMerge , setPreserveMetadataOnMerge , setSimpleMode , outSegTemplate , setOutSegTemplate , keyboardSeekAccFactor , keyboardNormalSeekSpeed , enableTransferTimestamps , outFormatLocked , setOutFormatLocked , safeOutputFileName , setSafeOutputFileName , enableAutoHtml5ify , segmentsToChaptersOnly , keyBindings , setKeyBindings , resetKeyBindings , enableSmartCut , customFfPath , storeProjectInWorkingDir , enableOverwriteOutput, mouseWheelZoomModifierKey , captureFrameMethod , captureFrameQuality , captureFrameFileNameFormat , enableNativeHevc , cleanupChoices , setCleanupChoices ,
captureFormat , setCaptureFormat , customOutDir , setCustomOutDir , keyframeCut , setKeyframeCut , preserveMovData , setPreserveMovData , movFastStart , setMovFastStart , avoidNegativeTs , autoMerge , timecodeFormat , invertCutSegments , setInvertCutSegments , autoExportExtraStreams , askBeforeClose , enableAskForImportChapters , enableAskForFileOpenAction , playbackVolume , setPlaybackVolume , autoSaveProjectFile , wheelSensitivity , invertTimelineScroll , language , ffmpegExperimental , hideNotifications , autoLoadTimecode , autoDeleteMergedSegments , exportConfirmEnabled , setExportConfirmEnabled , segmentsToChapters , setSegmentsToChapters , preserveMetadataOnMerge , setPreserveMetadataOnMerge , setSimpleMode , outSegTemplate , setOutSegTemplate , keyboardSeekAccFactor , keyboardNormalSeekSpeed , enableTransferTimestamps , outFormatLocked , setOutFormatLocked , safeOutputFileName , setSafeOutputFileName , enableAutoHtml5ify , segmentsToChaptersOnly , keyBindings , setKeyBindings , resetKeyBindings , enableSmartCut , customFfPath , storeProjectInWorkingDir , setStoreProjectInWorkingDir, enableOverwriteOutput, mouseWheelZoomModifierKey , captureFrameMethod , captureFrameQuality , captureFrameFileNameFormat , enableNativeHevc , cleanupChoices , setCleanupChoices ,
} = allUserSettings ;
} = allUserSettings ;
useEffect ( ( ) => {
useEffect ( ( ) => {
@ -374,15 +374,6 @@ const App = memo(() => {
const outputDir = getOutDir ( customOutDir , filePath ) ;
const outputDir = getOutDir ( customOutDir , filePath ) ;
const changeOutDir = useCallback ( async ( ) => {
const newOutDir = await askForOutDir ( outputDir ) ;
if ( newOutDir ) setCustomOutDir ( newOutDir ) ;
} , [ outputDir , setCustomOutDir ] ) ;
const clearOutDir = useCallback ( ( ) => {
setCustomOutDir ( ) ;
} , [ setCustomOutDir ] ) ;
const usingPreviewFile = ! ! previewFilePath ;
const usingPreviewFile = ! ! previewFilePath ;
const effectiveFilePath = previewFilePath || filePath ;
const effectiveFilePath = previewFilePath || filePath ;
const fileUri = effectiveFilePath ? filePathToUrl ( effectiveFilePath ) : '' ;
const fileUri = effectiveFilePath ? filePathToUrl ( effectiveFilePath ) : '' ;
@ -393,7 +384,8 @@ const App = memo(() => {
const getEdlFilePath = useCallback ( ( fp , cod ) => getSuffixedOutPath ( { customOutDir : cod , filePath : fp , nameSuffix : projectSuffix } ) , [ ] ) ;
const getEdlFilePath = useCallback ( ( fp , cod ) => getSuffixedOutPath ( { customOutDir : cod , filePath : fp , nameSuffix : projectSuffix } ) , [ ] ) ;
/ / O l d v e r s i o n s o f L o s s l e s s C u t u s e d C S V f i l e s a n d s t o r e d t h e m a l w a y s i n c u s t o m O u t D i r :
/ / O l d v e r s i o n s o f L o s s l e s s C u t u s e d C S V f i l e s a n d s t o r e d t h e m a l w a y s i n c u s t o m O u t D i r :
const getEdlFilePathOld = useCallback ( ( fp , cod ) => getSuffixedOutPath ( { customOutDir : cod , filePath : fp , nameSuffix : oldProjectSuffix } ) , [ ] ) ;
const getEdlFilePathOld = useCallback ( ( fp , cod ) => getSuffixedOutPath ( { customOutDir : cod , filePath : fp , nameSuffix : oldProjectSuffix } ) , [ ] ) ;
const projectFileSavePath = useMemo ( ( ) => getEdlFilePath ( filePath , storeProjectInWorkingDir ? customOutDir : undefined ) , [ getEdlFilePath , filePath , storeProjectInWorkingDir , customOutDir ] ) ;
const getProjectFileSavePath = useCallback ( ( storeProjectInWorkingDirIn ) => getEdlFilePath ( filePath , storeProjectInWorkingDirIn ? customOutDir : undefined ) , [ getEdlFilePath , filePath , customOutDir ] ) ;
const projectFileSavePath = useMemo ( ( ) => getProjectFileSavePath ( storeProjectInWorkingDir ) , [ getProjectFileSavePath , storeProjectInWorkingDir ] ) ;
const currentSaveOperation = useMemo ( ( ) => {
const currentSaveOperation = useMemo ( ( ) => {
if ( ! projectFileSavePath ) return undefined ;
if ( ! projectFileSavePath ) return undefined ;
@ -455,7 +447,7 @@ const App = memo(() => {
if ( ! supportsRotation && ! hideAllNotifications ) toast . fire ( { text : i18n . t ( 'Lossless rotation might not work with this file format. You may try changing to MP4' ) } ) ;
if ( ! supportsRotation && ! hideAllNotifications ) toast . fire ( { text : i18n . t ( 'Lossless rotation might not work with this file format. You may try changing to MP4' ) } ) ;
} , [ hideAllNotifications , fileFormat ] ) ;
} , [ hideAllNotifications , fileFormat ] ) ;
const { ensureWritableOutDir , ensureAccessToSourceDir } = useDirectoryAccess ( { customOutDir, setCustomOutDir } ) ;
const { ensureWritableOutDir , ensureAccessToSourceDir } = useDirectoryAccess ( { setCustomOutDir } ) ;
const toggleCaptureFormat = useCallback ( ( ) => setCaptureFormat ( f => ( f === 'png' ? 'jpeg' : 'png' ) ) , [ setCaptureFormat ] ) ;
const toggleCaptureFormat = useCallback ( ( ) => setCaptureFormat ( f => ( f === 'png' ? 'jpeg' : 'png' ) ) , [ setCaptureFormat ] ) ;
@ -486,6 +478,35 @@ const App = memo(() => {
return 'separate' ;
return 'separate' ;
} , [ autoDeleteMergedSegments , autoMerge , segmentsToChaptersOnly ] ) ;
} , [ autoDeleteMergedSegments , autoMerge , segmentsToChaptersOnly ] ) ;
const changeOutDir = useCallback ( async ( ) => {
const newOutDir = await askForOutDir ( outputDir ) ;
if ( newOutDir ) setCustomOutDir ( newOutDir ) ;
} , [ outputDir , setCustomOutDir ] ) ;
const clearOutDir = useCallback ( async ( ) => {
try {
await ensureWritableOutDir ( { inputPath : filePath , outDir : undefined } ) ;
setCustomOutDir ( ) ;
} catch ( err ) {
if ( err instanceof DirectoryAccessDeclinedError ) return ;
throw err ;
}
} , [ ensureWritableOutDir , filePath , setCustomOutDir ] ) ;
const toggleStoreProjectInWorkingDir = useCallback ( async ( ) => {
const newValue = ! storeProjectInWorkingDir ;
const path = getProjectFileSavePath ( newValue ) ;
if ( path ) { / / p a t h w i l l b e f a l s y i f n o f i l e l o a d e d
try {
await ensureAccessToSourceDir ( path ) ;
} catch ( err ) {
if ( err instanceof DirectoryAccessDeclinedError ) return ;
console . error ( err ) ;
}
}
setStoreProjectInWorkingDir ( newValue ) ;
} , [ ensureAccessToSourceDir , getProjectFileSavePath , setStoreProjectInWorkingDir , storeProjectInWorkingDir ] ) ;
const userSettingsContext = useMemo ( ( ) => ( {
const userSettingsContext = useMemo ( ( ) => ( {
... allUserSettings , toggleCaptureFormat , changeOutDir , toggleKeyframeCut , togglePreserveMovData , toggleMovFastStart , toggleExportConfirmEnabled , toggleSegmentsToChapters , togglePreserveMetadataOnMerge , toggleSimpleMode , toggleSafeOutputFileName , effectiveExportMode ,
... allUserSettings , toggleCaptureFormat , changeOutDir , toggleKeyframeCut , togglePreserveMovData , toggleMovFastStart , toggleExportConfirmEnabled , toggleSegmentsToChapters , togglePreserveMetadataOnMerge , toggleSimpleMode , toggleSafeOutputFileName , effectiveExportMode ,
} ) , [ allUserSettings , changeOutDir , effectiveExportMode , toggleCaptureFormat , toggleExportConfirmEnabled , toggleKeyframeCut , toggleMovFastStart , togglePreserveMetadataOnMerge , togglePreserveMovData , toggleSafeOutputFileName , toggleSegmentsToChapters , toggleSimpleMode ] ) ;
} ) , [ allUserSettings , changeOutDir , effectiveExportMode , toggleCaptureFormat , toggleExportConfirmEnabled , toggleKeyframeCut , toggleMovFastStart , togglePreserveMetadataOnMerge , togglePreserveMovData , toggleSafeOutputFileName , toggleSegmentsToChapters , toggleSimpleMode ] ) ;
@ -734,7 +755,7 @@ const App = memo(() => {
for ( const path of filePaths ) {
for ( const path of filePaths ) {
try {
try {
/ / e s l i n t - d i s a b l e - n e x t - l i n e n o - a w a i t - i n - l o o p
/ / e s l i n t - d i s a b l e - n e x t - l i n e n o - a w a i t - i n - l o o p
const newCustomOutDir = await ensureWritableOutDir ( path ) ;
const newCustomOutDir = await ensureWritableOutDir ( { inputPath : path , outDir : customOutDir } ) ;
/ / e s l i n t - d i s a b l e - n e x t - l i n e n o - a w a i t - i n - l o o p
/ / e s l i n t - d i s a b l e - n e x t - l i n e n o - a w a i t - i n - l o o p
await html5ify ( { customOutDir : newCustomOutDir , filePath : path , speed , hasAudio : true , hasVideo : true , onProgress : setTotalProgress } ) ;
await html5ify ( { customOutDir : newCustomOutDir , filePath : path , speed , hasAudio : true , hasVideo : true , onProgress : setTotalProgress } ) ;
@ -757,7 +778,7 @@ const App = memo(() => {
setWorking ( ) ;
setWorking ( ) ;
setCutProgress ( ) ;
setCutProgress ( ) ;
}
}
} , [ batchFiles , ensureWritableOutDir, html5ify , setWorking ] ) ;
} , [ batchFiles , customOutDir, ensureWritableOutDir, html5ify , setWorking ] ) ;
const getConvertToSupportedFormat = useCallback ( ( fallback ) => rememberConvertToSupportedFormat || fallback , [ rememberConvertToSupportedFormat ] ) ;
const getConvertToSupportedFormat = useCallback ( ( fallback ) => rememberConvertToSupportedFormat || fallback , [ rememberConvertToSupportedFormat ] ) ;
@ -920,7 +941,7 @@ const App = memo(() => {
const firstPath = paths [ 0 ] ;
const firstPath = paths [ 0 ] ;
if ( ! firstPath ) return ;
if ( ! firstPath ) return ;
const newCustomOutDir = await ensureWritableOutDir ( firstPath ) ;
const newCustomOutDir = await ensureWritableOutDir ( { inputPath : firstPath , outDir : customOutDir } ) ;
const outDir = getOutDir ( newCustomOutDir , firstPath ) ;
const outDir = getOutDir ( newCustomOutDir , firstPath ) ;
@ -974,7 +995,7 @@ const App = memo(() => {
setWorking ( ) ;
setWorking ( ) ;
setCutProgress ( ) ;
setCutProgress ( ) ;
}
}
} , [ setWorking , ensureWritableOutDir , segmentsToChapters, concatFiles , ffmpegExperimental , preserveMovData , movFastStart , preserveMetadataOnMerge , closeBatch , hideAllNotifications , handleConcatFailed ] ) ;
} , [ setWorking , ensureWritableOutDir , customOutDir, segmentsToChapters, concatFiles , ffmpegExperimental , preserveMovData , movFastStart , preserveMetadataOnMerge , closeBatch , hideAllNotifications , handleConcatFailed ] ) ;
const cleanupFiles = useCallback ( async ( cleanupChoices2 ) => {
const cleanupFiles = useCallback ( async ( cleanupChoices2 ) => {
/ / S t o r e p a t h s b e f o r e w e r e s e t s t a t e
/ / S t o r e p a t h s b e f o r e w e r e s e t s t a t e
@ -1370,7 +1391,7 @@ const App = memo(() => {
const hevcPlaybackSupported = enableNativeHevc && await hevcPlaybackSupportedPromise ;
const hevcPlaybackSupported = enableNativeHevc && await hevcPlaybackSupportedPromise ;
/ / n e e d t o e n s u r e w e h a v e a c c e s s t o w r i t e t o w o r k i n g d i r e c t o r y
/ / n e e d t o e n s u r e w e h a v e a c c e s s t o w r i t e t o w o r k i n g d i r e c t o r y
const cod = await ensureWritableOutDir ( fp ) ;
const cod = await ensureWritableOutDir ( { inputPath : fp , outDir : customOutDir } ) ;
/ / i f s t o r e P r o j e c t I n S o u r c e D i r i s t r u e , w e w i l l b e w r i t i n g p r o j e c t f i l e t o i n p u t p a t h ' s d i r , s o e n s u r e t h a t o n e t o o
/ / i f s t o r e P r o j e c t I n S o u r c e D i r i s t r u e , w e w i l l b e w r i t i n g p r o j e c t f i l e t o i n p u t p a t h ' s d i r , s o e n s u r e t h a t o n e t o o
if ( storeProjectInSourceDir ) await ensureAccessToSourceDir ( fp ) ;
if ( storeProjectInSourceDir ) await ensureAccessToSourceDir ( fp ) ;
@ -1436,7 +1457,7 @@ const App = memo(() => {
resetState ( ) ;
resetState ( ) ;
throw err ;
throw err ;
}
}
} , [ s etWorking, loadEdlFile , getEdlFilePath , getEdlFilePathOld , enableAskForImportChapters , loadCutSegments, autoLoadTimecode , enableNativeHevc , ensureWritableOutDir , storeProjectInWorkingDir, ensureAccessToSource Dir, resetState , setCopyStreamIdsForPath , setFileFormat , outFormatLocked , setDetectedFileFormat , html5ifyAndLoadWithPreferences , showPreviewFileLoadedMessage , showUnsupportedFileMessage , hideAllNotifications ] ) ;
} , [ s toreProjectInWorkingDir, s etWorking, loadEdlFile , getEdlFilePath , getEdlFilePathOld , enableAskForImportChapters , ensureAccessToSourceDir, loadCutSegments, autoLoadTimecode , enableNativeHevc , ensureWritableOutDir , customOut Dir, resetState , setCopyStreamIdsForPath , setFileFormat , outFormatLocked , setDetectedFileFormat , html5ifyAndLoadWithPreferences , showPreviewFileLoadedMessage , showUnsupportedFileMessage , hideAllNotifications ] ) ;
const toggleLastCommands = useCallback ( ( ) => setLastCommandsVisible ( val => ! val ) , [ ] ) ;
const toggleLastCommands = useCallback ( ( ) => setLastCommandsVisible ( val => ! val ) , [ ] ) ;
const toggleSettings = useCallback ( ( ) => setSettingsVisible ( val => ! val ) , [ ] ) ;
const toggleSettings = useCallback ( ( ) => setSettingsVisible ( val => ! val ) , [ ] ) ;
@ -2408,6 +2429,7 @@ const App = memo(() => {
onTunerRequested = { onTunerRequested }
onTunerRequested = { onTunerRequested }
onKeyboardShortcutsDialogRequested = { toggleKeyboardShortcuts }
onKeyboardShortcutsDialogRequested = { toggleKeyboardShortcuts }
askForCleanupChoices = { askForCleanupChoices }
askForCleanupChoices = { askForCleanupChoices }
toggleStoreProjectInWorkingDir = { toggleStoreProjectInWorkingDir }
/ >
/ >
< / Table.Body >
< / Table.Body >
< / Table >
< / Table >