Self-review H1: give useDownloadBar an explicit return type
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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<SetStateAction<boolean>>
|
||||
trim: string
|
||||
showSchedule: boolean
|
||||
setShowSchedule: Dispatch<SetStateAction<boolean>>
|
||||
scheduleAt: string
|
||||
setScheduleAt: Dispatch<SetStateAction<string>>
|
||||
// drag / dup
|
||||
dragActive: boolean
|
||||
setDragActive: Dispatch<SetStateAction<boolean>>
|
||||
dup: string | null
|
||||
setDup: Dispatch<SetStateAction<string | null>>
|
||||
// advanced / preview
|
||||
showAdvanced: boolean
|
||||
setShowAdvanced: Dispatch<SetStateAction<boolean>>
|
||||
downloadOptions: DownloadOptions
|
||||
incognito: boolean
|
||||
setIncognito: Dispatch<SetStateAction<boolean>>
|
||||
commandPreview: CommandPreviewResult | null
|
||||
previewLoading: boolean
|
||||
// probe (single video)
|
||||
info: MediaInfo | null
|
||||
thumbFailed: string | null
|
||||
setThumbFailed: Dispatch<SetStateAction<string | null>>
|
||||
probing: boolean
|
||||
probeError: string | null
|
||||
usingFormats: boolean
|
||||
selectedFormat: FormatOption | undefined
|
||||
// playlist
|
||||
playlist: PlaylistInfo | null
|
||||
selected: Set<number>
|
||||
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<void>
|
||||
fetchFormats: () => Promise<void>
|
||||
paste: () => Promise<void>
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user