2021-01-08 01:20:03 +01:00
|
|
|
import 'package:gecko/parsingGVA.dart';
|
|
|
|
import 'package:gecko/query.dart';
|
2020-12-21 01:05:00 +01:00
|
|
|
import 'package:flutter/material.dart';
|
2021-01-06 21:17:01 +01:00
|
|
|
import 'package:flutter/foundation.dart';
|
2021-01-06 05:04:54 +01:00
|
|
|
import 'package:qrscan/qrscan.dart' as scanner;
|
2020-12-21 01:05:00 +01:00
|
|
|
import 'dart:async';
|
|
|
|
import 'dart:typed_data';
|
|
|
|
import 'dart:ui';
|
2020-12-21 03:59:25 +01:00
|
|
|
import 'package:graphql_flutter/graphql_flutter.dart';
|
2021-01-06 05:04:54 +01:00
|
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
import 'package:sentry/sentry.dart' as sentry;
|
2021-01-08 01:20:03 +01:00
|
|
|
import 'package:truncate/truncate.dart';
|
2021-01-06 05:04:54 +01:00
|
|
|
|
2020-12-23 18:18:47 +01:00
|
|
|
//ignore: must_be_immutable
|
2021-01-08 00:12:22 +01:00
|
|
|
class HistoryScreen extends StatefulWidget {
|
|
|
|
const HistoryScreen({Key keyHistory}) : super(key: keyHistory);
|
2021-01-06 05:04:54 +01:00
|
|
|
|
|
|
|
@override
|
2021-01-08 00:12:22 +01:00
|
|
|
State<StatefulWidget> createState() => HistoryScreenState();
|
2021-01-06 05:04:54 +01:00
|
|
|
}
|
|
|
|
|
2021-01-08 00:12:22 +01:00
|
|
|
class HistoryScreenState extends State<HistoryScreen> {
|
2021-01-06 05:04:54 +01:00
|
|
|
Widget currentScreen;
|
|
|
|
|
2020-12-21 01:05:00 +01:00
|
|
|
Uint8List bytes = Uint8List(0);
|
2021-01-01 21:47:43 +01:00
|
|
|
final TextEditingController _outputPubkey = new TextEditingController();
|
2021-01-06 05:04:54 +01:00
|
|
|
final nRepositories = 20;
|
|
|
|
|
2021-01-08 02:10:23 +01:00
|
|
|
// String pubkey = 'D2meevcAHFTS2gQMvmRW5Hzi25jDdikk4nC4u1FkwRaU'; // For debug
|
|
|
|
String pubkey = '';
|
2021-01-06 05:04:54 +01:00
|
|
|
bool isBuilding = true;
|
2020-12-21 03:59:25 +01:00
|
|
|
ScrollController _scrollController = new ScrollController();
|
2020-12-21 01:05:00 +01:00
|
|
|
|
2021-01-06 05:04:54 +01:00
|
|
|
_scrollListener() {
|
|
|
|
if (_scrollController.offset >=
|
|
|
|
_scrollController.position.maxScrollExtent &&
|
|
|
|
!_scrollController.position.outOfRange) {
|
|
|
|
setState(() {
|
|
|
|
print("reach the bottom");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
_scrollController = ScrollController();
|
|
|
|
_scrollController.addListener(_scrollListener);
|
|
|
|
|
|
|
|
// _scrollController
|
|
|
|
// ..addListener(() {
|
|
|
|
// if (_scrollController.position.pixels ==
|
|
|
|
// _scrollController.position.maxScrollExtent) {
|
|
|
|
// // print(
|
|
|
|
// // "DEBUG H fetchMoreCursor in scrollController: $fetchMoreCursor");
|
|
|
|
// fetchMore(opts);
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
}
|
|
|
|
|
2020-12-21 01:05:00 +01:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2021-01-01 21:47:43 +01:00
|
|
|
print('Build pubkey : ' + pubkey);
|
|
|
|
print('Build this.pubkey : ' + this.pubkey);
|
2021-01-01 17:52:55 +01:00
|
|
|
print('isBuilding: ' + isBuilding.toString());
|
2021-01-10 07:49:29 +01:00
|
|
|
return Scaffold(
|
|
|
|
floatingActionButton: Container(
|
|
|
|
height: 80.0,
|
|
|
|
width: 80.0,
|
|
|
|
child: FittedBox(
|
|
|
|
child: FloatingActionButton(
|
|
|
|
heroTag: "buttonScan",
|
|
|
|
onPressed: () async {
|
|
|
|
await scan();
|
|
|
|
// print(resultScan);
|
|
|
|
// if (resultScan != 'false') {
|
|
|
|
// onTabTapped(0);
|
|
|
|
// }
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
height: 40.0,
|
|
|
|
width: 40.0,
|
|
|
|
child: Image.asset('images/scanner.png')),
|
|
|
|
backgroundColor: Color(
|
|
|
|
0xffEFEFBF), //Color(0xffFFD68E), //Color.fromARGB(500, 204, 255, 255),
|
|
|
|
),
|
2021-01-01 21:47:43 +01:00
|
|
|
),
|
2021-01-10 07:49:29 +01:00
|
|
|
),
|
|
|
|
body: Column(children: <Widget>[
|
|
|
|
SizedBox(height: 8),
|
|
|
|
TextField(
|
|
|
|
// Entrée de la pubkey
|
|
|
|
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: 14),
|
|
|
|
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: 14.0, fontWeight: FontWeight.bold)),
|
2021-01-11 19:46:20 +01:00
|
|
|
if (this.pubkey != '') historyQuery(),
|
2021-01-10 07:49:29 +01:00
|
|
|
]));
|
2021-01-01 21:47:43 +01:00
|
|
|
}
|
|
|
|
|
2021-01-08 02:10:23 +01:00
|
|
|
historyQuery() {
|
2021-01-01 21:47:43 +01:00
|
|
|
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) {
|
2021-01-11 19:46:20 +01:00
|
|
|
print('Error GVA: ' + result.exception.toString());
|
|
|
|
return Column(children: <Widget>[
|
|
|
|
SizedBox(height: 50),
|
|
|
|
Text(
|
|
|
|
"Aucun noeud GVA valide n'a pu être trouvé.\nVeuillez réessayer ultérieurement.",
|
|
|
|
style: TextStyle(fontSize: 17.0),
|
|
|
|
)
|
|
|
|
]);
|
2021-01-01 21:47:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result.data == null && result.exception.toString() == null) {
|
2021-01-11 19:46:20 +01:00
|
|
|
return const Text('Aucune donnée à afficher.');
|
2021-01-01 21:47:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
final List<dynamic> blockchainTX =
|
|
|
|
(result.data['txsHistoryBc']['both']['edges'] as List<dynamic>);
|
|
|
|
|
|
|
|
final Map pageInfo =
|
|
|
|
result.data['txsHistoryBc']['both']['pageInfo'];
|
|
|
|
|
2021-01-06 05:04:54 +01:00
|
|
|
final String fetchMoreCursor = pageInfo['endCursor'];
|
2021-01-01 21:47:43 +01:00
|
|
|
|
2021-01-09 10:48:06 +01:00
|
|
|
final num balance =
|
|
|
|
removeDecimalZero(result.data['balance']['amount'] / 100);
|
2021-01-08 02:10:23 +01:00
|
|
|
|
2021-01-01 21:47:43 +01:00
|
|
|
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;
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2021-01-06 05:04:54 +01:00
|
|
|
// _scrollController
|
|
|
|
// ..addListener(() {
|
|
|
|
// if (_scrollController.position.pixels ==
|
|
|
|
// _scrollController.position.maxScrollExtent) {
|
|
|
|
// if (!result.isLoading) {
|
|
|
|
// print(
|
|
|
|
// "DEBUG H fetchMoreCursor in scrollController: $fetchMoreCursor");
|
|
|
|
// fetchMore(opts);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
|
|
|
|
// s/o : https://stackoverflow.com/questions/54065354/how-to-detect-scroll-position-of-listview-in-flutter/54188385#54188385
|
|
|
|
// new NotificationListener(
|
|
|
|
// child: new ListView(
|
|
|
|
// controller: _scrollController,
|
|
|
|
// ),
|
|
|
|
// onNotification: (t) {
|
|
|
|
// if (t is ScrollEndNotification) {
|
|
|
|
// fetchMore(opts);
|
|
|
|
// }
|
|
|
|
// },
|
|
|
|
// );
|
|
|
|
|
|
|
|
// fetchMore(opts);
|
2021-01-01 21:47:43 +01:00
|
|
|
|
|
|
|
print(
|
|
|
|
"###### DEBUG H Parse blockchainTX list. Cursor: $fetchMoreCursor ######");
|
|
|
|
List _transBC = parseHistory(blockchainTX);
|
|
|
|
|
2021-01-08 02:10:23 +01:00
|
|
|
// Build history list
|
2021-01-01 21:47:43 +01:00
|
|
|
return Expanded(
|
2021-01-08 01:20:03 +01:00
|
|
|
child: ListView(
|
|
|
|
controller: _scrollController,
|
|
|
|
children: <Widget>[
|
2021-01-09 10:48:06 +01:00
|
|
|
SizedBox(height: 7),
|
2021-01-08 02:19:19 +01:00
|
|
|
if (this.pubkey != '')
|
|
|
|
Text(balance.toString() + ' Ğ1',
|
|
|
|
textAlign: TextAlign.center,
|
2021-01-09 09:17:01 +01:00
|
|
|
style: TextStyle(fontSize: 30.0)),
|
2021-01-09 10:48:06 +01:00
|
|
|
SizedBox(height: 12),
|
2021-01-08 01:20:03 +01:00
|
|
|
for (var repository in _transBC)
|
|
|
|
ListTile(
|
|
|
|
contentPadding: const EdgeInsets.all(5.0),
|
2021-01-09 10:48:06 +01:00
|
|
|
leading:
|
|
|
|
Text(repository[3], style: TextStyle(fontSize: 14.0)),
|
|
|
|
title: Text(
|
|
|
|
repository[1].toString() +
|
|
|
|
'\n' +
|
|
|
|
truncate(repository[2], 17,
|
|
|
|
omission: "...",
|
|
|
|
position: TruncatePosition.end),
|
|
|
|
style: TextStyle(fontSize: 14.0)),
|
|
|
|
subtitle:
|
|
|
|
Text(repository[5], style: TextStyle(fontSize: 14.0)),
|
2021-01-08 01:20:03 +01:00
|
|
|
dense: true,
|
|
|
|
onTap: () {
|
|
|
|
isPubkey(repository[2]);
|
|
|
|
}),
|
|
|
|
if (result.isLoading)
|
|
|
|
Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: <Widget>[
|
|
|
|
CircularProgressIndicator(),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
));
|
2021-01-01 21:47:43 +01:00
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
));
|
|
|
|
}
|
2020-12-21 01:05:00 +01:00
|
|
|
|
2021-01-08 00:12:22 +01:00
|
|
|
Future scan() async {
|
2020-12-21 01:05:00 +01:00
|
|
|
await Permission.camera.request();
|
2021-01-06 05:04:54 +01:00
|
|
|
String barcode;
|
|
|
|
try {
|
|
|
|
barcode = await scanner.scan();
|
|
|
|
} catch (e, stack) {
|
|
|
|
print(e);
|
2021-01-06 21:17:01 +01:00
|
|
|
if (kReleaseMode) {
|
|
|
|
await sentry.Sentry.captureException(
|
|
|
|
e,
|
|
|
|
stackTrace: stack,
|
|
|
|
);
|
|
|
|
}
|
2021-01-08 05:46:59 +01:00
|
|
|
return 'false';
|
2021-01-06 05:04:54 +01:00
|
|
|
}
|
2020-12-21 01:05:00 +01:00
|
|
|
// this._outputPubkey.text = "";
|
|
|
|
if (barcode != null) {
|
2021-01-01 21:47:43 +01:00
|
|
|
this._outputPubkey.text = barcode;
|
2020-12-21 01:05:00 +01:00
|
|
|
isPubkey(barcode);
|
2021-01-08 05:46:59 +01:00
|
|
|
} else {
|
|
|
|
return 'false';
|
2020-12-21 01:05:00 +01:00
|
|
|
}
|
|
|
|
return barcode;
|
|
|
|
}
|
|
|
|
|
2020-12-21 03:59:25 +01:00
|
|
|
String isPubkey(pubkey) {
|
2021-01-08 00:16:24 +01:00
|
|
|
final RegExp regExp = new RegExp(
|
2020-12-21 01:05:00 +01:00
|
|
|
r'^[a-zA-Z0-9]+$',
|
|
|
|
caseSensitive: false,
|
|
|
|
multiLine: false,
|
|
|
|
);
|
|
|
|
|
|
|
|
if (regExp.hasMatch(pubkey) == true &&
|
|
|
|
pubkey.length > 42 &&
|
|
|
|
pubkey.length < 45) {
|
|
|
|
print("C'est une pubkey !!!");
|
2020-12-23 18:18:47 +01:00
|
|
|
|
2021-01-06 05:04:54 +01:00
|
|
|
setState(() {
|
|
|
|
this.pubkey = pubkey;
|
2021-01-08 01:20:03 +01:00
|
|
|
this._outputPubkey.text = pubkey;
|
2021-01-06 05:04:54 +01:00
|
|
|
});
|
|
|
|
|
2021-01-08 02:10:23 +01:00
|
|
|
// setState(() {
|
|
|
|
// this._outputBalance.text = balance.toString();
|
|
|
|
// });
|
|
|
|
|
2020-12-23 18:18:47 +01:00
|
|
|
return pubkey;
|
2020-12-21 01:05:00 +01:00
|
|
|
}
|
|
|
|
|
2021-01-01 21:47:43 +01:00
|
|
|
return '';
|
2020-12-21 01:05:00 +01:00
|
|
|
}
|
2021-01-09 10:48:06 +01:00
|
|
|
|
|
|
|
num removeDecimalZero(double n) {
|
|
|
|
String result = n.toStringAsFixed(n.truncateToDouble() == n ? 0 : 1);
|
|
|
|
return num.parse(result);
|
|
|
|
}
|
2021-01-01 21:47:43 +01:00
|
|
|
}
|