feat(#402): wire screen-scoped providers to liveEventsProvider
#392's dispatcher only invalidates publicly-importable providers (myQuarantine + home). Screen-scoped providers (file-private in their feature folders) get their own ref.listen(liveEventsProvider, ...) so they go live without needing back-edge dependencies from /shared. Five screens wired: - library_screen.dart _LikedTab — invalidates _likedTracksProvider / _likedAlbumsProvider / _likedArtistsProvider on any of the six track/album/artist like/unlike kinds. - playlist_detail_screen.dart — invalidates playlistDetailProvider(id) on playlist.updated / playlist.tracks_changed matching the visible playlist_id. On playlist.deleted matching the visible id, pops back so the user isn't left staring at a gone playlist. - admin_requests_screen.dart — invalidates adminRequestsProvider on request.status_changed (covers user create/cancel + admin approve/reject + reconciler complete). - admin_quarantine_screen.dart — invalidates adminQuarantineProvider on any quarantine.* event (flag from a user / admin resolve / file delete / lidarr delete). - requests_screen.dart (own requests) — invalidates myRequestsProvider on request.status_changed. Server-side events are user-scoped via publishRequestStatusChanged's row.UserID, so admin actions on someone else's request route to the right stream. History tab is NOT wired (no server-side play.scrobbled event yet — documented in #402 body as deferred until that event ships). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../shared/live_events_provider.dart';
|
||||
import '../shared/widgets/main_app_bar_actions.dart';
|
||||
import '../theme/theme_extension.dart';
|
||||
import 'admin_providers.dart';
|
||||
@@ -12,6 +13,15 @@ class AdminQuarantineScreen extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final fs = Theme.of(context).extension<FabledSwordTheme>()!;
|
||||
// #402 wire-up: any quarantine event (flag from a user / admin
|
||||
// resolve / file delete / lidarr delete) refreshes the admin queue.
|
||||
ref.listen<AsyncValue<LiveEvent>>(liveEventsProvider, (_, next) {
|
||||
final e = next.asData?.value;
|
||||
if (e == null) return;
|
||||
if (e.kind.startsWith('quarantine.')) {
|
||||
ref.invalidate(adminQuarantineProvider);
|
||||
}
|
||||
});
|
||||
final items = ref.watch(adminQuarantineProvider);
|
||||
return Scaffold(
|
||||
backgroundColor: fs.obsidian,
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../models/admin_user.dart';
|
||||
import '../shared/live_events_provider.dart';
|
||||
import '../shared/widgets/main_app_bar_actions.dart';
|
||||
import '../theme/theme_extension.dart';
|
||||
import 'admin_providers.dart';
|
||||
@@ -13,6 +14,15 @@ class AdminRequestsScreen extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final fs = Theme.of(context).extension<FabledSwordTheme>()!;
|
||||
// #402 wire-up: invalidate the admin requests list when a user
|
||||
// creates/cancels/admin approves/rejects/reconciler completes —
|
||||
// request.status_changed covers all of them.
|
||||
ref.listen<AsyncValue<LiveEvent>>(liveEventsProvider, (_, next) {
|
||||
final e = next.asData?.value;
|
||||
if (e?.kind == 'request.status_changed') {
|
||||
ref.invalidate(adminRequestsProvider);
|
||||
}
|
||||
});
|
||||
final requests = ref.watch(adminRequestsProvider);
|
||||
// Best-effort lookup for requester usernames. If the users provider
|
||||
// hasn't loaded yet, valueOrNull is null and rows fall back to the
|
||||
|
||||
Reference in New Issue
Block a user