From b0cae2b5cee9f25f7967c508b4dce0ea7d016e1c Mon Sep 17 00:00:00 2001 From: poka <poka@p2p.legal> Date: Sun, 1 Dec 2024 18:24:52 +0100 Subject: [PATCH] improve membership renewal info --- assets/translations/en.json | 6 ++- assets/translations/es.json | 6 ++- assets/translations/fr.json | 6 ++- lib/models/membership_status.dart | 9 ++++ lib/providers/substrate_sdk.dart | 47 ++++++++++++++++---- lib/screens/myWallets/manage_membership.dart | 41 ++++++++++------- pubspec.yaml | 2 +- 7 files changed, 87 insertions(+), 30 deletions(-) create mode 100644 lib/models/membership_status.dart diff --git a/assets/translations/en.json b/assets/translations/en.json index e78ef29e..bd04327a 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -242,7 +242,9 @@ "renewMembership": "Renew my membership", "areYouSureYouWantToRenewMembership": "Are you sure you want to renew your membership ?", "membershipExpiredOn": "Membership expired on {}", - "membershipExpiresOn": "Membership expires on {}", + "membershipExpiresOnSimple": "Membership expires on {}", + "membershipExpiresOn": "Membership expires on {}, (renewable {} days before)", "renewingMembership": "Renewing membership", - "membershipRenewalConfirmed": "Your membership renewal request has been registered and will be effective within a few minutes" + "membershipRenewalConfirmed": "Your membership renewal request has been registered and will be effective within a few minutes", + "membershipRenewalPending": "Membership renewal in progress..." } diff --git a/assets/translations/es.json b/assets/translations/es.json index b92a7973..a1e9fcce 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -243,7 +243,9 @@ "renewMembership": "Renovar mi adhésion", "areYouSureYouWantToRenewMembership": "¿Estás seguro de que quieres renovar tu adhésion?", "membershipExpiredOn": "Adhésion expirée el {}", - "membershipExpiresOn": "Adhésion expira el {}", + "membershipExpiresOnSimple": "Adhésion expira el {}", + "membershipExpiresOn": "Adhésion expira el {}, (renovable {} dÃas antes)", "renewingMembership": "Renovando adhésion", - "membershipRenewalConfirmed": "Su solicitud de renovación de membresÃa ha sido registrada y será efectiva en unos minutos" + "membershipRenewalConfirmed": "Su solicitud de renovación de membresÃa ha sido registrada y será efectiva en unos minutos", + "membershipRenewalPending": "Renovación de membresÃa en curso..." } diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 0e48261e..fa833e88 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -242,7 +242,9 @@ "renewMembership": "Renouveler mon adhésion", "areYouSureYouWantToRenewMembership": "Êtes-vous sûr de vouloir renouveler votre adhésion ?", "membershipExpiredOn": "Adhésion expirée le {}", - "membershipExpiresOn": "Adhésion expire le {}", + "membershipExpiresOnSimple": "Adhésion expire le {}", + "membershipExpiresOn": "Adhésion expire le {} (renouvelable {} jours avant)", "renewingMembership": "Renouvellement d'adhésion", - "membershipRenewalConfirmed": "Votre demande de renouvellement d'adhésion a bien été prise en compte et sera effective d'ici quelques minutes" + "membershipRenewalConfirmed": "Votre demande de renouvellement d'adhésion a bien été prise en compte et sera effective d'ici quelques minutes", + "membershipRenewalPending": "Renouvellement d'adhésion en cours..." } diff --git a/lib/models/membership_status.dart b/lib/models/membership_status.dart new file mode 100644 index 00000000..4413943e --- /dev/null +++ b/lib/models/membership_status.dart @@ -0,0 +1,9 @@ +class MembershipStatus { + final DateTime? expireDate; + final bool hasPendingRenewal; + + const MembershipStatus({ + required this.expireDate, + required this.hasPendingRenewal, + }); +} diff --git a/lib/providers/substrate_sdk.dart b/lib/providers/substrate_sdk.dart index 3cce4033..86eb366c 100644 --- a/lib/providers/substrate_sdk.dart +++ b/lib/providers/substrate_sdk.dart @@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:gecko/globals.dart'; import 'package:gecko/models/chest_data.dart'; +import 'package:gecko/models/membership_status.dart'; import 'package:gecko/models/migrate_wallet_checks.dart'; import 'package:gecko/models/transaction_content.dart'; import 'package:gecko/models/wallet_data.dart'; @@ -139,10 +140,13 @@ class SubstrateSdk with ChangeNotifier { } } - Future<int> _getStorageConst(String call) async { - final result = (await sdk.webView!.evalJavascript('api.consts.$call', wrapPromise: false) ?? [null])[0]; + Future<List<int>> _getStorageConst(List<String> calls) async { + final result = await sdk.webView!.evalJavascript( + 'Object.values(Object.fromEntries([${calls.map((call) => '["$call", api.consts.$call[0]]').join(',')}]))', + wrapPromise: false, + ); - return checkInt(result) ?? 0; + return (result as List).map((dynamic value) => checkInt(value) ?? 0).toList(); } int? checkInt(dynamic value) { @@ -486,14 +490,19 @@ class SubstrateSdk with ChangeNotifier { 'certPeriod': 'certification.certPeriod.words', 'certMaxByIssuer': 'certification.maxByIssuer.words', 'certValidityPeriod': 'certification.validityPeriod.words', + 'membershipRenewalPeriod': 'membership.membershipRenewalPeriod.words', }; - for (final param in currencyParametersNames.keys) { - try { - currencyParameters[param] = await _getStorageConst(currencyParametersNames[param]!); - } catch (e) { - log.e('error while getting param $param :: $e'); + try { + final values = await _getStorageConst(currencyParametersNames.values.toList()); + + int i = 0; + for (final param in currencyParametersNames.keys) { + currencyParameters[param] = values[i]; + i++; } + } catch (e) { + log.e('error while getting currency parameters: $e'); } log.i('currencyParameters: $currencyParameters'); } @@ -1249,4 +1258,26 @@ newKeySig: $newKeySigType"""); _executeCall(transactionContent, txInfo, [], password); return transactionId; } + + Future<MembershipStatus> getMembershipStatus(String address) async { + final idtyIndex = await _getIdentityIndexOf(address); + if (idtyIndex == null) return MembershipStatus(expireDate: null, hasPendingRenewal: false); + + // Vérifier si une évaluation est en cours + final hasPendingRenewal = await _getStorage('distance.pendingEvaluationRequest($idtyIndex)') != null; + + final expireOnMap = await _getStorage('membership.membership($idtyIndex)') ?? {}; + final expireOn = expireOnMap['expireOn'] as int; + + // Calculate time difference from current block (6 seconds per block) + final blockDifference = expireOn - blocNumber; + + // Returns expiration date by adding (or subtracting if expired) time from now + final expireDate = DateTime.now().add(Duration(seconds: blockDifference * 6)); + + return MembershipStatus( + expireDate: expireDate, + hasPendingRenewal: hasPendingRenewal, + ); + } } diff --git a/lib/screens/myWallets/manage_membership.dart b/lib/screens/myWallets/manage_membership.dart index a4559d95..3732395d 100644 --- a/lib/screens/myWallets/manage_membership.dart +++ b/lib/screens/myWallets/manage_membership.dart @@ -13,6 +13,7 @@ import 'package:gecko/screens/myWallets/migrate_identity.dart'; import 'package:gecko/screens/transaction_in_progress.dart'; import 'package:gecko/widgets/commons/top_appbar.dart'; import 'package:provider/provider.dart'; +import 'package:gecko/models/membership_status.dart'; class ManageMembership extends StatelessWidget { const ManageMembership({super.key, required this.address}); @@ -28,11 +29,11 @@ class ManageMembership extends StatelessWidget { body: SafeArea( child: Column(children: <Widget>[ ScaledSizedBox(height: 20), - FutureBuilder<DateTime?>( - future: sub.membershipExpireIn(address), + FutureBuilder<MembershipStatus>( + future: sub.getMembershipStatus(address), builder: (context, snapshot) { if (snapshot.hasData) { - return renewMembership(context, snapshot.data); + return renewMembership(context, snapshot.data!); } return const SizedBox.shrink(); }, @@ -138,14 +139,17 @@ class ManageMembership extends StatelessWidget { ); } - Widget renewMembership(BuildContext context, DateTime? expireIn) { + Widget renewMembership(BuildContext context, MembershipStatus status) { final sub = Provider.of<SubstrateSdk>(context, listen: false); - if (expireIn == null) return const SizedBox.shrink(); + if (status.expireDate == null) return const SizedBox.shrink(); final now = DateTime.now(); - final twoMonthsFromNow = now.add(const Duration(days: 60)); - final isExpired = expireIn.isBefore(now); - final canRenew = expireIn.isBefore(twoMonthsFromNow); + final renewalPeriodInSeconds = (sub.currencyParameters['membershipRenewalPeriod']!) * 6; + final renewalDate = status.expireDate!.subtract(Duration(seconds: renewalPeriodInSeconds)); + final renewalPeriodInDays = (renewalPeriodInSeconds / 86400).truncate(); + + final isExpired = status.expireDate!.isBefore(now); + final canRenew = now.isAfter(renewalDate) && !status.hasPendingRenewal; return ScaledSizedBox( height: 75, @@ -196,13 +200,20 @@ class ManageMembership extends StatelessWidget { color: canRenew ? null : Colors.grey[500], ), ), - Text( - isExpired - ? 'membershipExpiredOn'.tr(args: [DateFormat('dd/MM/yyyy').format(expireIn)]) - : 'membershipExpiresOn'.tr(args: [DateFormat('dd/MM/yyyy').format(expireIn)]), - style: scaledTextStyle( - fontSize: 12, - color: Colors.grey[500], + SizedBox( + width: scaleSize(250), + child: Text( + status.hasPendingRenewal + ? 'membershipRenewalPending'.tr() + : isExpired + ? 'membershipExpiredOn'.tr(args: [DateFormat('dd/MM/yyyy').format(status.expireDate!)]) + : canRenew + ? 'membershipExpiresOnSimple'.tr(args: [DateFormat('dd/MM/yyyy').format(status.expireDate!)]) + : 'membershipExpiresOn'.tr(args: [DateFormat('dd/MM/yyyy').format(status.expireDate!), renewalPeriodInDays.toString()]), + style: scaledTextStyle( + fontSize: 12, + color: Colors.grey[500], + ), ), ), ], diff --git a/pubspec.yaml b/pubspec.yaml index fa73307b..0cf17bcb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: gecko description: Pay with G1. publish_to: "none" -version: 0.1.13+85 +version: 0.1.14+86 environment: sdk: ^3.5.3 -- GitLab