feat(engine): one-shot What's-new card after updates (Phase I) #180

Merged
funman300 merged 1 commits from feat/whats-new-card into master 2026-07-14 01:43:47 +00:00
Owner

First Phase I item from docs/ui-redesign-2026-07.md — and directly motivated by today: four releases shipped whose features nobody would discover on their own (ObtainX updates are silent).

How it works

  • On the first launch where the running release differs from the new Settings::last_seen_whats_new, a dismissible card summarises the latest changelog section. "Got it" or Esc dismisses; the seen-version stamp persists on spawn, so the card can never nag twice even if the app dies with it open.
  • Version source = the embedded CHANGELOG.md (include_str!, §4.2-compliant): its topmost ## [x.y.z] section provides both the card content and the app's release identity. No build-time version plumbing — the APK's versionName never reaches Rust and the workspace Cargo version is static (0.1.0; the splash's env!(CARGO_PKG_VERSION) display has been wrong forever, separate cleanup).
  • Card content: ### Internal sections dropped (players don't care about CI), each bullet reduced to its bold lead sentence, capped at 8.
  • Launch beat: splash → onboarding (first run only) → what's-new → Home. spawn_home_on_launch waits on the new WhatsNewPending resource exactly like it waits for onboarding. Fresh installs never see the card — onboarding completion stamps the current version silently.
  • Deliberately not ScrimDismissible: scrim-tap despawns without running the close handler, which would hold the launch beat forever.

Tests

8 new — changelog parsing (synthetic + the real embedded file), upgrade-shows/seen-skips/fresh-install-never gating, beat release on dismissal. Full workspace + clippy green. Emulator smoke skipped for this one: simulating an upgrade needs on-device settings surgery, and the gating logic is exactly what the unit tests pin down.

Remaining Phase I: contextual one-time tips (first stall → hint tip, first long-press stack → radial tip).

🤖 Generated with Claude Code

First Phase I item from docs/ui-redesign-2026-07.md — and directly motivated by today: four releases shipped whose features nobody would discover on their own (ObtainX updates are silent). ## How it works - On the first launch where the running release differs from the new `Settings::last_seen_whats_new`, a dismissible card summarises the latest changelog section. "Got it" or Esc dismisses; the seen-version stamp persists **on spawn**, so the card can never nag twice even if the app dies with it open. - **Version source = the embedded `CHANGELOG.md`** (`include_str!`, §4.2-compliant): its topmost `## [x.y.z]` section provides both the card content and the app's release identity. No build-time version plumbing — the APK's `versionName` never reaches Rust and the workspace Cargo version is static (`0.1.0`; the splash's `env!(CARGO_PKG_VERSION)` display has been wrong forever, separate cleanup). - Card content: `### Internal` sections dropped (players don't care about CI), each bullet reduced to its bold lead sentence, capped at 8. - **Launch beat**: splash → onboarding (first run only) → what's-new → Home. `spawn_home_on_launch` waits on the new `WhatsNewPending` resource exactly like it waits for onboarding. Fresh installs never see the card — onboarding completion stamps the current version silently. - Deliberately **not** `ScrimDismissible`: scrim-tap despawns without running the close handler, which would hold the launch beat forever. ## Tests 8 new — changelog parsing (synthetic + the real embedded file), upgrade-shows/seen-skips/fresh-install-never gating, beat release on dismissal. Full workspace + clippy green. Emulator smoke skipped for this one: simulating an upgrade needs on-device settings surgery, and the gating logic is exactly what the unit tests pin down. Remaining Phase I: contextual one-time tips (first stall → hint tip, first long-press stack → radial tip). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
funman300 added 1 commit 2026-07-14 01:05:38 +00:00
feat(engine): one-shot What's-new card after updates (Phase I)
Test / fmt (pull_request) Successful in 5s
Test / test (pull_request) Successful in 5m0s
25f1fd27d9
ObtainX updates install silently, so shipped features went unnoticed.
On the first launch where the running release differs from the new
Settings::last_seen_whats_new, a dismissible card summarises the
latest CHANGELOG.md section (embedded; its top version doubles as the
app's release identity — no build-time version plumbing). Internal
sections are dropped and bullets reduce to their bold lead sentence.

Launch beat: splash -> onboarding (first run) -> what's-new -> Home;
spawn_home_on_launch waits on the new WhatsNewPending resource. Fresh
installs never see the card — onboarding completion stamps the current
version silently. The seen-stamp persists on spawn, not dismissal, so
the card can never nag twice.

8 new tests (changelog parsing incl. the real embedded file, upgrade/
seen/fresh-install gating, dismissal). Workspace + clippy green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
funman300 merged commit 19ddf86c7b into master 2026-07-14 01:43:47 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#180