From c17d87c34875dca2d3915ee2f54ddc071674e6b6 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Fri, 6 Dec 2024 18:59:10 +0300 Subject: [PATCH] refactor(ui): Refactor Devices screen UI --- assets/translations/en.json | 3 +- lib/ui/atoms/list_tiles/section_headline.dart | 15 +- lib/ui/atoms/list_tiles/section_title.dart | 5 +- lib/ui/layouts/brand_hero_screen.dart | 7 +- lib/ui/molecules/list_items/device_item.dart | 131 +++++++++++++++ lib/ui/organisms/displays/key_display.dart | 60 +++++++ lib/ui/pages/backups/backup_details.dart | 11 +- lib/ui/pages/devices/devices.dart | 157 ++---------------- lib/ui/pages/devices/new_device.dart | 62 +------ lib/ui/pages/more/about_application.dart | 1 - .../more/app_settings/developer_settings.dart | 1 - lib/ui/pages/recovery_key/recovery_key.dart | 2 +- .../recovery_key/recovery_key_receiving.dart | 33 +--- lib/ui/router/router.dart | 2 + lib/ui/router/router.gr.dart | 23 ++- 15 files changed, 269 insertions(+), 244 deletions(-) create mode 100644 lib/ui/molecules/list_items/device_item.dart create mode 100644 lib/ui/organisms/displays/key_display.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index a19eccea..bf1db1e8 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -249,7 +249,7 @@ "autobackup_period_disable": "Disable automatic backups", "autobackup_set_period": "Set period", "backups_encryption_key": "Encryption key", - "backups_encryption_key_subtitle": "Keep it in a safe place.", + "backups_encryption_key_subtitle": "Keep it in a safe place", "backups_encryption_key_copy": "Copy the encryption key", "backups_encryption_key_show": "Show the encryption key", "backups_encryption_key_description": "This key is used to encrypt your backups. If you lose it, you will not be able to restore your backups. Keep it in a safe place, as it will be useful if you ever need to restore from backups manually.", @@ -598,7 +598,6 @@ "key_replace_button": "Generate new key", "key_receiving_description": "Write down this key and put to a safe place. It is used to restore full access to your server:", "key_receiving_info": "The key will never ever be shown again, but you will be able to replace it with another one.", - "key_receiving_done": "Done!", "generation_error": "Couldn't generate a recovery key. {}" }, "modals": { diff --git a/lib/ui/atoms/list_tiles/section_headline.dart b/lib/ui/atoms/list_tiles/section_headline.dart index be43d871..8423134e 100644 --- a/lib/ui/atoms/list_tiles/section_headline.dart +++ b/lib/ui/atoms/list_tiles/section_headline.dart @@ -1,15 +1,14 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class SectionHeadline extends StatelessWidget { const SectionHeadline({ required this.title, - required this.subtitle, + this.subtitle, super.key, }); final String title; - final String subtitle; + final String? subtitle; @override Widget build(final BuildContext context) => ListTile( @@ -19,9 +18,11 @@ class SectionHeadline extends StatelessWidget { color: Theme.of(context).colorScheme.secondary, ), ), - subtitle: Text( - subtitle, - style: Theme.of(context).textTheme.labelMedium, - ), + subtitle: subtitle != null + ? Text( + subtitle!, + style: Theme.of(context).textTheme.labelMedium, + ) + : null, ); } diff --git a/lib/ui/atoms/list_tiles/section_title.dart b/lib/ui/atoms/list_tiles/section_title.dart index dcf503c2..2ea28fc8 100644 --- a/lib/ui/atoms/list_tiles/section_title.dart +++ b/lib/ui/atoms/list_tiles/section_title.dart @@ -12,7 +12,10 @@ class SectionTitle extends StatelessWidget { @override Widget build(final BuildContext context) => Padding( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), child: Text( title, style: Theme.of(context).textTheme.labelLarge!.copyWith( diff --git a/lib/ui/layouts/brand_hero_screen.dart b/lib/ui/layouts/brand_hero_screen.dart index a58ea124..b331201c 100644 --- a/lib/ui/layouts/brand_hero_screen.dart +++ b/lib/ui/layouts/brand_hero_screen.dart @@ -19,7 +19,10 @@ class BrandHeroScreen extends StatelessWidget { this.heroTitle = '', this.heroSubtitle, this.onBackButtonPressed, - this.bodyPadding = const EdgeInsets.all(16.0), + this.bodyPadding = const EdgeInsets.symmetric( + vertical: 16.0, + horizontal: 8.0, + ), this.ignoreBreakpoints = false, this.hasSupportDrawer = false, }); @@ -80,7 +83,7 @@ class BrandHeroScreen extends StatelessWidget { style: Theme.of(context).textTheme.bodyMedium!.copyWith( color: Theme.of(context).colorScheme.onSurface, ), - textAlign: hasHeroIcon ? TextAlign.center : TextAlign.start, + textAlign: TextAlign.center, ), ]), ), diff --git a/lib/ui/molecules/list_items/device_item.dart b/lib/ui/molecules/list_items/device_item.dart new file mode 100644 index 00000000..ea2dbccb --- /dev/null +++ b/lib/ui/molecules/list_items/device_item.dart @@ -0,0 +1,131 @@ +import 'package:cubit_form/cubit_form.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:selfprivacy/logic/bloc/devices/devices_bloc.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/json/api_token.dart'; + +class DeviceItem extends StatelessWidget { + const DeviceItem({ + required this.device, + super.key, + }); + + final ApiToken device; + + @override + Widget build(final BuildContext context) => ListTile( + title: Text(device.name), + subtitle: Text( + 'devices.main_screen.access_granted_on' + .tr(args: [DateFormat.yMMMMd().format(device.date)]), + ), + onTap: device.isCaller + ? () => _showTokenRefreshDialog(context, device) + : () => _showConfirmationDialog(context, device), + ); + + Future _showConfirmationDialog( + final BuildContext context, + final ApiToken device, + ) => + showDialog( + context: context, + builder: (final context) => AlertDialog( + title: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Icons.link_off_outlined), + const SizedBox(height: 16), + Text( + 'devices.revoke_device_alert.header'.tr(), + style: Theme.of(context).textTheme.headlineSmall, + textAlign: TextAlign.center, + ), + ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'devices.revoke_device_alert.description' + .tr(args: [device.name]), + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), + actions: [ + TextButton( + child: Text('devices.revoke_device_alert.no'.tr()), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text( + 'devices.revoke_device_alert.yes'.tr(), + style: Theme.of(context).textTheme.labelLarge?.copyWith( + color: Theme.of(context).colorScheme.error, + ), + ), + onPressed: () { + context.read().add(DeleteDevice(device)); + Navigator.of(context).pop(); + }, + ), + ], + ), + ); + + Future _showTokenRefreshDialog( + final BuildContext context, + final ApiToken device, + ) => + showDialog( + context: context, + builder: (final context) => AlertDialog( + title: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Icons.update_outlined), + const SizedBox(height: 16), + Text( + 'devices.refresh_token_alert.header'.tr(), + style: Theme.of(context).textTheme.headlineSmall, + textAlign: TextAlign.center, + ), + ], + ), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'devices.refresh_token_alert.description' + .tr(args: [device.name]), + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), + actions: [ + TextButton( + child: Text('devices.refresh_token_alert.no'.tr()), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text('devices.refresh_token_alert.yes'.tr()), + onPressed: () { + context + .read() + .add(const RefreshServerApiTokenEvent()); + Navigator.of(context).pop(); + }, + ), + ], + ), + ); +} diff --git a/lib/ui/organisms/displays/key_display.dart b/lib/ui/organisms/displays/key_display.dart new file mode 100644 index 00000000..4771465b --- /dev/null +++ b/lib/ui/organisms/displays/key_display.dart @@ -0,0 +1,60 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:selfprivacy/ui/atoms/buttons/brand_button.dart'; +import 'package:selfprivacy/ui/molecules/info_box/info_box.dart'; + +class KeyDisplay extends StatelessWidget { + const KeyDisplay({ + required this.keyToDisplay, + required this.canCopy, + required this.infoboxText, + super.key, + }); + + final String keyToDisplay; + final bool canCopy; + final String infoboxText; + + @override + Widget build(final BuildContext context) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider(), + const SizedBox(height: 16), + if (canCopy) + SelectableText( + keyToDisplay, + style: Theme.of(context).textTheme.bodyLarge!.copyWith( + fontSize: 24, + fontFamily: 'RobotoMono', + ), + textAlign: TextAlign.center, + ), + if (!canCopy) + Text( + keyToDisplay, + style: Theme.of(context).textTheme.bodyLarge!.copyWith( + fontSize: 24, + fontFamily: 'RobotoMono', + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + const Divider(), + const SizedBox(height: 16), + InfoBox( + text: infoboxText, + ), + const SizedBox(height: 16), + BrandButton.filled( + child: Text( + 'basis.done'.tr(), + ), + onPressed: () { + Navigator.of(context).popUntil((final route) => route.isFirst); + }, + ), + const SizedBox(height: 24), + ], + ); +} diff --git a/lib/ui/pages/backups/backup_details.dart b/lib/ui/pages/backups/backup_details.dart index 6f0c4dea..01f57566 100644 --- a/lib/ui/pages/backups/backup_details.dart +++ b/lib/ui/pages/backups/backup_details.dart @@ -257,13 +257,8 @@ class BackupDetailsPage extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ListTile( - title: Text( - 'backup.pending_jobs'.tr(), - style: Theme.of(context).textTheme.headlineSmall!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), - ), + SectionHeadline( + title: 'backup.pending_jobs'.tr(), ), for (final job in backupJobs) Padding( @@ -312,7 +307,6 @@ class BackupDetailsPage extends StatelessWidget { ListTile( title: Text( 'backup.show_more'.tr(), - style: Theme.of(context).textTheme.labelMedium, ), leading: const Icon( Icons.arrow_drop_down, @@ -345,6 +339,7 @@ class BackupDetailsPage extends StatelessWidget { Icons.cached_outlined, color: overrideColor, ), + isThreeLine: true, onTap: preventActions ? null : () => context diff --git a/lib/ui/pages/devices/devices.dart b/lib/ui/pages/devices/devices.dart index 1adb8472..57b120fa 100644 --- a/lib/ui/pages/devices/devices.dart +++ b/lib/ui/pages/devices/devices.dart @@ -3,23 +3,22 @@ import 'package:cubit_form/cubit_form.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:selfprivacy/logic/bloc/devices/devices_bloc.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/json/api_token.dart'; +import 'package:selfprivacy/ui/atoms/list_tiles/section_title.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; import 'package:selfprivacy/ui/molecules/info_box/info_box.dart'; -import 'package:selfprivacy/ui/pages/devices/new_device.dart'; -import 'package:selfprivacy/utils/route_transitions/basic.dart'; +import 'package:selfprivacy/ui/molecules/list_items/device_item.dart'; +import 'package:selfprivacy/ui/router/router.dart'; @RoutePage() -class DevicesScreen extends StatefulWidget { - const DevicesScreen({super.key}); +class DevicesPage extends StatefulWidget { + const DevicesPage({super.key}); @override - State createState() => _DevicesScreenState(); + State createState() => _DevicesPageState(); } -class _DevicesScreenState extends State { +class _DevicesPageState extends State { @override Widget build(final BuildContext context) { final DevicesState devicesStatus = context.watch().state; @@ -31,6 +30,7 @@ class _DevicesScreenState extends State { child: BrandHeroScreen( heroTitle: 'devices.main_screen.header'.tr(), heroSubtitle: 'devices.main_screen.description'.tr(), + heroIcon: Icons.devices_outlined, hasBackButton: true, hasFlashButton: false, children: [ @@ -46,8 +46,7 @@ class _DevicesScreenState extends State { ), const SizedBox(height: 16), OutlinedButton( - onPressed: () => Navigator.of(context) - .push(materialRoute(const NewDeviceScreen())), + onPressed: () => context.pushRoute(const NewDeviceRoute()), child: Text('devices.main_screen.authorize_new_device'.tr()), ), const SizedBox(height: 16), @@ -75,22 +74,17 @@ class _DevicesInfo extends StatelessWidget { Widget build(final BuildContext context) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'devices.main_screen.this_device'.tr(), - style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), + SectionTitle( + title: 'devices.main_screen.this_device'.tr(), ), - _DeviceTile( + DeviceItem( device: devicesStatus.thisDevice, ), + const SizedBox(height: 8), const Divider(height: 1), - const SizedBox(height: 16), - Text( - 'devices.main_screen.other_devices'.tr(), - style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), + const SizedBox(height: 8), + SectionTitle( + title: 'devices.main_screen.other_devices'.tr(), ), if (devicesStatus is DevicesDeleting) ...[ const Center( @@ -100,127 +94,10 @@ class _DevicesInfo extends StatelessWidget { ], if (devicesStatus is! DevicesDeleting) ...devicesStatus.otherDevices.map( - (final device) => _DeviceTile( + (final device) => DeviceItem( device: device, ), ), ], ); } - -class _DeviceTile extends StatelessWidget { - const _DeviceTile({required this.device}); - - final ApiToken device; - - @override - Widget build(final BuildContext context) => ListTile( - contentPadding: EdgeInsets.zero, - title: Text(device.name), - subtitle: Text( - 'devices.main_screen.access_granted_on' - .tr(args: [DateFormat.yMMMMd().format(device.date)]), - ), - onTap: device.isCaller - ? () => _showTokenRefreshDialog(context, device) - : () => _showConfirmationDialog(context, device), - ); - - Future _showConfirmationDialog( - final BuildContext context, - final ApiToken device, - ) => - showDialog( - context: context, - builder: (final context) => AlertDialog( - title: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon(Icons.link_off_outlined), - const SizedBox(height: 16), - Text( - 'devices.revoke_device_alert.header'.tr(), - style: Theme.of(context).textTheme.headlineSmall, - textAlign: TextAlign.center, - ), - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'devices.revoke_device_alert.description' - .tr(args: [device.name]), - style: Theme.of(context).textTheme.bodyMedium, - ), - ], - ), - actions: [ - TextButton( - child: Text('devices.revoke_device_alert.no'.tr()), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: Text('devices.revoke_device_alert.yes'.tr()), - onPressed: () { - context.read().add(DeleteDevice(device)); - Navigator.of(context).pop(); - }, - ), - ], - ), - ); - - Future _showTokenRefreshDialog( - final BuildContext context, - final ApiToken device, - ) => - showDialog( - context: context, - builder: (final context) => AlertDialog( - title: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon(Icons.update_outlined), - const SizedBox(height: 16), - Text( - 'devices.refresh_token_alert.header'.tr(), - style: Theme.of(context).textTheme.headlineSmall, - textAlign: TextAlign.center, - ), - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'devices.refresh_token_alert.description' - .tr(args: [device.name]), - style: Theme.of(context).textTheme.bodyMedium, - ), - ], - ), - actions: [ - TextButton( - child: Text('devices.refresh_token_alert.no'.tr()), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: Text('devices.refresh_token_alert.yes'.tr()), - onPressed: () { - context - .read() - .add(const RefreshServerApiTokenEvent()); - Navigator.of(context).pop(); - }, - ), - ], - ), - ); -} diff --git a/lib/ui/pages/devices/new_device.dart b/lib/ui/pages/devices/new_device.dart index d5b875af..019a8e9b 100644 --- a/lib/ui/pages/devices/new_device.dart +++ b/lib/ui/pages/devices/new_device.dart @@ -1,13 +1,15 @@ +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:selfprivacy/logic/bloc/devices/devices_bloc.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; -import 'package:selfprivacy/ui/atoms/buttons/brand_button.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; +import 'package:selfprivacy/ui/organisms/displays/key_display.dart'; -class NewDeviceScreen extends StatelessWidget { - const NewDeviceScreen({super.key}); +@RoutePage() +class NewDevicePage extends StatelessWidget { + const NewDevicePage({super.key}); @override Widget build(final BuildContext context) => BrandHeroScreen( @@ -23,8 +25,10 @@ class NewDeviceScreen extends StatelessWidget { final AsyncSnapshot snapshot, ) { if (snapshot.hasData) { - return _KeyDisplay( - newDeviceKey: snapshot.data.toString(), + return KeyDisplay( + keyToDisplay: snapshot.data.toString(), + canCopy: true, + infoboxText: 'devices.add_new_device_screen.tip'.tr(), ); } else { return const Center( @@ -36,51 +40,3 @@ class NewDeviceScreen extends StatelessWidget { ], ); } - -class _KeyDisplay extends StatelessWidget { - const _KeyDisplay({required this.newDeviceKey}); - - final String newDeviceKey; - - @override - Widget build(final BuildContext context) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Divider(), - const SizedBox(height: 16), - SelectableText( - newDeviceKey, - style: Theme.of(context).textTheme.bodyLarge!.copyWith( - fontSize: 24, - fontFamily: 'RobotoMono', - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 16), - const Divider(), - const SizedBox(height: 16), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - Icons.info_outline, - color: Theme.of(context).colorScheme.onSurface, - ), - const SizedBox(height: 16), - Text( - 'devices.add_new_device_screen.tip'.tr(), - style: Theme.of(context).textTheme.bodyMedium, - ), - ], - ), - const SizedBox(height: 16), - BrandButton.filled( - child: Text( - 'basis.done'.tr(), - ), - onPressed: () => Navigator.of(context).pop(), - ), - const SizedBox(height: 24), - ], - ); -} diff --git a/lib/ui/pages/more/about_application.dart b/lib/ui/pages/more/about_application.dart index 8c62bbe4..63e87418 100644 --- a/lib/ui/pages/more/about_application.dart +++ b/lib/ui/pages/more/about_application.dart @@ -43,7 +43,6 @@ class AboutApplicationPage extends StatelessWidget { hasBackButton: true, hasFlashButton: false, heroTitle: 'about_application_page.title'.tr(), - bodyPadding: const EdgeInsets.symmetric(vertical: 16), children: [ SectionTitle(title: 'about_application_page.versions'.tr()), FutureBuilder( diff --git a/lib/ui/pages/more/app_settings/developer_settings.dart b/lib/ui/pages/more/app_settings/developer_settings.dart index 4430773a..dbd7c7e4 100644 --- a/lib/ui/pages/more/app_settings/developer_settings.dart +++ b/lib/ui/pages/more/app_settings/developer_settings.dart @@ -25,7 +25,6 @@ class _DeveloperSettingsPageState extends State { Widget build(final BuildContext context) => BrandHeroScreen( hasBackButton: true, hasFlashButton: false, - bodyPadding: const EdgeInsets.symmetric(vertical: 16), heroTitle: 'developer_settings.title'.tr(), heroSubtitle: 'developer_settings.subtitle'.tr(), children: [ diff --git a/lib/ui/pages/recovery_key/recovery_key.dart b/lib/ui/pages/recovery_key/recovery_key.dart index 0516c141..ed262940 100644 --- a/lib/ui/pages/recovery_key/recovery_key.dart +++ b/lib/ui/pages/recovery_key/recovery_key.dart @@ -250,7 +250,7 @@ class _RecoveryKeyConfigurationState extends State { }); await Navigator.of(context).push( materialRoute( - RecoveryKeyReceiving(recoveryKey: token), + NewRecoveryKeyPage(recoveryKey: token), ), ); } on GenerationError catch (e) { diff --git a/lib/ui/pages/recovery_key/recovery_key_receiving.dart b/lib/ui/pages/recovery_key/recovery_key_receiving.dart index 3f7279c3..631538c5 100644 --- a/lib/ui/pages/recovery_key/recovery_key_receiving.dart +++ b/lib/ui/pages/recovery_key/recovery_key_receiving.dart @@ -1,11 +1,10 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:selfprivacy/ui/atoms/buttons/brand_button.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; -import 'package:selfprivacy/ui/molecules/info_box/info_box.dart'; +import 'package:selfprivacy/ui/organisms/displays/key_display.dart'; -class RecoveryKeyReceiving extends StatelessWidget { - const RecoveryKeyReceiving({required this.recoveryKey, super.key}); +class NewRecoveryKeyPage extends StatelessWidget { + const NewRecoveryKeyPage({required this.recoveryKey, super.key}); final String recoveryKey; @@ -16,28 +15,10 @@ class RecoveryKeyReceiving extends StatelessWidget { hasBackButton: false, hasFlashButton: false, children: [ - const Divider(), - const SizedBox(height: 16), - Text( - recoveryKey, - style: Theme.of(context).textTheme.bodyLarge!.copyWith( - fontSize: 24, - fontFamily: 'RobotoMono', - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 16), - const Divider(), - const SizedBox(height: 16), - InfoBox( - text: 'recovery_key.key_receiving_info'.tr(), - ), - const SizedBox(height: 16), - BrandButton.filled( - child: Text('recovery_key.key_receiving_done'.tr()), - onPressed: () { - Navigator.of(context).popUntil((final route) => route.isFirst); - }, + KeyDisplay( + keyToDisplay: recoveryKey, + canCopy: false, + infoboxText: 'recovery_key.key_receiving_info'.tr(), ), ], ); diff --git a/lib/ui/router/router.dart b/lib/ui/router/router.dart index 903771e5..150edc41 100644 --- a/lib/ui/router/router.dart +++ b/lib/ui/router/router.dart @@ -7,6 +7,7 @@ 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'; import 'package:selfprivacy/ui/pages/devices/devices.dart'; +import 'package:selfprivacy/ui/pages/devices/new_device.dart'; import 'package:selfprivacy/ui/pages/dns_details/dns_details.dart'; import 'package:selfprivacy/ui/pages/more/about_application.dart'; import 'package:selfprivacy/ui/pages/more/app_settings/app_settings.dart'; @@ -101,6 +102,7 @@ class RootRouter extends RootStackRouter { AutoRoute(page: NewUserRoute.page), AutoRoute(page: RecoveryKeyRoute.page), AutoRoute(page: DevicesRoute.page), + AutoRoute(page: NewDeviceRoute.page), AutoRoute(page: AboutApplicationRoute.page), AutoRoute(page: DeveloperSettingsRoute.page), AutoRoute(page: ServiceRoute.page), diff --git a/lib/ui/router/router.gr.dart b/lib/ui/router/router.gr.dart index e858ad8d..4a3b03e1 100644 --- a/lib/ui/router/router.gr.dart +++ b/lib/ui/router/router.gr.dart @@ -198,7 +198,7 @@ class DeveloperSettingsRoute extends PageRouteInfo { } /// generated route for -/// [DevicesScreen] +/// [DevicesPage] class DevicesRoute extends PageRouteInfo { const DevicesRoute({List? children}) : super( @@ -211,7 +211,7 @@ class DevicesRoute extends PageRouteInfo { static PageInfo page = PageInfo( name, builder: (data) { - return const DevicesScreen(); + return const DevicesPage(); }, ); } @@ -344,6 +344,25 @@ class MoreRoute extends PageRouteInfo { ); } +/// generated route for +/// [NewDevicePage] +class NewDeviceRoute extends PageRouteInfo { + const NewDeviceRoute({List? children}) + : super( + NewDeviceRoute.name, + initialChildren: children, + ); + + static const String name = 'NewDeviceRoute'; + + static PageInfo page = PageInfo( + name, + builder: (data) { + return const NewDevicePage(); + }, + ); +} + /// generated route for /// [NewUserPage] class NewUserRoute extends PageRouteInfo {