Refactoring of payment workflow UX

This commit is contained in:
poka 2022-05-26 02:19:29 +02:00
parent 0009fc4009
commit 3672f4cd94
11 changed files with 259 additions and 67 deletions

View File

@ -63,10 +63,11 @@ class MyWalletsProvider with ChangeNotifier {
return _targetedWallet;
}
WalletData? getDefaultWallet(int? chest) {
WalletData? getDefaultWallet([int? chest]) {
if (chestBox.isEmpty) {
return WalletData(chest: 0, number: 0);
} else {
chest ??= getCurrentChest();
int? defaultWalletNumber = chestBox.get(chest)!.defaultWallet;
return getWalletData([chest, defaultWalletNumber]);
}

View File

@ -27,6 +27,7 @@ class SubstrateSdk with ChangeNotifier {
int blocNumber = 0;
bool isLoadingEndpoint = false;
String debugConnection = '';
String transactionStatus = '';
TextEditingController jsonKeystore = TextEditingController();
TextEditingController keystorePassword = TextEditingController();
@ -299,6 +300,8 @@ class SubstrateSdk with ChangeNotifier {
required String destAddress,
required double amount,
required String password}) async {
transactionStatus = '';
setCurrentWallet(fromAddress);
log.d(keyring.current.address);
@ -317,15 +320,31 @@ class SubstrateSdk with ChangeNotifier {
[destAddress, amount * 100],
password,
onStatusChange: (status) {
print('status: ' + status);
log.d('Transaction status: ' + status);
if (status == 'Ready') {
snack(context, 'Transaction terminé');
transactionStatus = 'sent';
notifyListeners();
// snack(context, 'Transaction terminé');
}
},
).timeout(
const Duration(seconds: 12),
onTimeout: () => {},
);
print(hash.toString());
return 'confirmed';
if (hash.isEmpty) {
transactionStatus = 'timeout';
notifyListeners();
return 'timeout';
} else {
transactionStatus = hash.toString();
notifyListeners();
return hash.toString();
}
} catch (e) {
transactionStatus = e.toString();
notifyListeners();
return e.toString();
}
}

View File

@ -275,8 +275,7 @@ Widget geckHome(context) {
height: 68 * ratio)),
onTap: () {
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(
configBox.get('currentChest'));
_myWalletProvider.getDefaultWallet();
Navigator.push(
context,
MaterialPageRoute(

View File

@ -115,7 +115,7 @@ class _ChooseChestState extends State<ChooseChest> {
onPressed: () {
configBox.put('currentChest', currentChest);
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(currentChest);
_myWalletProvider.getDefaultWallet();
_myWalletProvider.rebuildWidget();
Navigator.pushAndRemoveUntil(
context,

View File

@ -50,17 +50,7 @@ class ChooseWalletScreen extends StatelessWidget {
onPressed: () async {
Navigator.pop(context);
Navigator.pop(context);
// Payment workflow !
// final acc = _sub.getCurrentWallet();
// log.d(
// "fromAddress: ${acc.address!},destAddress: ${_walletViewProvider.outputPubkey.text}, amount: ${double.parse(_walletViewProvider.payAmount.text)}, password: $pin");
// final resultPay = await _sub.pay(context,
// fromAddress: acc.address!,
// destAddress: _walletViewProvider.outputPubkey.text,
// amount:
// double.parse(_walletViewProvider.payAmount.text),
// password: pin.toUpperCase());
// await paymentsResult(context, resultPay);
Navigator.pop(context);
},
child: const Text(
'Choisir ce portefeuille',
@ -85,7 +75,7 @@ class ChooseWalletScreen extends StatelessWidget {
Provider.of<WalletsProfilesProvider>(context, listen: false);
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(currentChest);
_myWalletProvider.getDefaultWallet();
_selectedId ??= defaultWallet!.id();
_derivation ??= defaultWallet!.derivation!;
@ -205,8 +195,10 @@ class ChooseWalletScreen extends StatelessWidget {
_selectedId = _repository.id();
chestBox.get(currentChest)!.defaultWallet =
_repository.number;
_sub.setCurrentWallet(_repository.address!);
// _myWalletProvider.rebuildWidget();
_myWalletProvider.rebuildWidget();
_walletViewProvider.reload();
_sub.reload();
},
)
@ -218,34 +210,3 @@ class ChooseWalletScreen extends StatelessWidget {
]);
}
}
Future<bool?> paymentsResult(context, String resultPay) {
final bool isValid = resultPay == "confirmed";
if (!isValid) log.e(resultPay);
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text(isValid
? '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: () async {
isValid
? await Navigator.of(context).pushNamedAndRemoveUntil(
'/',
ModalRoute.withName('/'),
)
: Navigator.pop(context);
},
),
],
);
},
);
}

View File

@ -164,10 +164,8 @@ class ConfirmStoreWallet extends StatelessWidget with ChangeNotifier {
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (context) {
return UnlockingWallet(
wallet:
_myWalletProvider.getDefaultWallet(
configBox.get('currentChest'),
),
wallet: _myWalletProvider
.getDefaultWallet(),
action: "mywallets",
);
}), ModalRoute.withName('/'));

View File

@ -8,9 +8,11 @@ import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/wallets_profiles.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/transaction_in_progress.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart';
import 'package:gecko/globals.dart';
@ -231,10 +233,26 @@ class UnlockingWallet extends StatelessWidget {
);
break;
case "pay":
// Navigator.pop(context);
// Navigator.pop(context);
// Payment workflow !
WalletsProfilesProvider _walletViewProvider =
Provider.of<WalletsProfilesProvider>(context,
listen: false);
final acc = _sub.getCurrentWallet();
log.d(
"fromAddress: ${acc.address!},destAddress: ${_walletViewProvider.outputPubkey.text}, amount: ${double.parse(_walletViewProvider.payAmount.text)}, password: $_pin");
_sub.pay(context,
fromAddress: acc.address!,
destAddress: _walletViewProvider.outputPubkey.text,
amount:
double.parse(_walletViewProvider.payAmount.text),
password: _pin.toUpperCase());
// await paymentsResult(context, resultPay);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ChooseWalletScreen(
return TransactionInProgress(
chest: currentChestNumber, pin: _pin.toUpperCase());
}),
);

View File

@ -29,7 +29,7 @@ class WalletOptions extends StatelessWidget {
final int _currentChest = _myWalletProvider.getCurrentChest()!;
// final currentWallet = _myWalletProvider.getDefaultWallet(_currentChest);
// final currentWallet = _myWalletProvider.getDefaultWallet();
// log.d(_walletOptions.getAddress(_currentChest, 3));
log.d("Wallet options: $_currentChest:${wallet.derivation}");
@ -336,7 +336,7 @@ class WalletOptions extends StatelessWidget {
WalletOptionsProvider _walletOptions,
int _currentChest) {
WalletData defaultWallet =
_myWalletProvider.getDefaultWallet(_currentChest)!;
_myWalletProvider.getDefaultWallet()!;
_walletOptions.isDefaultWallet = (defaultWallet.number == wallet.id()[1]);

View File

@ -155,7 +155,7 @@ class WalletsHome extends StatelessWidget {
List _listWallets = _myWalletProvider.listWallets;
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
_myWalletProvider.getDefaultWallet();
final double screenWidth = MediaQuery.of(context).size.width;
int nTule = 2;

View File

@ -0,0 +1,184 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:provider/provider.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
// ignore: must_be_immutable
class TransactionInProgress extends StatelessWidget {
const TransactionInProgress(
{Key? key, required this.chest, required this.pin})
: super(key: key);
final int chest;
final String pin;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: true);
WalletsProfilesProvider _walletViewProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
String _resultText;
bool isLoading = true;
// Map jsonResult;
final _result = _sub.transactionStatus;
final from = _myWalletProvider.getDefaultWallet()!.name!;
final to = _walletViewProvider
.getShortPubkey(_walletViewProvider.outputPubkey.text);
final amount = _walletViewProvider.payAmount.text;
switch (_result) {
case '':
{
_resultText = 'Envoi en cours ...';
}
break;
case 'sent':
{
_resultText = 'En cours de validation ...';
}
break;
default:
{
isLoading = false;
// jsonResult = json.decode(_result);
log.d(_result);
if (_result.contains('blockHash: ')) {
_resultText = 'Transcation validé !';
} else {
_resultText = "Une erreur s'est produite:\n\n$_result";
}
}
}
return WillPopScope(
onWillPop: () {
_sub.transactionStatus = '';
Navigator.pop(context);
Navigator.pop(context);
Navigator.pop(context);
return Future<bool>.value(true);
},
child: Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
elevation: 0,
automaticallyImplyLeading: false,
title: SizedBox(
height: 22,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[Text('Transaction en cours')]),
)),
body: SafeArea(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Column(children: <Widget>[
Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
const Color(0xfffafafa),
],
)),
child: Column(children: <Widget>[
const SizedBox(height: 10),
Text(
'$amount $currencyName',
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w600),
),
const SizedBox(height: 10),
const Text(
'de',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
Text(
from,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w600),
),
const SizedBox(height: 10),
const Text(
'vers',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
Text(
to,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w600),
),
const SizedBox(height: 20),
]),
),
// const SizedBox(height: 20, width: double.infinity),
const Spacer(),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Text(
_resultText,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 19 * ratio),
),
Visibility(
visible: isLoading,
child: SizedBox(
height: 15,
width: 15,
child: CircularProgressIndicator(
color: orangeC,
strokeWidth: 2,
),
),
),
]),
const Spacer(),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: 380 * ratio,
height: 60 * ratio,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.pop(context);
Navigator.pop(context);
Navigator.pop(context);
},
child: Text(
'Fermer',
style: TextStyle(
fontSize: 23 * ratio,
fontWeight: FontWeight.w600),
),
),
),
),
),
SizedBox(height: isTall ? 80 : 20)
])),
),
));
}
}

View File

@ -184,16 +184,18 @@ class WalletViewScreen extends StatelessWidget {
void paymentPopup(
BuildContext context, WalletsProfilesProvider _walletViewProvider) {
WalletsProfilesProvider _walletViewProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
// WalletsProfilesProvider _walletViewProvider =
// Provider.of<WalletsProfilesProvider>(context, listen: false);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
// SubstrateSdk _sub = Provider.of<SubstrateSdk>(context, listen: false);
const double shapeSize = 20;
WalletData? defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
WalletData? defaultWallet = _myWalletProvider.getDefaultWallet();
bool canValidate = false;
_walletViewProvider.outputPubkey.text = pubkey!;
showModalBottomSheet<void>(
@ -208,6 +210,15 @@ class WalletViewScreen extends StatelessWidget {
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
if (_walletViewProvider.payAmount.text != '' &&
double.parse(_walletViewProvider.payAmount.text) <=
double.parse(
balanceCache[defaultWallet!.address]!.split(' ')[0]) &&
_walletViewProvider.pubkey != defaultWallet.address) {
canValidate = true;
} else {
canValidate = false;
}
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
@ -251,7 +262,8 @@ class WalletViewScreen extends StatelessWidget {
MaterialPageRoute(
builder: (context) {
return UnlockingWallet(
wallet: defaultWallet, action: "pay");
wallet: defaultWallet,
action: "changeWallet");
},
),
);
@ -265,8 +277,8 @@ class WalletViewScreen extends StatelessWidget {
// BorderSide(color: Colors.grey[500], width: 2),
// borderRadius: BorderRadius.circular(8)),
border: Border.all(
color:
Colors.grey[500]!, // Set border color
color: Colors.blueAccent
.shade200, // Set border color
width: 2), // Set border width
borderRadius: const BorderRadius.all(
Radius.circular(10.0)), // Set ro
@ -376,7 +388,7 @@ class WalletViewScreen extends StatelessWidget {
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: _walletViewProvider.payAmount.text != ''
onPressed: canValidate
? () {
Navigator.push(
context,