add: launchTheme.css for consistent styling accross the whole components spectrum related to LaunchWindow
add: correct styles accross the popovers! with unstyled parameters in Popover.tsx because it was needed to make sure its the same
isAllowedLocalReadPath now resolves the candidate via fs.realpathSync and requires both the lexical and canonical paths to satisfy the policy, so a symlink placed under an allowed prefix that points outside the allowlist is rejected. The redundant 'either resolved or realResolved is allowed' check in read-local-file and generate-wallpaper-thumbnail is removed since the function canonicalizes internally. Adds a regression test that creates such a symlink (skipping when Windows refuses to create it without Developer Mode).
build-whisper-runtime now only soft-fails when invoked from postinstall, in CI, or with WHISPER_RUNTIME_ALLOW_MISSING=1. Direct 'npm run build*' invocations fail loudly when CMake is missing and no bundled runtime is staged so we don't ship release builds with broken auto-captioning.
isAllowedLocalReadPath previously returned true for any existing path because of an existsSync fast-path, which made the read-local-file IPC handler and the local media URL policy effectively allow reading arbitrary files on disk. Drop the existsSync bypass so only paths under app-managed directories or paths that have been explicitly approved (via dialogs, exports, recording sessions, etc.) are accepted. Adjust the local media path policy tests to cover the new behaviour.
Also make build-whisper-runtime fall back to bundled artifacts when CMake is missing (mirroring build-windows-capture) so npm ci does not fail on machines without a C++ toolchain.
Exports of recordings whose muxed output exceeds 2 GiB failed with
RangeError [ERR_FS_FILE_TOO_LARGE]: Node's fs.readFile rejects files
larger than kIoMaxLength (2 ** 31 - 1). The legacy export pipeline hit
this in muxExportedVideoAudioBuffer, which called
await fs.readFile(finalized.outputPath)
to ship the muxed bytes back to the renderer.
Mirror the path-based contract that mux-exported-video-audio-from-path
already uses:
- muxExportedVideoAudioBuffer now returns { outputPath, metrics } and
collects byte size via fs.stat instead of fs.readFile. The unmuxed
intermediate is still cleaned up; the muxed output is left for the
IPC handler to register and the renderer to finalize.
- The mux-exported-video-audio IPC handler registers the muxed output
via registerOwnedExportPath and returns { tempPath, metrics }.
- preload.ts and electron-env.d.ts: tempPath replaces data in the
renderer-facing return type.
- videoExporter.ts and modernVideoExporter.ts (the
finalizeExportWithFfmpegAudio fallback paths) now return
{ tempFilePath } so VideoEditor's existing finalize-exported-video
flow handles the move — the same path the modern stream-mode export
already takes.
The renderer already preferred tempFilePath over blob in
VideoEditor.tsx for MP4 saves (with the explicit comment "avoids ever
allocating a multi-GiB ArrayBuffer in the renderer"), so this just
removes the buffer-mode regression for large legacy exports.
Adds electron/ipc/export/native-video.test.ts asserting the new
contract: muxExportedVideoAudioBuffer returns a path, never calls
fs.readFile, and still records muxedVideoBytes via stat.
Closes#380