1
0
mirror of https://github.com/mifi/lossless-cut.git synced 2024-11-22 02:12:30 +01:00
This commit is contained in:
Mikael Finstad 2024-05-20 11:48:23 +02:00
parent e64e0fb216
commit 799333f898
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26
38 changed files with 189 additions and 164 deletions

View File

@ -7,7 +7,6 @@ module.exports = {
'jsx-a11y/control-has-associated-label': 0,
'unicorn/prefer-node-protocol': 0, // todo
'@typescript-eslint/no-var-requires': 0, // todo
'react/display-name': 0, // todo
},
overrides: [

View File

@ -5,7 +5,8 @@ import { FaTrashAlt, FaSave } from 'react-icons/fa';
import { mySpring } from './animations';
import { saveColor } from './colors';
const BetweenSegments = memo(({ start, end, duration, invertCutSegments }: { start: number, end: number, duration: number, invertCutSegments: boolean }) => {
function BetweenSegments({ start, end, duration, invertCutSegments }: { start: number, end: number, duration: number, invertCutSegments: boolean }) {
const left = `${(start / duration) * 100}%`;
return (
@ -38,6 +39,6 @@ const BetweenSegments = memo(({ start, end, duration, invertCutSegments }: { sta
<div style={{ flexGrow: 1, borderBottom: '1px dashed var(--gray10)', marginLeft: 5, marginRight: 5 }} />
</motion.div>
);
});
}
export default BetweenSegments;
export default memo(BetweenSegments);

View File

@ -31,6 +31,7 @@ const zoomOptions = Array.from({ length: 13 }).fill().map((unused, z) => 2 ** z)
const leftRightWidth = 100;
// eslint-disable-next-line react/display-name
const InvertCutModeButton = memo(({ invertCutSegments, setInvertCutSegments }) => {
const { t } = useTranslation();
@ -63,6 +64,7 @@ const InvertCutModeButton = memo(({ invertCutSegments, setInvertCutSegments }) =
});
// eslint-disable-next-line react/display-name
const CutTimeInput = memo(({ darkMode, cutTime, setCutTime, startTimeOffset, seekAbs, currentCutSeg, currentApparentCutSeg, isStart, formatTimecode, parseTimecode }) => {
const { t } = useTranslation();
const { getSegColor } = useSegColors();
@ -166,7 +168,7 @@ const CutTimeInput = memo(({ darkMode, cutTime, setCutTime, startTimeOffset, see
);
});
const BottomBar = memo(({
function BottomBar({
zoom, setZoom, timelineToggleComfortZoom,
isRotationSet, rotation, areWeCutting, increaseRotation, cleanupFilesDialog,
captureSnapshot, onExportPress, segmentsToExport, hasVideo,
@ -179,7 +181,7 @@ const BottomBar = memo(({
toggleShowThumbnails, toggleWaveformMode, waveformMode, showThumbnails,
outputPlaybackRate, setOutputPlaybackRate,
formatTimecode, parseTimecode,
}) => {
}) {
const { t } = useTranslation();
const { getSegColor } = useSegColors();
@ -458,6 +460,6 @@ const BottomBar = memo(({
</div>
</>
);
});
}
export default BottomBar;
export default memo(BottomBar);

View File

@ -5,9 +5,9 @@ import CopyClipboardButton from './components/CopyClipboardButton';
import Sheet from './components/Sheet';
import { FfmpegCommandLog } from './types';
const LastCommandsSheet = memo(({ visible, onTogglePress, ffmpegCommandLog }: {
function LastCommandsSheet({ visible, onTogglePress, ffmpegCommandLog }: {
visible: boolean, onTogglePress: () => void, ffmpegCommandLog: FfmpegCommandLog,
}) => {
}) {
const { t } = useTranslation();
return (
@ -28,6 +28,6 @@ const LastCommandsSheet = memo(({ visible, onTogglePress, ffmpegCommandLog }: {
)}
</Sheet>
);
});
}
export default LastCommandsSheet;
export default memo(LastCommandsSheet);

View File

@ -8,9 +8,9 @@ import useUserSettings from './hooks/useUserSettings';
const electron = window.require('electron');
const NoFileLoaded = memo(({ mifiLink, currentCutSeg, onClick, darkMode }: {
function NoFileLoaded({ mifiLink, currentCutSeg, onClick, darkMode }: {
mifiLink: unknown, currentCutSeg, onClick: () => void, darkMode?: boolean,
}) => {
}) {
const { t } = useTranslation();
const { simpleMode } = useUserSettings();
@ -48,6 +48,6 @@ const NoFileLoaded = memo(({ mifiLink, currentCutSeg, onClick, darkMode }: {
) : undefined}
</div>
);
});
}
export default NoFileLoaded;
export default memo(NoFileLoaded);

View File

@ -26,6 +26,7 @@ const buttonBaseStyle = {
const neutralButtonColor = 'var(--gray8)';
// eslint-disable-next-line react/display-name
const Segment = memo(({
seg,
index,
@ -218,7 +219,7 @@ const Segment = memo(({
);
});
const SegmentList = memo(({
function SegmentList({
width,
formatTimecode,
apparentCutSegments,
@ -294,7 +295,7 @@ const SegmentList = memo(({
setEditingSegmentTags: Dispatch<SetStateAction<SegmentTags | undefined>>,
setEditingSegmentTagsSegmentIndex: Dispatch<SetStateAction<number | undefined>>,
onEditSegmentTags: (index: number) => void,
}) => {
}) {
const { t } = useTranslation();
const { getSegColor } = useSegColors();
@ -502,6 +503,6 @@ const SegmentList = memo(({
</motion.div>
</>
);
});
}
export default SegmentList;
export default memo(SegmentList);

View File

@ -28,6 +28,7 @@ interface EditingStream {
path: string;
}
// eslint-disable-next-line react/display-name
const EditFileDialog = memo(({ editingFile, allFilesMeta, customTagsByFile, setCustomTagsByFile, editingTag, setEditingTag }: {
editingFile: string, allFilesMeta: FilesMeta, customTagsByFile: CustomTagsByFile, setCustomTagsByFile: Dispatch<SetStateAction<CustomTagsByFile>>, editingTag: string | undefined, setEditingTag: (tag: string | undefined) => void
}) => {
@ -92,6 +93,7 @@ function StreamParametersEditor({ stream, streamParams, updateStreamParams }: {
);
}
// eslint-disable-next-line react/display-name
const EditStreamDialog = memo(({ editingStream: { streamId: editingStreamId, path: editingFile }, setEditingStream, allFilesMeta, paramsByStreamId, updateStreamParams }: {
editingStream: EditingStream, setEditingStream: Dispatch<SetStateAction<EditingStream | undefined>>, allFilesMeta: FilesMeta, paramsByStreamId: ParamsByStreamId, updateStreamParams: UpdateStreamParams,
}) => {
@ -149,6 +151,7 @@ function onInfoClick(json: unknown, title: string) {
showJson5Dialog({ title, json });
}
// eslint-disable-next-line react/display-name
const Stream = memo(({ filePath, stream, onToggle, batchSetCopyStreamIds, copyStream, fileDuration, setEditingStream, onExtractStreamPress, paramsByStreamId, updateStreamParams, formatTimecode, loadSubtitleTrackToSegments }: {
filePath: string, stream: FFprobeStream, onToggle: (a: number) => void, batchSetCopyStreamIds: (filter: (a: FFprobeStream) => boolean, enabled: boolean) => void, copyStream: boolean, fileDuration: number | undefined, setEditingStream: (a: EditingStream) => void, onExtractStreamPress?: () => void, paramsByStreamId: ParamsByStreamId, updateStreamParams: UpdateStreamParams, formatTimecode: FormatTimecode, loadSubtitleTrackToSegments?: (index: number) => void,
}) => {

View File

@ -20,6 +20,7 @@ type CalculateTimelinePercent = (time: number) => string | undefined;
const currentTimeWidth = 1;
// eslint-disable-next-line react/display-name
const Waveform = memo(({ waveform, calculateTimelinePercent, durationSafe }: {
waveform: RenderableWaveform, calculateTimelinePercent: CalculateTimelinePercent, durationSafe: number,
}) => {
@ -43,6 +44,7 @@ const Waveform = memo(({ waveform, calculateTimelinePercent, durationSafe }: {
);
});
// eslint-disable-next-line react/display-name
const Waveforms = memo(({ calculateTimelinePercent, durationSafe, waveforms, zoom, height }: {
calculateTimelinePercent: CalculateTimelinePercent, durationSafe: number, waveforms: RenderableWaveform[], zoom: number, height: number,
}) => (
@ -53,6 +55,7 @@ const Waveforms = memo(({ calculateTimelinePercent, durationSafe, waveforms, zoo
</div>
));
// eslint-disable-next-line react/display-name
const CommandedTime = memo(({ commandedTimePercent }: { commandedTimePercent: string }) => {
const color = 'var(--gray12)';
const commonStyle: CSSProperties = { left: commandedTimePercent, position: 'absolute', pointerEvents: 'none' };
@ -70,7 +73,7 @@ const timelineHeight = 36;
const timeWrapperStyle: CSSProperties = { position: 'absolute', height: timelineHeight, left: 0, right: 0, bottom: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', pointerEvents: 'none' };
const timeStyle: CSSProperties = { background: 'rgba(0,0,0,0.4)', borderRadius: 3, padding: '2px 4px', color: 'rgba(255, 255, 255, 0.8)' };
const Timeline = memo(({
function Timeline({
durationSafe,
startTimeOffset,
playerTime,
@ -126,7 +129,7 @@ const Timeline = memo(({
commandedTimeRef: MutableRefObject<number>,
goToTimecode: () => void,
isSegmentSelected: (a: { segId: string }) => boolean,
}) => {
}) {
const { t } = useTranslation();
const { invertCutSegments } = useUserSettings();
@ -405,6 +408,6 @@ const Timeline = memo(({
</div>
</div>
);
});
}
export default Timeline;
export default memo(Timeline);

View File

@ -8,11 +8,11 @@ import { useSegColors } from './contexts';
import { ApparentCutSegment, FormatTimecode } from './types';
const TimelineSeg = memo(({
function TimelineSeg({
seg, duration, isActive, segNum, onSegClick, invertCutSegments, formatTimecode, selected,
} : {
seg: ApparentCutSegment, duration: number, isActive: boolean, segNum: number, onSegClick: (a: number) => void, invertCutSegments: boolean, formatTimecode: FormatTimecode, selected: boolean,
}) => {
}) {
const { darkMode } = useUserSettings();
const { getSegColor } = useSegColors();
@ -103,6 +103,6 @@ const TimelineSeg = memo(({
<div style={{ flexGrow: 1 }} />
</motion.div>
);
});
}
export default TimelineSeg;
export default memo(TimelineSeg);

View File

@ -16,7 +16,7 @@ import { InverseCutSegment } from './types';
const outFmtStyle = { height: 20, maxWidth: 100 };
const exportModeStyle = { flexGrow: 0, flexBasis: 140 };
const TopMenu = memo(({
function TopMenu({
filePath,
fileFormat,
copyAnyAudioTrack,
@ -42,7 +42,7 @@ const TopMenu = memo(({
selectedSegments: InverseCutSegment[],
isCustomFormatSelected: boolean,
clearOutDir: () => void,
}) => {
}) {
const { t } = useTranslation();
const { customOutDir, changeOutDir, simpleMode, outFormatLocked, setOutFormatLocked } = useUserSettings();
@ -113,6 +113,6 @@ const TopMenu = memo(({
<IoIosSettings size={24} role="button" onClick={toggleSettings} style={{ marginLeft: 5 }} />
</div>
);
});
}
export default TopMenu;
export default memo(TopMenu);

View File

@ -4,7 +4,7 @@ import { Button, ForkIcon, DisableIcon } from 'evergreen-ui';
import useUserSettings from '../hooks/useUserSettings';
const AutoExportToggler = memo(() => {
function AutoExportToggler() {
const { t } = useTranslation();
const { autoExportExtraStreams, setAutoExportExtraStreams } = useUserSettings();
@ -13,6 +13,6 @@ const AutoExportToggler = memo(() => {
{autoExportExtraStreams ? t('Extract') : t('Discard')}
</Button>
);
});
}
export default AutoExportToggler;
export default memo(AutoExportToggler);

View File

@ -5,9 +5,9 @@ import { FaAngleRight, FaFile } from 'react-icons/fa';
import useContextMenu from '../hooks/useContextMenu';
import { primaryTextColor } from '../colors';
const BatchFile = memo(({ path, isOpen, isSelected, name, onSelect, onDelete }: {
function BatchFile({ path, isOpen, isSelected, name, onSelect, onDelete }: {
path: string, isOpen: boolean, isSelected: boolean, name: string, onSelect: (a: string) => void, onDelete: (a: string) => void
}) => {
}) {
const ref = useRef<HTMLDivElement>(null);
const { t } = useTranslation();
@ -26,6 +26,6 @@ const BatchFile = memo(({ path, isOpen, isSelected, name, onSelect, onDelete }:
{isOpen && <FaAngleRight size={14} style={{ color: 'var(--gray9)', marginRight: -5, flexShrink: 0 }} />}
</div>
);
});
}
export default BatchFile;
export default memo(BatchFile);

View File

@ -20,10 +20,10 @@ const iconStyle = {
padding: '3px 5px',
};
const BatchFilesList = memo(({ selectedBatchFiles, filePath, width, batchFiles, setBatchFiles, onBatchFileSelect, batchListRemoveFile, closeBatch, onMergeFilesClick, onBatchConvertToSupportedFormatClick }) => {
function BatchFilesList({ selectedBatchFiles, filePath, width, batchFiles, setBatchFiles, onBatchFileSelect, batchListRemoveFile, closeBatch, onMergeFilesClick, onBatchConvertToSupportedFormatClick }) {
const { t } = useTranslation();
const [sortDesc, setSortDesc] = useState();
const [sortDesc, setSortDesc] = useState<boolean>();
const sortableList = batchFiles.map((batchFile) => ({ id: batchFile.path, batchFile }));
@ -70,6 +70,6 @@ const BatchFilesList = memo(({ selectedBatchFiles, filePath, width, batchFiles,
</div>
</motion.div>
);
});
}
export default BatchFilesList;
export default memo(BatchFilesList);

View File

@ -5,9 +5,9 @@ import { ffmpegExtractWindow } from '../util/constants';
import { RenderableWaveform } from '../types';
const BigWaveform = memo(({ waveforms, relevantTime, playing, durationSafe, zoom, seekRel }: {
function BigWaveform({ waveforms, relevantTime, playing, durationSafe, zoom, seekRel }: {
waveforms: RenderableWaveform[], relevantTime: number, playing: boolean, durationSafe: number, zoom: number, seekRel: (a: number) => void,
}) => {
}) {
const windowSize = ffmpegExtractWindow * 2;
const windowStart = Math.max(0, relevantTime - windowSize);
const windowEnd = relevantTime + windowSize;
@ -129,6 +129,6 @@ const BigWaveform = memo(({ waveforms, relevantTime, playing, durationSafe, zoom
<div style={{ pointerEvents: 'none', position: 'absolute', height: '100%', backgroundColor: 'var(--red11)', width: 1, left: '50%', top: 0 }} />
</div>
);
});
}
export default BigWaveform;
export default memo(BigWaveform);

View File

@ -2,9 +2,11 @@ import { ButtonHTMLAttributes, memo } from 'react';
import styles from './Button.module.css';
const Button = memo(({ type = 'button', ...props }: ButtonHTMLAttributes<HTMLButtonElement>) => (
// eslint-disable-next-line react/jsx-props-no-spreading, react/button-has-type
<button className={styles['button']} type={type} {...props} />
));
function Button({ type = 'button', ...props }: ButtonHTMLAttributes<HTMLButtonElement>) {
return (
// eslint-disable-next-line react/jsx-props-no-spreading, react/button-has-type
<button className={styles['button']} type={type} {...props} />
);
}
export default Button;
export default memo(Button);

View File

@ -6,7 +6,8 @@ import { FaImage } from 'react-icons/fa';
import useUserSettings from '../hooks/useUserSettings';
import { withBlur } from '../util';
const CaptureFormatButton = memo(({ showIcon = false, ...props }: { showIcon?: boolean } & ButtonProps) => {
function CaptureFormatButton({ showIcon = false, ...props }: { showIcon?: boolean } & ButtonProps) {
const { t } = useTranslation();
const { captureFormat, toggleCaptureFormat } = useUserSettings();
return (
@ -20,6 +21,6 @@ const CaptureFormatButton = memo(({ showIcon = false, ...props }: { showIcon?: b
{captureFormat}
</Button>
);
});
}
export default CaptureFormatButton;
export default memo(CaptureFormatButton);

View File

@ -26,9 +26,9 @@ const rowStyle: CSSProperties = {
color: 'black', fontSize: 14, margin: '4px 0px', overflowY: 'auto', whiteSpace: 'nowrap',
};
const ConcatDialog = memo(({ isShown, onHide, paths, onConcat, alwaysConcatMultipleFiles, setAlwaysConcatMultipleFiles }: {
function ConcatDialog({ isShown, onHide, paths, onConcat, alwaysConcatMultipleFiles, setAlwaysConcatMultipleFiles }: {
isShown: boolean, onHide: () => void, paths: string[], onConcat: (a: { paths: string[], includeAllStreams: boolean, streams: FFprobeStream[], outFileName: string, fileFormat: string, clearBatchFilesAfterConcat: boolean }) => Promise<void>, alwaysConcatMultipleFiles: boolean, setAlwaysConcatMultipleFiles: (a: boolean) => void,
}) => {
}) {
const { t } = useTranslation();
const { preserveMovData, setPreserveMovData, segmentsToChapters, setSegmentsToChapters, preserveMetadataOnMerge, setPreserveMetadataOnMerge } = useUserSettings();
@ -238,6 +238,6 @@ const ConcatDialog = memo(({ isShown, onHide, paths, onConcat, alwaysConcatMulti
</Dialog>
</>
);
});
}
export default ConcatDialog;
export default memo(ConcatDialog);

View File

@ -6,7 +6,7 @@ import { MotionStyle, motion, useAnimation } from 'framer-motion';
const electron = window.require('electron');
const { clipboard } = electron;
const CopyClipboardButton = memo(({ text, style }: { text: string, style?: MotionStyle }) => {
function CopyClipboardButton({ text, style }: { text: string, style?: MotionStyle }) {
const { t } = useTranslation();
const animation = useAnimation();
@ -24,6 +24,6 @@ const CopyClipboardButton = memo(({ text, style }: { text: string, style?: Motio
<FaClipboard title={t('Copy to clipboard')} onClick={onClick} />
</motion.span>
);
});
}
export default CopyClipboardButton;
export default memo(CopyClipboardButton);

View File

@ -8,9 +8,9 @@ import useUserSettings from '../hooks/useUserSettings';
import { SegmentToExport } from '../types';
const ExportButton = memo(({ segmentsToExport, areWeCutting, onClick, size = 1 }: {
function ExportButton({ segmentsToExport, areWeCutting, onClick, size = 1 }: {
segmentsToExport: SegmentToExport[], areWeCutting: boolean, onClick: () => void, size?: number | undefined,
}) => {
}) {
const CutIcon = areWeCutting ? FiScissors : FaFileExport;
const { t } = useTranslation();
@ -40,6 +40,6 @@ const ExportButton = memo(({ segmentsToExport, areWeCutting, onClick, size = 1 }
{text}
</div>
);
});
}
export default ExportButton;
export default memo(ExportButton);

View File

@ -39,7 +39,7 @@ const warningStyle: CSSProperties = { color: 'var(--orange8)', fontSize: '80%',
const HelpIcon = ({ onClick, style }: { onClick: () => void, style?: CSSProperties }) => <IoIosHelpCircle size={20} role="button" onClick={withBlur(onClick)} style={{ cursor: 'pointer', color: primaryTextColor, verticalAlign: 'middle', ...style }} />;
const ExportConfirm = memo(({
function ExportConfirm({
areWeCutting,
selectedSegments,
segmentsToExport,
@ -89,7 +89,7 @@ const ExportConfirm = memo(({
setMergedOutFileName: (a: string) => void,
smartCutBitrate: number | undefined,
setSmartCutBitrate: Dispatch<SetStateAction<number | undefined>>,
}) => {
}) {
const { t } = useTranslation();
const { changeOutDir, keyframeCut, toggleKeyframeCut, preserveMovData, movFastStart, avoidNegativeTs, setAvoidNegativeTs, autoDeleteMergedSegments, exportConfirmEnabled, toggleExportConfirmEnabled, segmentsToChapters, toggleSegmentsToChapters, preserveMetadataOnMerge, togglePreserveMetadataOnMerge, enableSmartCut, setEnableSmartCut, effectiveExportMode, enableOverwriteOutput, setEnableOverwriteOutput, ffmpegExperimental, setFfmpegExperimental, cutFromAdjustmentFrames, setCutFromAdjustmentFrames } = useUserSettings();
@ -539,6 +539,6 @@ const ExportConfirm = memo(({
)}
</AnimatePresence>
);
});
}
export default ExportConfirm;
export default memo(ExportConfirm);

View File

@ -7,7 +7,7 @@ import Select from './Select';
import { ExportMode } from '../types';
const ExportModeButton = memo(({ selectedSegments, style }: { selectedSegments: unknown[], style?: CSSProperties }) => {
function ExportModeButton({ selectedSegments, style }: { selectedSegments: unknown[], style?: CSSProperties }) {
const { t } = useTranslation();
const { effectiveExportMode, setAutoMerge, setAutoDeleteMergedSegments, setSegmentsToChaptersOnly } = useUserSettings();
@ -75,6 +75,6 @@ const ExportModeButton = memo(({ selectedSegments, style }: { selectedSegments:
})}
</Select>
);
});
}
export default ExportModeButton;
export default memo(ExportModeButton);

View File

@ -44,6 +44,7 @@ function fixKeys(keys: string[]) {
return orderBy(uniqed, [(key) => key !== 'shift', (key) => key !== 'ctrl', (key) => key !== 'alt', (key) => key !== 'meta', (key) => key]);
}
// eslint-disable-next-line react/display-name
const CreateBinding = memo(({
actionsMap, action, setCreatingBinding, onNewKeyBindingConfirmed,
}: {
@ -117,6 +118,7 @@ const CreateBinding = memo(({
const rowStyle = { display: 'flex', alignItems: 'center', margin: '.2em 0', borderBottom: '1px solid rgba(0,0,0,0.1)', paddingBottom: '.5em' };
// eslint-disable-next-line react/display-name
const KeyboardShortcuts = memo(({
keyBindings, setKeyBindings, resetKeyBindings, currentCutSeg,
}: {
@ -775,11 +777,11 @@ const KeyboardShortcuts = memo(({
);
});
const KeyboardShortcutsDialog = memo(({
function KeyboardShortcutsDialog({
isShown, onHide, keyBindings, setKeyBindings, resetKeyBindings, currentCutSeg,
}: {
isShown: boolean, onHide: () => void, keyBindings: KeyBinding[], setKeyBindings: Dispatch<SetStateAction<KeyBinding[]>>, resetKeyBindings: () => void, currentCutSeg: StateSegment,
}) => {
}) {
const { t } = useTranslation();
return (
@ -795,6 +797,6 @@ const KeyboardShortcutsDialog = memo(({
{isShown ? <KeyboardShortcuts keyBindings={keyBindings} setKeyBindings={setKeyBindings} currentCutSeg={currentCutSeg} resetKeyBindings={resetKeyBindings} /> : <div />}
</Dialog>
);
});
}
export default KeyboardShortcutsDialog;
export default memo(KeyboardShortcutsDialog);

View File

@ -3,10 +3,12 @@ import { memo } from 'react';
import TextInput from './TextInput';
const MergedOutFileName = memo(({ mergedOutFileName, setMergedOutFileName }: { mergedOutFileName: string | undefined, setMergedOutFileName: (a: string) => void }) => (
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
<TextInput value={mergedOutFileName ?? ''} onChange={(e) => setMergedOutFileName(e.target.value)} style={{ textAlign: 'right' }} />
</div>
));
function MergedOutFileName({ mergedOutFileName, setMergedOutFileName }: { mergedOutFileName: string | undefined, setMergedOutFileName: (a: string) => void }) {
return (
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
<TextInput value={mergedOutFileName ?? ''} onChange={(e) => setMergedOutFileName(e.target.value)} style={{ textAlign: 'right' }} />
</div>
);
}
export default MergedOutFileName;
export default memo(MergedOutFileName);

View File

@ -5,12 +5,12 @@ import useUserSettings from '../hooks/useUserSettings';
import Switch from './Switch';
const MovFastStartButton = memo(() => {
function MovFastStartButton() {
const { movFastStart, toggleMovFastStart } = useUserSettings();
return (
<Switch checked={movFastStart} onCheckedChange={withBlur(toggleMovFastStart)} />
);
});
}
export default MovFastStartButton;
export default memo(MovFastStartButton);

View File

@ -23,9 +23,9 @@ const formatVariable = (variable) => `\${${variable}}`;
const extVar = formatVariable('EXT');
const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generateOutSegFileNames, currentSegIndexSafe }: {
function OutSegTemplateEditor({ outSegTemplate, setOutSegTemplate, generateOutSegFileNames, currentSegIndexSafe }: {
outSegTemplate: string, setOutSegTemplate: (text: string) => void, generateOutSegFileNames: GenerateOutSegFileNames, currentSegIndexSafe: number,
}) => {
}) {
const { safeOutputFileName, toggleSafeOutputFileName, outputFileNameMinZeroPadding, setOutputFileNameMinZeroPadding } = useUserSettings();
const [text, setText] = useState(outSegTemplate);
@ -174,6 +174,6 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
</AnimatePresence>
</motion.div>
);
});
}
export default OutSegTemplateEditor;
export default memo(OutSegTemplateEditor);

View File

@ -9,15 +9,15 @@ const commonVideoAudioFormats = ['matroska', 'mov', 'mp4', 'mpegts', 'ogv', 'web
const commonAudioFormats = ['flac', 'ipod', 'mp3', 'oga', 'ogg', 'opus', 'wav'];
const commonSubtitleFormats = ['ass', 'srt', 'sup', 'webvtt'];
function renderFormatOptions(formats) {
function renderFormatOptions(formats: string[]) {
return formats.map((format) => (
<option key={format} value={format}>{format} - {allOutFormats[format]}</option>
));
}
const OutputFormatSelect = memo(({ style, detectedFileFormat, fileFormat, onOutputFormatUserChange }: {
function OutputFormatSelect({ style, detectedFileFormat, fileFormat, onOutputFormatUserChange }: {
style: CSSProperties, detectedFileFormat?: string | undefined, fileFormat?: string | undefined, onOutputFormatUserChange: (a: string) => void,
}) => {
}) {
const commonVideoAudioFormatsExceptDetectedFormat = useMemo(() => commonVideoAudioFormats.filter((f) => f !== detectedFileFormat), [detectedFileFormat]);
const commonAudioFormatsExceptDetectedFormat = useMemo(() => commonAudioFormats.filter((f) => f !== detectedFileFormat), [detectedFileFormat]);
const commonSubtitleFormatsExceptDetectedFormat = useMemo(() => commonSubtitleFormats.filter((f) => f !== detectedFileFormat), [detectedFileFormat]);
@ -49,6 +49,6 @@ const OutputFormatSelect = memo(({ style, detectedFileFormat, fileFormat, onOutp
{renderFormatOptions(otherFormats)}
</Select>
);
});
}
export default OutputFormatSelect;
export default memo(OutputFormatSelect);

View File

@ -3,7 +3,7 @@ import { MdSubtitles } from 'react-icons/md';
import { useTranslation } from 'react-i18next';
import Select from './Select';
const PlaybackStreamSelector = memo(({
function PlaybackStreamSelector({
subtitleStreams,
videoStreams,
audioStreams,
@ -23,7 +23,7 @@ const PlaybackStreamSelector = memo(({
onActiveSubtitleChange: (a?: number | undefined) => void,
onActiveVideoStreamChange: (a?: number | undefined) => void,
onActiveAudioStreamChange: (a?: number | undefined) => void,
}) => {
}) {
const [controlVisible, setControlVisible] = useState(false);
const timeoutRef = useRef<number>();
@ -105,6 +105,6 @@ const PlaybackStreamSelector = memo(({
/>
</>
);
});
}
export default PlaybackStreamSelector;
export default memo(PlaybackStreamSelector);

View File

@ -5,12 +5,12 @@ import useUserSettings from '../hooks/useUserSettings';
import Switch from './Switch';
const PreserveMovDataButton = memo(() => {
function PreserveMovDataButton() {
const { preserveMovData, togglePreserveMovData } = useUserSettings();
return (
<Switch checked={preserveMovData} onCheckedChange={withBlur(togglePreserveMovData)} />
);
});
}
export default PreserveMovDataButton;
export default memo(PreserveMovDataButton);

View File

@ -2,9 +2,12 @@ import { SelectHTMLAttributes, memo } from 'react';
import styles from './Select.module.css';
const Select = memo((props: SelectHTMLAttributes<HTMLSelectElement>) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<select className={styles['select']} {...props} />
));
export default Select;
function Select(props: SelectHTMLAttributes<HTMLSelectElement>) {
return (
// eslint-disable-next-line react/jsx-props-no-spreading
<select className={styles['select']} {...props} />
);
}
export default memo(Select);

View File

@ -41,7 +41,7 @@ const Header = ({ title }: { title: string }) => (
const detailsStyle: CSSProperties = { opacity: 0.75, fontSize: '.9em', marginTop: '.3em' };
const Settings = memo(({
function Settings({
onTunerRequested,
onKeyboardShortcutsDialogRequested,
askForCleanupChoices,
@ -55,7 +55,7 @@ const Settings = memo(({
toggleStoreProjectInWorkingDir: () => Promise<void>,
simpleMode: boolean,
clearOutDir: () => Promise<void>,
}) => {
}) {
const { t } = useTranslation();
const [showAdvanced, setShowAdvanced] = useState(!simpleMode);
@ -481,6 +481,6 @@ const Settings = memo(({
</table>
</>
);
});
}
export default Settings;
export default memo(Settings);

View File

@ -5,9 +5,10 @@ import { useTranslation } from 'react-i18next';
import styles from './Sheet.module.css';
const Sheet = memo(({ visible, onClosePress, children, maxWidth = 800, style }: {
function Sheet({ visible, onClosePress, children, maxWidth = 800, style }: {
visible: boolean, onClosePress: () => void, children: ReactNode, maxWidth?: number, style?: CSSProperties
}) => {
}) {
const { t } = useTranslation();
return (
@ -30,6 +31,6 @@ const Sheet = memo(({ visible, onClosePress, children, maxWidth = 800, style }:
)}
</AnimatePresence>
);
});
}
export default Sheet;
export default memo(Sheet);

View File

@ -6,7 +6,7 @@ import { primaryTextColor } from '../colors';
import useUserSettings from '../hooks/useUserSettings';
const SimpleModeButton = memo(({ size = 20, style }: { size?: number, style: CSSProperties }) => {
function SimpleModeButton({ size = 20, style }: { size?: number, style: CSSProperties }) {
const { t } = useTranslation();
const { simpleMode, toggleSimpleMode } = useUserSettings();
@ -18,6 +18,6 @@ const SimpleModeButton = memo(({ size = 20, style }: { size?: number, style: CSS
onClick={toggleSimpleMode}
/>
);
});
}
export default SimpleModeButton;
export default memo(SimpleModeButton);

View File

@ -1,7 +1,9 @@
import { CSSProperties, forwardRef } from 'react';
const inputStyle: CSSProperties = { borderRadius: '.4em', flexGrow: 1, fontFamily: 'inherit', fontSize: '.8em', backgroundColor: 'var(--gray3)', color: 'var(--gray12)', border: '1px solid var(--gray7)', appearance: 'none' };
// eslint-disable-next-line react/display-name
const TextInput = forwardRef<HTMLInputElement, JSX.IntrinsicElements['input']>(({ style, ...props }, forwardedRef) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<input type="text" ref={forwardedRef} style={{ ...inputStyle, ...style }} {...props} />

View File

@ -7,13 +7,13 @@ import { primaryTextColor } from '../colors';
import useUserSettings from '../hooks/useUserSettings';
const ToggleExportConfirm = memo(({ size = 23, style }: { size?: number | undefined, style?: CSSProperties }) => {
function ToggleExportConfirm({ size = 23, style }: { size?: number | undefined, style?: CSSProperties }) {
const { t } = useTranslation();
const { exportConfirmEnabled, toggleExportConfirmEnabled } = useUserSettings();
return (
<MdEventNote style={{ color: exportConfirmEnabled ? primaryTextColor : 'var(--gray11)', ...style }} size={size} title={t('Show export options screen before exporting?')} role="button" onClick={toggleExportConfirmEnabled} />
);
});
}
export default ToggleExportConfirm;
export default memo(ToggleExportConfirm);

View File

@ -5,9 +5,9 @@ import { useTranslation } from 'react-i18next';
import Switch from './Switch';
const ValueTuner = memo(({ style, title, value, setValue, onFinished, resolution = 1000, min: minIn = 0, max: maxIn = 1, resetToDefault }: {
function ValueTuner({ style, title, value, setValue, onFinished, resolution = 1000, min: minIn = 0, max: maxIn = 1, resetToDefault }: {
style?: CSSProperties, title: string, value: number, setValue: (string) => void, onFinished: () => void, resolution?: number, min?: number, max?: number, resetToDefault: () => void
}) => {
}) {
const { t } = useTranslation();
const [min, setMin] = useState(minIn);
@ -49,6 +49,6 @@ const ValueTuner = memo(({ style, title, value, setValue, onFinished, resolution
</div>
</div>
);
});
}
export default ValueTuner;
export default memo(ValueTuner);

View File

@ -5,7 +5,8 @@ import ValueTuner from './ValueTuner';
import useUserSettings from '../hooks/useUserSettings';
import { TunerType } from '../types';
const ValueTuners = memo(({ type, onFinished }: { type: TunerType, onFinished: () => void }) => {
function ValueTuners({ type, onFinished }: { type: TunerType, onFinished: () => void }) {
const { t } = useTranslation();
const { wheelSensitivity, setWheelSensitivity, keyboardNormalSeekSpeed, keyboardSeekSpeed2, setKeyboardSeekSpeed2, keyboardSeekSpeed3, setKeyboardSeekSpeed3, setKeyboardNormalSeekSpeed, keyboardSeekAccFactor, setKeyboardSeekAccFactor } = useUserSettings();
@ -57,7 +58,7 @@ const ValueTuners = memo(({ type, onFinished }: { type: TunerType, onFinished: (
const resetToDefault = () => setValue(defaultValue);
return <ValueTuner title={title} value={value} setValue={setValue} onFinished={onFinished} max={max} min={min} resetToDefault={resetToDefault} />;
});
}
export default ValueTuners;
export default memo(ValueTuners);

View File

@ -3,7 +3,7 @@ import { FaVolumeMute, FaVolumeUp } from 'react-icons/fa';
import { useTranslation } from 'react-i18next';
const VolumeControl = memo(({ playbackVolume, setPlaybackVolume }: { playbackVolume: number, setPlaybackVolume: (a: number) => void }) => {
function VolumeControl({ playbackVolume, setPlaybackVolume }: { playbackVolume: number, setPlaybackVolume: (a: number) => void }) {
const [volumeControlVisible, setVolumeControlVisible] = useState(false);
const timeoutRef = useRef<number>();
const { t } = useTranslation();
@ -52,6 +52,6 @@ const VolumeControl = memo(({ playbackVolume, setPlaybackVolume }: { playbackVol
/>
</>
);
});
}
export default VolumeControl;
export default memo(VolumeControl);

View File

@ -8,40 +8,42 @@ import { primaryColor } from '../colors';
import loadingLottie from '../7077-magic-flow.json';
const Working = memo(({ text, cutProgress, onAbortClick }: {
function Working({ text, cutProgress, onAbortClick }: {
text: string, cutProgress?: number | undefined, onAbortClick: () => void
}) => (
<div style={{ position: 'absolute', bottom: 0, top: 0, left: 0, right: 0, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<motion.div
style={{ background: primaryColor, boxShadow: `${primaryColor} 0px 0px 20px 25px`, borderRadius: 60, paddingBottom: 5, color: 'white', fontSize: 14, display: 'flex', flexDirection: 'column', alignItems: 'center' }}
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0 }}
>
<div style={{ width: 150, height: 80 }}>
<Lottie
loop
animationData={loadingLottie}
play
style={{ width: '170%', height: '210%', marginLeft: '-40%', marginTop: '-35%', pointerEvents: 'none' }}
/>
</div>
<div style={{ marginTop: 5 }}>
{text}...
</div>
{(cutProgress != null) && (
<div style={{ marginTop: 5 }}>
{`${(cutProgress * 100).toFixed(1)} %`}
}) {
return (
<div style={{ position: 'absolute', bottom: 0, top: 0, left: 0, right: 0, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<motion.div
style={{ background: primaryColor, boxShadow: `${primaryColor} 0px 0px 20px 25px`, borderRadius: 60, paddingBottom: 5, color: 'white', fontSize: 14, display: 'flex', flexDirection: 'column', alignItems: 'center' }}
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0 }}
>
<div style={{ width: 150, height: 80 }}>
<Lottie
loop
animationData={loadingLottie}
play
style={{ width: '170%', height: '210%', marginLeft: '-40%', marginTop: '-35%', pointerEvents: 'none' }}
/>
</div>
)}
<div style={{ marginTop: 5 }}>
<Button intent="danger" onClick={onAbortClick} height={20}><Trans>Abort</Trans></Button>
</div>
</motion.div>
</div>
));
<div style={{ marginTop: 5 }}>
{text}...
</div>
export default Working;
{(cutProgress != null) && (
<div style={{ marginTop: 5 }}>
{`${(cutProgress * 100).toFixed(1)} %`}
</div>
)}
<div style={{ marginTop: 5 }}>
<Button intent="danger" onClick={onAbortClick} height={20}><Trans>Abort</Trans></Button>
</div>
</motion.div>
</div>
);
}
export default memo(Working);