diff --git a/.gitignore b/.gitignore index 1b830d6..224512b 100644 --- a/.gitignore +++ b/.gitignore @@ -47,9 +47,6 @@ android/key.properties # Rust things /target -# Linux builds -linux/ - # Custom scripts/private/ AppDir/ @@ -59,6 +56,4 @@ android/app/build.gradle integration_test/duniter/data/chains/ # Ignore PC deps -macos/ -windows/ scripts/pushGecko \ No newline at end of file diff --git a/lib/providers/my_wallets.dart b/lib/providers/my_wallets.dart index ff66466..63017b0 100644 --- a/lib/providers/my_wallets.dart +++ b/lib/providers/my_wallets.dart @@ -15,6 +15,8 @@ class MyWalletsProvider with ChangeNotifier { bool isNewDerivationLoading = false; String lastFlyBy = ''; String dragAddress = ''; + bool isPinValid = false; + bool isPinLoading = true; int getCurrentChest() { if (configBox.get('currentChest') == null) { @@ -26,7 +28,7 @@ class MyWalletsProvider with ChangeNotifier { bool checkIfWalletExist() { if (chestBox.isEmpty) { - log.i('No wallets detected'); + // log.i('No wallets detected'); return false; } else { return true; diff --git a/lib/screens/myWallets/unlocking_wallet.dart b/lib/screens/myWallets/unlocking_wallet.dart index 8703081..44aec32 100644 --- a/lib/screens/myWallets/unlocking_wallet.dart +++ b/lib/screens/myWallets/unlocking_wallet.dart @@ -22,6 +22,8 @@ class UnlockingWallet extends StatelessWidget { late int currentChestNumber; late ChestData currentChest; bool canUnlock = true; + TextEditingController enterPin = TextEditingController(); + FocusNode pinFocus = FocusNode(debugLabel: 'pinFocusNode'); // ignore: close_sinks StreamController? errorController; @@ -30,8 +32,10 @@ class UnlockingWallet extends StatelessWidget { @override Widget build(BuildContext context) { - final walletOptions = Provider.of(context); - // final double statusBarHeight = MediaQuery.of(context).padding.top; + final walletOptions = + Provider.of(context, listen: false); + final myWalletProvider = + Provider.of(context, listen: false); currentChestNumber = configBox.get('currentChest'); currentChest = chestBox.get(currentChestNumber)!; @@ -39,136 +43,149 @@ class UnlockingWallet extends StatelessWidget { int pinLenght = walletOptions.getPinLenght(wallet.number); errorController = StreamController(); - return Scaffold( - backgroundColor: backgroundColor, - body: SafeArea( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack(children: [ - Positioned( - top: 10, //statusBarHeight + 10, - left: 15, - child: Builder( - builder: (context) => IconButton( - key: keyPopButton, - icon: const Icon( - Icons.arrow_back, - color: Colors.black, - size: 30, + // if (enterPin.text == '') myWalletProvider.isPinLoading = true; + + return WillPopScope( + onWillPop: () { + myWalletProvider.isPinValid = false; + myWalletProvider.isPinLoading = true; + return Future.value(true); + }, + child: Scaffold( + backgroundColor: backgroundColor, + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack(children: [ + Positioned( + top: 10, //statusBarHeight + 10, + left: 15, + child: Builder( + builder: (context) => IconButton( + key: keyPopButton, + icon: const Icon( + Icons.arrow_back, + color: Colors.black, + size: 30, + ), + onPressed: () { + myWalletProvider.isPinValid = false; + myWalletProvider.isPinLoading = true; + Navigator.pop(context); + }, ), - onPressed: () => Navigator.pop(context), ), ), - ), - Column(children: [ - SizedBox(height: isTall ? 100 : 20), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - currentChest.imageFile == null - ? Image.asset( - 'assets/chests/${currentChest.imageName}', - width: isTall ? 130 : 100, - ) - : Image.file( - currentChest.imageFile!, - width: isTall ? 130 : 100, - ), - const SizedBox(width: 5), - SizedBox( - width: 250, - child: Text( - currentChest.name!, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 25, - color: Colors.black, - fontWeight: FontWeight.w700), - )), - ]), - SizedBox(height: 30 * ratio), - SizedBox( - width: 400, - child: Text( - 'toUnlockEnterPassword'.tr(), - style: const TextStyle( - fontSize: 19, - color: Colors.black, - fontWeight: FontWeight.w400), - )), - SizedBox(height: 40 * ratio), - pinForm(context, pinLenght), - SizedBox(height: 3 * ratio), - if (canUnlock) - InkWell( - key: keyCachePassword, - onTap: () { - walletOptions.changePinCacheChoice(); - }, - child: Row(children: [ - const SizedBox(height: 30), - const Spacer(), - Icon( - configBox.get('isCacheChecked') - ? Icons.check_box - : Icons.check_box_outline_blank, - color: orangeC, - ), - const SizedBox(width: 8), - Text( - 'rememberPassword'.tr(), - style: TextStyle( - fontSize: 16, color: Colors.grey[700]), - ), - const Spacer() - ]), - ), - const SizedBox(height: 10), - // if (canUnlock) - InkWell( - key: keyChangeChest, - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return const ChooseChest(); - }), - ); - }, - child: SizedBox( + Column(children: [ + SizedBox(height: isTall ? 100 : 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + currentChest.imageFile == null + ? Image.asset( + 'assets/chests/${currentChest.imageName}', + width: isTall ? 130 : 100, + ) + : Image.file( + currentChest.imageFile!, + width: isTall ? 130 : 100, + ), + const SizedBox(width: 5), + SizedBox( + width: 250, + child: Text( + currentChest.name!, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 25, + color: Colors.black, + fontWeight: FontWeight.w700), + )), + ]), + SizedBox(height: 30 * ratio), + SizedBox( width: 400, - height: 50, - child: Center( - child: Text( - 'changeChest'.tr(), - style: const TextStyle( - fontSize: 22, - color: orangeC, - fontWeight: FontWeight.w600), + child: Text( + 'toUnlockEnterPassword'.tr(), + style: const TextStyle( + fontSize: 19, + color: Colors.black, + fontWeight: FontWeight.w400), + )), + SizedBox(height: 30 * ratio), + if (!myWalletProvider.isPinValid && + !myWalletProvider.isPinLoading) + Text( + "Ce n'est pas le bon code".tr(), + style: const TextStyle( + color: Colors.red, fontWeight: FontWeight.w500), + ), + SizedBox(height: 10 * ratio), + pinForm(context, pinLenght), + SizedBox(height: 3 * ratio), + if (canUnlock) + InkWell( + key: keyCachePassword, + onTap: () { + walletOptions.changePinCacheChoice(); + }, + child: Row(children: [ + const SizedBox(height: 30), + const Spacer(), + Icon( + configBox.get('isCacheChecked') + ? Icons.check_box + : Icons.check_box_outline_blank, + color: orangeC, ), - ), - )), + const SizedBox(width: 8), + Text( + 'rememberPassword'.tr(), + style: TextStyle( + fontSize: 16, color: Colors.grey[700]), + ), + const Spacer() + ]), + ), + const SizedBox(height: 10), + // if (canUnlock) + InkWell( + key: keyChangeChest, + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const ChooseChest(); + }), + ); + }, + child: SizedBox( + width: 400, + height: 50, + child: Center( + child: Text( + 'changeChest'.tr(), + style: const TextStyle( + fontSize: 22, + color: orangeC, + fontWeight: FontWeight.w600), + ), + ), + )), + ]), ]), ]), - ]), - )); + )), + ); } Widget pinForm(context, pinLenght) { - // var _walletPin = ''; -// ignore: close_sinks - StreamController errorController = - StreamController(); - TextEditingController enterPin = TextEditingController(); - final walletOptions = Provider.of(context); final myWalletProvider = Provider.of(context); final sub = Provider.of(context, listen: false); - FocusNode pinFocus = FocusNode(); WalletData defaultWallet = myWalletProvider.getDefaultWallet(); - // defaultWallet.address = null; if (defaultWallet.address == null) { canUnlock = false; return Text( @@ -180,11 +197,11 @@ class UnlockingWallet extends StatelessWidget { } return Form( - // key: keyPinForm, child: Padding( padding: EdgeInsets.symmetric(vertical: 5 * ratio, horizontal: 30), child: PinCodeTextField( key: keyPinForm, + textCapitalization: TextCapitalization.characters, focusNode: pinFocus, autoFocus: true, appContext: context, @@ -195,7 +212,8 @@ class UnlockingWallet extends StatelessWidget { length: pinLenght, obscureText: true, obscuringCharacter: '*', - animationType: AnimationType.fade, + animationType: AnimationType.slide, + animationDuration: const Duration(milliseconds: 80), validator: (v) { if (v!.length < pinLenght) { return "yourPasswordLengthIsX".tr(args: [pinLenght.toString()]); @@ -214,11 +232,9 @@ class UnlockingWallet extends StatelessWidget { ), showCursor: kDebugMode ? false : true, cursorColor: Colors.black, - animationDuration: const Duration(milliseconds: 300), - textStyle: const TextStyle(fontSize: 20, height: 1.6), + textStyle: const TextStyle(fontSize: 27, height: 1.6), backgroundColor: const Color(0xffF9F9F1), enableActiveFill: false, - errorAnimationController: errorController, controller: enterPin, keyboardType: TextInputType.visiblePassword, boxShadows: const [ @@ -229,28 +245,32 @@ class UnlockingWallet extends StatelessWidget { ) ], onCompleted: (pin) async { + myWalletProvider.isPinLoading = true; myWalletProvider.pinCode = pin.toUpperCase(); final isValid = await sub.checkPassword( defaultWallet.address!, pin.toUpperCase()); - if (!isValid) { await Future.delayed(const Duration(milliseconds: 50)); - errorController.add(ErrorAnimationType - .shake); // Triggering error shake animation pinColor = Colors.red[600]; + myWalletProvider.isPinLoading = false; + myWalletProvider.isPinValid = false; myWalletProvider.pinCode = myWalletProvider.mnemonic = ''; - walletOptions.reload(); + enterPin.text = ''; pinFocus.requestFocus(); } else { + myWalletProvider.isPinValid = true; + myWalletProvider.isPinLoading = false; pinColor = Colors.green[400]; myWalletProvider.resetPinCode(); Navigator.pop(context, pin.toUpperCase()); } }, onChanged: (value) { + if (enterPin.text != '') myWalletProvider.isPinLoading = true; if (pinColor != const Color(0xFFA4B600)) { pinColor = const Color(0xFFA4B600); } + myWalletProvider.reload(); }, )), ); diff --git a/lib/screens/onBoarding/10.dart b/lib/screens/onBoarding/10.dart index 0fb0f3a..e0432fc 100644 --- a/lib/screens/onBoarding/10.dart +++ b/lib/screens/onBoarding/10.dart @@ -26,117 +26,142 @@ class OnboardingStepTen extends StatelessWidget { final formKey = GlobalKey(); Color? pinColor = const Color(0xFFA4B600); bool hasError = false; + TextEditingController enterPin = TextEditingController(); + FocusNode pinFocus = FocusNode(debugLabel: 'pinFocusNode'); @override Widget build(BuildContext context) { final generateWalletProvider = Provider.of(context); final walletOptions = Provider.of(context); + final myWalletProvider = + Provider.of(context, listen: false); CommonElements common = CommonElements(); final pinLenght = generateWalletProvider.pin.text.length; - return Scaffold( - backgroundColor: backgroundColor, - appBar: AppBar( - toolbarHeight: 60 * ratio, - title: SizedBox( - height: 22, - child: Text( - 'myPassword'.tr(), - style: const TextStyle(fontWeight: FontWeight.w600), + return WillPopScope( + onWillPop: () { + myWalletProvider.isPinValid = false; + myWalletProvider.isPinLoading = true; + return Future.value(true); + }, + child: Scaffold( + backgroundColor: backgroundColor, + appBar: AppBar( + toolbarHeight: 60 * ratio, + title: SizedBox( + height: 22, + child: Text( + 'myPassword'.tr(), + style: const TextStyle(fontWeight: FontWeight.w600), + ), ), + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.black), + onPressed: () { + myWalletProvider.isPinValid = false; + myWalletProvider.isPinLoading = true; + Navigator.of(context).pop(); + }), ), - ), - extendBodyBehindAppBar: true, - body: SafeArea( - child: Stack(children: [ - Column(children: [ - SizedBox(height: isTall ? 40 : 20), - common.buildProgressBar(9), - SizedBox(height: isTall ? 40 : 20), - common.buildText("geckoWillCheckPassword".tr()), - SizedBox(height: isTall ? 80 : 20), - Visibility( - visible: generateWalletProvider.scanedValidWalletNumber != -1, - child: Padding( - padding: const EdgeInsets.only(bottom: 15), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("derivationsScanProgress".tr(args: [ - '${generateWalletProvider.scanedWalletNumber}', - '${generateWalletProvider.numberScan + 1}' - ])), - const SizedBox(width: 10), - const SizedBox( - height: 22, - width: 22, - child: CircularProgressIndicator( - color: orangeC, - strokeWidth: 3, + extendBodyBehindAppBar: true, + body: SafeArea( + child: Stack(children: [ + Column(children: [ + SizedBox(height: isTall ? 40 : 20), + common.buildProgressBar(9), + SizedBox(height: isTall ? 40 : 20), + common.buildText("geckoWillCheckPassword".tr()), + SizedBox(height: isTall ? 60 : 10), + Visibility( + visible: generateWalletProvider.scanedValidWalletNumber != -1, + child: Padding( + padding: const EdgeInsets.only(bottom: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("derivationsScanProgress".tr(args: [ + '${generateWalletProvider.scanedWalletNumber}', + '${generateWalletProvider.numberScan + 1}' + ])), + const SizedBox(width: 10), + const SizedBox( + height: 22, + width: 22, + child: CircularProgressIndicator( + color: orangeC, + strokeWidth: 3, + ), ), - ), - ], + ], + ), ), ), - ), - Consumer(builder: (context, sub, _) { - return sub.nodeConnected - ? pinForm(context, walletOptions, pinLenght, 1, 2) - : Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - Text( - 'Vous devez vous connecter à internet\npour valider votre coffre', - style: TextStyle( - fontSize: 20, - color: Colors.redAccent, - fontWeight: FontWeight.w500, + Consumer(builder: (context, mw, _) { + return Visibility( + visible: !myWalletProvider.isPinValid && + !myWalletProvider.isPinLoading, + child: Text( + "Ce n'est pas le bon code".tr(), + style: const TextStyle( + color: Colors.red, fontWeight: FontWeight.w500), + ), + ); + }), + SizedBox(height: isTall ? 20 : 10), + Consumer(builder: (context, sub, _) { + return sub.nodeConnected + ? pinForm(context, walletOptions, pinLenght, 1, 2) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Text( + 'Vous devez vous connecter à internet\npour valider votre coffre', + style: TextStyle( + fontSize: 20, + color: Colors.redAccent, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, + ]); + }), + Consumer(builder: (context, sub, _) { + return sub.nodeConnected + ? InkWell( + key: keyCachePassword, + onTap: () { + walletOptions.changePinCacheChoice(); + }, + child: Row(children: [ + const SizedBox(height: 30), + const Spacer(), + Icon( + configBox.get('isCacheChecked') ?? false + ? Icons.check_box + : Icons.check_box_outline_blank, + color: orangeC, ), - ]); - }), - Consumer(builder: (context, sub, _) { - return sub.nodeConnected - ? InkWell( - key: keyCachePassword, - onTap: () { - walletOptions.changePinCacheChoice(); - }, - child: Row(children: [ - const SizedBox(height: 30), - const Spacer(), - Icon( - configBox.get('isCacheChecked') ?? false - ? Icons.check_box - : Icons.check_box_outline_blank, - color: orangeC, - ), - const SizedBox(width: 8), - Text( - 'rememberPassword'.tr(), - style: TextStyle( - fontSize: 16, color: Colors.grey[700]), - ), - const Spacer() - ])) - : const Text(''); - }), - const SizedBox(height: 10), + const SizedBox(width: 8), + Text( + 'rememberPassword'.tr(), + style: TextStyle( + fontSize: 16, color: Colors.grey[700]), + ), + const Spacer() + ])) + : const Text(''); + }), + const SizedBox(height: 10), + ]), + CommonElements().offlineInfo(context), ]), - CommonElements().offlineInfo(context), - ]), - )); + )), + ); } Widget pinForm( context, final walletOptions, pinLenght, int walletNbr, int derivation) { - // var _walletPin = ''; -// ignore: close_sinks - StreamController errorController = - StreamController(); - TextEditingController enterPin = TextEditingController(); final myWalletProvider = Provider.of(context); final generateWalletProvider = Provider.of(context); @@ -150,6 +175,9 @@ class OnboardingStepTen extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 30), child: PinCodeTextField( key: keyPinForm, + textCapitalization: TextCapitalization.characters, + // autoDisposeControllers: false, + focusNode: pinFocus, autoFocus: true, appContext: context, pastedTextStyle: TextStyle( @@ -159,7 +187,8 @@ class OnboardingStepTen extends StatelessWidget { length: pinLenght, obscureText: true, obscuringCharacter: '*', - animationType: AnimationType.fade, + animationType: AnimationType.slide, + animationDuration: const Duration(milliseconds: 80), validator: (v) { if (v!.length < pinLenght) { return "yourPasswordLengthIsX".tr(args: [pinLenght.toString()]); @@ -172,17 +201,15 @@ class OnboardingStepTen extends StatelessWidget { borderWidth: 4, shape: PinCodeFieldShape.box, borderRadius: BorderRadius.circular(5), - fieldHeight: 60, + fieldHeight: 50 * ratio, fieldWidth: 50, - activeFillColor: hasError ? Colors.blueAccent : Colors.black, + activeFillColor: Colors.black, ), showCursor: kDebugMode ? false : true, cursorColor: Colors.black, - animationDuration: const Duration(milliseconds: 300), - textStyle: const TextStyle(fontSize: 20, height: 1.6), + textStyle: const TextStyle(fontSize: 27, height: 1.6), backgroundColor: const Color(0xffF9F9F1), enableActiveFill: false, - errorAnimationController: errorController, controller: enterPin, keyboardType: TextInputType.visiblePassword, boxShadows: const [ @@ -198,6 +225,8 @@ class OnboardingStepTen extends StatelessWidget { log.d('$pin || ${generateWalletProvider.pin.text}'); if (pin.toUpperCase() == generateWalletProvider.pin.text) { pinColor = Colors.green[500]; + myWalletProvider.isPinLoading = false; + myWalletProvider.isPinValid = true; await generateWalletProvider.storeHDWChest(context); bool isAlive = false; @@ -232,17 +261,21 @@ class OnboardingStepTen extends StatelessWidget { page: const OnboardingStepEleven(), isFast: false), ); } else { - errorController.add(ErrorAnimationType - .shake); // Triggering error shake animation hasError = true; + myWalletProvider.isPinLoading = false; + myWalletProvider.isPinValid = false; pinColor = Colors.red[600]; - walletOptions.reload(); + enterPin.text = ''; + // myWalletProvider.reload(); + pinFocus.requestFocus(); } }, onChanged: (value) { + if (enterPin.text != '') myWalletProvider.isPinLoading = true; if (pinColor != const Color(0xFFA4B600)) { pinColor = const Color(0xFFA4B600); } + myWalletProvider.reload(); }, )), ); diff --git a/lib/screens/onBoarding/9.dart b/lib/screens/onBoarding/9.dart index cde70f2..77b3e38 100644 --- a/lib/screens/onBoarding/9.dart +++ b/lib/screens/onBoarding/9.dart @@ -52,6 +52,7 @@ class OnboardingStepNine extends StatelessWidget { children: [ TextField( key: keyGeneratedPin, + textCapitalization: TextCapitalization.characters, enabled: false, controller: generateWalletProvider.pin, maxLines: 1, diff --git a/pubspec.lock b/pubspec.lock index 50b17e4..a7fbfb3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -224,21 +224,7 @@ packages: name: connectivity_plus url: "https://pub.dartlang.org" source: hosted - version: "2.3.9" - connectivity_plus_linux: - dependency: transitive - description: - name: connectivity_plus_linux - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - connectivity_plus_macos: - dependency: transitive - description: - name: connectivity_plus_macos - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.6" + version: "3.0.2" connectivity_plus_platform_interface: dependency: transitive description: @@ -246,20 +232,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.3" - connectivity_plus_web: - dependency: transitive - description: - name: connectivity_plus_web - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.5" - connectivity_plus_windows: - dependency: transitive - description: - name: connectivity_plus_windows - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.2" convert: dependency: transitive description: @@ -576,7 +548,7 @@ packages: name: graphql_flutter url: "https://pub.dartlang.org" source: hosted - version: "5.1.1-beta.4" + version: "5.1.1-beta.5" graphs: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e1d4709..eac80f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,7 +26,7 @@ dependencies: path_provider: ^2.0.9 pdf: ^3.7.1 permission_handler: ^10.0.0 - pin_code_fields: ^7.3.0 + pin_code_fields: ^7.4.0 printing: ^5.9.1 provider: ^6.0.1 barcode_scan2: ^4.2.1 @@ -51,7 +51,7 @@ dependencies: # ref: ec61ebab45287315fa1d7e84830a01d6e23891ae ref: d45eb8d787d625331e6425df5cec9c5d33b30d35 dots_indicator: ^2.1.0 - connectivity_plus: ^2.3.3 + connectivity_plus: ^3.0.2 image_cropper: ^3.0.0 easy_localization: ^3.0.1 flutter_markdown: ^0.6.10+2