Browse Source

neon: change login routing

pull/291/head
Nikolas Rimikis 2 years ago
parent
commit
5be0f1c54c
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 3
      packages/neon/neon/lib/src/blocs/accounts.dart
  2. 30
      packages/neon/neon/lib/src/pages/login.dart
  3. 35
      packages/neon/neon/lib/src/pages/login_check_server_status.dart
  4. 5
      packages/neon/neon/lib/src/pages/login_flow.dart
  5. 58
      packages/neon/neon/lib/src/pages/login_qrcode.dart
  6. 4
      packages/neon/neon/lib/src/pages/settings.dart
  7. 225
      packages/neon/neon/lib/src/router.dart
  8. 166
      packages/neon/neon/lib/src/router.g.dart
  9. 8
      packages/neon/neon/lib/src/widgets/exception.dart

3
packages/neon/neon/lib/src/blocs/accounts.dart

@ -207,6 +207,9 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState
return aa; return aa;
} }
/// Whether accounts are logged in.
bool get hasAccounts => activeAccount.value != null;
/// The options for the [activeAccount]. /// The options for the [activeAccount].
/// ///
/// Convenience method for [getOptionsFor] with the currently active account. /// Convenience method for [getOptionsFor] with the currently active account.

30
packages/neon/neon/lib/src/pages/login.dart

@ -1,5 +1,3 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:neon/l10n/localizations.dart'; import 'package:neon/l10n/localizations.dart';
import 'package:neon/src/platform/platform.dart'; import 'package:neon/src/platform/platform.dart';
@ -12,12 +10,9 @@ import 'package:provider/provider.dart';
class LoginPage extends StatefulWidget { class LoginPage extends StatefulWidget {
const LoginPage({ const LoginPage({
this.serverURL,
super.key, super.key,
}); });
final String? serverURL;
@override @override
_LoginPageState createState() => _LoginPageState(); _LoginPageState createState() => _LoginPageState();
} }
@ -29,12 +24,6 @@ class _LoginPageState extends State<LoginPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (widget.serverURL != null) {
WidgetsBinding.instance.addPostFrameCallback((final _) async {
await _beginLoginFlow(widget.serverURL!);
});
}
} }
@override @override
@ -43,16 +32,6 @@ class _LoginPageState extends State<LoginPage> {
super.dispose(); super.dispose();
} }
Future _beginLoginFlow(final String serverURL) async {
final result = await LoginCheckServerStatusRoute(serverURL: serverURL).push<bool>(context);
if ((result ?? false) && mounted) {
// This needs be done, otherwise the context is dirty after returning from the previously pushed route
WidgetsBinding.instance.addPostFrameCallback((final _) async {
await LoginFlowRoute(serverURL: serverURL).push(context);
});
}
}
@override @override
Widget build(final BuildContext context) { Widget build(final BuildContext context) {
final branding = Branding.of(context); final branding = Branding.of(context);
@ -61,7 +40,7 @@ class _LoginPageState extends State<LoginPage> {
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
appBar: AppBar( appBar: AppBar(
leading: Navigator.of(context).canPop() ? const CloseButton() : null, leading: Navigator.canPop(context) ? const CloseButton() : null,
), ),
body: Center( body: Center(
child: ConstrainedBox( child: ConstrainedBox(
@ -102,7 +81,7 @@ class _LoginPageState extends State<LoginPage> {
Icons.qr_code_scanner, Icons.qr_code_scanner,
size: 50, size: 50,
), ),
onPressed: () => unawaited(const LoginQrcodeRoute().push(context)), onPressed: () => const LoginQrcodeRoute().go(context),
), ),
const SizedBox( const SizedBox(
height: 20, height: 20,
@ -121,11 +100,10 @@ class _LoginPageState extends State<LoginPage> {
hintText: 'https://...', hintText: 'https://...',
), ),
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
initialValue: widget.serverURL,
validator: (final input) => validateHttpUrl(context, input), validator: (final input) => validateHttpUrl(context, input),
onFieldSubmitted: (final input) async { onFieldSubmitted: (final input) {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
await _beginLoginFlow(input); LoginCheckServerStatusRoute(serverUrl: input).go(context);
} else { } else {
_focusNode.requestFocus(); _focusNode.requestFocus();
} }

35
packages/neon/neon/lib/src/pages/login_check_server_status.dart

@ -3,6 +3,7 @@ import 'package:neon/l10n/localizations.dart';
import 'package:neon/src/bloc/result.dart'; import 'package:neon/src/bloc/result.dart';
import 'package:neon/src/bloc/result_builder.dart'; import 'package:neon/src/bloc/result_builder.dart';
import 'package:neon/src/blocs/login_check_server_status.dart'; import 'package:neon/src/blocs/login_check_server_status.dart';
import 'package:neon/src/router.dart';
import 'package:neon/src/theme/dialog.dart'; import 'package:neon/src/theme/dialog.dart';
import 'package:neon/src/widgets/exception.dart'; import 'package:neon/src/widgets/exception.dart';
import 'package:neon/src/widgets/linear_progress_indicator.dart'; import 'package:neon/src/widgets/linear_progress_indicator.dart';
@ -13,9 +14,19 @@ class LoginCheckServerStatusPage extends StatefulWidget {
const LoginCheckServerStatusPage({ const LoginCheckServerStatusPage({
required this.serverURL, required this.serverURL,
super.key, super.key,
}) : loginName = null,
password = null;
const LoginCheckServerStatusPage.withCredentials({
required this.serverURL,
required String this.loginName,
required String this.password,
super.key,
}); });
final String serverURL; final String serverURL;
final String? loginName;
final String? password;
@override @override
State<LoginCheckServerStatusPage> createState() => _LoginCheckServerStatusPageState(); State<LoginCheckServerStatusPage> createState() => _LoginCheckServerStatusPageState();
@ -47,7 +58,10 @@ class _LoginCheckServerStatusPageState extends State<LoginCheckServerStatusPage>
constraints: NeonDialogTheme.of(context).constraints, constraints: NeonDialogTheme.of(context).constraints,
child: ResultBuilder.behaviorSubject( child: ResultBuilder.behaviorSubject(
stream: bloc.state, stream: bloc.state,
builder: (final context, final state) => Column( builder: (final context, final state) {
final success = state.hasData && state.requireData.isSupported && !state.requireData.maintenance;
return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
NeonLinearProgressIndicator( NeonLinearProgressIndicator(
@ -62,20 +76,31 @@ class _LoginCheckServerStatusPageState extends State<LoginCheckServerStatusPage>
Align( Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,
child: ElevatedButton( child: ElevatedButton(
onPressed: state.hasData && state.requireData.isSupported && !state.requireData.maintenance onPressed: success ? _onContinue : null,
? () => Navigator.of(context).pop(true)
: null,
child: Text(AppLocalizations.of(context).actionContinue), child: Text(AppLocalizations.of(context).actionContinue),
), ),
), ),
], ],
), );
},
), ),
), ),
), ),
), ),
); );
void _onContinue() {
if (widget.loginName != null) {
LoginCheckAccountRoute(
serverUrl: widget.serverURL,
loginName: widget.loginName!,
password: widget.password!,
).pushReplacement(context);
} else {
LoginFlowRoute(serverUrl: widget.serverURL).pushReplacement(context);
}
}
Widget _buildServerVersionTile(final Result<CoreServerStatus> result) { Widget _buildServerVersionTile(final Result<CoreServerStatus> result) {
if (!result.hasData) { if (!result.hasData) {
return NeonValidationTile( return NeonValidationTile(

5
packages/neon/neon/lib/src/pages/login_flow.dart

@ -39,7 +39,7 @@ class _LoginFlowPageState extends State<LoginFlowPage> {
bloc.result.listen((final result) { bloc.result.listen((final result) {
LoginCheckAccountRoute( LoginCheckAccountRoute(
serverURL: result.server, serverUrl: result.server,
loginName: result.loginName, loginName: result.loginName,
password: result.appPassword, password: result.appPassword,
).pushReplacement(context); ).pushReplacement(context);
@ -56,6 +56,8 @@ class _LoginFlowPageState extends State<LoginFlowPage> {
Widget build(final BuildContext context) => Scaffold( Widget build(final BuildContext context) => Scaffold(
appBar: AppBar(), appBar: AppBar(),
body: Center( body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: ResultBuilder.behaviorSubject( child: ResultBuilder.behaviorSubject(
stream: bloc.init, stream: bloc.init,
builder: (final context, final init) => Column( builder: (final context, final init) => Column(
@ -82,5 +84,6 @@ class _LoginFlowPageState extends State<LoginFlowPage> {
), ),
), ),
), ),
),
); );
} }

58
packages/neon/neon/lib/src/pages/login_qrcode.dart

@ -1,5 +1,3 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_zxing/flutter_zxing.dart'; import 'package:flutter_zxing/flutter_zxing.dart';
import 'package:neon/src/router.dart'; import 'package:neon/src/router.dart';
@ -41,7 +39,12 @@ class _LoginQrcodePageState extends State<LoginQrcodePage> {
if (match == null) { if (match == null) {
throw InvalidQrcodeException(); throw InvalidQrcodeException();
} }
await processLoginQrcode(context, match);
LoginCheckServerStatusRoute.withCredentials(
serverUrl: match.server,
loginName: match.user,
password: match.password,
).pushReplacement(context);
} catch (e, s) { } catch (e, s) {
if (_lastErrorURL != url) { if (_lastErrorURL != url) {
debugPrint(e.toString()); debugPrint(e.toString());
@ -55,52 +58,3 @@ class _LoginQrcodePageState extends State<LoginQrcodePage> {
), ),
); );
} }
class LoginQrcodeIntermediatePage extends StatefulWidget {
const LoginQrcodeIntermediatePage({
required this.serverURL,
required this.loginName,
required this.password,
super.key,
});
final String serverURL;
final String loginName;
final String password;
@override
State<LoginQrcodeIntermediatePage> createState() => _LoginQrcodeIntermediatePageState();
}
class _LoginQrcodeIntermediatePageState extends State<LoginQrcodeIntermediatePage> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((final _) {
unawaited(
processLoginQrcode(
context,
LoginQrcode(
server: widget.serverURL,
user: widget.loginName,
password: widget.password,
),
),
);
});
}
@override
Widget build(final BuildContext context) => const SizedBox();
}
Future processLoginQrcode(final BuildContext context, final LoginQrcode qrcode) async {
final result = await LoginCheckServerStatusRoute(serverURL: qrcode.server).push<bool>(context);
if ((result ?? false) && context.mounted) {
LoginCheckAccountRoute(
serverURL: qrcode.server,
loginName: qrcode.user,
password: qrcode.password,
).pushReplacement(context);
}
}

4
packages/neon/neon/lib/src/pages/settings.dart

@ -208,9 +208,7 @@ class _SettingsPageState extends State<SettingsPage> {
], ],
CustomSettingsTile( CustomSettingsTile(
title: ElevatedButton.icon( title: ElevatedButton.icon(
onPressed: () { onPressed: () async => const LoginRoute().push(context),
const AddAccountRoute().go(context);
},
icon: Icon(MdiIcons.accountPlus), icon: Icon(MdiIcons.accountPlus),
label: Text(AppLocalizations.of(context).globalOptionsAccountsAdd), label: Text(AppLocalizations.of(context).globalOptionsAccountsAdd),
), ),

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

@ -1,3 +1,7 @@
// ignore_for_file: unnecessary_overrides
import 'dart:async';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@ -29,19 +33,17 @@ class AppRouter extends GoRouter {
navigatorKey: navigatorKey, navigatorKey: navigatorKey,
initialLocation: const HomeRoute().location, initialLocation: const HomeRoute().location,
redirect: (final context, final state) { redirect: (final context, final state) {
final account = accountsBloc.activeAccount.valueOrNull;
final loginQrcode = LoginQrcode.tryParse(state.location); final loginQrcode = LoginQrcode.tryParse(state.location);
if (loginQrcode != null) { if (loginQrcode != null) {
return LoginQrcodeIntermediateRoute( return LoginCheckServerStatusRoute.withCredentials(
serverURL: loginQrcode.server, serverUrl: loginQrcode.server,
loginName: loginQrcode.user, loginName: loginQrcode.user,
password: loginQrcode.password, password: loginQrcode.password,
).location; ).location;
} }
// redirect to loginscreen when no account is logged in // redirect to loginscreen when no account is logged in
if (account == null && !state.location.startsWith(const LoginRoute().location)) { if (!accountsBloc.hasAccounts && !state.location.startsWith(const LoginRoute().location)) {
return const LoginRoute().location; return const LoginRoute().location;
} }
@ -83,9 +85,23 @@ class AccountSettingsRoute extends GoRouteData {
path: 'apps/:appid', path: 'apps/:appid',
name: 'NextcloudAppSettings', name: 'NextcloudAppSettings',
), ),
TypedGoRoute<AddAccountRoute>( TypedGoRoute<_AddAccountRoute>(
path: 'account/add', path: 'account/add',
name: 'addAccount', name: 'addAccount',
routes: [
TypedGoRoute<_AddAccountFlowRoute>(
path: 'flow',
),
TypedGoRoute<_AddAccountQrcodeRoute>(
path: 'qrcode',
),
TypedGoRoute<_AddAccountCheckServerStatusRoute>(
path: 'check/server',
),
TypedGoRoute<_AddAccountCheckAccountRoute>(
path: 'check/account',
),
],
), ),
TypedGoRoute<AccountSettingsRoute>( TypedGoRoute<AccountSettingsRoute>(
path: 'account/:accountid', path: 'account/:accountid',
@ -113,47 +129,59 @@ class HomeRoute extends GoRouteData {
name: 'login', name: 'login',
routes: [ routes: [
TypedGoRoute<LoginFlowRoute>( TypedGoRoute<LoginFlowRoute>(
path: 'flow/:serverURL', path: 'flow',
name: 'loginFlow',
), ),
TypedGoRoute<LoginQrcodeRoute>( TypedGoRoute<LoginQrcodeRoute>(
path: 'qrcode', path: 'qrcode',
name: 'loginQrcode',
),
TypedGoRoute<LoginQrcodeIntermediateRoute>(
path: 'qrcode/intermediate/:serverURL/:loginName/:password',
name: 'loginQrcodeIntermediate',
), ),
TypedGoRoute<LoginCheckServerStatusRoute>( TypedGoRoute<LoginCheckServerStatusRoute>(
path: 'check/server/:serverURL', path: 'check/server',
name: 'checkServerStatus',
), ),
TypedGoRoute<LoginCheckAccountRoute>( TypedGoRoute<LoginCheckAccountRoute>(
path: 'check/account/:serverURL/:loginName/:password', path: 'check/account',
name: 'checkAccount',
), ),
], ],
) )
@immutable @immutable
class LoginRoute extends GoRouteData { class LoginRoute extends GoRouteData {
const LoginRoute({this.serverURL}); const LoginRoute();
final String? serverURL; @override
Widget build(final BuildContext context, final GoRouterState state) => const LoginPage();
@override @override
Widget build(final BuildContext context, final GoRouterState state) => LoginPage(serverURL: serverURL); FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
if (state.fullPath == location && hasAccounts) {
return const _AddAccountRoute().location;
}
return null;
}
} }
@immutable @immutable
class LoginFlowRoute extends GoRouteData { class LoginFlowRoute extends GoRouteData {
const LoginFlowRoute({ const LoginFlowRoute({
required this.serverURL, required this.serverUrl,
}); });
final String serverURL; final String serverUrl;
@override @override
Widget build(final BuildContext context, final GoRouterState state) => LoginFlowPage(serverURL: serverURL); Widget build(final BuildContext context, final GoRouterState state) => LoginFlowPage(serverURL: serverUrl);
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
if (state.fullPath == location && hasAccounts) {
return _AddAccountFlowRoute(serverUrl: serverUrl).location;
}
return null;
}
} }
@immutable @immutable
@ -162,68 +190,161 @@ class LoginQrcodeRoute extends GoRouteData {
@override @override
Widget build(final BuildContext context, final GoRouterState state) => const LoginQrcodePage(); Widget build(final BuildContext context, final GoRouterState state) => const LoginQrcodePage();
}
@immutable @override
class LoginQrcodeIntermediateRoute extends GoRouteData { FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
const LoginQrcodeIntermediateRoute({ final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
required this.serverURL,
required this.loginName,
required this.password,
});
final String serverURL; if (state.fullPath == location && hasAccounts) {
final String loginName; return const _AddAccountQrcodeRoute().location;
final String password; }
@override return null;
Widget build(final BuildContext context, final GoRouterState state) => LoginQrcodeIntermediatePage( }
serverURL: serverURL,
loginName: loginName,
password: password,
);
} }
@immutable @immutable
class LoginCheckServerStatusRoute extends GoRouteData { class LoginCheckServerStatusRoute extends GoRouteData {
const LoginCheckServerStatusRoute({ const LoginCheckServerStatusRoute({
required this.serverURL, required this.serverUrl,
}); }) : loginName = null,
password = null;
final String serverURL; const LoginCheckServerStatusRoute.withCredentials({
required this.serverUrl,
required String this.loginName,
required String this.password,
}) : assert(!kIsWeb, 'Might leak the password to the browser history');
final String serverUrl;
final String? loginName;
final String? password;
@override @override
Widget build(final BuildContext context, final GoRouterState state) => LoginCheckServerStatusPage( Widget build(final BuildContext context, final GoRouterState state) {
serverURL: serverURL, if (loginName != null && password != null) {
return LoginCheckServerStatusPage.withCredentials(
serverURL: serverUrl,
loginName: loginName!,
password: password!,
);
}
return LoginCheckServerStatusPage(
serverURL: serverUrl,
); );
}
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
if (state.fullPath == location && hasAccounts) {
if (loginName != null && password != null) {
return _AddAccountCheckServerStatusRoute.withCredentials(
serverUrl: serverUrl,
loginName: loginName!,
password: password!,
).location;
}
return _AddAccountCheckServerStatusRoute(
serverUrl: serverUrl,
).location;
}
return null;
}
} }
@immutable @immutable
class LoginCheckAccountRoute extends GoRouteData { class LoginCheckAccountRoute extends GoRouteData {
const LoginCheckAccountRoute({ const LoginCheckAccountRoute({
required this.serverURL, required this.serverUrl,
required this.loginName, required this.loginName,
required this.password, required this.password,
}); }) : assert(!kIsWeb, 'Might leak the password to the browser history');
final String serverURL; final String serverUrl;
final String loginName; final String loginName;
final String password; final String password;
@override @override
Widget build(final BuildContext context, final GoRouterState state) => LoginCheckAccountPage( Widget build(final BuildContext context, final GoRouterState state) => LoginCheckAccountPage(
serverURL: serverURL, serverURL: serverUrl,
loginName: loginName, loginName: loginName,
password: password, password: password,
); );
@override
FutureOr<String?> redirect(final BuildContext context, final GoRouterState state) {
final hasAccounts = Provider.of<AccountsBloc>(context, listen: false).hasAccounts;
if (state.fullPath == location && hasAccounts) {
return _AddAccountCheckAccountRoute(
serverUrl: serverUrl,
loginName: loginName,
password: password,
).location;
}
return null;
}
}
@immutable
class _AddAccountRoute extends LoginRoute {
const _AddAccountRoute();
}
@immutable
class _AddAccountFlowRoute extends LoginFlowRoute {
const _AddAccountFlowRoute({
required super.serverUrl,
});
@override
String get serverUrl => super.serverUrl;
}
@immutable
class _AddAccountQrcodeRoute extends LoginQrcodeRoute {
const _AddAccountQrcodeRoute();
} }
@immutable @immutable
class AddAccountRoute extends GoRouteData { class _AddAccountCheckServerStatusRoute extends LoginCheckServerStatusRoute {
const AddAccountRoute(); const _AddAccountCheckServerStatusRoute({
required super.serverUrl,
});
const _AddAccountCheckServerStatusRoute.withCredentials({
required super.serverUrl,
required super.loginName,
required super.password,
}) : super.withCredentials();
@override @override
Widget build(final BuildContext context, final GoRouterState state) => const LoginPage(); String get serverUrl => super.serverUrl;
@override
String? get loginName => super.loginName;
@override
String? get password => super.password;
}
@immutable
class _AddAccountCheckAccountRoute extends LoginCheckAccountRoute {
const _AddAccountCheckAccountRoute({
required super.serverUrl,
required super.loginName,
required super.password,
});
@override
String get serverUrl => super.serverUrl;
@override
String get loginName => super.loginName;
@override
String get password => super.password;
} }
@immutable @immutable

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

@ -29,7 +29,25 @@ RouteBase get $homeRoute => GoRouteData.$route(
GoRouteData.$route( GoRouteData.$route(
path: 'account/add', path: 'account/add',
name: 'addAccount', name: 'addAccount',
factory: $AddAccountRouteExtension._fromState, factory: $_AddAccountRouteExtension._fromState,
routes: [
GoRouteData.$route(
path: 'flow',
factory: $_AddAccountFlowRouteExtension._fromState,
),
GoRouteData.$route(
path: 'qrcode',
factory: $_AddAccountQrcodeRouteExtension._fromState,
),
GoRouteData.$route(
path: 'check/server',
factory: $_AddAccountCheckServerStatusRouteExtension._fromState,
),
GoRouteData.$route(
path: 'check/account',
factory: $_AddAccountCheckAccountRouteExtension._fromState,
),
],
), ),
GoRouteData.$route( GoRouteData.$route(
path: 'account/:accountid', path: 'account/:accountid',
@ -85,8 +103,8 @@ extension $NextcloudAppSettingsRouteExtension on NextcloudAppSettingsRoute {
void pushReplacement(BuildContext context) => context.pushReplacement(location); void pushReplacement(BuildContext context) => context.pushReplacement(location);
} }
extension $AddAccountRouteExtension on AddAccountRoute { extension $_AddAccountRouteExtension on _AddAccountRoute {
static AddAccountRoute _fromState(GoRouterState state) => const AddAccountRoute(); static _AddAccountRoute _fromState(GoRouterState state) => const _AddAccountRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/settings/account/add', '/settings/account/add',
@ -99,6 +117,81 @@ extension $AddAccountRouteExtension on AddAccountRoute {
void pushReplacement(BuildContext context) => context.pushReplacement(location); void pushReplacement(BuildContext context) => context.pushReplacement(location);
} }
extension $_AddAccountFlowRouteExtension on _AddAccountFlowRoute {
static _AddAccountFlowRoute _fromState(GoRouterState state) => _AddAccountFlowRoute(
serverUrl: state.queryParameters['server-url']!,
);
String get location => GoRouteData.$location(
'/settings/account/add/flow',
queryParams: {
'server-url': serverUrl,
},
);
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 $_AddAccountQrcodeRouteExtension on _AddAccountQrcodeRoute {
static _AddAccountQrcodeRoute _fromState(GoRouterState state) => const _AddAccountQrcodeRoute();
String get location => GoRouteData.$location(
'/settings/account/add/qrcode',
);
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 $_AddAccountCheckServerStatusRouteExtension on _AddAccountCheckServerStatusRoute {
static _AddAccountCheckServerStatusRoute _fromState(GoRouterState state) => _AddAccountCheckServerStatusRoute(
serverUrl: state.queryParameters['server-url']!,
);
String get location => GoRouteData.$location(
'/settings/account/add/check/server',
queryParams: {
'server-url': serverUrl,
},
);
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 $_AddAccountCheckAccountRouteExtension on _AddAccountCheckAccountRoute {
static _AddAccountCheckAccountRoute _fromState(GoRouterState state) => _AddAccountCheckAccountRoute(
serverUrl: state.queryParameters['server-url']!,
loginName: state.queryParameters['login-name']!,
password: state.queryParameters['password']!,
);
String get location => GoRouteData.$location(
'/settings/account/add/check/account',
queryParams: {
'server-url': serverUrl,
'login-name': loginName,
'password': password,
},
);
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 { extension $AccountSettingsRouteExtension on AccountSettingsRoute {
static AccountSettingsRoute _fromState(GoRouterState state) => AccountSettingsRoute( static AccountSettingsRoute _fromState(GoRouterState state) => AccountSettingsRoute(
accountid: state.pathParameters['accountid']!, accountid: state.pathParameters['accountid']!,
@ -121,43 +214,29 @@ RouteBase get $loginRoute => GoRouteData.$route(
factory: $LoginRouteExtension._fromState, factory: $LoginRouteExtension._fromState,
routes: [ routes: [
GoRouteData.$route( GoRouteData.$route(
path: 'flow/:serverURL', path: 'flow',
name: 'loginFlow',
factory: $LoginFlowRouteExtension._fromState, factory: $LoginFlowRouteExtension._fromState,
), ),
GoRouteData.$route( GoRouteData.$route(
path: 'qrcode', path: 'qrcode',
name: 'loginQrcode',
factory: $LoginQrcodeRouteExtension._fromState, factory: $LoginQrcodeRouteExtension._fromState,
), ),
GoRouteData.$route( GoRouteData.$route(
path: 'qrcode/intermediate/:serverURL/:loginName/:password', path: 'check/server',
name: 'loginQrcodeIntermediate',
factory: $LoginQrcodeIntermediateRouteExtension._fromState,
),
GoRouteData.$route(
path: 'check/server/:serverURL',
name: 'checkServerStatus',
factory: $LoginCheckServerStatusRouteExtension._fromState, factory: $LoginCheckServerStatusRouteExtension._fromState,
), ),
GoRouteData.$route( GoRouteData.$route(
path: 'check/account/:serverURL/:loginName/:password', path: 'check/account',
name: 'checkAccount',
factory: $LoginCheckAccountRouteExtension._fromState, factory: $LoginCheckAccountRouteExtension._fromState,
), ),
], ],
); );
extension $LoginRouteExtension on LoginRoute { extension $LoginRouteExtension on LoginRoute {
static LoginRoute _fromState(GoRouterState state) => LoginRoute( static LoginRoute _fromState(GoRouterState state) => const LoginRoute();
serverURL: state.queryParameters['server-u-r-l'],
);
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/login', '/login',
queryParams: {
if (serverURL != null) 'server-u-r-l': serverURL,
},
); );
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@ -169,11 +248,14 @@ extension $LoginRouteExtension on LoginRoute {
extension $LoginFlowRouteExtension on LoginFlowRoute { extension $LoginFlowRouteExtension on LoginFlowRoute {
static LoginFlowRoute _fromState(GoRouterState state) => LoginFlowRoute( static LoginFlowRoute _fromState(GoRouterState state) => LoginFlowRoute(
serverURL: state.pathParameters['serverURL']!, serverUrl: state.queryParameters['server-url']!,
); );
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/login/flow/${Uri.encodeComponent(serverURL)}', '/login/flow',
queryParams: {
'server-url': serverUrl,
},
); );
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@ -197,31 +279,16 @@ extension $LoginQrcodeRouteExtension on LoginQrcodeRoute {
void pushReplacement(BuildContext context) => context.pushReplacement(location); void pushReplacement(BuildContext context) => context.pushReplacement(location);
} }
extension $LoginQrcodeIntermediateRouteExtension on LoginQrcodeIntermediateRoute {
static LoginQrcodeIntermediateRoute _fromState(GoRouterState state) => LoginQrcodeIntermediateRoute(
serverURL: state.pathParameters['serverURL']!,
loginName: state.pathParameters['loginName']!,
password: state.pathParameters['password']!,
);
String get location => GoRouteData.$location(
'/login/qrcode/intermediate/${Uri.encodeComponent(serverURL)}/${Uri.encodeComponent(loginName)}/${Uri.encodeComponent(password)}',
);
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 $LoginCheckServerStatusRouteExtension on LoginCheckServerStatusRoute { extension $LoginCheckServerStatusRouteExtension on LoginCheckServerStatusRoute {
static LoginCheckServerStatusRoute _fromState(GoRouterState state) => LoginCheckServerStatusRoute( static LoginCheckServerStatusRoute _fromState(GoRouterState state) => LoginCheckServerStatusRoute(
serverURL: state.pathParameters['serverURL']!, serverUrl: state.queryParameters['server-url']!,
); );
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/login/check/server/${Uri.encodeComponent(serverURL)}', '/login/check/server',
queryParams: {
'server-url': serverUrl,
},
); );
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@ -233,13 +300,18 @@ extension $LoginCheckServerStatusRouteExtension on LoginCheckServerStatusRoute {
extension $LoginCheckAccountRouteExtension on LoginCheckAccountRoute { extension $LoginCheckAccountRouteExtension on LoginCheckAccountRoute {
static LoginCheckAccountRoute _fromState(GoRouterState state) => LoginCheckAccountRoute( static LoginCheckAccountRoute _fromState(GoRouterState state) => LoginCheckAccountRoute(
serverURL: state.pathParameters['serverURL']!, serverUrl: state.queryParameters['server-url']!,
loginName: state.pathParameters['loginName']!, loginName: state.queryParameters['login-name']!,
password: state.pathParameters['password']!, password: state.queryParameters['password']!,
); );
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/login/check/account/${Uri.encodeComponent(serverURL)}/${Uri.encodeComponent(loginName)}/${Uri.encodeComponent(password)}', '/login/check/account',
queryParams: {
'server-url': serverUrl,
'login-name': loginName,
'password': password,
},
); );
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);

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

@ -185,9 +185,11 @@ class NeonException extends StatelessWidget {
} }
static void _openLoginPage(final BuildContext context) { static void _openLoginPage(final BuildContext context) {
LoginRoute( unawaited(
serverURL: Provider.of<AccountsBloc>(context, listen: false).activeAccount.value!.serverURL, LoginCheckServerStatusRoute(
).go(context); serverUrl: Provider.of<AccountsBloc>(context, listen: false).activeAccount.value!.serverURL,
).push(context),
);
} }
} }

Loading…
Cancel
Save