Nikolas Rimikis
2 years ago
committed by
GitHub
13 changed files with 649 additions and 428 deletions
@ -1,41 +1,124 @@
|
||||
part of '../neon.dart'; |
||||
|
||||
// ignore: prefer_mixin |
||||
class AppRouter extends RouterDelegate<Account> with ChangeNotifier, PopNavigatorRouterDelegateMixin<Account> { |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:go_router/go_router.dart'; |
||||
import 'package:neon/neon.dart'; |
||||
import 'package:provider/provider.dart'; |
||||
|
||||
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, |
||||
); |
||||
} |
||||
|
||||
@override |
||||
Account? get currentConfiguration => accountsBloc.activeAccount.valueOrNull; |
||||
@immutable |
||||
class AccountSettingsRoute extends GoRouteData { |
||||
const AccountSettingsRoute({ |
||||
required this.accountid, |
||||
}); |
||||
|
||||
final String accountid; |
||||
|
||||
@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( |
||||
Widget build(final BuildContext context, final GoRouterState state) { |
||||
final bloc = Provider.of<AccountsBloc>(context, listen: false); |
||||
final account = bloc.accounts.value.find(accountid)!; |
||||
|
||||
return AccountSettingsPage( |
||||
bloc: bloc, |
||||
account: account, |
||||
); |
||||
} |
||||
} |
||||
|
||||
@TypedGoRoute<HomeRoute>( |
||||
path: '/', |
||||
name: 'home', |
||||
child: HomePage( |
||||
key: Key(currentConfiguration!.id), |
||||
account: currentConfiguration!, |
||||
routes: [ |
||||
TypedGoRoute<SettingsRoute>( |
||||
path: 'settings', |
||||
name: 'Settings', |
||||
routes: [ |
||||
TypedGoRoute<NextcloudAppSettingsRoute>( |
||||
path: ':appid', |
||||
name: 'NextcloudAppSettings', |
||||
), |
||||
TypedGoRoute<AccountSettingsRoute>( |
||||
path: 'account/:accountid', |
||||
name: 'AccountSettings', |
||||
), |
||||
], |
||||
) |
||||
], |
||||
); |
||||
) |
||||
@immutable |
||||
class HomeRoute extends GoRouteData { |
||||
const HomeRoute(); |
||||
|
||||
@override |
||||
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)); |
||||
} |
||||
} |
||||
|
||||
@TypedGoRoute<LoginRoute>( |
||||
path: '/login', |
||||
name: 'login', |
||||
) |
||||
@immutable |
||||
class LoginRoute extends GoRouteData { |
||||
const LoginRoute({this.server}); |
||||
|
||||
final String? server; |
||||
|
||||
@override |
||||
Widget build(final BuildContext context, final GoRouterState state) => LoginPage(serverURL: server); |
||||
} |
||||
|
||||
@immutable |
||||
class NextcloudAppSettingsRoute extends GoRouteData { |
||||
const NextcloudAppSettingsRoute({ |
||||
required this.appid, |
||||
}); |
||||
|
||||
final String appid; |
||||
|
||||
@override |
||||
Widget build(final BuildContext context, final GoRouterState state) { |
||||
final appImplementations = Provider.of<List<AppImplementation>>(context, listen: false); |
||||
final appImplementation = appImplementations.firstWhere((final app) => app.id == appid); |
||||
|
||||
return NextcloudAppSettingsPage(appImplementation: appImplementation); |
||||
} |
||||
} |
||||
|
||||
@immutable |
||||
class SettingsRoute extends GoRouteData { |
||||
const SettingsRoute(); |
||||
|
||||
@override |
||||
Widget build(final BuildContext context, final GoRouterState state) => const SettingsPage(); |
||||
} |
||||
|
@ -0,0 +1,122 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
|
||||
part of 'router.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// GoRouterGenerator |
||||
// ************************************************************************** |
||||
|
||||
List<RouteBase> get $appRoutes => [ |
||||
$homeRoute, |
||||
$loginRoute, |
||||
]; |
||||
|
||||
RouteBase get $homeRoute => GoRouteData.$route( |
||||
path: '/', |
||||
name: 'home', |
||||
factory: $HomeRouteExtension._fromState, |
||||
routes: [ |
||||
GoRouteData.$route( |
||||
path: 'settings', |
||||
name: 'Settings', |
||||
factory: $SettingsRouteExtension._fromState, |
||||
routes: [ |
||||
GoRouteData.$route( |
||||
path: ':appid', |
||||
name: 'NextcloudAppSettings', |
||||
factory: $NextcloudAppSettingsRouteExtension._fromState, |
||||
), |
||||
GoRouteData.$route( |
||||
path: 'account/:accountid', |
||||
name: 'AccountSettings', |
||||
factory: $AccountSettingsRouteExtension._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); |
||||
} |
||||
|
||||
extension $SettingsRouteExtension on SettingsRoute { |
||||
static SettingsRoute _fromState(GoRouterState state) => const SettingsRoute(); |
||||
|
||||
String get location => GoRouteData.$location( |
||||
'/settings', |
||||
); |
||||
|
||||
void go(BuildContext context) => context.go(location); |
||||
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location); |
||||
|
||||
void pushReplacement(BuildContext context) => context.pushReplacement(location); |
||||
} |
||||
|
||||
extension $NextcloudAppSettingsRouteExtension on NextcloudAppSettingsRoute { |
||||
static NextcloudAppSettingsRoute _fromState(GoRouterState state) => NextcloudAppSettingsRoute( |
||||
appid: state.pathParameters['appid']!, |
||||
); |
||||
|
||||
String get location => GoRouteData.$location( |
||||
'/settings/${Uri.encodeComponent(appid)}', |
||||
); |
||||
|
||||
void go(BuildContext context) => context.go(location); |
||||
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location); |
||||
|
||||
void pushReplacement(BuildContext context) => context.pushReplacement(location); |
||||
} |
||||
|
||||
extension $AccountSettingsRouteExtension on AccountSettingsRoute { |
||||
static AccountSettingsRoute _fromState(GoRouterState state) => AccountSettingsRoute( |
||||
accountid: state.pathParameters['accountid']!, |
||||
); |
||||
|
||||
String get location => GoRouteData.$location( |
||||
'/settings/account/${Uri.encodeComponent(accountid)}', |
||||
); |
||||
|
||||
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 $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); |
||||
} |
@ -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