cdb6eea437
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>
107 lines
3.6 KiB
TypeScript
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
|
|
}
|
|
}
|