kopia lustrzana https://github.com/mifi/lossless-cut
enable exactOptionalPropertyTypes
rodzic
41c18546c2
commit
cb5a8c2c85
|
@ -111,7 +111,7 @@ function App() {
|
||||||
const [ffmpegCommandLog, setFfmpegCommandLog] = useState<FfmpegCommandLog>([]);
|
const [ffmpegCommandLog, setFfmpegCommandLog] = useState<FfmpegCommandLog>([]);
|
||||||
|
|
||||||
const [previewFilePath, setPreviewFilePath] = useState<string>();
|
const [previewFilePath, setPreviewFilePath] = useState<string>();
|
||||||
const [working, setWorkingState] = useState<{ text: string, abortController?: AbortController }>();
|
const [working, setWorkingState] = useState<{ text: string, abortController?: AbortController | undefined }>();
|
||||||
const [usingDummyVideo, setUsingDummyVideo] = useState(false);
|
const [usingDummyVideo, setUsingDummyVideo] = useState(false);
|
||||||
const [playing, setPlaying] = useState(false);
|
const [playing, setPlaying] = useState(false);
|
||||||
const [compatPlayerEventId, setCompatPlayerEventId] = useState(0);
|
const [compatPlayerEventId, setCompatPlayerEventId] = useState(0);
|
||||||
|
@ -879,6 +879,7 @@ function App() {
|
||||||
setTotalProgress();
|
setTotalProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error todo
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
if (failedFiles.length > 0) toast.fire({ title: `${i18n.t('Failed to convert files:')} ${failedFiles.join(' ')}`, timer: null as any as undefined, showConfirmButton: true });
|
if (failedFiles.length > 0) toast.fire({ title: `${i18n.t('Failed to convert files:')} ${failedFiles.join(' ')}`, timer: null as any as undefined, showConfirmButton: true });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -11,15 +11,15 @@ const { createMediaSourceStream, readOneJpegFrame } = remote.require('./compatPl
|
||||||
async function startPlayback({ path, video, videoStreamIndex, audioStreamIndex, seekTo, signal, playSafe, onCanPlay, getTargetTime, size, fps }: {
|
async function startPlayback({ path, video, videoStreamIndex, audioStreamIndex, seekTo, signal, playSafe, onCanPlay, getTargetTime, size, fps }: {
|
||||||
path: string,
|
path: string,
|
||||||
video: HTMLVideoElement,
|
video: HTMLVideoElement,
|
||||||
videoStreamIndex?: number,
|
videoStreamIndex?: number | undefined,
|
||||||
audioStreamIndex?: number,
|
audioStreamIndex?: number | undefined,
|
||||||
seekTo: number,
|
seekTo: number,
|
||||||
signal: AbortSignal,
|
signal: AbortSignal,
|
||||||
playSafe: () => void,
|
playSafe: () => void,
|
||||||
onCanPlay: () => void,
|
onCanPlay: () => void,
|
||||||
getTargetTime: () => number,
|
getTargetTime: () => number,
|
||||||
size?: number,
|
size?: number | undefined,
|
||||||
fps?: number,
|
fps?: number | undefined,
|
||||||
}) {
|
}) {
|
||||||
let canPlay = false;
|
let canPlay = false;
|
||||||
let bufferEndTime: number | undefined;
|
let bufferEndTime: number | undefined;
|
||||||
|
|
|
@ -11,7 +11,7 @@ const CaptureFormatButton = memo(({ showIcon = false, ...props }: { showIcon?: b
|
||||||
const { captureFormat, toggleCaptureFormat } = useUserSettings();
|
const { captureFormat, toggleCaptureFormat } = useUserSettings();
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
iconBefore={showIcon ? <FaImage /> : undefined}
|
iconBefore={showIcon ? <FaImage /> : null}
|
||||||
title={t('Capture frame format')}
|
title={t('Capture frame format')}
|
||||||
onClick={withBlur(toggleCaptureFormat)}
|
onClick={withBlur(toggleCaptureFormat)}
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { CSSProperties, memo, useCallback } from 'react';
|
import { memo, useCallback } from 'react';
|
||||||
import { FaClipboard } from 'react-icons/fa';
|
import { FaClipboard } from 'react-icons/fa';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { motion, useAnimation } from 'framer-motion';
|
import { MotionStyle, motion, useAnimation } from 'framer-motion';
|
||||||
|
|
||||||
const electron = window.require('electron');
|
const electron = window.require('electron');
|
||||||
const { clipboard } = electron;
|
const { clipboard } = electron;
|
||||||
|
|
||||||
const CopyClipboardButton = memo(({ text, style }: { text: string, style?: CSSProperties }) => {
|
const CopyClipboardButton = memo(({ text, style }: { text: string, style?: MotionStyle }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const animation = useAnimation();
|
const animation = useAnimation();
|
||||||
|
|
|
@ -32,7 +32,7 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
||||||
const [text, setText] = useState(outSegTemplate);
|
const [text, setText] = useState(outSegTemplate);
|
||||||
const [debouncedText] = useDebounce(text, 500);
|
const [debouncedText] = useDebounce(text, 500);
|
||||||
const [validText, setValidText] = useState<string>();
|
const [validText, setValidText] = useState<string>();
|
||||||
const [outSegProblems, setOutSegProblems] = useState<{ error?: string, sameAsInputFileNameWarning?: boolean }>({ error: undefined, sameAsInputFileNameWarning: false });
|
const [outSegProblems, setOutSegProblems] = useState<{ error?: string | undefined, sameAsInputFileNameWarning?: boolean | undefined }>({ error: undefined, sameAsInputFileNameWarning: false });
|
||||||
const [outSegFileNames, setOutSegFileNames] = useState<string[]>();
|
const [outSegFileNames, setOutSegFileNames] = useState<string[]>();
|
||||||
const [shown, setShown] = useState<boolean>();
|
const [shown, setShown] = useState<boolean>();
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
|
@ -16,7 +16,7 @@ function renderFormatOptions(formats) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const OutputFormatSelect = memo(({ style, detectedFileFormat, fileFormat, onOutputFormatUserChange }: {
|
const OutputFormatSelect = memo(({ style, detectedFileFormat, fileFormat, onOutputFormatUserChange }: {
|
||||||
style: CSSProperties, detectedFileFormat?: string, fileFormat?: string, onOutputFormatUserChange: (a: string) => void,
|
style: CSSProperties, detectedFileFormat?: string | undefined, fileFormat?: string | undefined, onOutputFormatUserChange: (a: string) => void,
|
||||||
}) => {
|
}) => {
|
||||||
const commonVideoAudioFormatsExceptDetectedFormat = useMemo(() => commonVideoAudioFormats.filter((f) => f !== detectedFileFormat), [detectedFileFormat]);
|
const commonVideoAudioFormatsExceptDetectedFormat = useMemo(() => commonVideoAudioFormats.filter((f) => f !== detectedFileFormat), [detectedFileFormat]);
|
||||||
const commonAudioFormatsExceptDetectedFormat = useMemo(() => commonAudioFormats.filter((f) => f !== detectedFileFormat), [detectedFileFormat]);
|
const commonAudioFormatsExceptDetectedFormat = useMemo(() => commonAudioFormats.filter((f) => f !== detectedFileFormat), [detectedFileFormat]);
|
||||||
|
|
|
@ -17,12 +17,12 @@ const PlaybackStreamSelector = memo(({
|
||||||
subtitleStreams,
|
subtitleStreams,
|
||||||
videoStreams,
|
videoStreams,
|
||||||
audioStreams,
|
audioStreams,
|
||||||
activeSubtitleStreamIndex?: number,
|
activeSubtitleStreamIndex?: number | undefined,
|
||||||
activeVideoStreamIndex?: number,
|
activeVideoStreamIndex?: number | undefined,
|
||||||
activeAudioStreamIndex?: number,
|
activeAudioStreamIndex?: number | undefined,
|
||||||
onActiveSubtitleChange: (a?: number) => void,
|
onActiveSubtitleChange: (a?: number | undefined) => void,
|
||||||
onActiveVideoStreamChange: (a?: number) => void,
|
onActiveVideoStreamChange: (a?: number | undefined) => void,
|
||||||
onActiveAudioStreamChange: (a?: number) => void,
|
onActiveAudioStreamChange: (a?: number | undefined) => void,
|
||||||
}) => {
|
}) => {
|
||||||
const [controlVisible, setControlVisible] = useState(false);
|
const [controlVisible, setControlVisible] = useState(false);
|
||||||
const timeoutRef = useRef<number>();
|
const timeoutRef = useRef<number>();
|
||||||
|
|
|
@ -5,7 +5,7 @@ import useUserSettings from '../hooks/useUserSettings';
|
||||||
import { SegmentBase } from '../types';
|
import { SegmentBase } from '../types';
|
||||||
|
|
||||||
const SegmentCutpointButton = ({ currentCutSeg, side, Icon, onClick, title, style }: {
|
const SegmentCutpointButton = ({ currentCutSeg, side, Icon, onClick, title, style }: {
|
||||||
currentCutSeg: SegmentBase, side: 'start' | 'end', Icon, onClick?: () => void, title?: string, style?: CSSProperties
|
currentCutSeg: SegmentBase, side: 'start' | 'end', Icon, onClick?: (() => void) | undefined, title?: string | undefined, style?: CSSProperties | undefined
|
||||||
}) => {
|
}) => {
|
||||||
const { darkMode } = useUserSettings();
|
const { darkMode } = useUserSettings();
|
||||||
const { getSegColor } = useSegColors();
|
const { getSegColor } = useSegColors();
|
||||||
|
|
|
@ -9,7 +9,7 @@ import loadingLottie from '../7077-magic-flow.json';
|
||||||
|
|
||||||
|
|
||||||
const Working = memo(({ text, cutProgress, onAbortClick }: {
|
const Working = memo(({ text, cutProgress, onAbortClick }: {
|
||||||
text: string, cutProgress?: number, onAbortClick: () => void
|
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' }}>
|
<div style={{ position: 'absolute', bottom: 0, top: 0, left: 0, right: 0, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||||
<motion.div
|
<motion.div
|
||||||
|
|
|
@ -12,7 +12,7 @@ const ReactSwal = withReactContent(Swal);
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export async function askForHtml5ifySpeed({ allowedOptions, showRemember, initialOption }: {
|
export async function askForHtml5ifySpeed({ allowedOptions, showRemember, initialOption }: {
|
||||||
allowedOptions: Html5ifyMode[], showRemember?: boolean, initialOption?: Html5ifyMode
|
allowedOptions: Html5ifyMode[], showRemember?: boolean | undefined, initialOption?: Html5ifyMode | undefined
|
||||||
}) {
|
}) {
|
||||||
const availOptions: Record<Html5ifyMode, string> = {
|
const availOptions: Record<Html5ifyMode, string> = {
|
||||||
fastest: i18n.t('Fastest: FFmpeg-assisted playback'),
|
fastest: i18n.t('Fastest: FFmpeg-assisted playback'),
|
||||||
|
|
|
@ -19,7 +19,8 @@ const { dialog } = window.require('@electron/remote');
|
||||||
|
|
||||||
const ReactSwal = withReactContent(Swal);
|
const ReactSwal = withReactContent(Swal);
|
||||||
|
|
||||||
export async function promptTimeOffset({ initialValue, title, text }: { initialValue?: string, title: string, text?: string }) {
|
export async function promptTimeOffset({ initialValue, title, text }: { initialValue?: string | undefined, title: string, text?: string | undefined }) {
|
||||||
|
// @ts-expect-error todo
|
||||||
const { value } = await Swal.fire({
|
const { value } = await Swal.fire({
|
||||||
title,
|
title,
|
||||||
text,
|
text,
|
||||||
|
@ -44,6 +45,7 @@ export async function promptTimeOffset({ initialValue, title, text }: { initialV
|
||||||
export const showOpenDialog = async ({
|
export const showOpenDialog = async ({
|
||||||
filters = isWindows ? [{ name: i18n.t('All Files'), extensions: ['*'] }] : undefined,
|
filters = isWindows ? [{ name: i18n.t('All Files'), extensions: ['*'] }] : undefined,
|
||||||
...props
|
...props
|
||||||
|
// @ts-expect-error todo
|
||||||
}) => dialog.showOpenDialog({ ...props, filters });
|
}) => dialog.showOpenDialog({ ...props, filters });
|
||||||
|
|
||||||
export async function askForYouTubeInput() {
|
export async function askForYouTubeInput() {
|
||||||
|
@ -468,6 +470,7 @@ export async function showExportFailedDialog({ fileFormat, safeOutputFileName })
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// @ts-expect-error todo
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const { value } = await ReactSwal.fire({ title: i18n.t('Unable to export this file'), html, timer: null as any as undefined, showConfirmButton: true, showCancelButton: true, cancelButtonText: i18n.t('OK'), confirmButtonText: i18n.t('Report'), reverseButtons: true, focusCancel: true });
|
const { value } = await ReactSwal.fire({ title: i18n.t('Unable to export this file'), html, timer: null as any as undefined, showConfirmButton: true, showCancelButton: true, cancelButtonText: i18n.t('OK'), confirmButtonText: i18n.t('Report'), reverseButtons: true, focusCancel: true });
|
||||||
return value;
|
return value;
|
||||||
|
@ -489,6 +492,7 @@ export async function showConcatFailedDialog({ fileFormat }) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// @ts-expect-error todo
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const { value } = await ReactSwal.fire({ title: i18n.t('Unable to merge files'), html, timer: null as any as undefined, showConfirmButton: true, showCancelButton: true, cancelButtonText: i18n.t('OK'), confirmButtonText: i18n.t('Report'), reverseButtons: true, focusCancel: true });
|
const { value } = await ReactSwal.fire({ title: i18n.t('Unable to merge files'), html, timer: null as any as undefined, showConfirmButton: true, showCancelButton: true, cancelButtonText: i18n.t('OK'), confirmButtonText: i18n.t('Report'), reverseButtons: true, focusCancel: true });
|
||||||
return value;
|
return value;
|
||||||
|
@ -569,6 +573,7 @@ export function showJson5Dialog({ title, json }) {
|
||||||
export async function openDirToast({ filePath, text, html, ...props }: SweetAlertOptions & { filePath: string }) {
|
export async function openDirToast({ filePath, text, html, ...props }: SweetAlertOptions & { filePath: string }) {
|
||||||
const swal = text ? toast : ReactSwal;
|
const swal = text ? toast : ReactSwal;
|
||||||
|
|
||||||
|
// @ts-expect-error todo
|
||||||
const { value } = await swal.fire({
|
const { value } = await swal.fire({
|
||||||
...swalToastOptions,
|
...swalToastOptions,
|
||||||
showConfirmButton: true,
|
showConfirmButton: true,
|
||||||
|
@ -583,6 +588,7 @@ export async function openDirToast({ filePath, text, html, ...props }: SweetAler
|
||||||
}
|
}
|
||||||
|
|
||||||
const UnorderedList = ({ children }) => <ul style={{ paddingLeft: '1em' }}>{children}</ul>;
|
const UnorderedList = ({ children }) => <ul style={{ paddingLeft: '1em' }}>{children}</ul>;
|
||||||
|
// @ts-expect-error todo
|
||||||
const ListItem = ({ icon: Icon, iconColor, children, style }: { icon: IconComponent, iconColor?: string, children: ReactNode, style?: CSSProperties }) => <li style={{ listStyle: 'none', ...style }}>{Icon && <Icon color={iconColor} size={14} marginRight=".3em" />} {children}</li>;
|
const ListItem = ({ icon: Icon, iconColor, children, style }: { icon: IconComponent, iconColor?: string, children: ReactNode, style?: CSSProperties }) => <li style={{ listStyle: 'none', ...style }}>{Icon && <Icon color={iconColor} size={14} marginRight=".3em" />} {children}</li>;
|
||||||
|
|
||||||
const Notices = ({ notices }) => notices.map((msg) => <ListItem key={msg} icon={InfoSignIcon} iconColor="info">{msg}</ListItem>);
|
const Notices = ({ notices }) => notices.map((msg) => <ListItem key={msg} icon={InfoSignIcon} iconColor="info">{msg}</ListItem>);
|
||||||
|
@ -601,6 +607,7 @@ export async function openExportFinishedToast({ filePath, warnings, notices }) {
|
||||||
</UnorderedList>
|
</UnorderedList>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// @ts-expect-error todo
|
||||||
await openDirToast({ filePath, html, width: 800, position: 'center', timer: hasWarnings ? undefined : 30000 });
|
await openDirToast({ filePath, html, width: 800, position: 'center', timer: hasWarnings ? undefined : 30000 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ export interface ParameterDialogParameter { value: string, label?: string, hint?
|
||||||
export type ParameterDialogParameters = Record<string, ParameterDialogParameter>;
|
export type ParameterDialogParameters = Record<string, ParameterDialogParameter>;
|
||||||
|
|
||||||
const ParametersInput = ({ description, parameters: parametersIn, onChange, onSubmit, docUrl }: {
|
const ParametersInput = ({ description, parameters: parametersIn, onChange, onSubmit, docUrl }: {
|
||||||
description?: string, parameters: ParameterDialogParameters, onChange: (a: ParameterDialogParameters) => void, onSubmit: () => void, docUrl?: string,
|
description?: string | undefined, parameters: ParameterDialogParameters, onChange: (a: ParameterDialogParameters) => void, onSubmit: () => void, docUrl?: string | undefined,
|
||||||
}) => {
|
}) => {
|
||||||
const firstInputRef = useRef<HTMLInputElement>(null);
|
const firstInputRef = useRef<HTMLInputElement>(null);
|
||||||
const [parameters, setParameters] = useState(parametersIn);
|
const [parameters, setParameters] = useState(parametersIn);
|
||||||
|
@ -67,6 +67,7 @@ export async function showParametersDialog({ title, description, parameters: par
|
||||||
};
|
};
|
||||||
|
|
||||||
const promise2 = (async () => {
|
const promise2 = (async () => {
|
||||||
|
// @ts-expect-error todo
|
||||||
const { isConfirmed } = await ReactSwal.fire({
|
const { isConfirmed } = await ReactSwal.fire({
|
||||||
title,
|
title,
|
||||||
html: <ParametersInput description={description} parameters={parameters} onChange={(newParameters) => { parameters = newParameters; }} onSubmit={handleSubmit} docUrl={docUrl} />,
|
html: <ParametersInput description={description} parameters={parameters} onChange={(newParameters) => { parameters = newParameters; }} onSubmit={handleSubmit} docUrl={docUrl} />,
|
||||||
|
|
|
@ -93,7 +93,7 @@ export async function loadLlcProject(path: string) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readEdlFile({ type, path, fps }: { type: EdlFileType, path: string, fps?: number }) {
|
export async function readEdlFile({ type, path, fps }: { type: EdlFileType, path: string, fps?: number | undefined }) {
|
||||||
if (type === 'csv') return loadCsvSeconds(path);
|
if (type === 'csv') return loadCsvSeconds(path);
|
||||||
if (type === 'csv-frames') return loadCsvFrames(path, fps);
|
if (type === 'csv-frames') return loadCsvFrames(path, fps);
|
||||||
if (type === 'xmeml') return loadXmeml(path);
|
if (type === 'xmeml') return loadXmeml(path);
|
||||||
|
@ -110,7 +110,7 @@ export async function readEdlFile({ type, path, fps }: { type: EdlFileType, path
|
||||||
throw new Error('Invalid EDL type');
|
throw new Error('Invalid EDL type');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function askForEdlImport({ type, fps }: { type: EdlImportType, fps?: number }) {
|
export async function askForEdlImport({ type, fps }: { type: EdlImportType, fps?: number | undefined }) {
|
||||||
if (type === 'youtube') return askForYouTubeInput();
|
if (type === 'youtube') return askForYouTubeInput();
|
||||||
|
|
||||||
let filters;
|
let filters;
|
||||||
|
@ -132,7 +132,7 @@ export async function askForEdlImport({ type, fps }: { type: EdlImportType, fps?
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function exportEdlFile({ type, cutSegments, customOutDir, filePath, getFrameCount }: {
|
export async function exportEdlFile({ type, cutSegments, customOutDir, filePath, getFrameCount }: {
|
||||||
type: EdlExportType, cutSegments: Segment[], customOutDir?: string, filePath?: string, getFrameCount: (a: number) => number | undefined,
|
type: EdlExportType, cutSegments: Segment[], customOutDir?: string | undefined, filePath?: string | undefined, getFrameCount: (a: number) => number | undefined,
|
||||||
}) {
|
}) {
|
||||||
let filters;
|
let filters;
|
||||||
let ext;
|
let ext;
|
||||||
|
|
|
@ -26,7 +26,7 @@ function getFrameFromVideo(video, format, quality) {
|
||||||
|
|
||||||
export default ({ formatTimecode, treatOutputFileModifiedTimeAsStart }) => {
|
export default ({ formatTimecode, treatOutputFileModifiedTimeAsStart }) => {
|
||||||
const captureFramesRange = useCallback(async ({ customOutDir, filePath, fps, fromTime, toTime, estimatedMaxNumFiles, captureFormat, quality, filter, onProgress, outputTimestamps }: {
|
const captureFramesRange = useCallback(async ({ customOutDir, filePath, fps, fromTime, toTime, estimatedMaxNumFiles, captureFormat, quality, filter, onProgress, outputTimestamps }: {
|
||||||
customOutDir, filePath: string, fps: number, fromTime: number, toTime: number, estimatedMaxNumFiles: number, captureFormat: string, quality: number, filter?: string, onProgress: (a: number) => void, outputTimestamps: boolean
|
customOutDir, filePath: string, fps: number, fromTime: number, toTime: number, estimatedMaxNumFiles: number, captureFormat: string, quality: number, filter?: string | undefined, onProgress: (a: number) => void, outputTimestamps: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const getSuffix = (prefix: string) => `${prefix}.${captureFormat}`;
|
const getSuffix = (prefix: string) => `${prefix}.${captureFormat}`;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ export default function useNativeMenu(
|
||||||
const { x, y, onContext, onClose } = options;
|
const { x, y, onContext, onClose } = options;
|
||||||
|
|
||||||
const openMenu = useCallback((e: MouseEvent) => {
|
const openMenu = useCallback((e: MouseEvent) => {
|
||||||
|
// @ts-expect-error todo
|
||||||
menu.popup({
|
menu.popup({
|
||||||
window: remote.getCurrentWindow(),
|
window: remote.getCurrentWindow(),
|
||||||
x,
|
x,
|
||||||
|
|
|
@ -21,7 +21,7 @@ const { blackDetect, silenceDetect } = remote.require('./ffmpeg');
|
||||||
|
|
||||||
|
|
||||||
export default ({ filePath, workingRef, setWorking, setCutProgress, videoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly }: {
|
export default ({ filePath, workingRef, setWorking, setCutProgress, videoStream, duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments, segmentsToChaptersOnly }: {
|
||||||
filePath?: string, workingRef: MutableRefObject<boolean>, setWorking: (w: { text: string, abortController?: AbortController } | undefined) => void, setCutProgress: (a: number | undefined) => void, videoStream, duration?: number, getRelevantTime: () => number, maxLabelLength: number, checkFileOpened: () => boolean, invertCutSegments: boolean, segmentsToChaptersOnly: boolean,
|
filePath?: string | undefined, workingRef: MutableRefObject<boolean>, setWorking: (w: { text: string, abortController?: AbortController } | undefined) => void, setCutProgress: (a: number | undefined) => void, videoStream, duration?: number | undefined, getRelevantTime: () => number, maxLabelLength: number, checkFileOpened: () => boolean, invertCutSegments: boolean, segmentsToChaptersOnly: boolean,
|
||||||
}) => {
|
}) => {
|
||||||
// Segment related state
|
// Segment related state
|
||||||
const segCounterRef = useRef(0);
|
const segCounterRef = useRef(0);
|
||||||
|
|
|
@ -19,7 +19,7 @@ export interface StateSegment extends SegmentBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Segment extends SegmentBase {
|
export interface Segment extends SegmentBase {
|
||||||
name?: string,
|
name?: string | undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApparentCutSegment extends ApparentSegmentBase {
|
export interface ApparentCutSegment extends ApparentSegmentBase {
|
||||||
|
|
13
src/util.ts
13
src/util.ts
|
@ -44,16 +44,16 @@ function getFileBaseName(filePath?: string) {
|
||||||
return parsed.name;
|
return parsed.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOutPath<T extends string | undefined>(a: { customOutDir?: string, filePath?: T, fileName: string }): T extends string ? string : undefined;
|
export function getOutPath<T extends string | undefined>(a: { customOutDir?: string | undefined, filePath?: T | undefined, fileName: string }): T extends string ? string : undefined;
|
||||||
export function getOutPath({ customOutDir, filePath, fileName }: { customOutDir?: string, filePath?: string | undefined, fileName: string }) {
|
export function getOutPath({ customOutDir, filePath, fileName }: { customOutDir?: string | undefined, filePath?: string | undefined, fileName: string }) {
|
||||||
if (filePath == null) return undefined;
|
if (filePath == null) return undefined;
|
||||||
return join(getOutDir(customOutDir, filePath), fileName);
|
return join(getOutDir(customOutDir, filePath), fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getSuffixedFileName = (filePath: string | undefined, nameSuffix: string) => `${getFileBaseName(filePath)}-${nameSuffix}`;
|
export const getSuffixedFileName = (filePath: string | undefined, nameSuffix: string) => `${getFileBaseName(filePath)}-${nameSuffix}`;
|
||||||
|
|
||||||
export function getSuffixedOutPath<T extends string | undefined>(a: { customOutDir?: string, filePath?: T, nameSuffix: string }): T extends string ? string : undefined;
|
export function getSuffixedOutPath<T extends string | undefined>(a: { customOutDir?: string | undefined, filePath?: T | undefined, nameSuffix: string }): T extends string ? string : undefined;
|
||||||
export function getSuffixedOutPath({ customOutDir, filePath, nameSuffix }: { customOutDir?: string, filePath?: string | undefined, nameSuffix: string }) {
|
export function getSuffixedOutPath({ customOutDir, filePath, nameSuffix }: { customOutDir?: string | undefined, filePath?: string | undefined, nameSuffix: string }) {
|
||||||
if (filePath == null) return undefined;
|
if (filePath == null) return undefined;
|
||||||
return getOutPath({ customOutDir, filePath, fileName: getSuffixedFileName(filePath, nameSuffix) });
|
return getOutPath({ customOutDir, filePath, fileName: getSuffixedFileName(filePath, nameSuffix) });
|
||||||
}
|
}
|
||||||
|
@ -107,10 +107,11 @@ export async function dirExists(dirPath) {
|
||||||
const testFailFsOperation = false;
|
const testFailFsOperation = false;
|
||||||
|
|
||||||
// Retry because sometimes write operations fail on windows due to the file being locked for various reasons (often anti-virus) #272 #1797 #1704
|
// Retry because sometimes write operations fail on windows due to the file being locked for various reasons (often anti-virus) #272 #1797 #1704
|
||||||
export async function fsOperationWithRetry(operation, { signal, retries = 10, minTimeout = 100, maxTimeout = 2000, ...opts }: Options & { retries?: number, minTimeout?: number, maxTimeout?: number } = {}) {
|
export async function fsOperationWithRetry(operation, { signal, retries = 10, minTimeout = 100, maxTimeout = 2000, ...opts }: Options & { retries?: number | undefined, minTimeout?: number | undefined, maxTimeout?: number | undefined } = {}) {
|
||||||
return pRetry(async () => {
|
return pRetry(async () => {
|
||||||
if (testFailFsOperation && Math.random() > 0.3) throw Object.assign(new Error('test delete failure'), { code: 'EPERM' });
|
if (testFailFsOperation && Math.random() > 0.3) throw Object.assign(new Error('test delete failure'), { code: 'EPERM' });
|
||||||
await operation();
|
await operation();
|
||||||
|
// @ts-expect-error todo
|
||||||
}, {
|
}, {
|
||||||
retries,
|
retries,
|
||||||
signal,
|
signal,
|
||||||
|
@ -391,7 +392,7 @@ function setDocumentExtraTitle(extra) {
|
||||||
document.title = extra != null ? `${baseTitle} - ${extra}` : baseTitle;
|
document.title = extra != null ? `${baseTitle} - ${extra}` : baseTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setDocumentTitle({ filePath, working, cutProgress }: { filePath?: string, working?: string, cutProgress?: number }) {
|
export function setDocumentTitle({ filePath, working, cutProgress }: { filePath?: string | undefined, working?: string | undefined, cutProgress?: number | undefined }) {
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
if (filePath) parts.push(basename(filePath));
|
if (filePath) parts.push(basename(filePath));
|
||||||
if (working) {
|
if (working) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import padStart from 'lodash/padStart';
|
import padStart from 'lodash/padStart';
|
||||||
|
|
||||||
export function formatDuration({ seconds: totalSecondsIn, fileNameFriendly, showFraction = true, shorten = false, fps }: {
|
export function formatDuration({ seconds: totalSecondsIn, fileNameFriendly, showFraction = true, shorten = false, fps }: {
|
||||||
seconds?: number, fileNameFriendly?: boolean, showFraction?: boolean, shorten?: boolean, fps?: number,
|
seconds?: number | undefined, fileNameFriendly?: boolean | undefined, showFraction?: boolean | undefined, shorten?: boolean | undefined, fps?: number | undefined,
|
||||||
}) {
|
}) {
|
||||||
const totalSeconds = totalSecondsIn || 0;
|
const totalSeconds = totalSecondsIn || 0;
|
||||||
const totalSecondsAbs = Math.abs(totalSeconds);
|
const totalSecondsAbs = Math.abs(totalSeconds);
|
||||||
|
|
|
@ -111,7 +111,7 @@ export const isMov = (format: string) => ['ismv', 'ipod', 'mp4', 'mov'].includes
|
||||||
type GetVideoArgsFn = (a: { streamIndex: number, outputIndex: number }) => string[] | undefined;
|
type GetVideoArgsFn = (a: { streamIndex: number, outputIndex: number }) => string[] | undefined;
|
||||||
|
|
||||||
function getPerStreamFlags({ stream, outputIndex, outFormat, manuallyCopyDisposition = false, getVideoArgs = () => undefined }: {
|
function getPerStreamFlags({ stream, outputIndex, outFormat, manuallyCopyDisposition = false, getVideoArgs = () => undefined }: {
|
||||||
stream, outputIndex: number, outFormat: string, manuallyCopyDisposition?: boolean, getVideoArgs?: GetVideoArgsFn
|
stream, outputIndex: number, outFormat: string, manuallyCopyDisposition?: boolean | undefined, getVideoArgs?: GetVideoArgsFn | undefined
|
||||||
}) {
|
}) {
|
||||||
let args: string[] = [];
|
let args: string[] = [];
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"plugins": [{ "name": "typescript-plugin-css-modules" }],
|
"plugins": [{ "name": "typescript-plugin-css-modules" }],
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
|
|
||||||
"exactOptionalPropertyTypes": false, // todo
|
|
||||||
"noImplicitAny": false, // todo
|
"noImplicitAny": false, // todo
|
||||||
"checkJs": false, // todo
|
"checkJs": false, // todo
|
||||||
"allowJs": true, // todo
|
"allowJs": true, // todo
|
||||||
|
|
Ładowanie…
Reference in New Issue