Files
AeroFetch/src/main/portable.ts
T
debont80 1a2270c95e Initial commit: AeroFetch — yt-dlp/YouTube downloader for Windows
Electron + React (Fluent UI) desktop frontend for yt-dlp:
- Download queue with live progress, concurrency cap, cancel/retry
- Format/quality picker via yt-dlp probe; audio extraction to MP3
- Settings + history persistence (electron-store / JSON)
- Clipboard link auto-detect; persisted light/dark theme
- NSIS + portable packaging (binaries bundled at build time, not in git)

UI: "Studio" sidebar layout with a toffee-brown theme (light + neutral dark).
Dropdowns use a native <select> and tooltips a CSS-only Hint, to avoid a
dev-machine GPU overlay flicker/blank issue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 18:17:41 -04:00

35 lines
1.5 KiB
TypeScript

import { app } from 'electron'
import { join } from 'path'
import { accessSync, mkdirSync, constants } from 'fs'
/**
* When running as the portable build, keep all per-user data (settings, history,
* caches — everything under `userData`) in an `AeroFetch-data` folder right next to
* the portable .exe. That makes the app fully self-contained on a USB stick and
* leaves nothing behind on a shared/library PC.
*
* Detection: electron-builder's `portable` target sets PORTABLE_EXECUTABLE_DIR at
* runtime to the folder the user launched the exe from. The installed (NSIS) build
* and dev don't set it, so they correctly use the default %APPDATA%\AeroFetch —
* which is per-user and never requires admin either.
*
* If the portable folder is read-only (locked-down machine, read-only media), we
* silently fall back to %APPDATA%. Either way the app needs no admin privileges.
*
* Must be called at startup, before the app is ready and before anything reads a
* user path (electron-store, history DB, etc.).
*/
export function setupPortableData(): void {
const portableExeDir = process.env.PORTABLE_EXECUTABLE_DIR
if (!portableExeDir) return
const portableDataDir = join(portableExeDir, 'AeroFetch-data')
try {
mkdirSync(portableDataDir, { recursive: true })
accessSync(portableDataDir, constants.W_OK)
app.setPath('userData', portableDataDir)
} catch {
// Read-only media — keep the default %APPDATA% userData (per-user, no admin).
}
}