From 8f0018e326f6d89c05f09073f4d30a50c06db5fd Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 30 Nov 2021 10:28:13 +0100 Subject: [PATCH] New history screen --- lib/main.dart | 3 +- lib/models/cesium_plus.dart | 4 + lib/models/home.dart | 2 +- lib/models/search.dart | 2 +- lib/models/wallets_profiles.dart | 19 ++ lib/screens/history.dart | 569 +++++++++++++++++++++++++++++++ lib/screens/old_history_pay.dart | 4 +- lib/screens/search_result.dart | 5 +- lib/screens/wallet_view.dart | 359 +++++++++---------- pubspec.lock | 7 + pubspec.yaml | 3 +- 11 files changed, 797 insertions(+), 180 deletions(-) create mode 100644 lib/screens/history.dart diff --git a/lib/main.dart b/lib/main.dart index 053d46a..5165a30 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -69,7 +69,8 @@ Future main() async { // await HiveStore.open(path: '${appPath.path}/gqlCache'); // Get a valid GVA endpoint - endPointGVA = 'https://g1.librelois.fr/gva'; + // endPointGVA = 'https://g1.librelois.fr/gva'; + endPointGVA = 'https://duniter-g1.p2p.legal/gva'; // await _homeProvider.getValidEndpoint(); // if (endPointGVA == 'HS') { diff --git a/lib/models/cesium_plus.dart b/lib/models/cesium_plus.dart index b66306e..528cd79 100644 --- a/lib/models/cesium_plus.dart +++ b/lib/models/cesium_plus.dart @@ -79,6 +79,10 @@ class CesiumPlusProvider with ChangeNotifier { } Future getAvatar(String _pubkey, double size) async { + if (g1WalletsBox.get(_pubkey).avatar != null) { + return g1WalletsBox.get(_pubkey).avatar; + } + List queryOptions = await _buildQuery(_pubkey); http.Response response; diff --git a/lib/models/home.dart b/lib/models/home.dart index f8b99eb..f661211 100644 --- a/lib/models/home.dart +++ b/lib/models/home.dart @@ -21,7 +21,7 @@ class HomeProvider with ChangeNotifier { Widget appBarExplorer = Text('Explorateur', style: TextStyle(color: Colors.grey[850])); - List currentTab = [HistoryScreen(), WalletsHome()]; + List currentTab = [OldHistoryScreen(), WalletsHome()]; bool isFirstBuild = true; // AudioCache player = AudioCache(prefix: 'sounds/'); diff --git a/lib/models/search.dart b/lib/models/search.dart index 7fa8673..d1262ed 100644 --- a/lib/models/search.dart +++ b/lib/models/search.dart @@ -19,7 +19,7 @@ class SearchProvider with ChangeNotifier { searchResult.clear(); int searchTime = DateTime.now().millisecondsSinceEpoch; - if (cacheTime + 0 <= searchTime) { + if (cacheTime + cacheDuring <= searchTime) { g1WalletsBox.clear(); final url = Uri.parse('https://g1-stats.axiom-team.fr/data/forbes.json'); final response = await http.get(url); diff --git a/lib/models/wallets_profiles.dart b/lib/models/wallets_profiles.dart index 62a0dfc..9b26ade 100644 --- a/lib/models/wallets_profiles.dart +++ b/lib/models/wallets_profiles.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:dubp/dubp.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -14,6 +16,7 @@ import 'package:intl/intl.dart'; import 'package:truncate/truncate.dart'; import 'package:crypto/crypto.dart'; import 'package:fast_base58/fast_base58.dart'; +import 'package:http/http.dart' as http; class WalletsProfilesProvider with ChangeNotifier { WalletsProfilesProvider(this.pubkey); @@ -254,4 +257,20 @@ class WalletsProfilesProvider with ChangeNotifier { String generateIdenticon(String _pubkey) { return Jdenticon.toSvg(_pubkey); } + + Future getBalance(String _pubkey) async { + num balance; + final url = Uri.parse( + '$endPointGVA?query={%20balance(script:%20%22$_pubkey%22)%20{%20amount%20base%20}%20}'); + final response = await http.get(url); + final result = json.decode(response.body); + + if (result['data']['balance'] == null) { + balance = 0.0; + } else { + balance = removeDecimalZero(result['data']['balance']['amount'] / 100); + } + + return balance; + } } diff --git a/lib/screens/history.dart b/lib/screens/history.dart new file mode 100644 index 0000000..4cf5ad4 --- /dev/null +++ b/lib/screens/history.dart @@ -0,0 +1,569 @@ +import 'package:flutter/services.dart'; +import 'package:gecko/globals.dart'; +import 'package:gecko/models/cesium_plus.dart'; +import 'package:gecko/models/home.dart'; +import 'package:gecko/models/queries.dart'; +import 'package:gecko/models/wallets_profiles.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:gecko/screens/avatar_fullscreen.dart'; +import 'package:gecko/screens/wallet_view.dart'; +import 'dart:ui'; +import 'package:graphql_flutter/graphql_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.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 nRepositories = 20; + 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 : ' + _historyProvider.pubkey); + WidgetsBinding.instance.addPostFrameCallback((_) {}); + + 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), + if (_historyProvider.pubkey != '') + historyQuery(context, _historyProvider, _cesiumPlusProvider), + ])); + } + + Widget historyQuery(context, WalletsProfilesProvider _historyProvider2, + CesiumPlusProvider _cesiumPlusProvider) { + WalletsProfilesProvider _historyProvider = + Provider.of(context, listen: true); + RefreshController _refreshController = + RefreshController(initialRefresh: false); + return Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Query( + options: QueryOptions( + document: gql(getHistory), + variables: { + 'pubkey': _historyProvider.pubkey, + 'number': nRepositories, + '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: 17.0), + ) + ]); + } + + if (result.data == null && result.exception.toString() == null) { + return const Text('Aucune donnée à afficher.'); + } + + opts = _historyProvider.checkQueryResult(result, opts, pubkey); + + // Build history list + return NotificationListener( + child: Builder( + builder: (context) => Expanded( + child: SmartRefresher( + enablePullUp: false, + controller: _refreshController, + onRefresh: () { + _historyProvider.resetdHistory(); + _refreshController.refreshCompleted(); + }, + child: ListView( + key: const Key('listTransactions'), + controller: scrollController, + children: [historyView(context, result)], + ), + ), + ), + ), + onNotification: (t) { + if (t is ScrollEndNotification && + scrollController.position.pixels >= + scrollController.position.maxScrollExtent * 0.7) { + fetchMore(opts); + } + return true; + }); + }, + ), + ], + )); + } + + Widget historyView(context, result) { + WalletsProfilesProvider _historyProvider = + Provider.of(context, listen: false); + + return _historyProvider.transBC == null + ? const Text('Aucune transaction à afficher.') + : Column(children: [ + getTransactionTile(context, _historyProvider), + // for (var repository in _historyProvider.transBC) + // if (repository[1].toString().split(' ')[0] == '22-11-21') + // const Text("Aujourd'hui"), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 5.0), + // child: ListTile( + // key: Key('transaction${keyID++}'), + // contentPadding: const EdgeInsets.all(5.0), + // leading: Text(repository[1], + // style: TextStyle( + // fontSize: 12, + // color: Colors.grey[800], + // fontWeight: FontWeight.w700), + // textAlign: TextAlign.center), + // title: Text(repository[3], + // style: const TextStyle( + // fontSize: 15.0, fontFamily: 'Monospace'), + // textAlign: TextAlign.center), + // subtitle: Text(repository[6] != '' ? repository[6] : '-', + // style: const TextStyle(fontSize: 12.0), + // textAlign: TextAlign.center), + // trailing: Text("${repository[4]} Ğ1", + // style: const TextStyle(fontSize: 14.0), + // textAlign: TextAlign.justify), + // dense: true, + // isThreeLine: false, + // onTap: () { + // if (_historyProvider.isPubkey(context, repository[2])) { + // _homeProvider.currentIndex = 0; + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) { + // return const WalletViewScreen(); + // }), + // ); + // } + // Navigator.pop(context); + // }), + // ), + if (result.isLoading && + _historyProvider.pageInfo['hasPreviousPage']) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator(), + ], + ), + // if (_historyProvider.isTheEnd) // What I did before ... + 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) { + HomeProvider _homeProvider = + Provider.of(context, listen: false); + CesiumPlusProvider _cesiumPlusProvider = + Provider.of(context, listen: false); + int keyID = 0; + String dateDelimiter; + String lastDateDelimiter; + const double _avatarSize = 200; + + 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]}"; + } + log.d(dateForm); + + int weekNumber(DateTime date) { + int dayOfYear = int.parse(DateFormat("D").format(date)); + return ((dayOfYear - date.weekday + 10) / 7).floor(); + } + + if (DateTime(date.year, date.month, date.day) == + DateTime(now.year, now.month, now.day)) { + dateDelimiter = lastDateDelimiter = "Aujourd'hui"; + } else if (DateTime(date.year, date.month, date.day) == + DateTime(now.year, now.month, now.day - 1)) { + dateDelimiter = lastDateDelimiter = "Hier"; + } else if (weekNumber(date) == weekNumber(now) && + date.year == now.year && + lastDateDelimiter != "Cette semaine") { + dateDelimiter = lastDateDelimiter = "Cette semaine"; + } else if (lastDateDelimiter != monthsInYear[date.month] && + lastDateDelimiter != "${monthsInYear[date.month]} ${date.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]} Ğ1", + style: const TextStyle( + fontSize: 18, fontWeight: FontWeight.w500), + textAlign: TextAlign.justify), + dense: false, + isThreeLine: false, + onTap: () { + if (_historyProvider.isPubkey(context, repository[2])) { + _homeProvider.currentIndex = 0; + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return const WalletViewScreen(); + }), + ); + } + 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 ?? _historyProvider.pubkey)); + _historyProvider.snackCopyKey(context); + }, + child: Text( + _historyProvider.getShortPubkey( + pubkey ?? _historyProvider.pubkey), + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.w800, + ), + ), + ), + ]), + const SizedBox(height: 10), + if (username == null) + Query( + options: QueryOptions( + document: gql(getId), + variables: { + 'pubkey': _historyProvider.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) + 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()} Ğ1", + 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( + _historyProvider.pubkey, _avatarSize), + builder: + (BuildContext context, AsyncSnapshot _avatar) { + if (_avatar.connectionState != ConnectionState.done || + _avatar.hasError) { + return Stack(children: [ + ClipOval( + child: + _cesiumPlusProvider.defaultAvatar(_avatarSize), + ), + Positioned( + top: 16.5, + right: 47.5, + width: 55, + height: 55, + child: CircularProgressIndicator( + strokeWidth: 6, + 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: _avatar.data, + ), + ); + } + 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/old_history_pay.dart b/lib/screens/old_history_pay.dart index 581251e..f470db1 100644 --- a/lib/screens/old_history_pay.dart +++ b/lib/screens/old_history_pay.dart @@ -16,7 +16,7 @@ import 'package:provider/provider.dart'; import 'package:flutter_svg/flutter_svg.dart'; // ignore: must_be_immutable -class HistoryScreen extends StatelessWidget with ChangeNotifier { +class OldHistoryScreen extends StatelessWidget with ChangeNotifier { final TextEditingController _outputPubkey = TextEditingController(); ScrollController scrollController = ScrollController(); final nRepositories = 20; @@ -29,7 +29,7 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier { FetchMoreOptions opts; final GlobalKey _scaffoldKey = GlobalKey(); - HistoryScreen({Key key}) : super(key: key); + OldHistoryScreen({Key key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/screens/search_result.dart b/lib/screens/search_result.dart index 0fc216e..01d2efd 100644 --- a/lib/screens/search_result.dart +++ b/lib/screens/search_result.dart @@ -14,9 +14,10 @@ class SearchResultScreen extends StatelessWidget { @override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); - SearchProvider _searchProvider = Provider.of(context); + SearchProvider _searchProvider = + Provider.of(context, listen: false); CesiumPlusProvider _cesiumPlusProvider = - Provider.of(context); + Provider.of(context, listen: false); WalletsProfilesProvider _walletsProfilesClass = Provider.of(context, listen: false); diff --git a/lib/screens/wallet_view.dart b/lib/screens/wallet_view.dart index a625d0e..6821bfe 100644 --- a/lib/screens/wallet_view.dart +++ b/lib/screens/wallet_view.dart @@ -5,8 +5,9 @@ import 'package:flutter/material.dart'; import 'package:gecko/models/cesium_plus.dart'; import 'package:gecko/models/wallets_profiles.dart'; import 'package:gecko/models/queries.dart'; -// import 'package:gecko/models/wallet_options.dart'; import 'package:gecko/screens/avatar_fullscreen.dart'; +import 'package:gecko/screens/common_elements.dart'; +import 'package:gecko/screens/history.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:provider/provider.dart'; @@ -21,11 +22,9 @@ class WalletViewScreen extends StatelessWidget { Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); WalletsProfilesProvider _historyProvider = - Provider.of(context); + Provider.of(context, listen: false); CesiumPlusProvider _cesiumPlusProvider = - Provider.of(context); - // WalletOptionsProvider _walletOptions = WalletOptionsProvider(); - double _avatarSize = 150; + Provider.of(context, listen: false); return Scaffold( appBar: AppBar( @@ -65,172 +64,7 @@ class WalletViewScreen extends StatelessWidget { ), body: SafeArea( child: 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.symmetric(horizontal: 30), - child: Row(children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row(children: [ - GestureDetector( - key: const Key('copyPubkey'), - onTap: () { - Clipboard.setData(ClipboardData( - text: pubkey ?? _historyProvider.pubkey)); - _historyProvider.snackCopyKey(context); - }, - child: Text( - _historyProvider.getShortPubkey( - pubkey ?? _historyProvider.pubkey), - style: const TextStyle( - fontSize: 30, - fontWeight: FontWeight.w800, - ), - ), - ), - ]), - const SizedBox(height: 10), - if (username == null) - Query( - options: QueryOptions( - document: gql(getId), - variables: { - 'pubkey': _historyProvider.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) - Text( - username, - style: const TextStyle( - fontSize: 27, - color: Color(0xff814C00), - ), - ), - const SizedBox(height: 25), - FutureBuilder( - future: _cesiumPlusProvider - .getName(_historyProvider.pubkey), - initialData: '...', - builder: (context, snapshot) { - return SizedBox( - width: 230, - child: Text( - snapshot.data ?? '-', - style: const TextStyle( - fontSize: 18, color: Colors.black), - ), - ); - }), - const SizedBox(height: 30), - ]), - const Spacer(), - Column(children: [ - if (avatar == null) - FutureBuilder( - future: _cesiumPlusProvider.getAvatar( - _historyProvider.pubkey, _avatarSize), - builder: (BuildContext context, - AsyncSnapshot _avatar) { - if (_avatar.connectionState != - ConnectionState.done || - _avatar.hasError) { - return Stack(children: [ - ClipOval( - child: _cesiumPlusProvider - .defaultAvatar(_avatarSize), - ), - Positioned( - top: 16.5, - right: 47.5, - width: 55, - height: 55, - child: CircularProgressIndicator( - strokeWidth: 6, - 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: _avatar.data, - ), - ); - } - 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), - ]), - ]), - ), - ), + headerProfileView(context, _historyProvider, _cesiumPlusProvider), SizedBox(height: isTall ? 60 : 30), Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column(children: [ @@ -249,7 +83,16 @@ class WalletViewScreen extends StatelessWidget { 'assets/walletOptions/clock.png'), height: 90)), onTap: () { - null; + Navigator.push( + context, + FaderTransition( + page: HistoryScreen( + pubkey: pubkey ?? _historyProvider.pubkey, + username: username, + avatar: avatar, + ), + isFast: false), + ); }), ), ), @@ -352,4 +195,176 @@ class WalletViewScreen extends StatelessWidget { ]), )); } + + 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.start, children: < + Widget>[ + Row(children: [ + GestureDetector( + key: const Key('copyPubkey'), + onTap: () { + Clipboard.setData( + ClipboardData(text: pubkey ?? _historyProvider.pubkey)); + _historyProvider.snackCopyKey(context); + }, + child: Text( + _historyProvider + .getShortPubkey(pubkey ?? _historyProvider.pubkey), + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.w800, + ), + ), + ), + ]), + const SizedBox(height: 10), + if (username == null) + Query( + options: QueryOptions( + document: gql(getId), + variables: { + 'pubkey': _historyProvider.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) + Text( + username, + style: const TextStyle( + fontSize: 27, + color: Color(0xff814C00), + ), + ), + const SizedBox(height: 25), + FutureBuilder( + future: _cesiumPlusProvider.getName(_historyProvider.pubkey), + initialData: '...', + builder: (context, snapshot) { + return SizedBox( + width: 230, + child: Text( + snapshot.data ?? '-', + style: + const TextStyle(fontSize: 18, color: Colors.black), + ), + ); + }), + const SizedBox(height: 30), + ]), + const Spacer(), + Column(children: [ + if (avatar == null) + FutureBuilder( + future: _cesiumPlusProvider.getAvatar( + _historyProvider.pubkey, _avatarSize), + builder: + (BuildContext context, AsyncSnapshot _avatar) { + if (_avatar.connectionState != ConnectionState.done || + _avatar.hasError) { + return Stack(children: [ + ClipOval( + child: + _cesiumPlusProvider.defaultAvatar(_avatarSize), + ), + Positioned( + top: 16.5, + right: 47.5, + width: 55, + height: 55, + child: CircularProgressIndicator( + strokeWidth: 6, + 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: _avatar.data, + ), + ); + } + 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/pubspec.lock b/pubspec.lock index 68af98a..b646b7f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -885,6 +885,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.0" + pull_to_refresh: + dependency: "direct main" + description: + name: pull_to_refresh + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" qr: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 249c17f..89b6d3d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: Pay with G1. # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.3+9 +version: 0.0.3+10 environment: sdk: ">=2.7.0 <3.0.0" @@ -56,6 +56,7 @@ dependencies: truncate: ^3.0.1 unorm_dart: ^0.2.0 xml: ^5.3.0 + pull_to_refresh: ^2.0.0 flutter_icons: android: "ic_launcher"