Files
inji-wallet/screens/Scan/ScanScreen.tsx
PuBHARGAVI fe59309e88 [Injimob 812] openID4VP sharing flow UI implementation (#1628)
* [INJIMOB-1629] add an api to fetch the trusted verifiers list for vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add screens for showing vcs matching openId4vp authorization request and selecting VCs

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add states in scan machine to show loader screen when vp sharing is started

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] send events to parent machine from openId4vp machine to update UI when performing vp sharing

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] change the position of check box in vc container in vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add styles to send vp screen elements to match wireframe and add context variable to store vp sharing purpose

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] show error screen if no credential in wallet matches with authorization request

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] show confirmation pop up when user decline the consent for sharing vp

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] show error screen if the verifier authentication is failed after scanning vp sharing qr code

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] move error and overlay details assigning logic to send vp screen controller

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add translations for vp sharing flow texts in all languages

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] make changes in card skeleton component to show vc card loader in vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] fix issues with reject button in sharing vp screen

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add support for sharing vp with out selfie from kebab menu

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add support for sharing vp with selfie from kebab menu

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add missing translations for error and overlay screen texts of vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add logic in scan screen to show error screens in vp sharing from kebab menu flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add logic to filter the VCs based on the type of the VC in vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812]: generate proof for vp token and send vp

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-1629] show generic error message if any error occured while validating vp qr code

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add logic to allow user retry vp sharing 3 times if any technical error occurred

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] add react method in native module to send the generated vp response metadata and make changes to show any errors occured after sharing vp

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-1629] show success screen if vp is shared successfully to the verifier

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812]: refactor proof generation and integrate remote openid4vp package

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-812]: refactor proof generation and integrate remote openid4vp package

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-812] make changes in the code to fetch the VCs properly if scope is present in the authorization code

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] fix the logic of checking if order field value in issuer wellknown is null and empty or not

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] move qr login and openid4vp red id's to scan actions

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] remove unnecessary logs

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] rename openid4vp actions to make them more meaningful and remove unnecessary events in send vp screen controller

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] show error screen if none of the selected VC has image but user chosen share with selfie option

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] add guard logic for checking if any of the selected VC has image or not

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812]: update package resolved with openid4vp library

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-812] fix the logic of retry button in technical error screen and perform the vp sharing again when user click on retry button

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] show specific error screen if required info is missing in qr code

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812]: refactor native module and wrapper with updated library name

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-1709]: Integrate VC verifier aar for Vc verification of Mosip VC (#1624)

* [INJIMOB-1709]: integrate VC verifier aar for Vc verification of Mosip VC

Signed-off-by: Alka Prasad <prasadalka1998@gmail.com>

* [INJIMOB-1709]: Handling Response from Vc Verifier Library

Signed-off-by: BalachandarG <balachandar.g@thoughtworks.com>

* [INJIMOB-1709]: Removed mavenLocal from build.gradle

Signed-off-by: BalachandarG <balachandar.g@thoughtworks.com>

* [INJIMOB-1709]: Updated build.gradle

Signed-off-by: BalachandarG <balachandar.g@thoughtworks.com>

* [INJIMOB-1709]: Removed Certify from isMosipVC Condition.

Signed-off-by: BalachandarG <balachandar.g@thoughtworks.com>

* [INJIMOB-1709]: Adding isAndroid check and verifying using digital bazaar for iOs.

Signed-off-by: BalachandarG <balachandar.g@thoughtworks.com>

---------

Signed-off-by: Alka Prasad <prasadalka1998@gmail.com>
Signed-off-by: BalachandarG <balachandar.g@thoughtworks.com>
Co-authored-by: Alka Prasad <prasadalka1998@gmail.com>

* [INJIMOB-1629] rename openId4VP to openID4VP in all files and address pr comments

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] fetch trusted verifiers list from mimoto end point

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] rename openId4VP to openID4VP in all files

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] make trusted verifier api call cache preferred

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] rename openId4VP to openID4VP in all places

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812]: refactor and update openid4vp swift library

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-812] remove code related to scope in openid4vp flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] remove code related to type in openid4vp actions

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] rename response_uri to response_uris in openid4vp native wrappers

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] rename typegen file in openid4vp machine

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] change target state of checkFaceAuthConsent to getTrustedVerifiersList

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812]: update openid4vp swift package

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-2097]: bump up app version to 0.15.0 (#1631)

Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>
Co-authored-by: adityankannan-tw <adityan410pm@gmail.com>

* [INJIMOB-1884] remove SetupKeySelectionScreen (#1632)

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

* [INJIMOB-812] change the conditional logic for checking if downloading error is generic or not in issuer guards and selectors

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] fetch the trusted verifiers list properly from api response

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] send the list of selected vcs images to face scanner machine only if face is available

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] fix home button navigation issue in error screen of vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] move openid4vp machine to showError state if there is any occurred in vp sharing flow and reset error when user navigates to home screen

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] fix some flows in vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJIMOB-812] fix the logic for showing the error screen as part of scan screen in vp sharing flow

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

---------

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
Signed-off-by: adityankannan-tw <adityan410pm@gmail.com>
Signed-off-by: Alka Prasad <prasadalka1998@gmail.com>
Signed-off-by: BalachandarG <balachandar.g@thoughtworks.com>
Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Co-authored-by: adityankannan-tw <adityan410pm@gmail.com>
Co-authored-by: balachandarg-tw <115633327+balachandarg-tw@users.noreply.github.com>
Co-authored-by: Alka Prasad <prasadalka1998@gmail.com>
Co-authored-by: adityankannan-tw <109274996+adityankannan-tw@users.noreply.github.com>
Co-authored-by: abhip2565 <74866247+abhip2565@users.noreply.github.com>
2024-10-04 11:21:16 +05:30

353 lines
11 KiB
TypeScript

import React, {useEffect, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {
ErrorMessageOverlay,
MessageOverlay,
} from '../../components/MessageOverlay';
import {QrScanner} from '../../components/QrScanner';
import {Button, Centered, Column, Text} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils';
import {QrLogin} from '../QrLogin/QrLogin';
import {useScanScreen} from './ScanScreenController';
import BluetoothStateManager from 'react-native-bluetooth-state-manager';
import {Linking} from 'react-native';
import {isIOS, LIVENESS_CHECK} from '../../shared/constants';
import {BannerNotificationContainer} from '../../components/BannerNotificationContainer';
import {SharingStatusModal} from './SharingStatusModal';
import {SvgImage} from '../../components/ui/svg';
import {LocationPermissionRational} from './LocationPermissionRational';
import {FaceVerificationAlertOverlay} from './FaceVerificationAlertOverlay';
import {useSendVcScreen} from './SendVcScreenController';
import {useSendVPScreen} from './SendVPScreenController';
import {Error} from '../../components/ui/Error';
import {VPShareOverlay} from './VPShareOverlay';
import {VerifyIdentityOverlay} from '../VerifyIdentityOverlay';
import {VCShareFlowType} from '../../shared/Utils';
export const ScanScreen: React.FC = () => {
const {t} = useTranslation('ScanScreen');
const scanScreenController = useScanScreen();
const sendVcScreenController = useSendVcScreen();
const sendVPScreenController = useSendVPScreen();
const [isBluetoothOn, setIsBluetoothOn] = useState(false);
const showErrorModal =
sendVPScreenController.scanScreenError ||
(sendVPScreenController.errorModal.show &&
(sendVPScreenController.flowType ===
VCShareFlowType.MINI_VIEW_SHARE_OPENID4VP ||
sendVPScreenController.flowType ===
VCShareFlowType.MINI_VIEW_SHARE_WITH_SELFIE_OPENID4VP));
useEffect(() => {
(async () => {
await BluetoothStateManager.onStateChange(state => {
if (state === 'PoweredOff') {
setIsBluetoothOn(false);
} else {
setIsBluetoothOn(true);
}
}, true);
})();
}, [isBluetoothOn]);
// TODO(kludge): skip running this hook on every render
useEffect(() => {
if (
scanScreenController.isStartPermissionCheck &&
!scanScreenController.isEmpty
)
scanScreenController.START_PERMISSION_CHECK();
});
useEffect(() => {
if (scanScreenController.isQuickShareDone) scanScreenController.GOTO_HOME();
}, [scanScreenController.isQuickShareDone]);
const openSettings = () => {
Linking.openSettings();
};
const handleTextButtonEvent = () => {
sendVPScreenController.GO_TO_HOME();
sendVPScreenController.RESET_RETRY_COUNT();
};
function noShareableVcText() {
return (
<Text
testID="noShareableVcs"
align="center"
style={{paddingTop: 3}}
color={Theme.Colors.errorMessage}
margin="0 10">
{t('noShareableVcs')}
</Text>
);
}
function bluetoothIsOffText() {
return (
<Text
testID="bluetoothIsTurnedOffMessage"
align="center"
color={Theme.Colors.errorMessage}
margin="0 10">
{t(isIOS() ? 'bluetoothStateIos' : 'bluetoothStateAndroid')}
</Text>
);
}
function allowBluetoothPermissionComponent() {
return (
<Column padding="24" fill align="space-between">
<Centered fill>
<Text
align="center"
testID="enableBluetoothMessage"
color={Theme.Colors.errorMessage}>
{t('enableBluetoothMessage')}
</Text>
</Centered>
<Button
testID="enableBluetoothButton"
title={t('enableBluetoothButtonText')}
onPress={openSettings}
/>
</Column>
);
}
function allowNearbyDevicesPermissionComponent() {
return (
<Column padding="24" fill align="space-between">
<Centered fill>
<Text
testID="allowNearbyDevicesPermissionMessage"
align="center"
color={Theme.Colors.errorMessage}>
{t('errors.nearbyDevicesPermissionDenied.message')}
</Text>
</Centered>
<Button
testID="allowNearbyDevicesPermissionButton"
title={t('errors.nearbyDevicesPermissionDenied.button')}
onPress={openSettings}
/>
</Column>
);
}
function allowLocationComponent() {
return (
<Column padding="24" fill align="space-between">
<Centered fill>
<Text
testID="enableLocationServicesMessage"
align="center"
color={Theme.Colors.errorMessage}>
{scanScreenController.locationError.message}
</Text>
</Centered>
<Button
testID="enableLocationServicesButton"
title={scanScreenController.locationError.button}
onPress={scanScreenController.LOCATION_REQUEST}
/>
</Column>
);
}
function qrScannerComponent() {
return (
<Column crossAlign="center">
<QrScanner
onQrFound={scanScreenController.SCAN}
title={t('scanningGuide')}
/>
</Column>
);
}
function loadQRScanner() {
if (scanScreenController.isEmpty) {
return noShareableVcText();
}
if (scanScreenController.selectIsInvalid) {
return displayInvalidQRpopup();
}
if (scanScreenController.isNearByDevicesPermissionDenied) {
return allowNearbyDevicesPermissionComponent();
}
if (
(scanScreenController.isBluetoothDenied || !isBluetoothOn) &&
scanScreenController.isReadyForBluetoothStateCheck
) {
return bluetoothIsOffText();
}
if (scanScreenController.isLocalPermissionRational) {
return (
<LocationPermissionRational
onConfirm={scanScreenController.ALLOWED}
onCancel={scanScreenController.DENIED}
/>
);
}
if (
scanScreenController.isLocationDisabled ||
scanScreenController.isLocationDenied
) {
return allowLocationComponent();
}
if (scanScreenController.isBluetoothPermissionDenied) {
return allowBluetoothPermissionComponent();
}
if (scanScreenController.isScanning) {
return qrScannerComponent();
}
}
function displayStorageLimitReachedError(): React.ReactNode {
return (
!scanScreenController.isEmpty && (
<ErrorMessageOverlay
testID="storageLimitReachedError"
isVisible={
scanScreenController.isMinimumStorageRequiredForAuditEntryLimitReached
}
translationPath={'ScanScreen'}
error="errors.storageLimitReached"
onDismiss={scanScreenController.GOTO_HOME}
/>
)
);
}
function displayInvalidQRpopup(): React.ReactNode {
return (
!scanScreenController.isEmpty && (
<SharingStatusModal
isVisible={scanScreenController.selectIsInvalid}
testId={'invalidQrPopup'}
image={SvgImage.ErrorLogo()}
title={t(`status.bleError.TVW_CON_001.title`)}
message={t(`status.bleError.TVW_CON_001.message`)}
gradientButtonTitle={t('status.bleError.retry')}
clearButtonTitle={t('status.bleError.home')}
onGradientButton={scanScreenController.DISMISS}
onClearButton={scanScreenController.GOTO_HOME}
/>
)
);
}
const faceVerificationController = sendVPScreenController.flowType.startsWith(
'OpenID4VP',
)
? sendVPScreenController
: sendVcScreenController;
return (
<Column fill backgroundColor={Theme.Colors.whiteBackgroundColor}>
<BannerNotificationContainer />
<FaceVerificationAlertOverlay
isVisible={faceVerificationController.isFaceVerificationConsent}
onConfirm={faceVerificationController.FACE_VERIFICATION_CONSENT}
close={faceVerificationController.DISMISS}
/>
<Centered
padding="24 0"
align="space-evenly"
backgroundColor={Theme.Colors.whiteBackgroundColor}>
{loadQRScanner()}
{scanScreenController.isQrLogin && (
<QrLogin
isVisible={scanScreenController.isQrLogin}
service={scanScreenController.isQrRef}
/>
)}
<MessageOverlay
isVisible={scanScreenController.isQrLoginstoring}
title={t('loading')}
progress
/>
</Centered>
{displayStorageLimitReachedError()}
{sendVPScreenController.flowType.startsWith('OpenID4VP') &&
sendVPScreenController.flowType !== VCShareFlowType.OPENID4VP &&
sendVPScreenController.overlayDetails !== null && (
<VPShareOverlay
isVisible={sendVPScreenController.overlayDetails !== null}
title={sendVPScreenController.overlayDetails.title}
titleTestID={sendVPScreenController.overlayDetails.titleTestID}
message={sendVPScreenController.overlayDetails.message}
messageTestID={sendVPScreenController.overlayDetails.messageTestID}
primaryButtonTestID={
sendVPScreenController.overlayDetails.primaryButtonTestID
}
primaryButtonText={
sendVPScreenController.overlayDetails.primaryButtonText
}
primaryButtonEvent={
sendVPScreenController.overlayDetails.primaryButtonEvent
}
secondaryButtonTestID={
sendVPScreenController.overlayDetails.secondaryButtonTestID
}
secondaryButtonText={
sendVPScreenController.overlayDetails.secondaryButtonText
}
secondaryButtonEvent={
sendVPScreenController.overlayDetails.secondaryButtonEvent
}
/>
)}
<>
<Error
isModal
alignActionsOnEnd
showClose={false}
isVisible={showErrorModal}
title={sendVPScreenController.errorModal.title}
message={sendVPScreenController.errorModal.message}
image={SvgImage.PermissionDenied()}
primaryButtonTestID={'retry'}
primaryButtonText={
sendVPScreenController.errorModal.showRetryButton &&
sendVPScreenController.openID4VPRetryCount < 3
? t('ScanScreen:status.retry')
: undefined
}
primaryButtonEvent={sendVPScreenController.RETRY}
textButtonTestID={'home'}
textButtonText={t('ScanScreen:status.accepted.home')}
textButtonEvent={handleTextButtonEvent}
customImageStyles={{paddingBottom: 0, marginBottom: -6}}
customStyles={{marginTop: '30%'}}
testID={'vpShareError'}
/>
<VerifyIdentityOverlay
credential={sendVPScreenController.credentials}
verifiableCredentialData={
sendVPScreenController.verifiableCredentialsData
}
isVerifyingIdentity={sendVPScreenController.isVerifyingIdentity}
onCancel={sendVPScreenController.CANCEL}
onFaceValid={sendVPScreenController.FACE_VALID}
onFaceInvalid={sendVPScreenController.FACE_INVALID}
isInvalidIdentity={sendVPScreenController.isInvalidIdentity}
onNavigateHome={sendVPScreenController.GO_TO_HOME}
onRetryVerification={sendVPScreenController.RETRY_VERIFICATION}
isLivenessEnabled={LIVENESS_CHECK}
/>
</>
</Column>
);
};