feat(desktop): flapping bee on the setup loading screen#1631
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5034f6dea0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2db7ab98b3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af55ac28f5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
🤖 Refresh-freeze fix: the wing flap now runs on the compositor. Reproduced the "bee frozen on refresh" report: WebKit paints SVG children on the main thread, and on a warm refresh boot work (bundle eval + first React render of the app tree) hogs that thread for most of the window the gate is visible — a
Also repaired the setup-gate e2e test, which still asserted the #1570 black static gate this branch replaced (it was failing on this branch before this commit) — it now asserts the grainient wash + flapping-bee treatment, including that the flap uses zero Setup gate — light (GitHub Light)Setup gate — dark (Catppuccin Macchiato)Wings openWings tucked |
edf4a52 to
355dfc2
Compare
Replace the static Buzz mark and spinner on the setup splash and workspace-switch gate with the looping FuzzyLogo (fuzzy texture, theme-adaptive tint). A static BuzzMark renders underneath so the box paints instantly on hard reload instead of flashing blank. Loops continuously via loopRestSeconds=0 — the prior rest window left the mark visually static for ~63% of each cycle, which read as 'not animated'. Signed-off-by: Fizz <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
… hero Restore the pre-#1570 theme-adaptive grainient loading gate, with the animated Buzz bee as the visual hero replacing the old "Setting up your workspace" text (the caption stays as sr-only for screen readers). - Restore ThemeGrainientBackground and the grainient/shell CSS (orbiting radial grainient driven by --chart-* / --primary theme vars, plus the dark-mode alpha overrides and reduced-motion fallback) that #1570 stripped. - Rewire AppLoadingGate to the .buzz-setup-loading-shell + grainient + BeeLoader (relative z-10) structure. Drop the text-only rules (buzz-setup-loading-text, buzz-setup-character-rise) since the bee replaces the text. - index.html: paint the pre-React window in the cached theme --background (buzz-theme-cache) instead of always black, killing the black flash on light themes; falls back to black on the first-ever launch. Scoped to the cold-boot AppLoadingGate only; the quiet WorkspaceSwitchGate keeps the bee on a plain themed background. Signed-off-by: Fizz <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
Keep the setup loading gate's bee exactly as before (identical BuzzMark geometry) and just add motion: a new FlappingBee component tags the two wing lobes with bee-wing classes so the ported wing-flap keyframes beat them on a continuous infinite loop. Reduced-motion falls back to the static silhouette. Also fixes a biome useTemplate lint in index.html's cached-theme boot script. Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
…'t caught at rest On a warm Cmd+R refresh the cold-boot loading gate can be very short-lived, so the wing-flap was often caught at its 0% rest pose (no visible motion). Start the flap with a negative animation-delay (-0.14s) so the very first painted frame is already mid-beat — the bee never appears frozen at rest. Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
…sh doesn't freeze the bee On a warm refresh the bee flashed frozen: WebKit paints SVG *children* on the main thread, and boot work (bundle eval, first React render of the app tree) hogs that thread for most of the window the loading gate is visible, so a transform animation on the wing <circle>s never advances. Rebuild FlappingBee as layered HTML-level <svg> wings under the masked body SVG and animate the wing elements' CSS transforms in percentages — HTML-level transforms run on the compositor (Core Animation in WKWebView) and keep flapping while the main thread is blocked. The slot cutouts still punch through the wings via static CSS masks on the non-animated wing wrappers (evenodd alpha masks — CSS mask-image uses the alpha channel, not luminance), verified pixel-equivalent to the single-SVG mark at rest/mid/tuck phases (37-39dB PSNR, anti-aliasing only). Start pose moves from full tuck (-0.14s) to genuine mid-stroke (-0.07s) so a one-frame flash reads as caught mid-beat rather than squished. Also repair the setup-gate e2e assertions, which still tested the #1570 black static gate this branch replaced (pre-existing failure): assert the grainient wash + flapping bee treatment instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: klopez4212 <klopez4212@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 355dfc2427
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…e on cold boot Give the animated FuzzyLogo layer in BeeLoader an important full width/height so it overrides the buzz-logo--compact 1.5rem rule and fills the static BuzzMark instead of rendering at 24px. On first-ever launch (no theme cache) seed the dark class synchronously in the boot script so the setup gate paints from the dark :root vars, matching the default dark houston theme ThemeProvider applies moments later — no light Catppuccin-Latte flash between the black boot background and the themed gate. Addresses review comments on PR #1631. Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
355dfc2 to
c225b7e
Compare
…ld boot Cold boot resolves the workspace in well under 100ms — traced in the real staging app: the loading gate mounted at t=91ms and unmounted at t=150ms, before the hidden Tauri window (visible:false until show()) ever put a frame on screen. The wing animation was healthy the whole time; there was just nothing on screen long enough to see. Refresh only looked different because the window is already visible, so the flash is catchable. Keep the gate up as a fixed overlay above the already-mounted app for a minimum visible duration (1.2s + 200ms fade), then unmount it. Boot work and data loading proceed beneath the overlay, so time-to-interactive is unchanged — only the reveal waits. Workspace switches and first-run completion keep their quiet gates; boots slower than the hold behave exactly as before. E2E runs skip the hold (it would slow every spec's boot and block pointer actionability); specs can opt back in via __BUZZ_E2E__.bootSplashHoldMs, which the new boot-splash.spec.ts uses to assert the overlay holds with a running wing flap, doesn't delay the app beneath, and dismisses cleanly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 Cold-boot follow-up: traced the real staging app and found the gate only lived 59ms on cold boot (mounted t=91ms, unmounted t=150ms) — the wing animation was healthy, but the hidden Tauri window (
E2E runs skip the hold by default so spec boots stay fast and pointer actionability is unaffected; the new |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b3df88985b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| bg = parsed.vars["--background"]; | ||
| if (bg) document.documentElement.style.backgroundColor = `hsl(${bg})`; |
There was a problem hiding this comment.
Apply cached CSS vars before painting the splash
When the cached theme is anything other than the built-in Catppuccin light/dark vars, this only copies --background into html.style.backgroundColor and then adds a light/dark class. Fresh evidence beyond the prior thread is that ThemeProvider.applyCachedVars() reapplies the entire cached vars map (desktop/src/shared/theme/ThemeProvider.tsx:224-228), while body and the new loading gate read var(--background), --chart-*, etc. from CSS variables before React mounts; with a cached Houston/Buzz/custom theme the pre-React paint still uses the static Catppuccin variables and can flash the wrong themed splash until the bundle runs. Seed the cached vars on documentElement.style here before adding the class.
Useful? React with 👍 / 👎.
… survives cold boot A WKWebView born in a hidden Tauri window (visible:false until getCurrentWindow().show()) can lose the race between the window appearing and WebKit being told the view is visible. When that happens — some boots, not others, and inherited by every reload in that webview — the page's rendering scheduler wedges permanently: requestAnimationFrame fires exactly once and never again, CSS/compositor animations never advance, and even timer-driven DOM mutations only reach the screen when something external (user input) forces a flush, while visibilityState still reports "visible". Traced in the real staging app across many boots; no in-page implementation of the splash bee (CSS animation, rAF loop, timer + style writes, timer + SVG attribute mutation) could animate in that state, because every scheduling and flush primitive was dead. Boot the window visible instead. The hidden-window dance existed to hide an unstyled first paint, but index.html now paints the pre-React window in the cached theme background (with dark seeding on first launch), so there is nothing to hide — and a window that is never hidden cannot lose the visibility race. The committed splash implementation (compositor-driven wing flap + minimum-visible splash hold) then works on every boot and reload. getCurrentWindow().show() stays as a harmless no-op safety. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 Cold-boot freeze: actual root cause found and fixed ( The frozen-bee reports traced to a race, not to any animation implementation: a WKWebView born in a hidden Tauri window ( Fix: boot the window visible. The hidden-window dance existed to hide an unstyled first paint, but this branch already paints the pre-React window in the cached theme background via the index.html boot script (with dark seeding on first launch), so there's nothing left to hide — and a window that is never hidden can't lose the race. With that, the committed splash implementation (compositor wing flap + minimum-visible splash hold) works on every cold boot and reload; confirmed across repeated boots on staging. Worth noting for other features: in a wedged instance this race silently kills rAF and all CSS animation app-wide, so the |




What
Puts an animated, wing-flapping Buzz bee on the desktop cold-boot loading gate, over the restored theme-adaptive grainient background — replacing the flat "Setting up your workspace…" text that #1570 left as a static black screen.
ThemeGrainientBackground(orbiting radial gradient driven by theme vars, with aprefers-reduced-motionfallback). The bee is the hero; the "Setting up your workspace…" caption stayssr-only.FlappingBee— the sameBuzzMarksilhouette, with its wings beating on a continuous CSS loop.index.html): paint the pre-React window in the cached theme background instead of black, so light themes don't flash black on launch.Why the wings are HTML-level SVG layers
WebKit (WKWebView) paints SVG children on the main thread, so animating a transform on a wing
<circle>freezes the flap while boot work hogs the thread — exactly when the gate is on screen, so the bee looked static in the real app. Each wing is now its own HTML-level<svg>layer animated via CSS transform; HTML transforms run on the compositor (Core Animation) and keep flapping regardless of main-thread load. Static CSS masks reproduce the slot cutouts so the layered build stays pixel-identical to the masked single-SVG mark (verified 37–39 dB PSNR at rest/mid/tuck).Testing
just cigreen; pre-push clippy + tests green.currentColor, no SMIL).