diff --git a/assets/translations/en.json b/assets/translations/en.json index 48c5fdbb0eeaf7fae1720075d2c39a6a8de2c23c..16b16f004fa6ae13bcc868bfa7b925c6675b9fa3 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -179,7 +179,7 @@ "contactsManagement": "My contacts", "noContacts": "You don't have any contact", "addContact": "Add\nto contacts", - "removeContact": "Remove\nthis contact", + "removeContact": "Remove this contact", "scanRootDerivationInProgress": "Scan root address", "derivationsScanProgress": "Scan {} firsts addresses", "importDerivationsInProgress": "Import address {}/{}", @@ -251,5 +251,7 @@ "membershipRenewalPeriodNotRespected": "You must wait for the renewal period before you can renew your membership", "addComment": "Add a comment", "comment": "Comment", - "optionalComment": "Optional comment" + "optionalComment": "Optional comment", + "searchContacts": "Search contacts", + "advancedFeature": "Advanced feature reserved for experienced users" } diff --git a/assets/translations/es.json b/assets/translations/es.json index 309b7bdcfe92cc679a587435efa62fa3a0e342b0..87043e5d97a4beb5e2d513ff1bddb5f82eb996c2 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -180,7 +180,7 @@ "contactsManagement": "Mis contactos", "noContacts": "No tienes ningún contacto", "addContact": "Añadir\na contactos", - "removeContact": "Eliminar\neste contacto", + "removeContact": "Eliminar este contacto", "scanRootDerivationInProgress": "Scan root address", "derivationsScanProgress": "Scan {} firsts addresses", "importDerivationsInProgress": "Import address {}/{}", @@ -252,5 +252,7 @@ "membershipRenewalPeriodNotRespected": "Debe esperar el período de renovación antes de poder renovar su membresía", "addComment": "Añadir un comentario", "comment": "Comentario", - "optionalComment": "Comentario opcional" + "optionalComment": "Comentario opcional", + "searchContacts": "Buscar contactos", + "advancedFeature": "Función avanzada reservada para usuarios experimentados" } diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 99b5ee5586c549d370e3032069b5de665500c054..ae1fdcb2cd953b7b63e08c4f0138c737291132e7 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -179,7 +179,7 @@ "contactsManagement": "Mes contacts", "noContacts": "Vous n'avez aucun contact", "addContact": "Ajouter\naux contacts", - "removeContact": "Supprimer\nce contact", + "removeContact": "Supprimer ce contact", "scanRootDerivationInProgress": "Scan de l'adresse racine", "derivationsScanProgress": "Scan des {} premières adresses", "importDerivationsInProgress": "Importation de l'adresse {}/{}", @@ -251,5 +251,7 @@ "membershipRenewalPeriodNotRespected": "Vous devez attendre la période de renouvellement avant de pouvoir renouveler votre adhésion", "addComment": "Ajouter un commentaire", "comment": "Commentaire", - "optionalComment": "Commentaire optionnel" + "optionalComment": "Commentaire optionnel", + "searchContacts": "Rechercher des contacts", + "advancedFeature": "Fonctionnalité avancée réservée aux utilisateurs expérimentés" } diff --git a/integration_test/utility/general_actions.dart b/integration_test/utility/general_actions.dart index 3da41987d2166ea862c958a6943b5e7023ff15c4..5a357b420ad58b7feece19be6c2c01b86d3b9855 100644 --- a/integration_test/utility/general_actions.dart +++ b/integration_test/utility/general_actions.dart @@ -18,8 +18,7 @@ Future changeNode() async { await tapKey(keySelectDuniterNode('Personnalisé'), selectLast: true); await enterText(keyCustomDuniterEndpoint, 'ws://$ipAddress:9944'); await tapKey(keyConnectToEndpoint); - await isIconPresent(Icons.add_card_sharp, - timeout: const Duration(seconds: 8)); + await isIconPresent(Icons.add_card_sharp, timeout: const Duration(seconds: 8)); await goBack(); } @@ -97,8 +96,7 @@ Future restoreChest() async { } Future onboardingNewChest() async { - final generateWalletProvider = - Provider.of<GenerateWalletsProvider>(homeContext, listen: false); + final generateWalletProvider = Provider.of<GenerateWalletsProvider>(homeContext, listen: false); // Open screen create new wallet await tapKey(keyOnboardingNewChest); @@ -176,8 +174,7 @@ Future firstOpenChest() async { Future skipWalletDragTutorial() async { await pump(duration: const Duration(milliseconds: 500), number: 6); await pump(duration: const Duration(seconds: 2)); - if (await isPresent('explainDraggableWallet'.tr().substring(0, 13), - timeout: const Duration(seconds: 5), settle: false)) { + if (await isPresent('explainDraggableWallet'.tr().substring(0, 13), timeout: const Duration(seconds: 5), settle: false)) { await tapKey(keyDragAndDrop, duration: 0); } } diff --git a/lib/extensions.dart b/lib/extensions.dart new file mode 100644 index 0000000000000000000000000000000000000000..b2ecff520fe34447694a6d972764e0a52296e219 --- /dev/null +++ b/lib/extensions.dart @@ -0,0 +1,9 @@ +extension IterableExtension<T> on Iterable<T> { + /// The first element satisfying [test], or `null` if there are none. + T? firstWhereOrNull(bool Function(T element) test) { + for (var element in this) { + if (test(element)) return element; + } + return null; + } +} diff --git a/lib/providers/my_wallets.dart b/lib/providers/my_wallets.dart index 17741bb988bff454d36d7345da91117d0e6b208b..af8c1122f42f51e3c5fb53f094b4164cf4205e36 100644 --- a/lib/providers/my_wallets.dart +++ b/lib/providers/my_wallets.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:gecko/extensions.dart'; import 'dart:async'; import 'package:gecko/globals.dart'; import 'package:gecko/models/wallet_data.dart'; @@ -13,6 +14,8 @@ import 'package:provider/provider.dart'; class MyWalletsProvider with ChangeNotifier { List<WalletData> listWallets = []; + WalletData? idtyWallet; + List<WalletData> listWalletsWithoutIdty = []; String pinCode = ''; late String mnemonic; int? pinLenght; @@ -58,6 +61,14 @@ class MyWalletsProvider with ChangeNotifier { listWallets.add(wallet); n++; } + + listWallets.sort((p1, p2) => Comparable.compare(p1.number!, p2.number!)); + + idtyWallet = listWallets.firstWhereOrNull((w) => w.hasIdentity); + + listWalletsWithoutIdty = listWallets.toList(); + listWalletsWithoutIdty.removeWhere((w) => w.address == idtyWallet?.address); + return listWallets; } diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 2f0dd634fbe3e1f8eda0ccc0ee3237cc24082709..eabafb2a812325ec8280fb8edddd4178775df9a0 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:fast_base58/fast_base58.dart'; @@ -366,11 +368,12 @@ class SubstrateSdk with ChangeNotifier { return totalAmount; } - Future<CertState> certState(String from, String to) async { + Future<CertState> certState(String to) async { final toStatus = (await idtyStatusMulti([to])).first; - final myWallets = MyWalletsProvider(); + final myWallets = Provider.of<MyWalletsProvider>(homeContext, listen: false); + final from = myWallets.idtyWallet?.address; - if (from == to || !myWallets.getWalletDataByAddress(from)!.isMembre) { + if (from == null || from == to || !myWallets.getWalletDataByAddress(from)!.isMembre) { return CertState(status: CertStatus.none); } @@ -830,7 +833,7 @@ class SubstrateSdk with ChangeNotifier { } } - KeyPairData getCurrentWallet() { + KeyPairData getCurrentKeyPair() { try { final acc = keyring.current; return acc; diff --git a/lib/providers/wallet_options.dart b/lib/providers/wallet_options.dart index 307ba11df4d8711103fecf3e319b9ef999909723..55c4bb419578ec911592a2dc3bb385b5c1157795 100644 --- a/lib/providers/wallet_options.dart +++ b/lib/providers/wallet_options.dart @@ -27,7 +27,6 @@ class WalletOptionsProvider with ChangeNotifier { bool ischangedPin = false; final newPin = TextEditingController(); bool isEditing = false; - bool isBalanceBlur = false; final nameController = TextEditingController(); bool isDefaultWallet = false; bool canValidateNameBool = false; @@ -84,11 +83,6 @@ class WalletOptionsProvider with ChangeNotifier { return 0; } - void bluringBalance() { - isBalanceBlur = !isBalanceBlur; - notifyListeners(); - } - Future<String> changeAvatar() async { final datapod = Provider.of<V2sDatapodProvider>(homeContext, listen: false); diff --git a/lib/screens/home.dart b/lib/screens/home.dart index ec046f3897dc55d41ed621b67dc17303189e3bba..336df01bbed332fe36b1a04a36d7ec138eb0172f 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -93,6 +93,9 @@ class _HomeScreenState extends State<HomeScreen> { if (!connectivityResult.contains(ConnectivityResult.none)) { await sub.connectNode(); + // Load wallets list + myWalletProvider.readAllWallets(myWalletProvider.getCurrentChest()); + //Connect to Indexer await duniterIndexer.getValidIndexerEndpoint(); } diff --git a/lib/screens/myWallets/custom_derivations.dart b/lib/screens/myWallets/custom_derivations.dart index 383b2446a33b2fb53eaeb34db16c8990bd073e25..d97e94eb76acf713b735eac789472c4e8b70faa4 100644 --- a/lib/screens/myWallets/custom_derivations.dart +++ b/lib/screens/myWallets/custom_derivations.dart @@ -27,13 +27,9 @@ class _CustomDerivationState extends State<CustomDerivation> { @override Widget build(BuildContext context) { - final myWalletProvider = - Provider.of<MyWalletsProvider>(context, listen: false); + final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); - final derivationList = <String>[ - 'root', - for (var i = 0; i < 51; i += 1) i.toString() - ]; + final derivationList = <String>['root', for (var i = 0; i < 51; i += 1) i.toString()]; for (WalletData wallet in myWalletProvider.listWallets) { derivationList.remove(wallet.derivation.toString()); @@ -57,6 +53,15 @@ class _CustomDerivationState extends State<CustomDerivation> { 'chooseDerivation'.tr(), style: scaledTextStyle(fontSize: 16), ), + ScaledSizedBox(height: 8), + Text( + 'advancedFeature'.tr(), + style: scaledTextStyle( + fontSize: 13, + color: Colors.grey[600], + fontStyle: FontStyle.italic, + ), + ), ScaledSizedBox(height: 20), ScaledSizedBox( width: 100, @@ -78,8 +83,7 @@ class _CustomDerivationState extends State<CustomDerivation> { dropdownValue = newValue!; }); }, - items: derivationList - .map<DropdownMenuItem<String>>((String value) { + items: derivationList.map<DropdownMenuItem<String>>((String value) { return DropdownMenuItem<String>( value: value, child: ScaledSizedBox( @@ -88,8 +92,7 @@ class _CustomDerivationState extends State<CustomDerivation> { const Spacer(), Text( value, - style: scaledTextStyle( - fontSize: 16, color: Colors.black), + style: scaledTextStyle(fontSize: 16, color: Colors.black), ), const Spacer(), ]), @@ -104,16 +107,19 @@ class _CustomDerivationState extends State<CustomDerivation> { child: ElevatedButton( style: ElevatedButton.styleFrom( foregroundColor: Colors.white, - elevation: 4, backgroundColor: orangeC, + elevation: 2, + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: orangeC.withValues(alpha: 0.3), ), onPressed: () async { if (!await myWalletProvider.askPinCode()) return; - String newDerivationName = - '${'wallet'.tr()} ${myWalletProvider.listWallets.last.number! + 2}'; + String newDerivationName = '${'wallet'.tr()} ${myWalletProvider.listWallets.last.number! + 2}'; if (dropdownValue == 'root') { - await myWalletProvider.generateRootWallet( - context, 'rootWallet'.tr()); + await myWalletProvider.generateRootWallet(context, 'rootWallet'.tr()); } else { await myWalletProvider.generateNewDerivation( context, @@ -121,15 +127,15 @@ class _CustomDerivationState extends State<CustomDerivation> { int.parse(dropdownValue!), ); } - Navigator.popUntil( - context, ModalRoute.withName('/mywallets')); + Navigator.popUntil(context, ModalRoute.withName('/mywallets')); }, child: Text( 'validate'.tr(), style: scaledTextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Colors.white), + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.white, + ), ), ), ), diff --git a/lib/screens/myWallets/import_g1_v1.dart b/lib/screens/myWallets/import_g1_v1.dart index e13c394b62b0a411420057a3073227e97337fc95..482ac5670023420f8c25a7bbd06e3b087ca4d3df 100644 --- a/lib/screens/myWallets/import_g1_v1.dart +++ b/lib/screens/myWallets/import_g1_v1.dart @@ -26,8 +26,7 @@ class ImportG1v1 extends StatelessWidget { @override Widget build(BuildContext context) { - final myWalletProvider = - Provider.of<MyWalletsProvider>(context, listen: false); + final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); Timer? debounce; WalletData selectedWallet = myWalletProvider.getDefaultWallet(); @@ -42,25 +41,21 @@ class ImportG1v1 extends StatelessWidget { body: SafeArea( child: Consumer<SubstrateSdk>(builder: (context, sub, _) { return FutureBuilder( - future: sub.getBalanceAndIdtyStatus( - sub.g1V1NewAddress, selectedWallet.address), - builder: (BuildContext context, - AsyncSnapshot<MigrateWalletChecks> status) { + future: sub.getBalanceAndIdtyStatus(sub.g1V1NewAddress, selectedWallet.address), + builder: (BuildContext context, AsyncSnapshot<MigrateWalletChecks> status) { if (status.data == null) { return Column(children: [ ScaledSizedBox(height: 80), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ScaledSizedBox( - height: 35, - width: 35, - child: const CircularProgressIndicator( - color: orangeC, - strokeWidth: 4, - ), - ), - ]), + Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + ScaledSizedBox( + height: 35, + width: 35, + child: const CircularProgressIndicator( + color: orangeC, + strokeWidth: 4, + ), + ), + ]), ]); } @@ -79,13 +74,10 @@ class ImportG1v1 extends StatelessWidget { if (debounce?.isActive ?? false) { debounce!.cancel(); } - debounce = Timer( - const Duration(milliseconds: debouneTime), () { - if (sub.csSalt.text != '' && - sub.csPassword.text != '') { + debounce = Timer(const Duration(milliseconds: debouneTime), () { + if (sub.csSalt.text != '' && sub.csPassword.text != '') { sub.reload(); - sub.csToV2Address( - sub.csSalt.text, sub.csPassword.text); + sub.csToV2Address(sub.csSalt.text, sub.csPassword.text); } }); }, @@ -99,9 +91,7 @@ class ImportG1v1 extends StatelessWidget { suffixIcon: IconButton( key: keyCesiumIdVisible, icon: Icon( - sub.isCesiumIDVisible - ? Icons.visibility_off - : Icons.visibility, + sub.isCesiumIDVisible ? Icons.visibility_off : Icons.visibility, color: Colors.black, size: scaleSize(22), ), @@ -120,14 +110,11 @@ class ImportG1v1 extends StatelessWidget { if (debounce?.isActive ?? false) { debounce!.cancel(); } - debounce = Timer( - const Duration(milliseconds: debouneTime), () { + debounce = Timer(const Duration(milliseconds: debouneTime), () { sub.g1V1NewAddress = ''; - if (sub.csSalt.text != '' && - sub.csPassword.text != '') { + if (sub.csSalt.text != '' && sub.csPassword.text != '') { sub.reload(); - sub.csToV2Address( - sub.csSalt.text, sub.csPassword.text); + sub.csToV2Address(sub.csSalt.text, sub.csPassword.text); } }); }, @@ -140,9 +127,7 @@ class ImportG1v1 extends StatelessWidget { hintStyle: scaledTextStyle(fontSize: 13), suffixIcon: IconButton( icon: Icon( - sub.isCesiumIDVisible - ? Icons.visibility_off - : Icons.visibility, + sub.isCesiumIDVisible ? Icons.visibility_off : Icons.visibility, color: Colors.black, size: scaleSize(22), ), @@ -163,32 +148,24 @@ class ImportG1v1 extends StatelessWidget { GestureDetector( key: keyCopyPubkey, onTap: () { - Clipboard.setData( - ClipboardData(text: sub.g1V1OldPubkey)); + Clipboard.setData(ClipboardData(text: sub.g1V1OldPubkey)); snackCopyKey(context); }, child: Text( 'v1: ${getShortPubkey(sub.g1V1OldPubkey)}', - style: scaledTextStyle( - fontSize: 15, - fontWeight: FontWeight.w600, - fontFamily: 'Monospace'), + style: scaledTextStyle(fontSize: 15, fontWeight: FontWeight.w600, fontFamily: 'Monospace'), ), ), ScaledSizedBox(height: 5), GestureDetector( key: keyCopyAddress, onTap: () { - Clipboard.setData( - ClipboardData(text: sub.g1V1OldPubkey)); + Clipboard.setData(ClipboardData(text: sub.g1V1OldPubkey)); snackCopyKey(context); }, child: Text( 'v2: ${getShortPubkey(sub.g1V1NewAddress)}', - style: scaledTextStyle( - fontSize: 15, - fontWeight: FontWeight.w600, - fontFamily: 'Monospace'), + style: scaledTextStyle(fontSize: 15, fontWeight: FontWeight.w600, fontFamily: 'Monospace'), ), ), ], @@ -200,13 +177,9 @@ class ImportG1v1 extends StatelessWidget { '${statusData.fromBalance['transferableBalance']} $unit', style: scaledTextStyle(fontSize: 15), ), - IdentityStatus( - address: sub.g1V1NewAddress, - isOwner: false, - color: Colors.black), + IdentityStatus(address: sub.g1V1NewAddress, isOwner: false, color: Colors.black), ScaledSizedBox(width: 10), - Certifications( - address: sub.g1V1NewAddress, size: 14) + Certifications(address: sub.g1V1NewAddress, size: 14) ], ), ], @@ -247,13 +220,17 @@ class ImportG1v1 extends StatelessWidget { key: keyConfirm, style: ElevatedButton.styleFrom( foregroundColor: Colors.white, - elevation: 4, backgroundColor: orangeC, + elevation: 2, + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: orangeC.withValues(alpha: 0.3), ), onPressed: statusData.canValidate ? () async { - WalletData? defaultWallet = - myWalletProvider.getDefaultWallet(); + WalletData? defaultWallet = myWalletProvider.getDefaultWallet(); String? pin; if (myWalletProvider.pinCode == '') { @@ -261,8 +238,7 @@ class ImportG1v1 extends StatelessWidget { context, MaterialPageRoute( builder: (homeContext) { - return UnlockingWallet( - wallet: defaultWallet); + return UnlockingWallet(wallet: defaultWallet); }, ), ); @@ -284,10 +260,8 @@ class ImportG1v1 extends StatelessWidget { return TransactionInProgress( transactionId: transactionId, transType: 'identityMigration', - fromAddress: - getShortPubkey(sub.g1V1NewAddress), - toAddress: getShortPubkey( - selectedWallet.address)); + fromAddress: getShortPubkey(sub.g1V1NewAddress), + toAddress: getShortPubkey(selectedWallet.address)); }), ); resetScreen(); @@ -296,7 +270,10 @@ class ImportG1v1 extends StatelessWidget { child: Text( 'migrateAccount'.tr(), style: scaledTextStyle( - fontSize: 18, fontWeight: FontWeight.w600), + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.white, + ), ), ), ), @@ -304,8 +281,7 @@ class ImportG1v1 extends StatelessWidget { Text( statusData.validationStatus, textAlign: TextAlign.center, - style: scaledTextStyle( - fontSize: 11, color: Colors.grey[600]), + style: scaledTextStyle(fontSize: 11, color: Colors.grey[600]), ) ]); }); diff --git a/lib/screens/myWallets/show_seed.dart b/lib/screens/myWallets/show_seed.dart index 3382077d2b4f5b0b2ab54b44a380f33884938290..0c23bb33f5e165063d38ffb1bde4c7664140261a 100644 --- a/lib/screens/myWallets/show_seed.dart +++ b/lib/screens/myWallets/show_seed.dart @@ -16,18 +16,13 @@ import 'package:provider/provider.dart'; import 'package:pdf/widgets.dart' as pw; class ShowSeed extends StatelessWidget { - const ShowSeed( - {Key? keyMyWallets, - required this.walletName, - required this.walletProvider}) - : super(key: keyMyWallets); + const ShowSeed({Key? keyMyWallets, required this.walletName, required this.walletProvider}) : super(key: keyMyWallets); final String? walletName; final MyWalletsProvider walletProvider; @override Widget build(BuildContext context) { - final myWalletProvider = - Provider.of<MyWalletsProvider>(context, listen: false); + final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); final sub = Provider.of<SubstrateSdk>(context, listen: false); WalletData defaultWallet = myWalletProvider.getDefaultWallet(); @@ -39,11 +34,9 @@ class ShowSeed extends StatelessWidget { child: Column(children: <Widget>[ const Spacer(flex: 1), FutureBuilder( - future: - sub.getSeed(defaultWallet.address, walletProvider.pinCode), + future: sub.getSeed(defaultWallet.address, walletProvider.pinCode), builder: (BuildContext context, AsyncSnapshot<String?> seed) { - if (seed.connectionState != ConnectionState.done || - seed.hasError) { + if (seed.connectionState != ConnectionState.done || seed.hasError) { return ScaledSizedBox( height: 15, width: 15, @@ -56,66 +49,61 @@ class ShowSeed extends StatelessWidget { return const Text(''); } - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Column(children: [ - BuildText( - text: 'keepYourMnemonicSecret'.tr(), size: 16), - ScaledSizedBox(height: 35), - sentanceArray(context, seed.data!.split(' ')), - ScaledSizedBox(height: 20), - Row( - children: [ - ScaledSizedBox( - height: 39, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.black, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - backgroundColor: orangeC, - elevation: 1, - ), - onPressed: () { - Clipboard.setData( - ClipboardData(text: seed.data!)); - snackCopySeed(context); - }, - child: Row(children: <Widget>[ - Image.asset( - 'assets/walletOptions/copy-white.png', - height: scaleSize(24), - ), - ScaledSizedBox(width: 7), - Text( - 'copy'.tr(), - style: scaledTextStyle( - fontSize: 13, color: Colors.grey[50]), - ) - ]), + return Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + Column(children: [ + BuildText(text: 'keepYourMnemonicSecret'.tr(), size: 16), + ScaledSizedBox(height: 35), + sentanceArray(context, seed.data!.split(' ')), + ScaledSizedBox(height: 20), + Row( + children: [ + ScaledSizedBox( + height: 39, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.black, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), ), + backgroundColor: orangeC, + elevation: 1, ), - ScaledSizedBox(width: 50), - GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return PrintWallet(seed.data); - }), - ); - }, - child: Image.asset( - 'assets/printer.png', - height: scaleSize(38), + onPressed: () { + Clipboard.setData(ClipboardData(text: seed.data!)); + snackCopySeed(context); + }, + child: Row(children: <Widget>[ + Image.asset( + 'assets/walletOptions/copy-white.png', + height: scaleSize(24), ), - ), - ], + ScaledSizedBox(width: 7), + Text( + 'copy'.tr(), + style: scaledTextStyle(fontSize: 13, color: Colors.grey[50]), + ) + ]), + ), + ), + ScaledSizedBox(width: 50), + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return PrintWallet(seed.data); + }), + ); + }, + child: Image.asset( + 'assets/printer.png', + height: scaleSize(38), + ), ), - ]), - ]); + ], + ), + ]), + ]); }), const Spacer(flex: 3), ScaledSizedBox( @@ -124,8 +112,13 @@ class ShowSeed extends StatelessWidget { child: ElevatedButton( style: ElevatedButton.styleFrom( foregroundColor: Colors.white, - elevation: 4, backgroundColor: orangeC, + elevation: 2, + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: orangeC.withValues(alpha: 0.3), ), onPressed: () { Navigator.pop(context); @@ -133,9 +126,10 @@ class ShowSeed extends StatelessWidget { child: Text( 'close'.tr(), style: scaledTextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Colors.white), + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.white, + ), ), ), ), @@ -233,8 +227,7 @@ class PrintWallet extends StatelessWidget { } Future<Uint8List> printWallet(String seed) async { - final ByteData fontData = - await rootBundle.load("assets/OpenSans-Regular.ttf"); + final ByteData fontData = await rootBundle.load("assets/OpenSans-Regular.ttf"); final pw.Font ttf = pw.Font.ttf(fontData.buffer.asByteData()); final pdf = pw.Document(); @@ -250,13 +243,11 @@ class PrintWallet extends StatelessWidget { child: pw.Column(children: <pw.Widget>[ pw.Text( number.toString(), - style: pw.TextStyle( - fontSize: 14, color: const PdfColor(0.5, 0, 0), font: ttf), + style: pw.TextStyle(fontSize: 14, color: const PdfColor(0.5, 0, 0), font: ttf), ), pw.Text( dataWord, - style: pw.TextStyle( - fontSize: 19, color: const PdfColor(0, 0, 0), font: ttf), + style: pw.TextStyle(fontSize: 19, color: const PdfColor(0, 0, 0), font: ttf), ), pw.SizedBox(height: 10) ]), @@ -288,12 +279,7 @@ class PrintWallet extends StatelessWidget { arrayCell(7, seedList[6]), arrayCell(8, seedList[7]), ]), - pw.Row(children: <pw.Widget>[ - arrayCell(9, seedList[8]), - arrayCell(10, seedList[9]), - arrayCell(11, seedList[10]), - arrayCell(12, seedList[11]) - ]), + pw.Row(children: <pw.Widget>[arrayCell(9, seedList[8]), arrayCell(10, seedList[9]), arrayCell(11, seedList[10]), arrayCell(12, seedList[11])]), pw.SizedBox(height: 105), pw.Image(geckoLogo, height: 80), pw.SizedBox(height: 205), diff --git a/lib/screens/myWallets/unlocking_wallet.dart b/lib/screens/myWallets/unlocking_wallet.dart index 42e71639a64408399066f5e38f255890204d6c26..579f2e83505868ecf224cfb8649629e2d59fbe1d 100644 --- a/lib/screens/myWallets/unlocking_wallet.dart +++ b/lib/screens/myWallets/unlocking_wallet.dart @@ -29,9 +29,7 @@ class _UnlockingWalletState extends State<UnlockingWallet> { late final TextEditingController enterPin; late final FocusNode pinFocus; - StreamController<ErrorAnimationType>? errorController; - - Color? pinColor = const Color(0xffF9F9F1); + Color pinColor = const Color(0xffF9F9F1); @override void initState() { @@ -44,15 +42,10 @@ class _UnlockingWalletState extends State<UnlockingWallet> { @override Widget build(BuildContext context) { - final walletOptions = - Provider.of<WalletOptionsProvider>(context, listen: false); - final myWalletProvider = - Provider.of<MyWalletsProvider>(context, listen: false); - - int pinLenght = walletOptions.getPinLenght(widget.wallet.number); - errorController = StreamController<ErrorAnimationType>(); + final walletOptions = Provider.of<WalletOptionsProvider>(context, listen: false); + final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); - // if (enterPin.text == '') myWalletProvider.isPinLoading = true; + final pinLenght = walletOptions.getPinLenght(widget.wallet.number); return PopScope( onPopInvokedWithResult: (_, __) { @@ -62,135 +55,133 @@ class _UnlockingWalletState extends State<UnlockingWallet> { child: Scaffold( backgroundColor: backgroundColor, body: SafeArea( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: <Widget>[ - Stack(children: <Widget>[ - Positioned( - top: 10, - left: 15, - child: Builder( - builder: (context) => IconButton( - key: keyPopButton, - icon: Icon( - Icons.arrow_back, - color: Colors.black, - size: scaleSize(28), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ + Padding( + padding: const EdgeInsets.all(16.0), + child: IconButton( + key: keyPopButton, + icon: Icon( + Icons.arrow_back, + color: Colors.black, + size: scaleSize(28), + ), + onPressed: () { + myWalletProvider.isPinValid = false; + myWalletProvider.isPinLoading = true; + Navigator.pop(context); + }, + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: <Widget>[ + ScaledSizedBox(height: isTall ? 40 : 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + currentChest.imageFile == null + ? Image.asset( + 'assets/chests/${currentChest.imageName}', + width: scaleSize(95), + ) + : Image.file( + currentChest.imageFile!, + width: scaleSize(127), + ), + ScaledSizedBox(width: 18), + Flexible( + child: Text( + currentChest.name!, + textAlign: TextAlign.center, + style: scaledTextStyle( + fontSize: 24, + color: Colors.black, + fontWeight: FontWeight.w700, + ), ), - onPressed: () { - myWalletProvider.isPinValid = false; - myWalletProvider.isPinLoading = true; - Navigator.pop(context); - }, ), - ), + ], ), - Column(children: <Widget>[ - ScaledSizedBox(height: isTall ? 80 : 65), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: <Widget>[ - currentChest.imageFile == null - ? Image.asset( - 'assets/chests/${currentChest.imageName}', - width: scaleSize(95), - ) - : Image.file( - currentChest.imageFile!, - width: scaleSize(127), - ), - ScaledSizedBox(width: 5), - ScaledSizedBox( - width: 250, - child: Text( - currentChest.name!, - textAlign: TextAlign.center, - style: scaledTextStyle( - fontSize: 21, - color: Colors.black, - fontWeight: FontWeight.w700), - )), - ]), - ScaledSizedBox(height: isTall ? 30 : 15), - ScaledSizedBox( - width: 350, - child: Text( + ScaledSizedBox(height: isTall ? 40 : 25), + Container( + margin: const EdgeInsets.symmetric(horizontal: 24), + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.05), + blurRadius: 10, + offset: const Offset(0, 5), + ), + ], + ), + child: Column( + children: [ + Text( 'toUnlockEnterPassword'.tr(), textAlign: TextAlign.center, style: scaledTextStyle( - fontSize: 15, - color: Colors.black, - fontWeight: FontWeight.w400), - )), - ScaledSizedBox(height: isTall ? 30 : 15), - if (!myWalletProvider.isPinValid && - !myWalletProvider.isPinLoading) - Text( - "thisIsNotAGoodCode".tr(), - style: scaledTextStyle( - color: Colors.red, + fontSize: 16, + color: Colors.black87, fontWeight: FontWeight.w500, - fontSize: 15), - ), - ScaledSizedBox(height: isTall ? 8 : 0), - pinForm(context, pinLenght), - ScaledSizedBox(height: 8), - if (canUnlock) - Consumer<WalletOptionsProvider>( - builder: (context, sub, _) { - return InkWell( - key: keyCachePassword, - onTap: () { - walletOptions.changePinCacheChoice(); - }, - child: Row(children: [ - ScaledSizedBox(height: 30), - const Spacer(), - Icon( - configBox.get('isCacheChecked') - ? Icons.check_box - : Icons.check_box_outline_blank, - color: orangeC, - size: scaleSize(22), - ), - ScaledSizedBox(width: 8), - Text( - 'rememberPassword'.tr(), + ), + ), + ScaledSizedBox(height: isTall ? 24 : 16), + if (!myWalletProvider.isPinValid && !myWalletProvider.isPinLoading) + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text( + "thisIsNotAGoodCode".tr(), style: scaledTextStyle( - fontSize: 14, color: Colors.grey[700]), + color: Colors.red[700], + fontWeight: FontWeight.w500, + fontSize: 15, + ), ), - const Spacer() - ]), - ); - }), - // const ScaledSizedBox(height: 10), - // if (canUnlock) - // InkWell( - // key: keyChangeChest, - // onTap: () { - // // Navigator.push( - // // context, - // // MaterialPageRoute(builder: (context) { - // // return const ChooseChest(); - // // }), - // // ); - // }, - // child: ScaledSizedBox( - // width: 400, - // height: 50, - // child: Center( - // child: Text( - // 'changeChest'.tr(), - // style: const scaledTextStyle( - // fontSize: 21, - // color: Colors.grey, // orangeC - // fontWeight: FontWeight.w600), - // ), - // ), - // )), - ]), - ]), - ]), + ), + pinForm(context, pinLenght), + ScaledSizedBox(height: 16), + if (canUnlock) + Consumer<WalletOptionsProvider>(builder: (context, sub, _) { + return InkWell( + key: keyCachePassword, + onTap: () { + walletOptions.changePinCacheChoice(); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + configBox.get('isCacheChecked') ? Icons.check_box : Icons.check_box_outline_blank, + color: orangeC, + size: scaleSize(20), + ), + ScaledSizedBox(width: 8), + Flexible( + child: Text( + 'rememberPassword'.tr(), + style: scaledTextStyle( + fontSize: 12, + color: Colors.grey[700], + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ); + }), + ], + ), + ), + ], + ), + ), + ]), )), ); } @@ -199,22 +190,11 @@ class _UnlockingWalletState extends State<UnlockingWallet> { final myWalletProvider = Provider.of<MyWalletsProvider>(context); final sub = Provider.of<SubstrateSdk>(context, listen: false); - WalletData defaultWallet = myWalletProvider.getDefaultWallet(); - - // if (defaultWallet.address == null) { - // canUnlock = false; - // return Text( - // 'Impossible de retrouver votre\nportefeuille par défaut.\nID: ${defaultWallet.id()}', - // textAlign: TextAlign.center, - // style: const scaledTextStyle( - // color: Colors.redAccent, fontWeight: FontWeight.w500), - // ); - // } + final defaultWallet = myWalletProvider.getDefaultWallet(); return Form( child: Padding( - padding: EdgeInsets.symmetric( - vertical: scaleSize(3), horizontal: scaleSize(isTall ? 40 : 20)), + padding: EdgeInsets.symmetric(vertical: scaleSize(3), horizontal: scaleSize(isTall ? 30 : 20)), child: PinCodeTextField( key: keyPinForm, textCapitalization: TextCapitalization.characters, @@ -227,9 +207,9 @@ class _UnlockingWalletState extends State<UnlockingWallet> { ), length: pinLenght, obscureText: true, - obscuringCharacter: '*', - animationType: AnimationType.slide, - animationDuration: const Duration(milliseconds: 40), + obscuringCharacter: '●', + animationType: AnimationType.fade, + animationDuration: const Duration(milliseconds: 150), useHapticFeedback: true, validator: (v) { if (v!.length < pinLenght) { @@ -239,37 +219,38 @@ class _UnlockingWalletState extends State<UnlockingWallet> { } }, pinTheme: PinTheme( - activeColor: pinColor, - borderWidth: 4, shape: PinCodeFieldShape.box, - borderRadius: BorderRadius.circular(5), - fieldHeight: scaleSize(47), - fieldWidth: scaleSize(47), - activeFillColor: Colors.black, + borderRadius: BorderRadius.circular(12), + fieldHeight: scaleSize(50), + fieldWidth: scaleSize(50), + activeFillColor: Colors.white, + selectedFillColor: Colors.white, + inactiveFillColor: Colors.white, + activeColor: pinColor, + selectedColor: orangeC, + inactiveColor: Colors.grey[300], + borderWidth: 1.5, ), + enableActiveFill: true, showCursor: !kDebugMode, - cursorColor: Colors.black, - textStyle: scaledTextStyle(fontSize: 24, height: 1.6), - backgroundColor: const Color(0xffF9F9F1), - enableActiveFill: false, + cursorColor: orangeC, + cursorHeight: 25, + textStyle: scaledTextStyle( + fontSize: 24, + height: 1.6, + fontWeight: FontWeight.w600, + ), + backgroundColor: Colors.transparent, controller: enterPin, keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], - boxShadows: const [ - BoxShadow( - offset: Offset(0, 1), - color: Colors.black12, - blurRadius: 10, - ) - ], onCompleted: (pin) async { myWalletProvider.isPinLoading = true; myWalletProvider.pinCode = pin.toUpperCase(); - final isValid = await sub.checkPassword( - defaultWallet.address, pin.toUpperCase()); + final isValid = await sub.checkPassword(defaultWallet.address, pin.toUpperCase()); if (!isValid) { await Future.delayed(const Duration(milliseconds: 20)); - pinColor = Colors.red[600]; + pinColor = Colors.red[600]!; myWalletProvider.isPinLoading = false; myWalletProvider.isPinValid = false; myWalletProvider.pinCode = myWalletProvider.mnemonic = ''; @@ -278,7 +259,7 @@ class _UnlockingWalletState extends State<UnlockingWallet> { } else { myWalletProvider.isPinValid = true; myWalletProvider.isPinLoading = false; - pinColor = Colors.green[400]; + pinColor = Colors.green[400]!; myWalletProvider.debounceResetPinCode(); Navigator.pop(context, pin.toUpperCase()); } diff --git a/lib/screens/myWallets/wallet_options.dart b/lib/screens/myWallets/wallet_options.dart index 7066cbb70d8bfaba1df5b323fb7ec4bf2d9b2319..af723f5d50fb468af56a6cb6f2cf39aba1a2ad37 100644 --- a/lib/screens/myWallets/wallet_options.dart +++ b/lib/screens/myWallets/wallet_options.dart @@ -48,7 +48,6 @@ class WalletOptions extends StatelessWidget { return PopScope( onPopInvokedWithResult: (_, __) { walletOptions.isEditing = false; - walletOptions.isBalanceBlur = false; myWalletProvider.reload(); }, child: Scaffold( diff --git a/lib/screens/myWallets/wallets_home.dart b/lib/screens/myWallets/wallets_home.dart index 8be7ef544b0807f28123ddf2b2e539d09e3d0cae..3d541bfe90dd89740d098d7ede990ecf2708695e 100644 --- a/lib/screens/myWallets/wallets_home.dart +++ b/lib/screens/myWallets/wallets_home.dart @@ -6,7 +6,6 @@ import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/scale_functions.dart'; import 'package:gecko/models/widgets_keys.dart'; import 'package:gecko/providers/my_wallets.dart'; -import 'package:gecko/models/wallet_data.dart'; import 'package:flutter/material.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/screens/myWallets/wallet_options.dart'; @@ -21,32 +20,46 @@ import 'package:gecko/widgets/wallet_tile_membre.dart'; import 'package:provider/provider.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; -class WalletsHome extends StatelessWidget { +class WalletsHome extends StatefulWidget { const WalletsHome({super.key}); @override - Widget build(BuildContext context) { - final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); + State<WalletsHome> createState() => _WalletsHomeState(); +} - return FutureBuilder<List<WalletData>>( - future: myWalletProvider.readAllWallets(myWalletProvider.getCurrentChest()), - builder: (context, snapshot) { - if (snapshot.connectionState != ConnectionState.done) { - return const Scaffold( - body: Center( - child: CircularProgressIndicator(color: orangeC), - ), - ); - } +class _WalletsHomeState extends State<WalletsHome> with SingleTickerProviderStateMixin { + late final AnimationController _controller; + late final Animation<double> _animation; - // If only one wallet, directly show WalletOptions - if (myWalletProvider.listWallets.length == 1) { - return WalletOptions(wallet: myWalletProvider.listWallets[0]); - } + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: const Duration(milliseconds: 150), + vsync: this, + ); + _animation = CurvedAnimation( + parent: _controller, + curve: Curves.easeIn, + ); + _controller.forward(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); - // Otherwise show normal WalletsHome screen - return _WalletsHomeContent(); - }, + return Scaffold( + body: FadeTransition( + opacity: _animation, + child: myWalletProvider.listWallets.length == 1 ? WalletOptions(wallet: myWalletProvider.listWallets[0]) : _WalletsHomeContent(), + ), ); } } @@ -59,61 +72,44 @@ class _WalletsHomeContent extends StatelessWidget { final ChestData currentChest = chestBox.get(currentChestNumber)!; return Scaffold( - backgroundColor: backgroundColor, - appBar: AppBar( - toolbarHeight: scaleSize(57), - title: Row( - children: [ - Image.asset( - 'assets/chests/${currentChest.imageName}', - height: 32, - ), - ScaledSizedBox(width: 17), - Text( - currentChest.name!, - style: scaledTextStyle(color: Colors.grey[850], fontSize: 16, fontWeight: FontWeight.w500), - ), - ], + backgroundColor: backgroundColor, + appBar: AppBar( + toolbarHeight: scaleSize(57), + title: Row( + children: [ + Image.asset( + 'assets/chests/${currentChest.imageName}', + height: 32, + ), + ScaledSizedBox(width: 17), + Text( + currentChest.name!, + style: scaledTextStyle(color: Colors.grey[850], fontSize: 16, fontWeight: FontWeight.w500), + ), + ], + ), ), - ), - bottomNavigationBar: Consumer<MyWalletsProvider>(builder: (context, _, __) { - return myWalletProvider.lastFlyBy == null - ? const GeckoBottomAppBar( - actualRoute: 'safeHome', - ) - : DragWalletsInfo( - lastFlyBy: myWalletProvider.lastFlyBy!, - dragAddress: myWalletProvider.dragAddress!, - ); - }), - body: FutureBuilder( - future: myWalletProvider.readAllWallets(currentChestNumber), - builder: (context, snapshot) { - if (snapshot.connectionState != ConnectionState.done || snapshot.hasError) { - return Center( - child: ScaledSizedBox( - height: 50, - width: 50, - child: const CircularProgressIndicator( - color: orangeC, - strokeWidth: 3, - ), - ), - ); - } - return SafeArea( - child: Stack(children: [ - myWalletsTiles(context, currentChestNumber), - const OfflineInfo(), - ]), - ); - }), - ); + bottomNavigationBar: Consumer<MyWalletsProvider>(builder: (context, _, __) { + return myWalletProvider.lastFlyBy == null + ? const GeckoBottomAppBar( + actualRoute: 'safeHome', + ) + : DragWalletsInfo( + lastFlyBy: myWalletProvider.lastFlyBy!, + dragAddress: myWalletProvider.dragAddress!, + ); + }), + body: SafeArea( + child: Stack(children: [ + myWalletsTiles(context, currentChestNumber), + const OfflineInfo(), + ]), + )); } Widget myWalletsTiles(BuildContext context, int currentChestNumber) { final myWalletProvider = Provider.of<MyWalletsProvider>(context); - final bool isWalletsExists = myWalletProvider.isWalletsExists(); + final isWalletsExists = myWalletProvider.isWalletsExists(); if (!isWalletsExists) { return const Text(''); @@ -130,21 +126,6 @@ class _WalletsHomeContent extends StatelessWidget { ])); } - // Get wallet list and sort by derivation number - List<WalletData> listWallets = myWalletProvider.listWallets; - listWallets.sort((p1, p2) { - return Comparable.compare(p1.number!, p2.number!); - }); - - // Get first wallet with identity - final idtyWallet = listWallets.firstWhere( - (w) => w.hasIdentity, - orElse: () => WalletData(address: ''), - ); - - List<WalletData> listWalletsWithoutIdty = listWallets.toList(); - listWalletsWithoutIdty.removeWhere((w) => w.address == idtyWallet.address); - final screenWidth = MediaQuery.of(context).size.width; int nTule; @@ -188,7 +169,7 @@ class _WalletsHomeContent extends StatelessWidget { // configBox.delete('showDraggableTutorial'); final bool showDraggableTutorial = configBox.get('showDraggableTutorial') ?? true; - if (listWallets.length > 1 && showDraggableTutorial) { + if (myWalletProvider.listWallets.length > 1 && showDraggableTutorial) { tutorialCoachMark.show(context: context); configBox.put('showDraggableTutorial', false); } @@ -197,15 +178,15 @@ class _WalletsHomeContent extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 5), child: CustomScrollView(slivers: <Widget>[ SliverToBoxAdapter(child: ScaledSizedBox(height: 12)), - if (idtyWallet.address != '') + if (myWalletProvider.idtyWallet != null) SliverToBoxAdapter( child: DragTuleAction( - wallet: idtyWallet, - child: WalletTileMembre(repository: idtyWallet), + wallet: myWalletProvider.idtyWallet!, + child: WalletTileMembre(wallet: myWalletProvider.idtyWallet!), ), ), SliverGrid.count(key: keyListWallets, crossAxisCount: nTule, childAspectRatio: 1, crossAxisSpacing: 0, mainAxisSpacing: 0, children: <Widget>[ - for (WalletData repository in listWalletsWithoutIdty) + for (final repository in myWalletProvider.listWalletsWithoutIdty) DragTuleAction( wallet: repository, child: WalletTile(repository: repository), diff --git a/lib/screens/my_contacts.dart b/lib/screens/my_contacts.dart index 33317dea61bbe8c641711de87fcde18dd674bdcb..cd88da0c4db41f5e07ad9001a95e4560bebe30e1 100644 --- a/lib/screens/my_contacts.dart +++ b/lib/screens/my_contacts.dart @@ -8,30 +8,82 @@ import 'package:gecko/widgets/commons/top_appbar.dart'; import 'package:gecko/widgets/contacts_list.dart'; import 'package:provider/provider.dart'; -class ContactsScreen extends StatelessWidget { +class ContactsScreen extends StatefulWidget { const ContactsScreen({super.key}); + @override + State<ContactsScreen> createState() => _ContactsScreenState(); +} + +class _ContactsScreenState extends State<ContactsScreen> { + String searchQuery = ''; + final FocusNode _searchFocus = FocusNode(); + + @override + void dispose() { + _searchFocus.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { Provider.of<WalletsProfilesProvider>(context, listen: true); - final myContacts = contactsBox.toMap().values.toList(); + final allContacts = contactsBox.toMap().values.toList(); // Order contacts by username - myContacts.sort((p1, p2) { - return Comparable.compare(p1.username?.toLowerCase() ?? 'zz', - p2.username?.toLowerCase() ?? 'zz'); + allContacts.sort((p1, p2) { + return Comparable.compare(p1.username?.toLowerCase() ?? 'zz', p2.username?.toLowerCase() ?? 'zz'); }); - return Scaffold( - backgroundColor: backgroundColor, - appBar: GeckoAppBar( - 'contactsManagementWithNbr'.tr(args: ['${myContacts.length}'])), - bottomNavigationBar: const GeckoBottomAppBar(), - body: SafeArea( - child: Stack(children: [ - ContactsList(myContacts: myContacts), - const OfflineInfo(), - ]), + // Filter contacts based on search query + final filteredContacts = searchQuery.isEmpty + ? allContacts + : allContacts.where((contact) { + final username = (contact.username ?? '').toLowerCase(); + final address = contact.address.toLowerCase(); + final query = searchQuery.toLowerCase(); + return username.contains(query) || address.contains(query); + }).toList(); + + return GestureDetector( + onTap: () { + // Défocuser le champ de recherche quand on clique en dehors + if (_searchFocus.hasFocus) { + _searchFocus.unfocus(); + } + }, + child: Scaffold( + backgroundColor: backgroundColor, + appBar: GeckoAppBar('contactsManagementWithNbr'.tr(args: ['${allContacts.length}'])), + bottomNavigationBar: const GeckoBottomAppBar(), + body: SafeArea( + child: Stack(children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + focusNode: _searchFocus, + onChanged: (value) => setState(() => searchQuery = value), + decoration: InputDecoration( + hintText: 'searchContacts'.tr(), + prefixIcon: const Icon(Icons.search), + border: const OutlineInputBorder(), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: orangeC), + ), + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + ), + ), + ), + Expanded( + child: ContactsList(myContacts: filteredContacts), + ), + ], + ), + const OfflineInfo(), + ]), + ), ), ); } diff --git a/lib/screens/onBoarding/11_congratulations.dart b/lib/screens/onBoarding/11_congratulations.dart index bfb919c92352666ce5dbdc5010a0a9a71a9c445a..43e6df6df53028c966a84bb5c39170d45a89050a 100644 --- a/lib/screens/onBoarding/11_congratulations.dart +++ b/lib/screens/onBoarding/11_congratulations.dart @@ -115,15 +115,24 @@ Widget finishButton(BuildContext context) { key: keyGoWalletsHome, style: ElevatedButton.styleFrom( foregroundColor: Colors.white, - elevation: 4, backgroundColor: orangeC, + elevation: 2, + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: orangeC.withValues(alpha: 0.3), ), onPressed: () { Navigator.pushNamedAndRemoveUntil(context, '/mywallets', ModalRoute.withName('/')); }, child: Text( "accessMyChest".tr(), - style: scaledTextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Colors.white), + style: scaledTextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.white, + ), ), ), ); diff --git a/lib/screens/onBoarding/5.dart b/lib/screens/onBoarding/5.dart index 268ccf25a9a6270a7cb139c96832469640957a7b..a3f21378369a6628d1c11a461ad53a8ea1b97ab9 100644 --- a/lib/screens/onBoarding/5.dart +++ b/lib/screens/onBoarding/5.dart @@ -32,8 +32,7 @@ class OnboardingStepFive extends StatefulWidget { class _ChooseChestState extends State<OnboardingStepFive> { @override Widget build(BuildContext context) { - final generateWalletProvider = - Provider.of<GenerateWalletsProvider>(context, listen: false); + final generateWalletProvider = Provider.of<GenerateWalletsProvider>(context, listen: false); return Scaffold( backgroundColor: backgroundColor, @@ -64,8 +63,7 @@ class _ChooseChestState extends State<OnboardingStepFive> { elevation: 1, ), onPressed: () { - Clipboard.setData(ClipboardData( - text: generateWalletProvider.generatedMnemonic!)); + Clipboard.setData(ClipboardData(text: generateWalletProvider.generatedMnemonic!)); snackCopySeed(context); }, child: Row(children: <Widget>[ @@ -76,8 +74,7 @@ class _ChooseChestState extends State<OnboardingStepFive> { const Spacer(), Text( 'copy'.tr(), - style: scaledTextStyle( - fontSize: 14, color: Colors.grey[50]), + style: scaledTextStyle(fontSize: 14, color: Colors.grey[50]), ), const Spacer(), ]), @@ -89,8 +86,7 @@ class _ChooseChestState extends State<OnboardingStepFive> { Navigator.push( context, MaterialPageRoute(builder: (context) { - return PrintWallet( - generateWalletProvider.generatedMnemonic!); + return PrintWallet(generateWalletProvider.generatedMnemonic!); }), ); }, @@ -112,22 +108,34 @@ class _ChooseChestState extends State<OnboardingStepFive> { key: keyGenerateMnemonic, style: ElevatedButton.styleFrom( foregroundColor: Colors.black, - elevation: 4, backgroundColor: const Color(0xffFFD58D), + elevation: 2, + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: const Color(0xffFFD58D).withValues(alpha: 0.3), ), onPressed: () { setState(() {}); }, - child: Text("chooseAnotherMnemonic".tr(), + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + "chooseAnotherMnemonic".tr(), textAlign: TextAlign.center, style: scaledTextStyle( - fontSize: 21, fontWeight: FontWeight.w600))), + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + )), ), ), ), ScaledSizedBox(height: isTall ? 20 : 10), - nextButton( - context, "iNotedMyMnemonic".tr(), false, widget.skipIntro), + nextButton(context, "iNotedMyMnemonic".tr(), false, widget.skipIntro), isTall ? const Spacer() : const SizedBox(height: 5), ]), const OfflineInfo(), @@ -138,8 +146,7 @@ class _ChooseChestState extends State<OnboardingStepFive> { } Widget sentanceArray(BuildContext context) { - final generateWalletProvider = - Provider.of<GenerateWalletsProvider>(context, listen: false); + final generateWalletProvider = Provider.of<GenerateWalletsProvider>(context, listen: false); return Container( constraints: BoxConstraints(maxWidth: scaleSize(isTall ? 355 : 340)), @@ -205,12 +212,9 @@ Widget arrayCell(dataWord) { ); } -Widget nextButton( - BuildContext context, String text, bool isFast, bool skipIntro) { - final generateWalletProvider = - Provider.of<GenerateWalletsProvider>(context, listen: false); - final myWalletProvider = - Provider.of<MyWalletsProvider>(context, listen: false); +Widget nextButton(BuildContext context, String text, bool isFast, bool skipIntro) { + final generateWalletProvider = Provider.of<GenerateWalletsProvider>(context, listen: false); + final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); return ScaledSizedBox( width: 350, height: 55, @@ -218,28 +222,31 @@ Widget nextButton( key: keyGoNext, style: ElevatedButton.styleFrom( foregroundColor: Colors.white, - elevation: 4, backgroundColor: orangeC, + elevation: 2, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: orangeC.withValues(alpha: 0.3), ), onPressed: () { generateWalletProvider.nbrWord = generateWalletProvider.getRandomInt(); - generateWalletProvider.nbrWordAlpha = generateWalletProvider - .intToString(generateWalletProvider.nbrWord + 1); + generateWalletProvider.nbrWordAlpha = generateWalletProvider.intToString(generateWalletProvider.nbrWord + 1); myWalletProvider.mnemonic = generateWalletProvider.generatedMnemonic!; Navigator.push( context, - FaderTransition( - page: OnboardingStepSix( - generatedMnemonic: generateWalletProvider.generatedMnemonic, - skipIntro: skipIntro), - isFast: true), + FaderTransition(page: OnboardingStepSix(generatedMnemonic: generateWalletProvider.generatedMnemonic, skipIntro: skipIntro), isFast: true), ); }, child: Text( text, style: scaledTextStyle( - fontSize: 21, fontWeight: FontWeight.w600, color: Colors.white), + fontSize: 18, + fontWeight: FontWeight.w500, + color: Colors.white, + ), ), ), ); diff --git a/lib/screens/onBoarding/6.dart b/lib/screens/onBoarding/6.dart index 1f81e9a7a76153d3ef8958f6a2fbb1468092dea9..923409af28cf4485fb5d9dd322a1d27b4d00aa4a 100644 --- a/lib/screens/onBoarding/6.dart +++ b/lib/screens/onBoarding/6.dart @@ -17,8 +17,7 @@ import 'package:gecko/widgets/commons/top_appbar.dart'; import 'package:provider/provider.dart'; class OnboardingStepSix extends StatelessWidget { - OnboardingStepSix( - {super.key, required this.skipIntro, required this.generatedMnemonic}); + OnboardingStepSix({super.key, required this.skipIntro, required this.generatedMnemonic}); final bool skipIntro; String? generatedMnemonic; @@ -27,8 +26,7 @@ class OnboardingStepSix extends StatelessWidget { @override Widget build(BuildContext context) { - final generateWalletProvider = - Provider.of<GenerateWalletsProvider>(context, listen: true); + final generateWalletProvider = Provider.of<GenerateWalletsProvider>(context, listen: true); _mnemonicController.text = generatedMnemonic!; @@ -49,19 +47,11 @@ class OnboardingStepSix extends StatelessWidget { ScaledSizedBox(height: isTall ? 25 : 5), const BuildProgressBar(pagePosition: 5), ScaledSizedBox(height: isTall ? 25 : 5), - BuildText( - text: "didYouNoteMnemonicToBeSureTypeWord".tr(args: [ - (generateWalletProvider.nbrWord + 1).toString() - ]), - isMd: true), + BuildText(text: "didYouNoteMnemonicToBeSureTypeWord".tr(args: [(generateWalletProvider.nbrWord + 1).toString()]), isMd: true), ScaledSizedBox(height: isTall ? 40 : 5), if (isTall) Text('${generateWalletProvider.nbrWord + 1}', - key: keyAskedWord, - style: scaledTextStyle( - fontSize: 19, - color: orangeC, - fontWeight: FontWeight.w500)), + key: keyAskedWord, style: scaledTextStyle(fontSize: 19, color: orangeC, fontWeight: FontWeight.w500)), if (isTall) ScaledSizedBox(height: 5), Container( decoration: BoxDecoration( @@ -78,16 +68,12 @@ class OnboardingStepSix extends StatelessWidget { controller: wordController, textInputAction: TextInputAction.next, onChanged: (value) { - generateWalletProvider.checkAskedWord( - value, _mnemonicController.text); + generateWalletProvider.checkAskedWord(value, _mnemonicController.text); }, maxLines: 1, textAlign: TextAlign.center, decoration: InputDecoration( - labelStyle: scaledTextStyle( - fontSize: 18, - color: Colors.grey[500], - fontWeight: FontWeight.w500), + labelStyle: scaledTextStyle(fontSize: 18, color: Colors.grey[500], fontWeight: FontWeight.w500), labelText: generateWalletProvider.isAskedWordValid ? "itsTheGoodWord".tr() : "${generateWalletProvider.nbrWordAlpha} ${"nthMnemonicWord".tr()}", @@ -95,22 +81,13 @@ class OnboardingStepSix extends StatelessWidget { filled: true, contentPadding: const EdgeInsets.all(10), ), - style: scaledTextStyle( - fontSize: 25, - color: generateWalletProvider.askedWordColor, - fontWeight: FontWeight.w500))), + style: scaledTextStyle(fontSize: 25, color: generateWalletProvider.askedWordColor, fontWeight: FontWeight.w500))), Visibility( visible: generateWalletProvider.isAskedWordValid, child: Expanded( child: Align( alignment: Alignment.bottomCenter, - child: nextButton( - context, - 'continue'.tr(), - skipIntro - ? const OnboardingStepNine() - : const OnboardingStepSeven(), - false), + child: nextButton(context, 'continue'.tr(), skipIntro ? const OnboardingStepNine() : const OnboardingStepSeven(), false), ), ), ), @@ -135,8 +112,7 @@ class OnboardingStepSix extends StatelessWidget { } Widget nextButton(BuildContext context, String text, nextScreen, bool isFast) { - final generateWalletProvider = - Provider.of<GenerateWalletsProvider>(context, listen: false); + final generateWalletProvider = Provider.of<GenerateWalletsProvider>(context, listen: false); generateWalletProvider.isAskedWordValid = false; generateWalletProvider.askedWordColor = Colors.black; @@ -148,17 +124,24 @@ Widget nextButton(BuildContext context, String text, nextScreen, bool isFast) { key: keyGoNext, style: ElevatedButton.styleFrom( foregroundColor: Colors.white, - elevation: 4, backgroundColor: orangeC, + elevation: 2, + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: orangeC.withValues(alpha: 0.3), ), onPressed: () { - Navigator.push( - context, FaderTransition(page: nextScreen, isFast: isFast)); + Navigator.push(context, FaderTransition(page: nextScreen, isFast: isFast)); }, child: Text( text, style: scaledTextStyle( - fontSize: 21, fontWeight: FontWeight.w600, color: Colors.white), + fontSize: 18, + fontWeight: FontWeight.w600, + color: Colors.white, + ), ), ), ); diff --git a/lib/screens/qrcode_fullscreen.dart b/lib/screens/qrcode_fullscreen.dart index 77e82b3d9580480e03b0f775c07ab0b3ec9f0bc4..bc116e6935d79512eaa8abb954982fbcdcae7453 100644 --- a/lib/screens/qrcode_fullscreen.dart +++ b/lib/screens/qrcode_fullscreen.dart @@ -1,5 +1,6 @@ // ignore_for_file: must_be_immutable +import 'package:easy_localization/easy_localization.dart'; import 'package:gecko/globals.dart'; import 'package:flutter/material.dart'; import 'package:gecko/models/scale_functions.dart'; @@ -76,7 +77,33 @@ class _QrCodeFullscreenState extends State<QrCodeFullscreen> { version: QrVersions.auto, size: scaleSize(320), ), - const Spacer(flex: 2), + const Spacer(), + ScaledSizedBox( + width: 240, + height: 55, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: orangeC, + side: const BorderSide(color: orangeC, width: 1), + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + 'close'.tr(), + style: scaledTextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + color: orangeC, + ), + ), + ), + ), + const Spacer(), ], )), ), diff --git a/lib/screens/search.dart b/lib/screens/search.dart index b046a1cd1faef853f2300cd96678220773a99dff..90123b62310906a83a280ddb692e9b90530b6691 100644 --- a/lib/screens/search.dart +++ b/lib/screens/search.dart @@ -122,40 +122,65 @@ class _SearchScreenState extends State<SearchScreen> { ScaledSizedBox( width: 270, height: 70, - child: ElevatedButton( - key: keyConfirmSearch, - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - elevation: 4, - backgroundColor: orangeC, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25), + boxShadow: canValidate || searchProvider.canPasteAddress + ? [ + BoxShadow( + color: orangeC.withValues(alpha: 0.3), + blurRadius: 12, + offset: const Offset(0, 6), + spreadRadius: -2, + ), + BoxShadow( + color: orangeC.withValues(alpha: 0.2), + blurRadius: 4, + offset: const Offset(0, 2), + spreadRadius: 0, + ), + ] + : null, ), - onPressed: canValidate - ? () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return const SearchResultScreen(); - }), - ); - } - : searchProvider.canPasteAddress - ? () async { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return WalletViewScreen(address: searchProvider.pastedAddress, username: null); - }), - ); - } - : null, - child: Text( - canValidate - ? 'search'.tr() + child: ElevatedButton( + key: keyConfirmSearch, + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: orangeC, + elevation: 0, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(25), + ), + ), + onPressed: canValidate + ? () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const SearchResultScreen(); + }), + ); + } : searchProvider.canPasteAddress - ? 'pasteAddress'.tr() - : 'search'.tr(), - textAlign: TextAlign.center, - style: scaledTextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white), + ? () async { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return WalletViewScreen(address: searchProvider.pastedAddress, username: null); + }), + ); + } + : null, + child: Text( + canValidate + ? 'search'.tr() + : searchProvider.canPasteAddress + ? 'pasteAddress'.tr() + : 'search'.tr(), + textAlign: TextAlign.center, + style: scaledTextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white), + ), ), ), ), @@ -178,15 +203,21 @@ class _SearchScreenState extends State<SearchScreen> { ), child: Column(children: <Widget>[ Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( shape: BoxShape.circle, boxShadow: [ BoxShadow( - color: Colors.grey, - blurRadius: 1, - offset: Offset(1.5, 1.5), - spreadRadius: 0.2, - ) + color: Colors.black.withValues(alpha: 0.1), + blurRadius: 8, + offset: const Offset(0, 2), + spreadRadius: 0, + ), + BoxShadow( + color: Colors.black.withValues(alpha: 0.05), + blurRadius: 2, + offset: const Offset(0, 1), + spreadRadius: 0, + ), ], ), child: ClipOval( @@ -198,7 +229,6 @@ class _SearchScreenState extends State<SearchScreen> { child: Icon( Icons.contacts_rounded, size: scaleSize(25), - // color: backgroundColor, ), ), ), diff --git a/lib/screens/search_result.dart b/lib/screens/search_result.dart index b5a414a1c66e88805696bce951bacd9d5f4dfd95..cefaba31e7d8b661302b1667e2b63b0408e6cad1 100644 --- a/lib/screens/search_result.dart +++ b/lib/screens/search_result.dart @@ -41,7 +41,7 @@ class SearchResultScreen extends StatelessWidget { ), Text( '"${searchProvider.searchController.text}"', - style: scaledTextStyle(fontStyle: FontStyle.italic, fontSize: 17), + style: scaledTextStyle(fontStyle: FontStyle.italic, fontSize: 16), ) ], ), diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index 324dd4ccb2600429b8b6d76708a0fc9fd3761e78..78dc874f843e33a2b7f868ea8d6faf02cd67b553 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -8,7 +8,6 @@ import 'package:gecko/models/scale_functions.dart'; import 'package:gecko/models/widgets_keys.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/my_wallets.dart'; -import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/screens/activity.dart'; import 'package:gecko/widgets/certify/cert_state.dart'; @@ -65,9 +64,8 @@ class WalletViewScreen extends StatelessWidget { ), ), Consumer<SubstrateSdk>(builder: (context, sub, _) { - WalletData? defaultWallet = myWalletProvider.getDefaultWallet(); return FutureBuilder( - future: sub.certState(defaultWallet.address, address), + future: sub.certState(address), builder: (context, AsyncSnapshot<CertState> snapshot) { if (!snapshot.hasData) return const SizedBox.shrink(); final certState = snapshot.data!; diff --git a/lib/widgets/bottom_app_bar.dart b/lib/widgets/bottom_app_bar.dart index 9abe1496714818eac94faa3220fdde4806adc67f..7a3c3fcfd715b881dc3677eadc2664a72d4b4e45 100644 --- a/lib/widgets/bottom_app_bar.dart +++ b/lib/widgets/bottom_app_bar.dart @@ -1,6 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'dart:io'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/scale_functions.dart'; @@ -72,9 +71,11 @@ class GeckoBottomAppBar extends StatelessWidget { : () async { if (!await myWalletProvider.askPinCode()) return; - Navigator.popUntil(context, ModalRoute.withName('/')); - sleep(const Duration(milliseconds: 300)); - Navigator.pushNamed(context, '/mywallets'); + Navigator.pushNamedAndRemoveUntil( + context, + '/mywallets', + ModalRoute.withName('/'), + ); }, ), ], diff --git a/lib/widgets/buttons/chest_options_buttons.dart b/lib/widgets/buttons/chest_options_buttons.dart index 668b30cd65f5fc78a57348fcaa90ec718faad7e3..89c697f1c4f9b32b60f0d65a5d23b63c58fd5fad 100644 --- a/lib/widgets/buttons/chest_options_buttons.dart +++ b/lib/widgets/buttons/chest_options_buttons.dart @@ -26,8 +26,13 @@ class ChestOptionsButtons extends StatelessWidget { ), style: ElevatedButton.styleFrom( foregroundColor: Colors.black, - elevation: 2, backgroundColor: floattingYellow, + elevation: 2, + padding: const EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: floattingYellow.withValues(alpha: 0.3), ), onPressed: () => Navigator.push( context, @@ -64,14 +69,9 @@ class ChestOptionsButtons extends StatelessWidget { height: scaleSize(40), ), ScaledSizedBox( - width: 275, + width: 230, height: 60, - child: Center( - child: Text('importG1v1'.tr(), - style: scaledTextStyle( - fontSize: 16, - color: Colors.blue[900], - fontWeight: FontWeight.w500))), + child: Center(child: Text('importG1v1'.tr(), style: scaledTextStyle(fontSize: 16, color: Colors.blue[900], fontWeight: FontWeight.w500))), ), ], ), diff --git a/lib/widgets/certify/certify_button.dart b/lib/widgets/certify/certify_button.dart index a47933db5b442c245c75d8599304556def870ecd..c0a77b1501e79f243f2f049e967457069849712c 100644 --- a/lib/widgets/certify/certify_button.dart +++ b/lib/widgets/certify/certify_button.dart @@ -24,9 +24,7 @@ class CertifyButton extends StatelessWidget { Widget build(BuildContext context) { final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false); final sub = Provider.of<SubstrateSdk>(context, listen: false); - final myWalletProvider = - Provider.of<MyWalletsProvider>(context, listen: false); - final defaultWallet = myWalletProvider.getDefaultWallet(); + final myWalletProvider = Provider.of<MyWalletsProvider>(context, listen: false); return Column( children: <Widget>[ @@ -42,20 +40,21 @@ class CertifyButton extends StatelessWidget { final result = await confirmPopupCertification( context, 'areYouSureYouWantToCertify1'.tr(), - duniterIndexer.walletNameIndexer[address] ?? - "noIdentity".tr(), + duniterIndexer.walletNameIndexer[address] ?? "noIdentity".tr(), 'areYouSureYouWantToCertify2'.tr(), getShortPubkey(address), ) ?? false; if (!result) return; + await sub.setCurrentWallet(myWalletProvider.idtyWallet!); + if (myWalletProvider.pinCode == '') { await Navigator.push( context, MaterialPageRoute( builder: (homeContext) { - return UnlockingWallet(wallet: defaultWallet); + return UnlockingWallet(wallet: myWalletProvider.idtyWallet!); }, ), ); @@ -63,10 +62,8 @@ class CertifyButton extends StatelessWidget { if (myWalletProvider.pinCode == '') { return; } - WalletsProfilesProvider walletViewProvider = - Provider.of<WalletsProfilesProvider>(context, - listen: false); - final acc = sub.getCurrentWallet(); + WalletsProfilesProvider walletViewProvider = Provider.of<WalletsProfilesProvider>(context, listen: false); + final acc = sub.getCurrentKeyPair(); final transactionId = await sub.certify( acc.address!, walletViewProvider.address, @@ -94,8 +91,7 @@ class CertifyButton extends StatelessWidget { Text( "certify".tr(), textAlign: TextAlign.center, - style: scaledTextStyle( - fontSize: buttonFontSize, fontWeight: FontWeight.w500), + style: scaledTextStyle(fontSize: buttonFontSize, fontWeight: FontWeight.w500), ), ], ); diff --git a/lib/widgets/commons/next_button.dart b/lib/widgets/commons/next_button.dart index 5c213d3d63f73893cc2efbf948dd96baaa460f1a..1a5367a91f8437452cd50830d9f4f13f731515c7 100644 --- a/lib/widgets/commons/next_button.dart +++ b/lib/widgets/commons/next_button.dart @@ -26,16 +26,23 @@ class NextButton extends StatelessWidget { style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: orangeC, - elevation: 4, + elevation: 2, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + shadowColor: orangeC.withValues(alpha: 0.3), ), onPressed: () { - Navigator.push( - context, FaderTransition(page: nextScreen, isFast: isFast)); + Navigator.push(context, FaderTransition(page: nextScreen, isFast: isFast)); }, child: Text( text, style: scaledTextStyle( - fontSize: 22, fontWeight: FontWeight.w600, color: Colors.white), + fontSize: 22, + fontWeight: FontWeight.w600, + color: Colors.white, + ), ), ), ); diff --git a/lib/widgets/contacts_list.dart b/lib/widgets/contacts_list.dart index 8f5ee1a6f7fc43e8af21d12f626075b8a8660808..ce1df8860fdda72aa139f3a6adfde0d8510a6e98 100644 --- a/lib/widgets/contacts_list.dart +++ b/lib/widgets/contacts_list.dart @@ -22,6 +22,49 @@ class ContactsList extends StatelessWidget { final List<G1WalletsList> myContacts; + void _showContactMenu(BuildContext context, G1WalletsList contact) { + final walletsProfilesClass = Provider.of<WalletsProfilesProvider>(context, listen: false); + + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (BuildContext context) { + return Container( + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.symmetric(vertical: 12), + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey[600], + borderRadius: BorderRadius.circular(2), + ), + ), + ListTile( + leading: const Icon(Icons.delete_outline, color: Colors.red), + title: Text( + 'removeContact'.tr(), + style: const TextStyle(color: Colors.red), + ), + onTap: () { + Navigator.pop(context); + walletsProfilesClass.addContact(contact); + }, + ), + const SizedBox(height: 20), + ], + ), + ); + }, + ); + } + @override Widget build(BuildContext context) { final walletsProfilesClass = Provider.of<WalletsProfilesProvider>(context, listen: false); @@ -47,20 +90,21 @@ class ContactsList extends StatelessWidget { leading: DatapodAvatar(address: g1Wallet.address, size: 47), title: Row(children: <Widget>[ Text(getShortPubkey(g1Wallet.address), - style: scaledTextStyle(fontSize: 15, fontFamily: 'Monospace', fontWeight: FontWeight.w500), textAlign: TextAlign.center), + style: scaledTextStyle(fontSize: 14, fontFamily: 'Monospace', fontWeight: FontWeight.w500), textAlign: TextAlign.center), ]), trailing: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ ScaledSizedBox( width: 110, child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [ Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - Balance(address: g1Wallet.address, size: scaleSize(14)), + Balance(address: g1Wallet.address, size: scaleSize(13)), ]), ]), ), ]), - subtitle: Row(children: <Widget>[NameByAddress(size: scaleSize(15), wallet: WalletData(address: g1Wallet.address))]), + subtitle: Row(children: <Widget>[NameByAddress(size: scaleSize(14), wallet: WalletData(address: g1Wallet.address))]), isThreeLine: false, + onLongPress: () => _showContactMenu(context, g1Wallet), onTap: () { Navigator.push( context, diff --git a/lib/widgets/drag_tule_action.dart b/lib/widgets/drag_tule_action.dart index fe7c8d10201b6b8aad966d27af6401abbd2244bd..5fc1e07c87b48d90b8e92f002839b97def69c124 100644 --- a/lib/widgets/drag_tule_action.dart +++ b/lib/widgets/drag_tule_action.dart @@ -22,8 +22,7 @@ class DragTuleAction extends StatelessWidget { return LongPressDraggable<String>( delay: const Duration(milliseconds: 200), data: wallet.address, - dragAnchorStrategy: (Draggable<Object> _, BuildContext __, Offset ___) => - const Offset(55, 55), + dragAnchorStrategy: (Draggable<Object> _, BuildContext __, Offset ___) => const Offset(55, 55), onDragStarted: () => myWalletProvider.dragAddress = wallet, onDragEnd: (_) { myWalletProvider.lastFlyBy = null; @@ -44,12 +43,10 @@ class DragTuleAction extends StatelessWidget { ), child: DragTarget<String>( onAcceptWithDetails: (senderAddress) async { - final walletData = - myWalletProvider.getWalletDataByAddress(senderAddress.data); + final walletData = myWalletProvider.getWalletDataByAddress(senderAddress.data); await sub.setCurrentWallet(walletData!); sub.reload(); - paymentPopup(context, wallet.address, - g1WalletsBox.get(wallet.address)!.username ?? wallet.name!); + paymentPopup(context, wallet.address, g1WalletsBox.get(wallet.address)!.username ?? wallet.name!); }, onMove: (details) { if (wallet.address != myWalletProvider.lastFlyBy?.address) { @@ -57,14 +54,15 @@ class DragTuleAction extends StatelessWidget { myWalletProvider.reload(); } }, - onWillAcceptWithDetails: (senderAddress) => - senderAddress.data != wallet.address, + onWillAcceptWithDetails: (senderAddress) => senderAddress.data != wallet.address, builder: ( BuildContext context, List<dynamic> accepted, List<dynamic> rejected, ) { - return child; + return IntrinsicHeight( + child: child, + ); }), ); } diff --git a/lib/widgets/payment_popup.dart b/lib/widgets/payment_popup.dart index 1783cfbc2b7ca86e2d4d495619666a0361e58471..ff363a6303aa03c368a170f84b2d18ceee9d69e8 100644 --- a/lib/widgets/payment_popup.dart +++ b/lib/widgets/payment_popup.dart @@ -46,7 +46,7 @@ void paymentPopup(BuildContext context, String toAddress, String? username) { // Payment workflow ! final sub = Provider.of<SubstrateSdk>(context, listen: false); - final acc = sub.getCurrentWallet(); + final acc = sub.getCurrentKeyPair(); final transactionId = const Uuid().v4(); diff --git a/lib/widgets/search_identity_query.dart b/lib/widgets/search_identity_query.dart index 05a6cb2b7af19626d856f4cb8b235edb29793726..36a0796aa2fe2cf54411d859c530826bf62baf7d 100644 --- a/lib/widgets/search_identity_query.dart +++ b/lib/widgets/search_identity_query.dart @@ -74,18 +74,18 @@ class SearchIdentityQuery extends StatelessWidget { leading: DatapodAvatar(address: profile['node']['accountId'], size: avatarSize), title: Row(children: <Widget>[ Text(getShortPubkey(profile['node']['accountId']), - style: scaledTextStyle(fontSize: 15, fontFamily: 'Monospace', fontWeight: FontWeight.w500), textAlign: TextAlign.center), + style: scaledTextStyle(fontSize: 14, fontFamily: 'Monospace', fontWeight: FontWeight.w500), textAlign: TextAlign.center), ]), trailing: ScaledSizedBox( width: 120, child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [ Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - Balance(address: profile['node']['accountId'], size: 15), + Balance(address: profile['node']['accountId'], size: 14), ]), ]), ), subtitle: Row(children: <Widget>[ - Text(profile['node']['name'] ?? '', style: scaledTextStyle(fontSize: 16, fontWeight: FontWeight.w500), textAlign: TextAlign.center), + Text(profile['node']['name'] ?? '', style: scaledTextStyle(fontSize: 14, fontWeight: FontWeight.w500), textAlign: TextAlign.center), ]), dense: !isTall, isThreeLine: false, diff --git a/lib/widgets/search_result_list.dart b/lib/widgets/search_result_list.dart index f38f9e06f8ac371a5a8788af2f384eadad405e28..752e118c993ccd67235147c9eb0d6a1002ae5692 100644 --- a/lib/widgets/search_result_list.dart +++ b/lib/widgets/search_result_list.dart @@ -35,13 +35,11 @@ class SearchResult extends StatelessWidget { builder: (context, AsyncSnapshot<List?> snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.data?.isEmpty ?? true) { - return SearchIdentityQuery( - name: searchProvider.searchController.text); + return SearchIdentityQuery(name: searchProvider.searchController.text); } else { return Expanded( child: ListView(children: <Widget>[ - for (G1WalletsList g1Wallet in snapshot.data ?? []) - resultTileAddressSearch(g1Wallet, context), + for (G1WalletsList g1Wallet in snapshot.data ?? []) resultTileAddressSearch(g1Wallet, context), ]), ); } @@ -64,19 +62,14 @@ class SearchResult extends StatelessWidget { leading: DatapodAvatar(address: g1Wallet.address, size: avatarSize), title: Row(children: <Widget>[ Text(getShortPubkey(g1Wallet.address), - style: scaledTextStyle( - fontSize: 17, - fontFamily: 'Monospace', - fontWeight: FontWeight.w500), - textAlign: TextAlign.center), + style: scaledTextStyle(fontSize: 14, fontFamily: 'Monospace', fontWeight: FontWeight.w500), textAlign: TextAlign.center), ]), - trailing: - Column(mainAxisAlignment: MainAxisAlignment.center, children: [ + trailing: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ ScaledSizedBox( width: 110, child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [ Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - Balance(address: g1Wallet.address, size: 15), + Balance(address: g1Wallet.address, size: 14), ]), ]), ), @@ -84,6 +77,7 @@ class SearchResult extends StatelessWidget { subtitle: Row(children: <Widget>[ NameByAddress( wallet: WalletData(address: g1Wallet.address), + size: 14, ), ]), dense: false, diff --git a/lib/widgets/wallet_header.dart b/lib/widgets/wallet_header.dart index 9f600235e67b1b0863853c22fa69ee2c4c305351..5e301cea243ce5f1f17250447a186334ebbf3188 100644 --- a/lib/widgets/wallet_header.dart +++ b/lib/widgets/wallet_header.dart @@ -42,44 +42,39 @@ class WalletHeader extends StatelessWidget { vertical: scaleSize(16), ), child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ // Avatar section - Stack( - alignment: Alignment.center, - children: [ - Container( - width: scaleSize(90), - height: scaleSize(90), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.1), - blurRadius: 10, - offset: const Offset(0, 2), - ), - ], + Container( + width: scaleSize(90), + height: scaleSize(90), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.1), + blurRadius: 10, + offset: const Offset(0, 2), ), - child: ClipOval( - child: customImagePath == null || customImagePath == '' - ? (defaultImagePath != null - ? Image.asset( - 'assets/avatars/$defaultImagePath', - fit: BoxFit.cover, - ) - : DatapodAvatar( - address: address, - size: avatarSize, - )) - : Image.file( - File(customImagePath!), + ], + ), + child: ClipOval( + child: customImagePath == null || customImagePath == '' + ? (defaultImagePath != null + ? Image.asset( + 'assets/avatars/$defaultImagePath', fit: BoxFit.cover, - ), - ), - ), - ], + ) + : DatapodAvatar( + address: address, + size: avatarSize, + )) + : Image.file( + File(customImagePath!), + fit: BoxFit.cover, + ), + ), ), SizedBox(width: scaleSize(20)), diff --git a/lib/widgets/wallet_tile.dart b/lib/widgets/wallet_tile.dart index ab7ff3e9693e5a910f574285ab98ec556861e6c4..c6fab84f5a4677e4ac447c1cc7b7f319fddf2aab 100644 --- a/lib/widgets/wallet_tile.dart +++ b/lib/widgets/wallet_tile.dart @@ -39,7 +39,7 @@ class WalletTile extends StatelessWidget { ); }, child: ScaledSizedBox( - key: repository.number == 1 ? keyDragAndDrop : const Key('nothing'), + // key: repository.number == 1 ? keyDragAndDrop : const Key('nothing'), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), diff --git a/lib/widgets/wallet_tile_membre.dart b/lib/widgets/wallet_tile_membre.dart index ca90ff2c272b2484cef92bf3ea26a834d4ae2496..5ebbda9582b3f78b17bbe6526186b3b28d14f353 100644 --- a/lib/widgets/wallet_tile_membre.dart +++ b/lib/widgets/wallet_tile_membre.dart @@ -14,30 +14,30 @@ import 'package:gecko/widgets/name_by_address.dart'; import 'package:provider/provider.dart'; class WalletTileMembre extends StatelessWidget { - const WalletTileMembre({super.key, required this.repository}); + const WalletTileMembre({super.key, required this.wallet}); - final WalletData repository; + final WalletData wallet; @override Widget build(BuildContext context) { - repository.getDatapodAvatar(); + wallet.getDatapodAvatar(); return Padding( padding: EdgeInsets.symmetric(horizontal: scaleSize(52), vertical: scaleSize(15)), child: GestureDetector( - key: keyOpenWallet(repository.address), + key: keyOpenWallet(wallet.address), onTap: () { Navigator.push( context, SmoothTransition( page: WalletOptions( - wallet: repository, + wallet: wallet, ), ), ); }, child: ScaledSizedBox( - key: repository.number == 1 ? keyDragAndDrop : const Key('nothing'), + // key: wallet.number == 1 ? keyDragAndDrop : const Key('nothing'), height: 180, child: Container( decoration: BoxDecoration( @@ -75,11 +75,11 @@ class WalletTileMembre extends StatelessWidget { ], ), ), - child: repository.imageCustomPath == null || repository.imageCustomPath == '' + child: wallet.imageCustomPath == null || wallet.imageCustomPath == '' ? Padding( padding: EdgeInsets.all(scaleSize(16)), child: Image.asset( - 'assets/avatars/${repository.imageDefaultPath}', + 'assets/avatars/${wallet.imageDefaultPath}', alignment: Alignment.bottomCenter, ), ) @@ -90,7 +90,7 @@ class WalletTileMembre extends StatelessWidget { image: DecorationImage( fit: BoxFit.cover, image: FileImage( - File(repository.imageCustomPath!), + File(wallet.imageCustomPath!), ), ), ), @@ -129,21 +129,21 @@ class WalletTileMembre extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ NameByAddress( - wallet: repository, + wallet: wallet, size: 16, color: isDefault ? Colors.white : Colors.black87, fontWeight: FontWeight.w600, ), ScaledSizedBox(height: 4), Balance( - address: repository.address, + address: wallet.address, size: 14, color: isDefault ? Colors.white : Colors.black87, ), ], ), Certifications( - address: repository.address, + address: wallet.address, color: isDefault ? Colors.white : Colors.black87, size: 15, ), @@ -158,5 +158,5 @@ class WalletTileMembre extends StatelessWidget { ); } - bool get isDefault => repository.address == Provider.of<MyWalletsProvider>(homeContext, listen: false).getDefaultWallet().address; + bool get isDefault => wallet.address == Provider.of<MyWalletsProvider>(homeContext, listen: false).getDefaultWallet().address; } diff --git a/pubspec.yaml b/pubspec.yaml index 39a29733ff6c3921656374d7ffc65395aedf8300..4b039d05b17c2885c981c600c4f5bc0d71c0e612 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: gecko description: Pay with G1. publish_to: "none" -version: 0.1.19+91 +version: 0.1.20+92 environment: sdk: ^3.5.3