Files
inji-wallet/components/VC/Views/VCDetailView.tsx
KiruthikaJeyashankar 68488f3f0c [INJIMOB-2381] fix compile and target SDK 34 is causing app crash in debug build (#1877)
* [INJIMOB-2381] update package.json and resolve dependencies for react 0.73.0

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-2381] setup for 0.73.6

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-2381] fix font & image not loading issue

changes include
- move common image assets to android & iOS folders
- update gradle version to 8.2
- add expo-font asset for Inter regular
- replace useFont with expo-font
- remove flipper (reason: 0.74 react native decoupled flipper)
- npm package updates
- close icon changed to close text in QRScanner.tsx

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-2381] update android:mosip script as per updated react native version

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix android build failure issue

Changes include:
- rename android assets folder as per convention
- remove unused biometrics dependency
- use env from react-native-dotenv as per module registered in babel config
- revert conversion of close icon to image in QRScanner component

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix iOS build issue

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] rm unused local images linking in adnroid

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix splash screen not rendering issue in android

Issue: Local assets were not loaded via React Native Image component in android, to fix this @react-native/assets-registry has been added
Reference: https://github.com/expo/expo/issues/31240#issuecomment-2459049911

Other changes:
- remove usage of expo-image as we dont have any explicit usecase for expo-image and its unused

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] rm unused intro slider image assets

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] revert back using local font assets in android

Reason: Previously expo-font was used for fonts, to bring back the same compatiblity it is bought back

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] use GestureHandlerRootView in root level to handle gestures

ref - https://docs.swmansion.com/react-native-gesture-handler/docs/1.x/#js

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove custom assets and linking for images in iOS

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] use default parameters instead of defaultProps

Reason: React 18 has marked defaultProps as deprecated and it is removed in React 19 version. To avoid the issue of deprated usage, its modified.

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove unused terminal option in android build script

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove font assets in android

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] optimize import

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix failing test

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] set package.resolved version to 2

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix setting of camera view in face scanner

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix setting of camera view in face compare

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove flipper config file

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove unused debug logs

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor use component instead of type

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor use GestureHandlerRootView only on root level

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor remove unused config linking of font assets

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] refactor remove unused image assets

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] fix camera persmission issue in QRScanner

use expo-camera to request and getstatus of camera permission instead of expo-barcode-scanner to avoid multiple re-renders of scan screen in flow of camera permission denial

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove package expo-barcode-scanner

expo-barcode-scanner is deprecated and its suggested to use expo-camera to handle the scanning flows. The existing bar-code-scanner implementations have been replaced with expo-camera.

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] use extracted enums instead of legacy expo-camera

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove patch for react-native-0.71.8

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] revert date-fs version to 2.28.0

date-fns is not supporting filipino langauge, so we are maintaining patch for that. The patch created is for version 2.28.0 and updating the version of date-fns is causing conflicts in patch application if updated as well. To avoid this issue, version is kept as 2.28.0

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] update readme

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] remove usage of legacy expo-camera in getting image type

Other changes
- remove resolutions block from package.json
- sync pbxproj

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-2381] add active prop to expo-camera as per suggestions

expo-camera suggests "Only one Camera preview can be active at any given time. If you have multiple screens in your app, you should unmount Camera components whenever a screen is unfocused.". To handle this active prop is used which is set to false on unMount of the component whenever rendering Camera from expo-camera

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

---------

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Signed-off-by: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com>
Co-authored-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Co-authored-by: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com>
2025-04-10 14:37:41 +05:30

259 lines
9.0 KiB
TypeScript

import React from 'react';
import {useTranslation} from 'react-i18next';
import {Image, ImageBackground, ImageBackgroundProps, View} from 'react-native';
import {
Credential,
CredentialWrapper,
VerifiableCredential,
VerifiableCredentialData,
WalletBindingResponse,
} from '../../../machines/VerifiableCredential/VCMetaMachine/vc';
import {Button, Column, Row, Text} from '../../ui';
import {Theme} from '../../ui/styleUtils';
import {QrCodeOverlay} from '../../QrCodeOverlay';
import {SvgImage} from '../../ui/svg';
import {isActivationNeeded} from '../../../shared/openId4VCI/Utils';
import {
BOTTOM_SECTION_FIELDS_WITH_DETAILED_ADDRESS_FIELDS,
DETAIL_VIEW_BOTTOM_SECTION_FIELDS,
Display,
KEY_TYPE_FIELD,
fieldItemIterator,
} from '../common/VCUtils';
import {ProfileIcon} from '../../ProfileIcon';
import {VCFormat} from '../../../shared/VCFormat';
import {VCItemField} from '../common/VCItemField';
const getProfileImage = (face: any) => {
if (face) {
return (
<Image source={{uri: face}} style={Theme.Styles.detailedViewImage} />
);
}
return (
<ProfileIcon
profileIconContainerStyles={Theme.Styles.openCardProfileIconContainer}
profileIconSize={40}
/>
);
};
export const VCDetailView: React.FC<VCItemDetailsProps> = (props: VCItemDetailsProps) => {
const {t} = useTranslation('VcDetails');
const logo = props.verifiableCredentialData.issuerLogo;
const face = props.verifiableCredentialData.face;
const verifiableCredential = props.credential;
const wellknownDisplayProperty = new Display(props.wellknown);
const shouldShowHrLine = verifiableCredential => {
let availableFieldNames: string[] = [];
if (props.verifiableCredentialData.vcMetadata.format === VCFormat.ldp_vc) {
availableFieldNames = Object.keys(
verifiableCredential?.credentialSubject,
);
} else if (
props.verifiableCredentialData.vcMetadata.format === VCFormat.mso_mdoc
) {
const namespaces = verifiableCredential['issuerSigned']['nameSpaces'];
Object.keys(namespaces).forEach(namespace => {
(namespaces[namespace] as Array<Object>).forEach(element => {
availableFieldNames.push(
`${namespace}~${element['elementIdentifier']}`,
);
});
});
}
for (const fieldName of availableFieldNames) {
if (
BOTTOM_SECTION_FIELDS_WITH_DETAILED_ADDRESS_FIELDS.includes(fieldName)
) {
return true;
}
}
return false;
};
return (
<>
<Column scroll>
<Column fill>
<Column
padding="10 10 3 10"
backgroundColor={Theme.Colors.DetailedViewBackground}>
<ImageBackground
imageStyle={Theme.Styles.vcDetailBg}
resizeMethod="scale"
resizeMode="stretch"
style={[
Theme.Styles.openCardBgContainer,
wellknownDisplayProperty.getBackgroundColor(),
]}
source={wellknownDisplayProperty.getBackgroundImage(
Theme.OpenCard,
) as ImageBackgroundProps}>
<Row padding="14 14 0 14" margin="0 0 0 0">
<Column crossAlign="center">
{getProfileImage(face)}
<QrCodeOverlay
verifiableCredential={
props.credentialWrapper as unknown as VerifiableCredential
}
meta={props.verifiableCredentialData.vcMetadata}
/>
<Column
width={80}
height={59}
crossAlign="center"
margin="12 0 0 0">
<Image
src={logo?.url}
alt={logo?.alt_text}
style={Theme.Styles.issuerLogo}
resizeMethod="scale"
resizeMode="contain"
/>
</Column>
</Column>
<Column
align="space-evenly"
margin={'0 0 0 24'}
style={{flex: 1}}>
{fieldItemIterator(
props.fields,
verifiableCredential,
props.wellknown,
wellknownDisplayProperty,
props,
)}
</Column>
</Row>
<>
<View
style={[
Theme.Styles.hrLine,
{
borderBottomColor: wellknownDisplayProperty.getTextColor(
Theme.Styles.hrLine.borderBottomColor,
),
},
]}></View>
<Column padding="0 14 14 14">
{shouldShowHrLine(verifiableCredential) &&
fieldItemIterator(
DETAIL_VIEW_BOTTOM_SECTION_FIELDS,
verifiableCredential,
props.wellknown,
wellknownDisplayProperty,
props,
)}
<VCItemField
key={'keyTypeVcDetailView'}
fieldName={KEY_TYPE_FIELD}
fieldValue={props.keyType}
testID={'keyTypeVcDetailView'}
/>
</Column>
</>
</ImageBackground>
</Column>
</Column>
</Column>
{props.vcHasImage &&
!props.verifiableCredentialData?.vcMetadata.isExpired && (
<View
style={{
position: 'relative',
backgroundColor: Theme.Colors.DetailedViewBackground,
}}>
{props.activeTab !== 1 &&
(!props.walletBindingResponse &&
isActivationNeeded(props.verifiableCredentialData?.issuer) ? (
<Column
padding="10"
style={Theme.Styles.detailedViewActivationPopupContainer}>
<Row>
<Column crossAlign="flex-start" margin={'2 0 0 10'}>
{SvgImage.WalletUnActivatedLargeIcon()}
</Column>
<Column crossAlign="flex-start" margin={'5 18 13 8'}>
<Text
testID="offlineAuthDisabledHeader"
style={{
fontFamily: 'Inter_600SemiBold',
fontSize: 14,
}}
color={Theme.Colors.statusLabel}
margin={'0 18 0 0'}>
{t('offlineAuthDisabledHeader')}
</Text>
<Text
testID="offlineAuthDisabledMessage"
style={{
fontFamily: 'Inter_400Regular',
fontSize: 12,
}}
color={Theme.Colors.statusMessage}
margin={'0 18 0 0'}>
{t('offlineAuthDisabledMessage')}
</Text>
</Column>
</Row>
<Button
testID="enableVerification"
title={t('enableVerification')}
onPress={props.onBinding}
type="gradient"
size="Large"
disabled={
!props.verifiableCredentialData.vcMetadata.isVerified
}
/>
</Column>
) : (
<Column
style={Theme.Styles.detailedViewActivationPopupContainer}
padding="10">
<Row>
<Column crossAlign="flex-start" margin={'2 0 0 10'}>
{SvgImage.WalletActivatedLargeIcon()}
</Column>
<Column crossAlign="flex-start" margin={'5 18 13 8'}>
<Text
testID="profileAuthenticated"
color={Theme.Colors.statusLabel}
style={{
fontFamily: 'Inter_600SemiBold',
fontSize: 14,
}}
margin={'0 18 0 0'}>
{isActivationNeeded(
props.verifiableCredentialData?.issuer,
)
? t('profileAuthenticated')
: t('credentialActivated')}
</Text>
</Column>
</Row>
</Column>
))}
</View>
)}
</>
);
};
export interface VCItemDetailsProps {
fields: any[];
wellknown: any;
credential: VerifiableCredential | Credential;
verifiableCredentialData: VerifiableCredentialData;
walletBindingResponse?: WalletBindingResponse;
credentialWrapper: CredentialWrapper;
onBinding?: () => void;
activeTab?: Number;
vcHasImage: boolean;
keyType: string;
}