diff --git a/config/indexer_endpoints.json b/config/indexer_endpoints.json index 9e8dc83..feb604e 100644 --- a/config/indexer_endpoints.json +++ b/config/indexer_endpoints.json @@ -1,4 +1,4 @@ [ - "https://duniter-indexer.coinduf.eu/v1/graphql", - "http://192.168.1.72:8080/v1/graphql" + "https://duniter-indexer.coinduf.eu", + "http://192.168.1.72:8080" ] diff --git a/lib/main.dart b/lib/main.dart index c56bff1..01d339c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -58,6 +58,7 @@ Future main() async { HomeProvider _homeProvider = HomeProvider(); DuniterIndexer _duniterIndexer = DuniterIndexer(); + await initHiveForFlutter(); await _homeProvider.initHive(); appVersion = await _homeProvider.getAppVersion(); prefs = await SharedPreferences.getInstance(); @@ -67,7 +68,6 @@ Future main() async { Hive.registerAdapter(ChestDataAdapter()); Hive.registerAdapter(G1WalletsListAdapter()); Hive.registerAdapter(IdAdapter()); - // Hive.registerAdapter(KeyStoreDataAdapter()); walletBox = await Hive.openBox("walletBox"); chestBox = await Hive.openBox("chestBox"); @@ -82,10 +82,7 @@ Future main() async { } // log.d(await configBox.get('endpoint')); - await _duniterIndexer.getValidIndexerEndpoint(); - // _duniterIndexer.indexerEndpoint = "http://192.168.1.72:8080/v1/graphql"; - // _duniterIndexer.indexerEndpoint = - // "https://duniter-indexer.coinduf.eu/v1/graphql"; + _duniterIndexer.getValidIndexerEndpoint(); HttpOverrides.global = MyHttpOverrides(); @@ -131,20 +128,11 @@ class Gecko extends StatelessWidget { @override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); - final _httpLink = HttpLink( - indexerEndpoint!, - ); - final _client = ValueNotifier( - GraphQLClient( - cache: GraphQLCache(), - link: _httpLink, - ), - ); + // To configure multi_endpoints GraphQLProvider: https://stackoverflow.com/q/70656513/8301867 return MultiProvider( providers: [ - // Provider(create: (context) => HistoryProvider()), ChangeNotifierProvider(create: (_) => HomeProvider()), ChangeNotifierProvider(create: (_) => WalletsProfilesProvider('')), ChangeNotifierProvider(create: (_) => MyWalletsProvider()), @@ -156,44 +144,41 @@ class Gecko extends StatelessWidget { ChangeNotifierProvider(create: (_) => SubstrateSdk()), ChangeNotifierProvider(create: (_) => DuniterIndexer()) ], - child: GraphQLProvider( - client: _client, - child: MaterialApp( - builder: (context, widget) => ResponsiveWrapper.builder( - BouncingScrollWrapper.builder(context, widget!), - maxWidth: 1200, - minWidth: 480, - defaultScale: true, - breakpoints: [ - const ResponsiveBreakpoint.resize(480, name: MOBILE), - const ResponsiveBreakpoint.autoScale(800, name: TABLET), - const ResponsiveBreakpoint.resize(1000, name: DESKTOP), - ], - background: Container(color: backgroundColor)), - title: 'Ğecko', - theme: ThemeData( - appBarTheme: const AppBarTheme( - color: Color(0xffFFD58D), - foregroundColor: Color(0xFF000000), - ), - primaryColor: const Color(0xffFFD58D), - textTheme: const TextTheme( - bodyText1: TextStyle(fontSize: 16), - bodyText2: TextStyle(fontSize: 18), - ).apply( - bodyColor: const Color(0xFF000000), - ), - colorScheme: - ColorScheme.fromSwatch().copyWith(secondary: Colors.grey[850]), + child: MaterialApp( + builder: (context, widget) => ResponsiveWrapper.builder( + BouncingScrollWrapper.builder(context, widget!), + maxWidth: 1200, + minWidth: 480, + defaultScale: true, + breakpoints: [ + const ResponsiveBreakpoint.resize(480, name: MOBILE), + const ResponsiveBreakpoint.autoScale(800, name: TABLET), + const ResponsiveBreakpoint.resize(1000, name: DESKTOP), + ], + background: Container(color: backgroundColor)), + title: 'Ğecko', + theme: ThemeData( + appBarTheme: const AppBarTheme( + color: Color(0xffFFD58D), + foregroundColor: Color(0xFF000000), ), - home: const HomeScreen(), - initialRoute: "/", - routes: { - '/mywallets': (context) => const WalletsHome(), - '/search': (context) => const SearchScreen(), - '/searchResult': (context) => const SearchResultScreen(), - }, + primaryColor: const Color(0xffFFD58D), + textTheme: const TextTheme( + bodyText1: TextStyle(fontSize: 16), + bodyText2: TextStyle(fontSize: 18), + ).apply( + bodyColor: const Color(0xFF000000), + ), + colorScheme: + ColorScheme.fromSwatch().copyWith(secondary: Colors.grey[850]), ), + home: const HomeScreen(), + initialRoute: "/", + routes: { + '/mywallets': (context) => const WalletsHome(), + '/search': (context) => const SearchScreen(), + '/searchResult': (context) => const SearchResultScreen(), + }, ), ); } diff --git a/lib/models/queries_indexer.dart b/lib/models/queries_indexer.dart index 5c75ba3..25483cb 100644 --- a/lib/models/queries_indexer.dart +++ b/lib/models/queries_indexer.dart @@ -52,19 +52,31 @@ query ($address: String!) { '''; const String getHistoryByAddressQ3 = r''' -query ($address: String!) { +query ($address: String!, $number: Int!, $cursor: String) { transaction_connection(where: {_or: [ {issuer_id: {_eq: $address}}, {receiver_id: {_eq: $address}} ]}, - order_by: {created_at: desc}) { + order_by: {created_at: desc}, + first: $number, + after: $cursor) { edges { node { amount created_at issuer_id receiver_id + issuer { + identity { + name + } + } + receiver { + identity { + name + } + } } } pageInfo { diff --git a/lib/providers/duniter_indexer.dart b/lib/providers/duniter_indexer.dart index 891243e..4a5a501 100644 --- a/lib/providers/duniter_indexer.dart +++ b/lib/providers/duniter_indexer.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; @@ -17,6 +16,11 @@ import 'package:provider/provider.dart'; class DuniterIndexer with ChangeNotifier { Map walletNameIndexer = {}; + String? fetchMoreCursor; + Map? pageInfo; + int nPage = 1; + int nRepositories = 20; + List? transBC; void reload() { notifyListeners(); @@ -29,7 +33,8 @@ class DuniterIndexer with ChangeNotifier { final _client = HttpClient(); _client.connectionTimeout = const Duration(milliseconds: 1000); try { - final request = await _client.postUrl(Uri.parse(oldEndpoint)); + final request = + await _client.postUrl(Uri.parse('$oldEndpoint/v1/graphql')); final response = await request.close(); if (response.statusCode != 200) { log.d('INDEXER IS OFFILINE'); @@ -73,7 +78,8 @@ class DuniterIndexer with ChangeNotifier { } try { - final request = await _client.postUrl(Uri.parse(_listEndpoints[i])); + final request = + await _client.postUrl(Uri.parse('${_listEndpoints[i]}/v1/graphql')); final response = await request.close(); indexerEndpoint = _listEndpoints[i]; @@ -121,54 +127,67 @@ class DuniterIndexer with ChangeNotifier { } } } + final _httpLink = HttpLink( + '$indexerEndpoint/v1/graphql', + ); - return Query( - options: QueryOptions( - document: gql( - getNameByAddressQ), // this is the query string you just created - variables: { - 'address': address, - }, - // pollInterval: const Duration(seconds: 10), - ), - builder: (QueryResult result, - {VoidCallback? refetch, FetchMore? fetchMore}) { - if (result.hasException) { - return Text(result.exception.toString()); - } + final _client = ValueNotifier( + GraphQLClient( + cache: GraphQLCache(store: HiveStore()), + link: _httpLink, + ), + ); + return GraphQLProvider( + client: _client, + child: Query( + options: QueryOptions( + document: gql( + getNameByAddressQ), // this is the query string you just created + variables: { + 'address': address, + }, + // pollInterval: const Duration(seconds: 10), + ), + builder: (QueryResult result, + {VoidCallback? refetch, FetchMore? fetchMore}) { + if (result.hasException) { + return Text(result.exception.toString()); + } - if (result.isLoading) { - return const Text('Loading'); - } + if (result.isLoading) { + return const Text('Loading'); + } - walletNameIndexer[address] = - result.data?['account_by_pk']?['identity']?['name']; + walletNameIndexer[address] = + result.data?['account_by_pk']?['identity']?['name']; - if (walletNameIndexer[address] == null) { - if (wallet == null) { - return const SizedBox(); - } else { - if (canEdit) { - return _walletOptions.walletName(context, wallet, size, _color); + if (walletNameIndexer[address] == null) { + if (wallet == null) { + return const SizedBox(); } else { - return _walletOptions.walletNameController( - context, wallet, size); + if (canEdit) { + return _walletOptions.walletName( + context, wallet, size, _color); + } else { + return _walletOptions.walletNameController( + context, wallet, size); + } } } - } - return Text( - _color == Colors.grey[700]! - ? '(${walletNameIndexer[address]!})' - : walletNameIndexer[address]!, - style: TextStyle( - fontSize: size, - color: _color, - fontWeight: fontWeight, - fontStyle: fontStyle, - ), - ); - }); + return Text( + _color == Colors.grey[700]! + ? '(${walletNameIndexer[address]!})' + : walletNameIndexer[address]!, + style: TextStyle( + fontSize: size, + color: _color, + fontWeight: fontWeight, + fontStyle: fontStyle, + ), + ); + }), + ); } Widget searchIdentity(BuildContext context, String name) { @@ -182,79 +201,184 @@ class DuniterIndexer with ChangeNotifier { return const Text('Aucun résultat'); } - return Query( - options: QueryOptions( - document: gql( - searchAddressByNameQ), // this is the query string you just created - variables: { - 'name': name, - }, - // pollInterval: const Duration(seconds: 10), - ), - builder: (QueryResult result, - {VoidCallback? refetch, FetchMore? fetchMore}) { - if (result.hasException) { - return Text(result.exception.toString()); - } + final _httpLink = HttpLink( + '$indexerEndpoint/v1/graphql', + ); - if (result.isLoading) { - return const Text('Loading'); - } + final _client = ValueNotifier( + GraphQLClient( + cache: GraphQLCache(store: HiveStore()), + link: _httpLink, + ), + ); + return GraphQLProvider( + client: _client, + child: Query( + options: QueryOptions( + document: gql( + searchAddressByNameQ), // this is the query string you just created + variables: { + 'name': name, + }, + // pollInterval: const Duration(seconds: 10), + ), + builder: (QueryResult result, + {VoidCallback? refetch, FetchMore? fetchMore}) { + if (result.hasException) { + return Text(result.exception.toString()); + } - final List identities = result.data?['search_identity'] ?? []; + if (result.isLoading) { + return const Text('Loading'); + } - if (identities.isEmpty) { - return const Text('Aucun résultat'); - } + final List identities = result.data?['search_identity'] ?? []; - int keyID = 0; - double _avatarSize = 55; - return Expanded( - child: ListView(children: [ - for (Map profile in identities) - 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(profile['id']), - style: const TextStyle( - fontSize: 18, - fontFamily: 'Monospace', - fontWeight: FontWeight.w500), - textAlign: TextAlign.center), - ]), - trailing: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [balance(context, profile['id'], 16)]), - subtitle: Row(children: [ - Text(profile['name'] ?? '', - style: const TextStyle( - fontSize: 18, fontWeight: FontWeight.w500), - textAlign: TextAlign.center), - ]), - dense: false, - isThreeLine: false, - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - _walletsProfiles.address = profile['id']; - return WalletViewScreen( - pubkey: profile['id'], - username: - g1WalletsBox.get(profile['id'])?.id?.username, - avatar: g1WalletsBox.get(profile['id'])?.avatar, - ); - }), - ); - }), - ), - ]), - ); - }); + if (identities.isEmpty) { + return const Text('Aucun résultat'); + } + + int keyID = 0; + double _avatarSize = 55; + return Expanded( + child: ListView(children: [ + for (Map profile in identities) + 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(profile['id']), + style: const TextStyle( + fontSize: 18, + fontFamily: 'Monospace', + fontWeight: FontWeight.w500), + textAlign: TextAlign.center), + ]), + trailing: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [balance(context, profile['id'], 16)]), + subtitle: Row(children: [ + Text(profile['name'] ?? '', + style: const TextStyle( + fontSize: 18, fontWeight: FontWeight.w500), + textAlign: TextAlign.center), + ]), + dense: false, + isThreeLine: false, + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + _walletsProfiles.address = profile['id']; + return WalletViewScreen( + pubkey: profile['id'], + username: g1WalletsBox + .get(profile['id']) + ?.id + ?.username, + avatar: g1WalletsBox.get(profile['id'])?.avatar, + ); + }), + ); + }), + ), + ]), + ); + }), + ); } + + List parseHistory(blockchainTX, _pubkey) { + var transBC = []; + int i = 0; + + for (final trans in blockchainTX) { + final transaction = trans['node']; + final direction = + transaction['issuer_id'] != _pubkey ? 'RECEIVED' : 'SENT'; + + transBC.add(i); + transBC[i] = []; + transBC[i].add(DateTime.parse(transaction['created_at'])); + final int amountBrut = transaction['amount']; + final num amount = removeDecimalZero(amountBrut / 100); + if (direction == "RECEIVED") { + transBC[i].add(transaction['issuer_id']); + transBC[i].add(transaction['issuer']['identity']?['name'] ?? ''); + transBC[i].add(amount.toString()); + } else if (direction == "SENT") { + transBC[i].add(transaction['receiver_id']); + transBC[i].add(transaction['receiver']['identity']?['name'] ?? ''); + transBC[i].add('- ' + amount.toString()); + } + // transBC[i].add(''); //transaction comment + + i++; + } + return transBC; + } + + FetchMoreOptions? checkQueryResult(result, opts, _pubkey) { + final List? blockchainTX = + (result.data['transaction_connection']['edges'] as List?); + // final List mempoolTX = + // (result.data['txsHistoryMp']['receiving'] as List); + + pageInfo = result.data['transaction_connection']['pageInfo']; + fetchMoreCursor = pageInfo!['endCursor']; + if (fetchMoreCursor == null) nPage = 1; + + log.d(fetchMoreCursor); + + if (nPage == 1) { + nRepositories = 40; + } else if (nPage == 2) { + nRepositories = 100; + } + // nRepositories = 10; + nPage++; + + if (fetchMoreCursor != null) { + opts = FetchMoreOptions( + variables: {'cursor': fetchMoreCursor, 'number': nRepositories}, + updateQuery: (previousResultData, fetchMoreResultData) { + final List repos = [ + ...previousResultData!['transaction_connection']['edges'] + as List, + ...fetchMoreResultData!['transaction_connection']['edges'] + as List + ]; + + log.d('repos: ' + previousResultData.toString()); + log.d('repos: ' + fetchMoreResultData.toString()); + log.d('repos: ' + repos.toString()); + + fetchMoreResultData['transaction_connection']['edges'] = repos; + return fetchMoreResultData; + }, + ); + } + + log.d( + "###### DEBUG H Parse blockchainTX list. Cursor: $fetchMoreCursor ######"); + if (fetchMoreCursor != null) { + transBC = parseHistory(blockchainTX, _pubkey); + } else { + log.i("###### DEBUG H - Début de l'historique"); + } + + return opts; + } + + num removeDecimalZero(double n) { + String result = n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2); + return num.parse(result); + } + + // checkHistoryResult( + // QueryResult result, FetchMoreOptions options, String address) {} } diff --git a/lib/providers/wallet_options.dart b/lib/providers/wallet_options.dart index 2a6cc0b..a123809 100644 --- a/lib/providers/wallet_options.dart +++ b/lib/providers/wallet_options.dart @@ -577,7 +577,7 @@ Widget getCerts(BuildContext context, String address, double size, return FutureBuilder( future: _sdk.getCerts(address), builder: (BuildContext context, AsyncSnapshot> _certs) { - log.d(_certs.data); + // log.d(_certs.data); return _certs.data?[0] != 0 && _certs.data != null ? Row( diff --git a/lib/providers/wallets_profiles.dart b/lib/providers/wallets_profiles.dart index 267f364..a12817e 100644 --- a/lib/providers/wallets_profiles.dart +++ b/lib/providers/wallets_profiles.dart @@ -1,32 +1,30 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:gecko/globals.dart'; +import 'package:gecko/providers/cesium_plus.dart'; import 'package:gecko/providers/substrate_sdk.dart'; +import 'package:gecko/providers/wallet_options.dart'; +import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/wallet_view.dart'; -import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:jdenticon_dart/jdenticon_dart.dart'; import 'package:permission_handler/permission_handler.dart'; // import 'package:qrscan/qrscan.dart' as scanner; import 'package:barcode_scan2/barcode_scan2.dart'; -import 'dart:math'; -import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; class WalletsProfilesProvider with ChangeNotifier { WalletsProfilesProvider(this.address); String? address = ''; String pubkeyShort = ''; - List? transBC; - String? fetchMoreCursor; - Map? pageInfo; + bool isHistoryScreen = false; String historySwitchButtun = "Voir l'historique"; String? rawSvg; TextEditingController payAmount = TextEditingController(); TextEditingController payComment = TextEditingController(); - num? balance; - int nRepositories = 20; - int nPage = 1; + num? _balance; Future scan(context) async { if (Platform.isAndroid || Platform.isIOS) { @@ -97,117 +95,10 @@ class WalletsProfilesProvider with ChangeNotifier { // Matograine portefeuille: 9p5nHsES6xujFR7pw2yGy4PLKKHgWsMvsDHaHF64Uj25. // Lion simone: 78jhpprYkMNF6i5kQPXfkAVBpd2aqcpieNsXTSW4c21f - List parseHistory(txs, _pubkey) { - var transBC = []; - int i = 0; - - const currentBase = 0; - double currentUD = 10.54; - - for (final trans in txs) { - var direction = trans['direction']; - final transaction = trans['node']; - String? output; - if (direction == "RECEIVED") { - for (String line in transaction['outputs']) { - if (line.contains(_pubkey)) { - output = line; - } - } - } else { - output = transaction['outputs'][0]; - } - if (output == null) { - continue; - } - - transBC.add(i); - transBC[i] = []; - final dateBrut = DateTime.fromMillisecondsSinceEpoch( - transaction['writtenTime'] * 1000); - final DateFormat formatter = DateFormat('dd-MM-yy\nHH:mm'); - final date = formatter.format(dateBrut); - transBC[i].add(transaction['writtenTime']); - transBC[i].add(date); - final int amountBrut = int.parse(output.split(':')[0]); - final base = int.parse(output.split(':')[1]); - final int applyBase = base - currentBase; - final num amount = - removeDecimalZero(amountBrut * pow(10, applyBase) / 100); - num amountUD = amount / currentUD; - if (direction == "RECEIVED") { - transBC[i].add(transaction['issuers'][0]); - transBC[i].add(getShortPubkey(transaction['issuers'][0])); - transBC[i].add(amount.toString()); - transBC[i].add(amountUD.toStringAsFixed(2)); - } else if (direction == "SENT") { - final outPubkey = output.split("SIG(")[1].replaceAll(')', ''); - transBC[i].add(outPubkey); - transBC[i].add(getShortPubkey(outPubkey)); - transBC[i].add('- ' + amount.toString()); - transBC[i].add(amountUD.toStringAsFixed(2)); - } - transBC[i].add(transaction['comment']); - - i++; - } - return transBC; - } - - FetchMoreOptions? checkQueryResult(result, opts, _pubkey) { - final List? blockchainTX = - (result.data['txsHistoryBc']['both']['edges'] as List?); - // final List mempoolTX = - // (result.data['txsHistoryMp']['receiving'] as List); - - pageInfo = result.data['txsHistoryBc']['both']['pageInfo']; - fetchMoreCursor = pageInfo!['endCursor']; - if (fetchMoreCursor == null) nPage = 1; - - if (nPage == 1) { - nRepositories = 40; - } else if (nPage == 2) { - nRepositories = 100; - } - nPage++; - - if (fetchMoreCursor != null) { - opts = FetchMoreOptions( - variables: {'cursor': fetchMoreCursor, 'number': nRepositories}, - updateQuery: (previousResultData, fetchMoreResultData) { - final List repos = [ - ...previousResultData!['txsHistoryBc']['both']['edges'] - as List, - ...fetchMoreResultData!['txsHistoryBc']['both']['edges'] - as List - ]; - - fetchMoreResultData['txsHistoryBc']['both']['edges'] = repos; - return fetchMoreResultData; - }, - ); - } - - log.d( - "###### DEBUG H Parse blockchainTX list. Cursor: $fetchMoreCursor ######"); - if (fetchMoreCursor != null) { - transBC = parseHistory(blockchainTX, _pubkey); - } else { - log.i("###### DEBUG H - Début de l'historique"); - } - - return opts; - } - void resetdHistory() { notifyListeners(); } - num removeDecimalZero(double n) { - String result = n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 2); - return num.parse(result); - } - String generateIdenticon(String _pubkey) { return Jdenticon.toSvg(_pubkey); } @@ -228,13 +119,116 @@ class WalletsProfilesProvider with ChangeNotifier { // } Future getBalance(String? _pubkey) async { - while (balance == null) { + while (_balance == null) { await Future.delayed(const Duration(milliseconds: 50)); } - return balance; + return _balance; } + +Widget headerProfileView( + BuildContext context, String _address, String? username) { + const double _avatarSize = 140; + + WalletOptionsProvider _walletOptions = + Provider.of(context, listen: false); + CesiumPlusProvider _cesiumPlusProvider = + Provider.of(context, listen: false); + // SubstrateSdk _sub = Provider.of(context, listen: false); + + bool isAccountExist = balanceCache[_address] != 0; + + return Stack(children: [ + Consumer(builder: (context, _sub, _) { + return Container( + height: 180, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + isAccountExist ? yellowC : Colors.grey[400]!, + isAccountExist ? const Color(0xFFE7811A) : Colors.grey[600]!, + ], + ), + )); + }), + Padding( + padding: const EdgeInsets.only(left: 30, right: 40), + child: Row(children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 10, + color: yellowC, // Colors.grey[400], + ), + Row(children: [ + GestureDetector( + key: const Key('copyPubkey'), + onTap: () { + Clipboard.setData(ClipboardData(text: _address)); + snackCopyKey(context); + }, + child: Text( + getShortPubkey(_address), + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.w800, + ), + ), + ), + ]), + const SizedBox(height: 25), + + balance(context, _address, 22), + const SizedBox(height: 10), + _walletOptions.idtyStatus(context, _address, + isOwner: false, color: Colors.black), + getCerts(context, _address, 14), + + if (username == null && + g1WalletsBox.get(_address)?.username != null) + SizedBox( + width: 230, + child: Text( + g1WalletsBox.get(_address)?.username ?? '', + style: const TextStyle( + fontSize: 27, + color: Color(0xff814C00), + ), + ), + ), + if (username != null) + SizedBox( + width: 230, + child: Text( + username, + style: const TextStyle( + fontSize: 27, + color: Color(0xff814C00), + ), + ), + ), + const SizedBox(height: 55), + ]), + const Spacer(), + Column(children: [ + ClipOval( + child: _cesiumPlusProvider.defaultAvatar(_avatarSize), + ), + + const SizedBox(height: 25), + ]), + ]), + ), + CommonElements().offlineInfo(context), + ]); + } + + + void reload() { notifyListeners(); } diff --git a/lib/screens/activity.dart b/lib/screens/activity.dart new file mode 100644 index 0000000..18017cf --- /dev/null +++ b/lib/screens/activity.dart @@ -0,0 +1,350 @@ +import 'package:flutter/services.dart'; +import 'package:gecko/globals.dart'; +import 'package:gecko/models/queries_indexer.dart'; +import 'package:gecko/providers/cesium_plus.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/wallets_profiles.dart'; +import 'package:flutter/material.dart'; +import 'package:gecko/screens/wallet_view.dart'; +import 'package:graphql_flutter/graphql_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +// ignore: must_be_immutable +class ActivityScreen extends StatelessWidget with ChangeNotifier { + ActivityScreen({required this.address, this.avatar, this.username, Key? key}) + : super(key: key); + final ScrollController scrollController = ScrollController(); + final double avatarsSize = 80; + final String? address; + final String? username; + final Image? avatar; + + FetchMore? fetchMore; + FetchMoreOptions? opts; + + final GlobalKey _scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + WalletsProfilesProvider _walletProfile = + Provider.of(context, listen: false); + HomeProvider _homeProvider = + Provider.of(context, listen: false); + + return Scaffold( + key: _scaffoldKey, + appBar: AppBar( + elevation: 0, + toolbarHeight: 60 * ratio, + title: const SizedBox( + height: 22, + child: Text('Activité du compte'), + ), + ), + bottomNavigationBar: _homeProvider.bottomAppBar(context), + body: Column(children: [ + _walletProfile.headerProfileView(context, address!, username), + historyQuery(context), + ])); + } + + Widget historyQuery(context) { + DuniterIndexer _duniterIndexer = + Provider.of(context, listen: false); + + if (indexerEndpoint == '') { + Column(children: const [ + SizedBox(height: 50), + Text( + "L'état du réseau ne permet pas\nd'afficher l'historique du compte", + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ) + ]); + } + + final _httpLink = HttpLink( + '$indexerEndpoint/v1beta1/relay', + ); + + final _client = ValueNotifier( + GraphQLClient( + cache: GraphQLCache(), + link: _httpLink, + ), + ); + + return GraphQLProvider( + client: _client, + child: Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Query( + options: QueryOptions( + document: gql(getHistoryByAddressQ3), + variables: { + 'address': address, + 'number': 20, + 'cursor': null + }, + ), + builder: (QueryResult result, {fetchMore, refetch}) { + if (result.isLoading && result.data == null) { + return const Center( + child: CircularProgressIndicator(), + ); + } + + if (result.hasException) { + log.e('Error Indexer: ' + result.exception.toString()); + return Column(children: const [ + SizedBox(height: 50), + Text( + "L'état du réseau ne permet pas\nd'afficher l'historique du compte", + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ) + ]); + } else if (result.data == null) { + return Column(children: const [ + SizedBox(height: 50), + Text( + "Aucune donnée à afficher.", + style: TextStyle(fontSize: 18), + ) + ]); + } + + if (result.isNotLoading) { + // log.d(result.data); + opts = _duniterIndexer.checkQueryResult(result, opts, address!); + } + + // Build history list + return NotificationListener( + child: Builder( + builder: (context) => Expanded( + child: ListView( + key: const Key('listTransactions'), + controller: scrollController, + children: [historyView(context, result)], + ), + ), + ), + onNotification: (dynamic t) { + if (t is ScrollEndNotification && + scrollController.position.pixels >= + scrollController.position.maxScrollExtent * 0.7 && + _duniterIndexer.pageInfo!['hasNextPage'] && + result.isNotLoading) { + fetchMore!(opts!); + } + return true; + }); + }, + ), + ], + )), + ); + } + + Widget historyView(context, result) { + DuniterIndexer _duniterIndexer = + Provider.of(context, listen: false); + + return _duniterIndexer.transBC == null + ? Column(children: const [ + SizedBox(height: 50), + Text( + "Aucune transaction à afficher.", + style: TextStyle(fontSize: 18), + ) + ]) + : Column(children: [ + getTransactionTile(context, _duniterIndexer), + if (result.isLoading && + _duniterIndexer.pageInfo!['hasPreviousPage']) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator(), + ], + ), + if (!_duniterIndexer.pageInfo!['hasNextPage']) + Column( + children: const [ + SizedBox(height: 15), + Text("Début de l'historique.", + textAlign: TextAlign.center, + style: TextStyle(fontSize: 20)), + SizedBox(height: 15) + ], + ) + ]); + } + + Widget getTransactionTile( + BuildContext context, DuniterIndexer _duniterIndexer) { + CesiumPlusProvider _cesiumPlusProvider = + Provider.of(context, listen: false); + int keyID = 0; + String? dateDelimiter; + String? lastDateDelimiter; + const double _avatarSize = 200; + + bool isTody = false; + bool isYesterday = false; + bool isThisWeek = false; + + const Map monthsInYear = { + 1: "Janvier", + 2: "Février", + 3: "Mars", + 4: "Avril", + 5: "Mai", + 6: "Juin", + 7: "Juillet", + 8: "Aout", + 9: "Septembre", + 10: "Octobre", + 11: "Novembre", + 12: "Décembre" + }; + + return Column( + children: _duniterIndexer.transBC!.map((repository) { + // log.d('bbbbbbbbbbbbbbbbbbbbbb: ' + repository.toString()); + + DateTime now = DateTime.now(); + DateTime date = repository[0]; + + String dateForm; + if ({4, 10, 11, 12}.contains(date.month)) { + dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 3)}."; + } else if ({1, 2, 7, 9}.contains(date.month)) { + dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 4)}."; + } else { + dateForm = "${date.day} ${monthsInYear[date.month]}"; + } + + int weekNumber(DateTime date) { + int dayOfYear = int.parse(DateFormat("D").format(date)); + return ((dayOfYear - date.weekday + 10) / 7).floor(); + } + + final transactionDate = DateTime(date.year, date.month, date.day); + final todayDate = DateTime(now.year, now.month, now.day); + final yesterdayDate = DateTime(now.year, now.month, now.day - 1); + + if (transactionDate == todayDate && !isTody) { + dateDelimiter = lastDateDelimiter = "Aujourd'hui"; + isTody = true; + } else if (transactionDate == yesterdayDate && !isYesterday) { + dateDelimiter = lastDateDelimiter = "Hier"; + isYesterday = true; + } else if (weekNumber(date) == weekNumber(now) && + date.year == now.year && + lastDateDelimiter != "Cette semaine" && + transactionDate != yesterdayDate && + transactionDate != todayDate && + !isThisWeek) { + dateDelimiter = lastDateDelimiter = "Cette semaine"; + isThisWeek = true; + } else if (lastDateDelimiter != monthsInYear[date.month] && + lastDateDelimiter != "${monthsInYear[date.month]} ${date.year}" && + transactionDate != todayDate && + transactionDate != yesterdayDate && + !(weekNumber(date) == weekNumber(now) && date.year == now.year)) { + if (date.year == now.year) { + dateDelimiter = lastDateDelimiter = monthsInYear[date.month]; + } else { + dateDelimiter = + lastDateDelimiter = "${monthsInYear[date.month]} ${date.year}"; + } + } else { + dateDelimiter = null; + } + + return Column(children: [ + if (dateDelimiter != null) + Padding( + padding: const EdgeInsets.symmetric(vertical: 30), + child: Text( + dateDelimiter!, + style: TextStyle( + fontSize: 23, color: orangeC, fontWeight: FontWeight.w300), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 0), + child: + // Row(children: [Column(children: [],)],) + ListTile( + key: Key('transaction${keyID++}'), + contentPadding: const EdgeInsets.only( + left: 20, right: 30, top: 15, bottom: 15), + leading: ClipOval( + child: _cesiumPlusProvider.defaultAvatar(_avatarSize), + ), + title: Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Text(getShortPubkey(repository[1]), + style: const TextStyle( + fontSize: 18, fontFamily: 'Monospace')), + ), + subtitle: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: Colors.grey[700], + ), + children: [ + TextSpan( + text: dateForm, + ), + if (repository[2] != '') + TextSpan( + text: ' · ', + style: TextStyle( + fontSize: 20, + color: Colors.grey[550], + ), + ), + TextSpan( + text: repository[2], + style: TextStyle( + fontStyle: FontStyle.italic, + color: Colors.grey[600], + ), + ), + ], + ), + ), + trailing: Text("${repository[3]} $currencyName", + style: const TextStyle( + fontSize: 18, fontWeight: FontWeight.w500), + textAlign: TextAlign.justify), + dense: false, + isThreeLine: false, + onTap: () { + _duniterIndexer.nPage = 1; + // _cesiumPlusProvider.avatarCancelToken.cancel('cancelled'); + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return WalletViewScreen(pubkey: repository[1]); + }), + ); + // Navigator.pop(context); + }), + ), + ]); + }).toList()); + } +} diff --git a/lib/screens/history.dart b/lib/screens/history.dart deleted file mode 100644 index 119034f..0000000 --- a/lib/screens/history.dart +++ /dev/null @@ -1,552 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:gecko/globals.dart'; -import 'package:gecko/providers/cesium_plus.dart'; -import 'package:gecko/providers/substrate_sdk.dart'; -import 'package:gecko/providers/wallets_profiles.dart'; -import 'package:flutter/material.dart'; -import 'package:gecko/screens/avatar_fullscreen.dart'; -import 'package:gecko/screens/wallet_view.dart'; -import 'package:graphql_flutter/graphql_flutter.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; - -// ignore: must_be_immutable -class HistoryScreen extends StatelessWidget with ChangeNotifier { - HistoryScreen({required this.pubkey, this.avatar, this.username, Key? key}) - : super(key: key); - final ScrollController scrollController = ScrollController(); - final double avatarsSize = 80; - final String? pubkey; - final String? username; - final Image? avatar; - - FetchMore? fetchMore; - FetchMoreOptions? opts; - - final GlobalKey _scaffoldKey = GlobalKey(); - - @override - Widget build(BuildContext context) { - SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); - WalletsProfilesProvider _historyProvider = - Provider.of(context, listen: false); - CesiumPlusProvider _cesiumPlusProvider = - Provider.of(context, listen: false); - log.i('Build pubkey : ' + pubkey!); - // WidgetsBinding.instance.addPostFrameCallback((_) {}); - - _historyProvider.balance = _historyProvider.transBC = null; - - return Scaffold( - key: _scaffoldKey, - appBar: AppBar( - elevation: 0, - toolbarHeight: 60 * ratio, - title: const SizedBox( - height: 22, - child: Text('Historique des transactions'), - ), - ), - body: Column(children: [ - headerProfileView(context, _historyProvider, _cesiumPlusProvider), - historyQuery(context, _cesiumPlusProvider), - ])); - } - - Widget historyQuery(context, CesiumPlusProvider _cesiumPlusProvider) { - WalletsProfilesProvider _historyProvider = - Provider.of(context, listen: true); - - return Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Query( - options: QueryOptions( - document: gql('getHistory'), - variables: { - 'pubkey': pubkey, - 'number': 10, - 'cursor': null - }, - ), - builder: (QueryResult result, {fetchMore, refetch}) { - if (result.isLoading && result.data == null) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - if (result.hasException) { - log.e('Error GVA: ' + result.exception.toString()); - return Column(children: const [ - SizedBox(height: 50), - Text( - "Aucun noeud GVA valide n'a pu être trouvé.\nVeuillez réessayer ultérieurement.", - style: TextStyle(fontSize: 18), - ) - ]); - } else if (result.data == null) { - return Column(children: const [ - SizedBox(height: 50), - Text( - "Aucune donnée à afficher.", - style: TextStyle(fontSize: 18), - ) - ]); - } - - if (result.data!['balance'] == null) { - _historyProvider.balance = 0.0; - } else { - _historyProvider.balance = _historyProvider - .removeDecimalZero(result.data!['balance']['amount'] / 100); - } - - if (result.isNotLoading) { - // log.d(result.data); - opts = _historyProvider.checkQueryResult(result, opts, pubkey); - } - - // Build history list - return NotificationListener( - child: Builder( - builder: (context) => Expanded( - child: ListView( - key: const Key('listTransactions'), - controller: scrollController, - children: [historyView(context, result)], - ), - ), - ), - onNotification: (dynamic t) { - if (t is ScrollEndNotification && - scrollController.position.pixels >= - scrollController.position.maxScrollExtent * 0.7 && - _historyProvider.pageInfo!['hasPreviousPage'] && - result.isNotLoading) { - fetchMore!(opts!); - } - return true; - }); - }, - ), - ], - )); - } - - Widget historyView(context, result) { - WalletsProfilesProvider _historyProvider = - Provider.of(context, listen: false); - - return _historyProvider.transBC == null - ? Column(children: const [ - SizedBox(height: 50), - Text( - "Aucune transaction à afficher.", - style: TextStyle(fontSize: 18), - ) - ]) - : Column(children: [ - getTransactionTile(context, _historyProvider), - if (result.isLoading && - _historyProvider.pageInfo!['hasPreviousPage']) - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - CircularProgressIndicator(), - ], - ), - if (!_historyProvider.pageInfo!['hasPreviousPage']) - Column( - children: const [ - SizedBox(height: 15), - Text("Début de l'historique.", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 20)), - SizedBox(height: 15) - ], - ) - ]); - } - - Widget getTransactionTile( - BuildContext context, WalletsProfilesProvider _historyProvider) { - CesiumPlusProvider _cesiumPlusProvider = - Provider.of(context, listen: false); - int keyID = 0; - String? dateDelimiter; - String? lastDateDelimiter; - const double _avatarSize = 200; - - bool isTody = false; - bool isYesterday = false; - bool isThisWeek = false; - - const Map monthsInYear = { - 1: "Janvier", - 2: "Février", - 3: "Mars", - 4: "Avril", - 5: "Mai", - 6: "Juin", - 7: "Juillet", - 8: "Aout", - 9: "Septembre", - 10: "Octobre", - 11: "Novembre", - 12: "Décembre" - }; - - return Column( - children: _historyProvider.transBC!.map((repository) { - DateTime now = DateTime.now(); - DateTime date = DateTime.fromMillisecondsSinceEpoch(repository[0] * 1000); - - String dateForm; - if ({4, 10, 11, 12}.contains(date.month)) { - dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 3)}."; - } else if ({1, 2, 7, 9}.contains(date.month)) { - dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 4)}."; - } else { - dateForm = "${date.day} ${monthsInYear[date.month]}"; - } - - int weekNumber(DateTime date) { - int dayOfYear = int.parse(DateFormat("D").format(date)); - return ((dayOfYear - date.weekday + 10) / 7).floor(); - } - - final transactionDate = DateTime(date.year, date.month, date.day); - final todayDate = DateTime(now.year, now.month, now.day); - final yesterdayDate = DateTime(now.year, now.month, now.day - 1); - - if (transactionDate == todayDate && !isTody) { - dateDelimiter = lastDateDelimiter = "Aujourd'hui"; - isTody = true; - } else if (transactionDate == yesterdayDate && !isYesterday) { - dateDelimiter = lastDateDelimiter = "Hier"; - isYesterday = true; - } else if (weekNumber(date) == weekNumber(now) && - date.year == now.year && - lastDateDelimiter != "Cette semaine" && - transactionDate != yesterdayDate && - transactionDate != todayDate && - !isThisWeek) { - dateDelimiter = lastDateDelimiter = "Cette semaine"; - isThisWeek = true; - } else if (lastDateDelimiter != monthsInYear[date.month] && - lastDateDelimiter != "${monthsInYear[date.month]} ${date.year}" && - transactionDate != todayDate && - transactionDate != yesterdayDate && - !(weekNumber(date) == weekNumber(now) && date.year == now.year)) { - if (date.year == now.year) { - dateDelimiter = lastDateDelimiter = monthsInYear[date.month]; - } else { - dateDelimiter = - lastDateDelimiter = "${monthsInYear[date.month]} ${date.year}"; - } - } else { - dateDelimiter = null; - } - - return Column(children: [ - if (dateDelimiter != null) - Padding( - padding: const EdgeInsets.symmetric(vertical: 30), - child: Text( - dateDelimiter!, - style: TextStyle( - fontSize: 23, color: orangeC, fontWeight: FontWeight.w300), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 0), - child: - // Row(children: [Column(children: [],)],) - ListTile( - key: Key('transaction${keyID++}'), - contentPadding: const EdgeInsets.only( - left: 20, right: 30, top: 15, bottom: 15), - leading: g1WalletsBox.get(repository[2])?.avatar == null - ? FutureBuilder( - future: _cesiumPlusProvider.getAvatar( - repository[2], _avatarSize), - builder: (BuildContext context, - AsyncSnapshot _avatar) { - if (_avatar.connectionState != - ConnectionState.done || - _avatar.hasError) { - return Stack(children: [ - _cesiumPlusProvider.defaultAvatar(_avatarSize), - Positioned( - top: 8, - right: 0, - width: 12, - height: 12, - child: CircularProgressIndicator( - strokeWidth: 1, - color: orangeC, - ), - ), - ]); - } - if (_avatar.hasData) { - g1WalletsBox.get(repository[2])?.avatar = - _avatar.data; - return ClipOval(child: _avatar.data); - } else { - g1WalletsBox.get(repository[2])?.avatar = - _cesiumPlusProvider - .defaultAvatar(repository[2]); - return _cesiumPlusProvider - .defaultAvatar(_avatarSize); - } - }) - : ClipOval( - child: Image( - image: - g1WalletsBox.get(repository[2])!.avatar!.image, - height: _avatarSize, - ), - ), - title: Padding( - padding: EdgeInsets.only( - bottom: 5, top: repository[6] != '' ? 0 : 0), - child: Text(repository[3], - style: const TextStyle( - fontSize: 18, fontFamily: 'Monospace')), - ), - subtitle: RichText( - text: TextSpan( - style: TextStyle( - fontSize: 16, - color: Colors.grey[700], - ), - children: [ - TextSpan( - text: dateForm, - ), - if (repository[6] != '') - TextSpan( - text: ' · ', - style: TextStyle( - fontSize: 20, - color: Colors.grey[550], - ), - ), - TextSpan( - text: repository[6], - style: TextStyle( - fontStyle: FontStyle.italic, - color: Colors.grey[600], - ), - ), - ], - ), - ), - trailing: Text("${repository[4]} $currencyName", - style: const TextStyle( - fontSize: 18, fontWeight: FontWeight.w500), - textAlign: TextAlign.justify), - dense: false, - isThreeLine: false, - onTap: () { - _historyProvider.nPage = 1; - // _cesiumPlusProvider.avatarCancelToken.cancel('cancelled'); - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return WalletViewScreen(pubkey: repository[2]); - }), - ); - // Navigator.pop(context); - }), - ), - ]); - }).toList()); - } - - Widget headerProfileView( - BuildContext context, - WalletsProfilesProvider _historyProvider, - CesiumPlusProvider _cesiumPlusProvider) { - const double _avatarSize = 140; - - return Column(children: [ - Container( - height: 10, - color: yellowC, - ), - Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - yellowC, - const Color(0xFFE7811A), - ], - )), - child: Padding( - padding: const EdgeInsets.only(left: 30, right: 40), - child: Row(children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row(children: [ - GestureDetector( - key: const Key('copyPubkey'), - onTap: () { - Clipboard.setData(ClipboardData(text: pubkey)); - snackCopyKey(context); - }, - child: Text( - getShortPubkey(pubkey!), - style: const TextStyle( - fontSize: 30, - fontWeight: FontWeight.w800, - ), - ), - ), - ]), - const SizedBox(height: 10), - if (username == null) - Query( - options: QueryOptions( - document: gql('getId'), - variables: { - 'pubkey': pubkey, - }, - ), - builder: (QueryResult result, - {VoidCallback? refetch, FetchMore? fetchMore}) { - if (result.isLoading || result.hasException) { - return const Text('...'); - } else if (result.data!['idty'] == null || - result.data!['idty']['username'] == null) { - return const Text(''); - } else { - return SizedBox( - width: 230, - child: Text( - result.data!['idty']['username'] ?? '', - style: const TextStyle( - fontSize: 27, - color: Color(0xff814C00), - ), - ), - ); - } - }, - ), - if (username != null) - SizedBox( - width: 230, - child: Text( - username!, - style: const TextStyle( - fontSize: 27, - color: Color(0xff814C00), - ), - ), - ), - const SizedBox(height: 25), - ]), - FutureBuilder( - future: _historyProvider.getBalance(pubkey), - builder: - (BuildContext context, AsyncSnapshot _balance) { - if (_balance.connectionState != ConnectionState.done || - _balance.hasError) { - return const Text('...'); - } - return Text( - "${_balance.data.toString()} $currencyName", - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 22, fontWeight: FontWeight.w500), - ); - }), - const SizedBox(height: 30), - ]), - const Spacer(), - Column(children: [ - if (avatar == null) - FutureBuilder( - future: _cesiumPlusProvider.getAvatar(pubkey, _avatarSize), - builder: - (BuildContext context, AsyncSnapshot _avatar) { - if (_avatar.connectionState != ConnectionState.done) { - return Stack(children: [ - ClipOval( - child: - _cesiumPlusProvider.defaultAvatar(_avatarSize), - ), - Positioned( - top: 15, - right: 45, - width: 51, - height: 51, - child: CircularProgressIndicator( - strokeWidth: 5, - color: orangeC, - ), - ), - ]); - } - if (_avatar.hasData) { - return GestureDetector( - key: const Key('openAvatar'), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return AvatarFullscreen(_avatar.data); - }), - ); - }, - child: ClipOval( - child: Image( - image: _avatar.data!.image, - height: _avatarSize, - fit: BoxFit.cover, - ), - ), - ); - } - return ClipOval( - child: _cesiumPlusProvider.defaultAvatar(_avatarSize), - ); - }), - if (avatar != null) - GestureDetector( - key: const Key('openAvatar'), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return AvatarFullscreen(avatar); - }), - ); - }, - child: ClipOval( - child: Image( - image: avatar!.image, - height: _avatarSize, - fit: BoxFit.cover, - ), - ), - ), - const SizedBox(height: 25), - ]), - ]), - ), - ), - ]); - } -} diff --git a/lib/screens/myWallets/wallet_options.dart b/lib/screens/myWallets/wallet_options.dart index 907dbe8..0f41e31 100644 --- a/lib/screens/myWallets/wallet_options.dart +++ b/lib/screens/myWallets/wallet_options.dart @@ -10,6 +10,7 @@ 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/activity.dart'; import 'package:gecko/screens/myWallets/manage_membership.dart'; import 'package:gecko/screens/qrcode_fullscreen.dart'; import 'package:provider/provider.dart'; @@ -162,7 +163,7 @@ class WalletOptions extends StatelessWidget { return Column(children: [ pubkeyWidget(walletProvider, ctx), SizedBox(height: 10 * ratio), - historyWidget( + activityWidget( context, _historyProvider, walletProvider), SizedBox(height: 12 * ratio), setDefaultWalletWidget( @@ -316,30 +317,30 @@ class WalletOptions extends StatelessWidget { ); } - Widget historyWidget( + Widget activityWidget( BuildContext context, WalletsProfilesProvider _historyProvider, WalletOptionsProvider walletProvider) { return InkWell( - key: const Key('displayHistory'), + key: const Key('displayActivity'), onTap: () { - _historyProvider.nPage = 1; - // Navigator.push( - // context, - // MaterialPageRoute(builder: (context) { - // return HistoryScreen( - // pubkey: walletProvider.address.text, - // avatar: wallet.imageCustomPath == null - // ? Image.asset( - // 'assets/avatars/${wallet.imageDefaultPath}', - // width: 110, - // ) - // : Image.asset( - // wallet.imageCustomPath!, - // width: 110, - // )); - // }), - // ); + // _historyProvider.nPage = 1; + Navigator.push( + context, + MaterialPageRoute(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, + )); + }), + ); }, child: SizedBox( height: 50, @@ -350,8 +351,8 @@ class WalletOptions extends StatelessWidget { height: 45, ), const SizedBox(width: 22), - Text('Historique des transactions', - style: TextStyle(fontSize: 20, color: Colors.grey[500])), + const Text('Activité', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500)), ]), ), ); diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index 9644306..3c4ea93 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -8,7 +8,7 @@ import 'package:gecko/providers/wallet_options.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/avatar_fullscreen.dart'; +import 'package:gecko/screens/activity.dart'; import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/myWallets/choose_wallet.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; @@ -30,11 +30,11 @@ class WalletViewScreen extends StatelessWidget { @override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); - WalletsProfilesProvider _walletViewProvider = + WalletsProfilesProvider _walletProfile = Provider.of(context, listen: false); CesiumPlusProvider _cesiumPlusProvider = Provider.of(context, listen: false); - _walletViewProvider.address = pubkey!; + _walletProfile.address = pubkey!; SubstrateSdk _sub = Provider.of(context, listen: false); HomeProvider _homeProvider = Provider.of(context, listen: false); @@ -57,13 +57,13 @@ class WalletViewScreen extends StatelessWidget { context, MaterialPageRoute(builder: (context) { return QrCodeFullscreen( - _walletViewProvider.address!, + _walletProfile.address!, ); }), ); }, child: QrImageWidget( - data: _walletViewProvider.address!, + data: _walletProfile.address!, version: QrVersions.auto, size: 80, ), @@ -75,12 +75,9 @@ class WalletViewScreen extends StatelessWidget { ), ), bottomNavigationBar: _homeProvider.bottomAppBar(context), - // floatingActionButton: _homeProvider.floatingAction(context, 1), - // floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, body: SafeArea( child: Column(children: [ - headerProfileView( - context, _walletViewProvider, _cesiumPlusProvider), + _walletProfile.headerProfileView(context, pubkey!, username), SizedBox(height: isTall ? 10 : 0), Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column(children: [ @@ -88,8 +85,7 @@ class WalletViewScreen extends StatelessWidget { height: buttonSize, child: ClipOval( child: Material( - color: Colors - .grey[300], //const Color(0xffFFD58D), // button color + color: yellowC, //const Color(0xffFFD58D), // button color child: InkWell( key: const Key('viewHistory'), splashColor: orangeC, // inkwell color @@ -100,20 +96,16 @@ class WalletViewScreen extends StatelessWidget { 'assets/walletOptions/clock.png'), height: 90)), onTap: () { - //// Wait for subsquid indexer // _historyProvider.nPage = 1; - // Navigator.push( - // context, - // FaderTransition( - // page: HistoryScreen( - // pubkey: pubkey, - // username: username ?? - // g1WalletsBox.get(pubkey)?.username, - // avatar: avatar ?? - // g1WalletsBox.get(pubkey)?.avatar, - // ), - // isFast: false), - // ); + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return ActivityScreen( + address: pubkey, + avatar: + _cesiumPlusProvider.defaultAvatar(50)); + }), + ); }), ), ), @@ -386,7 +378,7 @@ class WalletViewScreen extends StatelessWidget { )), onTap: _sub.nodeConnected ? () { - paymentPopup(context, _walletViewProvider); + paymentPopup(context, _walletProfile); } : null), ), @@ -699,217 +691,4 @@ class WalletViewScreen extends StatelessWidget { }); }).then((value) => _walletViewProvider.payAmount.text = ''); } - - Widget headerProfileView( - BuildContext context, - WalletsProfilesProvider _historyProvider, - CesiumPlusProvider _cesiumPlusProvider) { - const double _avatarSize = 140; - - WalletOptionsProvider _walletOptions = - Provider.of(context, listen: false); - // SubstrateSdk _sub = Provider.of(context, listen: false); - - bool isAccountExist = balanceCache[pubkey] != 0; - - return Stack(children: [ - Consumer(builder: (context, _sub, _) { - return Container( - height: 180, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - isAccountExist ? yellowC : Colors.grey[400]!, - isAccountExist ? const Color(0xFFE7811A) : Colors.grey[600]!, - ], - ), - )); - }), - Padding( - padding: const EdgeInsets.only(left: 30, right: 40), - child: Row(children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - height: 10, - color: yellowC, // Colors.grey[400], - ), - Row(children: [ - GestureDetector( - key: const Key('copyPubkey'), - onTap: () { - Clipboard.setData(ClipboardData(text: pubkey)); - snackCopyKey(context); - }, - child: Text( - getShortPubkey(pubkey!), - style: const TextStyle( - fontSize: 30, - fontWeight: FontWeight.w800, - ), - ), - ), - ]), - const SizedBox(height: 25), - - balance(context, pubkey!, 22), - const SizedBox(height: 10), - _walletOptions.idtyStatus(context, pubkey!, - isOwner: false, color: Colors.black), - getCerts(context, pubkey!, 14), - - // if (username == null && - // g1WalletsBox.get(pubkey)?.username == null) - // Query( - // options: QueryOptions( - // document: gql(getId), - // variables: { - // 'pubkey': pubkey, - // }, - // ), - // builder: (QueryResult result, - // {VoidCallback? refetch, FetchMore? fetchMore}) { - // if (result.isLoading || result.hasException) { - // return const Text('...'); - // } else if (result.data!['idty'] == null || - // result.data!['idty']['username'] == null) { - // g1WalletsBox.get(pubkey)?.username = ''; - // return const Text(''); - // } else { - // g1WalletsBox.get(pubkey)?.username = - // result.data!['idty']['username'] ?? ''; - // return SizedBox( - // width: 230, - // child: Text( - // result.data!['idty']['username'] ?? '', - // style: const TextStyle( - // fontSize: 27, - // color: Color(0xff814C00), - // ), - // ), - // ); - // } - // }, - // ), - if (username == null && - g1WalletsBox.get(pubkey)?.username != null) - SizedBox( - width: 230, - child: Text( - g1WalletsBox.get(pubkey)?.username ?? '', - style: const TextStyle( - fontSize: 27, - color: Color(0xff814C00), - ), - ), - ), - if (username != null) - SizedBox( - width: 230, - child: Text( - username!, - style: const TextStyle( - fontSize: 27, - color: Color(0xff814C00), - ), - ), - ), - const SizedBox(height: 25), - //// To get Cs+ name - // FutureBuilder( - // future: _cesiumPlusProvider.getName(pubkey), - // initialData: '...', - // builder: (context, snapshot) { - // return SizedBox( - // width: 230, - // child: Text( - // snapshot.data.toString(), - // style: const TextStyle( - // fontSize: 18, color: Colors.black), - // ), - // ); - // }), - const SizedBox(height: 30), - ]), - const Spacer(), - Column(children: [ - if (avatar == null) - ClipOval( - child: _cesiumPlusProvider.defaultAvatar(_avatarSize), - ), - // FutureBuilder( - // future: _cesiumPlusProvider.getAvatar(pubkey, _avatarSize), - // builder: - // (BuildContext context, AsyncSnapshot _avatar) { - // if (_avatar.connectionState != ConnectionState.done) { - // return Stack(children: [ - // ClipOval( - // child: - // _cesiumPlusProvider.defaultAvatar(_avatarSize), - // ), - // Positioned( - // top: 15, - // right: 45, - // width: 51, - // height: 51, - // child: CircularProgressIndicator( - // strokeWidth: 5, - // color: orangeC, - // ), - // ), - // ]); - // } - // if (_avatar.hasData) { - // return GestureDetector( - // key: const Key('openAvatar'), - // onTap: () { - // Navigator.push( - // context, - // MaterialPageRoute(builder: (context) { - // return AvatarFullscreen(_avatar.data); - // }), - // ); - // }, - // child: ClipOval( - // child: Image( - // image: _avatar.data!.image, - // height: _avatarSize, - // fit: BoxFit.cover, - // ), - // ), - // ); - // } - // return ClipOval( - // child: _cesiumPlusProvider.defaultAvatar(_avatarSize), - // ); - // }), - if (avatar != null) - GestureDetector( - key: const Key('openAvatar'), - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return AvatarFullscreen(avatar); - }), - ); - }, - child: ClipOval( - child: Image( - image: avatar!.image, - height: _avatarSize, - fit: BoxFit.cover, - ), - ), - ), - const SizedBox(height: 25), - ]), - ]), - ), - CommonElements().offlineInfo(context), - ]); - } } diff --git a/pubspec.yaml b/pubspec.yaml index 705ea83..3ca445c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -97,7 +97,6 @@ flutter: uses-material-design: true assets: - - images/ - config/ - assets/ - assets/home/