From 9e0064aab2b2ac5b9e7778d282464a95177f585e Mon Sep 17 00:00:00 2001 From: debont80 Date: Tue, 30 Jun 2026 21:41:06 -0400 Subject: [PATCH] Self-review H1: give useDownloadBar an explicit return type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The extracted hook relied on inferred return typing, inconsistent with the codebase convention (useClipboardLink: ClipboardLink, useResolvedDark: boolean). Add a compiler-verified DownloadBarController interface and annotate the hook — the returned object is checked against it, so the surface can't silently drift. Co-Authored-By: Claude Opus 4.8 --- .../components/downloadBar/useDownloadBar.ts | 77 ++++++++++++++++++- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/components/downloadBar/useDownloadBar.ts b/src/renderer/src/components/downloadBar/useDownloadBar.ts index 2955ba0..0037d25 100644 --- a/src/renderer/src/components/downloadBar/useDownloadBar.ts +++ b/src/renderer/src/components/downloadBar/useDownloadBar.ts @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react' +import { useState, useEffect, useRef, type Dispatch, type SetStateAction } from 'react' import { parseUrlShortcutContent, type MediaInfo, @@ -12,7 +12,12 @@ import { useDownloads, type MediaKind } from '../../store/downloads' import { QUALITY_OPTIONS } from '../../qualityOptions' import { sameVideo } from '../../store/queueStats' import { useSettings } from '../../store/settings' -import { useClipboardLink, looksLikeUrl, firstUrlInText } from '../../useClipboardLink' +import { + useClipboardLink, + looksLikeUrl, + firstUrlInText, + type SuggestionSource +} from '../../useClipboardLink' import { logError } from '../../reportError' /** Pull the URL= target out of a dropped Windows .url Internet Shortcut file. */ @@ -29,12 +34,78 @@ export function toLocalDatetimeValue(d: Date): string { return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}` } +/** Everything the DownloadBar render needs — the hook's public surface. */ +export interface DownloadBarController { + // form state + url: string + kind: MediaKind + quality: string + // trim / schedule + showTrim: boolean + setShowTrim: Dispatch> + trim: string + showSchedule: boolean + setShowSchedule: Dispatch> + scheduleAt: string + setScheduleAt: Dispatch> + // drag / dup + dragActive: boolean + setDragActive: Dispatch> + dup: string | null + setDup: Dispatch> + // advanced / preview + showAdvanced: boolean + setShowAdvanced: Dispatch> + downloadOptions: DownloadOptions + incognito: boolean + setIncognito: Dispatch> + commandPreview: CommandPreviewResult | null + previewLoading: boolean + // probe (single video) + info: MediaInfo | null + thumbFailed: string | null + setThumbFailed: Dispatch> + probing: boolean + probeError: string | null + usingFormats: boolean + selectedFormat: FormatOption | undefined + // playlist + playlist: PlaylistInfo | null + selected: Set + allSelected: boolean + // suggestion banner + suggestion: string | null + suggestionSource: SuggestionSource + dismissSuggestion: () => void + // handlers + onDragOver: (e: React.DragEvent) => void + onDrop: (e: React.DragEvent) => void + onUrlChange: (next: string) => void + onKindChange: (next: MediaKind) => void + onQualityChange: (v: string) => void + onFormatIdChange: (v: string) => void + onTrimChange: (v: string) => void + onDownloadOptionsChange: (next: DownloadOptions) => void + toggleCommandPreview: () => Promise + fetchFormats: () => Promise + paste: () => Promise + acceptSuggestion: () => void + download: () => void + downloadAnyway: () => void + addPlaylist: () => void + toggleEntry: (index: number, on: boolean) => void + toggleAll: () => void + effKind: (index: number) => MediaKind + toggleItemKind: (index: number) => void + setAllKinds: (k: MediaKind) => void +} + /** * All state and behaviour for the DownloadBar. Extracted from the component so * the ~17 interdependent state hooks and their handlers live in one place and * the component is render-only. */ -export function useDownloadBar() { +export function useDownloadBar(): DownloadBarController { const addFromUrl = useDownloads((s) => s.addFromUrl) const addMany = useDownloads((s) => s.addMany) const settingsLoaded = useSettings((s) => s.loaded)