From 406f6f758ec3bb51ecaf504afc9709fb0914bc4c Mon Sep 17 00:00:00 2001 From: Brandon Berhent Date: Tue, 22 Oct 2019 09:54:20 -0400 Subject: [PATCH] Fix freepasa phone number validation, lock screen fixes and logout button --- lib/ui/lockscreen/lock_screen.dart | 209 +++++++++++++++----- lib/ui/overview/get_free_account_sheet.dart | 2 +- lib/ui/util/formatters.dart | 6 +- pubspec.yaml | 2 +- 4 files changed, 162 insertions(+), 57 deletions(-) diff --git a/lib/ui/lockscreen/lock_screen.dart b/lib/ui/lockscreen/lock_screen.dart index 53a401c..3eebc9a 100644 --- a/lib/ui/lockscreen/lock_screen.dart +++ b/lib/ui/lockscreen/lock_screen.dart @@ -1,9 +1,12 @@ +import 'package:auto_size_text/auto_size_text.dart'; import 'package:blaise_wallet_flutter/appstate_container.dart'; import 'package:blaise_wallet_flutter/localization.dart'; import 'package:blaise_wallet_flutter/model/authentication_method.dart'; import 'package:blaise_wallet_flutter/service_locator.dart'; +import 'package:blaise_wallet_flutter/ui/util/app_icons.dart'; import 'package:blaise_wallet_flutter/ui/util/routes.dart'; import 'package:blaise_wallet_flutter/ui/util/text_styles.dart'; +import 'package:blaise_wallet_flutter/ui/widgets/overlay_dialog.dart'; import 'package:blaise_wallet_flutter/util/ui_util.dart'; import 'package:blaise_wallet_flutter/ui/widgets/buttons.dart'; import 'package:blaise_wallet_flutter/ui/widgets/pin_screen.dart'; @@ -28,16 +31,6 @@ class _LockScreenPageState extends State { .pushNamedAndRemoveUntil('/overview', (Route route) => false); } - Widget _buildPinScreen(BuildContext context, String expectedPin) { - return PinScreen( - type: PinOverlayType.ENTER_PIN, - expectedPin: expectedPin, - description: AppLocalization.of(context).enterPINToUnlockParagraph, - onSuccess: (pin) { - _goHome(); - }); - } - String _formatCountDisplay(int count) { if (count <= 60) { // Seconds only @@ -129,51 +122,56 @@ class _LockScreenPageState extends State { setState(() { _lockedOut = false; }); - sl.get().getAuthMethod().then((authMethod) { - AuthUtil().hasBiometrics().then((hasBiometrics) { - if (authMethod.method == AuthMethod.BIOMETRICS && hasBiometrics) { + AuthenticationMethod authMethod = await sl.get().getAuthMethod(); + bool hasBiometrics = await AuthUtil().hasBiometrics(); + if (authMethod.method == AuthMethod.BIOMETRICS && hasBiometrics) { + setState(() { + _showUnlockButton = true; + }); + bool authenticated = await AuthUtil().authenticateWithBiometrics(AppLocalization.of(context).authenticateToUnlockParagraph); + if (authenticated) { + _goHome(); + } else { + setState(() { + _showUnlockButton = true; + }); + } + } else { + // PIN authentication + String expectedPin = await sl.get().getPin(); + if (transitions) { + Navigator.of(context).push( + MaterialPageRoute(builder: (BuildContext context) { + return PinScreen( + type: PinOverlayType.ENTER_PIN, + expectedPin: expectedPin, + description: AppLocalization.of(context).enterPINToUnlockParagraph, + onSuccess: (pin) { + _goHome(); + }); + }), + ); + } else { + Navigator.of(context).push( + NoPushTransitionRoute(builder: (BuildContext context) { + return PinScreen( + type: PinOverlayType.ENTER_PIN, + expectedPin: expectedPin, + description: AppLocalization.of(context).enterPINToUnlockParagraph, + onSuccess: (pin) { + _goHome(); + }); + }), + ); + } + Future.delayed(Duration(milliseconds: 200), () { + if (mounted) { setState(() { _showUnlockButton = true; }); - AuthUtil() - .authenticateWithBiometrics( - AppLocalization.of(context).authenticateToUnlockParagraph) - .then((authenticated) { - if (authenticated) { - _goHome(); - } else { - setState(() { - _showUnlockButton = true; - }); - } - }); - } else { - // PIN Authentication - sl.get().getPin().then((expectedPin) { - if (transitions) { - Navigator.of(context).push( - MaterialPageRoute(builder: (BuildContext context) { - return _buildPinScreen(context, expectedPin); - }), - ); - } else { - Navigator.of(context).push( - NoPushTransitionRoute(builder: (BuildContext context) { - return _buildPinScreen(context, expectedPin); - }), - ); - } - Future.delayed(Duration(milliseconds: 200), () { - if (mounted) { - setState(() { - _showUnlockButton = true; - }); - } - }); - }); } }); - }); + } } @override @@ -182,6 +180,52 @@ class _LockScreenPageState extends State { _authenticate(); } + void logoutPressed() { + showAppDialog( + context: context, + builder: (_) => DialogOverlay( + title: toUppercase( + AppLocalization.of(context).warningHeader, context), + warningStyle: true, + confirmButtonText: toUppercase( + AppLocalization.of(context).deletePrivateKeyAndLogoutButton, + context), + body: TextSpan( + children: formatLocalizedColorsDanger(context, + AppLocalization.of(context).logoutFirstDisclaimerParagraph), + ), + onConfirm: () { + Navigator.of(context).pop(); + showAppDialog( + context: context, + builder: (_) => DialogOverlay( + title: toUppercase( + AppLocalization.of(context).areYouSureHeader, + context), + warningStyle: true, + confirmButtonText: toUppercase( + AppLocalization.of(context).yesImSureButton, + context), + body: TextSpan( + children: formatLocalizedColorsDanger( + context, + AppLocalization.of(context) + .logoutSecondDisclaimerParagraph), + ), + onConfirm: () { + // Handle logging out + walletState.reset(); + sl.get().deleteAll().then((_) { + sl.get().deleteAll().then((_) { + Navigator.of(context).pushNamedAndRemoveUntil( + '/', (Route route) => false); + }); + }); + })); + }, + )); + } + @override Widget build(BuildContext context) { // The main scaffold that holds everything @@ -247,6 +291,67 @@ class _LockScreenPageState extends State { ), ], ), + // Logout button + Container( + margin: EdgeInsetsDirectional.only(start: 5, top: 30), + alignment: Alignment.topLeft, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + FlatButton( + splashColor: StateContainer.of(context) + .curTheme + .backgroundPrimary30, + highlightColor: StateContainer.of(context) + .curTheme + .backgroundPrimary15, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8)), + onPressed: () { + logoutPressed(); + }, + padding: EdgeInsetsDirectional.fromSTEB(12, 8, 12, 8), + // A row for logout icon and text + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + // log out icon + Container( + margin: EdgeInsetsDirectional.only(end: 8), + child: Icon(AppIcons.logout, + size: 20, + color: StateContainer.of(context) + .curTheme + .backgroundPrimary), + ), + // Support text + Container( + constraints: BoxConstraints( + maxWidth: + (MediaQuery.of(context).size.width - + 100) * + 0.4), + child: AutoSizeText( + AppLocalization.of(context).logoutHeader, + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 14, + fontFamily: "Metropolis", + color: StateContainer.of(context).curTheme.backgroundPrimary + ), + textAlign: TextAlign.center, + maxLines: 1, + minFontSize: 8, + stepGranularity: 0.1, + ), + ), + ], + ), + ), + ], + ), + ), ], ), ], @@ -274,9 +379,9 @@ class _LockScreenPageState extends State { text: _lockedOut ? _countDownTxt : AppLocalization.of(context).unlockButton, - onPressed: () { + onPressed: () async { if (!_lockedOut) { - _authenticate(transitions: true); + await _authenticate(transitions: true); } }, disabled: _lockedOut, diff --git a/lib/ui/overview/get_free_account_sheet.dart b/lib/ui/overview/get_free_account_sheet.dart index dc7ed88..b380347 100644 --- a/lib/ui/overview/get_free_account_sheet.dart +++ b/lib/ui/overview/get_free_account_sheet.dart @@ -388,7 +388,7 @@ class _GetFreeAccountSheetState extends State { // Submit request, return request ID if successful Future onSubmitted() async { // Validate phone number - if (_phoneNumberController.text.replaceAll(RegExp(r"[^0-9]"), "").length != 10) { + if (_phoneNumberController.text.replaceAll(RegExp(r"[^0-9]"), "").length < 5) { if (mounted) { setState(() { _showPhoneError = true; diff --git a/lib/ui/util/formatters.dart b/lib/ui/util/formatters.dart index 7158470..b088330 100644 --- a/lib/ui/util/formatters.dart +++ b/lib/ui/util/formatters.dart @@ -33,13 +33,13 @@ class PascalNameFormatter extends TextInputFormatter { } /// For phone numbers -/// Ensures no more than 10 digits +/// Ensures no more than 20 digits /// Ensures hyphens only occur after a number class PhoneNumberFormatter extends TextInputFormatter { @override TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { - // Check digit count, 10 is max - if (newValue.text.replaceAll(RegExp(r"[^0-9]"), "").length > 10) { + // Check digit count, 20 is max + if (newValue.text.replaceAll(RegExp(r"[^0-9]"), "").length > 20) { return oldValue; } // Ensure only 1 hyphen after a number diff --git a/pubspec.yaml b/pubspec.yaml index 676e542..4755279 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: A new Flutter project. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.3+13 +version: 1.0.4+14 environment: sdk: ">=2.1.0 <3.0.0"