Skip to content

Commit

Permalink
improve settings screen
Browse files Browse the repository at this point in the history
  • Loading branch information
mifi committed Feb 21, 2020
1 parent 6bb175b commit 3efd4ef
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 173 deletions.
58 changes: 30 additions & 28 deletions src/HelpSheet.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React 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');
Expand All @@ -23,39 +24,40 @@ const HelpSheet = ({
<IoIosCloseCircleOutline role="button" onClick={onTogglePress} size={30} style={{ position: 'fixed', right: 0, top: 0, padding: 20 }} />

<h1>Keyboard shortcuts</h1>
<ul>
<li><kbd>H</kbd> Show/hide this screen</li>
<li><kbd>SPACE</kbd>, <kbd>k</kbd> Play/pause</li>
<li><kbd>J</kbd> Slow down video</li>
<li><kbd>L</kbd> Speed up video</li>
<li><kbd></kbd> Seek backward 1 sec</li>
<li><kbd></kbd> Seek forward 1 sec</li>
<li><kbd>.</kbd> (period) Tiny seek forward (1/60 sec)</li>
<li><kbd>,</kbd> (comma) Tiny seek backward (1/60 sec)</li>
<li><kbd>I</kbd> Mark in / cut start point</li>
<li><kbd>O</kbd> Mark out / cut end point</li>
<li><kbd>E</kbd> Cut (export selection in the same directory)</li>
<li><kbd>C</kbd> Capture snapshot (in the same directory)</li>
<li><kbd>+</kbd> Add cut segment</li>
<li><kbd>BACKSPACE</kbd> Remove current cut segment</li>
<li><kbd>D</kbd> Delete source file</li>
</ul>
<div><kbd>H</kbd> Show/hide this screen</div>
<div><kbd>SPACE</kbd>, <kbd>k</kbd> Play/pause</div>
<div><kbd>J</kbd> Slow down video</div>
<div><kbd>L</kbd> Speed up video</div>
<div><kbd></kbd> Seek backward 1 sec</div>
<div><kbd></kbd> Seek forward 1 sec</div>
<div><kbd>.</kbd> (period) Tiny seek forward (1/60 sec)</div>
<div><kbd>,</kbd> (comma) Tiny seek backward (1/60 sec)</div>
<div><kbd>I</kbd> Mark in / cut start point</div>
<div><kbd>O</kbd> Mark out / cut end point</div>
<div><kbd>E</kbd> Cut (export selection in the same directory)</div>
<div><kbd>C</kbd> Capture snapshot (in the same directory)</div>
<div><kbd>+</kbd> Add cut segment</div>
<div><kbd>BACKSPACE</kbd> Remove current cut segment</div>
<div><kbd>D</kbd> Delete source file</div>

<p style={{ fontWeight: 'bold' }}>Hover mouse over buttons to see which function they have.</p>
<p style={{ fontWeight: 'bold' }}>Hover mouse over buttons in the main interface to see which function they have.</p>

<table style={{ marginTop: 40 }}>
<thead>
<tr style={{ textAlign: 'left' }}>
<th>Settings</th>
<th>Current setting</th>
</tr>
</thead>
<tbody>
<Table style={{ marginTop: 40 }}>
<Table.Head>
<Table.TextHeaderCell>
Settings
</Table.TextHeaderCell>
<Table.TextHeaderCell>
Current setting
</Table.TextHeaderCell>
</Table.Head>
<Table.Body>
{renderSettings()}
</tbody>
</table>
</Table.Body>
</Table>

<h1 style={{ marginTop: 40 }}>Segment list</h1>

<div style={{ overflowY: 'scroll', height: 200 }}>
{sortedCutSegments.map((seg) => (
<div key={seg.uuid} style={{ margin: '5px 0' }}>
Expand Down
6 changes: 3 additions & 3 deletions src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ input, button, textarea, :focus {
}

.help-sheet {
background: #525252;
color: white;
background: white;
color: black;
padding: 1em 2em;
position: fixed;
left: 0;
Expand All @@ -87,7 +87,7 @@ input, button, textarea, :focus {
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #fcfcfc;
background-color: rgba(0,0,0,0.03);
border: solid 1px #ccc;
border-bottom-color: #bbb;
border-radius: 3px;
Expand Down
276 changes: 134 additions & 142 deletions src/renderer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { FiScissors } from 'react-icons/fi';
import { AnimatePresence, motion } from 'framer-motion';
import Swal from 'sweetalert2';
import Lottie from 'react-lottie';
import { SideSheet, Button, Position } from 'evergreen-ui';
import { SideSheet, Button, Position, Table, SegmentedControl, Checkbox } from 'evergreen-ui';
import { useStateWithHistory } from 'react-use/lib/useStateWithHistory';

import fromPairs from 'lodash/fromPairs';
Expand Down Expand Up @@ -1220,9 +1220,9 @@ const App = memo(() => {
<option key={f} value={f}>{f} - {name}</option>
));
}
function renderOutFmt({ width } = {}) {
function renderOutFmt(style = {}) {
return (
<select style={{ width }} defaultValue="" value={fileFormat} title="Output format" onChange={withBlur(e => setFileFormat(e.target.value))}>
<select style={style} defaultValue="" value={fileFormat} title="Output format" onChange={withBlur(e => setFileFormat(e.target.value))}>
<option key="disabled1" value="" disabled>Format</option>

{detectedFileFormat && (
Expand Down Expand Up @@ -1252,145 +1252,137 @@ const App = memo(() => {
);
}

const renderSettings = () => (
<Fragment>
<tr>
<td>Output format (default autodetected)</td>
<td style={{ width: '50%' }}>{renderOutFmt()}</td>
</tr>

<tr>
<td>
Working directory<br />
This is where working files, exported files, project files (CSV) are stored.
</td>
<td>
<button
type="button"
onClick={setOutputDir}
>
{customOutDir ? 'Custom working directory' : 'Same directory as input file'}
</button>
<div>{customOutDir}</div>
</td>
</tr>

<tr>
<td>Auto merge segments to one file after export?</td>
<td>
<button
type="button"
onClick={toggleAutoMerge}
>
{autoMerge ? 'Auto merge segments to one file' : 'Export separate files'}
</button>
</td>
</tr>

<tr>
<td>keyframe cut mode</td>
<td>
<button
type="button"
onClick={toggleKeyframeCut}
>
{keyframeCut ? 'Nearest keyframe cut - will cut at the nearest keyframe' : 'Normal cut - cut accurate position but could leave an empty portion'}
</button>
</td>
</tr>

<tr>
<td>
Discard (cut away) or keep selected segments from video when exporting
</td>
<td>
<button
type="button"
onClick={withBlur(() => setInvertCutSegments(v => !v))}
>
{invertCutSegments ? 'Discard' : 'Keep'}
</button>
</td>
</tr>

<tr>
<td>
Discard audio?
</td>
<td>
<button
type="button"
onClick={toggleStripAudio}
>
{copyAnyAudioTrack ? 'Keep audio tracks' : 'Discard all audio tracks'}
</button>
</td>
</tr>

<tr>
<td>
Extract unprocessable tracks to separate files?<br />
(data tracks such as GoPro GPS, telemetry etc. are not copied over by default because ffmpeg cannot cut them, thus they will cause the media duration to stay the same after cutting video/audio)
</td>
<td>
<button
type="button"
onClick={() => setAutoExportExtraStreams(v => !v)}
>
{autoExportExtraStreams ? 'Extract unprocessable tracks' : 'Discard all unprocessable tracks'}
</button>
</td>
</tr>

<tr>
<td>
Auto save project?<br />
The project will be stored along with the output files as a CSV file
</td>
<td>
<button
type="button"
onClick={() => setAutoSaveProjectFile(v => !v)}
>
{autoSaveProjectFile ? 'Auto save project' : 'Don\'t save project file'}
</button>
</td>
</tr>

<tr>
<td>
Snapshot capture format
</td>
<td>
{renderCaptureFormatButton()}
</td>
</tr>

<tr>
<td>In timecode show</td>
<td>
<button
type="button"
onClick={() => setTimecodeShowFrames(v => !v)}
>
{timecodeShowFrames ? 'Frame numbers' : 'Millisecond fractions'}
</button>
</td>
</tr>

<tr>
<td>Ask for confirmation when closing app?</td>
<td>
<button
type="button"
onClick={() => setAskBeforeClose(v => !v)}
>
{askBeforeClose ? 'Ask before closing' : 'Don\'t ask before closing'}
</button>
</td>
</tr>
</Fragment>
);
const renderSettings = () => {
// eslint-disable-next-line react/jsx-props-no-spreading
const Row = (props) => <Table.Row height="auto" paddingY={12} {...props} />;
// eslint-disable-next-line react/jsx-props-no-spreading
const KeyCell = (props) => <Table.TextCell textProps={{ whiteSpace: 'auto' }} {...props} />;

return (
<Fragment>
<Row>
<KeyCell textProps={{ whiteSpace: 'auto' }}>Output format (default autodetected)</KeyCell>
<Table.TextCell>{renderOutFmt({ width: '100%' })}</Table.TextCell>
</Row>

<Row>
<KeyCell>
Working directory<br />
This is where working files, exported files, project files (CSV) are stored.
</KeyCell>
<Table.TextCell>
<button
type="button"
onClick={setOutputDir}
>
{customOutDir ? 'Custom working directory' : 'Same directory as input file'}
</button>
<div>{customOutDir}</div>
</Table.TextCell>
</Row>

<Row>
<KeyCell>Auto merge segments to one file during export or export to separate files?</KeyCell>
<Table.TextCell>
<SegmentedControl
options={[{ label: 'Auto merge', value: 'automerge' }, { label: 'Separate', value: 'separate' }]}
value={autoMerge ? 'automerge' : 'separate'}
onChange={value => setAutoMerge(value === 'automerge')}
/>
</Table.TextCell>
</Row>

<Row>
<KeyCell>
Keyframe cut mode<br />
<b>Nearest keyframe</b>: Cut at the nearest keyframe (not accurate time.)<br />
<b>Normal cut</b>: Accurate time but could leave an empty portion at the beginning of the video.<br />
</KeyCell>
<Table.TextCell>
<SegmentedControl
options={[{ label: 'Nearest keyframe', value: 'keyframe' }, { label: 'Normal cut', value: 'normal' }]}
value={keyframeCut ? 'keyframe' : 'normal'}
onChange={value => setKeyframeCut(value === 'keyframe')}
/>
</Table.TextCell>
</Row>

<Row>
<KeyCell>
<span role="img" aria-label="Yin Yang">☯️</span> Choose cutting mode: Cut away or keep selected segments from video when exporting?<br />
When <b>Keep</b> is selected, the video inside segments will be kept, while the video outside will be discarded.<br />
When <b>Cut away</b> is selected, the video inside segments will be discarded, while the video surrounding them will be kept.
</KeyCell>
<Table.TextCell>
<SegmentedControl
options={[{ label: 'Cut away', value: 'discard' }, { label: 'Keep', value: 'keep' }]}
value={invertCutSegments ? 'discard' : 'keep'}
onChange={value => setInvertCutSegments(value === 'discard')}
/>
</Table.TextCell>
</Row>

<Row>
<KeyCell>
Extract unprocessable tracks to separate files or discard them?<br />
(data tracks such as GoPro GPS, telemetry etc. are not copied over by default because ffmpeg cannot cut them, thus they will cause the media duration to stay the same after cutting video/audio)
</KeyCell>
<Table.TextCell>
<SegmentedControl
options={[{ label: 'Extract', value: 'extract' }, { label: 'Discard', value: 'discard' }]}
value={autoExportExtraStreams ? 'extract' : 'discard'}
onChange={value => setAutoExportExtraStreams(value === 'extract')}
/>
</Table.TextCell>
</Row>

<Row>
<KeyCell>
Auto save project file?<br />
The project will be stored along with the output files as a CSV file
</KeyCell>
<Table.TextCell>
<Checkbox
label="Auto save project"
checked={autoSaveProjectFile}
onChange={e => setAutoSaveProjectFile(e.target.checked)}
/>
</Table.TextCell>
</Row>

<Row>
<KeyCell>
Snapshot capture format
</KeyCell>
<Table.TextCell>
{renderCaptureFormatButton()}
</Table.TextCell>
</Row>

<Row>
<KeyCell>In timecode show</KeyCell>
<Table.TextCell>
<SegmentedControl
options={[{ label: 'Frame numbers', value: 'frames' }, { label: 'Millisecond fractions', value: 'ms' }]}
value={timecodeShowFrames ? 'frames' : 'ms'}
onChange={value => setTimecodeShowFrames(value === 'frames')}
/>
</Table.TextCell>
</Row>

<Row>
<KeyCell>Ask for confirmation when closing app?</KeyCell>
<Table.TextCell>
<Checkbox
label="Ask before closing"
checked={askBeforeClose}
onChange={e => setAskBeforeClose(e.target.checked)}
/>
</Table.TextCell>
</Row>
</Fragment>
);
};

useEffect(() => {
loadMifiLink().then(setMifiLink);
Expand Down

0 comments on commit 3efd4ef

Please sign in to comment.