Files
AeroFetch/src/renderer/src/components/settings/useAboutCard.ts
T
debont80 cdb6eea437 feat(audit): Batch 18 — watched visual pass (UI3, UI12, UI16, UI21, UX18, L109, UX26)
UI3: remaining list-row/control paddings on the SPACE scale (History row,
Downloads summary, Library head/detail, Terminal gate/log, template rows).
UI21: active-nav rail now shows collapsed too (moved into navItemActive).
UX18: stable 'Quality' label + brand '• fetched' tag instead of the
label/control morph after Fetch.
L109/UX26: skeleton lines for the About yt-dlp/ffmpeg boot load; skeleton
cards in Settings until the store's loaded flag flips.
UI12/UI16: deferred eyeball deltas verified via Electron-probe screenshots
(light+dark, collapsed sidebar, fetch flow); UI16 convention codified in
ui/tokens.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 11:55:45 -04:00

107 lines
3.6 KiB
TypeScript

import { useEffect, useState } from 'react'
import type { YtdlpVersionResult, YtdlpUpdateResult, FfmpegVersionResult } from '@shared/ipc'
import { useSettings } from '../../store/settings'
import { logError } from '../../reportError'
export interface AboutCardController {
checking: boolean
version: YtdlpVersionResult | null
ffmpeg: FfmpegVersionResult | null
updating: boolean
updateResult: YtdlpUpdateResult | null
checkVersion: () => Promise<void>
runUpdate: () => Promise<void>
refreshFfmpeg: () => void
}
/**
* View-model for the About card (L93/CC13): owns the yt-dlp/ffmpeg version state
* and the update orchestration so the card stays presentational — no `window.api`
* in the component (the `useDownloadBar` pattern).
*/
export function useAboutCard(): AboutCardController {
const ytdlpChannel = useSettings((s) => s.ytdlpChannel)
// `checking` starts true: the mount effect immediately loads the version, and
// the card shows a skeleton line for that boot load instead of a blank (L109).
const [checking, setChecking] = useState(true)
const [version, setVersion] = useState<YtdlpVersionResult | null>(null)
const [ffmpeg, setFfmpeg] = useState<FfmpegVersionResult | null>(null)
const [updating, setUpdating] = useState(false)
const [updateResult, setUpdateResult] = useState<YtdlpUpdateResult | null>(null)
useEffect(() => {
// Show the current yt-dlp version without a manual click, and reflect a
// background auto-update (which may run on launch) live in this panel.
window.api
.getYtdlpVersion()
.then(setVersion)
.catch(logError('getYtdlpVersion'))
.finally(() => setChecking(false))
// ffmpeg/ffprobe are display-only (bundled, not auto-updated); load them once.
// On a bridge failure, settle to "not found" rather than a permanent skeleton.
window.api
.getFfmpegVersions()
.then(setFfmpeg)
.catch((e) => {
logError('getFfmpegVersions')(e)
setFfmpeg({ ffmpeg: null, ffprobe: null })
})
return window.api.onYtdlpAutoUpdateStatus((s) => {
if (s.phase === 'checking') {
setChecking(true)
return
}
setChecking(false)
if (s.version) setVersion({ ok: true, version: s.version })
if (s.checkedAt) useSettings.setState({ ytdlpLastUpdateCheck: s.checkedAt })
if (s.phase === 'updated') {
setUpdateResult({ ok: true, output: `Updated to yt-dlp ${s.version ?? ''}`.trim() })
} else if (s.phase === 'error' && s.error) {
setUpdateResult({ ok: false, error: s.error })
}
})
}, [])
async function checkVersion(): Promise<void> {
setChecking(true)
setVersion(null)
try {
setVersion(await window.api.getYtdlpVersion())
} catch (e) {
setVersion({ ok: false, error: e instanceof Error ? e.message : String(e) })
} finally {
setChecking(false)
}
}
async function runUpdate(): Promise<void> {
setUpdating(true)
setUpdateResult(null)
try {
const result = await window.api.updateYtdlp(ytdlpChannel)
setUpdateResult(result)
if (result.ok) setVersion(null) // stale -- prompt a re-check rather than show a wrong version
} catch (e) {
setUpdateResult({ ok: false, error: e instanceof Error ? e.message : String(e) })
} finally {
setUpdating(false)
}
}
function refreshFfmpeg(): void {
window.api.getFfmpegVersions().then(setFfmpeg).catch(logError('getFfmpegVersions'))
}
return {
checking,
version,
ffmpeg,
updating,
updateResult,
checkVersion,
runUpdate,
refreshFfmpeg
}
}