diff --git a/README.md b/README.md index cfcc58c..76b99bf 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Unsupported files can still be remuxed (fast) or encoded (slow) to a friendly fo ## Typical workflow - Drag drop a video file into player or use /CTRL+O. - Press SPACE to play/pause or , ,. or mouse/trackpad wheel to seek back/forth -- Select the cut segment's start and end time by moving the time marker and then pressing I to set start time, and O to set end time. *Note that the segments you select will be **preserved** and exported to a new file. You can change this behavior with the Yin Yang symbol ☯️, in which case it will instead **cut away** all selected segments and export the parts between.* +- Select the cut segment's start and end time by moving the time marker and then pressing I to set start time, and O to set end time. *Note that the segments you select will be **preserved** and exported to a new file. You can change this behavior with the Yin Yang symbol ☯️, in which case it will instead **remove** all selected segments and export the parts between.* - *(optional)* If you want to add more than one segment, move to the desired start time and press +, then select the next segment start/end times with I/O. - *(optional)* If you want to re-merge all the selected segments to one file after cutting, toggle the button `Separate files` to `Merge cuts`. - *(optional)* If you want to export to a certain dir, press the `Working dir unset` button (default: Input file path) diff --git a/src/HelpSheet.jsx b/src/HelpSheet.jsx index 9dc2145..07d79a6 100644 --- a/src/HelpSheet.jsx +++ b/src/HelpSheet.jsx @@ -2,7 +2,6 @@ import React, { memo } from 'react'; import { IoIosCloseCircleOutline } from 'react-icons/io'; import { FaClipboard } from 'react-icons/fa'; import { motion, AnimatePresence } from 'framer-motion'; -import { Table } from 'evergreen-ui'; // eslint-disable-next-line import/no-extraneous-dependencies const { clipboard } = require('electron'); @@ -10,7 +9,7 @@ const { clipboard } = require('electron'); const { toast } = require('./util'); const HelpSheet = memo(({ - visible, onTogglePress, renderSettings, ffmpegCommandLog, + visible, onTogglePress, ffmpegCommandLog, }) => ( {visible && ( @@ -47,24 +46,11 @@ const HelpSheet = memo(({

Hover mouse over buttons in the main interface to see which function they have.

- - - - Settings - - - Current setting - - - - {renderSettings()} - -
-

Last ffmpeg commands

- {ffmpegCommandLog.reverse().map(({ command, time }) => ( -
+ {ffmpegCommandLog.reverse().map(({ command }, i) => ( + // eslint-disable-next-line react/no-array-index-key +
{ clipboard.writeText(command); toast.fire({ timer: 2000, icon: 'success', title: 'Copied to clipboard' }); }} /> {command}
))} diff --git a/src/LeftMenu.jsx b/src/LeftMenu.jsx index 263b255..b9f4621 100644 --- a/src/LeftMenu.jsx +++ b/src/LeftMenu.jsx @@ -3,35 +3,46 @@ import { Select } from 'evergreen-ui'; import { motion } from 'framer-motion'; import { FaYinYang } from 'react-icons/fa'; -const { withBlur } = require('./util'); +const { withBlur, toast } = require('./util'); -const LeftMenu = memo(({ zoom, setZoom, invertCutSegments, setInvertCutSegments }) => ( -
-
- - setInvertCutSegments(v => !v))} - /> - +const LeftMenu = memo(({ zoom, setZoom, invertCutSegments, setInvertCutSegments }) => { + function onYinYangClick() { + setInvertCutSegments(v => { + const newVal = !v; + if (newVal) toast.fire({ title: 'When you export, selected segments on the timeline will be REMOVED - the surrounding areas will be KEPT' }); + else toast.fire({ title: 'When you export, selected segments on the timeline will be KEPT - the surrounding areas will be REMOVED.' }); + return newVal; + }); + } + + return ( +
+
+ + + +
+ +
{Math.floor(zoom)}x
+
- -
{Math.floor(zoom)}x
- -
-)); + ); +}); export default LeftMenu; diff --git a/src/Settings.jsx b/src/Settings.jsx index 2ca7788..6fea03e 100644 --- a/src/Settings.jsx +++ b/src/Settings.jsx @@ -59,13 +59,13 @@ const Settings = memo(({ - ☯️ Choose cutting mode: Cut away or keep selected segments from video when exporting?
+ ☯️ Choose cutting mode: Remove or keep selected segments from video when exporting?
When Keep is selected, the video inside segments will be kept, while the video outside will be discarded.
- When Cut away is selected, the video inside segments will be discarded, while the video surrounding them will be kept. + When Remove is selected, the video inside segments will be discarded, while the video surrounding them will be kept.
setInvertCutSegments(value === 'discard')} /> diff --git a/src/SettingsSheet.jsx b/src/SettingsSheet.jsx new file mode 100644 index 0000000..e277022 --- /dev/null +++ b/src/SettingsSheet.jsx @@ -0,0 +1,43 @@ +import React, { memo } from 'react'; +import { IoIosCloseCircleOutline } from 'react-icons/io'; +import { FaClipboard } from 'react-icons/fa'; +import { motion, AnimatePresence } from 'framer-motion'; +import { Table } from 'evergreen-ui'; + +// eslint-disable-next-line import/no-extraneous-dependencies +const { clipboard } = require('electron'); + +const { toast } = require('./util'); + +const SettingsSheet = memo(({ + visible, onTogglePress, renderSettings, +}) => ( + + {visible && ( + + + + + + + Settings + + + Current setting + + + + {renderSettings()} + +
+
+ )} +
+)); + +export default SettingsSheet; diff --git a/src/TopMenu.jsx b/src/TopMenu.jsx index a4d7d0b..4550de2 100644 --- a/src/TopMenu.jsx +++ b/src/TopMenu.jsx @@ -1,5 +1,5 @@ import React, { Fragment, memo } from 'react'; -import { IoIosHelpCircle } from 'react-icons/io'; +import { IoIosHelpCircle, IoIosSettings } from 'react-icons/io'; import { Button } from 'evergreen-ui'; import { MdCallSplit, MdCallMerge } from 'react-icons/md'; @@ -9,7 +9,7 @@ import { withBlur } from './util'; const TopMenu = memo(({ filePath, copyAnyAudioTrack, toggleStripAudio, customOutDir, setOutputDir, renderOutFmt, outSegments, autoMerge, toggleAutoMerge, keyframeCut, toggleKeyframeCut, toggleHelp, - numStreamsToCopy, numStreamsTotal, setStreamsSelectorShown, + numStreamsToCopy, numStreamsTotal, setStreamsSelectorShown, toggleSettings, }) => { const AutoMergeIcon = autoMerge ? MdCallMerge : MdCallSplit; @@ -68,6 +68,7 @@ const TopMenu = memo(({ )} + ); }); diff --git a/src/menu.js b/src/menu.js index a788f4f..5432b51 100644 --- a/src/menu.js +++ b/src/menu.js @@ -72,6 +72,13 @@ module.exports = (app, mainWindow, newVersion) => { }, }, { type: 'separator' }, + { + label: 'Settings', + click() { + mainWindow.webContents.send('openSettings'); + }, + }, + { type: 'separator' }, { label: 'Exit', click() { @@ -124,7 +131,7 @@ module.exports = (app, mainWindow, newVersion) => { role: 'help', submenu: [ { - label: 'Help and Settings', + label: 'Help', click() { mainWindow.webContents.send('openHelp'); }, diff --git a/src/renderer.jsx b/src/renderer.jsx index dc32491..0dda496 100644 --- a/src/renderer.jsx +++ b/src/renderer.jsx @@ -16,6 +16,7 @@ import isEqual from 'lodash/isEqual'; import TopMenu from './TopMenu'; import HelpSheet from './HelpSheet'; +import SettingsSheet from './SettingsSheet'; import StreamsSelector from './StreamsSelector'; import SegmentList from './SegmentList'; import Settings from './Settings'; @@ -204,6 +205,7 @@ const App = memo(() => { // Global state const [helpVisible, setHelpVisible] = useState(false); + const [settingsVisible, setSettingsVisible] = useState(false); const [mifiLink, setMifiLink] = useState(); const videoRef = useRef(); @@ -1040,6 +1042,7 @@ const App = memo(() => { ]); const toggleHelp = useCallback(() => setHelpVisible(val => !val), []); + const toggleSettings = useCallback(() => setSettingsVisible(val => !val), []); const jumpSeg = useCallback((val) => setCurrentSegIndex((old) => Math.max(Math.min(old + val, cutSegments.length - 1), 0)), [cutSegments.length]); @@ -1264,6 +1267,10 @@ const App = memo(() => { toggleHelp(); } + function openSettings() { + toggleSettings(); + } + electron.ipcRenderer.on('file-opened', fileOpened); electron.ipcRenderer.on('close-file', closeFile); electron.ipcRenderer.on('html5ify', html5ify); @@ -1275,6 +1282,7 @@ const App = memo(() => { electron.ipcRenderer.on('importEdlFile', importEdlFile); electron.ipcRenderer.on('exportEdlFile', exportEdlFile); electron.ipcRenderer.on('openHelp', openHelp); + electron.ipcRenderer.on('openSettings', openSettings); return () => { electron.ipcRenderer.removeListener('file-opened', fileOpened); @@ -1288,11 +1296,12 @@ const App = memo(() => { electron.ipcRenderer.removeListener('importEdlFile', importEdlFile); electron.ipcRenderer.removeListener('exportEdlFile', exportEdlFile); electron.ipcRenderer.removeListener('openHelp', openHelp); + electron.ipcRenderer.removeListener('openSettings', openSettings); }; }, [ load, mergeFiles, outputDir, filePath, isFileOpened, customOutDir, startTimeOffset, getHtml5ifiedPath, createDummyVideo, resetState, extractAllStreams, userOpenFiles, cutSegmentsHistory, - loadEdlFile, cutSegments, edlFilePath, askBeforeClose, toggleHelp, + loadEdlFile, cutSegments, edlFilePath, askBeforeClose, toggleHelp, toggleSettings, ]); async function showAddStreamSourceDialog() { @@ -1457,6 +1466,7 @@ const App = memo(() => { keyframeCut={keyframeCut} toggleKeyframeCut={toggleKeyframeCut} toggleHelp={toggleHelp} + toggleSettings={toggleSettings} numStreamsToCopy={numStreamsToCopy} numStreamsTotal={numStreamsTotal} setStreamsSelectorShown={setStreamsSelectorShown} @@ -1685,11 +1695,16 @@ const App = memo(() => { + +
); });