feat(flutter): user-facing requests view + cancel (#356)
Closes the cleanest remaining #356 gap — Discover submits Lidarr requests but had no surface for users to view or cancel their own. Admin had it; user didn't. - RequestsApi at lib/api/endpoints/requests.dart — listMine() + cancel(id). Same /api/requests endpoint the web /requests page uses; identical AdminRequest wire shape so the existing model is reused (just augmented with matched_*_id fields for the "Listen" CTA on completed rows). - MyRequestsController mirrors the web's auto-poll (#369 piece already shipped server-side / web-side): 12s refresh while any row is mid-ingest (status='approved'), stops on settle. Riverpod Timer in build() that's cancelled in onDispose. - RequestsScreen with kind/status pills, ingest progress copy, Cancel (with confirm dialog) and Listen CTAs per row state. - Route /requests under the shell. Entry point in settings between Profile and Appearance — "My requests". - Widget tests cover empty / pending / completed / rejected states + the Cancel-confirm dialog. Out of scope this slice: Discover-screen "View your requests" CTA after submitting a new request. Reasonable follow-up but doesn't block the management loop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,9 @@ class AdminRequest {
|
||||
this.notes,
|
||||
required this.importedAlbumCount,
|
||||
required this.importedTrackCount,
|
||||
this.matchedTrackId,
|
||||
this.matchedAlbumId,
|
||||
this.matchedArtistId,
|
||||
});
|
||||
|
||||
final String id;
|
||||
@@ -38,6 +41,13 @@ class AdminRequest {
|
||||
final int importedAlbumCount;
|
||||
final int importedTrackCount;
|
||||
|
||||
/// Set when the ingest matched into the local library. The user-side
|
||||
/// "Listen" CTA on a completed request links to whichever id is set
|
||||
/// (most-specific first: track → album → artist).
|
||||
final String? matchedTrackId;
|
||||
final String? matchedAlbumId;
|
||||
final String? matchedArtistId;
|
||||
|
||||
/// Display label depending on the kind of request — what the user
|
||||
/// asked for. For an album request it's the album title; for an
|
||||
/// artist request it's the artist name; etc.
|
||||
@@ -60,5 +70,8 @@ class AdminRequest {
|
||||
notes: j['notes'] as String?,
|
||||
importedAlbumCount: (j['imported_album_count'] as int?) ?? 0,
|
||||
importedTrackCount: (j['imported_track_count'] as int?) ?? 0,
|
||||
matchedTrackId: j['matched_track_id'] as String?,
|
||||
matchedAlbumId: j['matched_album_id'] as String?,
|
||||
matchedArtistId: j['matched_artist_id'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user