From 241210ca3b65c9756ae606bcfa587a0ff21ca1ce Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Tue, 10 Dec 2024 23:48:39 +0800 Subject: [PATCH] fix types --- package.json | 5 +- src/renderer/src/App.tsx | 6 +-- src/renderer/src/BottomBar.tsx | 14 +++--- src/renderer/src/edlFormats.ts | 90 ++++++++++++++++------------------ yarn.lock | 28 ++++------- 5 files changed, 63 insertions(+), 80 deletions(-) diff --git a/package.json b/package.json index 37d7ec25..895ffa34 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,8 @@ "@vitejs/plugin-react": "^4.3.1", "color": "^3.1.0", "concurrently": "^6.0.0", - "csv-parse": "^4.15.3", - "csv-stringify": "^5.6.2", + "csv-parse": "^5.6.0", + "csv-stringify": "^6.5.2", "data-uri-to-buffer": "^4.0.0", "electron": "^33.2.1", "electron-builder": "^24.13.3", @@ -99,7 +99,6 @@ "nanoid": "^5.0.9", "p-map": "^5.5.0", "p-retry": "^6.2.0", - "pify": "^5.0.0", "pretty-bytes": "^6.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 4ad39eac..3216248d 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -759,7 +759,7 @@ function App() { setSelectedBatchFiles([]); }, [askBeforeClose]); - const batchListRemoveFile = useCallback((path) => { + const batchListRemoveFile = useCallback((path: string | undefined) => { setBatchFiles((existingBatch) => { const index = existingBatch.findIndex((existingFile) => existingFile.path === path); if (index < 0) return existingBatch; @@ -1246,7 +1246,7 @@ function App() { const storeProjectInSourceDir = !storeProjectInWorkingDir; - async function tryFindAndLoadProjectFile({ chapters, cod }: { chapters, cod: string | undefined }) { + async function tryFindAndLoadProjectFile({ chapters, cod }: { chapters: FFprobeChapter[], cod: string | undefined }) { try { // First try to open from from working dir if (await tryOpenProjectPath(getEdlFilePath(fp, cod), 'llc')) return; @@ -1658,7 +1658,7 @@ function App() { const batchLoadPaths = useCallback((newPaths: string[], append?: boolean) => { setBatchFiles((existingFiles) => { - const mapPathsToFiles = (paths) => paths.map((path) => ({ path, name: basename(path) })); + const mapPathsToFiles = (paths: string[]) => paths.map((path) => ({ path, name: basename(path) })); if (append) { const newUniquePaths = newPaths.filter((newPath) => !existingFiles.some(({ path: existingPath }) => newPath === existingPath)); const [firstNewUniquePath] = newUniquePaths; diff --git a/src/renderer/src/BottomBar.tsx b/src/renderer/src/BottomBar.tsx index 4288d70b..cfc92a6e 100644 --- a/src/renderer/src/BottomBar.tsx +++ b/src/renderer/src/BottomBar.tsx @@ -1,4 +1,4 @@ -import { CSSProperties, Dispatch, SetStateAction, memo, useCallback, useEffect, useMemo, useState } from 'react'; +import { CSSProperties, ClipboardEvent, Dispatch, FormEvent, SetStateAction, memo, useCallback, useEffect, useMemo, useState } from 'react'; import { motion } from 'framer-motion'; import { MdRotate90DegreesCcw } from 'react-icons/md'; import { useTranslation } from 'react-i18next'; @@ -100,7 +100,7 @@ const CutTimeInput = memo(({ darkMode, cutTime, setCutTime, startTimeOffset, see border, borderRadius: 5, backgroundColor: 'var(--gray5)', transition: darkModeTransition, fontSize: 13, textAlign: 'center', padding: '1px 5px', marginTop: 0, marginBottom: 0, marginLeft: isStart ? 0 : 5, marginRight: isStart ? 5 : 0, boxSizing: 'border-box', fontFamily: 'inherit', width: 90, outline: 'none', }; - const trySetTime = useCallback((timeWithOffset) => { + const trySetTime = useCallback((timeWithOffset: number) => { const timeWithoutOffset = Math.max(timeWithOffset - startTimeOffset, 0); try { setCutTime(isStart ? 'start' : 'end', timeWithoutOffset); @@ -113,7 +113,7 @@ const CutTimeInput = memo(({ darkMode, cutTime, setCutTime, startTimeOffset, see } }, [isStart, seekAbs, setCutTime, startTimeOffset]); - const handleSubmit = useCallback((e) => { + const handleSubmit = useCallback((e: FormEvent) => { e.preventDefault(); // Don't proceed if not a valid time value @@ -123,7 +123,7 @@ const CutTimeInput = memo(({ darkMode, cutTime, setCutTime, startTimeOffset, see trySetTime(timeWithOffset); }, [cutTimeManual, parseTimecode, trySetTime]); - const parseAndSetCutTime = useCallback((text) => { + const parseAndSetCutTime = useCallback((text: string) => { // Don't proceed if not a valid time value const timeWithOffset = parseTimecode(text); if (timeWithOffset === undefined) return; @@ -131,13 +131,13 @@ const CutTimeInput = memo(({ darkMode, cutTime, setCutTime, startTimeOffset, see trySetTime(timeWithOffset); }, [parseTimecode, trySetTime]); - function handleCutTimeInput(text) { + function handleCutTimeInput(text: string) { setCutTimeManual(text); if (isExactDurationMatch(text)) parseAndSetCutTime(text); } - const tryPaste = useCallback((clipboardText) => { + const tryPaste = useCallback((clipboardText: string) => { try { setCutTimeManual(clipboardText); parseAndSetCutTime(clipboardText); @@ -146,7 +146,7 @@ const CutTimeInput = memo(({ darkMode, cutTime, setCutTime, startTimeOffset, see } }, [parseAndSetCutTime]); - const handleCutTimePaste = useCallback((e) => { + const handleCutTimePaste = useCallback((e: ClipboardEvent) => { e.preventDefault(); try { diff --git a/src/renderer/src/edlFormats.ts b/src/renderer/src/edlFormats.ts index d9b73664..bf772dfa 100644 --- a/src/renderer/src/edlFormats.ts +++ b/src/renderer/src/edlFormats.ts @@ -1,18 +1,15 @@ import { XMLParser } from 'fast-xml-parser'; import i18n from 'i18next'; -import csvParse from 'csv-parse/lib/browser'; -import csvStringify from 'csv-stringify/lib/browser'; -import pify from 'pify'; +import { parse as csvParse } from 'csv-parse/browser/esm/sync'; +import { stringify as csvStringify } from 'csv-stringify/browser/esm/sync'; import sortBy from 'lodash/sortBy'; import type { ICueSheet, ITrack } from 'cue-parser/lib/types'; import { formatDuration } from './util/duration'; import { invertSegments, sortSegments } from './segments'; -import { Segment, SegmentBase } from './types'; - -const csvParseAsync = pify(csvParse); -const csvStringifyAsync = pify(csvStringify); +import { GetFrameCount, Segment, SegmentBase } from './types'; +import invariant from 'tiny-invariant'; export const getTimeFromFrameNum = (detectedFps: number, frameNum: number) => frameNum / detectedFps; @@ -48,7 +45,7 @@ export const getFrameValParser = (fps: number) => (str: string) => { }; export async function parseCsv(csvStr: string, parseTimeFn: (a: string) => number | undefined) { - const rows = await csvParseAsync(csvStr, {}) as [string, string, string][]; + const rows = csvParse(csvStr, {}) as [string, string, string][]; if (rows.length === 0) throw new Error(i18n.t('No rows found')); if (!rows.every((row) => row.length === 3)) throw new Error(i18n.t('One or more rows does not have 3 columns')); @@ -77,61 +74,56 @@ export async function parseCutlist(clStr: string) { param: /^\s*([^=]+?)\s*=\s*(.*?)\s*$/, comment: /^\s*;.*$/, }; - const iniValue = {}; + const iniValue: Record> = {}; + const lines = clStr.split(/[\n\r]+/); - let section: string | null | undefined = null; + let section: string | undefined; lines.forEach((line) => { if (regex.comment.test(line)) { return; - } if (regex.param.test(line)) { + } + if (regex.param.test(line)) { const match = line.match(regex.param) || []; - const [, m1, m2] = match; - if (m1) { + const [, key, value] = match; + if (key) { if (section) { - iniValue[section][m1] = m2; + const sectionObj = iniValue[section]; + invariant(sectionObj != null && typeof sectionObj !== 'string'); + sectionObj[key] = value; } else { - iniValue[m1] = m2; + iniValue[key] = value; } } } else if (regex.section.test(line)) { const match = line.match(regex.section) || []; - const [, m1] = match; - if (m1) { - iniValue[m1] = {}; - section = m1; + const [, sectionMatch] = match; + if (sectionMatch) { + iniValue[sectionMatch] = {}; + section = sectionMatch; } } else if (line.length === 0 && section) { - section = null; + section = undefined; } }); // end INI-File parse - let found = true; - let i = 0; const cutArr: { start: number, end: number, name: string }[] = []; - while (found) { + for (let i = 0; ; i += 1) { const cutEntry = iniValue[`Cut${i}`]; - if (cutEntry) { - const start = parseFloat(cutEntry.Start); - const end = Math.round((start + parseFloat(cutEntry.Duration) + Number.EPSILON) * 100) / 100; + if (cutEntry && typeof cutEntry !== 'string') { + const start = parseFloat(cutEntry['Start']!); + const end = Math.round((start + parseFloat(cutEntry['Duration']!) + Number.EPSILON) * 100) / 100; + invariant(!Number.isNaN(start), 'Invalid Start'); + invariant(!Number.isNaN(end), 'Invalid End'); cutArr.push({ start, end, name: `Cut ${i}`, }); } else { - found = false; + break; } - i += 1; - } - - if (!cutArr.every(({ start, end }) => ( - (start === undefined || !Number.isNaN(start)) - && (end === undefined || !Number.isNaN(end)) - ))) { - console.log(cutArr); - throw new Error(i18n.t('Invalid start or end value. Must contain a number of seconds')); } return cutArr; @@ -295,7 +287,7 @@ export function parseYouTube(str: string) { return edl.filter((ed) => ed.start !== ed.end); } -export function formatYouTube(segments) { +export function formatYouTube(segments: Segment[]) { return segments.map((segment) => { const timeStr = formatDuration({ seconds: segment.start, showFraction: false, shorten: true }); const namePart = segment.name ? ` ${segment.name}` : ''; @@ -304,16 +296,16 @@ export function formatYouTube(segments) { } // because null/undefined is also valid values (start/end of timeline) -const safeFormatDuration = (duration) => (duration != null ? formatDuration({ seconds: duration }) : ''); +const safeFormatDuration = (duration: number | undefined) => (duration != null ? formatDuration({ seconds: duration }) : ''); -export const formatSegmentsTimes = (cutSegments) => cutSegments.map(({ start, end, name }) => [ +export const formatSegmentsTimes = (cutSegments: Segment[]) => cutSegments.map(({ start, end, name }) => [ safeFormatDuration(start), safeFormatDuration(end), name, ]); -export async function formatCsvFrames({ cutSegments, getFrameCount }) { - const safeFormatFrameCount = (seconds) => (seconds != null ? getFrameCount(seconds) : ''); +export async function formatCsvFrames({ cutSegments, getFrameCount }: { cutSegments: Segment[], getFrameCount: GetFrameCount }) { + const safeFormatFrameCount = (seconds: number | undefined) => (seconds != null ? getFrameCount(seconds) : ''); const formatted = cutSegments.map(({ start, end, name }) => [ safeFormatFrameCount(start), @@ -321,20 +313,20 @@ export async function formatCsvFrames({ cutSegments, getFrameCount }) { name, ]); - return csvStringifyAsync(formatted); + return csvStringify(formatted); } -export async function formatCsvSeconds(cutSegments) { +export async function formatCsvSeconds(cutSegments: Segment[]) { const rows = cutSegments.map(({ start, end, name }) => [start, end, name]); - return csvStringifyAsync(rows); + return csvStringify(rows); } -export async function formatCsvHuman(cutSegments) { - return csvStringifyAsync(formatSegmentsTimes(cutSegments)); +export async function formatCsvHuman(cutSegments: Segment[]) { + return csvStringify(formatSegmentsTimes(cutSegments)); } -export async function formatTsv(cutSegments) { - return csvStringifyAsync(formatSegmentsTimes(cutSegments), { delimiter: '\t' }); +export async function formatTsv(cutSegments: Segment[]) { + return csvStringify(formatSegmentsTimes(cutSegments), { delimiter: '\t' }); } export function parseDvAnalyzerSummaryTxt(txt: string) { @@ -424,7 +416,7 @@ export function parseSrtToSegments(text: string) { })); } -export function formatSrt(segments) { +export function formatSrt(segments: Segment[]) { return segments.reduce((acc, segment, index) => `${acc}${index > 0 ? '\r\n' : ''}${index + 1}\r\n${formatDuration({ seconds: segment.start }).replaceAll('.', ',')} --> ${formatDuration({ seconds: segment.end }).replaceAll('.', ',')}\r\n${segment.name || '-'}\r\n`, ''); } diff --git a/yarn.lock b/yarn.lock index b32659ab..2d6dd4fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4005,17 +4005,17 @@ __metadata: languageName: node linkType: hard -"csv-parse@npm:^4.15.3": - version: 4.16.3 - resolution: "csv-parse@npm:4.16.3" - checksum: 10/b873dd2d312ac0329200f13788176bae3073862241483b0339a4777c9eddcebd9f2f48f13d02dc0baf4bc02e957f886ea03a9cb22160d70836b0017432f8fa41 +"csv-parse@npm:^5.6.0": + version: 5.6.0 + resolution: "csv-parse@npm:5.6.0" + checksum: 10/4c82e11f50ae0ccbac2aed716ef2502d0468bf96552083561db789fc0258ee4bb0a30106fcfb2684f153cb4042f0413e0eac3645d5466874803b7ccdeba67ac8 languageName: node linkType: hard -"csv-stringify@npm:^5.6.2": - version: 5.6.5 - resolution: "csv-stringify@npm:5.6.5" - checksum: 10/efed94869b8426e6a983f2237bd74eff15953e2e27affee9c1324f66a67dabe948573c4c21a8661a79aa20b58efbcafcf11c34e80bdd532a43f35e9cde5985b9 +"csv-stringify@npm:^6.5.2": + version: 6.5.2 + resolution: "csv-stringify@npm:6.5.2" + checksum: 10/7715664020d291ccece25a32ecca617cea8d7e320af0c4e58cabbfb52d914832c3ea63c77c9796ca032ce6b47b899c879140c55bfd380105c42038ec305607a3 languageName: node linkType: hard @@ -7604,8 +7604,8 @@ __metadata: "@vitejs/plugin-react": "npm:^4.3.1" color: "npm:^3.1.0" concurrently: "npm:^6.0.0" - csv-parse: "npm:^4.15.3" - csv-stringify: "npm:^5.6.2" + csv-parse: "npm:^5.6.0" + csv-stringify: "npm:^6.5.2" cue-parser: "npm:^0.3.0" data-uri-to-buffer: "npm:^4.0.0" electron: "npm:^33.2.1" @@ -7647,7 +7647,6 @@ __metadata: nanoid: "npm:^5.0.9" p-map: "npm:^5.5.0" p-retry: "npm:^6.2.0" - pify: "npm:^5.0.0" pretty-bytes: "npm:^6.0.0" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" @@ -8780,13 +8779,6 @@ __metadata: languageName: node linkType: hard -"pify@npm:^5.0.0": - version: 5.0.0 - resolution: "pify@npm:5.0.0" - checksum: 10/443e3e198ad6bfa8c0c533764cf75c9d5bc976387a163792fb553ffe6ce923887cf14eebf5aea9b7caa8eab930da8c33612990ae85bd8c2bc18bedb9eae94ecb - languageName: node - linkType: hard - "pkg-up@npm:^3.0.1": version: 3.1.0 resolution: "pkg-up@npm:3.1.0"