From c145037aad121bb9f6fd6e9068ff3cf77fb86a48 Mon Sep 17 00:00:00 2001 From: klopez4212 Date: Wed, 8 Jul 2026 18:25:03 +0100 Subject: [PATCH] feat(desktop): flapping bee on the setup loading screen (#1631) Signed-off-by: Fizz <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co> Signed-off-by: klopez4212 Co-authored-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Claude Fable 5 --- desktop/index.html | 42 ++- desktop/playwright.config.ts | 1 + desktop/src-tauri/tauri.conf.json | 2 +- desktop/src/app/App.tsx | 123 +++++++- desktop/src/app/ThemeGrainientBackground.tsx | 12 + .../src/shared/styles/globals/animations.css | 277 ++++++++++++++++++ .../src/shared/ui/buzz-logo/FlappingBee.tsx | 117 ++++++++ desktop/tests/e2e/boot-splash.spec.ts | 57 ++++ desktop/tests/e2e/onboarding.spec.ts | 54 ++-- 9 files changed, 651 insertions(+), 34 deletions(-) create mode 100644 desktop/src/app/ThemeGrainientBackground.tsx create mode 100644 desktop/src/shared/ui/buzz-logo/FlappingBee.tsx create mode 100644 desktop/tests/e2e/boot-splash.spec.ts diff --git a/desktop/index.html b/desktop/index.html index 31d90dc4d..c219f214d 100644 --- a/desktop/index.html +++ b/desktop/index.html @@ -6,18 +6,48 @@ + diff --git a/desktop/playwright.config.ts b/desktop/playwright.config.ts index 178cd47c3..440d8fac5 100644 --- a/desktop/playwright.config.ts +++ b/desktop/playwright.config.ts @@ -61,6 +61,7 @@ export default defineConfig({ "**/top-chrome-zoom-clearance.spec.ts", "**/thread-unread.spec.ts", "**/workspace-rail.spec.ts", + "**/boot-splash.spec.ts", "**/thread-reply-anchor-roleplay.spec.ts", "**/threadpane-ultrawide.spec.ts", "**/animated-avatar.spec.ts", diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index c33f3443b..7bcc434f7 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -20,7 +20,7 @@ "width": 800, "height": 600, "maximized": true, - "visible": false, + "visible": true, "backgroundColor": "#000000", "titleBarStyle": "Overlay", "hiddenTitle": true, diff --git a/desktop/src/app/App.tsx b/desktop/src/app/App.tsx index c3624af24..a830cfd2e 100644 --- a/desktop/src/app/App.tsx +++ b/desktop/src/app/App.tsx @@ -12,6 +12,7 @@ import { } from "react"; import { router } from "@/app/router"; +import { ThemeGrainientBackground } from "@/app/ThemeGrainientBackground"; import { useReloadShortcut } from "@/app/useReloadShortcut"; import { useAppOnboardingState } from "@/features/onboarding/hooks"; import { OnboardingSlideTransition } from "@/features/onboarding/ui/OnboardingSlideTransition"; @@ -25,27 +26,108 @@ import { createBuzzQueryClient } from "@/shared/api/queryClient"; import { isSharedIdentity as isSharedIdentityCmd } from "@/shared/api/tauri"; import { listenForDeepLinks } from "@/shared/deep-link"; import { useSystemColorScheme } from "@/shared/theme/useSystemColorScheme"; +import { cn } from "@/shared/lib/cn"; import { Button } from "@/shared/ui/button"; import { BuzzMark } from "@/shared/ui/buzz-logo/BuzzMark"; -import { Spinner } from "@/shared/ui/spinner"; +import { FlappingBee } from "@/shared/ui/buzz-logo/FlappingBee"; +import { FuzzyLogo } from "@/shared/ui/buzz-logo/FuzzyLogo"; import { StartupWindowDragRegion } from "@/shared/ui/StartupWindowDragRegion"; import { StepProgress } from "@/shared/ui/step-progress"; const LOADING_TEXT = "Setting up your workspace..."; -// Cold boot gate: a plain static Buzz mark (#D7D72E) on solid black. No -// animation machinery, no gradient — the mark must paint complete on the very -// first frame, even in webviews that render before scripting or SMIL start. +// Minimum time the cold-boot splash stays on screen. A real boot resolves the +// workspace in well under 100ms, and the hidden Tauri window (visible:false +// until getCurrentWindow().show()) takes longer than that to put its first +// frame on screen — without a hold, the bee is unmounted before it is ever +// visible. The hold runs as an overlay above the already-mounted app, so +// time-to-interactive is unchanged; only the reveal waits. +const BOOT_SPLASH_MIN_VISIBLE_MS = 1_200; +const BOOT_SPLASH_FADE_MS = 200; + +type BootSplashPhase = "holding" | "fading" | "done"; + +// E2E runs skip the hold (it would slow every spec's boot and block pointer +// actionability); a spec can opt back in via __BUZZ_E2E__.bootSplashHoldMs. +function bootSplashHoldMs(): number { + const e2e = ( + window as Window & { + __BUZZ_E2E__?: { bootSplashHoldMs?: number }; + } + ).__BUZZ_E2E__; + if (e2e) { + return e2e.bootSplashHoldMs ?? 0; + } + return BOOT_SPLASH_MIN_VISIBLE_MS; +} + +function useBootSplashHold(): BootSplashPhase { + const [phase, setPhase] = useState(() => + bootSplashHoldMs() > 0 ? "holding" : "done", + ); + + useEffect(() => { + const holdMs = bootSplashHoldMs(); + if (holdMs <= 0) { + return; + } + const fadeTimer = window.setTimeout(() => setPhase("fading"), holdMs); + const doneTimer = window.setTimeout( + () => setPhase("done"), + holdMs + BOOT_SPLASH_FADE_MS, + ); + return () => { + window.clearTimeout(fadeTimer); + window.clearTimeout(doneTimer); + }; + }, []); + + return phase; +} + +// Animated Buzz mark for the loading gates. The static BuzzMark renders in +// normal flow and sizes the box — it's plain SVG (no JS/SMIL), so it paints on +// the very first frame even before scripting starts, avoiding a blank flash on +// hard reload. The animated FuzzyLogo is layered on top and takes over once it +// begins playing. +function BeeLoader({ + ariaLabel, + className, + tintClassName = "text-foreground", +}: { + ariaLabel: string; + className?: string; + tintClassName?: string; +}) { + return ( +
+ + +
+ ); +} + +// Cold boot gate: the theme-adaptive grainient background with a single +// centered Buzz bee flying over it — the same static mark as before, now with +// its wings flapping (ported from the Buzz website's wing-flap). Replaces the +// old "Setting up your workspace" text, which stays as an sr-only caption. function AppLoadingGate() { return (
+ {LOADING_TEXT} - +
); } @@ -69,7 +151,11 @@ function WorkspaceSwitchGate() { Switching workspace… {showSpinner ? ( -