Skip to content

DIVE-3597: kill every remaining bee/Buzz visual (refresh indicator, theme label, iOS icons, dead asset) - #8

Merged
lodar merged 2 commits into
mainfrom
dive-3597-brand-debt
Aug 18, 2026
Merged

DIVE-3597: kill every remaining bee/Buzz visual (refresh indicator, theme label, iOS icons, dead asset)#8
lodar merged 2 commits into
mainfrom
dive-3597-brand-debt

Conversation

@5dive-bot

Copy link
Copy Markdown
Collaborator

Closes DIVE-3597. The byte-verifiable remainder of the rebrand, spec'd from olivia's disclosed
NOT-DONE list on DIVE-3578 plus quinn's grade. No UX changes beyond this scope.

1. No bee renders anywhere in the app

BeeRefreshIndicatorBrandRefreshIndicator, drawing FiveDiveMark — the same alpha-mask
asset the welcome hero uses, so the launcher icon, the onboarding hero and the refresh indicator
are now one mark. All 5 call sites moved (forum, activity ×2, pulse, channels).

flapping_bee.dart and tappable_flapping_bee.dart are now unreferenced and deleted: with
the indicator no longer sharing the painter, the reason the logo pass kept them has expired, and
leaving them compiles ~600 lines of another brand's path geometry into the APK for zero call
sites. Nothing warns about an unreferenced public class in lib/.

The brand-neutral gesture half is carried over verbatim — elastic pull off BouncingScrollPhysics'
negative scroll position, the OverscrollNotification fallback for clamping physics, the retained
72px loading gap, the reveal ramp, RefreshIndicator.noSpinner, and the single medium-impact arm
haptic. What dies with the bee is the easter egg: wing flap, pupils that grow past the arm
point, and the 👀 swap with its repeating selectionClick haptic. Calling that out explicitly
rather than letting a reviewer discover a silently-deleted interaction. It is replaced by a slow
12%-depth breathing pulse while the refresh is in flight, off under disableAnimations.

The test moved with it and keeps a positive assertion (find.byType(FiveDiveMark)) — the old
one asserted FlappingBee.flapAmount/eyeProgress, which the mark does not have, so the
reduced-motion arm is re-expressed as "the brand-refresh-scale transform does not move across a
pump".

2. Theme label — and why the persisted key is NOT renamed

The picker now reads 5dive / 5dive Dark in every mode, including the System-mode row and
the "default" row. That is the DONE line the ticket asked for.

The ticket said to do the full key rename. I did not, deliberately, because the key is not
mobile-private. mobile/lib/shared/theme/community_theme_preference.dart publishes the theme name
to the community relay under d-tag community-theme, and desktop/src/shared/theme/theme-loader.ts
in this same repo holds the same "buzz" catalog key. Both ends validate the name against
their own catalog and discard a preference naming a theme they do not know — mobile's
CommunityThemePreference.fromJson throws FormatException the moment findTheme() returns null.

So a mobile-only rename breaks it in both directions at once: mobile drops every stored/remote
preference that still says 'buzz', and Buzz Desktop drops every preference mobile writes saying
'5dive'. Nothing errors visibly; the palette just silently reverts on whichever client you are
not looking at. That is a cross-client wire break, not an internal rename — the wiki's §6 framed
this choice as mobile-internal and it is not.

What is here instead is a third shape that carries zero wire risk: one
themeDisplayNameOverrides map in theme_catalog.dart, consumed by both derivation sites —
ThemeColors.displayName (the explicit Light/Dark rows) and pairedThemeLabel (the
System-mode row) — plus defaultSchemeDisplayName. Wiring only one of the two would reproduce
exactly the two-names-for-one-palette bug §6 warns about. A real key rename is a
mobile + desktop + migration change and wants its own row.

Note themeGroups() sorts by displayName, so the override changes sort position: '5dive'
still sorts first (digits precede letters), which is what "Buzz leads the map" wanted, and the
theme_pairs_test arms that assert display-name ordering and paired.first.name still hold.

3. iOS AppIcon regenerated

All 15 distinct files regenerated from app/public/icon-512.png. iOS icons are opaque RGB
alpha is rejected — so this inverts the launcher recipe: it is a flatten, not a cut-out. The
source is composited onto its own background colour, sampled inside the rounded square
((20, 256)#1A1A1F) rather than at a corner, which is transparent.

Guards, because both failure modes here write a valid PNG and print nothing:

  • background sample asserted opaque before use;
  • flattened two-colour census: (26,26,31) × 237464 and (255,255,255) × 23468 on 512²;
  • near-white ("5") pixel count 23820, asserted > 5000 — the glyph survived and the square is
    not one flat colour;
  • every output re-opened and asserted size == (n, n) and mode == 'RGB'.

Contents.json has 19 entries but only 15 distinct filenames (iPhone/iPad share several), so the
loop is driven off a filename→size map with each filename asserted to resolve to exactly one size.

4. Dead asset

mobile/assets/images/buzz-icon.png removed from the tree and from pubspec.yaml; nothing in
lib/ referenced it and it was shipping in the APK. Zero buzz-icon references remain anywhere.

Checks

Ran on this host:

  • bash scripts/test-mobile-worktree-overrides.shall mobile worktree identity contract checks passed (read the pass line, not $? through a pipe).
  • grep: zero bee / FlappingBee / BeeRefresh references left in mobile/lib or mobile/test.
  • grep: zero buzz-icon references in the tree.
  • line-width sweep on every new and edited Dart file, since a red Format check leaves Analyze,
    Test and Build skipped in the same job and a skipped step reads as "not failing".

Not run here: dart format, flutter analyze, flutter test — there is no Flutter on the
agent hosts. CI's Mobile job is the check; read its per-step conclusions, not the run's.

🤖 Generated with Claude Code

lodar and others added 2 commits August 18, 2026 21:25
…eme label, iOS icons, dead asset)

- pull-to-refresh now renders the 5dive mark: BeeRefreshIndicator ->
  BrandRefreshIndicator across all 5 call sites, with flapping_bee.dart and
  tappable_flapping_bee.dart (now unreferenced) deleted, so no bee geometry
  ships in the APK at all.
- theme picker reads '5dive' / '5dive Dark' everywhere, via one override map
  consumed by both ThemeColors.displayName and pairedThemeLabel. The persisted
  'buzz' key is unchanged deliberately: it is a wire value published to the
  community relay and read back by Buzz Desktop, whose catalog rejects a theme
  name it does not know.
- iOS AppIcon regenerated from app/public/icon-512.png (15 files, all opaque
  RGB, glyph 9% of pixels).
- mobile/assets/images/buzz-icon.png removed from the tree and pubspec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… style drops the trailing comma when it fits)
@lodar
lodar merged commit 6566672 into main Aug 18, 2026
23 checks passed
@lodar
lodar deleted the dive-3597-brand-debt branch August 24, 2026 04:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants