From c5a9611a7595910c2b19f8ca3df7aa84a0131ec7 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Thu, 20 Jul 2023 18:37:34 +0545 Subject: [PATCH] feat: Handling credential manifest before showing Add credential Page #1733 --- lib/app/shared/constants/urls.dart | 3 + .../polygon_id_credential_offer_view.dart | 58 +++++++--- lib/polygon_id/cubit/polygon_id_cubit.dart | 105 +++++++++++------- lib/polygon_id/cubit/polygon_id_state.dart | 12 +- lib/splash/bloclisteners/blocklisteners.dart | 7 +- 5 files changed, 117 insertions(+), 68 deletions(-) diff --git a/lib/app/shared/constants/urls.dart b/lib/app/shared/constants/urls.dart index 4b4c22392..ab0cba5b1 100644 --- a/lib/app/shared/constants/urls.dart +++ b/lib/app/shared/constants/urls.dart @@ -43,6 +43,9 @@ class Urls { static const String bloometaCardUrl = 'https://issuer.talao.co/bloometa'; + static const String defaultPolygonIdCardUrl = + 'https://issuer.talao.co/credential-manifest/polygonid/default'; + static const String kycAgeCredentialUrl = 'https://issuer.talao.co/credential-manifest/polygonid/kycagecredential'; static const String kycCountryOfResidenceUrl = diff --git a/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart b/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart index 4dd4c7069..ffb8f6a34 100644 --- a/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart +++ b/lib/dashboard/home/tab_bar/credentials/polygon_id/polygon_id_credential_offer/view/polygon_id_credential_offer_view.dart @@ -4,25 +4,17 @@ import 'package:altme/l10n/l10n.dart'; import 'package:altme/pin_code/pin_code.dart'; import 'package:altme/polygon_id/polygon_id.dart'; import 'package:altme/theme/theme.dart'; +import 'package:credential_manifest/credential_manifest.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:polygonid/polygonid.dart'; class PolygonIdCredentialOfferPage extends StatelessWidget { const PolygonIdCredentialOfferPage({ super.key, - required this.claims, }); - final List claims; - - static Route route({ - required List claims, - }) => - MaterialPageRoute( - builder: (context) => PolygonIdCredentialOfferPage( - claims: claims, - ), + static Route route() => MaterialPageRoute( + builder: (context) => const PolygonIdCredentialOfferPage(), settings: const RouteSettings(name: '/PolygonIdCredentialOffer'), ); @@ -30,6 +22,8 @@ class PolygonIdCredentialOfferPage extends StatelessWidget { Widget build(BuildContext context) { final l10n = context.l10n; + final polygonIdCubitState = context.read().state; + return BasePage( title: l10n.credentialReceiveTitle, useSafeArea: true, @@ -47,12 +41,12 @@ class PolygonIdCredentialOfferPage extends StatelessWidget { ), const SizedBox(height: 30), ListView.builder( - itemCount: claims.length, + itemCount: polygonIdCubitState.claims!.length, padding: EdgeInsets.zero, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int i) { - final jsonCredential = claims[i].info; + final jsonCredential = polygonIdCubitState.claims![i].info; final credentialPreview = Credential.fromJson(jsonCredential); Widget widget; @@ -84,10 +78,40 @@ class PolygonIdCredentialOfferPage extends StatelessWidget { ); } else if (credentialSubjectType == CredentialSubjectType.civicPassCredential) { - widget = const CredentialBaseWidget( + final polygonIdCubitState = + context.read().state; + final DisplayMapping? titleDisplayMapping = + polygonIdCubitState.credentialManifests![i] + .outputDescriptors?.first.display?.title; + + var title = ''; + + if (titleDisplayMapping is DisplayMappingText) { + title = titleDisplayMapping.text; + } + + if (titleDisplayMapping is DisplayMappingPath) { + title = titleDisplayMapping.fallback ?? ''; + } + + final DisplayMapping? subTitleDisplayMapping = + polygonIdCubitState.credentialManifests![i] + .outputDescriptors?.first.display?.subtitle; + + var subTitle = ''; + + if (subTitleDisplayMapping is DisplayMappingText) { + subTitle = subTitleDisplayMapping.text; + } + + if (subTitleDisplayMapping is DisplayMappingPath) { + subTitle = subTitleDisplayMapping.fallback ?? ''; + } + widget = CredentialBaseWidget( + title: title, cardBackgroundImagePath: ImageStrings.civicPassCard, issuerName: 'CIVIC', - value: '', + value: subTitle, ); } else { widget = DefaultCredentialListWidget( @@ -127,9 +151,7 @@ class PolygonIdCredentialOfferPage extends StatelessWidget { Navigator.of(context).push( PinCodePage.route( isValidCallback: () { - context.read().addPolygonIdCredentials( - claims: claims, - ); + context.read().addPolygonIdCredentials(); }, restrictToBack: false, ), diff --git a/lib/polygon_id/cubit/polygon_id_cubit.dart b/lib/polygon_id/cubit/polygon_id_cubit.dart index 670a0b355..c0290ee4b 100644 --- a/lib/polygon_id/cubit/polygon_id_cubit.dart +++ b/lib/polygon_id/cubit/polygon_id_cubit.dart @@ -267,13 +267,59 @@ class PolygonIdCubit extends Cubit { } } else if (iden3MessageEntity.messageType == Iden3MessageType.credentialOffer) { - log.i('get claims'); - emit( - state.copyWith( - status: AppStatus.loading, - polygonAction: PolygonIdAction.offer, - ), - ); + try { + final List claims = await getClaims( + iden3MessageEntity: iden3MessageEntity, + ); + + final List credentialManifests = + []; + + for (final claimEntity in claims) { + dynamic response; + + // Try to get Credential manifest for kycAgeCredential + // and kycCountryOfResidence and proofOfTwitterStatsUrl + if (claimEntity.type == CredentialSubjectType.kycAgeCredential.name) { + response = await client.get(Urls.kycAgeCredentialUrl); + } else if (claimEntity.type == + CredentialSubjectType.kycCountryOfResidence.name) { + response = await client.get(Urls.kycCountryOfResidenceUrl); + } else if (claimEntity.type == + CredentialSubjectType.proofOfTwitterStats.name) { + response = await client.get(Urls.proofOfTwitterStatsUrl); + } else if (claimEntity.type == + CredentialSubjectType.civicPassCredential.name) { + response = await client.get(Urls.civicPassCredentialUrl); + } else { + response = await client.get(Urls.defaultPolygonIdCardUrl); + } + + final CredentialManifest credentialManifest = + CredentialManifest.fromJson(response as Map); + + credentialManifests.add(credentialManifest); + } + + if (claims.length != credentialManifests.length) { + throw Exception(); + } + + log.i('get claims'); + emit( + state.copyWith( + status: AppStatus.loading, + polygonAction: PolygonIdAction.offer, + claims: claims, + credentialManifests: credentialManifests, + ), + ); + } catch (e) { + log.e('can not get the credntials manifest for polygon error: $e'); + throw ResponseMessage( + ResponseString.RESPONSE_STRING_SOMETHING_WENT_WRONG_TRY_AGAIN_LATER, + ); + } } else if (iden3MessageEntity.messageType == Iden3MessageType.proofContractInvokeRequest) { log.i('contractFunctionCall'); @@ -395,14 +441,15 @@ class PolygonIdCubit extends Cubit { return claims; } - Future addPolygonIdCredentials({ - required List claims, - }) async { + Future addPolygonIdCredentials() async { try { log.i('add Claims'); emit(state.copyWith(status: AppStatus.loading)); - for (final claim in claims) { - await addToList(claim); + for (int i = 0; i < state.claims!.length; i++) { + await addToList( + claimEntity: state.claims![i], + credentialManifest: state.credentialManifests![i], + ); } emit(state.copyWith(status: AppStatus.goBack)); } catch (e) { @@ -424,39 +471,13 @@ class PolygonIdCubit extends Cubit { } } - Future addToList(ClaimEntity claimEntity) async { + Future addToList({ + required ClaimEntity claimEntity, + required CredentialManifest credentialManifest, + }) async { final jsonCredential = claimEntity.info; final credentialPreview = Credential.fromJson(jsonCredential); - CredentialManifest? credentialManifest; - - try { - // Try to get Credential manifest for kycAgeCredential - // and kycCountryOfResidence and proofOfTwitterStatsUrl - if (claimEntity.type == CredentialSubjectType.kycAgeCredential.name) { - final response = await client.get(Urls.kycAgeCredentialUrl); - credentialManifest = - CredentialManifest.fromJson(response as Map); - } else if (claimEntity.type == - CredentialSubjectType.kycCountryOfResidence.name) { - final response = await client.get(Urls.kycCountryOfResidenceUrl); - credentialManifest = - CredentialManifest.fromJson(response as Map); - } else if (claimEntity.type == - CredentialSubjectType.proofOfTwitterStats.name) { - final response = await client.get(Urls.proofOfTwitterStatsUrl); - credentialManifest = - CredentialManifest.fromJson(response as Map); - } else if (claimEntity.type == - CredentialSubjectType.civicPassCredential.name) { - final response = await client.get(Urls.civicPassCredentialUrl); - credentialManifest = - CredentialManifest.fromJson(response as Map); - } - } catch (e) { - log.e('can not get the credntials manifest for polygon error: $e'); - } - final credentialModel = CredentialModel( id: claimEntity.id, image: 'image', diff --git a/lib/polygon_id/cubit/polygon_id_state.dart b/lib/polygon_id/cubit/polygon_id_state.dart index 1ce8b676d..5d0e5e650 100644 --- a/lib/polygon_id/cubit/polygon_id_state.dart +++ b/lib/polygon_id/cubit/polygon_id_state.dart @@ -9,6 +9,8 @@ class PolygonIdState extends Equatable { this.message, this.loadingText, this.scannedResponse, + this.claims, + this.credentialManifests, }); factory PolygonIdState.fromJson(Map json) => @@ -21,12 +23,13 @@ class PolygonIdState extends Equatable { final MessageHandler? loadingText; final bool isInitialised; final String? scannedResponse; + final List? claims; + final List? credentialManifests; PolygonIdState error({required StateMessage message}) { - return PolygonIdState( + return copyWith( status: AppStatus.error, message: message, - scannedResponse: scannedResponse, ); } @@ -38,6 +41,8 @@ class PolygonIdState extends Equatable { MessageHandler? loadingText, Route? route, String? scannedResponse, + List? claims, + List? credentialManifests, }) { return PolygonIdState( status: status, @@ -46,6 +51,8 @@ class PolygonIdState extends Equatable { loadingText: loadingText, isInitialised: isInitialised ?? this.isInitialised, scannedResponse: scannedResponse ?? this.scannedResponse, + claims: claims ?? this.claims, + credentialManifests: credentialManifests ?? this.credentialManifests, ); } @@ -59,5 +66,6 @@ class PolygonIdState extends Equatable { isInitialised, scannedResponse, loadingText, + credentialManifests, ]; } diff --git a/lib/splash/bloclisteners/blocklisteners.dart b/lib/splash/bloclisteners/blocklisteners.dart index 140f158fd..b807a98a1 100644 --- a/lib/splash/bloclisteners/blocklisteners.dart +++ b/lib/splash/bloclisteners/blocklisteners.dart @@ -510,14 +510,9 @@ final polygonIdBlocListener = BlocListener( if (state.polygonAction == PolygonIdAction.offer) { try { - final Iden3MessageEntity iden3MessageEntity = await polygonIdCubit - .getIden3Message(message: state.scannedResponse!); - final List claims = await polygonIdCubit.getClaims( - iden3MessageEntity: iden3MessageEntity, - ); LoadingView().hide(); await Navigator.of(context) - .push(PolygonIdCredentialOfferPage.route(claims: claims)); + .push(PolygonIdCredentialOfferPage.route()); } catch (e) { final l10n = context.l10n; LoadingView().hide();