diff --git a/assets/translations/en.json b/assets/translations/en.json index 2d1f4f1..7ef8e91 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -168,5 +168,11 @@ "cancel": "Cancel", "inBlockchainResult": "In {} blockchain", "search": "Search", - "currencyNode": "{} node :" + "currencyNode": "{} node :", + "contactsManagementWithNbr": "My contacts ({})", + "contactsManagement": "My contacts", + "noContacts": "You don't have any contact", + "addContact": "Add\nto contacts", + "removeContact": "Remove\nthis contact" + } \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index a7299ec..cf765b5 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -168,5 +168,10 @@ "cancel": "Cancel", "inBlockchainResult": "In {} blockchain", "search": "Search", - "currencyNode": "{} node :" + "currencyNode": "{} node :", + "contactsManagementWithNbr": "My contacts ({})", + "contactsManagement": "My contacts", + "noContacts": "You don't have any contact", + "addContact": "Add\nto contacts", + "removeContact": "Remove\nthis contact" } \ No newline at end of file diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 963e071..5d6e0d3 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -169,5 +169,11 @@ "cancel": "Annuler", "inBlockchainResult": "Dans la blockchain {}", "search": "Rechercher", - "currencyNode": "Noeud {} :" + "currencyNode": "Noeud {} :", + "contactsManagementWithNbr": "Mes contacts ({})", + "contactsManagement": "Mes contacts", + "noContacts": "Vous n'avez aucun contact", + "addContact": "Ajouter\naux contacts", + "removeContact": "Supprimer\nce contact" + } \ No newline at end of file diff --git a/lib/globals.dart b/lib/globals.dart index 991afe7..dff45e6 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -22,6 +22,7 @@ late Box walletBox; late Box chestBox; late Box configBox; late Box g1WalletsBox; +late Box contactsBox; // late Box keystoreBox; late Directory imageDirectory; diff --git a/lib/main.dart b/lib/main.dart index 1c4362b..c0fd1f1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -73,6 +73,7 @@ Future main() async { configBox = await Hive.openBox("configBox"); await Hive.deleteBoxFromDisk('g1WalletsBox'); g1WalletsBox = await Hive.openBox("g1WalletsBox"); + contactsBox = await Hive.openBox("contactsBox"); await homeProvider.getValidEndpoints(); // await configBox.delete('isCacheChecked'); diff --git a/lib/providers/wallets_profiles.dart b/lib/providers/wallets_profiles.dart index 97226f4..0acf9ab 100644 --- a/lib/providers/wallets_profiles.dart +++ b/lib/providers/wallets_profiles.dart @@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; +import 'package:gecko/models/g1_wallets_list.dart'; import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallet_options.dart'; @@ -224,6 +225,20 @@ class WalletsProfilesProvider with ChangeNotifier { ]); } + bool isContact(String address) { + return contactsBox.containsKey(address); + } + + void addContact(G1WalletsList profile) { + log.d(profile.username); + if (isContact(profile.pubkey!)) { + contactsBox.delete(profile.pubkey); + } else { + contactsBox.put(profile.pubkey, profile); + } + notifyListeners(); + } + void reload() { notifyListeners(); } diff --git a/lib/screens/home.dart b/lib/screens/home.dart index c4d3c43..4157045 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -23,6 +23,7 @@ import 'package:gecko/screens/search.dart'; import 'package:gecko/screens/settings.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; +import 'package:gecko/screens/my_contacts.dart'; class HomeScreen extends StatelessWidget { const HomeScreen({Key? key}) : super(key: key); @@ -75,6 +76,20 @@ class HomeScreen extends StatelessWidget { ); }, ), + ListTile( + key: const Key('contacts'), + title: Text('contactsManagement'.tr()), + onTap: () { + Navigator.pop(context); + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const ContactsScreen(); + }), + ); + }, + ), + // ListTile( // key: const Key('substrateSandbox'), // title: const Text('Substrate debug'), diff --git a/lib/screens/my_contacts.dart b/lib/screens/my_contacts.dart new file mode 100644 index 0000000..939513d --- /dev/null +++ b/lib/screens/my_contacts.dart @@ -0,0 +1,123 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/services.dart'; +import 'package:gecko/globals.dart'; +import 'package:flutter/material.dart'; +import 'package:gecko/providers/cesium_plus.dart'; +import 'package:gecko/models/g1_wallets_list.dart'; +import 'package:gecko/providers/duniter_indexer.dart'; +import 'package:gecko/providers/home.dart'; +import 'package:gecko/providers/substrate_sdk.dart'; +import 'package:gecko/providers/wallet_options.dart'; +import 'package:gecko/providers/wallets_profiles.dart'; +import 'package:gecko/screens/common_elements.dart'; +import 'package:gecko/screens/wallet_view.dart'; +import 'package:provider/provider.dart'; + +class ContactsScreen extends StatelessWidget { + const ContactsScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + CesiumPlusProvider cesiumPlusProvider = + Provider.of(context, listen: false); + WalletsProfilesProvider walletsProfilesClass = + Provider.of(context, listen: false); + HomeProvider homeProvider = + Provider.of(context, listen: false); + DuniterIndexer duniterIndexer = + Provider.of(context, listen: false); + + int keyID = 0; + double avatarSize = 55; + + final myContacts = contactsBox.toMap().values.toList(); + // myContacts.sort((a, b) { + // final aa = a.username?.toLowerCase() ?? ''; + // final bb = b.username?.toLowerCase() ?? ''; + // return aa.compareTo(bb); + // }); + + return Scaffold( + backgroundColor: backgroundColor, + appBar: AppBar( + elevation: 1, + toolbarHeight: 60 * ratio, + title: SizedBox( + height: 22, + child: Text( + 'contactsManagementWithNbr'.tr(args: ['${myContacts.length}'])), + ), + ), + bottomNavigationBar: homeProvider.bottomAppBar(context), + body: SafeArea( + child: Stack(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + if (myContacts.isEmpty) + Text('noContacts'.tr()) + else + Expanded( + child: ListView(children: [ + for (G1WalletsList g1Wallet in myContacts) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: ListTile( + key: Key('searchResult${keyID++}'), + horizontalTitleGap: 40, + contentPadding: const EdgeInsets.all(5), + leading: cesiumPlusProvider + .defaultAvatar(avatarSize), + title: Row(children: [ + Text(getShortPubkey(g1Wallet.pubkey!), + style: const TextStyle( + fontSize: 18, + fontFamily: 'Monospace', + fontWeight: FontWeight.w500), + textAlign: TextAlign.center), + ]), + trailing: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + balance(context, g1Wallet.pubkey!, 16) + ]), + subtitle: Row(children: [ + duniterIndexer.getNameByAddress( + context, g1Wallet.pubkey!) + ]), + dense: false, + isThreeLine: false, + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + walletsProfilesClass.address = + g1Wallet.pubkey; + return WalletViewScreen( + pubkey: g1Wallet.pubkey, + username: g1WalletsBox + .get(g1Wallet.pubkey) + ?.id + ?.username, + avatar: g1WalletsBox + .get(g1Wallet.pubkey) + ?.avatar, + ); + }), + ); + }), + ), + ]), + ) + ]), + ), + CommonElements().offlineInfo(context), + ]), + ), + ); + } +} diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index 7d2c5cb..33463f2 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; import 'package:flutter/material.dart'; +import 'package:gecko/models/g1_wallets_list.dart'; import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/home.dart'; import 'package:gecko/providers/substrate_sdk.dart'; @@ -54,23 +55,44 @@ class WalletViewScreen extends StatelessWidget { elevation: 0, toolbarHeight: 60 * ratio, actions: [ - InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return QrCodeFullscreen( - walletProfile.address!, + Row( + children: [ + Consumer( + builder: (context, walletProfile, _) { + return IconButton( + onPressed: () { + final newContact = + G1WalletsList(pubkey: pubkey!, username: username); + walletProfile.addContact(newContact); + }, + icon: Icon( + walletProfile.isContact(pubkey!) + ? Icons.add_reaction_rounded + : Icons.add_reaction_outlined, + size: 35, + ), + ); + }), + const SizedBox(width: 10), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return QrCodeFullscreen( + walletProfile.address!, + ); + }), ); - }), - ); - }, - child: QrImageWidget( - data: walletProfile.address!, - version: QrVersions.auto, - size: 80, - ), - ), + }, + child: QrImageWidget( + data: walletProfile.address!, + version: QrVersions.auto, + size: 80, + ), + ), + ], + ) ], title: SizedBox( height: 22,