From 5f58aea3451a278f1d632038570bca61a4dc685f Mon Sep 17 00:00:00 2001 From: balachandarg-tw Date: Wed, 23 Apr 2025 13:03:01 +0530 Subject: [PATCH] [INJIMOB-3204]: Compass UI fixes (#1903) * [INJIMOB-3204]: Offline bluetooth VC sharing render fix Signed-off-by: BalachandarG * [INJIMOB-3204]: Flip Camera theme change and enabling share with selfie option for VC with image Signed-off-by: BalachandarG * [INJIMOB-3204]: Update tuvali version Signed-off-by: BalachandarG * [INJIMOB-3204]: Rename Title Case utils method Signed-off-by: BalachandarG --------- Signed-off-by: BalachandarG --- .talismanrc | 6 +++++- android/app/build.gradle | 12 +++++------ assets/Flip_Camera_Icon.svg | 2 +- components/VC/Views/VCCardView.tsx | 12 ++++++++++- components/VC/common/VCUtils.tsx | 3 ++- components/kebabMenuUtils.ts | 2 +- screens/Home/ViewVcModal.tsx | 18 ++++++++++++---- screens/Request/ReceiveVcScreen.tsx | 32 ++++++++++++++++++++--------- shared/Utils.ts | 9 ++++++++ 9 files changed, 71 insertions(+), 25 deletions(-) diff --git a/.talismanrc b/.talismanrc index c01a597d..485a61e0 100644 --- a/.talismanrc +++ b/.talismanrc @@ -274,7 +274,7 @@ fileignoreconfig: - filename: machines/Issuers/IssuersService.ts checksum: a87c0b8c73e0282e4c3075cef64effed9ecc456abaa369e9265f2c54e109e325 - filename: screens/Home/ViewVcModal.tsx - checksum: cfb25d562185488432b76287c4ef93359c1c64d8e29f5755d4c0a726c1485442 + checksum: 8965eddfed8058739e434161678ed2c4c39689926e38e235686d8369aabf1955 - filename: injitest/src/main/resources/TestData.json checksum: 1b5af14c96b456898259b4cb7a5607b006404cf0360274bdc204d7d065698e3c - filename: injitest/src/test/java/androidTestCases/ActivateVcTest.java @@ -398,4 +398,8 @@ fileignoreconfig: checksum: 6600a3d75033af4d702dd8c9663e12ad7c2c096a529bac2771bb856cc75a5ed0 - filename: locales/es.json checksum: a03fae655b13342afb45ab2b79998f3e06afcb02346c2ddf6aaacacf3b027209 + - filename: components/VC/Views/VCCardView.tsx + checksum: 0cab3ca20753328c19bb9681a0d7353dfece6bc6f9aefbf90cf7b36f2504bc53 + - filename: screens/Request/ReceiveVcScreen.tsx + checksum: ad4e831d935483d7ec8626b822cf36e431aef7dcdd914ec98f49bfe134b16b19 version: "" diff --git a/android/app/build.gradle b/android/app/build.gradle index f5c7ef9a..82a32c13 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -250,8 +250,8 @@ android { } packagingOptions { - pickFirst 'lib/arm64-v8a/liblog.so' - pickFirst 'lib/armeabi-v7a/liblog.so' + pickFirst 'lib/arm64-v8a/liblog.so' + pickFirst 'lib/armeabi-v7a/liblog.so' pickFirst 'lib/x86/liblog.so' pickFirst 'lib/x86_64/liblog.so' resources { @@ -267,7 +267,7 @@ dependencies { implementation 'com.facebook.soloader:soloader:0.10.1+' implementation("io.mosip:pixelpass-aar:0.6.0") implementation("io.mosip:secure-keystore:0.3.0") - implementation("io.mosip:tuvali:0.5.1") + implementation("io.mosip:tuvali:0.5.2-SNAPSHOT") implementation("io.mosip:inji-vci-client:0.2.0") implementation("com.google.code.gson:gson:2.10.1") implementation("io.mosip:vcverifier-aar:1.1.0"){ @@ -320,8 +320,8 @@ dependencies { } task copyFaceSdkModel(type: Copy) { - from '../../assets/models/' - include 'faceModel.tflite' + from '../../assets/models/' + include 'faceModel.tflite' into 'src/main/assets/' } @@ -342,4 +342,4 @@ apply from: file("../../node_modules/@react-native-community/cli-platform-androi // https://github.com/oblador/react-native-vector-icons?tab=readme-ov-file#android-setup apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle") -apply from: "./eas-build.gradle" \ No newline at end of file +apply from: "./eas-build.gradle" diff --git a/assets/Flip_Camera_Icon.svg b/assets/Flip_Camera_Icon.svg index 27b167ca..dfd7412f 100644 --- a/assets/Flip_Camera_Icon.svg +++ b/assets/Flip_Camera_Icon.svg @@ -11,7 +11,7 @@ - + diff --git a/components/VC/Views/VCCardView.tsx b/components/VC/Views/VCCardView.tsx index 1c3fd55e..b4592c94 100644 --- a/components/VC/Views/VCCardView.tsx +++ b/components/VC/Views/VCCardView.tsx @@ -10,7 +10,11 @@ import {VCCardSkeleton} from '../common/VCCardSkeleton'; import {VCCardViewContent} from './VCCardViewContent'; import {useVcItemController} from '../VCItemController'; import {getCredentialIssuersWellKnownConfig} from '../../../shared/openId4VCI/Utils'; -import {CARD_VIEW_DEFAULT_FIELDS, isVCLoaded} from '../common/VCUtils'; +import { + CARD_VIEW_DEFAULT_FIELDS, + DETAIL_VIEW_ADD_ON_FIELDS, + isVCLoaded, +} from '../common/VCUtils'; import {VCItemMachine} from '../../../machines/VerifiableCredential/VCItemMachine/VCItemMachine'; import {useTranslation} from 'react-i18next'; import {Copilot} from '../../ui/Copilot'; @@ -35,6 +39,8 @@ export const VCCardView: React.FC = props => { const [wellknown, setWellknown] = useState(null); const [vc, setVc] = useState(null); + const credential = controller.credential; + useEffect(() => { async function loadVc() { if (!props.isDownloading) { @@ -68,6 +74,10 @@ export const VCCardView: React.FC = props => { setFields(response.fields); }) .catch(error => { + const fields = Object.keys( + credential.credential.credentialSubject, + ).filter(key => key !== 'id' && key != 'face'); + setFields(fields.concat(DETAIL_VIEW_ADD_ON_FIELDS)); console.error( 'Error occurred while fetching wellknown for viewing VC ', error, diff --git a/components/VC/common/VCUtils.tsx b/components/VC/common/VCUtils.tsx index 70b00732..0db190dd 100644 --- a/components/VC/common/VCUtils.tsx +++ b/components/VC/common/VCUtils.tsx @@ -20,6 +20,7 @@ import { } from '../../../shared/openId4VCI/Utils'; import {VCFormat} from '../../../shared/VCFormat'; import {displayType} from '../../../machines/Issuers/IssuersMachine'; +import {toTitleCaseLabel, toTitleCaseLabel} from '../../../shared/Utils'; export const CARD_VIEW_DEFAULT_FIELDS = ['fullName']; export const DETAIL_VIEW_DEFAULT_FIELDS = [ @@ -146,7 +147,7 @@ export const getFieldName = ( } } } - return i18n.t(`VcDetails:${field}`); + return toTitleCaseLabel(i18n.t(`VcDetails:${field}`)); }; export function getAddressFields() { diff --git a/components/kebabMenuUtils.ts b/components/kebabMenuUtils.ts index 1a94fd88..eadb0853 100644 --- a/components/kebabMenuUtils.ts +++ b/components/kebabMenuUtils.ts @@ -68,7 +68,7 @@ export const getKebabMenuOptions = props => { if (props.vcMetadata.isVerified) { vcActionsList.splice(1, 0, share); - if (isMosipVC(props.vcMetadata.issuer)) { + if (isMosipVC(props.vcMetadata.issuer) || props.vcHasImage) { vcActionsList.splice(2, 0, shareWithSelfieOption, VCActivationOption); } if (props.vcMetadata.isExpired) { diff --git a/screens/Home/ViewVcModal.tsx b/screens/Home/ViewVcModal.tsx index d2a3dc12..6fdf6016 100644 --- a/screens/Home/ViewVcModal.tsx +++ b/screens/Home/ViewVcModal.tsx @@ -23,6 +23,7 @@ import {RemoveVcWarningOverlay} from './MyVcs/RemoveVcWarningOverlay'; import {HistoryTab} from './MyVcs/HistoryTab'; import {getDetailedViewFields} from '../../shared/openId4VCI/Utils'; import { + DETAIL_VIEW_ADD_ON_FIELDS, DETAIL_VIEW_DEFAULT_FIELDS, isVCLoaded, } from '../../components/VC/common/VCUtils'; @@ -42,6 +43,8 @@ export const ViewVcModal: React.FC = props => { const verificationStatus = controller.verificationStatus; const [verifiableCredential, setVerifiableCredential] = useState(null); + const credential = controller.credential; + useEffect(() => { async function processVC() { if (controller.credential) { @@ -79,10 +82,17 @@ export const ViewVcModal: React.FC = props => { verifiableCredentialData.credentialConfigurationId, DETAIL_VIEW_DEFAULT_FIELDS, verifiableCredentialData.vcMetadata.format, - ).then(response => { - setWellknown(response.matchingCredentialIssuerMetadata); - setFields(response.fields); - }); + ) + .then(response => { + setWellknown(response.matchingCredentialIssuerMetadata); + setFields(response.fields); + }) + .catch(() => { + const fields = Object.keys( + credential.credential.credentialSubject, + ).filter(key => key !== 'id' && key != 'face'); + setFields(fields.concat(DETAIL_VIEW_ADD_ON_FIELDS)); + }); }, [verifiableCredentialData?.wellKnown]); const headerRight = flow => { diff --git a/screens/Request/ReceiveVcScreen.tsx b/screens/Request/ReceiveVcScreen.tsx index fde7ffaa..d0f21bd3 100644 --- a/screens/Request/ReceiveVcScreen.tsx +++ b/screens/Request/ReceiveVcScreen.tsx @@ -9,9 +9,12 @@ import {useOverlayVisibleAfterTimeout} from '../../shared/hooks/useOverlayVisibl import {VcDetailsContainer} from '../../components/VC/VcDetailsContainer'; import {SharingStatusModal} from '../Scan/SharingStatusModal'; import {SvgImage} from '../../components/ui/svg'; -import {DETAIL_VIEW_DEFAULT_FIELDS} from '../../components/VC/common/VCUtils'; +import { + DETAIL_VIEW_ADD_ON_FIELDS, + DETAIL_VIEW_DEFAULT_FIELDS, +} from '../../components/VC/common/VCUtils'; import {getDetailedViewFields} from '../../shared/openId4VCI/Utils'; -import { VCProcessor } from '../../components/VC/common/VCProcessor'; +import {VCProcessor} from '../../components/VC/common/VCProcessor'; export const ReceiveVcScreen: React.FC = () => { const {t} = useTranslation('ReceiveVcScreen'); @@ -24,6 +27,8 @@ export const ReceiveVcScreen: React.FC = () => { const verifiableCredentialData = controller.verifiableCredentialData; const profileImage = verifiableCredentialData.face; + const verifiableCredential = controller.credential; + const [credential, setCredential] = useState(null); useEffect(() => { @@ -46,14 +51,21 @@ export const ReceiveVcScreen: React.FC = () => { verifiableCredentialData.credentialConfigurationId, DETAIL_VIEW_DEFAULT_FIELDS, verifiableCredentialData.vcMetadata.format, - ).then(response => { - setWellknown(response.matchingCredentialIssuerMetadata); - setFields(response.fields); - controller.STORE_INCOMING_VC_WELLKNOWN_CONFIG( - verifiableCredentialData?.issuer, - response.wellknownResponse, - ); - }); + ) + .then(response => { + setWellknown(response.matchingCredentialIssuerMetadata); + setFields(response.fields); + controller.STORE_INCOMING_VC_WELLKNOWN_CONFIG( + verifiableCredentialData?.issuer, + response.wellknownResponse, + ); + }) + .catch(() => { + const fields = Object.keys( + verifiableCredential.credential.credentialSubject, + ).filter(key => key !== 'id' && key != 'face'); + setFields(fields.concat(DETAIL_VIEW_ADD_ON_FIELDS)); + }); }, [verifiableCredentialData?.wellKnown]); return ( diff --git a/shared/Utils.ts b/shared/Utils.ts index e59367a9..0c59073f 100644 --- a/shared/Utils.ts +++ b/shared/Utils.ts @@ -54,3 +54,12 @@ export const parseJSON = (input: any) => { export const isNetworkError = (error: string) => { return error.includes(NETWORK_REQUEST_FAILED); }; + +export function toTitleCaseLabel(str: string): string { + if (str.includes(' ')) return str; + + return str + .replace(/([a-z])([A-Z])/g, '$1 $2') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') + .replace(/\b\w/g, char => char.toUpperCase()); +}