diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/lib/home.dart b/lib/home.dart index 4461c53..62a4a58 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -1,22 +1,96 @@ import 'package:flutter/material.dart'; +import 'package:qrscan/qrscan.dart' as scanner; +import 'package:gecko/ui/generateWallets.dart'; +import 'package:gecko/ui/historyWallets.dart'; import 'dart:async'; import 'dart:typed_data'; import 'dart:ui'; -import 'package:permission_handler/permission_handler.dart'; -import 'package:qrscan/qrscan.dart' as scanner; import 'package:graphql_flutter/graphql_flutter.dart'; -import 'api.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'parsingGVA.dart'; import 'query.dart'; +import 'package:sentry/sentry.dart' as sentry; + +// method to call from widget to fetchmore queries +typedef FetchMore = dynamic Function(FetchMoreOptions options); + +typedef Refetch = Future Function(); + +typedef QueryBuilder = Widget Function( + QueryResult result, { + Refetch refetch, + FetchMore fetchMore, +}); //ignore: must_be_immutable -class HistoryListScreen extends StatelessWidget with ChangeNotifier { +class HomeScreen extends StatefulWidget { + // const HistoryListScreen({ + // final Key key, + // @required this.options, + // @required this.builder, + // }) : super(key: key); + + // final QueryOptions options; + // final QueryBuilder builder; + + HomeScreen({this.screens}); + + static const Tag = "HistoryListScreen"; + final List screens; + + @override + _HomeScreenState createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + int _currentIndex = 0; + Widget currentScreen; + + void onTabTapped(int index) { + setState(() { + _currentIndex = index; + }); + } + Uint8List bytes = Uint8List(0); + final TextEditingController _outputPubkey = new TextEditingController(); - final nRepositories = 3; - String pubkey = 'D2meevcAHFTS2gQMvmRW5Hzi25jDdikk4nC4u1FkwRaU'; // For debug - bool isBuilding = true; // Just for debug + + final nRepositories = 20; + + // String pubkey = 'D2meevcAHFTS2gQMvmRW5Hzi25jDdikk4nC4u1FkwRaU'; // For debug + String pubkey = ''; + bool isBuilding = true; ScrollController _scrollController = new ScrollController(); + _scrollListener() { + if (_scrollController.offset >= + _scrollController.position.maxScrollExtent && + !_scrollController.position.outOfRange) { + setState(() { + print("reach the bottom"); + }); + } + } + + @override + void initState() { + // TODO: implement 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); + // } + // }); + } + @override Widget build(BuildContext context) { print('Build pubkey : ' + pubkey); @@ -24,31 +98,52 @@ class HistoryListScreen extends StatelessWidget with ChangeNotifier { print('isBuilding: ' + isBuilding.toString()); return MaterialApp( home: Scaffold( - backgroundColor: Colors.grey[300], - body: SafeArea( - child: Column( - children: masterHome, - ), - ), - floatingActionButton: Container( - height: 80.0, - width: 80.0, - child: FittedBox( - child: FloatingActionButton( - onPressed: () => _scan(), - child: Container( - height: 40.0, - width: 40.0, - child: Image.asset('images/scanner.png')), - backgroundColor: Color.fromARGB(500, 204, 255, 255), - ), - ), - ))); + backgroundColor: Colors.grey[300], + body: SafeArea( + child: IndexedStack( + index: _currentIndex, + children: [ + historyScreen(), + GenerateWalletScreen(), + // FriendsScreen() + ], + ), + ), + floatingActionButton: Container( + height: 80.0, + width: 80.0, + child: FittedBox( + child: FloatingActionButton( + onPressed: () => _scan(), + child: Container( + height: 40.0, + width: 40.0, + child: Image.asset('images/scanner.png')), + backgroundColor: Color.fromARGB(500, 204, 255, 255), + ), + ), + ), + bottomNavigationBar: BottomNavigationBar( + fixedColor: Colors.black, + type: BottomNavigationBarType.fixed, + onTap: onTabTapped, + currentIndex: _currentIndex, + items: [ + BottomNavigationBarItem( + icon: new Icon(Icons.format_list_bulleted), + label: 'HOME', + ), + BottomNavigationBarItem( + icon: new Icon(Icons.settings), + label: 'GENERATE WALLET', + ) + ], + ), + )); } - List get masterHome { - return [ - SizedBox(height: 20), + Widget historyScreen() { + return Column(children: [ TextField( onChanged: (text) { print("Clé tappxé: $text"); @@ -73,7 +168,7 @@ class HistoryListScreen extends StatelessWidget with ChangeNotifier { color: Colors.black, fontWeight: FontWeight.bold)), historyQuery(), - ]; + ]); } Expanded historyQuery() { @@ -113,8 +208,7 @@ class HistoryListScreen extends StatelessWidget with ChangeNotifier { final Map pageInfo = result.data['txsHistoryBc']['both']['pageInfo']; - final String fetchMoreCursor = - pageInfo['endCursor'] ?? 'cest null...'; + final String fetchMoreCursor = pageInfo['endCursor']; FetchMoreOptions opts = FetchMoreOptions( variables: {'cursor': fetchMoreCursor}, @@ -131,17 +225,31 @@ class HistoryListScreen extends StatelessWidget with ChangeNotifier { }, ); - _scrollController - ..addListener(() { - if (_scrollController.position.pixels == - _scrollController.position.maxScrollExtent) { - if (!result.isLoading) { - print( - "DEBUG H fetchMoreCursor in scrollController: $fetchMoreCursor"); - fetchMore(opts); - } - } - }); + // _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); print( "###### DEBUG H Parse blockchainTX list. Cursor: $fetchMoreCursor ######"); @@ -161,7 +269,16 @@ class HistoryListScreen extends StatelessWidget with ChangeNotifier { Future _scan() async { await Permission.camera.request(); - String barcode = await scanner.scan(); + String barcode; + try { + barcode = await scanner.scan(); + } catch (e, stack) { + print(e); + await sentry.Sentry.captureException( + e, + stackTrace: stack, + ); + } // this._outputPubkey.text = ""; if (barcode != null) { this._outputPubkey.text = barcode; @@ -183,91 +300,13 @@ class HistoryListScreen extends StatelessWidget with ChangeNotifier { pubkey.length < 45) { print("C'est une pubkey !!!"); + setState(() { + this.pubkey = pubkey; + }); + return pubkey; } 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(), - ], - ), - ], - ); - } -} diff --git a/lib/main.dart b/lib/main.dart index 0344393..053b0dd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,20 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -// import 'package:image_gallery_saver/image_gallery_saver.dart'; -// import 'package:flutter_html_view'; import 'home.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; -void main() => runApp(Gecko()); +// void main() => runApp(Gecko()); + +Future main() async { + await SentryFlutter.init( + (options) { + options.dsn = + 'https://c09587b46eaa42e8b9fda28d838ed180@o496840.ingest.sentry.io/5572110'; + }, + appRunner: () => runApp(Gecko()), + ); +} class Gecko extends StatelessWidget { @override @@ -27,7 +36,7 @@ class Gecko extends StatelessWidget { ThemeData(primaryColor: Colors.blue[50], accentColor: Colors.black), home: GraphQLProvider( client: _client, - child: HistoryListScreen(), + child: HomeScreen(), ), ); } diff --git a/lib/api.dart b/lib/parsingGVA.dart similarity index 88% rename from lib/api.dart rename to lib/parsingGVA.dart index f0c499d..d8821ce 100644 --- a/lib/api.dart +++ b/lib/parsingGVA.dart @@ -1,10 +1,6 @@ import 'dart:math'; import 'package:intl/intl.dart'; -// Configure node -const graphqlEndpoint = "https://g1.librelois.fr/gva"; -// const graphqlEndpoint = 'http://192.168.1.91:10060/gva'; - List parseHistory(txs) { var transBC = []; int i = 0; @@ -21,7 +17,7 @@ List parseHistory(txs) { transBC[i] = []; final dateBrut = DateTime.fromMillisecondsSinceEpoch(transaction['writtenTime'] * 1000); - final DateFormat formatter = DateFormat('dd-MM-yy - H:M'); + final DateFormat formatter = DateFormat('dd-MM-yy - HH:mm'); final date = formatter.format(dateBrut); transBC[i].add(transaction['writtenTime']); transBC[i].add(date); diff --git a/lib/query.dart b/lib/query.dart index 7009608..96daef9 100644 --- a/lib/query.dart +++ b/lib/query.dart @@ -46,7 +46,7 @@ const String getHistory = r''' } '''; -const String getxBalance = r''' +const String getBalance = r''' query ($pubkey: String!) { balance(script: "$pubkey") { amount diff --git a/lib/ui/generateWallets.dart b/lib/ui/generateWallets.dart new file mode 100644 index 0000000..3aa16dd --- /dev/null +++ b/lib/ui/generateWallets.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:dubp/dubp.dart'; +import 'package:sentry/sentry.dart' as sentry; + +class GenerateWalletScreen extends StatefulWidget { + @override + _GenerateWalletScreen createState() => _GenerateWalletScreen(); +} + +class _GenerateWalletScreen extends State { + void initState() { + super.initState(); + DubpRust.setup(); + } + + TextEditingController _mnemonic = new TextEditingController(); + TextEditingController _pubkey = new TextEditingController(); + TextEditingController _dewif = new TextEditingController(); + TextEditingController _pin = new TextEditingController(); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Column(children: [ + TextField( + enabled: false, + controller: this._mnemonic, + maxLines: 2, + textAlign: TextAlign.center, + decoration: InputDecoration(), + style: TextStyle( + fontSize: 15.0, + color: Colors.black, + fontWeight: FontWeight.bold)), + TextField( + enabled: false, + controller: this._pubkey, + maxLines: 1, + textAlign: TextAlign.center, + decoration: InputDecoration(), + style: TextStyle( + fontSize: 14.0, + color: Colors.black, + fontWeight: FontWeight.bold)), + TextField( + enabled: false, + controller: this._dewif, + maxLines: 3, + textAlign: TextAlign.center, + decoration: InputDecoration(), + style: TextStyle(fontSize: 12.0, color: Colors.red)), + TextField( + enabled: false, + controller: this._pin, + maxLines: 1, + textAlign: TextAlign.center, + decoration: InputDecoration(), + style: TextStyle( + fontSize: 20.0, + color: Colors.black, + fontWeight: FontWeight.bold)), + new RaisedButton( + onPressed: () => generateMnemonic(), + child: Text('Générer un wallet', style: TextStyle(fontSize: 20))), + ])); + } + + Future generateMnemonic() async { + String generatedMnemonic; + try { + generatedMnemonic = await DubpRust.genMnemonic(language: Language.french); + } catch (e, stack) { + print(e); + await sentry.Sentry.captureException( + e, + stackTrace: stack, + ); + } + + setState(() { + this._mnemonic.text = generatedMnemonic; + }); + generateWallet(generatedMnemonic); + } + + Future generateWallet(generatedMnemonic) async { + NewWallet newWallet; + try { + newWallet = await DubpRust.genWalletFromMnemonic( + language: Language.french, mnemonic: generatedMnemonic); + } catch (e, stack) { + print(e); + await sentry.Sentry.captureException( + e, + stackTrace: stack, + ); + } + + setState(() { + this._pubkey.text = newWallet.publicKey; + this._dewif.text = newWallet.dewif; + this._pin.text = newWallet.pin; + }); + } +} diff --git a/lib/ui/historyWallets.dart b/lib/ui/historyWallets.dart new file mode 100644 index 0000000..75ce4df --- /dev/null +++ b/lib/ui/historyWallets.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:truncate/truncate.dart'; + +// class HistoryListScreen extends StatefulWidget { +// @override +// _HistoryListScreen createState() => _HistoryListScreen(); +// } + +// class _HistoryListScreen extends State { +// @override +// Widget build(BuildContext context) { +// print('Coucou page 2'); + +// return MaterialApp( +// home: Scaffold( +// backgroundColor: Colors.grey[300], +// body: SafeArea(child: Text('Hello !')))); +// } +// } + +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 SafeArea( + // new NotificationListener( + // child: new ListView( + // controller: _scrollController, + // ), + // onNotification: (t) { + // if (t is ScrollEndNotification) { + // fetchMore(opts); + // } + // }, + // ); + + // child: new NotificationListener( + child: new ListView( + controller: _scrollController, + children: [ + for (var repository in transBC) + ListTile( + contentPadding: const EdgeInsets.all(5.0), + leading: Text(repository[3].toString()), + title: Text(repository[1].toString() + + '\n' + + truncate(repository[2].toString(), 17, + omission: "...", position: TruncatePosition.end)), + subtitle: Text(repository[5].toString()), + dense: true, + // enabled: _act == 2, + onTap: () {/* TODO: Load this history */}), + if (historyData.isLoading) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator(), + ], + ), + ], + ), + // onNotification: (t) { + // if (t is ScrollEndNotification) { + // // fetchMore(opts); + // print(_scrollController.position.pixels); + // } + // return t; + // }, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 0ae649b..0a25695 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -296,6 +296,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0-nullsafety.3" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4" normalize: dependency: transitive description: @@ -303,6 +310,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.5" + package_info: + dependency: transitive + description: + name: package_info + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.3+2" path: dependency: transitive description: @@ -394,6 +408,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.13" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.2+3" qrscan: dependency: "direct main" description: @@ -408,6 +429,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.24.1" + sentry: + dependency: transitive + description: + name: sentry + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + sentry_flutter: + dependency: "direct main" + description: + name: sentry_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" sky_engine: dependency: transitive description: flutter @@ -455,6 +490,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.19-nullsafety.2" + truncate: + dependency: "direct main" + description: + name: truncate + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" typed_data: dependency: transitive description: @@ -462,6 +504,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0-nullsafety.3" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.2" uuid_enhanced: dependency: transitive description: @@ -513,4 +562,4 @@ packages: version: "2.2.1" sdks: dart: ">=2.10.0-110 <2.11.0" - flutter: ">=1.12.13+hotfix.5 <2.0.0" + flutter: ">=1.17.0 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index b3637d4..1bc65e7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,9 @@ dependencies: image_gallery_saver: image_picker: graphql_flutter: ^4.0.0-beta.6 #^3.1.0 + provider: ^4.3.2+3 + truncate: ^2.1.2 + sentry_flutter: ^4.0.1 flutter_icons: diff --git a/scripts/build-apk.sh b/scripts/build-apk.sh index 7dc3af0..c8f992f 100755 --- a/scripts/build-apk.sh +++ b/scripts/build-apk.sh @@ -1,5 +1,4 @@ #!/bin/bash - # [[ -z $1 ]] && echo "Please choose a version." && exit 1 fVersion=$(grep "version: " pubspec.yaml | awk '{ print $2 }') @@ -11,7 +10,10 @@ ori_app="app.apk" echo "Nom du build final: ${APPNAME}-${VERSION}+${BUILD}.apk" -flutter build apk --split-per-abi --build-name $VERSION --build-number $BUILD +#flutter build apk --split-per-abi --build-name $VERSION --build-number $BUILD +flutter clean +flutter build apk --split-per-abi --target-platform android-arm,android-arm64 --build-name $VERSION --build-number $BUILD + if [[ -d $HOME/Téléchargements ]]; then DL="$HOME/Téléchargements"