import 'dart:async'; import 'package:flutter/widgets.dart'; import 'package:go_router/go_router.dart'; import 'session/session_cubit.dart'; import 'session/session_state.dart'; import '../features/auth/view/login_page.dart'; import '../features/auth/view/profile_page.dart'; import '../features/rating/data/rating_repository.dart'; import '../features/rating/view/rating_page.dart'; import '../features/trip/view/duty_page.dart'; import '../features/wallet/view/earnings_page.dart'; import '../features/splash/view/splash_page.dart'; import 'di.dart'; class Routes { const Routes._(); static const splash = '/'; static const login = '/login'; static const profile = '/profile'; static const home = '/home'; static const rating = '/rating'; static const wallet = '/wallet'; } /// التوجيه يُشتقّ من `SessionCubit` وحده — لا `Navigator.push` بعد الدخول /// موزّعة في الشاشات، فلا تتناقض حالتان. final appRouter = GoRouter( initialLocation: Routes.splash, refreshListenable: _CubitListenable(sl().stream), redirect: (context, state) { final session = sl().state; final loc = state.matchedLocation; // قبل أن نعرف: نبقى على الإقلاع ولا نقرّر شيئاً. if (!session.isReady) return loc == Routes.splash ? null : Routes.splash; return switch (session.status) { SessionStatus.unauthenticated => loc == Routes.login ? null : Routes.login, SessionStatus.needsProfile => loc == Routes.profile ? null : Routes.profile, // التقييم المعلّق يحجز التطبيق كله: لا شاشة أخرى قبل حسمه // (docs/38 §7 — يُفرض عند الفتح). SessionStatus.authenticated when session.pendingRating != null => loc == Routes.rating ? null : Routes.rating, SessionStatus.authenticated => (loc == Routes.login || loc == Routes.profile || loc == Routes.splash || loc == Routes.rating) ? Routes.home : null, SessionStatus.unknown => Routes.splash, }; }, routes: [ GoRoute( path: Routes.splash, builder: (context, state) => const SplashPage(), ), GoRoute( path: Routes.login, builder: (context, state) => const LoginPage(), ), GoRoute( path: Routes.profile, builder: (context, state) => const ProfilePage(), ), GoRoute( path: Routes.rating, builder: (context, state) { final pending = sl().state.pendingRating!; return RatingPage( pending: PendingRating( tripId: pending.tripId, role: pending.role, ), onDone: sl().onRatingResolved, ); }, ), GoRoute( path: Routes.wallet, builder: (context, state) => const EarningsPage(), ), GoRoute( path: Routes.home, builder: (context, state) => const DutyPage(), ), ], ); /// جسر بين تيّار الـCubit و`refreshListenable` الذي يطلبه go_router. class _CubitListenable extends ChangeNotifier { _CubitListenable(Stream stream) { _sub = stream.listen((_) => notifyListeners()); } late final StreamSubscription _sub; @override void dispose() { _sub.cancel(); super.dispose(); } }