Replace the Electron app with a native GPUI one - #38
Merged
Conversation
QuickToss shows you one file and waits for one keystroke. Doing that through Electron cost a 110MB DMG, a 341MB installed bundle, a 9-channel IPC contract between two processes, and five JavaScript libraries each approximating a file format macOS already renders. This rewrites the app on GPUI (Zed's GPU-accelerated Rust framework) with GPUI Kit for components. The download is now ~6MB and the installed app 13MB, from one universal binary rather than one build per architecture. The UX is deliberately unchanged: same three screens, same keys, same Trash-not-delete safety, and settings.json is read from where it already lives so existing preferences carry over. The chrome is new — the blue gradient is gone, the window follows the system appearance, and the folder you are working through is now visible while you work through it. Previews are the substantive improvement. One call to QLThumbnailGenerator replaces pdfjs, mammoth, SheetJS, JSZip and heic2any, so Word, PowerPoint and Excel files get a real preview for the first time and PDFs and HEIC render the way they do in Finder. Video playback is the one regression: GPUI has no video element and the only third-party player needs GStreamer installed system-wide. Video files now show their poster frame, and a new `O` binding opens any file in the app that owns it. Also drops the hardened-runtime JIT entitlements V8 required, ports the release pipeline and icon tooling off Node, and records the reasoning in ADR 0002. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Tauri paragraph claimed it would have kept the JavaScript preview stack. That is wrong: Tauri's backend is Rust, so the same QLThumbnailGenerator bridge would have worked there. The size win was likewise never GPUI-specific, since Tauri uses the system WebView. Both were presented as reasons GPUI won, which overstated the case and would mislead anyone revisiting this decision later. The benefits are now split into what leaving Electron buys — the bulk of it, available from either framework — and the four things GPUI adds on top, with Tauri's three genuine advantages named, video playback first among them. Also corrects a stale 21 MB figure to the measured 13 MB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four documents cited issue #12 as the tracker for the video-playback regression. #12 is closed, and it was about DOCX/PPTX/XLSX/HEIC previews — the work the Quick Look bridge actually completed. Pointing readers at a closed, unrelated issue is worse than not linking at all, so the limitation is now described in place. The filmstrip idea is written down in CONTRIBUTING rather than attributed to an issue that doesn't exist. Also: - .gitignore was still entirely Node-shaped; trimmed to what this repo produces. Its `/build/` rule had been hiding a stray copy of the V8 JIT entitlements, never tracked and dead since electron-builder left. - docs/PRD.md specified SwiftUI in section 5. It's a pre-release document and the flows still hold, so it gets a note about which parts didn't survive rather than a rewrite. The unmet sandboxing requirement is now marked as unmet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rewrites QuickToss on GPUI — Zed's GPU-accelerated Rust UI framework — with GPUI Kit for components, and drops Electron, React, Vite, Tailwind and the npm tree.
The UX is deliberately unchanged: same three screens, same keys, same Trash-not-delete safety.
settings.jsonis read from where it already lives, so anyone upgrading keeps their preferences.Numbers
node_modulesWorth being explicit, and ADR 0002 now says so: that size win is a "stop shipping Chromium" win, not a GPUI win. Tauri would have landed in the same order of magnitude. What GPUI adds on top is no process boundary, no npm, no JIT entitlements, and rendering that doesn't drift with the OS's WebKit.
Previews are the substantive improvement
One call to
QLThumbnailGenerator— the renderer behind Finder's Quick Look — replaces pdfjs, mammoth, SheetJS, JSZip and heic2any. Word, PowerPoint and Excel files get a real preview for the first time; a deck looks like the deck rather than a list of its text runs. Measured on real files:.mov)This also isn't GPUI-specific — Tauri's backend is Rust too — but it's the change that most improves the app.
The regression
Video no longer plays. GPUI has no video element, and the only third-party player needs GStreamer installed system-wide, which a 13 MB app shouldn't demand. Video shows its poster frame, and a new
Obinding opens any file in the app that owns it. Tracked in #37, with a scrubbable-filmstrip approach sketched out.videoAutoplayis dropped with it. The other two settings carry over.Also in here
allow-jitandallow-unsigned-executable-memoryfor V8 — precisely the exceptions that weaken the hardened runtime.electron-builder→scripts/bundle.sh(~120 readable lines). Icon generation no longer pullselectron-icon-builderand its deprecated phantomjs-prebuilt;qlmanage/sips/iconutildo it. Changelog extraction is now shell.react-pdfpinned at 6.2.2 because ofPromise.withResolvers— that whole class of constraint stops arriving.Verification
38 tests,
clippy -D warningsandfmtclean, the bundled.applaunches, the DMG builds. The Quick Look bridge is tested against real files rather than mocked, including that a missing file fails rather than hanging.Not verified: the UI itself. Screen access wasn't available during the work, so the layout has never been looked at and no toss/keep/undo cycle has been driven through the actual interface. It compiles, launches and stays running — that's all that can be claimed. Please exercise it before merging.
Review notes
The diff is large but lopsided: ~12k insertions are mostly
Cargo.lock, and ~14k deletions are mostlypackage-lock.json. The code worth reading is ~2,700 lines acrossapp/src/, of which roughly 700 are tests.session.rs,files.rs,settings.rsandupdate.rsare plain functions with no GPUI types in them — that's where the ported logic lives and where the tests point.ui.rsis the one file with no test coverage at all.🤖 Generated with Claude Code