Skip to content

fix: style screen title casing and google_fonts crash reporting - #295

Merged
richardthe3rd merged 3 commits into
mainfrom
claude/bug-hunt-fY6So
May 19, 2026
Merged

fix: style screen title casing and google_fonts crash reporting#295
richardthe3rd merged 3 commits into
mainfrom
claude/bug-hunt-fY6So

Conversation

@richardthe3rd

@richardthe3rd richardthe3rd commented May 18, 2026

Copy link
Copy Markdown
Owner

Summary

Bug fixes found during a bug hunt against the current main.

1. Style screen shows a lowercase slug instead of the style name (e9de883)

buildStylePath lowercases the style name for canonical URLs, so the router
hands StyleScreen a lowercased value. The screen rendered that raw value in
its header and breadcrumb — tapping the "Golden Ale" chip on a drink landed on
a page titled "golden ale". The display name is now resolved from a matched
drink's original style string; the lowercase value is kept only for URL/lookup.

2. Tasted toggle didn't refresh the list under the "not tasted" filter (1677402)

toggleFavorite re-applies filters when the favourites filter is active, but
toggleTasted did not. Marking a drink tasted while the "Not tasted"
visibility filter was on left it stuck in the visible list until the next
filter/sort/reload. toggleTasted now re-runs filter+sort when the notTasted
filter is active, mirroring toggleFavorite.

3. Transient google_fonts failures reported as fatal crashes (a1b9bd0)

google_fonts downloads fonts over HTTP on first use. A network/CDN failure
throws an uncaught async error that main.dart recorded to Crashlytics with
fatal: true, even though the app keeps running with a fallback font — so a
transient, handled condition was inflating the crash-free metric. Added
isTransientFontLoadError (matches the exception message and google_fonts
stack frames) and both error handlers now record these as non-fatal.

Test plan

  • ./bin/mise run test — full suite passes
  • ./bin/mise run analyze — clean (one pre-existing unrelated info)
  • New StyleScreen test: a lowercase URL param still renders the proper-cased name
  • New BeerProvider test: toggleTasted drops the drink from the list while the not-tasted filter is active
  • New isTransientFontLoadError tests: message detection, stack-frame detection, and that unrelated errors stay fatal
  • Manual: tap a style chip on a drink detail page and confirm the screen title shows proper case
  • Manual: enable "Not tasted", mark a drink tasted, confirm it disappears from the list

https://claude.ai/code/session_0135nVBYGpwkaQvG13XyS66H

claude added 2 commits May 18, 2026 21:12
Style URLs use a lowercase canonical form (buildStylePath), so the
router hands StyleScreen a lowercased style name. The screen rendered
that raw value in its header and breadcrumb, so tapping a "Golden Ale"
chip landed on a page titled "golden ale".

Resolve the display name from a matched drink's original style string
instead, keeping the lowercase value only for URL/lookup purposes.

https://claude.ai/code/session_0135nVBYGpwkaQvG13XyS66H
google_fonts downloads fonts over HTTP on first use. When the device is
offline or the font CDN fails, the load throws an uncaught async error
that PlatformDispatcher.onError recorded to Crashlytics with
fatal: true. The app keeps running with a fallback font, so this is a
transient, non-fatal condition — reporting it as fatal distorts the
crash-free metric.

Classify google_fonts font-fetch failures (by exception message and by
google_fonts stack frames) and record them as non-fatal in both the
Flutter and async error handlers.

https://claude.ai/code/session_0135nVBYGpwkaQvG13XyS66H
Copilot AI review requested due to automatic review settings May 18, 2026 21:37
@richardthe3rd richardthe3rd changed the title fix(style): show original-case style name instead of lowercase URL slug fix: style screen title casing and google_fonts crash reporting May 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a UI regression where StyleScreen displayed the lowercased style value coming from canonicalized style URLs, by resolving and rendering the original mixed-case style name from the matched drinks list. Additionally, this PR changes global Crashlytics error classification to treat certain google_fonts font-load failures as non-fatal, with accompanying unit tests.

Changes:

  • Resolve a mixed-case displayStyle from matching drinks and use it for the StyleScreen header + breadcrumb title.
  • Add a widget test ensuring a lowercase URL param (e.g. ipa) renders as IPA.
  • Downgrade detected google_fonts runtime font-fetch failures to non-fatal Crashlytics reports, and add unit tests for the detection helper.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
lib/screens/style_screen.dart Uses a resolved displayStyle (from matched drink data) for visible UI labels instead of the lowercased route param.
test/style_screen_test.dart Adds coverage to ensure lowercased route params still display the original mixed-case style name.
lib/main.dart Introduces isTransientFontLoadError and uses it to mark some font-load errors as non-fatal in Crashlytics.
test/main_test.dart Adds unit tests for isTransientFontLoadError classification behavior.

Comment thread lib/main.dart
Comment on lines +64 to +73
/// Whether [error] originates from `google_fonts` runtime font fetching.
///
/// google_fonts downloads fonts over HTTP on first use. When the device is
/// offline or the font CDN fails, the load throws an uncaught async error.
/// The app keeps running with a fallback font, so such failures are transient
/// and non-fatal — they must not be recorded to Crashlytics as fatal crashes,
/// which would otherwise distort the crash-free metric.
bool isTransientFontLoadError(Object error, StackTrace? stack) {
if (error.toString().contains('Failed to load font')) return true;
return stack != null && stack.toString().contains('google_fonts');
Comment thread lib/main.dart
Comment on lines +33 to +42
// Pass all uncaught Flutter errors to Crashlytics. Transient google_fonts
// font-fetch failures are downgraded to non-fatal (see
// isTransientFontLoadError).
FlutterError.onError = (details) {
if (isTransientFontLoadError(details.exception, details.stack)) {
FirebaseCrashlytics.instance.recordFlutterError(details);
} else {
FirebaseCrashlytics.instance.recordFlutterFatalError(details);
}
};
@github-actions

github-actions Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

LCOV of commit 1677402 during CI #235

Summary coverage rate:
  lines......: 81.0% (2598 of 3206 lines)
  functions..: no data found
  branches...: no data found

Files changed coverage rate:
                                                      |Lines       |Functions  |Branches    
  Filename                                            |Rate     Num|Rate    Num|Rate     Num
  ==========================================================================================
  lib/main.dart                                       | 0.0%    116|    -     0|    -      0
  lib/providers/beer_provider.dart                    | 0.0%    286|    -     0|    -      0
  lib/screens/style_screen.dart                       | 0.0%     66|    -     0|    -      0

@codecov

codecov Bot commented May 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 62.50000% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
lib/main.dart 33.33% 6 Missing ⚠️

📢 Thoughts on this report? Let us know!

toggleFavorite re-applies filters when the favourites filter is active,
but toggleTasted did not. Marking a drink tasted while the "not tasted"
visibility filter was on left the drink stuck in the visible list until
the next filter, sort or reload.

Re-run filter+sort in toggleTasted when the notTasted filter is active,
mirroring toggleFavorite.

https://claude.ai/code/session_0135nVBYGpwkaQvG13XyS66H
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Cloudflare Pages Preview

Your preview deployment is ready!

Preview URL: https://claude-bug-hunt-fy6so.staging-cambeerfestival.pages.dev

This preview will be automatically updated when you push new commits to this PR.

@richardthe3rd
richardthe3rd merged commit e3fdb5c into main May 19, 2026
10 of 11 checks passed
@richardthe3rd
richardthe3rd deleted the claude/bug-hunt-fY6So branch May 19, 2026 20:40
@github-actions github-actions Bot mentioned this pull request May 19, 2026
richardthe3rd added a commit that referenced this pull request May 19, 2026
* chore: add dart format to pre-commit check and CI

Adds a `format` mise task (`dart format .`) and includes it in the
`check` pre-commit gate. CI gains a `dart format --set-exit-if-changed .`
step before `flutter analyze` so unformatted code is a hard failure on
PRs rather than a silent auto-fix.

The local task reformats in place; CI uses `--set-exit-if-changed` to
fail the build without modifying files.

* style: apply dart format to entire codebase

Bulk-format all Dart files with `dart format .`. No logic changes —
line wrapping, trailing whitespace, and indentation only.

* docs: document dart format --no-deps usage in AGENTS.md

* chore: add dart:format, prettier:format and mise:format tasks

Splits the single `format` task into three named sub-tasks:
- `dart:format` — dart format . (use --no-deps for speed after Dart changes)
- `prettier:format` — Prettier for JS/TS/MJS files
- `mise:format` — mise fmt for mise.toml

The top-level `format` task now depends on all three. CI check
formatting step expanded to cover all three. Prettier added to root
package.json; .prettierignore excludes build/, android/, ios/.

* style: apply prettier to JS/TS/MJS files

* fix: correct CI format check and dart:format task ordering

- Add --output=none to dart format CI check so it doesn't modify
  files (--set-exit-if-changed alone still writes)
- Remove mise fmt --check from CI: mise is not installed in the CI
  environment (setup-flutter-app uses subosito/flutter-action directly)
- Make dart:format depend on generate so mock files are formatted
  after codegen, not before

* style: format files introduced by PR #295 bug fixes

---------

Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot mentioned this pull request May 31, 2026
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.

3 participants