diff --git a/assets/translations/en.json b/assets/translations/en.json index fb47f515..06c982d2 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -693,6 +693,11 @@ "loading": "Loading token status", "used_by": "Used for {servers}.", "check_again": "Check again", - "no_tokens": "No tokens" + "no_tokens": "No tokens", + "server_without_token": "{server_domain} has no token for {provider}.", + "tap_to_add_token": "Tap here to add a token", + "add_server_provider_token": "Add server provider token", + "server_provider_unknown": "Unknown server provider", + "server_provider_unknown_description": "Your server provider is not supported by this app version." } } diff --git a/lib/logic/bloc/tokens/tokens_bloc.dart b/lib/logic/bloc/tokens/tokens_bloc.dart index 6ad2c35e..d825d502 100644 --- a/lib/logic/bloc/tokens/tokens_bloc.dart +++ b/lib/logic/bloc/tokens/tokens_bloc.dart @@ -8,10 +8,13 @@ import 'package:selfprivacy/logic/get_it/resources_model.dart'; import 'package:selfprivacy/logic/models/hive/backups_credential.dart'; import 'package:selfprivacy/logic/models/hive/dns_provider_credential.dart'; import 'package:selfprivacy/logic/models/hive/server.dart'; +import 'package:selfprivacy/logic/models/hive/server_details.dart'; import 'package:selfprivacy/logic/models/hive/server_provider_credential.dart'; +import 'package:selfprivacy/logic/models/server_basic_info.dart'; import 'package:selfprivacy/logic/providers/backups_providers/backups_provider_factory.dart'; import 'package:selfprivacy/logic/providers/dns_providers/dns_provider_factory.dart'; import 'package:selfprivacy/logic/providers/provider_settings.dart'; +import 'package:selfprivacy/logic/providers/providers_controller.dart'; import 'package:selfprivacy/logic/providers/server_providers/server_provider_factory.dart'; part 'tokens_event.dart'; @@ -23,6 +26,12 @@ class TokensBloc extends Bloc { validateTokens, transformer: droppable(), ); + on( + addServerProviderCredential, + ); + on( + connectServerToProviderToken, + ); add(const RevalidateTokens()); @@ -154,6 +163,51 @@ class TokensBloc extends Bloc { return TokenStatus.valid; } + Future addServerProviderCredential( + final AddServerProviderToken event, + final Emitter emit, + ) async { + await getIt() + .addServerProviderToken(event.serverProviderCredential); + + final ServerProviderSettings settings = ServerProviderSettings( + provider: event.serverProviderCredential.provider, + token: event.serverProviderCredential.token, + isAuthorized: true, + ); + ProvidersController.initServerProvider(settings); + } + + Future connectServerToProviderToken( + final ServerSelectedForProviderToken event, + final Emitter emit, + ) async { + await getIt().associateServerWithToken( + event.providerServer.id, + event.serverProviderCredential.token, + ); + final Server newServerData = Server( + domain: event.server.domain, + hostingDetails: ServerHostingDetails( + ip4: event.providerServer.ip, + id: event.providerServer.id, + createTime: event.providerServer.created, + volume: ServerProviderVolume( + id: 0, + name: 'recovered_volume', + sizeByte: 0, + serverId: event.providerServer.id, + linuxDevice: '', + ), + apiToken: event.server.hostingDetails.apiToken, + provider: event.serverProviderCredential.provider, + serverLocation: event.server.hostingDetails.serverLocation, + serverType: event.server.hostingDetails.serverType, + ), + ); + await getIt().updateServerByDomain(newServerData); + } + @override Future close() { _resourcesModelSubscription.cancel(); diff --git a/lib/logic/bloc/tokens/tokens_event.dart b/lib/logic/bloc/tokens/tokens_event.dart index b72f808a..deb1133c 100644 --- a/lib/logic/bloc/tokens/tokens_event.dart +++ b/lib/logic/bloc/tokens/tokens_event.dart @@ -10,3 +10,27 @@ class RevalidateTokens extends TokensEvent { @override List get props => []; } + +class AddServerProviderToken extends TokensEvent { + const AddServerProviderToken(this.serverProviderCredential); + + final ServerProviderCredential serverProviderCredential; + + @override + List get props => [serverProviderCredential]; +} + +class ServerSelectedForProviderToken extends TokensEvent { + const ServerSelectedForProviderToken( + this.providerServer, + this.server, + this.serverProviderCredential, + ); + + final ServerBasicInfoWithValidators providerServer; + final Server server; + final ServerProviderCredential serverProviderCredential; + + @override + List get props => [providerServer, server, serverProviderCredential]; +} diff --git a/lib/logic/bloc/tokens/tokens_state.dart b/lib/logic/bloc/tokens/tokens_state.dart index b0c58748..bfa599b5 100644 --- a/lib/logic/bloc/tokens/tokens_state.dart +++ b/lib/logic/bloc/tokens/tokens_state.dart @@ -26,6 +26,21 @@ sealed class TokensState extends Equatable { List> get backupsCredentials; List get servers => _servers; + List get serversWithoutProviderCredentials => servers + .where( + (final Server server) => + server.hostingDetails.provider != ServerProviderType.unknown && + serverProviderCredentials.every( + ( + final TokenStatusWrapper + serverProviderCredential, + ) => + !serverProviderCredential.data.associatedServerIds + .contains(server.hostingDetails.id), + ), + ) + .toList(); + Server getServerById(final int serverId) => servers.firstWhere( (final Server server) => server.hostingDetails.id == serverId, ); diff --git a/lib/logic/bloc/volumes/volumes_bloc.dart b/lib/logic/bloc/volumes/volumes_bloc.dart index eb654040..e2bfec0f 100644 --- a/lib/logic/bloc/volumes/volumes_bloc.dart +++ b/lib/logic/bloc/volumes/volumes_bloc.dart @@ -6,6 +6,7 @@ import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/api_maps/generic_result.dart'; +import 'package:selfprivacy/logic/get_it/resources_model.dart'; import 'package:selfprivacy/logic/models/disk_size.dart'; import 'package:selfprivacy/logic/models/disk_status.dart'; import 'package:selfprivacy/logic/models/hive/server_details.dart'; @@ -68,10 +69,18 @@ class VolumesBloc extends Bloc { } }, ); + + _resourcesModelSubscription = + getIt().statusStream.listen((final event) { + if (event is ChangedServerProviderCredentials) { + add(const VolumesServerLoaded()); + } + }); } late StreamSubscription _apiStatusSubscription; late StreamSubscription _apiDataSubscription; + late StreamSubscription _resourcesModelSubscription; bool isLoaded = false; Future getPricePerGb() async { @@ -145,6 +154,7 @@ class VolumesBloc extends Bloc { Future close() async { await _apiStatusSubscription.cancel(); await _apiDataSubscription.cancel(); + await _resourcesModelSubscription.cancel(); await super.close(); } diff --git a/lib/logic/cubit/forms/setup/initializing/add_server_provider_to_exsisting_server_form_cubit.dart b/lib/logic/cubit/forms/setup/initializing/add_server_provider_to_exsisting_server_form_cubit.dart new file mode 100644 index 00000000..27358807 --- /dev/null +++ b/lib/logic/cubit/forms/setup/initializing/add_server_provider_to_exsisting_server_form_cubit.dart @@ -0,0 +1,54 @@ +import 'dart:async'; + +import 'package:cubit_form/cubit_form.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; + +class AddServerProviderToExistingServerFormCubit extends FormCubit { + AddServerProviderToExistingServerFormCubit( + this.serverInstallationCubit, + this.setServerProviderKey, + ) { + apiKey = FieldCubit( + initalValue: '', + validations: [ + RequiredStringValidation('validations.required'.tr()), + ], + ); + + super.addFields([apiKey]); + } + + @override + FutureOr onSubmit() async { + // serverInstallationCubit.setServerProviderKey(apiKey.state.value); + setServerProviderKey(apiKey.state.value); + } + + final ServerInstallationCubit serverInstallationCubit; + final Function(String) setServerProviderKey; + late final FieldCubit apiKey; + + @override + FutureOr asyncValidation() async { + bool? isKeyValid; + + try { + isKeyValid = await serverInstallationCubit + .isServerProviderApiTokenValid(apiKey.state.value); + } catch (e) { + addError(e); + } + + if (isKeyValid == null) { + apiKey.setError(''); + return false; + } + + if (!isKeyValid) { + apiKey.setError('initializing.provider_bad_key_error'.tr()); + } + + return isKeyValid; + } +} diff --git a/lib/logic/cubit/server_installation/server_installation_cubit.dart b/lib/logic/cubit/server_installation/server_installation_cubit.dart index ae67c395..ce4dea94 100644 --- a/lib/logic/cubit/server_installation/server_installation_cubit.dart +++ b/lib/logic/cubit/server_installation/server_installation_cubit.dart @@ -11,6 +11,7 @@ import 'package:selfprivacy/logic/models/callback_dialogue_branching.dart'; import 'package:selfprivacy/logic/models/disk_size.dart'; import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/hive/backups_credential.dart'; +import 'package:selfprivacy/logic/models/hive/server.dart'; import 'package:selfprivacy/logic/models/hive/server_details.dart'; import 'package:selfprivacy/logic/models/hive/server_domain.dart'; import 'package:selfprivacy/logic/models/hive/user.dart'; @@ -708,29 +709,54 @@ class ServerInstallationCubit extends Cubit { ); } - Future> getAvailableServers() async { - final ServerInstallationRecovery dataState = - state as ServerInstallationRecovery; - final List servers = - await repository.getServersOnProviderAccount(); + Future> getAvailableServers({ + final Server? server, + }) async { List validatedList = []; - try { - final Iterable validated = servers.map( - (final ServerBasicInfo server) => - ServerBasicInfoWithValidators.fromServerBasicInfo( - serverBasicInfo: server, - isIpValid: server.ip == dataState.serverDetails?.ip4, - isReverseDnsValid: - server.reverseDns == dataState.serverDomain?.domainName || - server.reverseDns == - dataState.serverDomain?.domainName.split('.')[0], - ), - ); - validatedList = validated.toList(); - } catch (e) { - print(e); - getIt() - .showSnackBar('modals.server_validators_error'.tr()); + if (server != null) { + final List servers = + await repository.getServersOnProviderAccount(); + try { + final Iterable validated = servers.map( + (final ServerBasicInfo hostingServer) => + ServerBasicInfoWithValidators.fromServerBasicInfo( + serverBasicInfo: hostingServer, + isIpValid: hostingServer.ip == server.hostingDetails.ip4, + isReverseDnsValid: + hostingServer.reverseDns == server.domain.domainName || + hostingServer.reverseDns == + server.domain.domainName.split('.')[0], + ), + ); + validatedList = validated.toList(); + } catch (e) { + print(e); + getIt() + .showSnackBar('modals.server_validators_error'.tr()); + } + } else { + final ServerInstallationRecovery dataState = + state as ServerInstallationRecovery; + final List servers = + await repository.getServersOnProviderAccount(); + try { + final Iterable validated = servers.map( + (final ServerBasicInfo server) => + ServerBasicInfoWithValidators.fromServerBasicInfo( + serverBasicInfo: server, + isIpValid: server.ip == dataState.serverDetails?.ip4, + isReverseDnsValid: + server.reverseDns == dataState.serverDomain?.domainName || + server.reverseDns == + dataState.serverDomain?.domainName.split('.')[0], + ), + ); + validatedList = validated.toList(); + } catch (e) { + print(e); + getIt() + .showSnackBar('modals.server_validators_error'.tr()); + } } return validatedList; diff --git a/lib/logic/get_it/resources_model.dart b/lib/logic/get_it/resources_model.dart index 98204749..b2143559 100644 --- a/lib/logic/get_it/resources_model.dart +++ b/lib/logic/get_it/resources_model.dart @@ -173,6 +173,17 @@ class ResourcesModel { _statusStreamController.add(const ChangedServers()); } + Future updateServerByDomain(final Server server) async { + final index = _servers.indexWhere( + (final s) => s.domain.domainName == server.domain.domainName, + ); + if (index != -1) { + _servers[index] = server; + await _box.put(BNames.servers, _servers); + _statusStreamController.add(const ChangedServers()); + } + } + Future setBackblazeBucket(final BackblazeBucket bucket) async { _backblazeBucket = bucket; await _box.put(BNames.backblazeBucket, _backblazeBucket); diff --git a/lib/logic/models/hive/server_details.dart b/lib/logic/models/hive/server_details.dart index 9a11165c..da248c93 100644 --- a/lib/logic/models/hive/server_details.dart +++ b/lib/logic/models/hive/server_details.dart @@ -117,6 +117,12 @@ enum ServerProviderType { hetzner => 'Hetzner Cloud', unknown => 'Unknown', }; + + String get supportArticle => switch (this) { + digitalOcean => 'how_digital_ocean', + hetzner => 'how_hetzner', + unknown => '', + }; } extension ServerProviderTypeIsSpecified on ServerProviderType? { diff --git a/lib/ui/pages/more/tokens/add_server_provider_token.dart b/lib/ui/pages/more/tokens/add_server_provider_token.dart new file mode 100644 index 00000000..669d7cf8 --- /dev/null +++ b/lib/ui/pages/more/tokens/add_server_provider_token.dart @@ -0,0 +1,167 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:cubit_form/cubit_form.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:selfprivacy/logic/bloc/tokens/tokens_bloc.dart'; +import 'package:selfprivacy/logic/cubit/forms/setup/initializing/add_server_provider_to_exsisting_server_form_cubit.dart'; +import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; +import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart'; +import 'package:selfprivacy/logic/models/hive/server.dart'; +import 'package:selfprivacy/logic/models/hive/server_details.dart'; +import 'package:selfprivacy/logic/models/hive/server_provider_credential.dart'; +import 'package:selfprivacy/ui/components/buttons/brand_button.dart'; +import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; +import 'package:selfprivacy/ui/pages/setup/recovering/recovery_confirm_server.dart'; + +@RoutePage() +class AddServerProviderTokenPage extends StatefulWidget { + const AddServerProviderTokenPage({ + required this.server, + super.key, + }); + + final Server server; + + @override + State createState() => + _AddServerProviderTokenPageState(); +} + +class _AddServerProviderTokenPageState + extends State { + bool isChoosingServer = false; + ServerProviderCredential? credential; + + @override + Widget build(final BuildContext context) { + final ServerInstallationCubit appConfig = + context.watch(); + + void setServerProviderKey(final String key) { + final newCredential = ServerProviderCredential( + token: key, + provider: widget.server.hostingDetails.provider, + tokenId: null, + associatedServerIds: [], + ); + context.read().add( + AddServerProviderToken(newCredential), + ); + setState(() { + isChoosingServer = true; + credential = newCredential; + }); + } + + if (isChoosingServer && credential != null) { + return RecoveryConfirmServer( + server: widget.server, + serverProviderCredential: credential, + submitCallback: () { + Navigator.of(context).popUntil((final route) => route.isFirst); + }, + ); + } + + if (widget.server.hostingDetails.provider == ServerProviderType.unknown) { + return BrandHeroScreen( + heroTitle: 'tokens.server_provider_unknown'.tr(), + heroSubtitle: 'tokens.server_provider_unknown_description'.tr(), + hasBackButton: true, + hasFlashButton: false, + ignoreBreakpoints: true, + onBackButtonPressed: () { + Navigator.of(context).popUntil((final route) => route.isFirst); + }, + children: [ + BrandButton.filled( + text: 'basis.close'.tr(), + onPressed: () => + Navigator.of(context).popUntil((final route) => route.isFirst), + ), + ], + ); + } + + return _TokenProviderInput( + appConfig: appConfig, + server: widget.server, + setServerProviderKey: setServerProviderKey, + ); + } +} + +class _TokenProviderInput extends StatelessWidget { + const _TokenProviderInput({ + required this.appConfig, + required this.server, + required this.setServerProviderKey, + }); + + final ServerInstallationCubit appConfig; + final Server server; + final Function(String) setServerProviderKey; + + @override + Widget build(final BuildContext context) => BlocProvider( + create: (final BuildContext context) => + AddServerProviderToExistingServerFormCubit( + appConfig, + setServerProviderKey, + ), + child: Builder( + builder: (final BuildContext context) => BrandHeroScreen( + heroTitle: 'recovering.provider_connected'.tr( + args: [ + server.hostingDetails.provider.displayName, + ], + ), + heroSubtitle: 'recovering.provider_connected_description'.tr( + args: [server.domain.domainName], + ), + hasBackButton: true, + hasFlashButton: false, + hasSupportDrawer: true, + onBackButtonPressed: () { + Navigator.of(context).popUntil((final route) => route.isFirst); + }, + children: [ + CubitFormTextField( + autofocus: true, + formFieldCubit: context + .read() + .apiKey, + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: 'recovering.provider_connected_placeholder'.tr( + args: [ + server.hostingDetails.provider.displayName, + ], + ), + ), + ), + const Gap(16), + BrandButton.filled( + onPressed: () => context + .read() + .trySubmit(), + child: Text('basis.continue'.tr()), + ), + const Gap(16), + Builder( + builder: (final context) => BrandButton.text( + title: 'initializing.how'.tr(), + onPressed: () => context + .read() + .showArticle( + article: server.hostingDetails.provider.supportArticle, + context: context, + ), + ), + ), + ], + ), + ), + ); +} diff --git a/lib/ui/pages/more/tokens/tokens_page.dart b/lib/ui/pages/more/tokens/tokens_page.dart index 0fcfef4f..a715dd5c 100644 --- a/lib/ui/pages/more/tokens/tokens_page.dart +++ b/lib/ui/pages/more/tokens/tokens_page.dart @@ -10,6 +10,7 @@ import 'package:selfprivacy/logic/models/hive/server_provider_credential.dart'; import 'package:selfprivacy/ui/components/cards/filled_card.dart'; import 'package:selfprivacy/ui/components/list_tiles/list_tile_on_surface_variant.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; +import 'package:selfprivacy/ui/router/router.dart'; @RoutePage() class TokensPage extends StatelessWidget { @@ -29,10 +30,7 @@ class TokensPage extends StatelessWidget { ListTileOnSurfaceVariant( title: 'tokens.server_provider_tokens'.tr(), ), - Divider( - height: 0, - color: Theme.of(context).colorScheme.outline, - ), + const Divider(height: 0), if (state.serverProviderCredentials.isEmpty) ListTileOnSurfaceVariant( title: 'tokens.no_tokens'.tr(), @@ -48,6 +46,34 @@ class TokensPage extends StatelessWidget { ) .toList(), ), + if (state.serversWithoutProviderCredentials.isNotEmpty) + Column( + children: [ + const Divider(height: 0), + Column( + children: state.serversWithoutProviderCredentials + .map( + (final server) => ListTileOnSurfaceVariant( + title: 'tokens.server_without_token'.tr( + namedArgs: { + 'server_domain': server.domain.domainName, + 'provider': server + .hostingDetails.provider.displayName, + }, + ), + subtitle: 'tokens.tap_to_add_token'.tr(), + leadingIcon: Icons.add_circle_outline, + onTap: () => context.router.push( + AddServerProviderTokenRoute( + server: server, + ), + ), + ), + ) + .toList(), + ), + ], + ), ], ), ), @@ -58,10 +84,7 @@ class TokensPage extends StatelessWidget { ListTileOnSurfaceVariant( title: 'tokens.dns_provider_tokens'.tr(), ), - Divider( - height: 0, - color: Theme.of(context).colorScheme.outline, - ), + const Divider(height: 0), if (state.dnsProviderCredentials.isEmpty) ListTileOnSurfaceVariant( title: 'tokens.no_tokens'.tr(), @@ -86,10 +109,7 @@ class TokensPage extends StatelessWidget { ListTileOnSurfaceVariant( title: 'tokens.backup_provider_tokens'.tr(), ), - Divider( - height: 0, - color: Theme.of(context).colorScheme.outline, - ), + const Divider(height: 0), if (state.backupsCredentials.isEmpty) ListTileOnSurfaceVariant( title: 'tokens.no_tokens'.tr(), diff --git a/lib/ui/pages/setup/recovering/recovery_confirm_server.dart b/lib/ui/pages/setup/recovering/recovery_confirm_server.dart index 9e7709bc..3b3ac4b8 100644 --- a/lib/ui/pages/setup/recovering/recovery_confirm_server.dart +++ b/lib/ui/pages/setup/recovering/recovery_confirm_server.dart @@ -1,13 +1,25 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:selfprivacy/logic/bloc/tokens/tokens_bloc.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; +import 'package:selfprivacy/logic/models/hive/server.dart'; +import 'package:selfprivacy/logic/models/hive/server_provider_credential.dart'; import 'package:selfprivacy/logic/models/server_basic_info.dart'; import 'package:selfprivacy/ui/components/buttons/brand_button.dart'; import 'package:selfprivacy/ui/components/cards/filled_card.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; class RecoveryConfirmServer extends StatefulWidget { - const RecoveryConfirmServer({super.key}); + const RecoveryConfirmServer({ + this.server, + this.serverProviderCredential, + this.submitCallback, + super.key, + }); + + final Server? server; + final ServerProviderCredential? serverProviderCredential; + final Function? submitCallback; @override State createState() => _RecoveryConfirmServerState(); @@ -45,8 +57,9 @@ class _RecoveryConfirmServerState extends State { hasFlashButton: false, children: [ FutureBuilder>( - future: - context.read().getAvailableServers(), + future: context + .read() + .getAvailableServers(server: widget.server), builder: (final context, final snapshot) { if (snapshot.hasData) { final servers = snapshot.data; @@ -248,8 +261,21 @@ class _RecoveryConfirmServerState extends State { TextButton( child: Text('modals.yes'.tr()), onPressed: () { - context.read().setServerId(server); - Navigator.of(context).pop(); + if (widget.server != null && + widget.serverProviderCredential != null) { + context.read().add( + ServerSelectedForProviderToken( + server, + widget.server!, + widget.serverProviderCredential!, + ), + ); + Navigator.of(context).pop(); + widget.submitCallback?.call(); + } else { + context.read().setServerId(server); + Navigator.of(context).pop(); + } }, ), ], diff --git a/lib/ui/router/router.dart b/lib/ui/router/router.dart index 7c1d9fe3..987b080f 100644 --- a/lib/ui/router/router.dart +++ b/lib/ui/router/router.dart @@ -2,6 +2,7 @@ import 'package:animations/animations.dart'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:selfprivacy/logic/models/disk_status.dart'; +import 'package:selfprivacy/logic/models/hive/server.dart'; import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/ui/pages/backups/backup_details.dart'; import 'package:selfprivacy/ui/pages/backups/backups_list.dart'; @@ -12,6 +13,7 @@ import 'package:selfprivacy/ui/pages/more/app_settings/app_settings.dart'; import 'package:selfprivacy/ui/pages/more/app_settings/developer_settings.dart'; import 'package:selfprivacy/ui/pages/more/console/console_page.dart'; import 'package:selfprivacy/ui/pages/more/more.dart'; +import 'package:selfprivacy/ui/pages/more/tokens/add_server_provider_token.dart'; import 'package:selfprivacy/ui/pages/more/tokens/tokens_page.dart'; import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart'; import 'package:selfprivacy/ui/pages/providers/providers.dart'; @@ -111,6 +113,7 @@ class RootRouter extends _$RootRouter { AutoRoute(page: ServerLogsRoute.page), AutoRoute(page: TokensRoute.page), AutoRoute(page: MemoryUsageByServiceRoute.page), + AutoRoute(page: AddServerProviderTokenRoute.page), ], ), AutoRoute(page: ServicesMigrationRoute.page), @@ -170,6 +173,8 @@ String getRouteTitle(final String routeName) { return 'tokens.title'; case 'MemoryUsageByServiceRoute': return 'resource_chart.memory'; + case 'AddServerProviderTokenPage': + return 'tokens.add_server_provider_token'; default: return routeName; } diff --git a/lib/ui/router/router.gr.dart b/lib/ui/router/router.gr.dart index 2936f3fe..76161cbe 100644 --- a/lib/ui/router/router.gr.dart +++ b/lib/ui/router/router.gr.dart @@ -21,6 +21,16 @@ abstract class _$RootRouter extends RootStackRouter { child: const AboutApplicationPage(), ); }, + AddServerProviderTokenRoute.name: (routeData) { + final args = routeData.argsAs(); + return AutoRoutePage( + routeData: routeData, + child: AddServerProviderTokenPage( + server: args.server, + key: args.key, + ), + ); + }, AppSettingsRoute.name: (routeData) { return AutoRoutePage( routeData: routeData, @@ -242,6 +252,45 @@ class AboutApplicationRoute extends PageRouteInfo { static const PageInfo page = PageInfo(name); } +/// generated route for +/// [AddServerProviderTokenPage] +class AddServerProviderTokenRoute + extends PageRouteInfo { + AddServerProviderTokenRoute({ + required Server server, + Key? key, + List? children, + }) : super( + AddServerProviderTokenRoute.name, + args: AddServerProviderTokenRouteArgs( + server: server, + key: key, + ), + initialChildren: children, + ); + + static const String name = 'AddServerProviderTokenRoute'; + + static const PageInfo page = + PageInfo(name); +} + +class AddServerProviderTokenRouteArgs { + const AddServerProviderTokenRouteArgs({ + required this.server, + this.key, + }); + + final Server server; + + final Key? key; + + @override + String toString() { + return 'AddServerProviderTokenRouteArgs{server: $server, key: $key}'; + } +} + /// generated route for /// [AppSettingsPage] class AppSettingsRoute extends PageRouteInfo {