@@ -6,6 +6,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
66import 'package:flutter_news_app_mobile_client_full_source_code/account/view/manage_followed_items/countries/add_country_to_follow_page.dart' ;
77import 'package:flutter_news_app_mobile_client_full_source_code/account/view/manage_followed_items/countries/followed_countries_list_page.dart' ;
88import 'package:flutter_news_app_mobile_client_full_source_code/account/view/manage_followed_items/manage_followed_items_page.dart' ;
9+ import 'package:flutter_news_app_mobile_client_full_source_code/account/view/account_page.dart' ;
910import 'package:flutter_news_app_mobile_client_full_source_code/account/view/manage_followed_items/sources/add_source_to_follow_page.dart' ;
1011import 'package:flutter_news_app_mobile_client_full_source_code/account/view/manage_followed_items/sources/followed_sources_list_page.dart' ;
1112import 'package:flutter_news_app_mobile_client_full_source_code/account/view/manage_followed_items/topics/add_topic_to_follow_page.dart' ;
@@ -228,6 +229,171 @@ GoRouter createRouter({
228229 ),
229230 ],
230231 ),
232+ // --- Account Routes (Top-Level Modal) ---
233+ // This route defines the main '/account' page as a full-screen modal.
234+ // All other account-related pages (settings, saved items, etc.) are
235+ // defined as sub-routes of this page, creating a unified navigation
236+ // stack for the entire account section.
237+ GoRoute (
238+ path: Routes .account,
239+ name: Routes .accountName,
240+ pageBuilder: (context, state) =>
241+ const MaterialPage (fullscreenDialog: true , child: AccountPage ()),
242+ routes: [
243+ // ShellRoute for settings to provide SettingsBloc to children
244+ ShellRoute (
245+ builder: (BuildContext context, GoRouterState state, Widget child) {
246+ final appBloc = context.read <AppBloc >();
247+ final userId = appBloc.state.user? .id;
248+
249+ return BlocProvider <SettingsBloc >(
250+ create: (context) {
251+ final settingsBloc = SettingsBloc (
252+ userAppSettingsRepository: context
253+ .read <DataRepository <UserAppSettings >>(),
254+ inlineAdCacheService: inlineAdCacheService,
255+ );
256+ if (userId != null ) {
257+ settingsBloc.add (SettingsLoadRequested (userId: userId));
258+ } else {
259+ logger.warning (
260+ 'User ID is null when creating SettingsBloc. '
261+ 'Settings will not be loaded.' ,
262+ );
263+ }
264+ return settingsBloc;
265+ },
266+ child: child,
267+ );
268+ },
269+ routes: [
270+ GoRoute (
271+ path: Routes .settings,
272+ name: Routes .settingsName,
273+ builder: (context, state) => const SettingsPage (),
274+ routes: [
275+ GoRoute (
276+ path: Routes .settingsAppearance,
277+ name: Routes .settingsAppearanceName,
278+ builder: (context, state) => const AppearanceSettingsPage (),
279+ routes: [
280+ GoRoute (
281+ path: Routes .settingsAppearanceTheme,
282+ name: Routes .settingsAppearanceThemeName,
283+ builder: (context, state) => const ThemeSettingsPage (),
284+ ),
285+ GoRoute (
286+ path: Routes .settingsAppearanceFont,
287+ name: Routes .settingsAppearanceFontName,
288+ builder: (context, state) => const FontSettingsPage (),
289+ ),
290+ ],
291+ ),
292+ GoRoute (
293+ path: Routes .settingsFeed,
294+ name: Routes .settingsFeedName,
295+ builder: (context, state) => const FeedSettingsPage (),
296+ ),
297+ GoRoute (
298+ path: Routes .settingsNotifications,
299+ name: Routes .settingsNotificationsName,
300+ builder: (context, state) =>
301+ const NotificationSettingsPage (),
302+ ),
303+ GoRoute (
304+ path: Routes .settingsLanguage,
305+ name: Routes .settingsLanguageName,
306+ builder: (context, state) => const LanguageSettingsPage (),
307+ ),
308+ ],
309+ ),
310+ ],
311+ ),
312+ GoRoute (
313+ path: Routes .manageFollowedItems,
314+ name: Routes .manageFollowedItemsName,
315+ builder: (context, state) => const ManageFollowedItemsPage (),
316+ routes: [
317+ GoRoute (
318+ path: Routes .followedTopicsList,
319+ name: Routes .followedTopicsListName,
320+ builder: (context, state) => const FollowedTopicsListPage (),
321+ routes: [
322+ GoRoute (
323+ path: Routes .addTopicToFollow,
324+ name: Routes .addTopicToFollowName,
325+ builder: (context, state) => const AddTopicToFollowPage (),
326+ ),
327+ ],
328+ ),
329+ GoRoute (
330+ path: Routes .followedSourcesList,
331+ name: Routes .followedSourcesListName,
332+ builder: (context, state) => const FollowedSourcesListPage (),
333+ routes: [
334+ GoRoute (
335+ path: Routes .addSourceToFollow,
336+ name: Routes .addSourceToFollowName,
337+ builder: (context, state) => const AddSourceToFollowPage (),
338+ ),
339+ ],
340+ ),
341+ GoRoute (
342+ path: Routes .followedCountriesList,
343+ name: Routes .followedCountriesListName,
344+ builder: (context, state) => const FollowedCountriesListPage (),
345+ routes: [
346+ GoRoute (
347+ path: Routes .addCountryToFollow,
348+ name: Routes .addCountryToFollowName,
349+ builder: (context, state) => const AddCountryToFollowPage (),
350+ ),
351+ ],
352+ ),
353+ ],
354+ ),
355+ GoRoute (
356+ path: Routes .accountSavedHeadlines,
357+ name: Routes .accountSavedHeadlinesName,
358+ builder: (context, state) => const SavedHeadlinesPage (),
359+ routes: [
360+ GoRoute (
361+ path: Routes .accountArticleDetails,
362+ name: Routes .accountArticleDetailsName,
363+ builder: (context, state) {
364+ final headlineFromExtra = state.extra as Headline ? ;
365+ final headlineIdFromPath = state.pathParameters['id' ];
366+ return MultiBlocProvider (
367+ providers: [
368+ BlocProvider (
369+ create: (context) => HeadlineDetailsBloc (
370+ headlinesRepository: context
371+ .read <DataRepository <Headline >>(),
372+ ),
373+ ),
374+ BlocProvider (
375+ create: (context) => SimilarHeadlinesBloc (
376+ headlinesRepository: context
377+ .read <DataRepository <Headline >>(),
378+ ),
379+ ),
380+ ],
381+ child: HeadlineDetailsPage (
382+ initialHeadline: headlineFromExtra,
383+ headlineId: headlineFromExtra? .id ?? headlineIdFromPath,
384+ ),
385+ );
386+ },
387+ ),
388+ ],
389+ ),
390+ GoRoute (
391+ path: Routes .accountSavedFilters,
392+ name: Routes .accountSavedFiltersName,
393+ builder: (context, state) => const SavedFiltersPage (),
394+ ),
395+ ],
396+ ),
231397
232398 // --- Entity Details Route (Top Level) ---
233399 //
@@ -369,174 +535,6 @@ GoRouter createRouter({
369535 );
370536 },
371537 ),
372- // --- Account-related routes (Top-Level Modals) ---
373- // These routes are for pages launched from the AccountSheet. They are
374- // defined at the top level and use `fullscreenDialog: true` to be
375- // presented modally over the entire app, including the AppShell.
376-
377- // ShellRoute for settings to provide SettingsBloc to children
378- ShellRoute (
379- builder: (BuildContext context, GoRouterState state, Widget child) {
380- final appBloc = context.read <AppBloc >();
381- final userId = appBloc.state.user? .id;
382-
383- return BlocProvider <SettingsBloc >(
384- create: (context) {
385- final settingsBloc = SettingsBloc (
386- userAppSettingsRepository: context
387- .read <DataRepository <UserAppSettings >>(),
388- inlineAdCacheService: inlineAdCacheService,
389- );
390- if (userId != null ) {
391- settingsBloc.add (SettingsLoadRequested (userId: userId));
392- } else {
393- logger.warning (
394- 'User ID is null when creating SettingsBloc. '
395- 'Settings will not be loaded.' ,
396- );
397- }
398- return settingsBloc;
399- },
400- child: child,
401- );
402- },
403- routes: [
404- GoRoute (
405- path: Routes .settings,
406- name: Routes .settingsName,
407- pageBuilder: (context, state) => const MaterialPage (
408- fullscreenDialog: true ,
409- child: SettingsPage (),
410- ),
411- routes: [
412- GoRoute (
413- path: Routes .settingsAppearance,
414- name: Routes .settingsAppearanceName,
415- builder: (context, state) => const AppearanceSettingsPage (),
416- routes: [
417- GoRoute (
418- path: Routes .settingsAppearanceTheme,
419- name: Routes .settingsAppearanceThemeName,
420- builder: (context, state) => const ThemeSettingsPage (),
421- ),
422- GoRoute (
423- path: Routes .settingsAppearanceFont,
424- name: Routes .settingsAppearanceFontName,
425- builder: (context, state) => const FontSettingsPage (),
426- ),
427- ],
428- ),
429- GoRoute (
430- path: Routes .settingsFeed,
431- name: Routes .settingsFeedName,
432- builder: (context, state) => const FeedSettingsPage (),
433- ),
434- GoRoute (
435- path: Routes .settingsNotifications,
436- name: Routes .settingsNotificationsName,
437- builder: (context, state) => const NotificationSettingsPage (),
438- ),
439- GoRoute (
440- path: Routes .settingsLanguage,
441- name: Routes .settingsLanguageName,
442- builder: (context, state) => const LanguageSettingsPage (),
443- ),
444- ],
445- ),
446- ],
447- ),
448- GoRoute (
449- path: Routes .manageFollowedItems,
450- name: Routes .manageFollowedItemsName,
451- pageBuilder: (context, state) => const MaterialPage (
452- fullscreenDialog: true ,
453- child: ManageFollowedItemsPage (),
454- ),
455- routes: [
456- GoRoute (
457- path: Routes .followedTopicsList,
458- name: Routes .followedTopicsListName,
459- builder: (context, state) => const FollowedTopicsListPage (),
460- routes: [
461- GoRoute (
462- path: Routes .addTopicToFollow,
463- name: Routes .addTopicToFollowName,
464- builder: (context, state) => const AddTopicToFollowPage (),
465- ),
466- ],
467- ),
468- GoRoute (
469- path: Routes .followedSourcesList,
470- name: Routes .followedSourcesListName,
471- builder: (context, state) => const FollowedSourcesListPage (),
472- routes: [
473- GoRoute (
474- path: Routes .addSourceToFollow,
475- name: Routes .addSourceToFollowName,
476- builder: (context, state) => const AddSourceToFollowPage (),
477- ),
478- ],
479- ),
480- GoRoute (
481- path: Routes .followedCountriesList,
482- name: Routes .followedCountriesListName,
483- builder: (context, state) => const FollowedCountriesListPage (),
484- routes: [
485- GoRoute (
486- path: Routes .addCountryToFollow,
487- name: Routes .addCountryToFollowName,
488- builder: (context, state) => const AddCountryToFollowPage (),
489- ),
490- ],
491- ),
492- ],
493- ),
494- GoRoute (
495- path: Routes .accountSavedHeadlines,
496- name: Routes .accountSavedHeadlinesName,
497- pageBuilder: (context, state) => const MaterialPage (
498- fullscreenDialog: true ,
499- child: SavedHeadlinesPage (),
500- ),
501- routes: [
502- GoRoute (
503- path: Routes .accountArticleDetails,
504- name: Routes .accountArticleDetailsName,
505- builder: (context, state) {
506- final headlineFromExtra = state.extra as Headline ? ;
507- final headlineIdFromPath = state.pathParameters['id' ];
508- return MultiBlocProvider (
509- providers: [
510- BlocProvider (
511- create: (context) => HeadlineDetailsBloc (
512- headlinesRepository: context
513- .read <DataRepository <Headline >>(),
514- ),
515- ),
516- BlocProvider (
517- create: (context) => SimilarHeadlinesBloc (
518- headlinesRepository: context
519- .read <DataRepository <Headline >>(),
520- ),
521- ),
522- ],
523- child: HeadlineDetailsPage (
524- initialHeadline: headlineFromExtra,
525- headlineId: headlineFromExtra? .id ?? headlineIdFromPath,
526- ),
527- );
528- },
529- ),
530- ],
531- ),
532- GoRoute (
533- path: Routes .accountSavedFilters,
534- name: Routes .accountSavedFiltersName,
535- pageBuilder: (context, state) => const MaterialPage (
536- fullscreenDialog: true ,
537- child: SavedFiltersPage (),
538- ),
539- ),
540538 // --- Main App Shell ---
541539 StatefulShellRoute .indexedStack (
542540 builder: (context, state, navigationShell) {
0 commit comments