Nikolas Rimikis
2 years ago
8 changed files with 171 additions and 39 deletions
@ -1,41 +1,63 @@
|
||||
// ignore: prefer_mixin |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:go_router/go_router.dart'; |
||||
import 'package:neon/neon.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
class AppRouter extends RouterDelegate<Account> with ChangeNotifier, PopNavigatorRouterDelegateMixin<Account> { |
||||
part 'router.g.dart'; |
||||
|
||||
class AppRouter extends GoRouter { |
||||
AppRouter({ |
||||
required this.navigatorKey, |
||||
required this.accountsBloc, |
||||
}); |
||||
required final GlobalKey<NavigatorState> navigatorKey, |
||||
required final AccountsBloc accountsBloc, |
||||
}) : super( |
||||
refreshListenable: StreamListenable.behaviorSubject(accountsBloc.activeAccount), |
||||
navigatorKey: navigatorKey, |
||||
initialLocation: const HomeRoute().location, |
||||
redirect: (final context, final state) { |
||||
final account = accountsBloc.activeAccount.valueOrNull; |
||||
|
||||
final AccountsBloc accountsBloc; |
||||
if (account == null) { |
||||
return const LoginRoute().location; |
||||
} |
||||
|
||||
@override |
||||
final GlobalKey<NavigatorState> navigatorKey; |
||||
if (state.location == const LoginRoute().location) { |
||||
return const HomeRoute().location; |
||||
} |
||||
|
||||
@override |
||||
Future setNewRoutePath(final Account? configuration) async {} |
||||
return null; |
||||
}, |
||||
routes: $appRoutes, |
||||
); |
||||
} |
||||
|
||||
@TypedGoRoute<LoginRoute>( |
||||
path: '/login', |
||||
name: 'login', |
||||
) |
||||
@immutable |
||||
class LoginRoute extends GoRouteData { |
||||
const LoginRoute({this.server}); |
||||
|
||||
final String? server; |
||||
|
||||
@override |
||||
Account? get currentConfiguration => accountsBloc.activeAccount.valueOrNull; |
||||
Widget build(final BuildContext context, final GoRouterState state) => LoginPage(serverURL: server); |
||||
} |
||||
|
||||
@TypedGoRoute<HomeRoute>( |
||||
path: '/', |
||||
name: 'home', |
||||
) |
||||
@immutable |
||||
class HomeRoute extends GoRouteData { |
||||
const HomeRoute(); |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) => Navigator( |
||||
key: navigatorKey, |
||||
onPopPage: (final route, final result) => route.didPop(result), |
||||
pages: [ |
||||
if (currentConfiguration == null) ...[ |
||||
const MaterialPage( |
||||
child: LoginPage(), |
||||
), |
||||
] else ...[ |
||||
MaterialPage( |
||||
name: 'home', |
||||
child: HomePage( |
||||
key: Key(currentConfiguration!.id), |
||||
), |
||||
), |
||||
], |
||||
], |
||||
); |
||||
Widget build(final BuildContext context, final GoRouterState state) { |
||||
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false); |
||||
final account = accountsBloc.activeAccount.valueOrNull!; |
||||
|
||||
return HomePage(key: Key(account.id)); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,57 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
|
||||
part of 'router.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// GoRouterGenerator |
||||
// ************************************************************************** |
||||
|
||||
List<RouteBase> get $appRoutes => [ |
||||
$loginRoute, |
||||
$homeRoute, |
||||
]; |
||||
|
||||
RouteBase get $loginRoute => GoRouteData.$route( |
||||
path: '/login', |
||||
name: 'login', |
||||
factory: $LoginRouteExtension._fromState, |
||||
); |
||||
|
||||
extension $LoginRouteExtension on LoginRoute { |
||||
static LoginRoute _fromState(GoRouterState state) => LoginRoute( |
||||
server: state.queryParameters['server'], |
||||
); |
||||
|
||||
String get location => GoRouteData.$location( |
||||
'/login', |
||||
queryParams: { |
||||
if (server != null) 'server': server, |
||||
}, |
||||
); |
||||
|
||||
void go(BuildContext context) => context.go(location); |
||||
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location); |
||||
|
||||
void pushReplacement(BuildContext context) => context.pushReplacement(location); |
||||
} |
||||
|
||||
RouteBase get $homeRoute => GoRouteData.$route( |
||||
path: '/', |
||||
name: 'home', |
||||
factory: $HomeRouteExtension._fromState, |
||||
); |
||||
|
||||
extension $HomeRouteExtension on HomeRoute { |
||||
static HomeRoute _fromState(GoRouterState state) => const HomeRoute(); |
||||
|
||||
String get location => GoRouteData.$location( |
||||
'/', |
||||
); |
||||
|
||||
void go(BuildContext context) => context.go(location); |
||||
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location); |
||||
|
||||
void pushReplacement(BuildContext context) => context.pushReplacement(location); |
||||
} |
@ -0,0 +1,38 @@
|
||||
part of '../../neon.dart'; |
||||
|
||||
/// Listenable Stream |
||||
/// |
||||
/// A class that implements [Listenable] for a stream. |
||||
/// Objects need to be manually disposed. |
||||
class StreamListenable extends ChangeNotifier { |
||||
/// Listenable Stream |
||||
/// |
||||
/// Implementation for all types of [Stream]s. |
||||
/// For an implementation tailored towards [BehaviorSubject] have a look at [StreamListenable.behaviorSubject]. |
||||
StreamListenable(final Stream<dynamic> stream) { |
||||
notifyListeners(); |
||||
|
||||
_subscription = stream.asBroadcastStream().listen((final value) { |
||||
notifyListeners(); |
||||
}); |
||||
} |
||||
|
||||
/// Listenable BehaviorSubject |
||||
/// |
||||
/// Implementation for a [BehaviorSubject]. It ensures to not unececcary notify listeners. |
||||
/// For an implementation tailored towards otnher kinds of [Stream] have a look at [StreamListenable]. |
||||
StreamListenable.behaviorSubject(final BehaviorSubject<dynamic> subject) { |
||||
_subscription = subject.listen((final value) { |
||||
notifyListeners(); |
||||
}); |
||||
} |
||||
|
||||
late final StreamSubscription<dynamic> _subscription; |
||||
|
||||
@override |
||||
void dispose() { |
||||
unawaited(_subscription.cancel()); |
||||
|
||||
super.dispose(); |
||||
} |
||||
} |
Loading…
Reference in new issue