diff --git a/src/App.jsx b/src/App.jsx index 39851fd9..65063b0d 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -65,9 +65,9 @@ import { exportEdlFile, readEdlFile, saveLlcProject, loadLlcProject, askForEdlIm import { formatYouTube, getFrameCountRaw, formatTsv } from './edlFormats'; import { getOutPath, getSuffixedOutPath, handleError, getOutDir, - isMasBuild, isStoreBuild, dragPreventer, + isStoreBuild, dragPreventer, havePermissionToReadFile, resolvePathIfNeeded, getPathReadAccessError, html5ifiedPrefix, html5dummySuffix, findExistingHtml5FriendlyFile, - deleteFiles, isOutOfSpaceError, isExecaFailure, readFileSize, readFileSizes, checkFileSizes, setDocumentTitle, getOutFileExtension, getSuffixedFileName, + deleteFiles, isOutOfSpaceError, isExecaFailure, readFileSize, readFileSizes, checkFileSizes, setDocumentTitle, getOutFileExtension, getSuffixedFileName, mustDisallowVob, readVideoTs, } from './util'; import { toast, errorToast } from './swal'; import { formatDuration } from './util/duration'; @@ -1564,12 +1564,8 @@ const App = memo(() => { } path = mediaFilePath; } - // Because Apple is being nazi about the ability to open "copy protected DVD files" - const disallowVob = isMasBuild; - if (disallowVob && /\.vob$/i.test(path)) { - toast.fire({ icon: 'error', text: 'Unfortunately .vob files are not supported in the App Store version of LosslessCut due to Apple restrictions' }); - return; - } + + if (/\.vob$/i.test(path) && mustDisallowVob()) return; await loadMedia({ filePath: path, projectPath }); }, [ensureAccessToSourceDir, loadMedia]); @@ -1771,7 +1767,8 @@ const App = memo(() => { }); }, []); - const userOpenFiles = useCallback(async (filePaths) => { + const userOpenFiles = useCallback(async (filePathsIn) => { + let filePaths = filePathsIn; if (!filePaths || filePaths.length < 1) return; console.log('userOpenFiles'); @@ -1779,6 +1776,12 @@ const App = memo(() => { [lastOpenedPath] = filePaths; + if (filePaths.length === 1 && basename(filePaths[0]) === 'VIDEO_TS') { + if (mustDisallowVob()) return; + filePaths = await readVideoTs(filePaths[0]); + } + + if (filePaths.length > 1) { if (alwaysConcatMultipleFiles) { batchLoadPaths(filePaths); @@ -1792,8 +1795,6 @@ const App = memo(() => { // filePaths.length is now 1 const firstFilePath = filePaths[0]; - const filePathLowerCase = firstFilePath.toLowerCase(); - if (workingRef.current) return; try { setWorking(i18n.t('Loading file')); @@ -1806,6 +1807,7 @@ const App = memo(() => { return; } + const filePathLowerCase = firstFilePath.toLowerCase(); const isLlcProject = filePathLowerCase.endsWith('.llc'); // Need to ask the user what to do if more than one option diff --git a/src/util.js b/src/util.js index c0b9be46..75a7ee03 100644 --- a/src/util.js +++ b/src/util.js @@ -2,18 +2,19 @@ import i18n from 'i18next'; import pMap from 'p-map'; import ky from 'ky'; import prettyBytes from 'pretty-bytes'; +import sortBy from 'lodash/sortBy'; import isDev from './isDev'; import Swal, { toast } from './swal'; const { dirname, parse: parsePath, join, extname, isAbsolute, resolve, basename } = window.require('path'); const fsExtra = window.require('fs-extra'); -const { stat } = window.require('fs/promises'); +const { stat, readdir } = window.require('fs/promises'); const os = window.require('os'); const { ipcRenderer } = window.require('electron'); const remote = window.require('@electron/remote'); -const { readdir, unlink } = fsExtra; +const { unlink } = fsExtra; const trashFile = async (path) => ipcRenderer.invoke('tryTrashItem', path); @@ -352,3 +353,19 @@ export function setDocumentTitle({ filePath, working, cutProgress }) { } setDocumentExtraTitle(parts.length > 0 ? parts.join(' ') : undefined); } + +export function mustDisallowVob() { + // Because Apple is being nazi about the ability to open "copy protected DVD files" + if (isMasBuild) { + toast.fire({ icon: 'error', text: 'Unfortunately .vob files are not supported in the App Store version of LosslessCut due to Apple restrictions' }); + return true; + } + return false; +} + +export async function readVideoTs(videoTsPath) { + const files = await readdir(videoTsPath); + const relevantFiles = files.filter((file) => /VTS_\d+_\d+\.vob/i.test(file) && !/VTS_\d+_00\.vob/i.test(file)); // skip menu + const ret = sortBy(relevantFiles).map((file) => join(videoTsPath, file)); + if (ret.length === 0) throw new Error('No VTS vob files found in folder'); +}