From 225d2b342bf929d60acf10270cea7897e6db1477 Mon Sep 17 00:00:00 2001 From: poka Date: Sat, 9 Dec 2023 21:00:45 +0100 Subject: [PATCH] feat: welcome back Cs+ avatars (disabled) feat: add methode to store cs+ avatar (disabled due to sr25519 cryptotype) --- lib/globals.dart | 4 +- lib/models/g1_wallets_list.dart | 9 +- lib/models/g1_wallets_list.g.dart | 15 +- lib/providers/cesium_plus.dart | 314 ++++++++++++++-------- lib/providers/substrate_sdk.dart | 60 ++++- lib/screens/activity.dart | 3 +- lib/screens/home.dart | 4 + lib/screens/myWallets/wallet_options.dart | 14 +- lib/screens/my_contacts.dart | 3 +- lib/screens/wallet_view.dart | 8 +- lib/widgets/cesium_avatar.dart | 37 +++ lib/widgets/commons/loading.dart | 25 ++ lib/widgets/contacts_list.dart | 18 +- lib/widgets/header_profile.dart | 8 +- lib/widgets/search_identity_query.dart | 7 +- lib/widgets/search_result_list.dart | 5 +- pubspec.lock | 26 +- pubspec.yaml | 2 + 18 files changed, 382 insertions(+), 180 deletions(-) create mode 100644 lib/widgets/cesium_avatar.dart create mode 100644 lib/widgets/commons/loading.dart diff --git a/lib/globals.dart b/lib/globals.dart index ac34913..641c106 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -23,8 +23,8 @@ late Box contactsBox; // late Box keystoreBox; late Directory imageDirectory; -// String cesiumPod = "https://g1.data.le-sou.org"; -String cesiumPod = "https://g1.data.presles.fr"; +String cesiumPod = "https://g1.data.le-sou.org"; +// String cesiumPod = "https://g1.data.presles.fr"; // String cesiumPod = "https://g1.data.e-is.pro"; // Responsive ratios diff --git a/lib/models/g1_wallets_list.dart b/lib/models/g1_wallets_list.dart index 3fce1b3..3fe0695 100644 --- a/lib/models/g1_wallets_list.dart +++ b/lib/models/g1_wallets_list.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; part 'g1_wallets_list.g.dart'; @@ -15,22 +14,18 @@ class G1WalletsList { Id? id; @HiveField(3) - Image? avatar; - - @HiveField(4) String? username; - @HiveField(5) + @HiveField(4) String? csName; - @HiveField(6) + @HiveField(5) bool? isMembre; G1WalletsList({ required this.address, this.balance, this.id, - this.avatar, this.username, this.csName, this.isMembre, diff --git a/lib/models/g1_wallets_list.g.dart b/lib/models/g1_wallets_list.g.dart index 8b84c23..9a800f8 100644 --- a/lib/models/g1_wallets_list.g.dart +++ b/lib/models/g1_wallets_list.g.dart @@ -20,17 +20,16 @@ class G1WalletsListAdapter extends TypeAdapter { address: fields[0] as String, balance: fields[1] as double?, id: fields[2] as Id?, - avatar: fields[3] as Image?, - username: fields[4] as String?, - csName: fields[5] as String?, - isMembre: fields[6] as bool?, + username: fields[3] as String?, + csName: fields[4] as String?, + isMembre: fields[5] as bool?, ); } @override void write(BinaryWriter writer, G1WalletsList obj) { writer - ..writeByte(7) + ..writeByte(6) ..writeByte(0) ..write(obj.address) ..writeByte(1) @@ -38,12 +37,10 @@ class G1WalletsListAdapter extends TypeAdapter { ..writeByte(2) ..write(obj.id) ..writeByte(3) - ..write(obj.avatar) - ..writeByte(4) ..write(obj.username) - ..writeByte(5) + ..writeByte(4) ..write(obj.csName) - ..writeByte(6) + ..writeByte(5) ..write(obj.isMembre); } diff --git a/lib/providers/cesium_plus.dart b/lib/providers/cesium_plus.dart index bfc630b..d8ddb76 100644 --- a/lib/providers/cesium_plus.dart +++ b/lib/providers/cesium_plus.dart @@ -2,8 +2,13 @@ import 'dart:convert'; import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; +import 'package:gecko/providers/substrate_sdk.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:crypto/crypto.dart'; + // import 'package:http/http.dart' as http; class CesiumPlusProvider with ChangeNotifier { @@ -11,105 +16,186 @@ class CesiumPlusProvider with ChangeNotifier { CancelToken avatarCancelToken = CancelToken(); - Future _buildQuery(pubkey) async { - var queryGetAvatar = json.encode({ - "query": { - "bool": { - "should": [ - { - "match": { - '_id': {"query": pubkey, "boost": 2} - } - }, - { - "prefix": {'_id': pubkey} - } - ] - } - }, - "highlight": { - "fields": {"title": {}, "tags": {}} - }, - "from": 0, - "size": 100, - "_source": [ - "title", - "avatar", - "avatar._content_type", - "description", - "city", - "address", - "socials.url", - "creationTime", - "membersCount", - "type" - ], - "indices_boost": {"user": 100, "page": 1, "group": 0.01} + final Map _headers = { + 'Content-type': 'application/json', + 'Accept': 'application/json', + }; + + // List _buildQueryGetAvatar(String pubkeyV1) { + // final queryGetAvatar = json.encode({ + // "query": { + // "bool": { + // "should": [ + // { + // "match": { + // '_id': {"query": pubkeyV1, "boost": 1} + // } + // }, + // { + // "prefix": {'_id': pubkeyV1} + // } + // ] + // } + // }, + // "_source": [ + // "avatar", + // "avatar._content_type", + // ], + // "indices_boost": {"user": 1, "page": 1, "group": 0.01} + // }); + + // const requestUrl = "/user,page,group/profile,record/_search"; + // final podRequest = cesiumPod + requestUrl; + + // return [podRequest, queryGetAvatar]; + // } + + Future _buildQuerySetAvatar( + String pubkeyV1, String address, String avatar) async { + int timeSent = DateTime.now().millisecondsSinceEpoch ~/ 1000; + final queryGetAvatar = json.encode({ + "avatar": {"_content": avatar, "_content_type": "image/png"}, + "time": timeSent, + "issuer": pubkeyV1, + "version": 2, + "tags": [] }); - String requestUrl = "/user,page,group/profile,record/_search"; - String podRequest = cesiumPod + requestUrl; + final requestUrl = + "/user/profile?pubkey=$pubkeyV1/_update?pubkey=$pubkeyV1"; + final podRequest = cesiumPod + requestUrl; - Map headers = { - 'Content-type': 'application/json', - 'Accept': 'application/json', + final signedDocument = await signDoc(queryGetAvatar, address); + + return [podRequest, signedDocument]; + } + + Future signDoc(String document, String address) async { + final sub = Provider.of(homeContext, listen: false); + final hashDocBytes = utf8.encode(document); + final hashDoc = sha256.convert(hashDocBytes); + final hashDocHex = hashDoc.toString().toUpperCase(); + + // Generate signature of document + final signature = await sub.signCsPlusDocument(hashDocHex, address); + + // Build final document + final Map data = { + 'hash': hashDocHex, + 'signature': signature + }; + final signJSON = jsonEncode(data); + final Map finalJSON = { + ...jsonDecode(signJSON), + ...jsonDecode(document) }; - return [podRequest, queryGetAvatar, headers]; + return jsonEncode(finalJSON); + } + // Future getName(String address) async { + // String? name; + + // if (g1WalletsBox.get(address)?.csName != null) { + // return g1WalletsBox.get(address)!.csName!; + // } + + // List queryOptions = await _buildQueryName(address); + + // var dio = Dio(); + // late Response response; + // try { + // response = await dio.post( + // queryOptions[0], + // data: queryOptions[1], + // options: Options( + // headers: queryOptions[2], + // sendTimeout: const Duration(seconds: 3), + // receiveTimeout: const Duration(seconds: 5), + // ), + // ); + // // response = await http.post((Uri.parse(queryOptions[0])), + // // body: queryOptions[1], headers: queryOptions[2]); + // } catch (e) { + // log.e(e); + // } + + // if (response.data['hits']['hits'].toString() == '[]') { + // return ''; + // } + // final bool nameExist = + // response.data['hits']['hits'][0]['_source'].containsKey("title"); + // if (!nameExist) { + // return ''; + // } + // name = response.data['hits']['hits'][0]['_source']['title']; + + // name ??= ''; + // g1WalletsBox.get(address)!.csName = name; + + // return name; + // } + + Future getAvatar(String address, double size) async { + return defaultAvatar(size); + // final sub = Provider.of(homeContext, listen: false); + // if (await isAvatarExist(address)) { + // return await getAvatarLocal(address, size); + // } + + // final pubkeyV1 = await sub.addressToPubkeyB58(address); + // var dio = Dio(); + + // List queryOptions = _buildQueryGetAvatar(pubkeyV1); + + // late Response response; + // try { + // response = await dio + // .post(queryOptions[0], + // data: queryOptions[1], + // options: Options( + // headers: _headers, + // sendTimeout: const Duration(seconds: 4), + // receiveTimeout: const Duration(seconds: 15), + // ), + // cancelToken: avatarCancelToken) + // .timeout( + // const Duration(seconds: 15), + // ); + // } catch (e) { + // log.e(e); + // } + + // if (response.data['hits']['hits'].toString() == '[]' || + // !response.data['hits']['hits'][0]['_source'].containsKey("avatar")) { + // return defaultAvatar(size); + // } + + // final avatar = + // response.data['hits']['hits'][0]['_source']['avatar']['_content']; + + // final avatarFile = await saveAvatar(address, avatar); + + // final finalAvatar = Image.file( + // avatarFile, + // height: size, + // fit: BoxFit.fitWidth, + // ); + + // return finalAvatar; } - Future getName(String? pubkey) async { - String? name; - - if (g1WalletsBox.get(pubkey)?.csName != null) { - return g1WalletsBox.get(pubkey)!.csName!; - } - - List queryOptions = await _buildQuery(pubkey); + Future setAvatar(String address, String avatarPath) async { + final sub = Provider.of(homeContext, listen: false); + final pubkeyV1 = await sub.addressToPubkeyB58(address); var dio = Dio(); - late Response response; - try { - response = await dio.post( - queryOptions[0], - data: queryOptions[1], - options: Options( - headers: queryOptions[2], - sendTimeout: const Duration(seconds: 3), - receiveTimeout: const Duration(seconds: 5), - ), - ); - // response = await http.post((Uri.parse(queryOptions[0])), - // body: queryOptions[1], headers: queryOptions[2]); - } catch (e) { - log.e(e); - } + final Uint8List avatarBytes = await File(avatarPath).readAsBytes(); + final avatarString = base64Encode(avatarBytes); - if (response.data['hits']['hits'].toString() == '[]') { - return ''; - } - final bool nameExist = - response.data['hits']['hits'][0]['_source'].containsKey("title"); - if (!nameExist) { - return ''; - } - name = response.data['hits']['hits'][0]['_source']['title']; - - name ??= ''; - g1WalletsBox.get(pubkey)!.csName = name; - - return name; - } - - Future getAvatar(String? pubkey, double size) async { - if (g1WalletsBox.get(pubkey)?.avatar != null) { - return g1WalletsBox.get(pubkey)!.avatar; - } - var dio = Dio(); - - // log.d(_pubkey); - - List queryOptions = await _buildQuery(pubkey); + List queryOptions = + await _buildQuerySetAvatar(pubkeyV1, address, avatarString); + log.d(queryOptions[0]); + log.d(jsonDecode(queryOptions[1])); late Response response; try { @@ -117,7 +203,7 @@ class CesiumPlusProvider with ChangeNotifier { .post(queryOptions[0], data: queryOptions[1], options: Options( - headers: queryOptions[2], + headers: _headers, sendTimeout: const Duration(seconds: 4), receiveTimeout: const Duration(seconds: 15), ), @@ -125,33 +211,51 @@ class CesiumPlusProvider with ChangeNotifier { .timeout( const Duration(seconds: 15), ); - // response = await http.post((Uri.parse(queryOptions[0])), - // body: queryOptions[1], headers: queryOptions[2]); + log.d(response.data); + return response.statusCode == 200; } catch (e) { log.e(e); + return false; } + } - if (response.data['hits']['hits'].toString() == '[]' || - !response.data['hits']['hits'][0]['_source'].containsKey("avatar")) { - return defaultAvatar(size); + Future getLocalPath() async { + final directory = await getApplicationDocumentsDirectory(); + return directory.path; + } + + Future saveAvatar(String address, String data) async { + final path = await getLocalPath(); + final avatarFolder = Directory('$path/avatars/'); + if (!await avatarFolder.exists()) { + await avatarFolder.create(); } + final file = File('$path/avatars/$address'); + return await file.writeAsBytes(base64.decode(data)); + } - final avatar = - response.data['hits']['hits'][0]['_source']['avatar']['_content']; - - var avatarFile = - File('${(await getTemporaryDirectory()).path}/avatar_$pubkey.png'); - await avatarFile.writeAsBytes(base64.decode(avatar)); - - final finalAvatar = Image.file( + Future getAvatarLocal(String address, double size) async { + final path = await getLocalPath(); + final avatarFile = File('$path/avatars/$address'); + return Image.file( avatarFile, height: size, fit: BoxFit.fitWidth, ); + } - g1WalletsBox.get(pubkey)!.avatar = finalAvatar; + Future isAvatarExist(String address) async { + final path = await getLocalPath(); + final avatarFile = File('$path/avatars/$address'); + return avatarFile.exists(); + } - return finalAvatar; + Future deleteAvatarFolder() async { + final path = await getLocalPath(); + final avatarFolder = Directory('$path/avatars/'); + if (await avatarFolder.exists()) { + await avatarFolder.delete(recursive: true); + } } } diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 0ff0835..0eb1477 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -136,6 +136,42 @@ class SubstrateSdk with ChangeNotifier { return res?.signature ?? ''; } + Future signCsPlusDocument(String document, String address) async { + final myWallets = + Provider.of(homeContext, listen: false); + final messageToSign = Uint8List.fromList(document.codeUnits); + // final pubkeyV1 = json.decode(document)['issuer']; + // final address = await pubkeyV1ToAddress(pubkeyV1); + // final walletData = myWallets.getWalletDataByAddress(address); + // final derivationPath = + // walletData!.derivation == null ? '' : "//${walletData.derivation}"; + + // final seed = await getSeed(address, myWallets.pinCode); + // final addressEd25519 = await importAccount( + // mnemonic: seed, + // password: 'AAAAA', + // cryptoType: CryptoType.ed25519, + // derivePath: derivationPath); + + // final pubkeyEd25519 = await addressToPubkeyB58(addressEd25519); + + final signatureString = + await _signMessage(messageToSign, address, myWallets.pinCode); + final signatureInt = HEX.decode(signatureString.substring(2)); + final signature64 = base64Encode(signatureInt); + +// await deleteAccounts([addressEd25519]); + +// log.d(""" +// $addressEd25519 +// $pubkeyEd25519 +// $derivationPath +// $signature64 +// """); + + return signature64; + } + //////////////////////////////////////////// ////////// 2: GET ONCHAIN STORAGE ////////// //////////////////////////////////////////// @@ -449,9 +485,16 @@ class SubstrateSdk with ChangeNotifier { return pubkeyByte; } - // Future pubkeyToAddress(String pubkey) async { - // await sdk.api.account.encodeAddress([pubkey]); - // } + Future addressToPubkeyB58(String address) async { + return Base58Encode(await addressToPubkey(address)); + } + + Future pubkeyV1ToAddress(String pubkey) async { + final pubkeyByte = Base58Decode(pubkey); + final String pubkeyHex = '0x${HEX.encode(pubkeyByte)}'; + final address = await sdk.api.account.encodeAddress([pubkeyHex]); + return address!.keys.first; + } Future initCurrencyParameters() async { try { @@ -677,7 +720,8 @@ class SubstrateSdk with ChangeNotifier { Future importAccount( {String mnemonic = '', String derivePath = '', - required String password}) async { + required String password, + CryptoType cryptoType = CryptoType.sr25519}) async { const keytype = KeyType.mnemonic; if (mnemonic != '') generatedMnemonic = mnemonic; @@ -691,7 +735,7 @@ class SubstrateSdk with ChangeNotifier { name: derivePath, password: password, derivePath: derivePath, - cryptoType: CryptoType.sr25519) + cryptoType: cryptoType) .catchError((e) { importIsLoading = false; notifyListeners(); @@ -748,12 +792,6 @@ class SubstrateSdk with ChangeNotifier { return seedText; } - int getDerivationNumber(String address) { - final account = getKeypair(address); - final deriveNbr = account.name!.split('//')[1]; - return int.parse(deriveNbr); - } - Future changePassword(BuildContext context, String address, String passOld, String passNew) async { final account = getKeypair(address); diff --git a/lib/screens/activity.dart b/lib/screens/activity.dart index 9435d87..2831b91 100644 --- a/lib/screens/activity.dart +++ b/lib/screens/activity.dart @@ -13,11 +13,10 @@ import 'package:provider/provider.dart'; class ActivityScreen extends StatefulWidget { const ActivityScreen( - {required this.address, required this.avatar, this.username}) + {required this.address, this.username}) : super(key: keyActivityScreen); final String address; final String? username; - final Image avatar; @override State createState() => _ActivityScreenState(); diff --git a/lib/screens/home.dart b/lib/screens/home.dart index df22b2e..489e07a 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -6,6 +6,7 @@ import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/g1_wallets_list.dart'; import 'package:gecko/models/widgets_keys.dart'; +import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/chest_provider.dart'; import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/home.dart'; @@ -41,6 +42,8 @@ class _HomeScreenState extends State { Provider.of(context, listen: false); final myWalletProvider = Provider.of(context, listen: false); + final csProvider = + Provider.of(context, listen: false); final bool isWalletsExists = myWalletProvider.checkIfWalletExist(); @@ -66,6 +69,7 @@ class _HomeScreenState extends State { if (sub.sdkReady && !sub.nodeConnected) { walletBox = await Hive.openBox("walletBox"); await Hive.deleteBoxFromDisk('g1WalletsBox'); + await csProvider.deleteAvatarFolder(); g1WalletsBox = await Hive.openBox("g1WalletsBox"); contactsBox = await Hive.openBox("contactsBox"); diff --git a/lib/screens/myWallets/wallet_options.dart b/lib/screens/myWallets/wallet_options.dart index 50a83dd..18f93ad 100644 --- a/lib/screens/myWallets/wallet_options.dart +++ b/lib/screens/myWallets/wallet_options.dart @@ -286,6 +286,8 @@ class WalletOptions extends StatelessWidget { if (newPath != '') { wallet.imageCustomPath = newPath; walletBox.put(wallet.key, wallet); + // Uncomment to enable Cs+ avatar storage + // CesiumPlusProvider().setAvatar(wallet.address, newPath); } walletProvider.reload(); }, @@ -448,17 +450,7 @@ class WalletOptions extends StatelessWidget { Navigator.push( context, PageNoTransit(builder: (context) { - return ActivityScreen( - address: walletProvider.address.text, - avatar: wallet.imageCustomPath == null - ? Image.asset( - 'assets/avatars/${wallet.imageDefaultPath}', - width: 110, - ) - : Image.asset( - wallet.imageCustomPath!, - width: 110, - )); + return ActivityScreen(address: walletProvider.address.text); }), ); }, diff --git a/lib/screens/my_contacts.dart b/lib/screens/my_contacts.dart index 75872bb..a42456c 100644 --- a/lib/screens/my_contacts.dart +++ b/lib/screens/my_contacts.dart @@ -14,7 +14,6 @@ class ContactsScreen extends StatelessWidget { @override Widget build(BuildContext context) { Provider.of(context, listen: true); - double avatarSize = 55; final myContacts = contactsBox.toMap().values.toList(); // Order contacts by username @@ -37,7 +36,7 @@ class ContactsScreen extends StatelessWidget { bottomNavigationBar: const GeckoBottomAppBar(), body: SafeArea( child: Stack(children: [ - ContactsList(myContacts: myContacts, avatarSize: avatarSize), + ContactsList(myContacts: myContacts), const OfflineInfo(), ]), ), diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index 83571cc..17b8314 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -6,7 +6,6 @@ import 'package:gecko/globals.dart'; import 'package:flutter/material.dart'; import 'package:gecko/models/g1_wallets_list.dart'; import 'package:gecko/models/widgets_keys.dart'; -import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/my_wallets.dart'; @@ -29,11 +28,10 @@ const double buttonFontSize = 18; class WalletViewScreen extends StatelessWidget { const WalletViewScreen( - {required this.address, required this.username, this.avatar, Key? key}) + {required this.address, required this.username, Key? key}) : super(key: key); final String address; final String? username; - final Image? avatar; @override Widget build(BuildContext context) { @@ -136,9 +134,7 @@ class WalletViewScreen extends StatelessWidget { Navigator.push( context, PageNoTransit(builder: (context) { - return ActivityScreen( - address: address, - avatar: defaultAvatar(50)); + return ActivityScreen(address: address); }), ); }), diff --git a/lib/widgets/cesium_avatar.dart b/lib/widgets/cesium_avatar.dart new file mode 100644 index 0000000..4290189 --- /dev/null +++ b/lib/widgets/cesium_avatar.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:gecko/globals.dart'; +import 'package:gecko/providers/cesium_plus.dart'; +import 'package:gecko/widgets/commons/loading.dart'; +import 'package:provider/provider.dart'; + +class CesiumAvatar extends StatelessWidget { + const CesiumAvatar({Key? key, required this.address, this.size = 15}) + : super(key: key); + final String address; + final double size; + + @override + Widget build(BuildContext context) { + final csProvider = Provider.of(context, listen: false); + log.d('tatata'); + + return ClipOval( + child: FutureBuilder( + future: csProvider.getAvatar(address, size), + builder: ((context, AsyncSnapshot avatar) { + if (avatar.hasError) { + log.e(avatar.error); + return (Icon(Icons.close_outlined, + color: Colors.red, size: size)); + } else if (avatar.connectionState != ConnectionState.done) { + return SizedBox( + width: size, + height: size, + child: const FractionallySizedBox( + widthFactor: 0.6, heightFactor: 0.6, child: Loading())); + } + return avatar.data!; + })), + ); + } +} diff --git a/lib/widgets/commons/loading.dart b/lib/widgets/commons/loading.dart new file mode 100644 index 0000000..b969606 --- /dev/null +++ b/lib/widgets/commons/loading.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:gecko/globals.dart'; + +class Loading extends StatelessWidget { + const Loading({ + Key? key, + this.size = 15, + this.stroke = 2, + }) : super(key: key); + + final double size; + final double stroke; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: size, + width: size, + child: CircularProgressIndicator( + color: orangeC, + strokeWidth: stroke, + ), + ); + } +} diff --git a/lib/widgets/contacts_list.dart b/lib/widgets/contacts_list.dart index 2dd8aab..128ed94 100644 --- a/lib/widgets/contacts_list.dart +++ b/lib/widgets/contacts_list.dart @@ -1,15 +1,14 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:gecko/globals.dart'; import 'package:gecko/models/g1_wallets_list.dart'; import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/widgets_keys.dart'; -import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/screens/wallet_view.dart'; import 'package:gecko/widgets/balance.dart'; +import 'package:gecko/widgets/cesium_avatar.dart'; import 'package:gecko/widgets/name_by_address.dart'; import 'package:provider/provider.dart'; @@ -17,11 +16,9 @@ class ContactsList extends StatelessWidget { const ContactsList({ Key? key, required this.myContacts, - required this.avatarSize, }) : super(key: key); final List myContacts; - final double avatarSize; @override Widget build(BuildContext context) { @@ -47,7 +44,8 @@ class ContactsList extends StatelessWidget { key: keySearchResult('keyID++'), horizontalTitleGap: 40, contentPadding: const EdgeInsets.all(5), - leading: defaultAvatar(avatarSize), + leading: + CesiumAvatar(address: g1Wallet.address, size: 55), title: Row(children: [ Text(getShortPubkey(g1Wallet.address), style: const TextStyle( @@ -87,13 +85,9 @@ class ContactsList extends StatelessWidget { MaterialPageRoute(builder: (context) { walletsProfilesClass.address = g1Wallet.address; return WalletViewScreen( - address: g1Wallet.address, - username: duniterIndexer - .walletNameIndexer[g1Wallet.address], - avatar: g1WalletsBox - .get(g1Wallet.address) - ?.avatar, - ); + address: g1Wallet.address, + username: duniterIndexer + .walletNameIndexer[g1Wallet.address]); }), ); }), diff --git a/lib/widgets/header_profile.dart b/lib/widgets/header_profile.dart index 1337e2d..d852e54 100644 --- a/lib/widgets/header_profile.dart +++ b/lib/widgets/header_profile.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/widgets_keys.dart'; -import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallet_options.dart'; @@ -10,6 +9,7 @@ import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/screens/certifications.dart'; import 'package:gecko/widgets/balance.dart'; import 'package:gecko/widgets/certifications.dart'; +import 'package:gecko/widgets/cesium_avatar.dart'; import 'package:gecko/widgets/commons/offline_info.dart'; import 'package:gecko/widgets/idty_status.dart'; import 'package:gecko/widgets/page_route_no_transition.dart'; @@ -50,7 +50,7 @@ class HeaderProfile extends StatelessWidget { )); }), Padding( - padding: const EdgeInsets.only(left: 30, right: 40), + padding: const EdgeInsets.only(left: 30, right: 30), child: Row(children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -107,9 +107,7 @@ class HeaderProfile extends StatelessWidget { ]), const Spacer(), Column(children: [ - ClipOval( - child: defaultAvatar(avatarSize), - ), + CesiumAvatar(address: address, size: avatarSize), ]), ]), ), diff --git a/lib/widgets/search_identity_query.dart b/lib/widgets/search_identity_query.dart index 8e6ddb8..2a2a351 100644 --- a/lib/widgets/search_identity_query.dart +++ b/lib/widgets/search_identity_query.dart @@ -4,13 +4,13 @@ import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/queries_indexer.dart'; import 'package:gecko/models/widgets_keys.dart'; -import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/search.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/screens/wallet_view.dart'; import 'package:gecko/widgets/balance.dart'; +import 'package:gecko/widgets/cesium_avatar.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:provider/provider.dart'; @@ -86,7 +86,8 @@ class SearchIdentityQuery extends StatelessWidget { key: keySearchResult(profile['pubkey']), horizontalTitleGap: 40, contentPadding: const EdgeInsets.all(5), - leading: defaultAvatar(avatarSize), + leading: CesiumAvatar( + address: profile['pubkey'], size: avatarSize), title: Row(children: [ Text(getShortPubkey(profile['pubkey']), style: const TextStyle( @@ -125,8 +126,6 @@ class SearchIdentityQuery extends StatelessWidget { return WalletViewScreen( address: profile['pubkey'], username: profile['name'], - avatar: - g1WalletsBox.get(profile['pubkey'])?.avatar, ); }), ); diff --git a/lib/widgets/search_result_list.dart b/lib/widgets/search_result_list.dart index 9a09db8..6c701a3 100644 --- a/lib/widgets/search_result_list.dart +++ b/lib/widgets/search_result_list.dart @@ -3,13 +3,13 @@ import 'package:gecko/globals.dart'; import 'package:gecko/models/g1_wallets_list.dart'; import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/widgets_keys.dart'; -import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/duniter_indexer.dart'; import 'package:gecko/providers/search.dart'; import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/screens/wallet_view.dart'; import 'package:gecko/widgets/balance.dart'; +import 'package:gecko/widgets/cesium_avatar.dart'; import 'package:gecko/widgets/name_by_address.dart'; import 'package:gecko/widgets/search_identity_query.dart'; @@ -65,7 +65,7 @@ class SearchResult extends StatelessWidget { key: keySearchResult(g1Wallet.address), horizontalTitleGap: 40, contentPadding: const EdgeInsets.all(5), - leading: defaultAvatar(avatarSize), + leading: CesiumAvatar(address: g1Wallet.address, size: avatarSize), title: Row(children: [ Text(getShortPubkey(g1Wallet.address), style: const TextStyle( @@ -101,7 +101,6 @@ class SearchResult extends StatelessWidget { return WalletViewScreen( address: g1Wallet.address, username: g1Wallet.username, - avatar: g1Wallet.avatar, ); }), ); diff --git a/pubspec.lock b/pubspec.lock index b52e77f..e63bcb1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -298,7 +298,7 @@ packages: source: hosted version: "0.3.3+7" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab @@ -711,6 +711,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + hive_generator: + dependency: "direct dev" + description: + name: hive_generator + sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" + url: "https://pub.dev" + source: hosted + version: "2.0.1" html: dependency: transitive description: @@ -1411,6 +1419,22 @@ packages: description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.dev" + source: hosted + version: "1.3.4" source_span: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 13347ff..f9e54cf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,12 +59,14 @@ dependencies: tutorial_coach_mark: ^1.2.8 confetti: ^0.7.0 url_launcher: ^6.1.11 + crypto: ^3.0.3 dev_dependencies: # flutter_launcher_icons: ^0.9.2 # flutter_launcher_icons_maker: ^^0.10.2 icons_launcher: ^2.0.6 build_runner: ^2.1.2 + hive_generator: ^2.0.1 flutter_lints: ^3.0.1 flutter_test: sdk: flutter