Browse Source

neon: use go_router

pull/338/head
Nikolas Rimikis 2 years ago
parent
commit
7431a35ece
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 16
      packages/app/pubspec.lock
  2. 1
      packages/neon/neon/lib/neon.dart
  3. 2
      packages/neon/neon/lib/src/app.dart
  4. 78
      packages/neon/neon/lib/src/router.dart
  5. 57
      packages/neon/neon/lib/src/router.g.dart
  6. 38
      packages/neon/neon/lib/src/utils/stream_listenable.dart
  7. 14
      packages/neon/neon/lib/src/widgets/exception.dart
  8. 4
      packages/neon/neon/pubspec.yaml

16
packages/app/pubspec.lock

@ -317,6 +317,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
go_router:
dependency: transitive
description:
name: go_router
sha256: "00d1b67d6e9fa443331da229084dd3eb04407f5a2dff22940bd7bba6af5722c3"
url: "https://pub.dev"
source: hosted
version: "7.1.1"
html:
dependency: transitive
description:
@ -434,6 +442,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.2"
logging:
dependency: transitive
description:
name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
markdown:
dependency: transitive
description:

1
packages/neon/neon/lib/neon.dart

@ -89,6 +89,7 @@ part 'src/utils/settings_export_helper.dart';
part 'src/utils/sort_box_builder.dart';
part 'src/utils/sort_box_order_option_values.dart';
part 'src/utils/storage.dart';
part 'src/utils/stream_listenable.dart';
part 'src/utils/theme.dart';
part 'src/utils/validators.dart';
part 'src/widgets/account_avatar.dart';

2
packages/neon/neon/lib/src/app.dart

@ -295,7 +295,7 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
keepOriginalAccentColor: nextcloudTheme == null || (themeKeepOriginalAccentColor ?? false),
oledAsDark: themeOLEDAsDark,
),
routerDelegate: _routerDelegate,
routerConfig: _routerDelegate,
);
},
);

78
packages/neon/neon/lib/src/router.dart

@ -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));
}
}

57
packages/neon/neon/lib/src/router.g.dart

@ -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);
}

38
packages/neon/neon/lib/src/utils/stream_listenable.dart

@ -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();
}
}

14
packages/neon/neon/lib/src/widgets/exception.dart

@ -62,7 +62,7 @@ class NeonException extends StatelessWidget {
: AppLocalizations.of(context).actionRetry,
onPressed: () async {
if (details.isUnauthorized) {
await _openLoginPage(context);
_openLoginPage(context);
} else {
onRetry();
}
@ -177,14 +177,10 @@ class NeonException extends StatelessWidget {
);
}
static Future _openLoginPage(final BuildContext context) async {
await Navigator.of(context).push(
MaterialPageRoute(
builder: (final context) => LoginPage(
serverURL: Provider.of<AccountsBloc>(context, listen: false).activeAccount.value!.serverURL,
),
),
);
static void _openLoginPage(final BuildContext context) {
LoginRoute(
server: Provider.of<AccountsBloc>(context, listen: false).activeAccount.value!.serverURL,
).go(context);
}
}

4
packages/neon/neon/pubspec.yaml

@ -21,6 +21,7 @@ dependencies:
sdk: flutter
flutter_native_splash: ^2.2.19
flutter_svg: ^2.0.5
go_router: ^7.1.1
http: ^0.13.6
intl: ^0.18.0
json_annotation: ^4.8.1
@ -56,7 +57,8 @@ dependencies:
xml: ^6.3.0
dev_dependencies:
build_runner: ^2.4.2
build_runner: ^2.4.4
go_router_builder: ^2.0.1
json_serializable: ^6.6.2
nit_picking:
git:

Loading…
Cancel
Save