import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'app_route_observer.dart'; import '../di/injection.dart'; import '../../../features/auth/presentation/bloc/auth_bloc.dart'; import '../../../features/auth/presentation/bloc/auth_state.dart'; import '../../../features/chat/presentation/bloc/chat_bloc.dart'; import 'app_routes.dart'; import 'go_router_refresh_stream.dart'; import '../../../features/auth/presentation/screens/auth_boot_screen.dart'; import '../../../features/auth/presentation/screens/login_screen.dart'; import '../../../features/home/presentation/screens/home_screen.dart'; import '../../../features/messages/presentation/screens/message_invite_list_screen.dart'; import '../../../features/contacts/presentation/screens/contacts_screen.dart'; import '../../../features/contacts/presentation/screens/contact_detail_screen.dart'; import '../../../features/contacts/data/apis/users_api.dart'; import '../../../features/calendar/presentation/screens/calendar_dayweek_screen.dart'; import '../../../features/calendar/presentation/screens/calendar_month_screen.dart'; import '../../../features/calendar/presentation/screens/calendar_event_detail_screen.dart'; import '../../../features/calendar/presentation/screens/calendar_event_create_screen.dart'; import '../../../features/calendar/presentation/screens/calendar_event_edit_screen.dart'; import '../../../features/calendar/presentation/screens/calendar_event_share_screen.dart'; import '../../../features/calendar/presentation/screens/calendar_reminder_alarm_screen.dart'; import '../../../features/calendar/presentation/calendar_time_utils.dart'; import '../../../features/todo/presentation/screens/todo_quadrants_screen.dart'; import '../../../features/todo/presentation/screens/todo_detail_screen.dart'; import '../../../features/todo/presentation/screens/todo_edit_screen.dart'; import '../../../features/settings/presentation/screens/settings_screen.dart'; import '../../../features/settings/presentation/screens/features_screen.dart'; import '../../../features/settings/presentation/screens/job_detail_screen.dart'; import '../../../features/settings/presentation/screens/memory_screen.dart'; import '../../../features/settings/presentation/screens/user_memory_view_screen.dart'; import '../../../features/settings/presentation/screens/work_memory_view_screen.dart'; import '../../../features/settings/presentation/screens/user_memory_detail_screen.dart'; import '../../../features/settings/presentation/screens/work_memory_detail_screen.dart'; import '../../../features/settings/presentation/screens/edit_profile_screen.dart'; import '../services/app_prewarm_orchestrator.dart'; final _homeSecondLevelRoutes = [ AppRoutes.shellCalendarBranch, AppRoutes.calendarMonth, AppRoutes.shellTodoBranch, AppRoutes.settingsMain, ]; final _protectedRoutes = [ ..._homeSecondLevelRoutes, AppRoutes.contactsList, '/contacts/', '/calendar/events', '/calendar/reminders', AppRoutes.settingsFeatures, AppRoutes.settingsMemory, AppRoutes.settingsMemoryUser, AppRoutes.settingsMemoryWork, AppRoutes.settingsMemoryUserEdit, AppRoutes.settingsMemoryWorkEdit, AppRoutes.settingsEditProfile, AppRoutes.messageInviteList, ]; String? resolveAuthRedirect({ required AuthState authState, required String matchedLocation, AppPrewarmOrchestrator? prewarm, }) { final isAuthenticated = authState is AuthAuthenticated; final isAuthChecking = authState is AuthInitial || authState is AuthLoading; final isBootRoute = matchedLocation == AppRoutes.authBoot; final isAuthRoute = matchedLocation == AppRoutes.authLogin || matchedLocation.startsWith('/login'); final isHomeRoute = matchedLocation == AppRoutes.homeMain; final isProtected = isHomeRoute || _protectedRoutes.any((route) => matchedLocation.startsWith(route)); if (isAuthChecking && !isBootRoute) { return AppRoutes.authBoot; } if (!isAuthChecking && isBootRoute) { return isAuthenticated ? AppRoutes.homeMain : AppRoutes.authLogin; } if (!isAuthenticated && isProtected) { return AppRoutes.authLogin; } if (isAuthenticated && isAuthRoute) { return AppRoutes.homeMain; } return null; } Widget buildHomeRouteScreen(AuthState authState) { final userId = authState is AuthAuthenticated ? authState.user.id : null; return BlocProvider.value( value: sl(), child: HomeScreen(initialUserId: userId), ); } GoRouter createAppRouter(AuthBloc authBloc) { final authRefresh = GoRouterRefreshStream(authBloc.stream); final prewarm = sl(); return GoRouter( initialLocation: AppRoutes.authBoot, observers: [appRouteObserver], refreshListenable: Listenable.merge([authRefresh, prewarm]), redirect: (context, state) { return resolveAuthRedirect( authState: authBloc.state, matchedLocation: state.matchedLocation, prewarm: prewarm, ); }, routes: [ GoRoute( path: AppRoutes.authBoot, builder: (context, state) => const AuthBootScreen(), ), GoRoute( path: AppRoutes.calendarEventCreate, builder: (context, state) => CalendarEventCreateScreen( initialDate: parseYmd(state.uri.queryParameters['date']), ), ), GoRoute( path: '/calendar/events/:id', builder: (context, state) => CalendarEventDetailScreen(eventId: state.pathParameters['id']!), ), GoRoute( path: '/calendar/events/:id/edit', builder: (context, state) => CalendarEventEditScreen(eventId: state.pathParameters['id']!), ), GoRoute( path: '/calendar/events/:id/share', builder: (context, state) => CalendarEventShareScreen(eventId: state.pathParameters['id']!), ), GoRoute( path: '/calendar/reminders/:id/alarm', builder: (context, state) => CalendarReminderAlarmScreen(eventId: state.pathParameters['id']!), ), GoRoute( path: AppRoutes.authLogin, builder: (context, state) => const LoginScreen(), ), GoRoute( path: AppRoutes.homeMain, builder: (context, state) => buildHomeRouteScreen(authBloc.state), ), GoRoute( path: AppRoutes.messageInviteList, builder: (context, state) => const MessageInviteListScreen(), ), GoRoute( path: AppRoutes.contactsList, builder: (context, state) => const ContactsScreen(), ), GoRoute( path: '/contacts/:id', builder: (context, state) { final user = state.extra as UserBasicInfo; return ContactDetailScreen(user: user); }, ), GoRoute( path: AppRoutes.calendarDayWeek, builder: (context, state) { final fromHome = state.uri.queryParameters['from'] == 'home'; final initialDate = parseYmd(state.uri.queryParameters['date']); return CalendarDayWeekScreen( initialDate: initialDate, resetToToday: fromHome, ); }, ), GoRoute( path: AppRoutes.calendarMonth, builder: (context, state) { final fromHome = state.uri.queryParameters['from'] == 'home'; return CalendarMonthScreen(resetToToday: fromHome); }, ), GoRoute( path: AppRoutes.todoList, builder: (context, state) => const TodoQuadrantsScreen(), ), GoRoute( path: AppRoutes.todoCreate, builder: (context, state) => const TodoEditScreen.create(), ), GoRoute( path: '/todo/:id', builder: (context, state) => TodoDetailScreen(todoId: state.pathParameters['id']!), ), GoRoute( path: '/todo/:id/edit', builder: (context, state) => TodoEditScreen(todoId: state.pathParameters['id']!), ), GoRoute( path: AppRoutes.settingsMain, builder: (context, state) => const SettingsScreen(), ), GoRoute( path: AppRoutes.settingsFeatures, builder: (context, state) => const FeaturesScreen(), ), GoRoute( path: AppRoutes.settingsJobNew, builder: (context, state) => const JobDetailScreen(), ), GoRoute( path: '/settings/job/:id', builder: (context, state) => JobDetailScreen(jobId: state.pathParameters['id']), ), GoRoute( path: AppRoutes.settingsMemory, builder: (context, state) => const MemoryScreen(), ), GoRoute( path: AppRoutes.settingsMemoryUser, builder: (context, state) => const UserMemoryViewScreen(), ), GoRoute( path: AppRoutes.settingsMemoryWork, builder: (context, state) => const WorkMemoryViewScreen(), ), GoRoute( path: AppRoutes.settingsMemoryUserEdit, builder: (context, state) => const UserMemoryDetailScreen(), ), GoRoute( path: AppRoutes.settingsMemoryWorkEdit, builder: (context, state) => const WorkMemoryDetailScreen(), ), GoRoute( path: AppRoutes.settingsEditProfile, builder: (context, state) => const EditProfileScreen(), ), ], ); }