diff --git a/assets/translations/en.json b/assets/translations/en.json index 5e790282f32bc35ad92bc13fa48fe4305ff4e0b7..3eabc1a3872d5ba65aedb23daf52ad13fa0cf0a1 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -338,6 +338,7 @@ "wot_create_identity": "Create Identity", "request_distance_evaluation": "Request Distance Evaluation", "certify_member": "Certify", + "idty_status_title": "Status", "idty_status_MEMBER": "Member", "idty_status_NOTMEMBER": "Not Member", "idty_status_REMOVED": "Removed", @@ -352,6 +353,10 @@ "op_in_block": "The operation has been confirmed and included in a block.", "op_broadcast": "The operation has been sent to the network and is being processed.", "op_processing": "The operation is being processed.", - "op_successful": "The operation was successful." + "op_successful": "The operation was successful.", + "can_cert": "Can Certify", + "can_cert_on": "Can Certify on (approx)", + "yes": "Yes", + "no": "No" } diff --git a/assets/translations/es.json b/assets/translations/es.json index 64dd5670b1d3f85e20d777e09f951c7167dc137f..640085b511c6f32d7bc1f61d98edd62aa67ff6c7 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -344,6 +344,7 @@ "wot_create_identity": "Crear Identidad", "request_distance_evaluation": "Solicitar evaluación de Distancia", "certify_member": "Certificar Miembro", + "idty_status_title": "Estado", "idty_status_MEMBER": "Miembro", "idty_status_NOTMEMBER": "No Miembro", "idty_status_REMOVED": "Eliminado", @@ -358,5 +359,9 @@ "op_in_block": "La operación ha sido confirmada e incluida en un bloque.", "op_broadcast": "La operación se ha enviado a la red y está siendo procesada.", "op_processing": "La operación está siendo procesada.", - "op_successful": "La operación se ha completado con éxito." + "op_successful": "La operación se ha completado con éxito.", + "can_cert": "Puede certificar", + "can_cert_on": "Puede certificar el (aprox.)", + "yes": "SÃ", + "no": "No" } diff --git a/lib/data/models/contact_wot_info.dart b/lib/data/models/contact_wot_info.dart index b847256722b2ff77328fd61f5ea8bbe85090d2e7..9ddb6c2060e0d44eedfaea0a481b3941af612e45 100644 --- a/lib/data/models/contact_wot_info.dart +++ b/lib/data/models/contact_wot_info.dart @@ -12,6 +12,7 @@ class ContactWotInfo { bool? canCert; bool? canCreateIdty; bool? waitingForCerts; + DateTime? canCertOn; @override String toString() { diff --git a/lib/ui/widgets/contact_page.dart b/lib/ui/widgets/contact_page.dart index 8d23db7ac9605a0ff541da606c22a7dca94b2854..598ca47e110ce2a5e54d73f082a4e6979f1a1ebf 100644 --- a/lib/ui/widgets/contact_page.dart +++ b/lib/ui/widgets/contact_page.dart @@ -11,9 +11,9 @@ import '../../data/models/app_cubit.dart'; import '../../data/models/contact.dart'; import '../../data/models/contact_cubit.dart'; import '../../data/models/contact_wot_info.dart'; -import '../../data/models/wot_menu_action.dart'; import '../../data/models/multi_wallet_transaction_cubit.dart'; import '../../data/models/node_manager.dart'; +import '../../data/models/wot_menu_action.dart'; import '../../g1/api.dart'; import '../../g1/duniter_indexer_helper.dart'; import '../../g1/g1_v2_helper_others.dart'; @@ -132,7 +132,7 @@ class _ContactPageState extends State<ContactPage> { final ProgressDialog pd = ProgressDialog(context: context); pd.show( progressType: defProgressType, - msg: 'FIXME', + msg: '', hideValue: defProgressHideValue, progressBgColor: defProgressBgColor, barrierDismissible: defProgressBarrierDismissible, @@ -187,7 +187,7 @@ class _ContactPageState extends State<ContactPage> { Expanded( child: TabBarView( children: <Widget>[ - _buildInfoTab(contact), + _buildInfoTab(contact, contactWotInfo.canCertOn), _buildTransactionsTab(contact), ], ), @@ -210,7 +210,7 @@ class _ContactPageState extends State<ContactPage> { ); } - Widget _buildInfoTab(Contact contact) { + Widget _buildInfoTab(Contact contact, DateTime? canCertOn) { return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -225,10 +225,27 @@ class _ContactPageState extends State<ContactPage> { _buildQrListTile(contact, isV2: true), if (contact.status != null) ListTile( - leading: const Icon(Icons.build), - title: Text(tr('status')), + leading: const Icon(Icons.card_membership_outlined), + title: Text(tr('idty_status_title')), subtitle: Text(tr('idty_status_${contact.status!.name}')), ), + if (canCertOn != null && !canCertOn.isAfter(DateTime.now())) + ListTile( + leading: const Icon(Icons.verified_outlined), + title: Text(tr('can_cert')), + subtitle: Text(tr('yes')), + ), + if (canCertOn != null && canCertOn.isAfter(DateTime.now())) + ListTile( + leading: const Icon(Icons.timelapse), + title: Text(tr('can_cert_on')), + subtitle: Text( + humanizeTimeFuture(context.locale.languageCode, + canCertOn.millisecond * 1000) ?? + '??', + // In red + style: const TextStyle(color: Colors.red)), + ), // FIXME: Add: Available for Cert yer or no?? if (inDevelopment && contact.createdOn != null) ListTile( @@ -467,11 +484,21 @@ class _ContactPageState extends State<ContactPage> { (await getIdentity(address: you.address)) != null; wotInfo.canCreateIdty = iAmMember && enoughBalance && !identityUsed; } + final int currentBlock = await polkadotCurrentBlock(); + + final bool youAMember = you.isMember ?? false; + if (youAMember) { + final IdtyValue? youIdty = await polkadotIdentity(you); + final IdtyCertMeta? youCertMeta = await polkadotIdtyCertMeta(you); + if (youIdty != null && youCertMeta != null) { + wotInfo.canCertOn = + estimateDate(youCertMeta.nextIssuableOn, currentBlock); + } + } // Can Certificate final IdtyValue? myIdty = await polkadotIdentity(me); final IdtyCertMeta? idtyCertMeta = await polkadotIdtyCertMeta(me); if (myIdty != null && idtyCertMeta != null) { - final int currentBlock = await polkadotCurrentBlock(); // From: https://duniter.org/wiki/duniter-v2/doc/wot/ // storage.identity.identities(AliceIndex).nextCreatableIdentityOn is lower than current block // storage.certification.storageIdtyCertMeta(AliceIndex).nextIssuableOn is lower than current block @@ -510,3 +537,10 @@ Widget _buildBadge(BuildContext context, int count) { )), ); } + +// Based on duniter-vue +DateTime estimateDate(int futureBlock, int currentBlockHeight) { + const int millisPerBlock = 6000; + final int diff = futureBlock - currentBlockHeight; + return DateTime.now().add(Duration(milliseconds: diff * millisPerBlock)); +}