From f41f7aadd074800fcf6647f8e9b4c3c773beb8e0 Mon Sep 17 00:00:00 2001 From: Bibash Shrestha Date: Fri, 15 Mar 2024 15:18:54 +0545 Subject: [PATCH] feat: Display image of card for SD-JWT #2503 --- .../helper_functions/helper_functions.dart | 65 +++++++++++++++++++ .../detail/view/credentials_details_page.dart | 45 ++++++++++--- .../widget/display_selective_disclosure.dart | 31 +-------- 3 files changed, 103 insertions(+), 38 deletions(-) diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index 8d5988775..9b6528ad0 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:altme/app/app.dart'; import 'package:altme/dashboard/dashboard.dart'; import 'package:altme/oidc4vc/oidc4vc.dart'; +import 'package:altme/selective_disclosure/selective_disclosure.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:convert/convert.dart'; @@ -1591,3 +1592,67 @@ Future<(String?, String?, String?, String?)> getClientDetails({ } return (display, credentialSupported); } + +String? getClaimsData( + Map uncryptedDatas, + CredentialModel credentialModel, + String key, +) { + String? data; + + final JsonPath dataPath = JsonPath( + // ignore: prefer_interpolation_to_compose_strings + r'$..' + key, + ); + + try { + final uncryptedDataPath = dataPath.read(uncryptedDatas).first; + data = uncryptedDataPath.value.toString(); + } catch (e) { + try { + final credentialModelPath = dataPath.read(credentialModel.data).first; + data = credentialModelPath.value.toString(); + } catch (e) { + data = null; + } + } + + return data; +} + +String? getPicture({ + required CredentialModel credentialModel, +}) { + if (credentialModel.format.toString() != VCFormatType.vcSdJWT.value) { + return null; + } + + final credentialSupported = credentialModel.credentialSupported; + if (credentialSupported == null) return null; + + final claims = credentialSupported['claims']; + if (claims is! Map) return null; + + final picture = claims['picture']; + if (picture == null) return null; + if (picture is! Map) return null; + + if (picture.containsKey('mandatory')) { + final mandatory = picture['mandatory']; + if (mandatory is! bool) return null; + } + + final valueType = picture['value_type']; + if (valueType == null) return null; + + if (valueType == 'image/jpeg') { + final selectiveDisclosure = SelectiveDisclosure(credentialModel); + + final data = + getClaimsData(selectiveDisclosure.values, credentialModel, 'picture'); + + return data; + } else { + return null; + } +} diff --git a/lib/dashboard/home/tab_bar/credentials/detail/view/credentials_details_page.dart b/lib/dashboard/home/tab_bar/credentials/detail/view/credentials_details_page.dart index 072200dcc..594ee5bfb 100644 --- a/lib/dashboard/home/tab_bar/credentials/detail/view/credentials_details_page.dart +++ b/lib/dashboard/home/tab_bar/credentials/detail/view/credentials_details_page.dart @@ -144,6 +144,17 @@ class _CredentialsDetailsViewState extends State { final isSecure = profileData.profileSetting.selfSovereignIdentityOptions .customOidc4vcProfile.securityLevel; + final credentialSupported = widget.credentialModel.credentialSupported; + + final claims = credentialSupported?['claims']; + final containClaims = claims != null; + + String? credentialImage; + + if (containClaims) { + credentialImage = getPicture(credentialModel: widget.credentialModel); + } + return BlocConsumer( listener: (context, state) { if (state.status == AppStatus.loading) { @@ -188,11 +199,30 @@ class _CredentialsDetailsViewState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - CredentialDisplay( - credentialModel: widget.credentialModel, - credDisplayType: CredDisplayType.Detail, - profileSetting: profileSetting, - ), + if (credentialImage != null) + AspectRatio( + aspectRatio: Sizes.credentialAspectRatio, + child: ClipRRect( + borderRadius: BorderRadius.circular( + Sizes.credentialBorderRadius, + ), + child: CachedImageFromNetwork( + credentialImage, + fit: BoxFit.contain, + width: double.infinity, + bgColor: Colors.transparent, + height: double.infinity, + errorMessage: '', + showLoading: false, + ), + ), + ) + else + CredentialDisplay( + credentialModel: widget.credentialModel, + credDisplayType: CredDisplayType.Detail, + profileSetting: profileSetting, + ), const SizedBox(height: 20), Column( children: [ @@ -304,10 +334,7 @@ class _CredentialsDetailsViewState extends State { /// selective disclouse data - _sd /// and normal data too - if (widget.credentialModel.credentialSupported != - null && - widget.credentialModel.credentialSupported! - .containsKey('claims')) ...[ + if (containClaims) ...[ DisplaySelectiveDisclosure( credentialModel: widget.credentialModel, claims: null, diff --git a/lib/selective_disclosure/widget/display_selective_disclosure.dart b/lib/selective_disclosure/widget/display_selective_disclosure.dart index 12a843861..e3d21240d 100644 --- a/lib/selective_disclosure/widget/display_selective_disclosure.dart +++ b/lib/selective_disclosure/widget/display_selective_disclosure.dart @@ -6,7 +6,6 @@ import 'package:altme/selective_disclosure/selective_disclosure.dart'; import 'package:altme/theme/theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:json_path/json_path.dart'; class DisplaySelectiveDisclosure extends StatelessWidget { const DisplaySelectiveDisclosure({ @@ -45,7 +44,8 @@ class DisplaySelectiveDisclosure extends StatelessWidget { if (display == null) return Container(); title = display['name'].toString(); - data = getData(selectiveDisclosure.values, credentialModel, key); + data = + getClaimsData(selectiveDisclosure.values, credentialModel, key); if (data == null) return Container(); @@ -113,31 +113,4 @@ class DisplaySelectiveDisclosure extends StatelessWidget { return null; } } - - String? getData( - Map uncryptedDatas, - CredentialModel credentialModel, - String key, - ) { - String? data; - - final JsonPath dataPath = JsonPath( - // ignore: prefer_interpolation_to_compose_strings - r'$..' + key, - ); - - try { - final uncryptedDataPath = dataPath.read(uncryptedDatas).first; - data = uncryptedDataPath.value.toString(); - } catch (e) { - try { - final credentialModelPath = dataPath.read(credentialModel.data).first; - data = credentialModelPath.value.toString(); - } catch (e) { - data = null; - } - } - - return data; - } }