@@ -16,6 +16,7 @@ import 'package:flutter_news_app_mobile_client_full_source_code/app/services/app
1616import 'package:flutter_news_app_mobile_client_full_source_code/feed_decorators/services/feed_decorator_service.dart' ;
1717import 'package:flutter_news_app_mobile_client_full_source_code/headlines-feed/services/feed_cache_service.dart' ;
1818import 'package:flutter_news_app_mobile_client_full_source_code/l10n/app_localizations.dart' ;
19+ import 'package:flutter_news_app_mobile_client_full_source_code/shared/widgets/feed_core/headline_tap_handler.dart' ;
1920import 'package:flutter_news_app_mobile_client_full_source_code/notifications/services/push_notification_service.dart' ;
2021import 'package:flutter_news_app_mobile_client_full_source_code/router/router.dart' ;
2122import 'package:flutter_news_app_mobile_client_full_source_code/router/routes.dart' ;
@@ -50,7 +51,7 @@ class App extends StatelessWidget {
5051 required DataRepository <RemoteConfig > remoteConfigRepository,
5152 required DataRepository <AppSettings > appSettingsRepository,
5253 required DataRepository <UserContentPreferences >
53- userContentPreferencesRepository,
54+ userContentPreferencesRepository,
5455 required AppEnvironment environment,
5556 required DataRepository <InAppNotification > inAppNotificationRepository,
5657 required InlineAdCacheService inlineAdCacheService,
@@ -60,23 +61,23 @@ class App extends StatelessWidget {
6061 required GlobalKey <NavigatorState > navigatorKey,
6162 required PushNotificationService pushNotificationService,
6263 super .key,
63- }) : _authenticationRepository = authenticationRepository,
64- _headlinesRepository = headlinesRepository,
65- _topicsRepository = topicsRepository,
66- _countriesRepository = countriesRepository,
67- _sourcesRepository = sourcesRepository,
68- _userRepository = userRepository,
69- _remoteConfigRepository = remoteConfigRepository,
70- _appSettingsRepository = appSettingsRepository,
71- _userContentPreferencesRepository = userContentPreferencesRepository,
72- _pushNotificationService = pushNotificationService,
73- _inAppNotificationRepository = inAppNotificationRepository,
74- _environment = environment,
75- _adService = adService,
76- _feedDecoratorService = feedDecoratorService,
77- _feedCacheService = feedCacheService,
78- _navigatorKey = navigatorKey,
79- _inlineAdCacheService = inlineAdCacheService;
64+ }) : _authenticationRepository = authenticationRepository,
65+ _headlinesRepository = headlinesRepository,
66+ _topicsRepository = topicsRepository,
67+ _countriesRepository = countriesRepository,
68+ _sourcesRepository = sourcesRepository,
69+ _userRepository = userRepository,
70+ _remoteConfigRepository = remoteConfigRepository,
71+ _appSettingsRepository = appSettingsRepository,
72+ _userContentPreferencesRepository = userContentPreferencesRepository,
73+ _pushNotificationService = pushNotificationService,
74+ _inAppNotificationRepository = inAppNotificationRepository,
75+ _environment = environment,
76+ _adService = adService,
77+ _feedDecoratorService = feedDecoratorService,
78+ _feedCacheService = feedCacheService,
79+ _navigatorKey = navigatorKey,
80+ _inlineAdCacheService = inlineAdCacheService;
8081
8182 /// The initial user, pre-fetched during startup.
8283 final User ? user;
@@ -99,7 +100,7 @@ class App extends StatelessWidget {
99100 final DataRepository <RemoteConfig > _remoteConfigRepository;
100101 final DataRepository <AppSettings > _appSettingsRepository;
101102 final DataRepository <UserContentPreferences >
102- _userContentPreferencesRepository;
103+ _userContentPreferencesRepository;
103104 final AppEnvironment _environment;
104105 final DataRepository <InAppNotification > _inAppNotificationRepository;
105106 final AdService _adService;
@@ -202,8 +203,8 @@ class _AppViewState extends State<_AppView> {
202203 // This stream is the single source of truth for the user's auth state
203204 // and drives the entire app lifecycle by dispatching AppUserChanged events.
204205 _userSubscription = context.read <AuthRepository >().authStateChanges.listen (
205- (user) => context.read <AppBloc >().add (AppUserChanged (user)),
206- );
206+ (user) => context.read <AppBloc >().add (AppUserChanged (user)),
207+ );
207208
208209 // Subscribe to foreground push notifications. When a message is received,
209210 // dispatch an event to the AppBloc to update the UI state (e.g., show an
@@ -214,29 +215,23 @@ class _AppViewState extends State<_AppView> {
214215
215216 // Subscribe to notifications that are tapped and open the app.
216217 // This is the core of the deep-linking functionality.
217- _onMessageOpenedAppSubscription =
218- pushNotificationService.onMessageOpenedApp.listen ((payload) {
219- _routerLogger.fine (
220- 'Notification opened app with payload: $payload ' ,
221- );
222- final contentType = payload.contentType;
223- final contentId = payload.contentId;
224- final notificationId = payload.notificationId;
218+ _onMessageOpenedAppSubscription = pushNotificationService.onMessageOpenedApp
219+ .listen ((payload) async {
220+ _routerLogger.fine ('Notification opened app with payload: $payload ' );
221+ final contentType = payload.contentType;
222+ final contentId = payload.contentId;
225223
226- if (contentType == ContentType .headline && contentId.isNotEmpty) {
227- // Use pushNamed instead of goNamed.
228- // goNamed replaces the entire navigation stack, which causes issues
229- // when the app is launched from a terminated state. The new page
230- // would lack the necessary ancestor widgets (like RepositoryProviders).
231- // pushNamed correctly pushes the details page on top of the existing
232- // stack (e.g., the feed), ensuring a valid context.
233- _router.pushNamed (
234- Routes .globalArticleDetailsName,
235- pathParameters: {'id' : contentId},
236- extra: {'notificationId' : notificationId},
237- );
238- }
239- });
224+ if (contentType == ContentType .headline && contentId.isNotEmpty) {
225+ // Guard against using BuildContext across async gaps by checking
226+ // if the widget is still mounted before using its context.
227+ if (mounted) {
228+ await HeadlineTapHandler .handleTapFromSystemNotification (
229+ context,
230+ contentId,
231+ );
232+ }
233+ }
234+ });
240235 // Instantiate and initialize the AppStatusService.
241236 // This service monitors the app's lifecycle (e.g., resuming from
242237 // background) and periodically triggers remote configuration fetches,
0 commit comments