Skip to content

Commit f838424

Browse files
committed
feat(router): enhance navigation handling for deep links
- Add support for push notification deep-links in account and global article details routes - Improve type safety for route 'extra' parameters - Refactor BlocProvider creations for better readability - Extract common provider setup for entity and headline details pages
1 parent ee93b90 commit f838424

File tree

1 file changed

+63
-47
lines changed

1 file changed

+63
-47
lines changed

lib/router/router.dart

Lines changed: 63 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ GoRouter createRouter({
241241
// in the BuildContext when InAppNotificationCenterPage's initState runs.
242242
return BlocProvider(
243243
create: (context) => InAppNotificationCenterBloc(
244-
inAppNotificationRepository: context.read<DataRepository<InAppNotification>>(),
244+
inAppNotificationRepository:
245+
context.read<DataRepository<InAppNotification>>(),
245246
appBloc: context.read<AppBloc>(),
246247
logger: context.read<Logger>(),
247248
)..add(const InAppNotificationCenterSubscriptionRequested()),
@@ -259,8 +260,8 @@ GoRouter createRouter({
259260
return BlocProvider<SettingsBloc>(
260261
create: (context) {
261262
final settingsBloc = SettingsBloc(
262-
userAppSettingsRepository: context
263-
.read<DataRepository<UserAppSettings>>(),
263+
userAppSettingsRepository:
264+
context.read<DataRepository<UserAppSettings>>(),
264265
inlineAdCacheService: context.read<InlineAdCacheService>(),
265266
);
266267
if (userId != null) {
@@ -356,7 +357,8 @@ GoRouter createRouter({
356357
GoRoute(
357358
path: Routes.addCountryToFollow,
358359
name: Routes.addCountryToFollowName,
359-
builder: (context, state) => const AddCountryToFollowPage(),
360+
builder: (context, state) =>
361+
const AddCountryToFollowPage(),
360362
),
361363
],
362364
),
@@ -371,26 +373,31 @@ GoRouter createRouter({
371373
path: Routes.accountArticleDetails,
372374
name: Routes.accountArticleDetailsName,
373375
builder: (context, state) {
374-
final headlineFromExtra = state.extra as Headline?;
376+
final extra = state.extra;
377+
final headlineFromExtra = extra is Headline ? extra : null;
375378
final headlineIdFromPath = state.pathParameters['id'];
379+
final notificationId = extra is Map<String, dynamic>
380+
? extra['notificationId'] as String?
381+
: null;
376382
return MultiBlocProvider(
377383
providers: [
378384
BlocProvider(
379385
create: (context) => HeadlineDetailsBloc(
380-
headlinesRepository: context
381-
.read<DataRepository<Headline>>(),
386+
headlinesRepository:
387+
context.read<DataRepository<Headline>>(),
382388
),
383389
),
384390
BlocProvider(
385391
create: (context) => SimilarHeadlinesBloc(
386-
headlinesRepository: context
387-
.read<DataRepository<Headline>>(),
392+
headlinesRepository:
393+
context.read<DataRepository<Headline>>(),
388394
),
389395
),
390396
],
391397
child: HeadlineDetailsPage(
392398
initialHeadline: headlineFromExtra,
393399
headlineId: headlineFromExtra?.id ?? headlineIdFromPath,
400+
notificationId: notificationId,
394401
),
395402
);
396403
},
@@ -429,25 +436,22 @@ GoRouter createRouter({
429436
return MultiBlocProvider(
430437
providers: [
431438
BlocProvider(
432-
create: (context) =>
433-
EntityDetailsBloc(
434-
headlinesRepository: context
435-
.read<DataRepository<Headline>>(),
436-
topicRepository: context.read<DataRepository<Topic>>(),
437-
sourceRepository: context.read<DataRepository<Source>>(),
438-
countryRepository: context
439-
.read<DataRepository<Country>>(),
440-
appBloc: context.read<AppBloc>(),
441-
adService: context.read<AdService>(),
442-
inlineAdCacheService: context
443-
.read<InlineAdCacheService>(),
444-
)..add(
445-
EntityDetailsLoadRequested(
446-
entityId: args.entityId,
447-
contentType: args.contentType,
448-
adThemeStyle: adThemeStyle,
449-
),
439+
create: (context) => EntityDetailsBloc(
440+
headlinesRepository: context.read<DataRepository<Headline>>(),
441+
topicRepository: context.read<DataRepository<Topic>>(),
442+
sourceRepository: context.read<DataRepository<Source>>(),
443+
countryRepository: context.read<DataRepository<Country>>(),
444+
appBloc: context.read<AppBloc>(),
445+
adService: context.read<AdService>(),
446+
inlineAdCacheService:
447+
context.read<InlineAdCacheService>(),
448+
)..add(
449+
EntityDetailsLoadRequested(
450+
entityId: args.entityId,
451+
contentType: args.contentType,
452+
adThemeStyle: adThemeStyle,
450453
),
454+
),
451455
),
452456
],
453457
child: EntityDetailsPage(args: args),
@@ -458,8 +462,14 @@ GoRouter createRouter({
458462
path: Routes.globalArticleDetails,
459463
name: Routes.globalArticleDetailsName,
460464
builder: (context, state) {
461-
final headlineFromExtra = state.extra as Headline?;
465+
// The 'extra' can be a Headline object (from feed navigation) or a Map
466+
// (from a push notification deep-link).
467+
final extra = state.extra;
468+
final headlineFromExtra = extra is Headline ? extra : null;
462469
final headlineIdFromPath = state.pathParameters['id'];
470+
final notificationId = extra is Map<String, dynamic>
471+
? extra['notificationId'] as String?
472+
: null;
463473

464474
return MultiBlocProvider(
465475
providers: [
@@ -477,6 +487,7 @@ GoRouter createRouter({
477487
child: HeadlineDetailsPage(
478488
initialHeadline: headlineFromExtra,
479489
headlineId: headlineFromExtra?.id ?? headlineIdFromPath,
490+
notificationId: notificationId,
480491
),
481492
);
482493
},
@@ -490,8 +501,7 @@ GoRouter createRouter({
490501
final allItems = extra['allItems'] as List<dynamic>? ?? [];
491502
final initialSelectedItems =
492503
extra['initialSelectedItems'] as Set<dynamic>? ?? {};
493-
final itemBuilder =
494-
extra['itemBuilder'] as Function? ??
504+
final itemBuilder = extra['itemBuilder'] as Function? ??
495505
(dynamic item) => item.toString();
496506

497507
return MultiSelectSearchPage<dynamic>(
@@ -525,13 +535,13 @@ GoRouter createRouter({
525535
final initialUserContentPreferences =
526536
appBloc.state.userContentPreferences;
527537
return HeadlinesFeedBloc(
528-
headlinesRepository: context
529-
.read<DataRepository<Headline>>(),
538+
headlinesRepository:
539+
context.read<DataRepository<Headline>>(),
530540
feedDecoratorService: FeedDecoratorService(),
531541
adService: context.read<AdService>(),
532542
appBloc: appBloc,
533-
inlineAdCacheService: context
534-
.read<InlineAdCacheService>(),
543+
inlineAdCacheService:
544+
context.read<InlineAdCacheService>(),
535545
feedCacheService: context.read<FeedCacheService>(),
536546
initialUserContentPreferences:
537547
initialUserContentPreferences,
@@ -551,28 +561,34 @@ GoRouter createRouter({
551561
path: 'article/:id',
552562
name: Routes.articleDetailsName,
553563
builder: (context, state) {
554-
final headlineFromExtra = state.extra as Headline?;
564+
final extra = state.extra;
565+
final headlineFromExtra =
566+
extra is Headline ? extra : null;
555567
final headlineIdFromPath = state.pathParameters['id'];
568+
final notificationId = extra is Map<String, dynamic>
569+
? extra['notificationId'] as String?
570+
: null;
556571

557572
return MultiBlocProvider(
558573
providers: [
559574
BlocProvider(
560575
create: (context) => HeadlineDetailsBloc(
561-
headlinesRepository: context
562-
.read<DataRepository<Headline>>(),
576+
headlinesRepository:
577+
context.read<DataRepository<Headline>>(),
563578
),
564579
),
565580
BlocProvider(
566581
create: (context) => SimilarHeadlinesBloc(
567-
headlinesRepository: context
568-
.read<DataRepository<Headline>>(),
582+
headlinesRepository:
583+
context.read<DataRepository<Headline>>(),
569584
),
570585
),
571586
],
572587
child: HeadlineDetailsPage(
573588
initialHeadline: headlineFromExtra,
574589
headlineId:
575590
headlineFromExtra?.id ?? headlineIdFromPath,
591+
notificationId: notificationId,
576592
),
577593
);
578594
},
@@ -637,22 +653,22 @@ GoRouter createRouter({
637653
builder: (context, state) {
638654
final extra =
639655
state.extra as Map<String, dynamic>? ??
640-
{};
656+
{};
641657
final allCountries =
642658
extra['allCountries'] as List<Country>? ??
643-
[];
659+
[];
644660
final allSourceTypes =
645661
extra['allSourceTypes']
646-
as List<SourceType>? ??
647-
[];
662+
as List<SourceType>? ??
663+
[];
648664
final initialSelectedHeadquarterCountries =
649665
extra['initialSelectedHeadquarterCountries']
650-
as Set<Country>? ??
651-
{};
666+
as Set<Country>? ??
667+
{};
652668
final initialSelectedSourceTypes =
653669
extra['initialSelectedSourceTypes']
654-
as Set<SourceType>? ??
655-
{};
670+
as Set<SourceType>? ??
671+
{};
656672

657673
return feed_filter.SourceListFilterPage(
658674
allCountries: allCountries,

0 commit comments

Comments
 (0)