|
|
@ -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'; |
|
|
@ -11,6 +15,7 @@ import 'package:neon/src/pages/login.dart'; |
|
|
|
import 'package:neon/src/pages/login_check_account.dart'; |
|
|
|
import 'package:neon/src/pages/login_check_account.dart'; |
|
|
|
import 'package:neon/src/pages/login_check_server_status.dart'; |
|
|
|
import 'package:neon/src/pages/login_check_server_status.dart'; |
|
|
|
import 'package:neon/src/pages/login_flow.dart'; |
|
|
|
import 'package:neon/src/pages/login_flow.dart'; |
|
|
|
|
|
|
|
import 'package:neon/src/pages/login_qrcode.dart'; |
|
|
|
import 'package:neon/src/pages/nextcloud_app_settings.dart'; |
|
|
|
import 'package:neon/src/pages/nextcloud_app_settings.dart'; |
|
|
|
import 'package:neon/src/pages/settings.dart'; |
|
|
|
import 'package:neon/src/pages/settings.dart'; |
|
|
|
import 'package:neon/src/utils/stream_listenable.dart'; |
|
|
|
import 'package:neon/src/utils/stream_listenable.dart'; |
|
|
@ -29,10 +34,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); |
|
|
|
|
|
|
|
if (loginQrcode != null) { |
|
|
|
|
|
|
|
return LoginCheckServerStatusRoute.withCredentials( |
|
|
|
|
|
|
|
serverUrl: loginQrcode.serverURL, |
|
|
|
|
|
|
|
loginName: loginQrcode.username, |
|
|
|
|
|
|
|
password: loginQrcode.password, |
|
|
|
|
|
|
|
).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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -74,9 +86,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', |
|
|
@ -104,81 +130,222 @@ class HomeRoute extends GoRouteData { |
|
|
|
name: 'login', |
|
|
|
name: 'login', |
|
|
|
routes: [ |
|
|
|
routes: [ |
|
|
|
TypedGoRoute<LoginFlowRoute>( |
|
|
|
TypedGoRoute<LoginFlowRoute>( |
|
|
|
path: 'flow/:serverURL', |
|
|
|
path: 'flow', |
|
|
|
name: 'loginFlow', |
|
|
|
), |
|
|
|
|
|
|
|
TypedGoRoute<LoginQrcodeRoute>( |
|
|
|
|
|
|
|
path: 'qrcode', |
|
|
|
), |
|
|
|
), |
|
|
|
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 |
|
|
|
|
|
|
|
class LoginQrcodeRoute extends GoRouteData { |
|
|
|
|
|
|
|
const LoginQrcodeRoute(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
|
|
|
Widget build(final BuildContext context, final GoRouterState state) => const LoginQrcodePage(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@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 const _AddAccountQrcodeRoute().location; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@immutable |
|
|
|
@immutable |
|
|
|
class LoginCheckServerStatusRoute extends GoRouteData { |
|
|
|
class LoginCheckServerStatusRoute extends GoRouteData { |
|
|
|
const LoginCheckServerStatusRoute({ |
|
|
|
const LoginCheckServerStatusRoute({ |
|
|
|
required this.serverURL, |
|
|
|
required this.serverUrl, |
|
|
|
}); |
|
|
|
}) : loginName = null, |
|
|
|
|
|
|
|
password = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 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 |
|
|
|
@immutable |
|
|
|
class AddAccountRoute extends GoRouteData { |
|
|
|
class _AddAccountRoute extends LoginRoute { |
|
|
|
const AddAccountRoute(); |
|
|
|
const _AddAccountRoute(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@immutable |
|
|
|
|
|
|
|
class _AddAccountFlowRoute extends LoginFlowRoute { |
|
|
|
|
|
|
|
const _AddAccountFlowRoute({ |
|
|
|
|
|
|
|
required super.serverUrl, |
|
|
|
|
|
|
|
}); |
|
|
|
@override |
|
|
|
@override |
|
|
|
Widget build(final BuildContext context, final GoRouterState state) => const LoginPage(); |
|
|
|
String get serverUrl => super.serverUrl; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@immutable |
|
|
|
|
|
|
|
class _AddAccountQrcodeRoute extends LoginQrcodeRoute { |
|
|
|
|
|
|
|
const _AddAccountQrcodeRoute(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@immutable |
|
|
|
|
|
|
|
class _AddAccountCheckServerStatusRoute extends LoginCheckServerStatusRoute { |
|
|
|
|
|
|
|
const _AddAccountCheckServerStatusRoute({ |
|
|
|
|
|
|
|
required super.serverUrl, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const _AddAccountCheckServerStatusRoute.withCredentials({ |
|
|
|
|
|
|
|
required super.serverUrl, |
|
|
|
|
|
|
|
required super.loginName, |
|
|
|
|
|
|
|
required super.password, |
|
|
|
|
|
|
|
}) : super.withCredentials(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
|
|
|
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 |
|
|
|