diff --git a/lib/domain/usecases/authentication/authentication.dart b/lib/domain/usecases/authentication/authentication.dart index 5c4004938..bda84a4c7 100644 --- a/lib/domain/usecases/authentication/authentication.dart +++ b/lib/domain/usecases/authentication/authentication.dart @@ -17,7 +17,7 @@ mixin AuthenticationWithLock { static int get maxFailedAttempts => 5; Duration lockDuration(int attempts) { - if (attempts == 20) { + if (attempts >= 20) { return const Duration(hours: 24); } diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 7bf121650..a1e69a9ac 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -60,6 +60,7 @@ "biometricsMethod": "Biometrics", "language": "Language", "removeWallet": "Remove Wallet from this device", + "removeWalletBtn": "Remove Wallet", "removeWalletDescription": "You can find it at any time with your secret phrase", "resyncWallet": "Resynchronize Wallet", "resyncWalletAreYouSure": "Are you sure you want to clear your cache and reload the information from the blockchain?\n\nThis action takes a few seconds and is safe because it only reloads your recent transactions.", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 4f58a329a..214408040 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -60,6 +60,7 @@ "biometricsMethod": "Biométrie", "language": "Langue", "removeWallet": "Supprimer le wallet de cet appareil", + "removeWalletBtn": "Supprimer le wallet", "resyncWallet": "Resynchroniser le wallet", "resyncWalletAreYouSure": "Êtes-vous sûr(e) de vouloir vider votre cache et recharger les informations à partir de la blockchain ?\n\nCette action requiert quelques secondes et est sans risque car elle recharge uniquement vos transactions récentes.", "resyncWalletDescription": "Vider le cache et recharger les informations de la blockchain", diff --git a/lib/main.dart b/lib/main.dart index 132bc2419..9afcf8235 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -43,7 +43,6 @@ import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; -import 'package:material_symbols_icons/symbols.dart'; import 'package:oktoast/oktoast.dart'; import 'package:window_manager/window_manager.dart'; @@ -439,15 +438,13 @@ class SplashState extends ConsumerState { .textStyleSize16W400MainButtonLabel.color, ), child: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Symbols.delete), - const Spacer(), Text( - 'Remove wallet', + AppLocalizations.of(context)!.removeWalletBtn, style: ArchethicThemeStyles .textStyleSize16W400MainButtonLabel, ), - const Spacer(), ], ), ), diff --git a/lib/ui/views/authenticate/auto_lock_guard.dart b/lib/ui/views/authenticate/auto_lock_guard.dart index 508706135..a5c190a82 100644 --- a/lib/ui/views/authenticate/auto_lock_guard.dart +++ b/lib/ui/views/authenticate/auto_lock_guard.dart @@ -4,15 +4,21 @@ import 'package:aewallet/application/authentication/authentication.dart'; import 'package:aewallet/ui/themes/archethic_theme.dart'; import 'package:aewallet/ui/themes/styles.dart'; import 'package:aewallet/ui/util/dimens.dart'; +import 'package:aewallet/ui/views/authenticate/auth_factory.dart'; import 'package:aewallet/ui/views/authenticate/components/lock_overlay.mixin.dart'; +import 'package:aewallet/ui/views/authenticate/logging_out.dart'; import 'package:aewallet/ui/views/main/components/sheet_appbar.dart'; +import 'package:aewallet/ui/widgets/components/app_button.dart'; import 'package:aewallet/ui/widgets/components/app_button_tiny.dart'; import 'package:aewallet/ui/widgets/components/sheet_skeleton.dart'; import 'package:aewallet/ui/widgets/components/sheet_skeleton_interface.dart'; +import 'package:archethic_dapp_framework_flutter/archethic_dapp_framework_flutter.dart' + as aedappfm; import 'package:async/async.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; part 'components/lock_mask_screen.dart'; diff --git a/lib/ui/views/authenticate/countdown_lock_screen.dart b/lib/ui/views/authenticate/countdown_lock_screen.dart index e6b1a1948..303d5cee4 100644 --- a/lib/ui/views/authenticate/countdown_lock_screen.dart +++ b/lib/ui/views/authenticate/countdown_lock_screen.dart @@ -80,19 +80,51 @@ class _CountdownLockScreen extends ConsumerWidget ) .valueOrNull ?? ''; - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AppButtonTiny( - AppButtonTinyType.primary, - isLocked ? countDownString : localizations.unlock, - Dimens.buttonBottomDimens, - key: const Key('unlock'), - onPressed: () { - if (isLocked) return; - CountdownLockOverlay.instance().hide(); - }, - disabled: isLocked, + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AppButtonTiny( + AppButtonTinyType.primary, + isLocked ? countDownString : localizations.unlock, + Dimens.buttonTopDimens, + key: const Key('unlock'), + onPressed: () { + if (isLocked) return; + CountdownLockOverlay.instance().hide(); + }, + disabled: isLocked, + ), + ], + ), + Container( + height: 50, + margin: Dimens.buttonBottomDimens.edgeInsetsDirectional, + child: FilledButton( + onPressed: () { + RemoveWalletDialogOverlay.showOverlay( + context, + ref, + ); + }, + style: FilledButton.styleFrom( + backgroundColor: Colors.red, + foregroundColor: + ArchethicThemeStyles.textStyleSize16W400MainButtonLabel.color, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + AppLocalizations.of(context)!.removeWalletBtn, + style: + ArchethicThemeStyles.textStyleSize16W400MainButtonLabel, + ), + ], + ), + ), ), ], ); @@ -123,3 +155,152 @@ class _CountdownLockScreen extends ConsumerWidget ); } } + +class RemoveWalletDialogOverlay { + static void showOverlay( + BuildContext context, + WidgetRef ref, + ) { + final localizations = AppLocalizations.of(context)!; + + OverlayEntry? overlayEntry; + + overlayEntry = OverlayEntry( + builder: (BuildContext overlayContext) { + return Positioned( + top: 0, + bottom: 0, + left: 0, + right: 0, + child: Material( + color: Colors.black.withOpacity(0.8), + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: Center( + child: aedappfm.PopupTemplate( + displayCloseButton: false, + popupTitle: localizations.warning, + popupContent: Column( + children: [ + Text( + localizations.removeWalletDetail, + style: ArchethicThemeStyles.textStyleSize12W100Primary, + ), + const SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AppButton( + key: const Key('cancelButton'), + labelBtn: AppLocalizations.of( + context, + )! + .no, + onPressed: () { + overlayEntry?.remove(); + }, + ), + AppButton( + key: const Key('yesButton'), + labelBtn: localizations.yes, + onPressed: () async { + overlayEntry?.remove(); + Overlay.of(context).insert( + _createConfirmOverlay( + context, + ref, + ), + ); + }, + ), + ], + ), + ], + ), + ), + ), + ), + ), + ); + }, + ); + + Overlay.of(context).insert(overlayEntry); + } + + static OverlayEntry _createConfirmOverlay( + BuildContext context, + WidgetRef ref, + ) { + final localizations = AppLocalizations.of(context)!; + + OverlayEntry? overlayEntry; + + // ignore: join_return_with_assignment + overlayEntry = OverlayEntry( + builder: (BuildContext overlayContext) { + return Positioned( + top: 0, + bottom: 0, + left: 0, + right: 0, + child: Material( + color: Colors.black.withOpacity(0.8), + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: Center( + child: aedappfm.PopupTemplate( + displayCloseButton: false, + popupTitle: localizations.areYouSure, + popupContent: Column( + children: [ + Text( + localizations.removeWalletReassurance, + style: ArchethicThemeStyles.textStyleSize12W100Primary, + ), + const SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AppButton( + key: const Key('cancelButton'), + labelBtn: AppLocalizations.of( + context, + )! + .no, + onPressed: () { + overlayEntry?.remove(); + }, + ), + AppButton( + key: const Key('yesButton'), + labelBtn: AppLocalizations.of( + context, + )! + .yes, + onPressed: () async { + overlayEntry?.remove(); + + CountdownLockOverlay.instance().hide(); + context.go(LoggingOutScreen.routerPage); + }, + ), + ], + ), + ], + ), + ), + ), + ), + ), + ); + }, + ); + + return overlayEntry; + } +}