d7b5737806
Addressing issues found reviewing this session's audit commits:
REGRESSIONS FIXED
- updater.ts (L52): reverted the spawn(detached) installer launch. Raw
CreateProcess/spawn fails with ERROR_ELEVATION_REQUIRED if the NSIS build
flips to perMachine (the config comment invites this), and it silently
dropped shell.openPath's launch-error detection. Restored shell.openPath
(ShellExecute honors the elevation manifest) and kept the L52 goal by
replacing the 1500ms timer with setImmediate(app.quit).
- LibraryView.tsx (M15): native <button> doesn't inherit color (UA sets
ButtonText), so the source-card chevron (currentColor) would render wrong
in dark mode. Added color: colorNeutralForeground1 to cardHead.
INEFFECTIVE CHANGE REVERTED
- base.css (W18): forced-color-adjust:auto on * is the CSS default (no-op),
and [class*="backdrop"] never matches Fluent/Griffel's hashed atomic class
names. Reverted; W18 unmarked (needs real High-Contrast testing).
WEAK FIX REVERTED
- Onboarding.tsx (L67): "Skip" and "Get started" called the identical handler
on a single-screen onboarding. Removed the duplicate button; L67 unmarked
(real ask is a "show tips again" revisit affordance).
STYLE / CORRECTNESS
- Stripped UTF-8 BOMs accidentally added to Select/CommandPalette/App/
Onboarding by the PowerShell sanitizer; left pre-existing BOMs untouched.
- DownloadBar.tsx: merged the duplicate @shared/ipc import; removed a stray
double blank line.
- qualityOptions.ts (L29): restored the original `satisfies Record<MediaKind,
readonly string[]>` constraint + the noUncheckedIndexedAccess rationale
comment (the extraction had dropped both for a weaker `as const`).
- downloads.ts: removed double blank line left by the QUALITY_OPTIONS move.
- binaries.ts: corrected YTDLP_MISSING_MSG doc comment ("at startup" -> the
actual call sites).
typecheck + 242 tests + eslint all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
140 lines
3.4 KiB
TypeScript
140 lines
3.4 KiB
TypeScript
import {
|
|
Card,
|
|
Title2,
|
|
Body1,
|
|
Caption1,
|
|
Field,
|
|
Button,
|
|
makeStyles,
|
|
tokens,
|
|
shorthands
|
|
} from '@fluentui/react-components'
|
|
import {
|
|
ArrowDownloadFilled,
|
|
ClipboardPasteRegular,
|
|
HistoryRegular,
|
|
OptionsRegular,
|
|
RocketRegular
|
|
} from '@fluentui/react-icons'
|
|
import { useSettings } from '../store/settings'
|
|
|
|
const useStyles = makeStyles({
|
|
root: {
|
|
height: '100%',
|
|
width: '100%',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
overflowY: 'auto',
|
|
padding: '24px'
|
|
},
|
|
card: {
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: '20px',
|
|
padding: '32px',
|
|
maxWidth: '460px',
|
|
width: '100%',
|
|
...shorthands.borderRadius(tokens.borderRadiusXLarge)
|
|
},
|
|
brandRow: {
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: '14px'
|
|
},
|
|
mark: {
|
|
width: '48px',
|
|
height: '48px',
|
|
flexShrink: 0,
|
|
...shorthands.borderRadius(tokens.borderRadiusLarge),
|
|
backgroundColor: tokens.colorBrandBackground,
|
|
color: tokens.colorNeutralForegroundOnBrand,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
fontSize: '26px'
|
|
},
|
|
folderNote: {
|
|
color: tokens.colorNeutralForeground3
|
|
},
|
|
tips: {
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: '10px'
|
|
},
|
|
tip: {
|
|
display: 'flex',
|
|
alignItems: 'flex-start',
|
|
gap: '10px'
|
|
},
|
|
tipIcon: {
|
|
fontSize: '18px',
|
|
flexShrink: 0,
|
|
marginTop: '2px',
|
|
color: tokens.colorCompoundBrandForeground1
|
|
}
|
|
})
|
|
|
|
const TIPS: { icon: React.JSX.Element; text: string }[] = [
|
|
{
|
|
icon: <ClipboardPasteRegular />,
|
|
text: 'Copy a video link and AeroFetch offers to fetch it as soon as you switch back.'
|
|
},
|
|
{
|
|
icon: <HistoryRegular />,
|
|
text: 'Downloads queue with a concurrency cap, and every completed file lands in History.'
|
|
},
|
|
{
|
|
icon: <OptionsRegular />,
|
|
text: 'Subtitles, SponsorBlock, custom yt-dlp commands, and more live in Settings.'
|
|
}
|
|
]
|
|
|
|
export function Onboarding(): React.JSX.Element {
|
|
const styles = useStyles()
|
|
const update = useSettings((s) => s.update)
|
|
|
|
return (
|
|
<div className={styles.root}>
|
|
<Card className={styles.card}>
|
|
<div className={styles.brandRow}>
|
|
<div className={styles.mark}>
|
|
<ArrowDownloadFilled />
|
|
</div>
|
|
<Title2>Welcome to AeroFetch</Title2>
|
|
</div>
|
|
|
|
<Body1>
|
|
A no-frills frontend for yt-dlp: paste a link, pick a quality, and download video or
|
|
audio. yt-dlp and ffmpeg are bundled, so there's nothing else to install.
|
|
</Body1>
|
|
|
|
<Field label="Where downloads go">
|
|
<Caption1 className={styles.folderNote}>
|
|
Videos save to your <strong>Documents\Video</strong> folder and audio to{' '}
|
|
<strong>Documents\Audio</strong>. You can point each to a different folder any time in
|
|
Settings.
|
|
</Caption1>
|
|
</Field>
|
|
|
|
<div className={styles.tips}>
|
|
{TIPS.map((tip) => (
|
|
<div key={tip.text} className={styles.tip}>
|
|
<span className={styles.tipIcon}>{tip.icon}</span>
|
|
<Caption1>{tip.text}</Caption1>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<Button
|
|
appearance="primary"
|
|
icon={<RocketRegular />}
|
|
onClick={() => update({ hasCompletedOnboarding: true })}
|
|
>
|
|
Get started
|
|
</Button>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|