mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-20 05:28:05 +02:00
La route /dashboard faisait ref.watch(selectedPlaylistProvider) avec le ref du routerProvider : le GoRouter entier dépendait de la playlist. Un choix dans le sélecteur du rail recréait le routeur, reparti de /login puis redirigé vers /playlists. Un Consumer limite la reconstruction à la route, et une clé par IPTV réinitialise les onglets, qui ne chargent leur catalogue qu'en initState. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
125 lines
4.3 KiB
Dart
125 lines
4.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import '../../features/auth/providers/auth_provider.dart';
|
|
import '../../features/auth/screens/login_screen.dart';
|
|
import '../../features/iptv/screens/playlist_selection_screen.dart';
|
|
import '../../features/iptv/screens/dashboard_screen.dart';
|
|
import '../../features/admin/screens/admin_panel.dart';
|
|
import '../../mobile/features/iptv/screens/mobile_playlist_selection_screen.dart';
|
|
import '../../mobile/features/iptv/screens/mobile_dashboard_screen.dart';
|
|
import '../../mobile/features/auth/screens/mobile_login_screen.dart';
|
|
import '../widgets/themed_loading_screen.dart';
|
|
import '../../features/iptv/providers/xtream_provider.dart';
|
|
|
|
final routerProvider = Provider<GoRouter>((ref) {
|
|
return GoRouter(
|
|
initialLocation: '/login',
|
|
refreshListenable: RouterRefreshNotifier(ref),
|
|
redirect: (context, state) {
|
|
final authState = ref.read(authProvider);
|
|
final isLoggedIn = authState.isAuthenticated;
|
|
final isLoginRoute = state.matchedLocation == '/login';
|
|
|
|
// Wait for initial auth check to complete
|
|
if (!authState.isInitialized) {
|
|
return null;
|
|
}
|
|
|
|
// Redirect to login if not authenticated
|
|
if (!isLoggedIn && !isLoginRoute) {
|
|
return '/login';
|
|
}
|
|
|
|
// Redirect to playlists if already logged in and trying to access login
|
|
if (isLoggedIn && isLoginRoute) {
|
|
return '/playlists';
|
|
}
|
|
|
|
// Admin guard for /admin route
|
|
if (state.matchedLocation == '/admin' && !authState.isAdmin) {
|
|
return '/playlists';
|
|
}
|
|
|
|
// If we are on dashboard but have no playlist selected, try to restore it
|
|
if (state.matchedLocation == '/dashboard') {
|
|
final playlist = ref.read(selectedPlaylistProvider);
|
|
if (playlist == null) {
|
|
return '/playlists';
|
|
}
|
|
}
|
|
|
|
return null;
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: '/login',
|
|
builder: (context, state) {
|
|
if (MediaQuery.of(context).size.width < 768) {
|
|
return const MobileLoginScreen();
|
|
}
|
|
return const LoginScreen();
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: '/playlists',
|
|
builder: (context, state) {
|
|
if (MediaQuery.of(context).size.width < 768) {
|
|
return const MobilePlaylistSelectionScreen();
|
|
}
|
|
return const PlaylistSelectionScreen();
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: '/dashboard',
|
|
// Le `ref` du routeur ne doit pas surveiller la playlist : un
|
|
// `ref.watch` ici rend `routerProvider` dépendant de
|
|
// `selectedPlaylistProvider`, si bien que changer d'IPTV depuis le
|
|
// tableau de bord recréait le GoRouter, reparti de `/login` puis
|
|
// redirigé vers `/playlists`. Le `Consumer` limite la reconstruction
|
|
// à cette seule route.
|
|
builder: (context, state) => Consumer(
|
|
builder: (context, ref, _) {
|
|
final playlist = ref.watch(selectedPlaylistProvider);
|
|
if (playlist == null) {
|
|
return const Scaffold(
|
|
body: ThemedLoading(),
|
|
);
|
|
}
|
|
|
|
// Une clé par IPTV : les onglets chargent leur catalogue dans
|
|
// `initState` et ignorent un changement de `playlist`. Sans elle,
|
|
// le tableau de bord garderait le contenu de l'IPTV précédente.
|
|
final key = ValueKey(playlist.id);
|
|
|
|
// Adaptive layout without forcing a router rebuild on every pixel change
|
|
final isMobile = MediaQuery.sizeOf(context).width < 768;
|
|
if (isMobile) {
|
|
return MobileDashboardScreen(key: key, playlist: playlist);
|
|
}
|
|
return DashboardScreen(key: key, playlist: playlist);
|
|
},
|
|
),
|
|
),
|
|
GoRoute(
|
|
path: '/admin',
|
|
builder: (context, state) => const AdminPanel(),
|
|
),
|
|
],
|
|
);
|
|
});
|
|
|
|
/// Notifier that triggers router refresh when auth state or selected playlist changes
|
|
class RouterRefreshNotifier extends ChangeNotifier {
|
|
RouterRefreshNotifier(this._ref) {
|
|
_ref.listen(authProvider, (_, __) {
|
|
notifyListeners();
|
|
});
|
|
_ref.listen(selectedPlaylistProvider, (_, __) {
|
|
notifyListeners();
|
|
});
|
|
}
|
|
|
|
final Ref _ref;
|
|
}
|