Add Rust binding; Tab views; ListTile;

This commit is contained in:
poka 2021-01-06 05:04:54 +01:00
parent 14ad52b9ae
commit 35df9f8734
10 changed files with 426 additions and 140 deletions

View File

@ -0,0 +1 @@
include ':app'

View File

@ -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<QueryResult> 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<Widget> screens;
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
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: <Widget>[
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<Widget> get masterHome {
return <Widget>[
SizedBox(height: 20),
Widget historyScreen() {
return Column(children: <Widget>[
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: <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(),
],
),
],
);
}
}

View File

@ -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<void> 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(),
),
);
}

View File

@ -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);

View File

@ -46,7 +46,7 @@ const String getHistory = r'''
}
''';
const String getxBalance = r'''
const String getBalance = r'''
query ($pubkey: String!) {
balance(script: "$pubkey") {
amount

105
lib/ui/generateWallets.dart Normal file
View File

@ -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<GenerateWalletScreen> {
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: <Widget>[
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;
});
}
}

View File

@ -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<HistoryListScreen> {
// @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: <Widget>[
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: <Widget>[
CircularProgressIndicator(),
],
),
],
),
// onNotification: (t) {
// if (t is ScrollEndNotification) {
// // fetchMore(opts);
// print(_scrollController.position.pixels);
// }
// return t;
// },
);
}
}

View File

@ -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"

View File

@ -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:

View File

@ -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"