@ -1707,29 +1707,27 @@ function App() {
} ) ;
} ) ;
} , [ ] ) ;
} , [ ] ) ;
const userOpenFiles = useCallback ( async ( f ilePathsIn?: string [ ] ) = > {
const userOpenFiles = useCallback ( async ( newF ilePathsIn?: string [ ] ) = > {
await withErrorHandling ( async ( ) = > {
await withErrorHandling ( async ( ) = > {
let filePaths = f ilePathsIn;
let newFilePaths = newF ilePathsIn;
if ( ! filePaths || f ilePaths. length === 0 ) return ;
if ( ! newFilePaths || newF ilePaths. length === 0 ) return ;
console . log ( 'userOpenFiles' ) ;
console . log ( 'userOpenFiles' ) ;
console . log ( f ilePaths. join ( '\n' ) ) ;
console . log ( newF ilePaths. join ( '\n' ) ) ;
lastOpenedPathRef . current = f ilePaths[ 0 ] ! ;
lastOpenedPathRef . current = newF ilePaths[ 0 ] ! ;
let first FilePath = f ilePaths[ 0 ] ! ;
let first NewFilePath = newF ilePaths[ 0 ] ! ;
// first check if it is a single directory, and if so, read it recursively
// first check if it is a single directory, and if so, read it recursively
if ( f ilePaths. length === 1 && ( await lstat ( first FilePath) ) . isDirectory ( ) ) {
if ( newF ilePaths. length === 1 && ( await lstat ( first New FilePath) ) . isDirectory ( ) ) {
console . log ( 'Reading directory...' ) ;
console . log ( 'Reading directory...' ) ;
invariant ( first FilePath != null ) ;
invariant ( first New FilePath != null ) ;
f ilePaths = await readDirRecursively ( first FilePath) ;
newF ilePaths = await readDirRecursively ( first New FilePath) ;
}
}
// Only allow opening regular files
// Only allow opening regular files
// eslint-disable-next-line no-restricted-syntax
for ( const path of newFilePaths ) {
for ( const path of filePaths ) {
// eslint-disable-next-line no-await-in-loop
const fileStat = await lstat ( path ) ;
const fileStat = await lstat ( path ) ;
if ( ! fileStat . isFile ( ) ) {
if ( ! fileStat . isFile ( ) ) {
@ -1739,98 +1737,93 @@ function App() {
}
}
}
}
if ( filePaths . length > 1 ) {
if ( newFilePaths . length > 1 && alwaysConcatMultipleFiles ) {
if ( alwaysConcatMultipleFiles ) {
batchLoadPaths ( newFilePaths ) ;
batchLoadPaths ( filePaths ) ;
setConcatSheetOpen ( true ) ;
setConcatSheetOpen ( true ) ;
} else {
batchLoadPaths ( filePaths , true ) ;
}
return ;
return ;
}
}
// filePaths.length is now 1
firstNewFilePath = newFilePaths [ 0 ] ! ;
firstFilePath = filePaths [ 0 ] ! ;
invariant ( firstNewFilePath != null ) ;
invariant ( firstFilePath != null ) ;
// https://en.wikibooks.org/wiki/Inside_DVD-Video/Directory_Structure
// https://en.wikibooks.org/wiki/Inside_DVD-Video/Directory_Structure
if ( /^video_ts$/i . test ( basename ( first FilePath) ) ) {
if ( newFilePaths . length === 1 && /^video_ts$/i . test ( basename ( first New FilePath) ) ) {
if ( mustDisallowVob ( ) ) return ;
if ( mustDisallowVob ( ) ) return ;
f ilePaths = await readVideoTs ( first FilePath) ;
newF ilePaths = await readVideoTs ( first New FilePath) ;
}
}
if ( workingRef . current ) return ;
if ( workingRef . current ) return ;
try {
try {
setWorking ( { text : i18n.t ( 'Loading file' ) } ) ;
setWorking ( { text : i18n.t ( 'Loading file' ) } ) ;
// I mport segments for for already opened file
// I f it's a project file (not llc) and we have an already opened file, import segments from the project
const matchingImportProjectType = getImportProjectType ( first FilePath) ;
const matchingImportProjectType = getImportProjectType ( first New FilePath) ;
if ( matchingImportProjectType ) {
if ( matchingImportProjectType ) {
if ( ! checkFileOpened ( ) ) return ;
if ( ! checkFileOpened ( ) ) return ;
await loadEdlFile ( { path : first FilePath, type : matchingImportProjectType , append : true } ) ;
await loadEdlFile ( { path : first New FilePath, type : matchingImportProjectType , append : true } ) ;
return ;
return ;
}
}
const filePathLowerCase = first FilePath. toLowerCase ( ) ;
const filePathLowerCase = first New FilePath. toLowerCase ( ) ;
const isLlcProject = filePathLowerCase . endsWith ( '.llc' ) ;
const isLlcProject = filePathLowerCase . endsWith ( '.llc' ) ;
// Need to ask the user what to do if more than one option
// Need to ask the user what to do if more than one option
const inputOptions : { open : string , project? : string , tracks? : string , subtitles? : string , addToBatch? : string , mergeWithCurrentFile? : string } = {
const inputOptions : { open? : string , project? : string , tracks? : string , subtitles? : string , addToBatch? : string , mergeWithCurrentFile? : string } = { } ;
open : isFileOpened ? i18n . t ( 'Open the file instead of the current one' ) : i18n . t ( 'Open the file' ) ,
} ;
if ( isFileOpened ) {
if ( newFilePaths . length === 1 ) {
inputOptions . open = isFileOpened ? i18n . t ( 'Open the file instead of the current one' ) : i18n . t ( 'Open the file' ) ;
}
if ( isFileOpened && newFilePaths . length === 1 ) {
if ( isLlcProject ) inputOptions . project = i18n . t ( 'Load segments from the new file, but keep the current media' ) ;
if ( isLlcProject ) inputOptions . project = i18n . t ( 'Load segments from the new file, but keep the current media' ) ;
if ( filePathLowerCase . endsWith ( '.srt' ) ) inputOptions . subtitles = i18n . t ( 'Convert subtitiles into segments' ) ;
else if ( filePathLowerCase . endsWith ( '.srt' ) ) inputOptions . subtitles = i18n . t ( 'Convert subtitiles into segments' ) ;
inputOptions . tracks = i18n . t ( 'Include all tracks from the new file' ) ;
inputOptions . tracks = i18n . t ( 'Include all tracks from the new file' ) ;
}
}
if ( batchFiles. length > 0 ) inputOptions . addToBatch = i18n . t ( 'Add the file to the batch list ') ;
if ( isFileOpened) inputOptions . mergeWithCurrentFile = i18n . t ( 'Merge/concatenate with current file ') ;
else if ( isFileOpened ) inputOptions . mergeWithCurrentFile = i18n . t ( 'Merge/concatenate with current file ') ;
if ( batchFiles . length > 0 || newFilePaths . length > 1 ) inputOptions . addToBatch = i18n . t ( 'Add the file to the batch list ') ;
if ( Object . keys ( inputOptions ) . length > 1 ) {
const inputOptionsKeys = Object . keys ( inputOptions ) ;
const openFileResponse = enableAskForFileOpenAction ? await askForFileOpenAction ( inputOptions ) : 'open' ;
if ( openFileResponse === 'open' ) {
let openFileResponse : string | undefined ;
await userOpenSingleFile ( { path : firstFilePath , isLlcProject } ) ;
if ( inputOptionsKeys . length === 1 ) [ openFileResponse ] = inputOptionsKeys ;
return ;
if ( enableAskForFileOpenAction && inputOptionsKeys . length > 1 ) openFileResponse = await askForFileOpenAction ( inputOptions ) ;
}
else if ( newFilePaths . length === 1 ) openFileResponse = 'open' ;
if ( openFileResponse === 'project' ) {
await loadEdlFile ( { path : firstFilePath , type : 'llc' } ) ;
return ;
}
if ( openFileResponse === 'subtitles' ) {
await loadEdlFile ( { path : firstFilePath , type : 'srt' } ) ;
return ;
}
if ( openFileResponse === 'tracks' ) {
await addStreamSourceFile ( firstFilePath ) ;
setStreamsSelectorShown ( true ) ;
return ;
}
if ( openFileResponse === 'addToBatch' ) {
batchLoadPaths ( [ firstFilePath ] , true ) ;
return ;
}
if ( openFileResponse === 'mergeWithCurrentFile' ) {
const batchPaths = new Set < string > ( ) ;
if ( filePath ) batchPaths . add ( filePath ) ;
filePaths . forEach ( ( path ) = > batchPaths . add ( path ) ) ;
batchLoadPaths ( [ . . . batchPaths ] ) ;
if ( batchPaths . size > 1 ) setConcatSheetOpen ( true ) ;
return ;
}
// Dialog canceled:
if ( openFileResponse === 'open' ) {
await userOpenSingleFile ( { path : firstNewFilePath , isLlcProject } ) ;
return ;
return ;
}
}
if ( openFileResponse === 'project' ) {
await userOpenSingleFile ( { path : firstFilePath , isLlcProject } ) ;
await loadEdlFile ( { path : firstNewFilePath , type : 'llc' } ) ;
return ;
}
if ( openFileResponse === 'subtitles' ) {
await loadEdlFile ( { path : firstNewFilePath , type : 'srt' } ) ;
return ;
}
if ( openFileResponse === 'tracks' ) {
await addStreamSourceFile ( firstNewFilePath ) ;
setStreamsSelectorShown ( true ) ;
return ;
}
if ( openFileResponse === 'addToBatch' ) {
batchLoadPaths ( newFilePaths , true ) ;
return ;
}
if ( openFileResponse === 'mergeWithCurrentFile' ) {
const batchPaths = new Set < string > ( ) ;
if ( filePath ) batchPaths . add ( filePath ) ;
newFilePaths . forEach ( ( path ) = > batchPaths . add ( path ) ) ;
batchLoadPaths ( [ . . . batchPaths ] ) ;
if ( batchPaths . size > 1 ) setConcatSheetOpen ( true ) ;
}
// else: no match means dialog canceled or nothing useful to do:
} finally {
} finally {
setWorking ( undefined ) ;
setWorking ( undefined ) ;
}
}
} , i18n . t ( 'Failed to open file' ) ) ;
} , i18n . t ( 'Failed to open file' ) ) ;
} , [ withErrorHandling , workingRef , alwaysConcatMultipleFiles , batchLoadPaths , setWorking , isFileOpened , batchFiles . length , userOpenSingleFile , checkFileOpened , loadEdlFile , enableAskForFileOpenAction , addStreamSourceFile , filePath ] ) ;
} , [ withErrorHandling , alwaysConcatMultipleFiles, workingRef , batchLoadPaths , setWorking , isFileOpened , batchFiles . length , enableAskForFileOpenAction, checkFileOpened , loadEdlFile , userOpenSingleFile , addStreamSourceFile , filePath ] ) ;
const openFilesDialog = useCallback ( async ( ) = > {
const openFilesDialog = useCallback ( async ( ) = > {
// On Windows and Linux an open dialog can not be both a file selector and a directory selector, so if you set `properties` to `['openFile', 'openDirectory']` on these platforms, a directory selector will be shown. #1995
// On Windows and Linux an open dialog can not be both a file selector and a directory selector, so if you set `properties` to `['openFile', 'openDirectory']` on these platforms, a directory selector will be shown. #1995