From 90126d92b19c800ed2fda1152108ccb286d6df03 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Wed, 9 Mar 2022 22:43:35 +0800 Subject: [PATCH] move merge options into separate dialog also add option to clear batch closes #1063 --- src/App.jsx | 75 ++++++++++++++--------------- src/components/ConcatDialog.jsx | 83 ++++++++++++++++++--------------- 2 files changed, 83 insertions(+), 75 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 750c7ca3..1d5d4897 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -703,43 +703,6 @@ const App = memo(() => { return { cancel: false, newCustomOutDir }; }, [customOutDir, setCustomOutDir]); - const userConcatFiles = useCallback(async ({ paths, includeAllStreams, streams, fileFormat: outFormat, isCustomFormatSelected: isCustomFormatSelected2 }) => { - if (workingRef.current) return; - try { - setConcatDialogVisible(false); - setWorking(i18n.t('Merging')); - - const firstPath = paths[0]; - const { newCustomOutDir, cancel } = await ensureAccessibleDirectories({ inputPath: firstPath }); - if (cancel) return; - - const ext = getOutFileExtension({ isCustomFormatSelected: isCustomFormatSelected2, outFormat, filePath: firstPath }); - const outPath = getOutPath({ customOutDir: newCustomOutDir, filePath: firstPath, nameSuffix: `merged${ext}` }); - const outDir = getOutDir(customOutDir, firstPath); - - let chaptersFromSegments; - if (segmentsToChapters) { - const chapterNames = paths.map((path) => parsePath(path).name); - chaptersFromSegments = await createChaptersFromSegments({ segmentPaths: paths, chapterNames }); - } - - // console.log('merge', paths); - const metadataFromPath = paths[0]; - await concatFiles({ paths, outPath, outDir, outFormat, metadataFromPath, includeAllStreams, streams, ffmpegExperimental, onProgress: setCutProgress, preserveMovData, movFastStart, preserveMetadataOnMerge, chapters: chaptersFromSegments, appendFfmpegCommandLog }); - openDirToast({ icon: 'success', dirPath: outDir, text: i18n.t('Files merged!') }); - } catch (err) { - if (isOutOfSpaceError(err)) { - showDiskFull(); - return; - } - errorToast(i18n.t('Failed to merge files. Make sure they are all of the exact same codecs')); - console.error('Failed to merge files', err); - } finally { - setWorking(); - setCutProgress(); - } - }, [setWorking, ensureAccessibleDirectories, customOutDir, segmentsToChapters, concatFiles, ffmpegExperimental, preserveMovData, movFastStart, preserveMetadataOnMerge]); - const concatCurrentBatch = useCallback(() => { if (batchFiles.length < 2) { errorToast(i18n.t('Please open at least 2 files to merge, then try again')); @@ -1109,6 +1072,44 @@ const App = memo(() => { }); }, []); + const userConcatFiles = useCallback(async ({ paths, includeAllStreams, streams, fileFormat: outFormat, isCustomFormatSelected: isCustomFormatSelected2, clearBatchFilesAfterConcat }) => { + if (workingRef.current) return; + try { + setConcatDialogVisible(false); + setWorking(i18n.t('Merging')); + + const firstPath = paths[0]; + const { newCustomOutDir, cancel } = await ensureAccessibleDirectories({ inputPath: firstPath }); + if (cancel) return; + + const ext = getOutFileExtension({ isCustomFormatSelected: isCustomFormatSelected2, outFormat, filePath: firstPath }); + const outPath = getOutPath({ customOutDir: newCustomOutDir, filePath: firstPath, nameSuffix: `merged${ext}` }); + const outDir = getOutDir(customOutDir, firstPath); + + let chaptersFromSegments; + if (segmentsToChapters) { + const chapterNames = paths.map((path) => parsePath(path).name); + chaptersFromSegments = await createChaptersFromSegments({ segmentPaths: paths, chapterNames }); + } + + // console.log('merge', paths); + const metadataFromPath = paths[0]; + await concatFiles({ paths, outPath, outDir, outFormat, metadataFromPath, includeAllStreams, streams, ffmpegExperimental, onProgress: setCutProgress, preserveMovData, movFastStart, preserveMetadataOnMerge, chapters: chaptersFromSegments, appendFfmpegCommandLog }); + if (clearBatchFilesAfterConcat) closeBatch(); + openDirToast({ icon: 'success', dirPath: outDir, text: i18n.t('Files merged!') }); + } catch (err) { + if (isOutOfSpaceError(err)) { + showDiskFull(); + return; + } + errorToast(i18n.t('Failed to merge files. Make sure they are all of the exact same codecs')); + console.error('Failed to merge files', err); + } finally { + setWorking(); + setCutProgress(); + } + }, [setWorking, ensureAccessibleDirectories, customOutDir, segmentsToChapters, concatFiles, ffmpegExperimental, preserveMovData, movFastStart, preserveMetadataOnMerge, closeBatch]); + const cleanupFilesDialog = useCallback(async () => { if (!isFileOpened) return; diff --git a/src/components/ConcatDialog.jsx b/src/components/ConcatDialog.jsx index 9693cdd1..ad43f97f 100644 --- a/src/components/ConcatDialog.jsx +++ b/src/components/ConcatDialog.jsx @@ -1,6 +1,6 @@ import React, { memo, useState, useCallback, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { Dialog, Checkbox, Button, Paragraph } from 'evergreen-ui'; +import { Dialog, Checkbox, Button, Paragraph, CogIcon } from 'evergreen-ui'; import { AiOutlineMergeCells } from 'react-icons/ai'; import { readFileMeta, getSmarterOutFormat } from '../ffmpeg'; @@ -26,6 +26,8 @@ const ConcatDialog = memo(({ const [paths, setPaths] = useState(initialPaths); const [includeAllStreams, setIncludeAllStreams] = useState(false); const [fileMeta, setFileMeta] = useState(); + const [clearBatchFilesAfterConcat, setClearBatchFilesAfterConcat] = useState(false); + const [settingsVisible, setSettingsVisible] = useState(false); const { fileFormat, setFileFormat, detectedFileFormat, setDetectedFileFormat, isCustomFormatSelected } = useFileFormatState(); @@ -60,53 +62,58 @@ const ConcatDialog = memo(({ const onOutputFormatUserChange = useCallback((newFormat) => setFileFormat(newFormat), [setFileFormat]); - const onConcatClick = useCallback(() => onConcat({ paths, includeAllStreams, streams: fileMeta.streams, fileFormat, isCustomFormatSelected }), [fileFormat, fileMeta, includeAllStreams, isCustomFormatSelected, onConcat, paths]); + const onConcatClick = useCallback(() => onConcat({ paths, includeAllStreams, streams: fileMeta.streams, fileFormat, isCustomFormatSelected, clearBatchFilesAfterConcat }), [clearBatchFilesAfterConcat, fileFormat, fileMeta, includeAllStreams, isCustomFormatSelected, onConcat, paths]); return ( - - {fileFormat && detectedFileFormat && } - - - - )} - > -
-
- {t('This dialog can be used to concatenate files in series, e.g. one after the other:\n[file1][file2][file3]\nIt can NOT be used for merging tracks in parallell (like adding an audio track to a video).\nMake sure all files are of the exact same codecs & codec parameters (fps, resolution etc).')} + <> + + + {fileFormat && detectedFileFormat && } + + + + )} + > +
+
+ {t('This dialog can be used to concatenate files in series, e.g. one after the other:\n[file1][file2][file3]\nIt can NOT be used for merging tracks in parallell (like adding an audio track to a video).\nMake sure all files are of the exact same codecs & codec parameters (fps, resolution etc).')} +
+ +
+ {paths.map((path, index) => ( +
+ {index + 1} + {'. '} + {basename(path)} +
+ ))} +
+
-
- setIncludeAllStreams(e.target.checked)} label={`${t('Include all tracks?')} ${t('If this is checked, all audio/video/subtitle/data tracks will be included. This may not always work for all file types. If not checked, only default streams will be included.')}`} /> + setSettingsVisible(false)} title={t('Options')} hasCancel={false} confirmLabel={t('Close')}> + setIncludeAllStreams(e.target.checked)} label={`${t('Include all tracks?')} ${t('If this is checked, all audio/video/subtitle/data tracks will be included. This may not always work for all file types. If not checked, only default streams will be included.')}`} /> - setPreserveMetadataOnMerge(e.target.checked)} label={t('Preserve original metadata when merging? (slow)')} /> + setPreserveMetadataOnMerge(e.target.checked)} label={t('Preserve original metadata when merging? (slow)')} /> - setPreserveMovData(e.target.checked)} label={t('Preserve all MP4/MOV metadata?')} /> + setPreserveMovData(e.target.checked)} label={t('Preserve all MP4/MOV metadata?')} /> - setSegmentsToChapters(e.target.checked)} label={t('Create chapters from merged segments? (slow)')} /> + setSegmentsToChapters(e.target.checked)} label={t('Create chapters from merged segments? (slow)')} /> - setAlwaysConcatMultipleFiles(e.target.checked)} label={t('Always open this dialog when opening multiple files')} /> + setAlwaysConcatMultipleFiles(e.target.checked)} label={t('Always open this dialog when opening multiple files')} /> - {t('Note that also other settings from the normal export dialog apply to this merge function. For more information about all options, see the export dialog.')} -
+ setClearBatchFilesAfterConcat(e.target.checked)} label={t('Clear batch file list after merge')} /> -
- {paths.map((path, index) => ( -
- {index + 1} - {'. '} - {basename(path)} -
- ))} -
-
-
+ {t('Note that also other settings from the normal export dialog apply to this merge function. For more information about all options, see the export dialog.')} + + ); });