From a9d7a27e9d7e64bc355e9c9ee3759df32cb10c56 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 4 Apr 2023 17:31:35 +0300 Subject: [PATCH] refactor(ui): Update recovery flow to use new support drawer --- .../components/drawers/progress_drawer.dart | 113 ++++++++++++ .../support_drawer.dart | 0 lib/ui/layouts/brand_hero_screen.dart | 24 ++- .../root_scaffold_with_navigation.dart | 2 +- .../binds_migration/services_migration.dart | 3 +- .../setup/initializing/initializing.dart | 172 ++++-------------- .../recovering/recover_by_new_device_key.dart | 2 + .../recovering/recover_by_old_token.dart | 2 + .../recovering/recover_by_recovery_key.dart | 1 + .../recovery_confirm_backblaze.dart | 28 +-- .../recovery_confirm_cloudflare.dart | 30 ++- .../recovering/recovery_confirm_server.dart | 1 + .../recovering/recovery_method_select.dart | 2 + .../setup/recovering/recovery_routing.dart | 1 + .../recovery_server_provider_connected.dart | 30 ++- lib/ui/pages/users/reset_password.dart | 125 +++++++------ lib/ui/pages/users/user_details.dart | 121 ++++++------ 17 files changed, 335 insertions(+), 322 deletions(-) create mode 100644 lib/ui/components/drawers/progress_drawer.dart rename lib/ui/components/{support_drawer => drawers}/support_drawer.dart (100%) diff --git a/lib/ui/components/drawers/progress_drawer.dart b/lib/ui/components/drawers/progress_drawer.dart new file mode 100644 index 00000000..d886da02 --- /dev/null +++ b/lib/ui/components/drawers/progress_drawer.dart @@ -0,0 +1,113 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +class ProgressDrawer extends StatelessWidget { + /// A [Drawer] that displays a list of steps and the current step. + /// Used in setup wizards. The [trailing] widget is displayed at the bottom. + /// The [steps] are translated using [EasyLocalization]. + const ProgressDrawer({ + required this.steps, + required this.currentStep, + required this.constraints, + required this.trailing, + required this.title, + super.key, + }); + + final List steps; + final int currentStep; + final Widget trailing; + final BoxConstraints constraints; + final String title; + + @override + Widget build(final BuildContext context) => SizedBox( + width: 300, + height: constraints.maxHeight, + child: Drawer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + title, + style: Theme.of(context).textTheme.titleLarge, + ), + ), + Flexible( + fit: FlexFit.tight, + child: SingleChildScrollView( + child: Column( + children: [ + ...steps.map((final step) { + final index = steps.indexOf(step); + return _StepIndicator( + title: step.tr(), + isCurrent: index == currentStep, + isCompleted: index < currentStep, + ); + }), + ], + ), + ), + ), + // const Spacer(), + Padding( + padding: const EdgeInsets.all(16.0), + child: trailing, + ), + ], + ), + ), + ); +} + +class _StepIndicator extends StatelessWidget { + const _StepIndicator({ + required this.title, + required this.isCompleted, + required this.isCurrent, + }); + + final String title; + final bool isCompleted; + final bool isCurrent; + + @override + Widget build(final BuildContext context) => ListTile( + selected: isCurrent, + leading: isCurrent + ? const _StepCurrentIcon() + : isCompleted + ? const _StepCompletedIcon() + : const _StepPendingIcon(), + title: Text( + title, + ), + textColor: Theme.of(context).colorScheme.onSurfaceVariant, + iconColor: Theme.of(context).colorScheme.onSurfaceVariant, + ); +} + +class _StepCompletedIcon extends StatelessWidget { + const _StepCompletedIcon(); + + @override + Widget build(final BuildContext context) => const Icon(Icons.check_circle); +} + +class _StepPendingIcon extends StatelessWidget { + const _StepPendingIcon(); + + @override + Widget build(final BuildContext context) => const Icon(Icons.circle_outlined); +} + +class _StepCurrentIcon extends StatelessWidget { + const _StepCurrentIcon(); + + @override + Widget build(final BuildContext context) => + const Icon(Icons.build_circle_outlined); +} diff --git a/lib/ui/components/support_drawer/support_drawer.dart b/lib/ui/components/drawers/support_drawer.dart similarity index 100% rename from lib/ui/components/support_drawer/support_drawer.dart rename to lib/ui/components/drawers/support_drawer.dart diff --git a/lib/ui/layouts/brand_hero_screen.dart b/lib/ui/layouts/brand_hero_screen.dart index cc916b87..adb94902 100644 --- a/lib/ui/layouts/brand_hero_screen.dart +++ b/lib/ui/layouts/brand_hero_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:ionicons/ionicons.dart'; import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart'; +import 'package:selfprivacy/ui/components/drawers/support_drawer.dart'; import 'package:selfprivacy/ui/helpers/widget_size.dart'; import 'package:selfprivacy/utils/breakpoints.dart'; @@ -18,6 +19,8 @@ class BrandHeroScreen extends StatelessWidget { this.heroSubtitle, this.onBackButtonPressed, this.bodyPadding = const EdgeInsets.all(16.0), + this.ignoreBreakpoints = false, + this.hasSupportDrawer = false, }); final List children; @@ -30,6 +33,15 @@ class BrandHeroScreen extends StatelessWidget { final VoidCallback? onBackButtonPressed; final EdgeInsetsGeometry bodyPadding; + /// On non-mobile screens the buttons of the app bar are hidden. + /// This is because this widget implies that it is nested inside a bigger layout. + /// If it is not nested, set this to true. + final bool ignoreBreakpoints; + + /// Usually support drawer is provided by the parent layout. + /// If it is not provided, set this to true. + final bool hasSupportDrawer; + @override Widget build(final BuildContext context) { final Widget heroIconWidget = this.heroIconWidget ?? @@ -41,6 +53,8 @@ class BrandHeroScreen extends StatelessWidget { final bool hasHeroIcon = heroIcon != null || this.heroIconWidget != null; return Scaffold( + endDrawerEnableOpenDragGesture: false, + endDrawer: hasSupportDrawer ? const SupportDrawer() : null, body: CustomScrollView( slivers: [ HeroSliverAppBar( @@ -50,6 +64,7 @@ class BrandHeroScreen extends StatelessWidget { onBackButtonPressed: onBackButtonPressed, heroIconWidget: heroIconWidget, hasFlashButton: hasFlashButton, + ignoreBreakpoints: ignoreBreakpoints, ), if (heroSubtitle != null) SliverPadding( @@ -89,6 +104,7 @@ class HeroSliverAppBar extends StatefulWidget { required this.onBackButtonPressed, required this.heroIconWidget, required this.hasFlashButton, + required this.ignoreBreakpoints, super.key, }); @@ -98,6 +114,7 @@ class HeroSliverAppBar extends StatefulWidget { final bool hasFlashButton; final VoidCallback? onBackButtonPressed; final Widget heroIconWidget; + final bool ignoreBreakpoints; @override State createState() => _HeroSliverAppBarState(); @@ -107,7 +124,8 @@ class _HeroSliverAppBarState extends State { Size _size = Size.zero; @override Widget build(final BuildContext context) { - final isMobile = Breakpoints.small.isActive(context); + final isMobile = + widget.ignoreBreakpoints ? true : Breakpoints.small.isActive(context); final isJobsListEmpty = context.watch().state is JobsStateEmpty; return SliverAppBar( expandedHeight: @@ -127,8 +145,7 @@ class _HeroSliverAppBarState extends State { onPressed: () { showModalBottomSheet( context: context, - builder: (final BuildContext context) => - const JobsContent(), + builder: (final BuildContext context) => const JobsContent(), ); }, icon: Icon( @@ -139,6 +156,7 @@ class _HeroSliverAppBarState extends State { : Theme.of(context).colorScheme.primary, ), ), + const SizedBox.shrink(), ], flexibleSpace: FlexibleSpaceBar( title: LayoutBuilder( diff --git a/lib/ui/layouts/root_scaffold_with_navigation.dart b/lib/ui/layouts/root_scaffold_with_navigation.dart index 8fd3d7a7..fcc58515 100644 --- a/lib/ui/layouts/root_scaffold_with_navigation.dart +++ b/lib/ui/layouts/root_scaffold_with_navigation.dart @@ -1,7 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:selfprivacy/ui/components/pre_styled_buttons/flash_fab.dart'; -import 'package:selfprivacy/ui/components/support_drawer/support_drawer.dart'; +import 'package:selfprivacy/ui/components/drawers/support_drawer.dart'; import 'package:selfprivacy/ui/router/root_destinations.dart'; import 'package:selfprivacy/utils/breakpoints.dart'; diff --git a/lib/ui/pages/server_storage/binds_migration/services_migration.dart b/lib/ui/pages/server_storage/binds_migration/services_migration.dart index ed03e896..d747cafa 100644 --- a/lib/ui/pages/server_storage/binds_migration/services_migration.dart +++ b/lib/ui/pages/server_storage/binds_migration/services_migration.dart @@ -182,8 +182,7 @@ class _ServicesMigrationPageState extends State { ); showModalBottomSheet( context: context, - builder: (final BuildContext context) => - const JobsContent(), + builder: (final BuildContext context) => const JobsContent(), ); }, ), diff --git a/lib/ui/pages/setup/initializing/initializing.dart b/lib/ui/pages/setup/initializing/initializing.dart index 27ca4f5a..199203c3 100644 --- a/lib/ui/pages/setup/initializing/initializing.dart +++ b/lib/ui/pages/setup/initializing/initializing.dart @@ -13,8 +13,9 @@ import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart import 'package:selfprivacy/ui/components/buttons/brand_button.dart'; import 'package:selfprivacy/ui/components/buttons/outlined_button.dart'; import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart'; +import 'package:selfprivacy/ui/components/drawers/progress_drawer.dart'; import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart'; -import 'package:selfprivacy/ui/components/support_drawer/support_drawer.dart'; +import 'package:selfprivacy/ui/components/drawers/support_drawer.dart'; import 'package:selfprivacy/ui/layouts/responsive_layout_with_infobox.dart'; import 'package:selfprivacy/ui/pages/setup/initializing/server_provider_picker.dart'; import 'package:selfprivacy/ui/pages/setup/initializing/server_type_picker.dart'; @@ -113,10 +114,42 @@ class InitializingPage extends StatelessWidget { builder: (final context, final constraints) => Row( children: [ if (Breakpoints.large.isActive(context)) - _ProgressDrawer( + ProgressDrawer( steps: steps, - cubit: cubit, + currentStep: cubit.state.progress.index, + title: 'more_page.configuration_wizard'.tr(), constraints: constraints, + trailing: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (cubit.state is ServerInstallationEmpty || + cubit.state is ServerInstallationNotFinished) + Container( + alignment: Alignment.center, + child: BrandButton.filled( + text: 'basis.connect_to_existing'.tr(), + onPressed: () { + context.router.replace(const RecoveryRoute()); + }, + ), + ), + ConstrainedBox( + constraints: const BoxConstraints( + minWidth: double.infinity, + ), + child: OutlinedButton( + child: Text( + cubit.state is ServerInstallationFinished + ? 'basis.close'.tr() + : 'basis.later'.tr(), + ), + onPressed: () { + context.router.popUntilRoot(); + }, + ), + ), + ], + ), ), SizedBox( width: constraints.maxWidth - @@ -625,136 +658,3 @@ class InitializingPage extends StatelessWidget { ); } } - -class _ProgressDrawer extends StatelessWidget { - const _ProgressDrawer({ - required this.steps, - required this.cubit, - required this.constraints, - }); - - final List steps; - final ServerInstallationCubit cubit; - final BoxConstraints constraints; - - @override - Widget build(final BuildContext context) => SizedBox( - width: 300, - height: constraints.maxHeight, - child: Drawer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - 'more_page.configuration_wizard'.tr(), - style: Theme.of(context).textTheme.titleLarge, - ), - ), - Flexible( - fit: FlexFit.tight, - child: SingleChildScrollView( - child: Column( - children: [ - ...steps.map((final step) { - final index = steps.indexOf(step); - return _StepIndicator( - title: step.tr(), - isCurrent: index == cubit.state.progress.index, - isCompleted: index < cubit.state.progress.index, - ); - }), - ], - ), - ), - ), - // const Spacer(), - Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (cubit.state is ServerInstallationEmpty || - cubit.state is ServerInstallationNotFinished) - Container( - alignment: Alignment.center, - child: BrandButton.filled( - text: 'basis.connect_to_existing'.tr(), - onPressed: () { - context.router.replace(const RecoveryRoute()); - }, - ), - ), - ConstrainedBox( - constraints: const BoxConstraints( - minWidth: double.infinity, - ), - child: OutlinedButton( - child: Text( - cubit.state is ServerInstallationFinished - ? 'basis.close'.tr() - : 'basis.later'.tr(), - ), - onPressed: () { - context.router.popUntilRoot(); - }, - ), - ), - ], - ), - ), - ], - ), - ), - ); -} - -class _StepIndicator extends StatelessWidget { - const _StepIndicator({ - required this.title, - required this.isCompleted, - required this.isCurrent, - }); - - final String title; - final bool isCompleted; - final bool isCurrent; - - @override - Widget build(final BuildContext context) => ListTile( - selected: isCurrent, - leading: isCurrent - ? const _StepCurrentIcon() - : isCompleted - ? const _StepCompletedIcon() - : const _StepPendingIcon(), - title: Text( - title, - ), - textColor: Theme.of(context).colorScheme.onSurfaceVariant, - iconColor: Theme.of(context).colorScheme.onSurfaceVariant, - ); -} - -class _StepCompletedIcon extends StatelessWidget { - const _StepCompletedIcon(); - - @override - Widget build(final BuildContext context) => const Icon(Icons.check_circle); -} - -class _StepPendingIcon extends StatelessWidget { - const _StepPendingIcon(); - - @override - Widget build(final BuildContext context) => const Icon(Icons.circle_outlined); -} - -class _StepCurrentIcon extends StatelessWidget { - const _StepCurrentIcon(); - - @override - Widget build(final BuildContext context) => - const Icon(Icons.build_circle_outlined); -} diff --git a/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart b/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart index ea264749..4f6cf352 100644 --- a/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart +++ b/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart @@ -17,6 +17,7 @@ class RecoverByNewDeviceKeyInstruction extends StatelessWidget { heroSubtitle: 'recovering.method_device_description'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, onBackButtonPressed: context.read().revertRecoveryStep, children: [ @@ -61,6 +62,7 @@ class RecoverByNewDeviceKeyInput extends StatelessWidget { heroSubtitle: 'recovering.method_device_input_description'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, children: [ CubitFormTextField( formFieldCubit: diff --git a/lib/ui/pages/setup/recovering/recover_by_old_token.dart b/lib/ui/pages/setup/recovering/recover_by_old_token.dart index d08e6bf7..42d60f34 100644 --- a/lib/ui/pages/setup/recovering/recover_by_old_token.dart +++ b/lib/ui/pages/setup/recovering/recover_by_old_token.dart @@ -28,6 +28,7 @@ class RecoverByOldTokenInstruction extends StatelessWidget { heroTitle: 'recovering.recovery_main_header'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, onBackButtonPressed: context.read().revertRecoveryStep, children: [ @@ -72,6 +73,7 @@ class RecoverByOldToken extends StatelessWidget { heroSubtitle: 'recovering.method_device_input_description'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, children: [ CubitFormTextField( formFieldCubit: diff --git a/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart b/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart index 859a6eca..b39dc2da 100644 --- a/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart +++ b/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart @@ -31,6 +31,7 @@ class RecoverByRecoveryKey extends StatelessWidget { heroSubtitle: 'recovering.method_recovery_input_description'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, onBackButtonPressed: context.read().revertRecoveryStep, children: [ diff --git a/lib/ui/pages/setup/recovering/recovery_confirm_backblaze.dart b/lib/ui/pages/setup/recovering/recovery_confirm_backblaze.dart index dac2d7e1..f7216a74 100644 --- a/lib/ui/pages/setup/recovering/recovery_confirm_backblaze.dart +++ b/lib/ui/pages/setup/recovering/recovery_confirm_backblaze.dart @@ -1,12 +1,11 @@ import 'package:cubit_form/cubit_form.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_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/ui/components/buttons/brand_button.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; -import 'package:selfprivacy/ui/components/brand_md/brand_md.dart'; class RecoveryConfirmBackblaze extends StatelessWidget { const RecoveryConfirmBackblaze({super.key}); @@ -27,6 +26,8 @@ class RecoveryConfirmBackblaze extends StatelessWidget { heroTitle: 'recovering.confirm_backblaze'.tr(), heroSubtitle: 'recovering.confirm_backblaze_description'.tr(), hasBackButton: true, + ignoreBreakpoints: true, + hasSupportDrawer: true, onBackButtonPressed: () { Navigator.of(context).popUntil((final route) => route.isFirst); }, @@ -56,24 +57,15 @@ class RecoveryConfirmBackblaze extends StatelessWidget { text: 'basis.connect'.tr(), ), const SizedBox(height: 16), - BrandButton.text( - onPressed: () => showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (final BuildContext context) => Padding( - padding: paddingH15V0, - child: ListView( - padding: const EdgeInsets.symmetric(vertical: 16), - children: const [ - BrandMarkdown( - fileName: 'how_backblaze', + Builder( + builder: (final context) => BrandButton.text( + onPressed: () => + context.read().showArticle( + article: 'how_backblaze', + context: context, ), - ], - ), - ), + title: 'initializing.how'.tr(), ), - title: 'initializing.how'.tr(), ), ], ); diff --git a/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart b/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart index 8ffc6dfa..93c889a5 100644 --- a/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart +++ b/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart @@ -1,12 +1,11 @@ import 'package:cubit_form/cubit_form.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_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/ui/components/buttons/brand_button.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; -import 'package:selfprivacy/ui/components/brand_md/brand_md.dart'; class RecoveryConfirmCloudflare extends StatelessWidget { const RecoveryConfirmCloudflare({super.key}); @@ -30,6 +29,8 @@ class RecoveryConfirmCloudflare extends StatelessWidget { ), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, + hasSupportDrawer: true, onBackButtonPressed: context.read().revertRecoveryStep, children: [ @@ -48,24 +49,15 @@ class RecoveryConfirmCloudflare extends StatelessWidget { text: 'basis.connect'.tr(), ), const SizedBox(height: 16), - BrandButton.text( - onPressed: () => showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (final BuildContext context) => Padding( - padding: paddingH15V0, - child: ListView( - padding: const EdgeInsets.symmetric(vertical: 16), - children: const [ - BrandMarkdown( - fileName: 'how_cloudflare', - ), - ], - ), - ), + Builder( + builder: (final context) => BrandButton.text( + onPressed: () => + context.read().showArticle( + article: 'how_cloudflare', + context: context, + ), + title: 'initializing.how'.tr(), ), - title: 'initializing.how'.tr(), ), ], ); diff --git a/lib/ui/pages/setup/recovering/recovery_confirm_server.dart b/lib/ui/pages/setup/recovering/recovery_confirm_server.dart index 9ad22ebc..1c75ad75 100644 --- a/lib/ui/pages/setup/recovering/recovery_confirm_server.dart +++ b/lib/ui/pages/setup/recovering/recovery_confirm_server.dart @@ -38,6 +38,7 @@ class _RecoveryConfirmServerState extends State { ? 'recovering.choose_server_description'.tr() : 'recovering.confirm_server_description'.tr(), hasBackButton: true, + ignoreBreakpoints: true, onBackButtonPressed: () { Navigator.of(context).popUntil((final route) => route.isFirst); }, diff --git a/lib/ui/pages/setup/recovering/recovery_method_select.dart b/lib/ui/pages/setup/recovering/recovery_method_select.dart index 72f557d3..8713685d 100644 --- a/lib/ui/pages/setup/recovering/recovery_method_select.dart +++ b/lib/ui/pages/setup/recovering/recovery_method_select.dart @@ -17,6 +17,7 @@ class RecoveryMethodSelect extends StatelessWidget { heroSubtitle: 'recovering.method_select_description'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, onBackButtonPressed: context.read().revertRecoveryStep, children: [ @@ -74,6 +75,7 @@ class RecoveryFallbackMethodSelect extends StatelessWidget { heroSubtitle: 'recovering.fallback_select_description'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, children: [ OutlinedCard( child: ListTile( diff --git a/lib/ui/pages/setup/recovering/recovery_routing.dart b/lib/ui/pages/setup/recovering/recovery_routing.dart index 193e3292..14c3f9a7 100644 --- a/lib/ui/pages/setup/recovering/recovery_routing.dart +++ b/lib/ui/pages/setup/recovering/recovery_routing.dart @@ -112,6 +112,7 @@ class SelectDomainToRecover extends StatelessWidget { heroSubtitle: 'recovering.domain_recovery_description'.tr(), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, onBackButtonPressed: () { Navigator.of(context).pushAndRemoveUntil( materialRoute(const RootPage()), diff --git a/lib/ui/pages/setup/recovering/recovery_server_provider_connected.dart b/lib/ui/pages/setup/recovering/recovery_server_provider_connected.dart index 4cf4bdec..91999fb9 100644 --- a/lib/ui/pages/setup/recovering/recovery_server_provider_connected.dart +++ b/lib/ui/pages/setup/recovering/recovery_server_provider_connected.dart @@ -1,12 +1,11 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart'; +import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart'; import 'package:selfprivacy/ui/components/buttons/brand_button.dart'; import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart'; import 'package:cubit_form/cubit_form.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; -import 'package:selfprivacy/ui/components/brand_md/brand_md.dart'; class RecoveryServerProviderConnected extends StatelessWidget { const RecoveryServerProviderConnected({super.key}); @@ -30,6 +29,8 @@ class RecoveryServerProviderConnected extends StatelessWidget { ), hasBackButton: true, hasFlashButton: false, + ignoreBreakpoints: true, + hasSupportDrawer: true, onBackButtonPressed: () { Navigator.of(context).popUntil((final route) => route.isFirst); }, @@ -50,23 +51,14 @@ class RecoveryServerProviderConnected extends StatelessWidget { child: Text('basis.continue'.tr()), ), const SizedBox(height: 16), - BrandButton.text( - title: 'initializing.how'.tr(), - onPressed: () => showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (final BuildContext context) => Padding( - padding: paddingH15V0, - child: ListView( - padding: const EdgeInsets.symmetric(vertical: 16), - children: const [ - BrandMarkdown( - fileName: 'how_hetzner', - ), - ], - ), - ), + Builder( + builder: (final context) => BrandButton.text( + title: 'initializing.how'.tr(), + onPressed: () => + context.read().showArticle( + article: 'how_hetzner', + context: context, + ), ), ), ], diff --git a/lib/ui/pages/users/reset_password.dart b/lib/ui/pages/users/reset_password.dart index 56670803..64785d3a 100644 --- a/lib/ui/pages/users/reset_password.dart +++ b/lib/ui/pages/users/reset_password.dart @@ -10,73 +10,72 @@ class ResetPassword extends StatelessWidget { @override Widget build(final BuildContext context) => BlocProvider( - create: (final BuildContext context) => UserFormCubit( - jobsCubit: context.read(), - fieldFactory: FieldCubitFactory(context), - initialUser: user, - ), - child: Builder( - builder: (final BuildContext context) { - final FormCubitState formCubitState = - context.watch().state; + create: (final BuildContext context) => UserFormCubit( + jobsCubit: context.read(), + fieldFactory: FieldCubitFactory(context), + initialUser: user, + ), + child: Builder( + builder: (final BuildContext context) { + final FormCubitState formCubitState = + context.watch().state; - return BlocListener( - listener: - (final BuildContext context, final FormCubitState state) { - if (state.isSubmitted) { - Navigator.pop(context); - } - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - BrandHeader( - title: 'users.reset_password'.tr(), - ), - const SizedBox(width: 14), - Padding( - padding: paddingH15V0, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CubitFormTextField( - formFieldCubit: - context.read().password, - decoration: InputDecoration( - alignLabelWithHint: false, - labelText: 'basis.password'.tr(), - suffixIcon: Padding( - padding: const EdgeInsets.only(right: 8), - child: IconButton( - icon: Icon( - BrandIcons.refresh, - color: - Theme.of(context).colorScheme.secondary, + return BlocListener( + listener: + (final BuildContext context, final FormCubitState state) { + if (state.isSubmitted) { + Navigator.pop(context); + } + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + BrandHeader( + title: 'users.reset_password'.tr(), + ), + const SizedBox(width: 14), + Padding( + padding: paddingH15V0, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CubitFormTextField( + formFieldCubit: + context.read().password, + decoration: InputDecoration( + alignLabelWithHint: false, + labelText: 'basis.password'.tr(), + suffixIcon: Padding( + padding: const EdgeInsets.only(right: 8), + child: IconButton( + icon: Icon( + BrandIcons.refresh, + color: + Theme.of(context).colorScheme.secondary, + ), + onPressed: context + .read() + .genNewPassword, + ), ), - onPressed: context - .read() - .genNewPassword, ), ), - ), + const SizedBox(height: 30), + BrandButton.rised( + onPressed: formCubitState.isSubmitting + ? null + : () => context.read().trySubmit(), + text: 'basis.apply'.tr(), + ), + const SizedBox(height: 30), + ], ), - const SizedBox(height: 30), - BrandButton.rised( - onPressed: formCubitState.isSubmitting - ? null - : () => - context.read().trySubmit(), - text: 'basis.apply'.tr(), - ), - const SizedBox(height: 30), - ], - ), + ), + ], ), - ], - ), - ); - }, - ), - ); + ); + }, + ), + ); } diff --git a/lib/ui/pages/users/user_details.dart b/lib/ui/pages/users/user_details.dart index c6ef2a8c..be7205fb 100644 --- a/lib/ui/pages/users/user_details.dart +++ b/lib/ui/pages/users/user_details.dart @@ -255,69 +255,68 @@ class NewSshKey extends StatelessWidget { @override Widget build(final BuildContext context) => BlocProvider( - create: (final context) { - final jobCubit = context.read(); - final jobState = jobCubit.state; - if (jobState is JobsStateWithJobs) { - final jobs = jobState.clientJobList; - for (final job in jobs) { - if (job is CreateSSHKeyJob && job.user.login == user.login) { - user.sshKeys.add(job.publicKey); - } - } - } - return SshFormCubit( - jobsCubit: jobCubit, - user: user, - ); - }, - child: Builder( - builder: (final context) { - final formCubitState = context.watch().state; - - return BlocListener( - listener: (final context, final state) { - if (state.isSubmitted) { - Navigator.pop(context); + create: (final context) { + final jobCubit = context.read(); + final jobState = jobCubit.state; + if (jobState is JobsStateWithJobs) { + final jobs = jobState.clientJobList; + for (final job in jobs) { + if (job is CreateSSHKeyJob && job.user.login == user.login) { + user.sshKeys.add(job.publicKey); + } } - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - BrandHeader( - title: user.login, - ), - const SizedBox(width: 14), - Padding( - padding: paddingH15V0, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - IntrinsicHeight( - child: CubitFormTextField( - formFieldCubit: context.read().key, - decoration: InputDecoration( - labelText: 'ssh.input_label'.tr(), + } + return SshFormCubit( + jobsCubit: jobCubit, + user: user, + ); + }, + child: Builder( + builder: (final context) { + final formCubitState = context.watch().state; + + return BlocListener( + listener: (final context, final state) { + if (state.isSubmitted) { + Navigator.pop(context); + } + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + BrandHeader( + title: user.login, + ), + const SizedBox(width: 14), + Padding( + padding: paddingH15V0, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IntrinsicHeight( + child: CubitFormTextField( + formFieldCubit: context.read().key, + decoration: InputDecoration( + labelText: 'ssh.input_label'.tr(), + ), + ), ), - ), + const SizedBox(height: 30), + BrandButton.rised( + onPressed: formCubitState.isSubmitting + ? null + : () => context.read().trySubmit(), + text: 'ssh.create'.tr(), + ), + const SizedBox(height: 30), + ], ), - const SizedBox(height: 30), - BrandButton.rised( - onPressed: formCubitState.isSubmitting - ? null - : () => - context.read().trySubmit(), - text: 'ssh.create'.tr(), - ), - const SizedBox(height: 30), - ], - ), + ), + ], ), - ], - ), - ); - }, - ), - ); + ); + }, + ), + ); }