Compare commits

...

10 Commits

31 changed files with 1095 additions and 807 deletions

View File

@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app') project.evaluationDependsOn(':app')
} }
task clean(type: Delete) { tasks.register("clean", Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }

BIN
assets/drag-and-drop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -23,7 +23,7 @@
"toUnlockEnterPassword": "To unlock your safe, enter your secret code, away from prying lizards:", "toUnlockEnterPassword": "To unlock your safe, enter your secret code, away from prying lizards:",
"rememberPassword": "Keep this code in memory for 15 minutes", "rememberPassword": "Keep this code in memory for 15 minutes",
"myRootWallet": "My root wallet", "myRootWallet": "My root wallet",
"currentWallet": "My current chest", "currentWallet": "My current wallet",
"wallet": "Wallet", "wallet": "Wallet",
"displayMnemonic": "Display my mnemonic sentence", "displayMnemonic": "Display my mnemonic sentence",
"changePassword": "Change my password", "changePassword": "Change my password",
@ -218,5 +218,12 @@
"thisIdentityAlreadyExist": "This identity already exists", "thisIdentityAlreadyExist": "This identity already exists",
"removedFromcontacts": "Removed from contacts", "removedFromcontacts": "Removed from contacts",
"addedToContacts": "Added to contacts", "addedToContacts": "Added to contacts",
"certificationsOf": "Certifications of {}" "certificationsOf": "Certifications of {}",
"explainDraggableWallet": "Drag and drop a tile onto another to make a transaction, by holding down the tile.",
"skip": "Skip",
"fees": "fees: {} {}",
"feesExplanation": "To ensure network security, an execution fee is charged on each transaction.",
"feesExplanationDetails": "These fees are transferred to the common treasury account.",
"gotit": "Got it",
"moreInfo": "More information"
} }

View File

@ -23,7 +23,7 @@
"toUnlockEnterPassword": "Para desbloquear tu cofre, introduce tu contraseña, lejos de lagartijas curiosas:", "toUnlockEnterPassword": "Para desbloquear tu cofre, introduce tu contraseña, lejos de lagartijas curiosas:",
"rememberPassword": "Mantener en memoria mi contraseña durante 15 minutos", "rememberPassword": "Mantener en memoria mi contraseña durante 15 minutos",
"myRootWallet": "Mi monedero principal", "myRootWallet": "Mi monedero principal",
"currentWallet": "Mi cofre actual", "currentWallet": "Mi monedero actual",
"wallet": "monedero", "wallet": "monedero",
"displayMnemonic": "Mostrar mi frase de restauración", "displayMnemonic": "Mostrar mi frase de restauración",
"changePassword": "Cambiar mi contraseña", "changePassword": "Cambiar mi contraseña",
@ -219,5 +219,12 @@
"thisIdentityAlreadyExist": "Esta identidad ya existe", "thisIdentityAlreadyExist": "Esta identidad ya existe",
"removedFromcontacts": "Removed from contacts", "removedFromcontacts": "Removed from contacts",
"addedToContacts": "Added to contacts", "addedToContacts": "Added to contacts",
"certificationsOf": "Certifications of {}" "certificationsOf": "Certifications of {}",
"explainDraggableWallet": "Drag and drop a tile onto another to make a transaction, by holding down the tile.",
"skip": "Skip",
"fees": "fees: {} {}",
"feesExplanation": "To ensure network security, an execution fee is charged on each transaction.",
"feesExplanationDetails": "These fees are transferred to the common treasury account.",
"gotit": "Got it",
"moreInfo": "More information"
} }

View File

@ -218,5 +218,12 @@
"thisIdentityAlreadyExist": "Cette identité existe déjà", "thisIdentityAlreadyExist": "Cette identité existe déjà",
"removedFromcontacts": "Retiré des contact", "removedFromcontacts": "Retiré des contact",
"addedToContacts": "Ajouté au contacts", "addedToContacts": "Ajouté au contacts",
"certificationsOf": "Certifications de {}" "certificationsOf": "Certifications de {}",
"explainDraggableWallet": "Faites glisser et déposez une tuile sur une autre pour effectuer une transaction, avec un appui long.",
"skip": "Passer",
"fees": "frais: {} {}",
"feesExplanation": "Pour garantir la sécurité du réseau, des frais d'exécution sont prélevés sur chaque transaction.",
"feesExplanationDetails": "Ces frais sont transférés vers le compte de trésorerie commune.",
"gotit": "J'ai compris",
"moreInfo": "Plus d'info"
} }

View File

@ -71,6 +71,10 @@ Future restoreChest() async {
// Go to wallets home // Go to wallets home
await tapKey(keyGoWalletsHome, duration: 0); await tapKey(keyGoWalletsHome, duration: 0);
// Skip tutorial
await sleep(500);
await tapKey(keyDragAndDrop).timeout(const Duration(seconds: 3));
// Check if string "ĞD" is present in screen // Check if string "ĞD" is present in screen
await waitFor('ĞD'); await waitFor('ĞD');

View File

@ -24,6 +24,7 @@ const keyImportG1v1 = Key('keyImportG1v1');
const keyChangeChest = Key('keyChangeChest'); const keyChangeChest = Key('keyChangeChest');
const keyListWallets = Key('keyListWallets'); const keyListWallets = Key('keyListWallets');
const keyAddDerivation = Key('keyAddDerivation'); const keyAddDerivation = Key('keyAddDerivation');
final keyDragAndDrop = GlobalKey(debugLabel: 'keyDragAndDrop');
// Wallet options // Wallet options
const keyCopyAddress = Key('keyCopyAddress'); const keyCopyAddress = Key('keyCopyAddress');

View File

@ -8,7 +8,6 @@ import 'package:gecko/globals.dart';
import 'package:gecko/models/queries_indexer.dart'; import 'package:gecko/models/queries_indexer.dart';
import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/substrate_sdk.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
class DuniterIndexer with ChangeNotifier { class DuniterIndexer with ChangeNotifier {
Map<String, String?> walletNameIndexer = {}; Map<String, String?> walletNameIndexer = {};
@ -255,61 +254,51 @@ Future<QueryResult> _execQuery(
} }
Map computeHistoryView(repository, String address) { Map computeHistoryView(repository, String address) {
bool isTody = false;
bool isYesterday = false;
bool isThisWeek = false;
bool isMigrationTime = false;
bool isChangeOwnerkeyTime = false;
String? dateDelimiter;
DateTime now = DateTime.now();
final bool isUdUnit = configBox.get('isUdUnit') ?? false; final bool isUdUnit = configBox.get('isUdUnit') ?? false;
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
late double amount; late double amount;
late String finalAmount; late String finalAmount;
DateTime date = repository[0]; final DateTime date = repository[0];
String dateForm;
bool isDelimiter = true;
if ({4, 10, 11, 12}.contains(date.month)) { final dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 3)}"; 1,
} else if ({1, 2, 7, 9}.contains(date.month)) { 2,
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 4)}"; 7,
} else { 9
dateForm = "${date.day} ${monthsInYear[date.month]}"; }.contains(date.month) ? 4 : 3)}";
DateTime normalizeDate(DateTime inputDate) {
return DateTime(inputDate.year, inputDate.month, inputDate.day);
} }
final transactionDate = DateTime(date.year, date.month, date.day); String getDateDelimiter() {
final todayDate = DateTime(now.year, now.month, now.day); DateTime now = DateTime.now();
final yesterdayDate = DateTime(now.year, now.month, now.day - 1); final transactionDate = normalizeDate(date.toLocal());
final todayDate = normalizeDate(now);
final yesterdayDate = normalizeDate(now.subtract(const Duration(days: 1)));
final isSameWeek = weekNumber(transactionDate) == weekNumber(now) &&
transactionDate.year == now.year;
final isTodayOrYesterday =
transactionDate == todayDate || transactionDate == yesterdayDate;
if (transactionDate == todayDate && !isTody) { if (transactionDate == todayDate) {
dateDelimiter = "today".tr(); return "today".tr();
isTody = true; } else if (transactionDate == yesterdayDate) {
} else if (transactionDate == yesterdayDate && !isYesterday) { return "yesterday".tr();
dateDelimiter = "yesterday".tr(); } else if (isSameWeek && !isTodayOrYesterday) {
isYesterday = true; return "thisWeek".tr();
} else if (weekNumber(date) == weekNumber(now) && } else if (!isSameWeek && !isTodayOrYesterday) {
date.year == now.year && if (transactionDate.year == now.year) {
transactionDate != yesterdayDate && return monthsInYear[transactionDate.month]!;
transactionDate != todayDate && } else {
!isThisWeek) { return "${monthsInYear[transactionDate.month]} ${transactionDate.year}";
dateDelimiter = "thisWeek".tr(); }
isThisWeek = true;
} else if (dateDelimiter != "${monthsInYear[date.month]} ${date.year}" &&
transactionDate != todayDate &&
transactionDate != yesterdayDate &&
!(weekNumber(date) == weekNumber(now) && date.year == now.year)) {
if (date.year == now.year) {
dateDelimiter = monthsInYear[date.month];
} else { } else {
dateDelimiter = "${monthsInYear[date.month]} ${date.year}"; return '';
} }
} else {
isDelimiter = false;
} }
final dateDelimiter = getDateDelimiter();
amount = repository[4] == 'RECEIVED' ? repository[3] : repository[3] * -1; amount = repository[4] == 'RECEIVED' ? repository[3] : repository[3] * -1;
if (isUdUnit) { if (isUdUnit) {
@ -319,27 +308,20 @@ Map computeHistoryView(repository, String address) {
finalAmount = '$amount $currencyName'; finalAmount = '$amount $currencyName';
} }
if (startBlockchainInitialized && date.compareTo(startBlockchainTime) < 0) { bool isMigrationTime =
isMigrationTime = true; startBlockchainInitialized && date.compareTo(startBlockchainTime) < 0;
} else {
isMigrationTime = false;
}
log.d('taaaaaaaaaaaaaa: $date'); //TODO: Migration date and transaction migration doesn't match, add this event to v2s indexer.
log.d('taaaaaaa: ${sub.oldOwnerKeys[address]?[1]}');
if (date.compareTo(sub.oldOwnerKeys[address]?[1] ?? DateTime(2000)) < 0) { // log.d('debug date transaction: $date');
isChangeOwnerkeyTime = true; // log.d('debug date identity migration: ${sub.oldOwnerKeys[address]?[1]}');
} else { // isChangeOwnerkeyTime = date.compareTo(sub.oldOwnerKeys[address]?[1] ?? DateTime(2000)) < 0;
isChangeOwnerkeyTime = false;
}
return { return {
'finalAmount': finalAmount, 'finalAmount': finalAmount,
'isMigrationTime': isMigrationTime, 'isMigrationTime': isMigrationTime,
'dateDelimiter': dateDelimiter ?? '', 'dateDelimiter': dateDelimiter,
'isDelimiter': isDelimiter,
'dateForm': dateForm, 'dateForm': dateForm,
'isChangeOwnerkeyTime': isChangeOwnerkeyTime
}; };
} }

View File

@ -20,7 +20,7 @@ class GenerateWalletsProvider with ChangeNotifier {
// NewWallet generatedWallet; // NewWallet generatedWallet;
durt.NewWallet? actualWallet; durt.NewWallet? actualWallet;
FocusNode walletNameFocus = FocusNode(); final walletNameFocus = FocusNode();
Color? askedWordColor = Colors.black; Color? askedWordColor = Colors.black;
bool isAskedWordValid = false; bool isAskedWordValid = false;
int scanedValidWalletNumber = -1; int scanedValidWalletNumber = -1;
@ -33,8 +33,8 @@ class GenerateWalletsProvider with ChangeNotifier {
String? generatedMnemonic; String? generatedMnemonic;
bool walletIsGenerated = true; bool walletIsGenerated = true;
TextEditingController mnemonicController = TextEditingController(); final mnemonicController = TextEditingController();
TextEditingController pin = TextEditingController(); final pin = TextEditingController();
// Import wallet // Import wallet
TextEditingController cesiumID = TextEditingController(); TextEditingController cesiumID = TextEditingController();

View File

@ -93,7 +93,7 @@ class SubstrateSdk with ChangeNotifier {
try { try {
return await sdk.webView!.evalJavascript('api.query.$call'); return await sdk.webView!.evalJavascript('api.query.$call');
} catch (e) { } catch (e) {
log.i("catched _getStorage error"); log.e("_getStorage error: $e");
return Future(() {}); return Future(() {});
} }
} }
@ -200,6 +200,16 @@ class SubstrateSdk with ChangeNotifier {
return balanceRatio; return balanceRatio;
} }
Future getBalanceMulti(List addresses) async {
List stringifyAddresses = [];
for (var element in addresses) {
stringifyAddresses.add('"$element"');
}
final List balanceGlobal =
await _getStorage('system.account.multi($stringifyAddresses)');
log.d('debug multi: $balanceGlobal');
}
Future<Map<String, double>> getBalance(String address) async { Future<Map<String, double>> getBalance(String address) async {
if (!nodeConnected) { if (!nodeConnected) {
return { return {

View File

@ -10,7 +10,6 @@ import 'package:jdenticon_dart/jdenticon_dart.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
// import 'package:qrscan/qrscan.dart' as scanner; // import 'package:qrscan/qrscan.dart' as scanner;
import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:confetti/confetti.dart';
class WalletsProfilesProvider with ChangeNotifier { class WalletsProfilesProvider with ChangeNotifier {
WalletsProfilesProvider(this.address); WalletsProfilesProvider(this.address);
@ -24,8 +23,6 @@ class WalletsProfilesProvider with ChangeNotifier {
TextEditingController payAmount = TextEditingController(); TextEditingController payAmount = TextEditingController();
TextEditingController payComment = TextEditingController(); TextEditingController payComment = TextEditingController();
num? _balance; num? _balance;
final centerController =
ConfettiController(duration: const Duration(milliseconds: 300));
Future<String> scan(context) async { Future<String> scan(context) async {
if (Platform.isAndroid || Platform.isIOS) { if (Platform.isAndroid || Platform.isIOS) {
@ -145,7 +142,6 @@ class WalletsProfilesProvider with ChangeNotifier {
snackMessage(homeContext, snackMessage(homeContext,
message: 'removedFromcontacts'.tr(), duration: 4); message: 'removedFromcontacts'.tr(), duration: 4);
} else { } else {
centerController.play();
await contactsBox.put(profile.address, profile); await contactsBox.put(profile.address, profile);
// drawStar(Size(50, 50)); // drawStar(Size(50, 50));
snackMessage(homeContext, message: 'addedToContacts'.tr(), duration: 4); snackMessage(homeContext, message: 'addedToContacts'.tr(), duration: 4);

View File

@ -118,6 +118,15 @@ class _HomeScreenState extends State<HomeScreen> {
isTall = true; isTall = true;
ratio = 1.125; ratio = 1.125;
} }
//TODO: finish to implement multiqueries
// final sub = Provider.of<SubstrateSdk>(context, listen: false);
// sub.getBalanceMulti([
// '5CQ8T4qpbYJq7uVsxGPQ5q2df7x3Wa4aRY6HUWMBYjfLZhnn',
// '5Dq8xjvkmbz7q4g2LbZgyExD26VSCutfEc6n4W4AfQeVHZqz'
// ]);
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
drawer: MainDrawer(isWalletsExists: isWalletsExists), drawer: MainDrawer(isWalletsExists: isWalletsExists),

View File

@ -85,7 +85,7 @@ class ChooseWalletScreen extends StatelessWidget {
} }
if (myWalletProvider.listWallets.isEmpty) { if (myWalletProvider.listWallets.isEmpty) {
return Column(children: const <Widget>[ return const Column(children: <Widget>[
Center( Center(
child: Text( child: Text(
'Veuillez générer votre premier portefeuille', 'Veuillez générer votre premier portefeuille',

View File

@ -61,11 +61,11 @@ class ImportG1v1 extends StatelessWidget {
// log.d(_certs.data); // log.d(_certs.data);
if (status.data == null) { if (status.data == null) {
return Column(children: [ return const Column(children: [
const SizedBox(height: 80), SizedBox(height: 80),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: const [ children: [
SizedBox( SizedBox(
height: 35, height: 35,
width: 35, width: 35,

View File

@ -93,9 +93,9 @@ class ManageMembership extends StatelessWidget {
}), }),
); );
}, },
child: SizedBox( child: const SizedBox(
height: 60, height: 60,
child: Row(children: const <Widget>[ child: Row(children: <Widget>[
SizedBox(width: 16), SizedBox(width: 16),
Icon(Icons.change_circle_outlined, size: 35), Icon(Icons.change_circle_outlined, size: 35),
SizedBox(width: 11.5), SizedBox(width: 11.5),

View File

@ -47,12 +47,12 @@ class MigrateIdentityScreen extends StatelessWidget {
); );
if (walletsList.length < 2) { if (walletsList.length < 2) {
return Column( return const Column(
children: [ children: [
const SizedBox(height: 80), SizedBox(height: 80),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: const [ children: [
Text( Text(
'Vous devez avoir au moins 2 portefeuilles\npour effecter cette opération', 'Vous devez avoir au moins 2 portefeuilles\npour effecter cette opération',
style: TextStyle(fontSize: 20), style: TextStyle(fontSize: 20),
@ -78,20 +78,18 @@ class MigrateIdentityScreen extends StatelessWidget {
fromAddress, selectedWallet.address), fromAddress, selectedWallet.address),
builder: (BuildContext context, AsyncSnapshot<List> status) { builder: (BuildContext context, AsyncSnapshot<List> status) {
if (status.data == null) { if (status.data == null) {
return Column(children: [ return const Column(children: [
const SizedBox(height: 80), SizedBox(height: 80),
Row( Row(mainAxisAlignment: MainAxisAlignment.center, children: [
mainAxisAlignment: MainAxisAlignment.center, SizedBox(
children: const [ height: 35,
SizedBox( width: 35,
height: 35, child: CircularProgressIndicator(
width: 35, color: orangeC,
child: CircularProgressIndicator( strokeWidth: 4,
color: orangeC, ),
strokeWidth: 4, ),
), ]),
),
]),
]); ]);
} }
@ -136,7 +134,7 @@ class MigrateIdentityScreen extends StatelessWidget {
final unit = isUdUnit ? 'ud'.tr(args: ['']) : currencyName; final unit = isUdUnit ? 'ud'.tr(args: ['']) : currencyName;
return Column(children: <Widget>[ return Column(children: <Widget>[
Row(children: const []), const Row(children: []),
const SizedBox(height: 20), const SizedBox(height: 20),
SizedBox( SizedBox(

View File

@ -81,7 +81,7 @@ class ShowSeed extends StatelessWidget {
), ),
onPressed: () { onPressed: () {
Clipboard.setData( Clipboard.setData(
ClipboardData(text: seed.data)); ClipboardData(text: seed.data!));
snackCopySeed(context); snackCopySeed(context);
}, },
child: Row(children: <Widget>[ child: Row(children: <Widget>[

View File

@ -15,16 +15,15 @@ import 'package:gecko/screens/myWallets/chest_options.dart';
import 'package:gecko/screens/myWallets/import_g1_v1.dart'; import 'package:gecko/screens/myWallets/import_g1_v1.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/myWallets/wallet_options.dart'; import 'package:gecko/screens/myWallets/wallet_options.dart';
import 'package:gecko/screens/wallet_view.dart';
// import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:gecko/widgets/balance.dart'; import 'package:gecko/widgets/balance.dart';
import 'package:gecko/widgets/bottom_app_bar.dart'; import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/commons/offline_info.dart'; import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:gecko/widgets/commons/smooth_transition.dart'; import 'package:gecko/widgets/commons/smooth_transition.dart';
import 'package:gecko/widgets/name_by_address.dart'; import 'package:gecko/widgets/name_by_address.dart';
import 'package:gecko/widgets/payment_popup.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
// import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
class WalletsHome extends StatefulWidget { class WalletsHome extends StatefulWidget {
const WalletsHome({Key? key}) : super(key: key); const WalletsHome({Key? key}) : super(key: key);
@ -34,9 +33,6 @@ class WalletsHome extends StatefulWidget {
} }
class _WalletsHomeState extends State<WalletsHome> { class _WalletsHomeState extends State<WalletsHome> {
final safeKey = GlobalKey();
// List<TargetFocus> targets = [];
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -232,8 +228,8 @@ class _WalletsHomeState extends State<WalletsHome> {
} }
if (myWalletProvider.listWallets.isEmpty) { if (myWalletProvider.listWallets.isEmpty) {
return Expanded( return const Expanded(
child: Column(children: const <Widget>[ child: Column(children: <Widget>[
Center( Center(
child: Text( child: Text(
'Veuillez générer votre premier portefeuille', 'Veuillez générer votre premier portefeuille',
@ -259,13 +255,45 @@ class _WalletsHomeState extends State<WalletsHome> {
} else { } else {
nTule = 2; nTule = 2;
} }
// Offset followDragAnchorStrategy(
// Draggable<Object> d, BuildContext context, Offset point) {
// return Offset(d.feedbackOffset.dx - 30, d.feedbackOffset.dy - 0);
// }
// showTutorial(); final tutorialCoachMark = TutorialCoachMark(
// Future.delayed(const Duration(seconds: 1), showTutorial); targets: [
TargetFocus(
identify: "drag_and_drop",
keyTarget: keyDragAndDrop,
contents: [
TargetContent(
child: Column(
children: [
Image.asset('assets/drag-and-drop.png', height: 140),
const SizedBox(height: 15),
Text(
'explainDraggableWallet'.tr(),
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 22, fontWeight: FontWeight.w500),
),
],
))
],
alignSkip: Alignment.bottomRight,
enableOverlayTab: true,
),
],
colorShadow: orangeC,
textSkip: "skip".tr(),
paddingFocus: 10,
opacityShadow: 0.8,
);
// configBox.delete('showDraggableTutorial');
final bool showDraggableTutorial =
configBox.get('showDraggableTutorial') ?? true;
if (listWallets.length > 1 && showDraggableTutorial) {
tutorialCoachMark.show(context: context);
configBox.put('showDraggableTutorial', false);
}
return CustomScrollView(slivers: <Widget>[ return CustomScrollView(slivers: <Widget>[
const SliverToBoxAdapter(child: SizedBox(height: 20)), const SliverToBoxAdapter(child: SizedBox(height: 20)),
@ -312,7 +340,11 @@ class _WalletsHomeState extends State<WalletsHome> {
.getWalletDataByAddress(senderAddress); .getWalletDataByAddress(senderAddress);
await sub.setCurrentWallet(walletData!); await sub.setCurrentWallet(walletData!);
sub.reload(); sub.reload();
paymentPopup(context, repository.address); paymentPopup(
context,
repository.address,
g1WalletsBox.get(repository.address)!.username ??
repository.name!);
}, },
onMove: (details) { onMove: (details) {
if (repository.address != myWalletProvider.lastFlyBy) { if (repository.address != myWalletProvider.lastFlyBy) {
@ -343,83 +375,91 @@ class _WalletsHomeState extends State<WalletsHome> {
), ),
); );
}, },
child: ClipOvalShadow( child: SizedBox(
shadow: const Shadow( key: repository.number == 1
color: Colors.transparent, ? keyDragAndDrop
offset: Offset(0, 0), : const Key('nothing'),
blurRadius: 5, child: ClipOvalShadow(
), shadow: const Shadow(
clipper: CustomClipperOval(), color: Colors.transparent,
child: ClipRRect( offset: Offset(0, 0),
borderRadius: blurRadius: 5,
const BorderRadius.all(Radius.circular(12)), ),
child: Column(children: <Widget>[ clipper: CustomClipperOval(),
Expanded( child: ClipRRect(
child: Container( borderRadius:
width: double.infinity, const BorderRadius.all(Radius.circular(12)),
height: double.infinity, child: Column(children: <Widget>[
decoration: const BoxDecoration( Expanded(
gradient: RadialGradient( child: Container(
radius: 0.8, width: double.infinity,
colors: [ height: double.infinity,
Color.fromARGB(255, 255, 255, 211), decoration: const BoxDecoration(
yellowC, gradient: RadialGradient(
], radius: 0.8,
colors: [
Color.fromARGB(255, 255, 255, 211),
yellowC,
],
),
), ),
), child:
child: // SvgPicture.asset('assets/chopp-gecko2.png',
// SvgPicture.asset('assets/chopp-gecko2.png', // semanticsLabel: 'Gecko', height: 48),
// semanticsLabel: 'Gecko', height: 48), repository.imageCustomPath == null ||
repository.imageCustomPath == null || repository.imageCustomPath == ''
repository.imageCustomPath == '' ? Image.asset(
? Image.asset( 'assets/avatars/${repository.imageDefaultPath}',
'assets/avatars/${repository.imageDefaultPath}', alignment:
alignment: Alignment.bottomCenter, Alignment.bottomCenter,
scale: 0.5, scale: 0.5,
) )
: Container( : Container(
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: Colors.transparent, color: Colors.transparent,
image: DecorationImage( image: DecorationImage(
fit: BoxFit.fitHeight, fit: BoxFit.fitHeight,
image: FileImage( image: FileImage(
File(repository File(repository
.imageCustomPath!), .imageCustomPath!),
),
), ),
), ),
), ),
), )),
)), Stack(children: <Widget>[
Stack(children: <Widget>[ BalanceBuilder(
BalanceBuilder( address: repository.address,
address: repository.address, isDefault: repository.address ==
isDefault: repository.address == defaultWallet.address),
defaultWallet.address), Row(
Row( mainAxisAlignment:
mainAxisAlignment: MainAxisAlignment.center, MainAxisAlignment.center,
children: [ children: [
Column( Column(
children: [ children: [
const SizedBox(height: 7), const SizedBox(height: 7),
Opacity( Opacity(
opacity: 0.7, opacity: 0.7,
child: NameByAddress( child: NameByAddress(
wallet: repository, wallet: repository,
size: 20, size: 20,
color: defaultWallet.address == color:
repository.address defaultWallet.address ==
? Colors.white repository.address
: Colors.black, ? Colors.white
fontWeight: FontWeight.w600, : Colors.black,
fontStyle: FontStyle.normal, fontWeight: FontWeight.w600,
)) fontStyle: FontStyle.normal,
], ))
), ],
], ),
), ],
),
]),
]), ]),
]), ),
), ),
), ),
), ),

View File

@ -94,7 +94,7 @@ class _ChooseChestState extends State<OnboardingStepFive> {
), ),
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData( Clipboard.setData(ClipboardData(
text: generateWalletProvider.generatedMnemonic)); text: generateWalletProvider.generatedMnemonic!));
snackCopySeed(context); snackCopySeed(context);
}, },
child: Row(children: <Widget>[ child: Row(children: <Widget>[

View File

@ -16,8 +16,8 @@ class TemplateScreen extends StatelessWidget {
height: 22, height: 22,
child: Text('Template screen'), child: Text('Template screen'),
)), )),
body: SafeArea( body: const SafeArea(
child: Column(children: const <Widget>[ child: Column(children: <Widget>[
SizedBox(height: 20), SizedBox(height: 20),
Text('data'), Text('data'),
SizedBox(height: 20), SizedBox(height: 20),

View File

@ -1,8 +1,4 @@
// ignore_for_file: use_build_context_synchronously // ignore_for_file: use_build_context_synchronously
import 'dart:math';
import 'package:confetti/confetti.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -15,18 +11,16 @@ import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/substrate_sdk.dart'; import 'package:gecko/providers/substrate_sdk.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/models/wallet_data.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart'; import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/activity.dart'; import 'package:gecko/screens/activity.dart';
import 'package:gecko/widgets/commons/common_elements.dart'; import 'package:gecko/widgets/commons/common_elements.dart';
import 'package:gecko/screens/myWallets/choose_wallet.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/qrcode_fullscreen.dart'; import 'package:gecko/screens/qrcode_fullscreen.dart';
import 'package:gecko/screens/transaction_in_progress.dart'; import 'package:gecko/screens/transaction_in_progress.dart';
import 'package:gecko/widgets/balance.dart';
import 'package:gecko/widgets/bottom_app_bar.dart'; import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/header_profile.dart'; import 'package:gecko/widgets/header_profile.dart';
import 'package:gecko/widgets/page_route_no_transition.dart'; import 'package:gecko/widgets/page_route_no_transition.dart';
import 'package:gecko/widgets/payment_popup.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart';
@ -53,6 +47,8 @@ class WalletViewScreen extends StatelessWidget {
walletProfile.address = address; walletProfile.address = address;
sub.setCurrentWallet(defaultWallet); sub.setCurrentWallet(defaultWallet);
log.d("username: $username");
return Scaffold( return Scaffold(
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
@ -62,16 +58,6 @@ class WalletViewScreen extends StatelessWidget {
actions: [ actions: [
Row( Row(
children: [ children: [
ConfettiWidget(
confettiController: walletProfile.centerController,
blastDirection: pi / 2,
maxBlastForce: 7,
minBlastForce: 3,
emissionFrequency: 0,
numberOfParticles: 7,
shouldLoop: false,
gravity: 0.001,
),
Consumer<WalletsProfilesProvider>( Consumer<WalletsProfilesProvider>(
builder: (context, walletProfile, _) { builder: (context, walletProfile, _) {
return IconButton( return IconButton(
@ -358,8 +344,23 @@ class WalletViewScreen extends StatelessWidget {
key: keyPay, key: keyPay,
splashColor: yellowC, splashColor: yellowC,
onTap: sub.nodeConnected onTap: sub.nodeConnected
? () { ? () async {
paymentPopup(context, address); String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(
wallet: defaultWallet);
},
),
);
}
if (pin != null ||
myWalletProvider.pinCode != '') {
paymentPopup(context, address, username);
}
} }
: null, : null,
child: const Padding( child: const Padding(
@ -417,301 +418,3 @@ class WalletViewScreen extends StatelessWidget {
]); ]);
} }
} }
void paymentPopup(BuildContext context, String toAddress) {
final walletViewProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
const double shapeSize = 20;
WalletData? defaultWallet = myWalletProvider.getDefaultWallet();
log.d(defaultWallet.address);
bool canValidate = false;
final toWalletData = myWalletProvider.getWalletDataByAddress(toAddress);
Future executeTransfert() async {
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(wallet: defaultWallet);
},
),
);
}
log.d(pin);
if (pin != null || myWalletProvider.pinCode != '') {
// Payment workflow !
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final acc = sub.getCurrentWallet();
log.d(
"fromAddress: ${acc.address!},destAddress: $toAddress, amount: ${double.parse(walletViewProvider.payAmount.text)}, password: $pin");
sub.pay(
fromAddress: acc.address!,
destAddress: toAddress,
amount: double.parse(walletViewProvider.payAmount.text),
password: pin ?? myWalletProvider.pinCode);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const TransactionInProgress();
}),
);
}
}
showModalBottomSheet<void>(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(shapeSize),
topLeft: Radius.circular(shapeSize),
),
),
isScrollControlled: true,
context: context,
builder: (BuildContext context) {
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
double fees = 0;
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
if (walletViewProvider.payAmount.text != '' &&
(double.parse(walletViewProvider.payAmount.text) +
2 / balanceRatio) <=
(walletOptions.balanceCache[defaultWallet.address] ?? 0) &&
toAddress != defaultWallet.address) {
if ((walletOptions.balanceCache[toAddress] == 0 ||
walletOptions.balanceCache[toAddress] == null) &&
double.parse(walletViewProvider.payAmount.text) <
5 / balanceRatio) {
canValidate = false;
} else {
canValidate = true;
}
} else {
canValidate = false;
}
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 420,
decoration: const ShapeDecoration(
color: Color(0xffffeed1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(shapeSize),
topLeft: Radius.circular(shapeSize),
),
),
),
child: Padding(
padding: const EdgeInsets.only(
top: 24, bottom: 0, left: 24, right: 24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'executeATransfer'.tr(),
style: const TextStyle(
fontSize: 26, fontWeight: FontWeight.w700),
),
IconButton(
iconSize: 40,
icon: const Icon(Icons.cancel_outlined),
onPressed: () {
Navigator.pop(context);
},
),
]),
const SizedBox(height: 20),
Text(
'from'.tr(),
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const SizedBox(height: 10),
Consumer<SubstrateSdk>(builder: (context, sub, _) {
return InkWell(
key: keyChangeChest,
onTap: () async {
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(
wallet: defaultWallet);
},
),
);
}
if (pin != null || myWalletProvider.pinCode != '') {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ChooseWalletScreen(
pin: pin ?? myWalletProvider.pinCode);
}),
);
}
},
child: Container(
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent.shade200, width: 2),
borderRadius:
const BorderRadius.all(Radius.circular(10.0)),
),
padding: const EdgeInsets.all(10),
child: Row(children: [
Text(defaultWallet.name!),
const Spacer(),
Balance(address: defaultWallet.address, size: 20),
]),
),
);
}),
const SizedBox(height: 12),
Row(
children: [
Text(
'to'.tr(),
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const SizedBox(width: 10),
Column(
children: [
const SizedBox(height: 2),
Text(
toWalletData == null
? getShortPubkey(toAddress)
: toWalletData.name!,
style: const TextStyle(
fontSize: 21,
fontWeight: FontWeight.w600,
),
),
],
),
],
),
const SizedBox(height: 12),
Row(
children: [
Text(
'amount'.tr(),
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const Spacer(),
Text(
'frais: $fees $currencyName',
style: const TextStyle(
color: orangeC,
fontSize: 17,
fontWeight: FontWeight.w500,
),
),
const SizedBox(width: 10),
],
),
const SizedBox(height: 10),
TextField(
textInputAction: TextInputAction.done,
onEditingComplete: () async =>
canValidate ? await executeTransfert() : null,
key: keyAmountField,
controller: walletViewProvider.payAmount,
autofocus: true,
maxLines: 1,
textAlign: TextAlign.center,
keyboardType: const TextInputType.numberWithOptions(
decimal: true),
onChanged: (_) async {
fees = await sub.txFees(
defaultWallet.address,
toAddress,
double.parse(
walletViewProvider.payAmount.text == ''
? '0'
: walletViewProvider.payAmount.text));
log.d(fees);
setState(() {});
},
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.deny(',',
replacementString: '.'),
FilteringTextInputFormatter.allow(
RegExp(r'(^\d+\.?\d{0,2})')),
],
decoration: InputDecoration(
hintText: '0.00',
suffix: Text(isUdUnit
? 'ud'.tr(args: [''])
: currencyName), // udUnitDisplay(40),
filled: true,
fillColor: Colors.transparent,
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey[500]!, width: 2),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.all(20),
),
style: const TextStyle(
fontSize: 35,
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
const Spacer(),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
key: keyConfirmPayment,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
),
onPressed: canValidate
? () async => await executeTransfert()
: null,
child: Text(
'executeTheTransfer'.tr(),
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.w600),
),
),
),
const Spacer(),
]),
),
),
);
});
}).then((value) => walletViewProvider.payAmount.text = '');
}

View File

@ -8,7 +8,7 @@ class BuildProgressBar extends StatelessWidget {
required this.pagePosition, required this.pagePosition,
}) : super(key: key); }) : super(key: key);
final double pagePosition; final int pagePosition;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -155,11 +155,14 @@ Future<void> infoPopup(BuildContext context, String title) async {
children: [ children: [
TextButton( TextButton(
key: keyInfoPopup, key: keyInfoPopup,
child: const Text( child: Padding(
"D'accord", padding: const EdgeInsets.all(8),
style: TextStyle( child: Text(
fontSize: 21, "gotit".tr(),
color: Color(0xffD80000), style: const TextStyle(
fontSize: 21,
color: Color(0xffD80000),
),
), ),
), ),
onPressed: () { onPressed: () {

View File

@ -24,7 +24,7 @@ class InfoIntro extends StatelessWidget {
final String assetName; final String assetName;
final String buttonText; final String buttonText;
final Widget nextScreen; final Widget nextScreen;
final double pagePosition; final int pagePosition;
final bool isMd; final bool isMd;
final bool isFast; final bool isFast;
final double boxHeight; final double boxHeight;

View File

@ -24,11 +24,11 @@ class MainDrawer extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: ListView(padding: EdgeInsets.zero, children: <Widget>[ child: ListView(padding: EdgeInsets.zero, children: <Widget>[
DrawerHeader( const DrawerHeader(
decoration: const BoxDecoration( decoration: BoxDecoration(
color: orangeC, color: orangeC,
), ),
child: Column(children: const <Widget>[ child: Column(children: <Widget>[
SizedBox(height: 0), SizedBox(height: 0),
Image( Image(
image: AssetImage('assets/icon/gecko_final.png'), image: AssetImage('assets/icon/gecko_final.png'),

View File

@ -2,6 +2,9 @@ import 'package:easy_localization/easy_localization.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/duniter_indexer.dart'; import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:gecko/widgets/page_route_no_transition.dart';
import 'package:gecko/widgets/transaction_tile.dart'; import 'package:gecko/widgets/transaction_tile.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -18,6 +21,8 @@ class HistoryView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false); final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
int keyID = 0; int keyID = 0;
const double avatarSize = 200; const double avatarSize = 200;
bool isMigrationPassed = false; bool isMigrationPassed = false;
@ -66,28 +71,6 @@ class HistoryView extends StatelessWidget {
], ],
), ),
), ),
if (answer['isChangeOwnerkeyTime'])
Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Image(
image: AssetImage('assets/party.png'), height: 40),
const SizedBox(width: 40),
Text(
'Identité migré !'.tr(),
style: const TextStyle(
fontSize: 25,
color: Colors.blueAccent,
fontWeight: FontWeight.w500),
),
const SizedBox(width: 40),
const Image(
image: AssetImage('assets/party.png'), height: 40),
],
),
),
if (pastDelimiters.length == 1 || if (pastDelimiters.length == 1 ||
pastDelimiters.length >= 2 && pastDelimiters.length >= 2 &&
!(pastDelimiters[pastDelimiters.length - 2] == !(pastDelimiters[pastDelimiters.length - 2] ==
@ -113,12 +96,56 @@ class HistoryView extends StatelessWidget {
]); ]);
}).toList()), }).toList()),
if (result.isLoading && duniterIndexer.pageInfo!['hasPreviousPage']) if (result.isLoading && duniterIndexer.pageInfo!['hasPreviousPage'])
Row( const Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[ children: <Widget>[
CircularProgressIndicator(), CircularProgressIndicator(),
], ],
), ),
if (!duniterIndexer.pageInfo!['hasNextPage'] &&
sub.oldOwnerKeys[address]?[0] != null)
Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: InkWell(
onTap: () => Navigator.push(
context,
PageNoTransit(builder: (context) {
return WalletViewScreen(
address: sub.oldOwnerKeys[address]![0],
username: '',
);
}),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.account_circle,
size: 40,
color: Colors.blueAccent,
),
const SizedBox(width: 40),
Column(children: [
Text(
'Identité migré:'.tr(),
style: const TextStyle(
fontSize: 25,
color: Colors.blueAccent,
fontWeight: FontWeight.w500),
),
Text(
'Ancienne adresse: ${getShortPubkey(sub.oldOwnerKeys[address]![0])}')
]),
const SizedBox(width: 40),
const Icon(
Icons.account_circle,
size: 40,
color: Colors.blueAccent,
),
],
),
),
),
if (!duniterIndexer.pageInfo!['hasNextPage']) if (!duniterIndexer.pageInfo!['hasNextPage'])
Column( Column(
children: <Widget>[ children: <Widget>[

View File

@ -0,0 +1,431 @@
// ignore_for_file: use_build_context_synchronously
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/transaction_in_progress.dart';
import 'package:gecko/widgets/balance.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
void paymentPopup(BuildContext context, String toAddress, String username) {
final walletViewProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
double fees = 0;
const double shapeSize = 20;
var defaultWallet = myWalletProvider.getDefaultWallet();
bool canValidate = false;
final amountFocus = FocusNode();
final dropdownKey = GlobalKey();
Future executeTransfert() async {
String? pin;
if (myWalletProvider.pinCode == '') {
pin = await Navigator.push(
context,
MaterialPageRoute(
builder: (homeContext) {
return UnlockingWallet(wallet: defaultWallet);
},
),
);
}
log.d(pin);
if (pin != null || myWalletProvider.pinCode != '') {
// Payment workflow !
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final acc = sub.getCurrentWallet();
log.d(
"fromAddress: ${acc.address!},destAddress: $toAddress, amount: ${double.parse(walletViewProvider.payAmount.text)}, password: $pin");
sub.pay(
fromAddress: acc.address!,
destAddress: toAddress,
amount: double.parse(walletViewProvider.payAmount.text),
password: pin ?? myWalletProvider.pinCode);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const TransactionInProgress();
}),
);
}
}
myWalletProvider.readAllWallets();
log.d(myWalletProvider.listWallets);
showModalBottomSheet<void>(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(shapeSize),
topLeft: Radius.circular(shapeSize),
),
),
isScrollControlled: true,
context: context,
builder: (BuildContext context) {
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
if (walletViewProvider.payAmount.text != '' &&
(double.parse(walletViewProvider.payAmount.text) +
2 / balanceRatio) <=
(walletOptions.balanceCache[defaultWallet.address] ?? 0) &&
toAddress != defaultWallet.address) {
if ((walletOptions.balanceCache[toAddress] == 0 ||
walletOptions.balanceCache[toAddress] == null) &&
double.parse(walletViewProvider.payAmount.text) <
5 / balanceRatio) {
canValidate = false;
} else {
canValidate = true;
}
} else {
canValidate = false;
}
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 420,
decoration: const ShapeDecoration(
color: Color(0xffffeed1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(shapeSize),
topLeft: Radius.circular(shapeSize),
),
),
),
child: Padding(
padding: const EdgeInsets.only(
top: 24, bottom: 0, left: 24, right: 24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'executeATransfer'.tr(),
style: const TextStyle(
fontSize: 26, fontWeight: FontWeight.w700),
),
IconButton(
iconSize: 40,
icon: const Icon(Icons.cancel_outlined),
onPressed: () {
Navigator.pop(context);
},
),
]),
const SizedBox(height: 20),
Text(
'from'.tr(),
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const SizedBox(height: 10),
Consumer<SubstrateSdk>(builder: (context, sub, _) {
// TODO: about keyboard dismiss issue, should try this: https://stackoverflow.com/a/76352647/8301867
return DropdownButton(
dropdownColor: const Color(0xffffeed1),
elevation: 12,
key: dropdownKey,
value: defaultWallet,
// onTap: () async {
// await Future.delayed(const Duration(milliseconds: 10));
// amountFocus.requestFocus();
// },
selectedItemBuilder: (_) {
return myWalletProvider.listWallets
.map((WalletData wallet) {
return Container(
width: 408,
decoration: BoxDecoration(
border: Border.all(
color: Colors.blueAccent.shade200,
width: 2),
borderRadius: const BorderRadius.all(
Radius.circular(10.0)),
),
padding: const EdgeInsets.all(10),
child: Row(children: [
Text(g1WalletsBox
.get(wallet.address)
?.username ??
wallet.name!),
const Spacer(),
Balance(address: wallet.address, size: 20),
]),
);
}).toList();
},
onChanged: (WalletData? newSelectedWallet) async {
defaultWallet = newSelectedWallet!;
await sub.setCurrentWallet(newSelectedWallet);
sub.reload();
amountFocus.requestFocus();
setState(() {});
},
items: myWalletProvider.listWallets
.map((WalletData wallet) {
return DropdownMenuItem(
value: wallet,
child: Container(
color: const Color(0xffffeed1),
width: 408,
height: 80,
padding: const EdgeInsets.all(10),
child: Row(children: [
Text(g1WalletsBox
.get(wallet.address)
?.username ??
wallet.name!),
const Spacer(),
Balance(address: wallet.address, size: 20),
]),
),
);
}).toList(),
);
}),
const SizedBox(height: 12),
Row(
children: [
Text(
'to'.tr(),
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const SizedBox(width: 10),
Column(
children: [
const SizedBox(height: 2),
Text(
username == ''
? getShortPubkey(toAddress)
: username,
style: const TextStyle(
fontSize: 21,
fontWeight: FontWeight.w600,
),
),
],
),
],
),
const SizedBox(height: 12),
Row(
children: [
Text(
'amount'.tr(),
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const Spacer(),
InkWell(
onTap: () => infoFeesPopup(context),
child: Row(
children: [
const Icon(Icons.info_outlined, color: orangeC),
const SizedBox(width: 5),
Text(
'fees'.tr(
args: [fees.toString(), currencyName]),
style: const TextStyle(
color: orangeC,
fontSize: 17,
fontWeight: FontWeight.w500,
),
),
],
),
),
const SizedBox(width: 10),
],
),
const SizedBox(height: 10),
TextField(
textInputAction: TextInputAction.done,
onEditingComplete: () async =>
canValidate ? await executeTransfert() : null,
key: keyAmountField,
controller: walletViewProvider.payAmount,
autofocus: true,
focusNode: amountFocus,
maxLines: 1,
textAlign: TextAlign.center,
keyboardType: const TextInputType.numberWithOptions(
decimal: true),
onChanged: (_) async {
fees = await sub.txFees(
defaultWallet.address,
toAddress,
double.parse(
walletViewProvider.payAmount.text == ''
? '0'
: walletViewProvider.payAmount.text));
log.d(fees);
setState(() {});
},
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.deny(',',
replacementString: '.'),
FilteringTextInputFormatter.allow(
RegExp(r'(^\d+\.?\d{0,2})')),
],
decoration: InputDecoration(
hintText: '0.00',
suffix: Text(isUdUnit
? 'ud'.tr(args: [''])
: currencyName), // udUnitDisplay(40),
filled: true,
fillColor: Colors.transparent,
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey[500]!, width: 2),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.all(20),
),
style: const TextStyle(
fontSize: 35,
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
const Spacer(),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
key: keyConfirmPayment,
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, elevation: 4,
backgroundColor: orangeC, // foreground
),
onPressed: canValidate
? () async => await executeTransfert()
: null,
child: Text(
'executeTheTransfer'.tr(),
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.w600),
),
),
),
const Spacer(),
]),
),
),
);
});
}).then((value) => walletViewProvider.payAmount.text = '');
}
Future<void> infoFeesPopup(BuildContext context) async {
return showDialog<void>(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: backgroundColor,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.info_outlined, color: orangeC, size: 40),
const SizedBox(height: 20),
Text(
'feesExplanation'.tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
const SizedBox(height: 30),
Text(
'feesExplanationDetails'.tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w300),
),
const SizedBox(height: 5),
InkWell(
onTap: () async => await _launchUrl('https://duniter.org'),
child: Container(
padding: const EdgeInsets.only(
bottom: 2,
),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.blueAccent,
width: 1,
))),
child: Text(
'moreInfo'.tr(),
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w300,
color: Colors.blueAccent,
// decoration: TextDecoration.underline,
),
),
),
),
],
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
key: keyInfoPopup,
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
'gotit'.tr(),
style: const TextStyle(
fontSize: 21,
color: Color(0xffD80000),
),
),
),
onPressed: () {
Navigator.pop(context, true);
},
),
],
)
],
);
},
);
}
Future<void> _launchUrl(String url) async {
if (!await launchUrl(Uri.parse(url))) {
throw Exception('Could not launch $url');
}
}

View File

@ -75,7 +75,6 @@ class SearchIdentityQuery extends StatelessWidget {
} }
searchProvider.resultLenght = identities.length; searchProvider.resultLenght = identities.length;
// TODO: Find a way to reload a provider here, in Widget build... riverpod refacto needed... or not ...
double avatarSize = 55; double avatarSize = 55;
return Expanded( return Expanded(
@ -125,7 +124,7 @@ class SearchIdentityQuery extends StatelessWidget {
walletsProfiles.address = profile['pubkey']; walletsProfiles.address = profile['pubkey'];
return WalletViewScreen( return WalletViewScreen(
address: profile['pubkey'], address: profile['pubkey'],
username: name, username: profile['name'] ?? '',
avatar: avatar:
g1WalletsBox.get(profile['pubkey'])?.avatar, g1WalletsBox.get(profile['pubkey'])?.avatar,
); );

View File

@ -100,8 +100,7 @@ class SearchResult extends StatelessWidget {
walletsProfilesClass.address = g1Wallet.address; walletsProfilesClass.address = g1Wallet.address;
return WalletViewScreen( return WalletViewScreen(
address: g1Wallet.address, address: g1Wallet.address,
username: username: g1WalletsBox.get(g1Wallet)!.username ?? '',
duniterIndexer.walletNameIndexer[g1Wallet.address] ?? '',
avatar: g1WalletsBox.get(g1Wallet.address)?.avatar, avatar: g1WalletsBox.get(g1Wallet.address)?.avatar,
); );
}), }),

File diff suppressed because it is too large Load Diff

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.1.0+56 version: 0.1.0+57
environment: environment:
sdk: '>=2.12.0 <3.0.0' sdk: '>=2.12.0 <3.0.0'
@ -34,8 +34,8 @@ dependencies:
git: git:
url: https://github.com/insinfo/qr.flutter.git url: https://github.com/insinfo/qr.flutter.git
ref: master ref: master
responsive_framework: ^0.2.0 responsive_framework: 0.2.0
sentry_flutter: ^6.18.0 sentry_flutter: ^7.4.1
shared_preferences: ^2.0.7 shared_preferences: ^2.0.7
truncate: ^3.0.1 truncate: ^3.0.1
unorm_dart: ^0.2.0 unorm_dart: ^0.2.0
@ -49,7 +49,7 @@ dependencies:
url: https://github.com/poka-IT/sdk.git url: https://github.com/poka-IT/sdk.git
# ref: gecko-fixes-2 # ref: gecko-fixes-2
ref: ff98a117e86060a91113107f31355a17ccfb346c ref: ff98a117e86060a91113107f31355a17ccfb346c
dots_indicator: ^2.1.0 dots_indicator: ^3.0.0
connectivity_plus: ^3.0.2 connectivity_plus: ^3.0.2
image_cropper: ^3.0.0 image_cropper: ^3.0.0
easy_localization: ^3.0.1 easy_localization: ^3.0.1
@ -64,13 +64,14 @@ dependencies:
graphql: ^5.1.1 graphql: ^5.1.1
hive_generator: ^2.0.0 hive_generator: ^2.0.0
riverpod: ^2.1.1 riverpod: ^2.1.1
tutorial_coach_mark: ^1.2.4 tutorial_coach_mark: ^1.2.8
confetti: ^0.7.0 confetti: ^0.7.0
url_launcher: ^6.1.11
dev_dependencies: dev_dependencies:
# flutter_launcher_icons: ^0.9.2 # flutter_launcher_icons: ^0.9.2
# flutter_launcher_icons_maker: ^^0.10.2 # flutter_launcher_icons_maker: ^^0.10.2
flutter_launcher_icons: ^0.12.0 flutter_launcher_icons: ^0.13.0
icons_launcher: ^2.0.6 icons_launcher: ^2.0.6
build_runner: ^2.1.2 build_runner: ^2.1.2
flutter_test: flutter_test: