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>
This commit is contained in:
2026-06-30 15:11:13 -04:00
parent ab085f2bfe
commit d7b5737806
12 changed files with 54 additions and 69 deletions
+1 -1
View File
@@ -80,7 +80,7 @@ export function getFfprobePath(): string {
return join(getBinDir(), 'ffprobe.exe')
}
/** User-facing error shown whenever yt-dlp.exe is not found at startup. */
/** User-facing error shown by download/probe/index/update when yt-dlp.exe is missing. */
export const YTDLP_MISSING_MSG =
'yt-dlp.exe is missing. Open Settings → Software update to re-download it.'
+9 -8
View File
@@ -1,5 +1,4 @@
import { app, net, type WebContents } from 'electron'
import { spawn } from 'child_process'
import { app, net, shell, type WebContents } from 'electron'
import { createWriteStream, type WriteStream } from 'fs'
import { stat, unlink } from 'fs/promises'
import { join, normalize, dirname } from 'path'
@@ -426,12 +425,14 @@ export async function runAppUpdate(filePath: string): Promise<{ ok: boolean; err
return { ok: false, error: 'Refused to run an unexpected file.' }
}
await stat(target) // throws if the file is missing
// Spawn the installer detached + unref'd so it outlives our process even on a
// slow machine. shell.openPath goes through ShellExecute but gives us no child
// PID to wait on; spawning directly lets us call unref() before we quit.
const child = spawn(target, [], { detached: true, stdio: 'ignore', shell: false })
child.unref()
// Let the IPC response reach the renderer before we exit.
// Hand the installer to the OS via ShellExecute, which (unlike a raw
// CreateProcess/spawn) honors the NSIS elevation manifest — needed if the
// build ever flips to perMachine. openPath resolves once the launch is
// initiated, so the installer process already exists when we quit.
const err = await shell.openPath(target)
if (err) return { ok: false, error: err }
// Quit on the next tick so this IPC response reaches the renderer first; the
// launched installer is independent of our process and survives the quit.
setImmediate(() => app.quit())
return { ok: true }
} catch (e) {