Files
AeroFetch/src/renderer/src/components/Onboarding.tsx
T
debont80 d7b5737806 Self-review fixes: revert ineffective/regression-risk changes from audit batch
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>
2026-06-30 15:11:13 -04:00

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&apos;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>
)
}