Skip to content
Snippets Groups Projects
Commit 9a83df3d authored by poka's avatar poka
Browse files

Remove states management, keep just history pagination mechanic, clean code.

parent 7652b8e6
No related branches found
No related tags found
No related merge requests found
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;
}
......@@ -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<HistoryListScreen>
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: <Widget>[
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: <Widget>[
Query(
options: QueryOptions(
document: gql(getHistory),
variables: <String, dynamic>{
'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<dynamic> blockchainTX =
(result.data['txsHistoryBc']['both']['edges']
as List<dynamic>);
// final List<dynamic> mempoolTX =
// (result.data['txsHistoryBc']['both']['edges']
// as List<dynamic>);
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<dynamic> repos = [
...previousResultData['txsHistoryBc']['both']
['edges'] as List<dynamic>,
...fetchMoreResultData['txsHistoryBc']['both']
['edges'] as List<dynamic>
];
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: <Widget>[
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: <Widget>[
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: <Widget>[
CircularProgressIndicator(),
],
),
],
),
);
},
),
],
)),
],
children: masterHome,
),
),
floatingActionButton: Container(
......@@ -279,17 +46,125 @@ class _HistoryListScreenState extends State<HistoryListScreen>
)));
}
// Future checkNode() async {
// final response = await Dio().post(graphqlEndpoint);
// showHistory(response);
// return response;
// }
List<Widget> get masterHome {
return <Widget>[
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: <Widget>[
Query(
options: QueryOptions(
document: gql(getHistory),
variables: <String, dynamic>{
'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<dynamic> blockchainTX =
(result.data['txsHistoryBc']['both']['edges'] as List<dynamic>);
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<dynamic> repos = [
...previousResultData['txsHistoryBc']['both']['edges']
as List<dynamic>,
...fetchMoreResultData['txsHistoryBc']['both']['edges']
as List<dynamic>
];
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<HistoryListScreen>
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 '';
}
}
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";
}
return '';
}
}
class HistoryListView extends StatelessWidget {
const HistoryListView(
{Key key,
@required ScrollController scrollController,
@required this.transBC,
@required this.historyData})
: _scrollController = scrollController,
super(key: key);
// 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");
// }
// }
final ScrollController _scrollController;
final List transBC;
final historyData;
@override
Widget build(BuildContext context) {
return ListView(
controller: _scrollController,
children: <Widget>[
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: <Widget>[
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: <Widget>[
CircularProgressIndicator(),
],
),
],
);
}
}
......@@ -11,15 +11,13 @@ class Gecko extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _httpLink = HttpLink(
'http://127.0.0.1:30901/gva',
// defaultHeaders: <String, String>{
// '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,
),
);
......
......@@ -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"
......
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment