Three info-level lints from CI:
- playlist_card.dart doc comment: "/playlists/<id>" → "/playlists/{id}"
in backticks, since `<id>` was flagged as unintended HTML.
- compact_track_card_test.dart: home: Scaffold(...) is now const, which
propagates const to CompactTrackCard and makes the inner [_track]
implicitly const.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expands the existing single test into four cases:
- 4 placeholder cards in Playlists row when no system playlists exist
- Empty-state copy for each section verbatim against the strings
in HomeScreen
- Real For-You card renders with the system badge when present
- Existing rollups (Recently added / Rediscover) still render correctly
alongside the new providers
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the web CompactTrackCard — small horizontal cell with cover
art (48dp), title, artist. Tap plays from this track in the section.
Width 176dp matches web's compact density so 25 tracks per row scroll
naturally on phone widths.
Cover URL is derived from track.albumId (/api/albums/<id>/cover) since
TrackRef itself doesn't carry a cover field — same pattern as web's
coverUrl() helper.
Used in the next commit's home Most-played section (3 rows × 25);
otherwise unused this slice.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Making the outer FabledSwordTheme(...) and HomeData(...) constructors
const made every inner const redundant — Dart's analyzer fires
unnecessary_const for each. Strip the inner consts so the outer
context owns the const inference.
1. lib/app.dart + lib/shared/routing.dart — buildRouter takes a Ref but was
being called from a ConsumerWidget's build() with a WidgetRef. Add a
routerProvider; the widget watches it instead of constructing the
router from its own ref. Real bug — would have crashed compile in
slice 1, just never compiled until CI ran.
2. lib/player/audio_handler.dart — override of AudioHandler.seek used
`p` for the Duration; rename to `position` to match the base class
(avoid_renaming_method_parameters lint).
3. lib/theme/theme_extension.dart — fromTokens() returned a non-const
constructor; all inputs are const so make the call const too
(prefer_const_constructors).
4. test/library/home_screen_test.dart — same const-constructor lint on
the HomeData test fixture.
5. test/smoke_test.dart — drop the unused
`import 'package:flutter/material.dart'`.
These are exactly the kind of issues the no-in-task-tests rule shifted
to CI; this is the first run that actually exercises the analyzer
against the slice 1 code.
Headers carry placeholder play buttons (wired in Task 18) + room for
LikeButton (Task 16). Artist screen has a 2-column album grid; album
screen has a track list with mm:ss durations. Routes :id-parameterized
under the shell so the PlayerBar persists.
Sections mirror the web home: Recently added · Rediscover (albums +
artists) · Most played · Last played artists. Tap routes pushed for
albums/artists; track-tap is wired in the player task. Pull-to-refresh
re-fetches /api/home.
HorizontalScrollRow takes an optional shared ScrollController so
multi-row sections (Most played: 3 rows) couple their scroll like the
web HorizontalScrollRow.svelte. Cards fall back to the synced
album-fallback.svg when coverUrl is empty.