Merge branch 'dev'

This commit is contained in:
poka 2023-11-11 11:25:24 +01:00
commit 6b42aab079
46 changed files with 1344 additions and 910 deletions

View File

@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
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:",
"rememberPassword": "Keep this code in memory for 15 minutes",
"myRootWallet": "My root wallet",
"currentWallet": "My current chest",
"currentWallet": "My current wallet",
"wallet": "Wallet",
"displayMnemonic": "Display my mnemonic sentence",
"changePassword": "Change my password",
@ -202,7 +202,7 @@
"smithCantMigrateIdentity": "You can't migrate this identity while you're member of smith web",
"received": "Received",
"sent": "Sent",
"createIdentity": "Create a new \nidentity",
"createIdentity": "Create a new\nidentity",
"memberAccountOf": "Account of {}",
"pasteAddress": "Paste address from\nclipboard",
"historyStart": "Beginning of history",
@ -217,5 +217,13 @@
"youHaveToBeConnectedToValidateChest": "You have to be connected\nto validate your chest",
"thisIdentityAlreadyExist": "This identity already exists",
"removedFromcontacts": "Removed from contacts",
"addedToContacts": "Added to contacts"
"addedToContacts": "Added to contacts",
"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:",
"rememberPassword": "Mantener en memoria mi contraseña durante 15 minutos",
"myRootWallet": "Mi monedero principal",
"currentWallet": "Mi cofre actual",
"currentWallet": "Mi monedero actual",
"wallet": "monedero",
"displayMnemonic": "Mostrar mi frase de restauración",
"changePassword": "Cambiar mi contraseña",
@ -203,7 +203,7 @@
"smithCantMigrateIdentity": "You can't migrate this identity while you're member of smith web",
"received": "Received",
"sent": "Sent",
"createIdentity": "Create a new \nidentity",
"createIdentity": "Create a new\nidentity",
"memberAccountOf": "Account of {}",
"pasteAddress": "Paste address from\nclipboard",
"historyStart": "Beginning of history",
@ -218,5 +218,13 @@
"youHaveToBeConnectedToValidateChest": "Tienes que tener conneción\npara validar tu cofre",
"thisIdentityAlreadyExist": "Esta identidad ya existe",
"removedFromcontacts": "Removed from contacts",
"addedToContacts": "Added to contacts"
"addedToContacts": "Added to contacts",
"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

@ -217,5 +217,13 @@
"youHaveToBeConnectedToValidateChest": "Vous devez vous connecter à internet\npour valider votre coffre",
"thisIdentityAlreadyExist": "Cette identité existe déjà",
"removedFromcontacts": "Retiré des contact",
"addedToContacts": "Ajouté au contacts"
"addedToContacts": "Ajouté au contacts",
"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

@ -3,7 +3,7 @@ version: "3.5"
services:
duniter-v2s-gecko-tests:
container_name: duniter-v2s-gecko-tests
image: duniter/duniter-v2s:debug-latest
image: duniter/duniter-v2s:debug-sha-4d5e08be
command: --sealing=manual
ports:
- "127.0.0.1:9615:9615"

View File

@ -25,7 +25,7 @@ void main() async {
await tapKey(keyConfirmSearch);
await waitFor(test5.shortAddress());
await tapKey(keySearchResult(test5.address));
await waitFor('certify'.tr());
await waitFor('createIdentity'.tr());
await waitFor('mustWaitXBeforeCertify'.tr().substring(0, 6), reverse: true);
await waitFor('canRenewCertInX'.tr().substring(0, 8), reverse: true);

View File

@ -1,4 +1,5 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:integration_test/integration_test.dart';
@ -10,6 +11,7 @@ void main() async {
// await dotenv.load();
testWidgets('Gecko complete', (testerLoc) async {
FlutterError.onError = ignoreOverflowErrors;
// Share WidgetTester to test provider
tester = testerLoc;
@ -50,8 +52,10 @@ Future payTest2() async {
await enterText(keyAmountField, '12.14');
await tapKey(keyConfirmPayment);
spawnBlock(duration: 500);
await tester.pump(const Duration(seconds: 2));
await waitFor('sending'.tr(),
reverse: true, settle: false, timeout: const Duration(seconds: 20));
await waitFor('extrinsicValidated'.tr(), timeout: const Duration(seconds: 1));
await tapKey(keyCloseTransactionScreen, duration: 0);
await waitFor('12.14');
spawnBlock(duration: 500);
@ -63,8 +67,10 @@ Future certifyTest5() async {
// Create identity with Test1 account
await tapKey(keyCertify);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('extrinsicValidated'.tr(), timeout: const Duration(seconds: 1));
spawnBlock(duration: 1000);
await tester.pump(const Duration(seconds: 2));
await waitFor('sending'.tr(),
reverse: true, settle: false, timeout: const Duration(seconds: 20));
await tapKey(keyCloseTransactionScreen);
await waitFor('identityCreated'.tr());
@ -76,8 +82,10 @@ Future certifyTest5() async {
await tapKey(keyConfirmIdentity);
await enterText(keyEnterIdentityUsername, test5.name);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('extrinsicValidated'.tr(), timeout: const Duration(seconds: 1));
spawnBlock(duration: 1000);
await tester.pump(const Duration(seconds: 2));
await waitFor('sending'.tr(),
reverse: true, settle: false, timeout: const Duration(seconds: 20));
await tapKey(keyCloseTransactionScreen);
await waitFor('identityConfirmed'.tr());
humanRead(2);
@ -102,8 +110,10 @@ Future certifyTest5() async {
// Certify with test2 account
await tapKey(keyCertify);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('extrinsicValidated'.tr(), timeout: const Duration(seconds: 1));
spawnBlock(duration: 1000);
await tester.pump(const Duration(seconds: 2));
await waitFor('sending'.tr(),
reverse: true, settle: false, timeout: const Duration(seconds: 20));
await tapKey(keyCloseTransactionScreen);
await waitFor('2');
@ -117,10 +127,12 @@ Future certifyTest5() async {
// Certify with test3 account
await tapKey(keyCertify);
await tapKey(keyConfirm);
spawnBlock(duration: 500);
await waitFor('extrinsicValidated'.tr(), timeout: const Duration(seconds: 1));
spawnBlock(duration: 1000);
await tester.pump(const Duration(seconds: 2));
await waitFor('sending'.tr(),
reverse: true, settle: false, timeout: const Duration(seconds: 20));
await tapKey(keyCloseTransactionScreen);
await waitFor('mustWaitXBeforeCertify'.substring(0, 12));
await waitFor('mustWaitXBeforeCertify'.tr().substring(0, 8));
// Check if test5 is member
await tapKey(keyAppBarChest, duration: 300);

View File

@ -35,12 +35,15 @@ void main() async {
await waitFor('memberValidated'.tr(), exactMatch: true);
// Revoke test5
await tapKey(keyManageMembership, duration: 1000);
await goBack();
await tapKey(keyOpenWallet(test5.address));
await tapKey(keyManageMembership, duration: 100);
await tapKey(keyRevokeIdty);
await tapKey(keyConfirm);
spawnBlock(duration: 2000);
await waitFor('extrinsicValidated'.tr().substring(3),
timeout: const Duration(seconds: 4));
spawnBlock(duration: 1000);
await tester.pump(const Duration(seconds: 2));
await waitFor('sending'.tr(),
reverse: true, settle: false, timeout: const Duration(seconds: 20));
await tapKey(keyCloseTransactionScreen, duration: 0);
await waitFor('noIdentity'.tr(), exactMatch: true);
await sleep();
@ -48,9 +51,8 @@ void main() async {
// Check test1 cannot be revoked
await goBack();
await tapKey(keyAddDerivation);
await tapKey(keyOpenWallet(test1.address), duration: 500);
await tapKey(keyManageMembership, duration: 1000);
await tapKey(keyOpenWallet(test1.address), duration: 300);
await tapKey(keyManageMembership, duration: 300);
await waitFor('youCannotRevokeThisIdentity'.tr().substring(0, 15));
}, timeout: testTimeout());
}

View File

@ -42,8 +42,10 @@ void main() async {
await tapKey(keySelectThisWallet(test6.address), selectLast: true);
await waitForButtonEnabled(keyConfirm);
await tapKey(keyConfirm);
spawnBlock(duration: 2000);
await waitFor('extrinsicValidated'.tr());
spawnBlock(duration: 1000);
await tester.pump(const Duration(seconds: 2));
await waitFor('sending'.tr(),
reverse: true, settle: false, timeout: const Duration(seconds: 20));
await tapKey(keyCloseTransactionScreen, duration: 0);
await tapKey(keyOpenWallet(test6.address), duration: 300);

View File

@ -66,11 +66,15 @@ Future restoreChest() async {
await enterText(keyPinForm, 'AAAAA', 0);
// Check if string "Accéder à mon coffre" is present in screen
await waitFor('accessMyChest'.tr());
await waitFor('accessMyChest'.tr(), pumpDuration: 30);
// Go to wallets home
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
await waitFor('ĞD');

View File

@ -114,7 +114,7 @@ Future goBack() async {
final NavigatorState navigator = tester.state(find.byType(Navigator));
log.d('INTEGRATION TEST: Go back');
navigator.pop();
await tester.pump();
await tester.pumpAndSettle();
humanRead();
}
@ -129,8 +129,10 @@ Future enterText(Key fieldKey, String textIn, [int duration = 200]) async {
Future<void> waitFor(String text,
{Duration timeout = const Duration(seconds: 5),
bool reverse = false,
bool exactMatch = false}) async {
final bool reverse = false,
final bool exactMatch = false,
final bool settle = true,
final int pumpDuration = 100}) async {
final end = DateTime.now().add(timeout);
Finder finder = exactMatch ? find.text(text) : find.textContaining(text);
@ -143,7 +145,9 @@ Future<void> waitFor(String text,
throw Exception('Timed out waiting for $searchType : "$text"');
}
await tester.pumpAndSettle();
if (settle) {
await tester.pumpAndSettle(Duration(milliseconds: pumpDuration));
}
await Future.delayed(const Duration(milliseconds: 100));
} while (reverse ? finder.evaluate().isNotEmpty : finder.evaluate().isEmpty);
humanRead();
@ -317,6 +321,32 @@ String getWidgetText(Key key) {
return (word4Finder.evaluate().single.widget as Text).data!;
}
void ignoreOverflowErrors(
FlutterErrorDetails details, {
bool forceReport = false,
}) {
bool ifIsOverflowError = false;
bool isUnableToLoadAsset = false;
// Detect overflow error.
var exception = details.exception;
if (exception is FlutterError) {
ifIsOverflowError = !exception.diagnostics.any(
(e) => e.value.toString().startsWith("A RenderFlex overflowed by"),
);
isUnableToLoadAsset = !exception.diagnostics.any(
(e) => e.value.toString().startsWith("Unable to load asset"),
);
}
// Ignore if is overflow error.
if (ifIsOverflowError || isUnableToLoadAsset) {
debugPrint('Ignored Error');
} else {
FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
}
}
class TestWallet {
String address;
String name;

View File

@ -11,6 +11,7 @@ const keyAppBarChest = Key('keyAppBarChest');
// Home
const keyParameters = Key('keyParameters');
const keyDebugScreen = Key('keyDebugScreen');
const keyContacts = Key('keyContacts');
const keyDrawerMenu = Key('keyDrawerMenu');
const keyOpenWalletsHomme = Key('keyOpenWalletsHomme');
@ -23,6 +24,7 @@ const keyImportG1v1 = Key('keyImportG1v1');
const keyChangeChest = Key('keyChangeChest');
const keyListWallets = Key('keyListWallets');
const keyAddDerivation = Key('keyAddDerivation');
final keyDragAndDrop = GlobalKey(debugLabel: 'keyDragAndDrop');
// Wallet options
const keyCopyAddress = Key('keyCopyAddress');

View File

@ -253,59 +253,52 @@ Future<QueryResult> _execQuery(
return await client.query(options);
}
Map computeHistoryView(repository) {
bool isTody = false;
bool isYesterday = false;
bool isThisWeek = false;
bool isMigrationTime = false;
String? dateDelimiter;
DateTime now = DateTime.now();
Map computeHistoryView(repository, String address) {
final bool isUdUnit = configBox.get('isUdUnit') ?? false;
late double amount;
late String finalAmount;
DateTime date = repository[0];
String dateForm;
bool isDelimiter = true;
final DateTime date = repository[0];
if ({4, 10, 11, 12}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 3)}";
} else if ({1, 2, 7, 9}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 4)}";
} else {
dateForm = "${date.day} ${monthsInYear[date.month]}";
final dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, {
1,
2,
7,
9
}.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);
final todayDate = DateTime(now.year, now.month, now.day);
final yesterdayDate = DateTime(now.year, now.month, now.day - 1);
String getDateDelimiter() {
DateTime now = DateTime.now();
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) {
dateDelimiter = "today".tr();
isTody = true;
} else if (transactionDate == yesterdayDate && !isYesterday) {
dateDelimiter = "yesterday".tr();
isYesterday = true;
} else if (weekNumber(date) == weekNumber(now) &&
date.year == now.year &&
transactionDate != yesterdayDate &&
transactionDate != todayDate &&
!isThisWeek) {
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];
if (transactionDate == todayDate) {
return "today".tr();
} else if (transactionDate == yesterdayDate) {
return "yesterday".tr();
} else if (isSameWeek && !isTodayOrYesterday) {
return "thisWeek".tr();
} else if (!isSameWeek && !isTodayOrYesterday) {
if (transactionDate.year == now.year) {
return monthsInYear[transactionDate.month]!;
} else {
return "${monthsInYear[transactionDate.month]} ${transactionDate.year}";
}
} else {
dateDelimiter = "${monthsInYear[date.month]} ${date.year}";
return '';
}
} else {
isDelimiter = false;
}
final dateDelimiter = getDateDelimiter();
amount = repository[4] == 'RECEIVED' ? repository[3] : repository[3] * -1;
if (isUdUnit) {
@ -315,17 +308,19 @@ Map computeHistoryView(repository) {
finalAmount = '$amount $currencyName';
}
if (startBlockchainInitialized && date.compareTo(startBlockchainTime) < 0) {
isMigrationTime = true;
} else {
isMigrationTime = false;
}
bool isMigrationTime =
startBlockchainInitialized && date.compareTo(startBlockchainTime) < 0;
//TODO: Migration date and transaction migration doesn't match, add this event to v2s indexer.
// log.d('debug date transaction: $date');
// log.d('debug date identity migration: ${sub.oldOwnerKeys[address]?[1]}');
// isChangeOwnerkeyTime = date.compareTo(sub.oldOwnerKeys[address]?[1] ?? DateTime(2000)) < 0;
return {
'finalAmount': finalAmount,
'isMigrationTime': isMigrationTime,
'dateDelimiter': dateDelimiter ?? '',
'isDelimiter': isDelimiter,
'dateDelimiter': dateDelimiter,
'dateForm': dateForm,
};
}

View File

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

View File

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/home.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/wallet_options.dart';
@ -46,6 +47,7 @@ class SubstrateSdk with ChangeNotifier {
bool isCesiumAddresLoading = false;
late int udValue;
Map<String, List<int>> certsCounterCache = {};
Map<String, List> oldOwnerKeys = {};
/////////////////////////////////////
////////// 1: API METHODS ///////////
@ -91,7 +93,7 @@ class SubstrateSdk with ChangeNotifier {
try {
return await sdk.webView!.evalJavascript('api.query.$call');
} catch (e) {
log.i("catched _getStorage error");
log.e("_getStorage error: $e");
return Future(() {});
}
}
@ -198,6 +200,16 @@ class SubstrateSdk with ChangeNotifier {
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 {
if (!nodeConnected) {
return {
@ -219,6 +231,7 @@ class SubstrateSdk with ChangeNotifier {
await _getStorage('universalDividend.pastReevals()');
// Compute amount of claimable UDs
currentUdIndex = await getCurrentUdIndex();
final int unclaimedUds = _computeUnclaimUds(
idtyData?['data']?['firstEligibleUd'] ?? 0, pastReevals);
@ -264,6 +277,9 @@ class SubstrateSdk with ChangeNotifier {
}
}
// log.d(
// "debug computeUnclaimUds: ${pastReevals.reversed} --- $firstEligibleUd --- $currentUdIndex");
return totalAmount;
}
@ -330,6 +346,29 @@ class SubstrateSdk with ChangeNotifier {
return certMeta;
}
Future<List> getOldOwnerKey(String address) async {
// final walletOptions =
// Provider.of<WalletOptionsProvider>(homeContext, listen: false);
var idtyIndex = await _getIdentityIndexOf(address);
if (idtyIndex == 0) return [];
final Map? idtyData = await _getStorage('identity.identities($idtyIndex)');
if (idtyData == null || idtyData['oldOwnerKey'] == null) return [];
List oldKeys = idtyData['oldOwnerKey'] ?? [];
if (oldKeys.isEmpty) return [];
oldKeys[1] = blocNumberToDate(oldKeys[1]);
oldOwnerKeys.putIfAbsent(address, () => oldKeys);
return oldKeys;
}
DateTime blocNumberToDate(int blocNumber) {
return startBlockchainTime.add(Duration(seconds: blocNumber * 6));
}
Future<String> idtyStatus(String address) async {
// final walletOptions =
// Provider.of<WalletOptionsProvider>(homeContext, listen: false);
@ -560,10 +599,14 @@ class SubstrateSdk with ChangeNotifier {
}
notifyListeners();
});
currentUdIndex =
int.parse(await _getStorage('universalDividend.currentUdIndex()'));
currentUdIndex = await getCurrentUdIndex();
await getBalanceRatio();
// Currency parameters
await initCurrencyParameters();
// Indexer Blockchain start
getBlockStart();
notifyListeners();
homeProvider.changeMessage(
"wellConnectedToNode"
@ -594,6 +637,10 @@ class SubstrateSdk with ChangeNotifier {
return node;
}
Future<int> getCurrentUdIndex() async {
return int.parse(await _getStorage('universalDividend.currentUdIndex()'));
}
NetworkParams getDuniterCustomEndpoint() {
final nodeParams = NetworkParams();
nodeParams.name = currencyName;
@ -911,6 +958,9 @@ class SubstrateSdk with ChangeNotifier {
// log.d('debug: ${currencyParameters['minCertForMembership']}');
log.d(
"debug toCert: ${toCerts[0]} --- ${currencyParameters['minCertForMembership']!} --- $toIdtyStatus");
if (toIdtyStatus == 'noid') {
txInfo = TxInfoData(
'identity',

View File

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

View File

@ -5,18 +5,32 @@ import 'package:gecko/globals.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:flutter/material.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/header_profile.dart';
import 'package:gecko/widgets/history_query.dart';
import 'package:provider/provider.dart';
class ActivityScreen extends StatelessWidget with ChangeNotifier {
ActivityScreen({required this.address, required this.avatar, this.username})
class ActivityScreen extends StatefulWidget {
const ActivityScreen(
{required this.address, required this.avatar, this.username})
: super(key: keyActivityScreen);
final String address;
final String? username;
final Image avatar;
@override
State<ActivityScreen> createState() => _ActivityScreenState();
}
class _ActivityScreenState extends State<ActivityScreen> {
@override
void initState() {
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
sub.getOldOwnerKey(widget.address);
super.initState();
}
@override
Widget build(BuildContext context) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: true);
@ -45,8 +59,8 @@ class ActivityScreen extends StatelessWidget with ChangeNotifier {
),
bottomNavigationBar: const GeckoBottomAppBar(),
body: Column(children: <Widget>[
HeaderProfile(address: address, username: username),
HistoryQuery(address: address),
HeaderProfile(address: widget.address, username: widget.username),
HistoryQuery(address: widget.address),
])),
);
}

View File

@ -23,7 +23,7 @@ class CertificationsScreen extends StatelessWidget {
toolbarHeight: 60 * ratio,
title: SizedBox(
height: 22,
child: Text('Certifications de $username'),
child: Text('certificationsOf'.tr(args: [username])),
)),
body: SafeArea(
child: Accordion(
@ -45,7 +45,10 @@ class CertificationsScreen extends StatelessWidget {
headerBackgroundColor: yellowC,
headerBackgroundColorOpened: orangeC,
header: Row(children: [
Text('received'.tr()),
Text(
'received'.tr(),
style: const TextStyle(fontSize: 20),
),
const SizedBox(width: 5),
CertsCounter(address: address)
]),
@ -60,7 +63,10 @@ class CertificationsScreen extends StatelessWidget {
headerBackgroundColor: yellowC,
headerBackgroundColorOpened: orangeC,
header: Row(children: [
Text('sent'.tr()),
Text(
'sent'.tr(),
style: const TextStyle(fontSize: 20),
),
const SizedBox(width: 5),
CertsCounter(address: address, isSent: true)
]),

View File

@ -95,10 +95,6 @@ class _HomeScreenState extends State<HomeScreen> {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult != ConnectivityResult.none) {
await sub.connectNode(context);
// Currency parameters
await sub.initCurrencyParameters();
// Indexer Blockchain start
getBlockStart();
}
}
});
@ -122,6 +118,15 @@ class _HomeScreenState extends State<HomeScreen> {
isTall = true;
ratio = 1.125;
}
//TODO: finish to implement multiqueries
// final sub = Provider.of<SubstrateSdk>(context, listen: false);
// sub.getBalanceMulti([
// '5CQ8T4qpbYJq7uVsxGPQ5q2df7x3Wa4aRY6HUWMBYjfLZhnn',
// '5Dq8xjvkmbz7q4g2LbZgyExD26VSCutfEc6n4W4AfQeVHZqz'
// ]);
return Scaffold(
resizeToAvoidBottomInset: false,
drawer: MainDrawer(isWalletsExists: isWalletsExists),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,10 +13,10 @@ import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/providers/wallets_profiles.dart';
import 'package:gecko/screens/certifications.dart';
import 'package:gecko/screens/activity.dart';
import 'package:gecko/screens/myWallets/manage_membership.dart';
import 'package:gecko/screens/qrcode_fullscreen.dart';
import 'package:gecko/widgets/balance.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/buttons/manage_membership_button.dart';
import 'package:gecko/widgets/certifications.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:gecko/widgets/idty_status.dart';
@ -40,9 +40,8 @@ class WalletOptions extends StatelessWidget {
final myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
// final sub = Provider.of<SubstrateSdk>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(context, listen: false);
// sub.spawnBlock();
// sub.spawnBlock(0, 20);
@ -146,7 +145,7 @@ class WalletOptions extends StatelessWidget {
builder: (context, walletProvider, _) {
return NameByAddress(
wallet: wallet,
size: 27,
size: 29,
color: Colors.black,
fontWeight: wallet.isMember
? FontWeight.w500
@ -183,7 +182,7 @@ class WalletOptions extends StatelessWidget {
]),
SizedBox(height: isTall ? 5 : 0),
Balance(
address: walletProvider.address.text, size: 21),
address: walletProvider.address.text, size: 24),
const SizedBox(width: 30),
InkWell(
onTap: () => isWalletNameIndexed
@ -245,6 +244,11 @@ class WalletOptions extends StatelessWidget {
SizedBox(height: 30 * ratio),
Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
final defaultWallet =
myWalletProvider.getDefaultWallet();
walletProvider.isDefaultWallet =
walletOptions.address.text ==
defaultWallet.address;
return Column(children: [
confirmIdentityButton(walletProvider),
pubkeyWidget(walletProvider, ctx),
@ -278,7 +282,7 @@ class WalletOptions extends StatelessWidget {
else
const SizedBox(),
if (isMember.data!)
manageMembership(context)
const ManageMembershipButton()
]);
}),
]);
@ -496,36 +500,6 @@ class WalletOptions extends StatelessWidget {
);
}
Widget manageMembership(BuildContext context) {
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
return InkWell(
key: keyManageMembership,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ManageMembership(
address: walletOptions.address.text,
);
}),
);
},
child: SizedBox(
height: 40,
child: Row(children: <Widget>[
const SizedBox(width: 32),
Image.asset(
'assets/medal.png',
height: 45,
),
const SizedBox(width: 22),
Text('manageMembership'.tr(), style: const TextStyle(fontSize: 20)),
]),
),
);
}
Widget setDefaultWalletWidget(
BuildContext context,
WalletOptionsProvider walletProvider,

View File

@ -6,7 +6,6 @@ import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:flutter/material.dart';
@ -16,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/unlocking_wallet.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/bottom_app_bar.dart';
import 'package:gecko/widgets/commons/offline_info.dart';
import 'package:gecko/widgets/commons/smooth_transition.dart';
import 'package:gecko/widgets/name_by_address.dart';
import 'package:gecko/widgets/payment_popup.dart';
import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:truncate/truncate.dart';
// import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
class WalletsHome extends StatefulWidget {
const WalletsHome({Key? key}) : super(key: key);
@ -35,36 +33,8 @@ class WalletsHome extends StatefulWidget {
}
class _WalletsHomeState extends State<WalletsHome> {
final safeKey = GlobalKey();
// List<TargetFocus> targets = [];
@override
void initState() {
// targets
// .add(TargetFocus(identify: "Target 1", keyTarget: safeKey, contents: [
// TargetContent(
// align: ContentAlign.right,
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: const <Widget>[
// Text(
// "Titulo lorem ipsum",
// style: TextStyle(
// fontWeight: FontWeight.bold,
// color: Colors.white,
// fontSize: 20.0),
// ),
// Padding(
// padding: EdgeInsets.only(top: 10.0),
// child: Text(
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin pulvinar tortor eget maximus iaculis.",
// style: TextStyle(color: Colors.white),
// ),
// )
// ],
// ))
// ]));
super.initState();
}
@ -252,15 +222,14 @@ class _WalletsHomeState extends State<WalletsHome> {
Provider.of<WalletOptionsProvider>(context, listen: false);
final bool isWalletsExists = myWalletProvider.checkIfWalletExist();
final sub = Provider.of<SubstrateSdk>(context, listen: false);
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
if (!isWalletsExists) {
return const Text('');
}
if (myWalletProvider.listWallets.isEmpty) {
return Expanded(
child: Column(children: const <Widget>[
return const Expanded(
child: Column(children: <Widget>[
Center(
child: Text(
'Veuillez générer votre premier portefeuille',
@ -286,13 +255,45 @@ class _WalletsHomeState extends State<WalletsHome> {
} else {
nTule = 2;
}
// Offset followDragAnchorStrategy(
// Draggable<Object> d, BuildContext context, Offset point) {
// return Offset(d.feedbackOffset.dx - 30, d.feedbackOffset.dy - 0);
// }
// showTutorial();
// Future.delayed(const Duration(seconds: 1), showTutorial);
final tutorialCoachMark = TutorialCoachMark(
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>[
const SliverToBoxAdapter(child: SizedBox(height: 20)),
@ -339,7 +340,11 @@ class _WalletsHomeState extends State<WalletsHome> {
.getWalletDataByAddress(senderAddress);
await sub.setCurrentWallet(walletData!);
sub.reload();
paymentPopup(context, repository.address);
paymentPopup(
context,
repository.address,
g1WalletsBox.get(repository.address)!.username ??
repository.name!);
},
onMove: (details) {
if (repository.address != myWalletProvider.lastFlyBy) {
@ -370,97 +375,91 @@ class _WalletsHomeState extends State<WalletsHome> {
),
);
},
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: const BoxDecoration(
gradient: RadialGradient(
radius: 0.8,
colors: [
Color.fromARGB(255, 255, 255, 211),
yellowC,
],
child: SizedBox(
key: repository.number == 1
? keyDragAndDrop
: const Key('nothing'),
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: const BoxDecoration(
gradient: RadialGradient(
radius: 0.8,
colors: [
Color.fromARGB(255, 255, 255, 211),
yellowC,
],
),
),
),
child:
// SvgPicture.asset('assets/chopp-gecko2.png',
// semanticsLabel: 'Gecko', height: 48),
repository.imageCustomPath == null ||
repository.imageCustomPath == ''
? Image.asset(
'assets/avatars/${repository.imageDefaultPath}',
alignment: Alignment.bottomCenter,
scale: 0.5,
)
: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.fitHeight,
image: FileImage(
File(repository
.imageCustomPath!),
child:
// SvgPicture.asset('assets/chopp-gecko2.png',
// semanticsLabel: 'Gecko', height: 48),
repository.imageCustomPath == null ||
repository.imageCustomPath == ''
? Image.asset(
'assets/avatars/${repository.imageDefaultPath}',
alignment:
Alignment.bottomCenter,
scale: 0.5,
)
: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.fitHeight,
image: FileImage(
File(repository
.imageCustomPath!),
),
),
),
),
),
)),
Stack(children: <Widget>[
BalanceBuilder(
address: repository.address,
isDefault: repository.address ==
defaultWallet.address),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
const SizedBox(height: 7),
Opacity(
opacity: 0.7,
child: Text(
duniterIndexer.walletNameIndexer[
repository.address] ??
truncate(
repository.name!, 20),
style: TextStyle(
fontSize: 20,
)),
Stack(children: <Widget>[
BalanceBuilder(
address: repository.address,
isDefault: repository.address ==
defaultWallet.address),
Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Column(
children: [
const SizedBox(height: 7),
Opacity(
opacity: 0.7,
child: NameByAddress(
wallet: repository,
size: 20,
color:
defaultWallet.address ==
repository.address
? Colors.white
: Colors.black,
fontWeight: FontWeight.w500),
),
)
// NameByAddress(
// wallet: repository,
// address: repository.address,
// size: 20,
// color: defaultWallet.address ==
// repository.address
// ? Colors.white
// : Colors.black,
// ),
],
),
],
),
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal,
))
],
),
],
),
]),
]),
]),
),
),
),
),

View File

@ -16,7 +16,7 @@ class OnboardingStepEleven extends StatelessWidget {
@override
Widget build(BuildContext context) {
final conffetiController =
ConfettiController(duration: const Duration(milliseconds: 300));
ConfettiController(duration: const Duration(milliseconds: 500));
conffetiController.play();
return WillPopScope(
onWillPop: () {
@ -55,16 +55,29 @@ class OnboardingStepEleven extends StatelessWidget {
const SizedBox(height: 40),
]),
Align(
alignment: Alignment.topCenter,
alignment: Alignment.topLeft,
child: ConfettiWidget(
confettiController: conffetiController,
blastDirection: pi / 2,
maxBlastForce: 5,
blastDirection: pi * 0.1,
maxBlastForce: 10,
minBlastForce: 1,
emissionFrequency: 0.01,
numberOfParticles: 10,
numberOfParticles: 7,
shouldLoop: false,
gravity: 0.1,
gravity: 0.2,
),
),
Align(
alignment: Alignment.topRight,
child: ConfettiWidget(
confettiController: conffetiController,
blastDirection: pi * 0.9,
maxBlastForce: 10,
minBlastForce: 1,
emissionFrequency: 0.01,
numberOfParticles: 7,
shouldLoop: false,
gravity: 0.2,
),
),
]),

View File

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

View File

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

View File

@ -1,8 +1,4 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:math';
import 'package:confetti/confetti.dart';
import 'package:easy_localization/easy_localization.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/my_wallets.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/screens/activity.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/qrcode_fullscreen.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/header_profile.dart';
import 'package:gecko/widgets/page_route_no_transition.dart';
import 'package:gecko/widgets/payment_popup.dart';
import 'package:provider/provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
@ -53,7 +47,7 @@ class WalletViewScreen extends StatelessWidget {
walletProfile.address = address;
sub.setCurrentWallet(defaultWallet);
log.d('aaaaaaaaaaaaaaaaaaa: $username');
log.d("username: $username");
return Scaffold(
backgroundColor: backgroundColor,
@ -64,16 +58,6 @@ class WalletViewScreen extends StatelessWidget {
actions: [
Row(
children: [
ConfettiWidget(
confettiController: walletProfile.centerController,
blastDirection: pi / 2,
maxBlastForce: 7,
minBlastForce: 3,
emissionFrequency: 0,
numberOfParticles: 7,
shouldLoop: false,
gravity: 0.001,
),
Consumer<WalletsProfilesProvider>(
builder: (context, walletProfile, _) {
return IconButton(
@ -360,8 +344,23 @@ class WalletViewScreen extends StatelessWidget {
key: keyPay,
splashColor: yellowC,
onTap: sub.nodeConnected
? () {
paymentPopup(context, address);
? () async {
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,
child: const Padding(
@ -419,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

@ -0,0 +1,43 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/myWallets/manage_membership.dart';
import 'package:provider/provider.dart';
class ManageMembershipButton extends StatelessWidget {
const ManageMembershipButton({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final walletOptions =
Provider.of<WalletOptionsProvider>(context, listen: false);
return InkWell(
key: keyManageMembership,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return ManageMembership(
address: walletOptions.address.text,
);
}),
);
},
child: SizedBox(
height: 40,
child: Row(children: <Widget>[
const SizedBox(width: 32),
Image.asset(
'assets/medal.png',
height: 45,
),
const SizedBox(width: 22),
Text('manageMembership'.tr(), style: const TextStyle(fontSize: 20)),
]),
),
);
}
}

View File

@ -37,12 +37,12 @@ class CertTile extends StatelessWidget {
title: Padding(
padding: const EdgeInsets.only(bottom: 5),
child: Text(repository['name'],
style: const TextStyle(fontSize: 20)),
style: const TextStyle(fontSize: 22)),
),
subtitle: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
fontSize: 18,
color: Colors.grey[700],
),
children: <TextSpan>[
@ -60,9 +60,9 @@ class CertTile extends StatelessWidget {
TextSpan(
text: getShortPubkey(repository['address']),
style: TextStyle(
fontStyle: FontStyle.italic,
color: Colors.grey[600],
),
fontStyle: FontStyle.italic,
color: Colors.grey[600],
fontSize: 18),
),
],
),

View File

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

View File

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

View File

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

View File

@ -24,11 +24,11 @@ class MainDrawer extends StatelessWidget {
children: <Widget>[
Expanded(
child: ListView(padding: EdgeInsets.zero, children: <Widget>[
DrawerHeader(
decoration: const BoxDecoration(
const DrawerHeader(
decoration: BoxDecoration(
color: orangeC,
),
child: Column(children: const <Widget>[
child: Column(children: <Widget>[
SizedBox(height: 0),
Image(
image: AssetImage('assets/icon/gecko_final.png'),
@ -64,7 +64,7 @@ class MainDrawer extends StatelessWidget {
),
if (kDebugMode)
ListTile(
key: keyParameters,
key: keyDebugScreen,
title: Text('Debug screen'.tr()),
onTap: () {
Navigator.pop(context);

View File

@ -74,9 +74,9 @@ class HeaderProfile extends StatelessWidget {
),
),
]),
const SizedBox(height: 25),
Balance(address: address, size: 22),
const SizedBox(height: 10),
const SizedBox(height: 23),
Balance(address: address, size: 25),
const SizedBox(height: 9),
InkWell(
onTap: () => duniterIndexer.walletNameIndexer[address] != null
? {

View File

@ -116,7 +116,12 @@ class HistoryQuery extends StatelessWidget {
child: ListView(
key: keyListTransactions,
controller: scrollController,
children: <Widget>[HistoryView(result: result)],
children: <Widget>[
HistoryView(
result: result,
address: address,
)
],
),
),
),

View File

@ -2,6 +2,9 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.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:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
@ -10,12 +13,16 @@ class HistoryView extends StatelessWidget {
const HistoryView({
Key? key,
required this.result,
required this.address,
}) : super(key: key);
final QueryResult result;
final String address;
@override
Widget build(BuildContext context) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
final sub = Provider.of<SubstrateSdk>(homeContext, listen: false);
int keyID = 0;
const double avatarSize = 200;
bool isMigrationPassed = false;
@ -32,7 +39,7 @@ class HistoryView extends StatelessWidget {
: Column(children: <Widget>[
Column(
children: duniterIndexer.transBC!.map((repository) {
final answer = computeHistoryView(repository);
final answer = computeHistoryView(repository, address);
pastDelimiters.add(answer['dateDelimiter']);
bool isMigrationTime = false;
@ -64,8 +71,6 @@ class HistoryView extends StatelessWidget {
],
),
),
// if ((countsDelimiter[answer['dateDelimiter']] ?? 0) >= 1)
if (pastDelimiters.length == 1 ||
pastDelimiters.length >= 2 &&
!(pastDelimiters[pastDelimiters.length - 2] ==
@ -91,12 +96,56 @@ class HistoryView extends StatelessWidget {
]);
}).toList()),
if (result.isLoading && duniterIndexer.pageInfo!['hasPreviousPage'])
Row(
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
children: <Widget>[
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'])
Column(
children: <Widget>[
@ -109,4 +158,4 @@ class HistoryView extends StatelessWidget {
)
]);
}
}
}

View File

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/substrate_sdk.dart';
@ -22,6 +23,8 @@ class IdentityStatus extends StatelessWidget {
Widget build(BuildContext context) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
final walletData = walletBox.get(address) ?? WalletData(address: address);
return Consumer<SubstrateSdk>(builder: (context, sub, _) {
return FutureBuilder(
future: sub.idtyStatus(address),
@ -30,14 +33,20 @@ class IdentityStatus extends StatelessWidget {
duniterIndexer.idtyStatusCache[address] = snapshot.data.toString();
switch (snapshot.data.toString()) {
case 'noid':
walletData.isMember = false;
walletBox.put(address, walletData);
{
return showText('noIdentity'.tr());
}
case 'Created':
walletData.isMember = false;
walletBox.put(address, walletData);
{
return showText('identityCreated'.tr());
}
case 'ConfirmedByOwner':
walletData.isMember = false;
walletBox.put(address, walletData);
{
return isOwner
? showText('identityConfirmed'.tr())
@ -49,17 +58,21 @@ class IdentityStatus extends StatelessWidget {
fontStyle: FontStyle.italic);
}
case 'Validated':
walletData.isMember = true;
walletBox.put(address, walletData);
{
return isOwner
? showText('memberValidated'.tr(), 18, true)
: NameByAddress(
wallet: WalletData(address: address),
size: 20,
size: 24,
color: Colors.black,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal);
}
case 'expired':
walletData.isMember = false;
walletBox.put(address, walletData);
{
return showText('identityExpired'.tr());
}

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;
// TODO: Find a way to reload a provider here, in Widget build... riverpod refacto needed...
double avatarSize = 55;
return Expanded(
@ -125,7 +124,7 @@ class SearchIdentityQuery extends StatelessWidget {
walletsProfiles.address = profile['pubkey'];
return WalletViewScreen(
address: profile['pubkey'],
username: name,
username: profile['name'] ?? '',
avatar:
g1WalletsBox.get(profile['pubkey'])?.avatar,
);

View File

@ -100,8 +100,7 @@ class SearchResult extends StatelessWidget {
walletsProfilesClass.address = g1Wallet.address;
return WalletViewScreen(
address: g1Wallet.address,
username:
duniterIndexer.walletNameIndexer[g1Wallet.address] ?? '',
username: g1WalletsBox.get(g1Wallet)!.username ?? '',
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.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.1.0+56
version: 0.1.1+58
environment:
sdk: '>=2.12.0 <3.0.0'
@ -34,8 +34,8 @@ dependencies:
git:
url: https://github.com/insinfo/qr.flutter.git
ref: master
responsive_framework: ^0.2.0
sentry_flutter: ^6.18.0
responsive_framework: 0.2.0
sentry_flutter: ^7.4.1
shared_preferences: ^2.0.7
truncate: ^3.0.1
unorm_dart: ^0.2.0
@ -49,7 +49,7 @@ dependencies:
url: https://github.com/poka-IT/sdk.git
# ref: gecko-fixes-2
ref: ff98a117e86060a91113107f31355a17ccfb346c
dots_indicator: ^2.1.0
dots_indicator: ^3.0.0
connectivity_plus: ^3.0.2
image_cropper: ^3.0.0
easy_localization: ^3.0.1
@ -64,13 +64,14 @@ dependencies:
graphql: ^5.1.1
hive_generator: ^2.0.0
riverpod: ^2.1.1
tutorial_coach_mark: ^1.2.4
tutorial_coach_mark: ^1.2.8
confetti: ^0.7.0
url_launcher: ^6.1.11
dev_dependencies:
# flutter_launcher_icons: ^0.9.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
build_runner: ^2.1.2
flutter_test: