Optimize payments: Use direct mnemonic or cesium seed instead of dewif unlocking; Add screen to choose a wallet other than default wallet for payment; Can restore chest from settings

This commit is contained in:
poka 2021-12-30 00:51:04 +01:00
parent f05c335073
commit 24d2ca5d0a
15 changed files with 608 additions and 275 deletions

View File

@ -1,3 +1,6 @@
import 'dart:typed_data';
import 'package:durt/durt.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:async'; import 'dart:async';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
@ -6,6 +9,8 @@ import 'package:gecko/models/wallet_data.dart';
class MyWalletsProvider with ChangeNotifier { class MyWalletsProvider with ChangeNotifier {
List<WalletData> listWallets = []; List<WalletData> listWallets = [];
late String pinCode; late String pinCode;
late String mnemonic;
late Uint8List cesiumSeed;
int? pinLenght; int? pinLenght;
int? getCurrentChest() { int? getCurrentChest() {
@ -16,6 +21,24 @@ class MyWalletsProvider with ChangeNotifier {
return configBox.get('currentChest'); return configBox.get('currentChest');
} }
String dewifToMnemonic(context, WalletData _wallet, String _pin) {
String _mnemonic;
try {
String _localDewif = chestBox.get(_wallet.chest)!.dewif!;
_mnemonic = Dewif()
.mnemonicFromDewif(_localDewif, _pin.toUpperCase(), lang: appLang);
} on ChecksumException catch (e) {
log.e(e.cause);
return 'bad';
} catch (e) {
// _homeProvider.playSound('non', 0.6);
log.e('ERROR READING FILE: $e');
return 'bad';
}
return _mnemonic;
}
bool checkIfWalletExist() { bool checkIfWalletExist() {
if (chestBox.isEmpty) { if (chestBox.isEmpty) {
log.i('No wallets detected'); log.i('No wallets detected');

View File

@ -4,11 +4,11 @@ import 'package:durt/durt.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/providers/my_wallets.dart'; import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/screens/wallet_view.dart'; import 'package:gecko/screens/wallet_view.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:jdenticon_dart/jdenticon_dart.dart'; import 'package:jdenticon_dart/jdenticon_dart.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:qrscan/qrscan.dart' as scanner; import 'package:qrscan/qrscan.dart' as scanner;
import 'dart:math'; import 'dart:math';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@ -59,29 +59,32 @@ class WalletsProfilesProvider with ChangeNotifier {
return barcode; return barcode;
} }
Future<String> pay(BuildContext context, String pinCode) async { Future<String> pay(BuildContext context, {int? derivation}) async {
MyWalletsProvider _myWalletModel = MyWalletsProvider(); MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
int? currentChest = configBox.get('currentChest'); int? currentChest = configBox.get('currentChest');
WalletData? defaultWallet = _myWalletModel.getDefaultWallet(currentChest); String result;
String dewif = chestBox.get(currentChest)!.dewif!;
int? derivation;
if (chestBox.get(currentChest)!.isCesium!) { if (chestBox.get(currentChest)!.isCesium!) {
derivation = -1; result = await Gva(node: endPointGVA).pay(
recipient: pubkey!,
amount: double.parse(payAmount.text),
cesiumSeed: _myWalletProvider.cesiumSeed,
comment: payComment.text,
derivation: -1,
lang: appLang);
} else { } else {
derivation = defaultWallet!.derivation; derivation ??=
_myWalletProvider.getDefaultWallet(currentChest)!.derivation!;
result = await Gva(node: endPointGVA).pay(
recipient: pubkey!,
amount: double.parse(payAmount.text),
mnemonic: _myWalletProvider.mnemonic,
comment: payComment.text,
derivation: derivation,
lang: appLang);
} }
String result = await Gva(node: endPointGVA).pay(
recipient: pubkey!,
amount: double.parse(payAmount.text),
dewif: dewif,
password: pinCode,
comment: payComment.text,
derivation: derivation,
lang: appLang);
return result; return result;
} }

View File

@ -218,30 +218,28 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
return ((dayOfYear - date.weekday + 10) / 7).floor(); return ((dayOfYear - date.weekday + 10) / 7).floor();
} }
if (DateTime(date.year, date.month, date.day) == final transactionDate = DateTime(date.year, date.month, date.day);
DateTime(now.year, now.month, now.day) && final todayDate = DateTime(now.year, now.month, now.day);
!isTody) { final yesterdayDate = DateTime(now.year, now.month, now.day - 1);
if (transactionDate == todayDate && !isTody) {
dateDelimiter = lastDateDelimiter = "Aujourd'hui"; dateDelimiter = lastDateDelimiter = "Aujourd'hui";
isTody = true; isTody = true;
} else if (DateTime(date.year, date.month, date.day) == } else if (transactionDate == yesterdayDate && !isYesterday) {
DateTime(now.year, now.month, now.day - 1) &&
!isYesterday) {
dateDelimiter = lastDateDelimiter = "Hier"; dateDelimiter = lastDateDelimiter = "Hier";
isYesterday = true; isYesterday = true;
} else if (weekNumber(date) == weekNumber(now) && } else if (weekNumber(date) == weekNumber(now) &&
date.year == now.year && date.year == now.year &&
lastDateDelimiter != "Cette semaine" && lastDateDelimiter != "Cette semaine" &&
DateTime(date.year, date.month, date.day) != transactionDate != yesterdayDate &&
DateTime(now.year, now.month, now.day - 1) && transactionDate != todayDate &&
!isThisWeek) { !isThisWeek) {
dateDelimiter = lastDateDelimiter = "Cette semaine"; dateDelimiter = lastDateDelimiter = "Cette semaine";
isThisWeek = true; isThisWeek = true;
} else if (lastDateDelimiter != monthsInYear[date.month] && } else if (lastDateDelimiter != monthsInYear[date.month] &&
lastDateDelimiter != "${monthsInYear[date.month]} ${date.year}" && lastDateDelimiter != "${monthsInYear[date.month]} ${date.year}" &&
DateTime(date.year, date.month, date.day) != transactionDate != todayDate &&
DateTime(now.year, now.month, now.day) && transactionDate != yesterdayDate &&
DateTime(date.year, date.month, date.day) !=
DateTime(now.year, now.month, now.day - 1) &&
!(weekNumber(date) == weekNumber(now) && date.year == now.year)) { !(weekNumber(date) == weekNumber(now) && date.year == now.year)) {
if (date.year == now.year) { if (date.year == now.year) {
dateDelimiter = lastDateDelimiter = monthsInYear[date.month]; dateDelimiter = lastDateDelimiter = monthsInYear[date.month];

View File

@ -65,13 +65,11 @@ class HomeScreen extends StatelessWidget {
); );
}, },
), ),
ListTile( // ListTile(
title: const Text('A propos'), // title: const Text('A propos'),
onTap: () { // onTap: () {
// Update the state of the app. // },
// ... // ),
},
),
])), ])),
Align( Align(
alignment: FractionalOffset.bottomCenter, alignment: FractionalOffset.bottomCenter,

View File

@ -16,7 +16,6 @@ import 'package:provider/provider.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart';
int _nbrLinesName = 1;
bool _isNewNameValid = false; bool _isNewNameValid = false;
class CesiumWalletOptions extends StatelessWidget { class CesiumWalletOptions extends StatelessWidget {
@ -47,13 +46,6 @@ class CesiumWalletOptions extends StatelessWidget {
cesiumWallet.name = _walletOptions.nameController.text; cesiumWallet.name = _walletOptions.nameController.text;
} }
_walletOptions.nameController.text.length >= 15
? _nbrLinesName = 2
: _nbrLinesName = 1;
if (_walletOptions.nameController.text.length >= 26 && isTall) {
_nbrLinesName = 3;
}
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
_walletOptions.isEditing = false; _walletOptions.isEditing = false;
@ -102,36 +94,40 @@ class CesiumWalletOptions extends StatelessWidget {
const Color(0xfffafafa), const Color(0xfffafafa),
], ],
)), )),
child: Row(children: <Widget>[ child: Row(
const SizedBox(width: 25), crossAxisAlignment: CrossAxisAlignment.start,
InkWell( mainAxisAlignment: MainAxisAlignment.spaceAround,
onTap: () async { children: <Widget>[
File newAvatar = await (_walletOptions.changeAvatar()); const Spacer(flex: 1),
cesiumWallet.imageFile = newAvatar; InkWell(
_walletOptions.reloadBuild(); onTap: () async {
}, File newAvatar =
child: cesiumWallet.imageFile == null await (_walletOptions.changeAvatar());
? Image.asset(
'assets/chests/${cesiumWallet.imageName}',
width: 110,
)
: Image.file(cesiumWallet.imageFile!, width: 110),
),
InkWell(
onTap: () async {
File newAvatar = await (_walletOptions.changeAvatar());
cesiumWallet.imageFile = newAvatar; cesiumWallet.imageFile = newAvatar;
_walletOptions.reloadBuild(); _walletOptions.reloadBuild();
}, },
child: Column(children: <Widget>[ child: cesiumWallet.imageFile == null
Image.asset( ? Image.asset(
'assets/walletOptions/camera.png', 'assets/chests/${cesiumWallet.imageName}',
height: 40, width: 110,
), )
const SizedBox(height: 80) : Image.file(cesiumWallet.imageFile!, width: 110),
])), ),
Column(children: <Widget>[ InkWell(
Row(children: <Widget>[ onTap: () async {
File newAvatar =
await (_walletOptions.changeAvatar());
cesiumWallet.imageFile = newAvatar;
_walletOptions.reloadBuild();
},
child: Column(children: <Widget>[
Image.asset(
'assets/walletOptions/camera.png',
height: 40,
),
const SizedBox(height: 80)
])),
const Spacer(flex: 1),
Column(children: <Widget>[ Column(children: <Widget>[
SizedBox( SizedBox(
width: 260, width: 260,
@ -141,7 +137,8 @@ class CesiumWalletOptions extends StatelessWidget {
focusNode: _walletOptions.walletNameFocus, focusNode: _walletOptions.walletNameFocus,
enabled: _walletOptions.isEditing, enabled: _walletOptions.isEditing,
controller: _walletOptions.nameController, controller: _walletOptions.nameController,
maxLines: _nbrLinesName, minLines: 1,
maxLines: 3,
textAlign: TextAlign.center, textAlign: TextAlign.center,
decoration: const InputDecoration( decoration: const InputDecoration(
border: InputBorder.none, border: InputBorder.none,
@ -151,10 +148,10 @@ class CesiumWalletOptions extends StatelessWidget {
contentPadding: EdgeInsets.all(15.0), contentPadding: EdgeInsets.all(15.0),
), ),
style: TextStyle( style: TextStyle(
fontSize: isTall ? 27 : 23, fontSize: isTall ? 27 : 23,
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontFamily: 'Monospace')), )),
), ),
SizedBox(height: isTall ? 5 : 0), SizedBox(height: isTall ? 5 : 0),
Query( Query(
@ -231,7 +228,6 @@ class CesiumWalletOptions extends StatelessWidget {
), ),
), ),
]), ]),
const SizedBox(width: 0),
Column(children: <Widget>[ Column(children: <Widget>[
InkWell( InkWell(
key: const Key('renameWallet'), key: const Key('renameWallet'),
@ -254,10 +250,9 @@ class CesiumWalletOptions extends StatelessWidget {
const SizedBox( const SizedBox(
height: 60, height: 60,
) )
]) ]),
const Spacer(flex: 3),
]), ]),
]),
]),
); );
}), }),
SizedBox(height: 4 * ratio), SizedBox(height: 4 * ratio),

View File

@ -0,0 +1,222 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:provider/provider.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
// ignore: must_be_immutable
class ChooseWalletScreen extends StatelessWidget {
ChooseWalletScreen({Key? key}) : super(key: key);
int? _derivation;
List<int?>? _selectedId;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
WalletsProfilesProvider _walletsProfilesProvider =
Provider.of<WalletsProfilesProvider>(context);
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Choix du portefeuille source'),
)),
body: SafeArea(
child: Stack(children: [
myWalletsTiles(context),
Positioned.fill(
bottom: 60,
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 470,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () async {
final resultPay = await _walletsProfilesProvider
.pay(context, derivation: _derivation);
await paymentsResult(context, resultPay);
},
child: const Text(
'Valider le paiement',
style:
TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
),
),
),
// const SizedBox(height: 160),
]),
));
}
Widget myWalletsTiles(BuildContext context) {
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context);
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
_selectedId ??= defaultWallet!.id();
_derivation ??= defaultWallet!.derivation!;
_myWalletProvider.readAllWallets(configBox.get('currentChest'));
if (!isWalletsExists) {
return const Text('');
}
if (_myWalletProvider.listWallets.isEmpty) {
return Column(children: const <Widget>[
Center(
child: Text(
'Veuillez générer votre premier portefeuille',
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500),
)),
]);
}
List _listWallets = _myWalletProvider.listWallets;
final double screenWidth = MediaQuery.of(context).size.width;
int nTule = 2;
if (screenWidth >= 900) {
nTule = 4;
} else if (screenWidth >= 650) {
nTule = 3;
}
return CustomScrollView(slivers: <Widget>[
const SliverToBoxAdapter(child: SizedBox(height: 20)),
SliverGrid.count(
key: const Key('listWallets'),
crossAxisCount: nTule,
childAspectRatio: 1,
crossAxisSpacing: 0,
mainAxisSpacing: 0,
children: <Widget>[
for (WalletData _repository in _listWallets as Iterable<WalletData>)
Padding(
padding: const EdgeInsets.all(16),
child: GestureDetector(
onTap: () {
_derivation = _repository.derivation!;
_selectedId = _repository.id();
_myWalletProvider.rebuildWidget();
},
child: ClipOvalShadow(
shadow: const Shadow(
color: Colors.transparent,
offset: Offset(0, 0),
blurRadius: 5,
),
clipper: CustomClipperOval(),
child: ClipRRect(
borderRadius:
const BorderRadius.all(Radius.circular(12)),
child: Column(children: <Widget>[
Expanded(
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
gradient: RadialGradient(
radius: 0.6,
colors: [
Colors.green[400]!,
const Color(0xFFE7E7A6),
],
)),
child: _repository.imageFile == null
? Image.asset(
'assets/avatars/${_repository.imageName}',
alignment: Alignment.bottomCenter,
scale: 0.5,
)
: Image.file(
_repository.imageFile!,
alignment: Alignment.bottomCenter,
scale: 0.5,
),
)),
ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(12),
),
),
tileColor: _repository.id()[1] == _selectedId![1]
? orangeC
: const Color(0xffFFD58D),
title: Center(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 5),
child: Text(
_repository.name!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 17.0,
color:
_repository.id()[1] == _selectedId![1]
? const Color(0xffF9F9F1)
: Colors.black,
fontStyle: FontStyle.italic),
),
),
),
onTap: () {
_derivation = _repository.derivation!;
_selectedId = _repository.id();
_myWalletProvider.rebuildWidget();
},
)
]),
),
),
)),
]),
]);
}
}
Future<bool?> paymentsResult(context, String resultPay) {
if (resultPay != "success") log.e(resultPay);
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text(resultPay == "success"
? 'Paiement effecuté avec succès !'
: "Une erreur s'est produite lors du paiement:\n$resultPay"),
content: const SingleChildScrollView(child: Text('')),
actions: <Widget>[
TextButton(
child: const Text("OK"),
onPressed: () {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
},
),
],
);
},
);
}

View File

@ -0,0 +1,44 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
// ignore: must_be_immutable
class TransactionCommentScreen extends StatelessWidget {
TextEditingController tplController = TextEditingController();
TransactionCommentScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Confirmer le paiement'),
),
),
body: SafeArea(
child: Column(children: <Widget>[
const SizedBox(height: 20),
TextField(
enabled: true,
controller: tplController,
maxLines: 1,
textAlign: TextAlign.center,
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(15.0),
),
style: const TextStyle(
fontSize: 22.0,
color: Colors.black,
fontWeight: FontWeight.w400)),
const SizedBox(height: 20),
]),
));
}
}

View File

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:durt/durt.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/providers/wallets_profiles.dart';
@ -8,6 +9,7 @@ import 'package:gecko/providers/wallet_options.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/screens/myWallets/cesium_wallet_options.dart'; import 'package:gecko/screens/myWallets/cesium_wallet_options.dart';
import 'package:gecko/screens/myWallets/choose_chest.dart'; import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:gecko/screens/myWallets/choose_wallet.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart'; import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:pin_code_fields/pin_code_fields.dart'; import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -26,7 +28,6 @@ class UnlockingWallet extends StatelessWidget {
final formKey = GlobalKey<FormState>(); final formKey = GlobalKey<FormState>();
Color? pinColor = const Color(0xffF9F9F1); Color? pinColor = const Color(0xffF9F9F1);
var walletPin = ''; var walletPin = '';
String? resultPay;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -201,20 +202,38 @@ class UnlockingWallet extends StatelessWidget {
onCompleted: (_pin) async { onCompleted: (_pin) async {
log.d("Completed"); log.d("Completed");
_myWalletProvider.pinCode = _pin; _myWalletProvider.pinCode = _pin;
final String? resultWallet = _walletOptions.readLocalWallet(
context, wallet!, _pin.toUpperCase(), _pinLenght); if (currentChest.isCesium!) {
try {
String _localDewif = chestBox.get(wallet!.chest)!.dewif!;
final cesiumWallet =
CesiumWallet.fromDewif(_localDewif, _pin.toUpperCase());
_walletOptions.pubkey.text = cesiumWallet.pubkey;
_myWalletProvider.cesiumSeed = cesiumWallet.seed;
_myWalletProvider.mnemonic = 'cesium';
} catch (e) {
log.e(e);
_myWalletProvider.mnemonic = 'bad';
}
} else {
_myWalletProvider.mnemonic = _myWalletProvider.dewifToMnemonic(
context, wallet!, _pin.toUpperCase());
}
// final String? resultWallet = _walletOptions.readLocalWallet(
// context, wallet!, _pin.toUpperCase(), _pinLenght);
// _myWalletProvider.pinCode = _pin.toUpperCase(); // _myWalletProvider.pinCode = _pin.toUpperCase();
_myWalletProvider.pinLenght = _pinLenght; _myWalletProvider.pinLenght = _pinLenght;
if (resultWallet == 'bad') { if (_myWalletProvider.mnemonic == 'bad') {
await Future.delayed(const Duration(milliseconds: 50));
errorController.add(ErrorAnimationType errorController.add(ErrorAnimationType
.shake); // Triggering error shake animation .shake); // Triggering error shake animation
pinColor = Colors.red[600]; pinColor = Colors.red[600];
_myWalletProvider.pinCode = _myWalletProvider.mnemonic = '';
_walletOptions.reloadBuild(); _walletOptions.reloadBuild();
pinFocus.requestFocus(); pinFocus.requestFocus();
} else { } else {
pinColor = Colors.green[400]; pinColor = Colors.green[400];
// await Future.delayed(Duration(milliseconds: 50));
if (action == "mywallets") { if (action == "mywallets") {
currentChest.isCesium! currentChest.isCesium!
? Navigator.push( ? Navigator.push(
@ -223,17 +242,25 @@ class UnlockingWallet extends StatelessWidget {
return CesiumWalletOptions( return CesiumWalletOptions(
cesiumWallet: currentChest); cesiumWallet: currentChest);
}), }),
) ).then((value) => _myWalletProvider.mnemonic = '')
: Navigator.push( : Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return const WalletsHome(); return const WalletsHome();
}), }),
); ).then((value) => _myWalletProvider.cesiumSeed.clear());
} else if (action == "pay") { } else if (action == "pay") {
resultPay = if (currentChest.isCesium!) {
await _historyProvider.pay(context, _pin.toUpperCase()); final resultPay = await _historyProvider.pay(context);
await _paymentsResult(context); await paymentsResult(context, resultPay);
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ChooseWalletScreen();
}),
);
}
} }
} }
}, },
@ -245,31 +272,4 @@ class UnlockingWallet extends StatelessWidget {
)), )),
); );
} }
Future<bool?> _paymentsResult(context) {
if (resultPay != "success") log.i(resultPay);
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text(resultPay == "success"
? 'Paiement effecuté avec succès !'
: "Une erreur s'est produite lors du paiement:\n$resultPay"),
content: const SingleChildScrollView(child: Text('')),
actions: <Widget>[
TextButton(
child: const Text("OK"),
onPressed: () {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
},
),
],
);
},
);
}
} }

View File

@ -83,17 +83,15 @@ class WalletOptions extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[ children: <Widget>[
const Spacer(), const Spacer(flex: 1),
avatar(walletProvider), avatar(walletProvider),
const Spacer(), const Spacer(flex: 1),
Column(children: <Widget>[ Column(children: <Widget>[
walletName(walletProvider, _walletOptions), walletName(walletProvider, _walletOptions),
SizedBox(height: isTall ? 5 : 0), SizedBox(height: isTall ? 5 : 0),
balance(walletProvider), balance(walletProvider),
]), ]),
const Spacer(), const Spacer(flex: 3),
const Spacer(),
const Spacer(),
]), ]),
); );
}), }),

View File

@ -1,3 +1,4 @@
import 'package:durt/durt.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
@ -29,6 +30,7 @@ class WalletsHome extends StatelessWidget {
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
myWalletProvider.pinCode = myWalletProvider.mnemonic = '';
Navigator.popUntil( Navigator.popUntil(
context, context,
ModalRoute.withName('/'), ModalRoute.withName('/'),
@ -41,6 +43,7 @@ class WalletsHome extends StatelessWidget {
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () { onPressed: () {
myWalletProvider.pinCode = myWalletProvider.mnemonic = '';
Navigator.popUntil( Navigator.popUntil(
context, context,
ModalRoute.withName('/'), ModalRoute.withName('/'),
@ -177,8 +180,11 @@ class WalletsHome extends StatelessWidget {
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
_walletOptions.readLocalWallet(context, _repository, // _walletOptions.readLocalWallet(context, _repository,
_myWalletProvider.pinCode, pinLength); // _myWalletProvider.pinCode, pinLength);
_walletOptions.pubkey.text =
HdWallet.fromMnemonic(_myWalletProvider.mnemonic)
.getPubkey(_repository.derivation!);
Navigator.push( Navigator.push(
context, context,
SmoothTransition( SmoothTransition(
@ -264,11 +270,15 @@ class WalletsHome extends StatelessWidget {
), ),
// dense: true, // dense: true,
onTap: () { onTap: () {
_walletOptions.readLocalWallet( // _walletOptions.readLocalWallet(
context, // context,
_repository, // _repository,
_myWalletProvider.pinCode, // _myWalletProvider.pinCode,
pinLength); // pinLength);
_walletOptions.pubkey.text =
HdWallet.fromMnemonic(
_myWalletProvider.mnemonic)
.getPubkey(_repository.derivation!);
Navigator.push( Navigator.push(
context, context,
SmoothTransition( SmoothTransition(

View File

@ -6,6 +6,7 @@ import 'package:gecko/screens/myWallets/generate_wallets.dart';
import 'dart:io'; import 'dart:io';
import 'package:gecko/screens/myWallets/import_cesium_wallet.dart'; import 'package:gecko/screens/myWallets/import_cesium_wallet.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/screens/myWallets/restore_chest.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class SettingsScreen extends StatelessWidget { class SettingsScreen extends StatelessWidget {
@ -39,43 +40,74 @@ class SettingsScreen extends StatelessWidget {
body: Column(children: <Widget>[ body: Column(children: <Widget>[
const SizedBox(height: 40), const SizedBox(height: 40),
SizedBox( SizedBox(
height: 70, height: 70,
width: 500, width: 500,
child: ElevatedButton( child: ElevatedButton(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
elevation: 5, elevation: 5,
primary: yellowC, // background primary: yellowC, // background
onPrimary: Colors.black, // foreground onPrimary: Colors.black, // foreground
), ),
onPressed: () => Navigator.push( onPressed: () => Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return const ImportWalletScreen(); return const ImportWalletScreen();
}), }),
).then((value) => { ).then((value) => {
if (value == true) {Navigator.pop(context)} if (value == true) {Navigator.pop(context)}
}), }),
child: const Text("Importer un portefeuille Cesium", child: const Text(
style: TextStyle(fontSize: 16)))), "Importer un portefeuille Cesium",
style: TextStyle(fontSize: 16),
),
),
),
const SizedBox(height: 30), const SizedBox(height: 30),
SizedBox( SizedBox(
height: 70, height: 70,
width: 500, width: 500,
child: ElevatedButton( child: ElevatedButton(
key: const Key('generateKeychain'), key: const Key('generateKeychain'),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
elevation: 5, elevation: 5,
primary: yellowC, // background primary: yellowC, // background
onPrimary: Colors.black, // foreground onPrimary: Colors.black, // foreground
), ),
onPressed: () => Navigator.push( onPressed: () => Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return GenerateFastChestScreen(); return GenerateFastChestScreen();
}), }),
), ),
child: const Text("Générer un nouveau trousseau", child: const Text(
style: TextStyle(fontSize: 16)))), "Générer un nouveau trousseau",
style: TextStyle(fontSize: 16),
),
),
),
const SizedBox(height: 30),
SizedBox(
height: 70,
width: 500,
child: ElevatedButton(
key: const Key('generateKeychain'),
style: ElevatedButton.styleFrom(
elevation: 5,
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const RestoreChest();
}),
),
child: const Text(
"Restaurer un coffre",
style: TextStyle(fontSize: 16),
),
),
),
Expanded( Expanded(
child: Align( child: Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,

View File

@ -31,6 +31,8 @@ class WalletViewScreen extends StatelessWidget {
CesiumPlusProvider _cesiumPlusProvider = CesiumPlusProvider _cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false); Provider.of<CesiumPlusProvider>(context, listen: false);
_historyProvider.pubkey = pubkey!;
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
appBar: AppBar( appBar: AppBar(
@ -185,7 +187,8 @@ class WalletViewScreen extends StatelessWidget {
// WalletsProfilesProvider _walletViewProvider = // WalletsProfilesProvider _walletViewProvider =
// Provider.of<WalletsProfilesProvider>(context); // Provider.of<WalletsProfilesProvider>(context);
const double shapeSize = 20; const double shapeSize = 20;
MyWalletsProvider _myWalletProvider = MyWalletsProvider(); MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
WalletData? defaultWallet = WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest')); _myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
@ -199,111 +202,120 @@ class WalletViewScreen extends StatelessWidget {
isScrollControlled: true, isScrollControlled: true,
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return Padding( return StatefulBuilder(
padding: EdgeInsets.only( builder: (BuildContext context, StateSetter setState) {
bottom: MediaQuery.of(context).viewInsets.bottom), return Padding(
child: Container( padding: EdgeInsets.only(
height: 400, bottom: MediaQuery.of(context).viewInsets.bottom),
decoration: const ShapeDecoration( child: Container(
color: Color(0xffffeed1), height: 400,
shape: RoundedRectangleBorder( decoration: const ShapeDecoration(
borderRadius: BorderRadius.only( color: Color(0xffffeed1),
topRight: Radius.circular(shapeSize), shape: RoundedRectangleBorder(
topLeft: Radius.circular(shapeSize), borderRadius: BorderRadius.only(
topRight: Radius.circular(shapeSize),
topLeft: Radius.circular(shapeSize),
),
), ),
), ),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'Effectuer un virement',
style: TextStyle(
fontSize: 26, fontWeight: FontWeight.w700),
),
const SizedBox(height: 20),
Text(
'Saisissez dans le champ ci-dessous le montant à virer.',
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const Spacer(),
Center(
child: Column(children: <Widget>[
TextField(
controller: _walletViewProvider.payAmount,
autofocus: true,
maxLines: 1,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
onChanged: (_) => setState(() {}),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp(r'^\d+\.?\d{0,2}')),
],
// onChanged: (v) => _searchProvider.rebuildWidget(),
decoration: InputDecoration(
hintText: '0.00',
suffix: const Text('Ğ1'),
filled: true,
fillColor: Colors.transparent,
// border: OutlineInputBorder(
// borderSide:
// BorderSide(color: Colors.grey[500], width: 2),
// borderRadius: BorderRadius.circular(8)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey[500]!, width: 2),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.all(20),
),
style: const TextStyle(
fontSize: 40,
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 40),
// const Spacer(),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed:
_walletViewProvider.payAmount.text != ''
? () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UnlockingWallet(
wallet: defaultWallet,
action: "pay");
},
),
);
}
: null,
child: const Text(
'Effectuer le virement',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600),
),
),
),
const SizedBox(height: 20),
]),
),
]),
),
), ),
child: Padding( );
padding: const EdgeInsets.all(24), });
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'Effectuer un virement',
style: TextStyle(
fontSize: 26, fontWeight: FontWeight.w700),
),
const SizedBox(height: 20),
Text(
'Saisissez dans le champ ci-dessous le montant à virer de ... vers ...',
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const Spacer(),
Center(
child: Column(children: <Widget>[
TextField(
controller: _walletViewProvider.payAmount,
autofocus: true,
maxLines: 1,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp(r'^\d+\.?\d{0,2}')),
],
// onChanged: (v) => _searchProvider.rebuildWidget(),
decoration: InputDecoration(
hintText: '0.00',
suffix: const Text('Ğ1'),
filled: true,
fillColor: Colors.transparent,
// border: OutlineInputBorder(
// borderSide:
// BorderSide(color: Colors.grey[500], width: 2),
// borderRadius: BorderRadius.circular(8)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey[500]!, width: 2),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.all(20),
),
style: const TextStyle(
fontSize: 40,
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 40),
// const Spacer(),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UnlockingWallet(
wallet: defaultWallet, action: "pay");
},
),
);
},
child: const Text(
'Effectuer le virement',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w600),
),
),
),
const SizedBox(height: 20),
]),
),
]),
),
),
);
}).then((value) => _walletViewProvider.payAmount.text = ''); }).then((value) => _walletViewProvider.payAmount.text = '');
} }

View File

@ -301,7 +301,7 @@ packages:
name: durt name: durt
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.5+7" version: "0.1.6"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:

View File

@ -5,7 +5,7 @@ description: Pay with G1.
# pub.dev using `pub publish`. This is preferred for private packages. # pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.4+6 version: 0.0.4+8
environment: environment:
sdk: '>=2.12.0 <3.0.0' sdk: '>=2.12.0 <3.0.0'
@ -62,7 +62,7 @@ dependencies:
pull_to_refresh: ^2.0.0 pull_to_refresh: ^2.0.0
dio: ^4.0.4 dio: ^4.0.4
desktop_window: ^0.4.0 desktop_window: ^0.4.0
durt: ^0.1.5+7 durt: ^0.1.6
package_info_plus: ^1.3.0 package_info_plus: ^1.3.0
flutter_icons: flutter_icons:

View File

@ -13,8 +13,6 @@ echo "Nom du build final: ${APPNAME}-${VERSION}+${BUILD}.apk"
## To build Rust dependancies ## To build Rust dependancies
# cargo br # cargo br
echo "To compile Rust binding, exec: cargo br"
flutter clean flutter clean
if [[ $1 == "bundle" ]]; then if [[ $1 == "bundle" ]]; then
flutter build appbundle --release --target-platform android-arm,android-arm64 --build-name $VERSION --build-number $BUILD flutter build appbundle --release --target-platform android-arm,android-arm64 --build-name $VERSION --build-number $BUILD