From 9a83df3d00f71e8b9bb482ce5507f65b4f63a688 Mon Sep 17 00:00:00 2001 From: poka Date: Fri, 1 Jan 2021 21:47:43 +0100 Subject: [PATCH] Remove states management, keep just history pagination mechanic, clean code. --- lib/api.dart | 259 +------------------------------ lib/home.dart | 489 ++++++++++++++++++++++++---------------------------------- lib/main.dart | 8 +- pubspec.lock | 20 +-- pubspec.yaml | 7 +- 5 files changed, 216 insertions(+), 567 deletions(-) diff --git a/lib/api.dart b/lib/api.dart index 93170bc..f0c499d 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -1,260 +1,11 @@ import 'dart:math'; -import "package:dio/dio.dart" as dio; -import 'package:gql/language.dart' as gqlLang; -import 'package:gql_dio_link/gql_dio_link.dart'; -import 'package:gql_exec/gql_exec.dart'; -import "package:gql_link/gql_link.dart"; import 'package:intl/intl.dart'; // Configure node -// const graphqlEndpoint = "https://g1.librelois.fr/gva"; -const graphqlEndpoint = 'http://127.0.0.1:10060/gva'; - -// // Check node connection -// Future getHttp() async { -// try { -// final client = await dio.Dio().get(graphqlEndpoint); -// print(client); -// return 0; -// } catch (e) { -// print(e); -// return e; -// } -// } - -// Build queries -Future buildQ(query) async { - var client; - try { - client = dio.Dio(); - print(client); - } catch (e) { - print(e); - } - // final client = dio.Dio(); - Link link; - link = DioLink( - graphqlEndpoint, - client: client, - ); - - try { - final res = await link - .request(Request( - operation: Operation(document: gqlLang.parseString(query)), - )) - .first; - return res; - } catch (e) { - print("Erreur: Noeud injoingnable."); - return 2; - } -} - -/* Requests functions */ - -// Get current UD -Future getUD() async { - const query = """{ - currentUd { - amount - base - } - }"""; - - final result = await buildQ(query); - return result.data["currentUd"]["amount"]; -} - -// Get balance -Future getBalance(String pubkey) async { - var query = """{ - balance(script: "$pubkey") { - amount - base - } - }"""; - - final result = await buildQ(query); - return result.data["balance"]["amount"] / 100; -} - -// // Get history -// Future getHistory(String pubkey) async { -// print(pubkey); -// var number = 20; -// var query = """{ -// txsHistoryBc( -// pubkeyOrScript: "$pubkey" -// pagination: { pageSize: $number, ord: DESC } -// ) { -// both { -// pageInfo { -// hasPreviousPage -// hasNextPage -// startCursor -// endCursor -// } -// edges { -// direction -// node { -// currency -// issuers -// outputs -// comment -// writtenTime -// } -// } -// } -// } -// txsHistoryMp(pubkey: "$pubkey") { -// receiving { -// currency -// issuers -// comment -// outputs -// writtenTime -// } -// sending { -// currency -// issuers -// comment -// outputs -// writtenTime -// } -// } -// currentUd { -// amount -// base -// } -// }"""; - -// final res = await buildQ(query); - -// // Parse history -// var resBC, resMP; -// print(res.toString()); -// try { -// resBC = res.data["txsHistoryBc"]['both']['edges']; -// resMP = res.data["txsHistoryMp"]; -// } catch (e) { -// return false; -// } -// var i = 0; -// // String outPubkey; -// var transBC = []; -// final currentBase = res.data['currentUd']['base']; -// final currentUD = res.data['currentUd']['amount'] / 100; - -// // Get tx blockchain -// for (final trans in resBC) { -// var direction = trans['direction']; - -// print(trans); -// final transaction = trans['node']; -// var output = transaction['outputs'][0]; - -// print("DEBUG1 " + transaction['writtenTime'].toString()); -// transBC.add(i); -// transBC[i] = []; -// transBC[i].add(transaction['writtenTime']); -// var amountBrut = int.parse(output.split(':')[0]); -// final base = int.parse(output.split(':')[1]); -// final applyBase = base - currentBase; -// final amount = amountBrut * pow(10, applyBase) / 100; -// var amountUD = amount / currentUD; -// if (direction == "RECEIVED") { -// transBC[i].add(transaction['issuers'][0]); -// transBC[i].add(amount); -// transBC[i].add(amountUD.toStringAsFixed(2)); -// } else if (direction == "SENT") { -// final outPubkey = output.split("SIG(")[1].replaceAll(')', ''); -// transBC[i].add(outPubkey); -// transBC[i].add(-amount); -// transBC[i].add(amountUD.toStringAsFixed(2)); -// } -// transBC[i].add(transaction['comment']); -// transBC[i].add(base); - -// i++; -// } - -// // Get tx mempool -// var transMP = []; -// i = 0; -// for (var transaction in resMP['receiving']) { -// if (transMP == null) { -// break; -// } -// var output = transaction['outputs'][0]; -// var outPubkey = output.split("SIG(")[1].replaceAll(')', ''); -// transMP.add(i); -// transMP[i] = []; -// transMP[i].add(transaction['writtenTime']); -// transMP[i].add(transaction['issuers'][0]); -// var amountBrut = int.parse(output.split(':')[0]); -// final base = int.parse(output.split(':')[1]); -// final applyBase = base - currentBase; -// final amount = amountBrut * pow(10, applyBase) / 100; -// transMP[i].add(amount); -// final amountUD = amount / currentUD; -// transMP[i].add(amountUD.toStringAsFixed(2)); -// transMP[i].add(transaction['comment']); -// transMP[i].add(base); -// transMP[i].add(outPubkey); - -// i++; -// } - -// transMP = []; -// i = 0; -// for (var transaction in resMP['sending']) { -// if (transMP == null) { -// break; -// } -// var output = transaction['outputs'][0]; -// var outPubkey = output.split("SIG(")[1].replaceAll(')', ''); -// transMP.add(i); -// transMP[i] = []; -// transMP[i].add(transaction['writtenTime']); -// transMP[i].add(transaction['issuers'][0]); -// var amountBrut = int.parse(output.split(':')[0]); -// final base = int.parse(output.split(':')[1]); -// final applyBase = base - currentBase; -// final amount = amountBrut * pow(10, applyBase) / 100; -// transMP[i].add(-amount); -// final amountUD = amount / currentUD; -// transMP[i].add(amountUD.toStringAsFixed(2)); -// transMP[i].add(transaction['comment']); -// transMP[i].add(base); -// transMP[i].add(outPubkey); - -// i++; -// } - -// // Order transactions by date -// transBC.sort((b, a) => Comparable.compare(a[0], b[0])); -// transMP.sort((b, a) => Comparable.compare(a[0], b[0])); - -// // // Keep only base if there is base change -// // var lastBase = 0; -// // for (i in trans) { -// // if (i[5] == lastBase){ -// // i[6] = null; -// // } -// // else { -// // lastBase = i[6]; -// // } - -// // print(trans); -// return [transBC, transMP]; -// } - -// NEW WAY // +const graphqlEndpoint = "https://g1.librelois.fr/gva"; +// const graphqlEndpoint = 'http://192.168.1.91:10060/gva'; List parseHistory(txs) { - // print(blockchainTX[0]['node']['comment']); - var transBC = []; int i = 0; @@ -263,12 +14,9 @@ List parseHistory(txs) { for (final trans in txs) { var direction = trans['direction']; - - // print(trans); final transaction = trans['node']; var output = transaction['outputs'][0]; - print("DEBUG comment: " + transaction['comment'].toString()); transBC.add(i); transBC[i] = []; final dateBrut = @@ -277,6 +25,8 @@ List parseHistory(txs) { final date = formatter.format(dateBrut); transBC[i].add(transaction['writtenTime']); transBC[i].add(date); + print( + "DEBUG date et comment: ${date.toString()} -- ${transaction['comment'].toString()}"); var amountBrut = int.parse(output.split(':')[0]); final base = int.parse(output.split(':')[1]); final applyBase = base - currentBase; @@ -298,6 +48,5 @@ List parseHistory(txs) { } // transBC.sort((b, a) => Comparable.compare(a[0], b[0])); - return transBC; } diff --git a/lib/home.dart b/lib/home.dart index 7ae2b59..4461c53 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -4,263 +4,30 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:permission_handler/permission_handler.dart'; import 'package:qrscan/qrscan.dart' as scanner; -import 'api.dart'; -// import "package:dio/dio.dart"; import 'package:graphql_flutter/graphql_flutter.dart'; +import 'api.dart'; import 'query.dart'; //ignore: must_be_immutable -class HistoryListScreen extends StatefulWidget { - @override - _HistoryListScreenState createState() => _HistoryListScreenState(); -} - -class _HistoryListScreenState extends State - with ChangeNotifier { +class HistoryListScreen extends StatelessWidget with ChangeNotifier { Uint8List bytes = Uint8List(0); - TextEditingController _outputPubkey; - TextEditingController _outputBalance; + final TextEditingController _outputPubkey = new TextEditingController(); final nRepositories = 3; - var pubkey = ''; + String pubkey = 'D2meevcAHFTS2gQMvmRW5Hzi25jDdikk4nC4u1FkwRaU'; // For debug bool isBuilding = true; // Just for debug ScrollController _scrollController = new ScrollController(); @override - initState() { - super.initState(); - this._outputPubkey = new TextEditingController(); - this._outputBalance = new TextEditingController(); - // checkNode().then((result) { - // setState(() { - // _result = result; - // }); - // }); - } - - @override Widget build(BuildContext context) { - pubkey = 'D2meevcAHFTS2gQMvmRW5Hzi25jDdikk4nC4u1FkwRaU'; - - // var pubkey = ''; - print('Build state : ' + pubkey); + print('Build pubkey : ' + pubkey); + print('Build this.pubkey : ' + this.pubkey); print('isBuilding: ' + isBuilding.toString()); return MaterialApp( home: Scaffold( backgroundColor: Colors.grey[300], - body: Container( + body: SafeArea( child: Column( - children: [ - SizedBox(height: 20), - TextField( - // enabled: false, - onChanged: (text) { - print("Clé tappxé: $text"); - pubkey = text; - // pubkey = - isPubkey(text); - }, - controller: this._outputPubkey, - maxLines: 1, - textAlign: TextAlign.center, - decoration: InputDecoration( - hintText: 'Tappez/Collez une clé publique, ou scannez', - hintStyle: TextStyle(fontSize: 15), - contentPadding: - EdgeInsets.symmetric(horizontal: 7, vertical: 15), - border: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - ), - style: TextStyle( - fontSize: 15.0, - color: Colors.black, - fontWeight: FontWeight.bold)), - TextField( - // Affichage balance - enabled: false, - controller: this._outputBalance, - maxLines: 1, - textAlign: TextAlign.center, - decoration: InputDecoration( - hintText: '', - hintStyle: TextStyle(fontSize: 15), - contentPadding: - EdgeInsets.symmetric(horizontal: 7, vertical: 15), - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - disabledBorder: InputBorder.none, - ), - style: TextStyle(fontSize: 30.0, color: Colors.black)), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Query( - options: QueryOptions( - document: gql(getHistory), - variables: { - 'pubkey': pubkey, // pubkey, - 'number': nRepositories, - // set cursor to null so as to start at the beginning - // 'cursor': null - }, - ), - builder: (QueryResult result, - {refetch, FetchMore fetchMore}) { - if (result.isLoading && result.data == null) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - if (result.hasException) { - return Text( - '\nErrors: \n ' + result.exception.toString()); - } - - if (result.data == null && - result.exception.toString() == null) { - return const Text('Both data and errors are null'); - } - - final List blockchainTX = - (result.data['txsHistoryBc']['both']['edges'] - as List); - - // final List mempoolTX = - // (result.data['txsHistoryBc']['both']['edges'] - // as List); - - final Map pageInfo = - result.data['txsHistoryBc']['both']['pageInfo']; - - final String fetchMoreCursor = - pageInfo['endCursor'] ?? 'cest null...'; - - FetchMoreOptions opts = FetchMoreOptions( - variables: {'cursor': fetchMoreCursor}, - updateQuery: - (previousResultData, fetchMoreResultData) { - // this is where you combine your previous data and response - // in this case, we want to display previous repos plus next repos - // so, we combine data in both into a single list of repos - final List repos = [ - ...previousResultData['txsHistoryBc']['both'] - ['edges'] as List, - ...fetchMoreResultData['txsHistoryBc']['both'] - ['edges'] as List - ]; - - fetchMoreResultData['txsHistoryBc']['both'] - ['edges'] = repos; - print('DEBUG NULL OPTION: '); - print(fetchMoreResultData); - print(fetchMoreCursor); - return fetchMoreResultData; - }, - ); - - _scrollController - ..addListener(() { - if (_scrollController.position.pixels == - _scrollController.position.maxScrollExtent) { - if (!result.isLoading) { - print('DEBUG NULL scrollController: ' + - fetchMoreCursor); - fetchMore(opts); - } - } - }); - - print( - 'DEBUG blockchainTX: ' + blockchainTX.toString()); - List transBC = parseHistory(blockchainTX); - // parseHistory(mempoolTX); - - return Expanded( - child: ListView( - controller: _scrollController, - children: [ - for (var repository in transBC) - Card( - // 1 - elevation: 2.0, - // 2 - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(3.0)), - // 3 - child: Padding( - padding: const EdgeInsets.all(100.0), - // 4 - child: Column( - children: [ - SizedBox( - height: 8.0, - ), - Text( - // Date - repository[1].toString(), - style: TextStyle( - fontSize: 12.0, - fontWeight: FontWeight.w300, - ), - ), - Text( - // Issuer - repository[2], - style: TextStyle( - fontSize: 13.0, - fontWeight: FontWeight.w500, - ), - ), - Text( - // Amount - repository[3].toString(), - style: TextStyle( - fontSize: 15.0, - fontWeight: FontWeight.w500, - ), - ), - // Text( - // // amountUD - // repository[4].toString(), - // style: TextStyle( - // fontSize: 12.0, - // fontWeight: FontWeight.w500, - // ), - // ), - Text( - // Comment - repository[5].toString(), - style: TextStyle( - fontSize: 12.0, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), - ), - if (result.isLoading) - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CircularProgressIndicator(), - ], - ), - ], - ), - ); - }, - ), - ], - )), - ], + children: masterHome, ), ), floatingActionButton: Container( @@ -279,17 +46,125 @@ class _HistoryListScreenState extends State ))); } - // Future checkNode() async { - // final response = await Dio().post(graphqlEndpoint); - // showHistory(response); - // return response; - // } + List get masterHome { + return [ + SizedBox(height: 20), + TextField( + onChanged: (text) { + print("Clé tappxé: $text"); + this.pubkey = text; + isPubkey(text); + }, + controller: this._outputPubkey, + maxLines: 1, + textAlign: TextAlign.center, + decoration: InputDecoration( + hintText: 'Tappez/Collez une clé publique, ou scannez', + hintStyle: TextStyle(fontSize: 15), + contentPadding: EdgeInsets.symmetric(horizontal: 7, vertical: 15), + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + ), + style: TextStyle( + fontSize: 15.0, + color: Colors.black, + fontWeight: FontWeight.bold)), + historyQuery(), + ]; + } + + Expanded historyQuery() { + return Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Query( + options: QueryOptions( + document: gql(getHistory), + variables: { + 'pubkey': this.pubkey, + 'number': nRepositories, + // set cursor to null so as to start at the beginning + 'cursor': null + }, + ), + builder: (QueryResult result, {refetch, FetchMore fetchMore}) { + if (result.isLoading && result.data == null) { + return const Center( + child: CircularProgressIndicator(), + ); + } + + if (result.hasException) { + return Text('\nErrors: \n ' + result.exception.toString()); + } + + if (result.data == null && result.exception.toString() == null) { + return const Text('Both data and errors are null'); + } + + final List blockchainTX = + (result.data['txsHistoryBc']['both']['edges'] as List); + + final Map pageInfo = + result.data['txsHistoryBc']['both']['pageInfo']; + + final String fetchMoreCursor = + pageInfo['endCursor'] ?? 'cest null...'; + + FetchMoreOptions opts = FetchMoreOptions( + variables: {'cursor': fetchMoreCursor}, + 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; + }, + ); + + _scrollController + ..addListener(() { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + if (!result.isLoading) { + print( + "DEBUG H fetchMoreCursor in scrollController: $fetchMoreCursor"); + fetchMore(opts); + } + } + }); + + print( + "###### DEBUG H Parse blockchainTX list. Cursor: $fetchMoreCursor ######"); + List _transBC = parseHistory(blockchainTX); + + return Expanded( + child: HistoryListView( + scrollController: _scrollController, + transBC: _transBC, + historyData: result), + ); + }, + ), + ], + )); + } Future _scan() async { await Permission.camera.request(); String barcode = await scanner.scan(); // this._outputPubkey.text = ""; if (barcode != null) { + this._outputPubkey.text = barcode; isPubkey(barcode); } return barcode; @@ -307,46 +182,92 @@ class _HistoryListScreenState extends State pubkey.length > 42 && pubkey.length < 45) { print("C'est une pubkey !!!"); - showHistory(pubkey); - - // var tata = _scrollController; - - notifyListeners(); - - setState(() { - print('setPubkey: ' + pubkey); - pubkey = pubkey; - // // fetchMoreCursor = fetchMoreCursor; - }); return pubkey; - } else { - return ''; } + + return ''; + } +} + +class HistoryListView extends StatelessWidget { + const HistoryListView( + {Key key, + @required ScrollController scrollController, + @required this.transBC, + @required this.historyData}) + : _scrollController = scrollController, + super(key: key); + + final ScrollController _scrollController; + final List transBC; + final historyData; + + @override + Widget build(BuildContext context) { + return ListView( + controller: _scrollController, + children: [ + for (var repository in transBC) + Card( + // 1 + elevation: 2.0, + // 2 + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(3.0)), + // 3 + child: Padding( + padding: const EdgeInsets.all(100.0), + // 4 + child: Column( + children: [ + SizedBox( + height: 8.0, + ), + Text( + // Date + repository[1].toString(), + style: TextStyle( + fontSize: 12.0, + fontWeight: FontWeight.w300, + ), + ), + Text( + // Issuer + repository[2], + style: TextStyle( + fontSize: 13.0, + fontWeight: FontWeight.w500, + ), + ), + Text( + // Amount + repository[3].toString(), + style: TextStyle( + fontSize: 15.0, + fontWeight: FontWeight.w500, + ), + ), + Text( + // Comment + repository[5].toString(), + style: TextStyle( + fontSize: 12.0, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + ), + if (historyData.isLoading) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator(), + ], + ), + ], + ); } - - Future showHistory(pubkey) async { - // String pubkey = await _scan(); - if (pubkey == null) { - print('nothing return.'); - } else { - this._outputPubkey.text = ""; - this._outputBalance.text = ""; - // final udValue = await getUD(); - this._outputPubkey.text = pubkey; - final myBalance = await getBalance(pubkey.toString()); - this._outputBalance.text = myBalance.toString() + " Ğ1"; - } - } - - // Future _generateBarCode(String inputCode) async { - // if (inputCode != null && inputCode.isNotEmpty) { - // // print("Résultat du scan: " + inputCode); - // Uint8List result = await scanner.generateBarCode(inputCode); - // this.setState(() => this.bytes = result); - // } else { - // print("Veuillez renseigner une clé publique"); - // } - // } - } diff --git a/lib/main.dart b/lib/main.dart index cc3fb1f..0344393 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,15 +11,13 @@ class Gecko extends StatelessWidget { @override Widget build(BuildContext context) { final _httpLink = HttpLink( - 'http://127.0.0.1:30901/gva', - // defaultHeaders: { - // 'Content-Type': 'application/json', - // }, + // 'http://192.168.1.91:10060/gva', + 'https://g1.librelois.fr/gva', ); final _client = ValueNotifier( GraphQLClient( - cache: GraphQLCache(), + cache: GraphQLCache(store: null), link: _httpLink, ), ); diff --git a/pubspec.lock b/pubspec.lock index 50dc01d..26b71cc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -99,13 +99,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.5" - dio: - dependency: "direct main" - description: - name: dio - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.10" fake_async: dependency: transitive description: @@ -170,13 +163,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.10" - gql_dio_link: - dependency: "direct main" - description: - name: gql_dio_link - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.4" gql_error_link: dependency: transitive description: @@ -185,7 +171,7 @@ packages: source: hosted version: "0.1.1-alpha+1601131172858" gql_exec: - dependency: "direct main" + dependency: transitive description: name: gql_exec url: "https://pub.dartlang.org" @@ -199,7 +185,7 @@ packages: source: hosted version: "0.3.2" gql_link: - dependency: "direct main" + dependency: transitive description: name: gql_link url: "https://pub.dartlang.org" @@ -283,7 +269,7 @@ packages: source: hosted version: "2.2.3" intl: - dependency: "direct main" + dependency: transitive description: name: intl url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index cf4992a..28d42ed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,16 +23,11 @@ environment: dependencies: flutter: sdk: flutter + flutter_launcher_icons: "^0.8.0" qrscan: ^0.2.21 permission_handler: image_gallery_saver: image_picker: - dio: - gql_dio_link: - gql_exec: - gql_link: - intl: - flutter_launcher_icons: "^0.8.0" infinite_scroll_pagination: ^2.2.3 graphql_flutter: ^4.0.0-beta.6 #^3.1.0