Skip to content

Replace artist popup menu with a full action sheet#191

Merged
phanan merged 3 commits into
masterfrom
feat/artist-action-sheet
May 2, 2026
Merged

Replace artist popup menu with a full action sheet#191
phanan merged 3 commits into
masterfrom
feat/artist-action-sheet

Conversation

@phanan
Copy link
Copy Markdown
Member

@phanan phanan commented May 2, 2026

Summary

  • Mirrors the album action sheet from Replace album popup menu with a full action sheet #190 for artists. The long-press on artist cards and rows now opens an Apple-Music-style sheet with thumbnail, name, a Favorite / Play All / Shuffle All quick-action row, and Play Next / Play Last / Edit list rows.
  • No "Go to Artist" row, since the user is already acting on an artist.
  • Adds the optimistic Artist.favorite toggle with the koel >= 7.11.0 feature gate (the favorite quick action is hidden on older servers).
  • Removes the old artist_actions_menu.dart popup.

Test plan

  • flutter test — all 297 tests pass, including new model + sheet coverage.
  • Long-press an artist card and an artist row on a fresh-master server, exercise each action.
  • Long-press on an older koel: Favorite quick action is hidden, the rest still works.
  • Long-press an artist that's read-only: Edit row is hidden.

Summary by CodeRabbit

  • New Features

    • Artists can be marked favorite with a quick-toggle (optimistic update).
  • UI

    • New artist action sheet replaces the old long-press menu.
    • Actions: Play All, Shuffle All, Play Next, Play Last, Favorite/Undo, and Edit… when allowed.
    • Favorite button is shown only on supported app versions.
  • Tests

    • Added tests for artist favorites, merging behavior, and the artist action sheet interactions.

Mirrors the album action sheet (#190) for artists: a Music-style
sheet with thumbnail, name, the Favorite/Play All/Shuffle All quick
row, and Play Next / Play Last / Edit list rows. There's no
"Go to Artist" row since the user is already acting on an artist.

Adds the optimistic favorite toggle on Artist + ArtistProvider with
the koel >= 7.11.0 feature gate, and removes the old long-press
popup menu (artist_actions_menu.dart).
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 2, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Artist gains a persistent favorite boolean (model, JSON, factory, merge). ArtistProvider adds optimistic toggleFavorite. A new ArtistActionSheet replaces the old long-press menu, wiring play/queue/favorite/edit flows; UI exports, widgets, and tests/mocks updated accordingly.

Changes

Artist favorite + action sheet

Layer / File(s) Summary
Data Shape
lib/models/artist.dart
Adds bool favorite field (default false); constructor and Artist.fake accept favorite; fromJson reads json['favorite'] == true; merge(Artist remote) copies favorite.
Provider / API
lib/providers/artist_provider.dart
Adds Future<void> toggleFavorite(Artist artist) performing an optimistic flip, notifyListeners(), POST to favorites/toggle, and revert/throw on failure.
Core UI Component
lib/ui/screens/artist_action_sheet.dart
New ArtistActionSheet widget and showArtistActionSheet wrapper. Fetches playables via PlayableProvider.fetchForArtist, offers favorite toggle (feature-gated), Play All/Shuffle (replace queue), Play Next (queueAfterCurrent using reversed order), Play Last (queueToBottom), optional Edit flow, and overlay confirmations.
Integration / Wiring
lib/ui/screens/artists.dart, lib/ui/widgets/artist_card.dart
Long-press handlers changed to call showArtistActionSheet(context, artist: artist); removed per-tap-position capture and old long-press menu invocations.
Exports & Cleanup
lib/ui/screens/screens.dart, lib/ui/widgets/widgets.dart, lib/ui/widgets/artist_actions_menu.dart
Added artist_action_sheet.dart to screens barrel export; removed artist_actions_menu.dart file and its export from widgets barrel.
Tests & Mocks
test/models/artist_test.dart, test/ui/screens/artist_action_sheet_test.dart, test/ui/screens/artist_action_sheet_test.mocks.dart, test/ui/widgets/artist_card_test.{dart,mocks.dart}, test/ui/widgets/artist_row_test.dart
Model tests added for favorite parsing and merge. New comprehensive widget tests for ArtistActionSheet (structure, action delegation, queue semantics, API-version gating). Generated mocks for action sheet tests added. Old long-press/menu tests removed or reduced; some mock generation trimmed accordingly.

Sequence Diagram

sequenceDiagram
    participant User as User / UI
    participant Sheet as ArtistActionSheet
    participant Provider as ArtistProvider
    participant API as API Server
    participant State as AppState

    User->>Sheet: Tap favorite button
    Sheet->>Sheet: Flip artist.favorite (optimistic)
    Sheet->>State: notifyListeners()
    Sheet->>Provider: toggleFavorite(artist)
    Provider->>API: POST /favorites/toggle
    alt success
        API-->>Provider: 200 OK
        Provider-->>Sheet: completes
    else failure
        API-->>Provider: Error
        Provider->>Sheet: revert favorite, notifyListeners(), rethrow
    end
Loading
sequenceDiagram
    participant User as User / UI
    participant Sheet as ArtistActionSheet
    participant Playable as PlayableProvider
    participant Audio as KoelAudioHandler
    participant Overlay as Overlay Feedback

    User->>Sheet: Tap "Play All" / "Shuffle All"
    Sheet->>Sheet: Dismiss sheet
    Sheet->>Playable: fetchForArtist(id)
    Playable-->>Sheet: songs[]
    Sheet->>Audio: replaceQueue(songs, shuffle: true/false)
    Sheet->>Overlay: show confirmation (auto-dismiss)
    Note over Sheet,Audio: Play Next / Play Last variations
    User->>Sheet: Tap "Play Next"
    loop for each song in songs.reversed
        Sheet->>Audio: queueAfterCurrent(song)
    end
    User->>Sheet: Tap "Play Last"
    loop for each song in songs
        Sheet->>Audio: queueToBottom(song)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop with joy, a little heart aflutter,
A favorite flag now tucked beneath the cover,
Sheets slide up, queues dance in merry line,
Old menus rest — new actions shine! ✨🎶

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately describes the main change: replacing the artist popup menu UI with a new action sheet implementation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/artist-action-sheet

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 6/8 reviews remaining, refill in 11 minutes and 20 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/ui/screens/artist_action_sheet_test.dart (1)

94-97: ⚡ Quick win

Consider adding an action test for tapping "Edit…".

The structure tests verify the Edit… row is conditionally visible, but there's no interaction test asserting what happens when it's tapped (e.g., navigation to an edit screen or opening an edit dialog). This is the only action row that lacks a corresponding test in the actions group — Play Next/Play Last/Play All/Shuffle All/Favorite all have them.

✅ Suggested addition to the `actions` group
// Requires a MockAppRouter (or equivalent) injected via the mount helper,
// and a stub/verify on the navigation call triggered by tapping Edit.
testWidgets('tapping Edit navigates to the artist edit screen',
    (tester) async {
  final artist = Artist.fake(name: 'Editable', canEdit: true);
  // stub router or dialog expectation here
  await mount(tester, artist);
  await tester.tap(find.text('Edit…'));
  await tester.pumpAndSettle();
  // verify navigation / dialog was shown
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/ui/screens/artist_action_sheet_test.dart` around lines 94 - 97, Add an
interaction test to the existing actions group that mounts the sheet with
Artist.fake(name: 'Editable', canEdit: true) using the same mount helper,
stubs/injects a MockAppRouter (or equivalent) used by the widget, simulates
tapping the 'Edit…' row via tester.tap(find.text('Edit…')) and
tester.pumpAndSettle(), and then verifies the expected navigation or dialog call
was made on the router (or the dialog was shown); reference the existing
testWidgets harness and mount helper so the new test mirrors the other action
tests (e.g., Play Next/Play Last) and asserts the router/navigation method was
invoked for the edit flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/ui/screens/artist_action_sheet.dart`:
- Around line 90-93: The onTap currently calls
artistProvider.toggleFavorite(artist) without awaiting or handling its Future,
which lets toggleFavorite's rethrow produce an unhandled Future error; update
the onTap handler (where Navigator.pop(context) and
artistProvider.toggleFavorite(artist) are called) to either make the onTap async
and await artistProvider.toggleFavorite(artist) inside a try/catch, or append a
.catchError(...) to the returned Future to swallow/log the error (and optionally
show user feedback), ensuring toggleFavorite's exceptions are consumed.

---

Nitpick comments:
In `@test/ui/screens/artist_action_sheet_test.dart`:
- Around line 94-97: Add an interaction test to the existing actions group that
mounts the sheet with Artist.fake(name: 'Editable', canEdit: true) using the
same mount helper, stubs/injects a MockAppRouter (or equivalent) used by the
widget, simulates tapping the 'Edit…' row via tester.tap(find.text('Edit…')) and
tester.pumpAndSettle(), and then verifies the expected navigation or dialog call
was made on the router (or the dialog was shown); reference the existing
testWidgets harness and mount helper so the new test mirrors the other action
tests (e.g., Play Next/Play Last) and asserts the router/navigation method was
invoked for the edit flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 172d2fb2-8076-44cc-a507-4737082d2601

📥 Commits

Reviewing files that changed from the base of the PR and between 4c1ae08 and 7403ee0.

📒 Files selected for processing (14)
  • lib/models/artist.dart
  • lib/providers/artist_provider.dart
  • lib/ui/screens/artist_action_sheet.dart
  • lib/ui/screens/artists.dart
  • lib/ui/screens/screens.dart
  • lib/ui/widgets/artist_actions_menu.dart
  • lib/ui/widgets/artist_card.dart
  • lib/ui/widgets/widgets.dart
  • test/models/artist_test.dart
  • test/ui/screens/artist_action_sheet_test.dart
  • test/ui/screens/artist_action_sheet_test.mocks.dart
  • test/ui/widgets/artist_card_test.dart
  • test/ui/widgets/artist_card_test.mocks.dart
  • test/ui/widgets/artist_row_test.dart
💤 Files with no reviewable changes (3)
  • lib/ui/widgets/widgets.dart
  • lib/ui/widgets/artist_actions_menu.dart
  • test/ui/widgets/artist_row_test.dart

Comment thread lib/ui/screens/artist_action_sheet.dart
@phanan phanan merged commit 85abbf4 into master May 2, 2026
1 of 2 checks passed
@phanan phanan deleted the feat/artist-action-sheet branch May 2, 2026 10:02
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.

1 participant