From f3965eb39957ef2ada122186a8796834cf764897 Mon Sep 17 00:00:00 2001 From: Abhishek Shroff Date: Wed, 16 Apr 2025 19:59:40 +0530 Subject: [PATCH] [client] Separate login/logout MaterialApps --- client/lib/app.dart | 84 +------------------ client/lib/main.dart | 23 +---- client/lib/ui/login/login_app.dart | 84 +++++++++++++++++++ client/lib/ui/{ => login}/login_page.dart | 3 +- client/lib/ui/logout/logout_app.dart | 71 ++++++++++++++++ .../logout_page.dart} | 4 +- 6 files changed, 164 insertions(+), 105 deletions(-) create mode 100644 client/lib/ui/login/login_app.dart rename client/lib/ui/{ => login}/login_page.dart (97%) create mode 100644 client/lib/ui/logout/logout_app.dart rename client/lib/ui/{app/app_logout.dart => logout/logout_page.dart} (95%) diff --git a/client/lib/app.dart b/client/lib/app.dart index 7ac2ca0b..ad2bf5ad 100644 --- a/client/lib/app.dart +++ b/client/lib/app.dart @@ -1,7 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_state_notifier/flutter_state_notifier.dart'; -import 'package:go_router/go_router.dart'; import 'package:offtheline/offtheline.dart'; import 'package:phylum/app_shortcuts.dart'; import 'package:phylum/integrations/download_manager.dart'; @@ -10,7 +9,7 @@ import 'package:phylum/libphylum/phylum_account.dart'; import 'package:phylum/libphylum/phylum_api_types.dart'; import 'package:phylum/ui/app/action_queue_status_notifier.dart'; import 'package:phylum/ui/app/app_layout.dart'; -import 'package:phylum/ui/app/app_logout.dart'; +import 'package:phylum/ui/logout/logout_app.dart'; import 'package:phylum/libphylum/explorer/page.dart'; import 'package:provider/provider.dart'; @@ -80,20 +79,8 @@ class _PhylumAppState extends State { shortcuts: getAppShortcuts(), ); } - return MaterialApp.router( - key: ValueKey('loggingout'), - title: 'Logging Out | Phylum', - debugShowCheckedModeBanner: false, - theme: theme, - darkTheme: darkTheme, - routerConfig: createLogoutRouter(), - ); + return const LogoutApp(); } - - RouterConfig createLogoutRouter() => GoRouter( - errorBuilder: (context, state) => const AppLogout(), - routes: [], - ); } class PhylumRouteInformationParser extends RouteInformationParser { @@ -147,12 +134,6 @@ class PhylumRouterDelegate extends RouterDelegate return Navigator( key: navigatorKey, onGenerateRoute: (settings) => MaterialPageRoute(builder: (context) => const AppLayout()), - // pages: [ - // MaterialPage( - // child: const AppLayout(), - // onPopInvoked: (didPop, result) => navigator.goBack(), - // ) - // ], ); } @@ -164,67 +145,6 @@ class PhylumRouterDelegate extends RouterDelegate @override Future setNewRoutePath(ExplorerPage configuration) { - // navigator.go(configuration); return SynchronousFuture(null); } } - -// sealed class PhylumRoute { -// Uri get uri; - -// ExplorerPage get page; - -// const PhylumRoute(); -// } - -// class PhylumRouteHome extends PhylumRoute { -// @override -// Uri get uri => Uri(path: '/home'); - -// @override -// ExplorerPage get page => const ExplorerPageHome(); - -// const PhylumRouteHome(); -// } - -// class PhylumRouteFolder extends PhylumRoute { -// @override -// Uri get uri => Uri(path: '/folder/$folderId'); - -// final String folderId; - -// @override -// ExplorerPage get page => ExplorerPageFolder(folderId: folderId); - -// const PhylumRouteFolder(this.folderId); -// } - -// class PhylumRouteRecents extends PhylumRoute { -// @override -// Uri get uri => Uri(path: '/recents'); - -// @override -// ExplorerPage get page => const ExplorerPageRecents(); - -// const PhylumRouteRecents(); -// } - -// class PhylumRouteShared extends PhylumRoute { -// @override -// Uri get uri => Uri(path: '/shared'); - -// @override -// ExplorerPage get page => const ExplorerPageShared(); - -// const PhylumRouteShared(); -// } - -// class PhylumRouteTrash extends PhylumRoute { -// @override -// Uri get uri => Uri(path: '/trash'); - -// @override -// ExplorerPage get page => const ExplorerPageTrash(); - -// const PhylumRouteTrash(); -// } diff --git a/client/lib/main.dart b/client/lib/main.dart index e3e337ae..b521f977 100644 --- a/client/lib/main.dart +++ b/client/lib/main.dart @@ -14,7 +14,7 @@ import 'package:phylum/integrations/directories.dart'; import 'package:phylum/libphylum/actions/deserializers.dart'; import 'package:phylum/libphylum/db/db.dart'; import 'package:phylum/libphylum/phylum_account.dart'; -import 'package:phylum/ui/login_page.dart'; +import 'package:phylum/ui/login/login_app.dart'; import 'package:phylum/util/logging.dart'; import 'package:provider/provider.dart'; @@ -36,7 +36,6 @@ void main() async { }; logger.log(lvl, message, error: error, stackTrace: stackTrace); }; - // GoRouter.optionURLReflectsImperativeAPIs = true; // We use multiple distinct databases for different accounts, so this is expected behavior driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; @@ -70,9 +69,8 @@ void main() async { class AccountSelector extends StatelessWidget { final AccountManager accountManager; - final Key _loginAppKey = UniqueKey(); - AccountSelector({ + const AccountSelector({ super.key, required this.accountManager, }); @@ -86,23 +84,8 @@ class AccountSelector extends StatelessWidget { context.select, PhylumAccount?>((state) => state.selectedAccount); if (account == null) { - return buildLoginPage(context); + return const LoginApp(key: ValueKey('login')); } return PhylumApp.create(account); }); - - Widget buildLoginPage(BuildContext context) => MaterialApp( - key: _loginAppKey, - title: 'Login | Phylum', - debugShowCheckedModeBanner: false, - theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange)), - darkTheme: ThemeData.dark(), - initialRoute: '/', - onGenerateRoute: (settings) { - return MaterialPageRoute( - settings: settings, - builder: (context) => const LoginPage(), - ); - }, - ); } diff --git a/client/lib/ui/login/login_app.dart b/client/lib/ui/login/login_app.dart new file mode 100644 index 00000000..deb92d5a --- /dev/null +++ b/client/lib/ui/login/login_app.dart @@ -0,0 +1,84 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:uri/uri.dart'; + +import 'login_page.dart'; + +class LoginApp extends StatefulWidget { + const LoginApp({super.key}); + + @override + State createState() => _LoginAppState(); +} + +class _LoginAppState extends State { + final delegate = LoginRouterDelegate(); + + @override + Widget build(BuildContext context) { + return MaterialApp.router( + title: 'Login | Phylum', + debugShowCheckedModeBanner: false, + theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange)), + darkTheme: ThemeData.dark(), + routeInformationParser: const LoginRouteInformationParser(), + routerDelegate: delegate, + ); + } +} + +class LoginRouteConfiguration { + final String? next; + + LoginRouteConfiguration(this.next); +} + +class LoginRouteInformationParser extends RouteInformationParser { + const LoginRouteInformationParser(); + + @override + Future parseRouteInformation(RouteInformation routeInformation) { + final uri = routeInformation.uri; + final segments = uri.pathSegments; + + final next = (segments.isEmpty || (segments.length == 1 && segments[0] == 'home')) ? null : uri.path; + return SynchronousFuture(LoginRouteConfiguration(next)); + } + + @override + RouteInformation? restoreRouteInformation(LoginRouteConfiguration configuration) { + final b = UriBuilder()..path = '/login'; + if (configuration.next != null) { + b.queryParameters['next'] = configuration.next!; + } + + return RouteInformation(uri: b.build()); + } +} + +class LoginRouterDelegate extends RouterDelegate + with ChangeNotifier, PopNavigatorRouterDelegateMixin { + @override + final navigatorKey = GlobalKey(); + + LoginRouterDelegate(); + + LoginRouteConfiguration? _currentConfiguration; + @override + LoginRouteConfiguration? get currentConfiguration => _currentConfiguration; + + @override + Widget build(BuildContext context) { + return Navigator( + key: navigatorKey, + onGenerateRoute: (settings) => MaterialPageRoute(builder: (context) => const LoginPage()), + ); + } + + @override + Future setNewRoutePath(LoginRouteConfiguration configuration) { + _currentConfiguration = configuration; + notifyListeners(); + return SynchronousFuture(null); + } +} diff --git a/client/lib/ui/login_page.dart b/client/lib/ui/login/login_page.dart similarity index 97% rename from client/lib/ui/login_page.dart rename to client/lib/ui/login/login_page.dart index 5ed82401..426cee19 100644 --- a/client/lib/ui/login_page.dart +++ b/client/lib/ui/login/login_page.dart @@ -27,7 +27,8 @@ class _LoginPageState extends State { String? urlError; String? emailError; - bool get serverUrlValid => (kIsWeb && serverUrl == Uri()) || (serverUrl?.hasScheme == true && serverUrl?.hasAuthority == true); + bool get serverUrlValid => + (kIsWeb && serverUrl == Uri()) || (serverUrl?.hasScheme == true && serverUrl?.hasAuthority == true); @override void initState() { diff --git a/client/lib/ui/logout/logout_app.dart b/client/lib/ui/logout/logout_app.dart new file mode 100644 index 00000000..59da14ea --- /dev/null +++ b/client/lib/ui/logout/logout_app.dart @@ -0,0 +1,71 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:phylum/ui/logout/logout_page.dart'; + +class LogoutApp extends StatefulWidget { + const LogoutApp({super.key}); + + @override + State createState() => _LoginAppState(); +} + +class _LoginAppState extends State { + final delegate = LogoutRouterDelegate(); + + @override + Widget build(BuildContext context) { + return MaterialApp.router( + title: 'Login | Phylum', + debugShowCheckedModeBanner: false, + theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange)), + darkTheme: ThemeData.dark(), + routeInformationParser: const LogoutRouteInformationParser(), + routerDelegate: delegate, + ); + } +} + +class LogoutRouteConfiguration { + const LogoutRouteConfiguration(); +} + +class LogoutRouteInformationParser extends RouteInformationParser { + const LogoutRouteInformationParser(); + + @override + Future parseRouteInformation(RouteInformation routeInformation) { + return SynchronousFuture(const LogoutRouteConfiguration()); + } + + @override + RouteInformation? restoreRouteInformation(LogoutRouteConfiguration configuration) { + return RouteInformation(uri: Uri(path: '/logout')); + } +} + +class LogoutRouterDelegate extends RouterDelegate + with ChangeNotifier, PopNavigatorRouterDelegateMixin { + @override + final navigatorKey = GlobalKey(); + + LogoutRouterDelegate(); + + LogoutRouteConfiguration? _currentConfiguration; + @override + LogoutRouteConfiguration? get currentConfiguration => _currentConfiguration; + + @override + Widget build(BuildContext context) { + return Navigator( + key: navigatorKey, + onGenerateRoute: (settings) => MaterialPageRoute(builder: (context) => const LogoutPage()), + ); + } + + @override + Future setNewRoutePath(LogoutRouteConfiguration configuration) { + _currentConfiguration = configuration; + notifyListeners(); + return SynchronousFuture(null); + } +} diff --git a/client/lib/ui/app/app_logout.dart b/client/lib/ui/logout/logout_page.dart similarity index 95% rename from client/lib/ui/app/app_logout.dart rename to client/lib/ui/logout/logout_page.dart index 77a2c4e9..4ae3d73e 100644 --- a/client/lib/ui/app/app_logout.dart +++ b/client/lib/ui/logout/logout_page.dart @@ -3,8 +3,8 @@ import 'package:offtheline/offtheline.dart'; import 'package:phylum/libphylum/phylum_account.dart'; import 'package:provider/provider.dart'; -class AppLogout extends StatelessWidget { - const AppLogout({super.key}); +class LogoutPage extends StatelessWidget { + const LogoutPage({super.key}); @override Widget build(BuildContext context) {