Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/app/view/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'package:flutter_news_app_mobile_client_full_source_code/router/router.da
import 'package:flutter_news_app_mobile_client_full_source_code/status/view/view.dart';
import 'package:go_router/go_router.dart';
import 'package:kv_storage_service/kv_storage_service.dart';
import 'package:logging/logging.dart';
import 'package:ui_kit/ui_kit.dart';

/// {@template app_widget}
Expand Down Expand Up @@ -223,6 +224,7 @@ class _AppViewState extends State<_AppView> {
late final GoRouter _router;
late final ValueNotifier<AppLifeCycleStatus> _statusNotifier;
AppStatusService? _appStatusService;
final _routerLogger = Logger('GoRouter');

@override
void initState() {
Expand Down Expand Up @@ -257,6 +259,7 @@ class _AppViewState extends State<_AppView> {
adService: widget.adService,
navigatorKey: widget.navigatorKey,
inlineAdCacheService: widget.inlineAdCacheService,
logger: _routerLogger,
);
}

Expand Down
6 changes: 6 additions & 0 deletions lib/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ Future<Widget> bootstrap(
app_config.AppConfig appConfig,
app_config.AppEnvironment environment,
) async {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen(
(record) => print(
'${record.level.name}: ${record.time}: ${record.loggerName}: ${record.message}',
),
);
WidgetsFlutterBinding.ensureInitialized();
Bloc.observer = const AppBlocObserver();
final logger = Logger('bootstrap');
Expand Down
36 changes: 36 additions & 0 deletions lib/router/go_router_observer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';

class GoRouterObserver extends NavigatorObserver {
GoRouterObserver({required this.logger});

final Logger logger;

@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
logger.info(
'Pushed: ${route.settings.name} | from: ${previousRoute?.settings.name}',
);
}

@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
logger.info(
'Popped: ${route.settings.name} | to: ${previousRoute?.settings.name}',
);
}

@override
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
logger.info(
'Removed: ${route.settings.name} | previous: ${previousRoute?.settings.name}',
);
}

@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
logger.info(
'Replaced: ${oldRoute?.settings.name} | with: ${newRoute?.settings.name}',
);
}
}
24 changes: 13 additions & 11 deletions lib/router/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import 'package:flutter_news_app_mobile_client_full_source_code/settings/view/se
import 'package:flutter_news_app_mobile_client_full_source_code/settings/view/theme_settings_page.dart';
import 'package:flutter_news_app_mobile_client_full_source_code/shared/services/feed_decorator_service.dart';
import 'package:go_router/go_router.dart';
import 'package:logging/logging.dart';

/// Creates and configures the GoRouter instance for the application.
///
Expand Down Expand Up @@ -76,6 +77,7 @@ GoRouter createRouter({
required AdService adService,
required GlobalKey<NavigatorState> navigatorKey,
required InlineAdCacheService inlineAdCacheService,
required Logger logger,
}) {
// Instantiate FeedDecoratorService once to be shared
final feedDecoratorService = FeedDecoratorService(
Expand All @@ -101,7 +103,7 @@ GoRouter createRouter({
final appStatus = context.read<AppBloc>().state.status;
final currentLocation = state.matchedLocation;

print(
logger.info(
'GoRouter Redirect Check:\n'
' Current Location (Matched): $currentLocation\n'
' AppStatus: $appStatus',
Expand All @@ -118,24 +120,24 @@ GoRouter createRouter({
// If the user is unauthenticated, they must be on an auth path.
// If they try to go anywhere else, they are redirected to the sign-in page.
if (appStatus == AppLifeCycleStatus.unauthenticated) {
print(' Redirect: User is unauthenticated.');
logger.info(' Redirect: User is unauthenticated.');
return isGoingToAuth ? null : authenticationPath;
}

// --- Case 2: Anonymous User ---
// An anonymous user is partially authenticated. They can browse the app.
if (appStatus == AppLifeCycleStatus.anonymous) {
print(' Redirect: User is anonymous.');
logger.info(' Redirect: User is anonymous.');
// Block anonymous users from the main sign-in page.
if (isGoingToAuth) {
print(
logger.info(
' Action: Anonymous user on auth path. Redirecting to feed.',
);
return feedPath;
}
// If at the root, send them to the feed.
if (currentLocation == rootPath) {
print(' Action: User at root. Redirecting to feed.');
logger.info(' Action: User at root. Redirecting to feed.');
return feedPath;
}
// Allow navigation to other pages, including the new linking page.
Expand All @@ -145,23 +147,23 @@ GoRouter createRouter({
// --- Case 3: Authenticated User ---
// A fully authenticated user should be blocked from all auth/linking pages.
if (appStatus == AppLifeCycleStatus.authenticated) {
print(' Redirect: User is authenticated.');
logger.info(' Redirect: User is authenticated.');
if (isGoingToAuth || isGoingToLinking) {
print(
logger.info(
' Action: Authenticated user on auth/linking path. Redirecting to feed.',
);
return feedPath;
}
// If at the root, send them to the feed.
if (currentLocation == rootPath) {
print(' Action: User at root. Redirecting to feed.');
logger.info(' Action: User at root. Redirecting to feed.');
return feedPath;
}
}

// --- Fallback ---
// For any other case (or if no conditions are met), allow navigation.
print(' Redirect: No condition met. Allowing navigation.');
logger.info(' Redirect: No condition met. Allowing navigation.');
return null;
},
// --- Authentication Routes ---
Expand Down Expand Up @@ -551,8 +553,8 @@ GoRouter createRouter({
);
} else {
// Handle case where user is unexpectedly null.
print(
'ShellRoute/SettingsBloc: User ID is null when creating SettingsBloc. Settings will not be loaded.',
logger.warning(
'User ID is null when creating SettingsBloc. Settings will not be loaded.',
);
}
return settingsBloc;
Expand Down
Loading