diff --git a/package.json b/package.json index 640e0e73..f148d0ee 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "react-sortable-hoc": "^2.0.0", "react-sortablejs": "^6.0.0", "react-syntax-highlighter": "^15.4.3", - "react-use": "^13.26.1", + "react-use": "^17.3.2", "scroll-into-view-if-needed": "^2.2.28", "sharp": "^0.29.3", "smpte-timecode": "^1.2.3", diff --git a/src/App.jsx b/src/App.jsx index 8380978b..ac85f2c5 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -52,7 +52,7 @@ import { isAudioDefinitelyNotSupported, isIphoneHevc, tryMapChaptersToEdl, getDuration, getTimecodeFromStreams, createChaptersFromSegments, extractSubtitleTrack, } from './ffmpeg'; -import { exportEdlFile, readEdlFile, saveLlcProject, loadLlcProject, readEdl } from './edlStore'; +import { exportEdlFile, readEdlFile, saveLlcProject, loadLlcProject, askForEdlImport } from './edlStore'; import { formatYouTube } from './edlFormats'; import { getOutPath, toast, errorToast, handleError, setFileNameTitle, getOutDir, withBlur, @@ -166,7 +166,7 @@ const App = memo(() => { return ret; }, []); - const createInitialCutSegments = useCallback(() => () => [createSegmentAndIncrementCount()], [createSegmentAndIncrementCount]); + const createInitialCutSegments = useCallback(() => [createSegmentAndIncrementCount()], [createSegmentAndIncrementCount]); const [currentSegIndex, setCurrentSegIndex] = useState(0); const [cutStartTimeManual, setCutStartTimeManual] = useState(); @@ -1299,7 +1299,7 @@ const App = memo(() => { setCutSegments(newSegments); }, [createSegmentAndIncrementCount, cutSegments, firstSegmentAtCursorIndex, setCutSegments]); - const loadCutSegments = useCallback((edl) => { + const loadCutSegments = useCallback((edl, append = false) => { const validEdl = edl.filter((row) => ( (row.start === undefined || row.end === undefined || row.start < row.end) && (row.start === undefined || row.start >= 0) @@ -1310,13 +1310,19 @@ const App = memo(() => { if (validEdl.length === 0) throw new Error(i18n.t('No valid segments found')); - clearSegCounter(); - setCutSegments(validEdl.map(createSegmentAndIncrementCount)); + if (!append) { + clearSegCounter(); + } + setCutSegments((existingSegments) => { + const newSegments = validEdl.map(createSegmentAndIncrementCount); + if (append && existingSegments.length > 1) return [...existingSegments, ...newSegments]; + return newSegments; + }); }, [clearSegCounter, createSegmentAndIncrementCount, setCutSegments]); - const loadEdlFile = useCallback(async (path, type) => { - console.log('Loading EDL file', type, path); - loadCutSegments(await readEdlFile({ type, path })); + const loadEdlFile = useCallback(async ({ path, type, append }) => { + console.log('Loading EDL file', type, path, append); + loadCutSegments(await readEdlFile({ type, path }), append); }, [loadCutSegments]); const loadMedia = useCallback(async ({ filePath: fp, customOutDir: cod, projectPath }) => { @@ -1389,11 +1395,11 @@ const App = memo(() => { const openedFileEdlPathOld = getEdlFilePathOld(fp); if (projectPath) { - await loadEdlFile(projectPath, 'llc'); + await loadEdlFile({ path: projectPath, type: 'llc' }); } else if (await exists(openedFileEdlPath)) { - await loadEdlFile(openedFileEdlPath, 'llc'); + await loadEdlFile({ path: openedFileEdlPath, type: 'llc' }); } else if (await exists(openedFileEdlPathOld)) { - await loadEdlFile(openedFileEdlPathOld, 'csv'); + await loadEdlFile({ path: openedFileEdlPathOld, type: 'csv' }); } else { const edl = await tryMapChaptersToEdl(ch); if (edl.length > 0 && enableAskForImportChapters && (await askForImportChapters())) { @@ -1620,7 +1626,6 @@ const App = memo(() => { return; } - // filePaths.length is now 1 const firstFilePath = filePaths[0]; @@ -1630,12 +1635,12 @@ const App = memo(() => { try { setWorking(i18n.t('Loading file')); - // Import CSV project for existing video + // Import segments for for already opened file const edlFormats = { csv: 'csv', pbf: 'pbf', edl: 'mplayer', cue: 'cue', xml: 'xmeml' }; const matchingExt = Object.keys(edlFormats).find((ext) => filePathLowerCase.endsWith(`.${ext}`)); if (matchingExt) { if (!checkFileOpened()) return; - await loadEdlFile(firstFilePath, edlFormats[matchingExt]); + await loadEdlFile({ path: firstFilePath, type: edlFormats[matchingExt], append: true }); return; } @@ -1654,7 +1659,7 @@ const App = memo(() => { return; } if (openFileResponse === 'project') { - await loadEdlFile(firstFilePath, 'llc'); + await loadEdlFile({ path: firstFilePath, type: 'llc' }); return; } if (openFileResponse === 'tracks') { @@ -1906,8 +1911,8 @@ const App = memo(() => { if (!checkFileOpened()) return; try { - const edl = await readEdl(type); - if (edl.length > 0) loadCutSegments(edl); + const edl = await askForEdlImport(type); + if (edl.length > 0) loadCutSegments(edl, true); } catch (err) { handleError(err); } diff --git a/src/edlStore.js b/src/edlStore.js index 7ff30f73..61099672 100644 --- a/src/edlStore.js +++ b/src/edlStore.js @@ -97,7 +97,7 @@ export async function readEdlFile({ type, path }) { throw new Error('Invalid EDL type'); } -export async function readEdl(type) { +export async function askForEdlImport(type) { if (type === 'youtube') return askForYouTubeInput(); let filters; diff --git a/yarn.lock b/yarn.lock index 4bd8af05..ebd19bd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1861,10 +1861,10 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/js-cookie@2.2.5": - version "2.2.5" - resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.5.tgz#38dfaacae8623b37cc0b0d27398e574e3fc28b1e" - integrity sha512-cpmwBRcHJmmZx0OGU7aPVwGWGbs4iKwVYchk9iuMtxNCA2zorwdaTz4GkLgs2WGxiRZRFKnV1k6tRUHX7tBMxg== +"@types/js-cookie@^2.2.6": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3" + integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.9" @@ -2267,7 +2267,7 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" -"@xobotyi/scrollbar-width@1.9.5": +"@xobotyi/scrollbar-width@^1.9.5": version "1.9.5" resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d" integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ== @@ -3683,7 +3683,7 @@ cookie@0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== -copy-to-clipboard@^3.2.0: +copy-to-clipboard@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== @@ -7906,7 +7906,7 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" -nano-css@^5.2.1: +nano-css@^5.3.1: version "5.3.4" resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.4.tgz#40af6a83a76f84204f346e8ccaa9169cdae9167b" integrity sha512-wfcviJB6NOxDIDfr7RFn/GlaN7I/Bhe4d39ZRCJ3xvZX60LVe2qZ+rDqM49nm4YT81gAjzS+ZklhKP/Gnfnubg== @@ -9573,24 +9573,30 @@ react-transition-group@^4.4.1: loose-envify "^1.4.0" prop-types "^15.6.2" -react-use@^13.26.1: - version "13.27.1" - resolved "https://registry.yarnpkg.com/react-use/-/react-use-13.27.1.tgz#e2ae2b708dafc7893c4772628801589aab9de370" - integrity sha512-bAwdqDMXs5lovEanXnL1izledfrPEUUv1afoTVB59eUiYcDyKul+M/dT/2WcgHjoY/R6QlrTcZoW4R7ifwvBfw== +react-universal-interface@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" + integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== + +react-use@^17.3.2: + version "17.3.2" + resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.3.2.tgz#448abf515f47c41c32455024db28167cb6e53be8" + integrity sha512-bj7OD0/1wL03KyWmzFXAFe425zziuTf7q8olwCYBfOeFHY1qfO1FAMjROQLsLZYwG4Rx63xAfb7XAbBrJsZmEw== dependencies: - "@types/js-cookie" "2.2.5" - "@xobotyi/scrollbar-width" "1.9.5" - copy-to-clipboard "^3.2.0" - fast-deep-equal "^3.1.1" + "@types/js-cookie" "^2.2.6" + "@xobotyi/scrollbar-width" "^1.9.5" + copy-to-clipboard "^3.3.1" + fast-deep-equal "^3.1.3" fast-shallow-equal "^1.0.0" js-cookie "^2.2.1" - nano-css "^5.2.1" + nano-css "^5.3.1" + react-universal-interface "^0.6.2" resize-observer-polyfill "^1.5.1" - screenfull "^5.0.0" + screenfull "^5.1.0" set-harmonic-interval "^1.0.1" - throttle-debounce "^2.1.0" + throttle-debounce "^3.0.1" ts-easing "^0.2.0" - tslib "^1.10.0" + tslib "^2.1.0" react@^17.0.2: version "17.0.2" @@ -10064,7 +10070,7 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" -screenfull@^5.0.0: +screenfull@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba" integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== @@ -10987,10 +10993,10 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== -throttle-debounce@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz#fd31865e66502071e411817e241465b3e9c372e2" - integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ== +throttle-debounce@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz#32f94d84dfa894f786c9a1f290e7a645b6a19abb" + integrity sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg== through2-filter@^3.0.0: version "3.0.0"