From cf6423f85e3900933db7e3f6258480de37d6b9b5 Mon Sep 17 00:00:00 2001 From: Alessandro Mazzon Date: Wed, 11 Dec 2024 18:10:22 +0100 Subject: [PATCH] feat(IT Wallet): [SIW-1853] Ipatente routing with IT Wallet (#6521) ## Short description This PR enables a link between the iPatente service and IT Wallet adding a custom route parsing the credentialType used by iPatente service. ## List of changes proposed in this pull request - A new error screen was added when the user tries to navigate to the credential without having that specific credential. - Added the navigation routing when using a specific deep link related to the iPatente service. ## How to test Use this deep link to navigate into the credential (MDL only) and check these results: - Wallet not active -> Error screen that route you to activate the wallet - Wallet active but MDL not requested -> Screen that route you to request the MDL - Wallet active MDL active -> MDL details screen Deep link to be used: `ioit://itw/presentation/credential-detail/MDL` Screenshot: ![IMAGE 2024-12-11 15:08:36](https://github.com/user-attachments/assets/ac182db6-273c-4163-bec7-670be8bb2b4d) --------- Co-authored-by: Federico Mastrini --- locales/en/index.yml | 3 + locales/it/index.yml | 3 + .../components/ItwCredentialNotFound.tsx | 61 +++++++++++++++++++ .../itwallet/navigation/ItwStackNavigator.tsx | 4 +- .../navigation/useItwLinkingOptions.tsx | 7 ++- .../ItwPresentationCredentialDetailScreen.tsx | 7 +-- 6 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 ts/features/itwallet/common/components/ItwCredentialNotFound.tsx diff --git a/locales/en/index.yml b/locales/en/index.yml index 38d9d105f8a..0a19dad2cd7 100644 --- a/locales/en/index.yml +++ b/locales/en/index.yml @@ -3432,6 +3432,9 @@ features: bodyBold: Documenti su IO primaryAction: Inizia secondaryAction: Non ora + credentialNotFound: + title: "Aggiungi il documento al Portafoglio" + subtitle: "Per usare i documenti su IO, prima aggiungili al Portafoglio. È facile e veloce." unsupportedDevice: text: Starting from 02.07.2024 your device may no longer be compatible with IO. moreInfo: More info diff --git a/locales/it/index.yml b/locales/it/index.yml index 10c69323e1d..df363048c71 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -3432,6 +3432,9 @@ features: bodyBold: Documenti su IO primaryAction: Inizia secondaryAction: Non ora + credentialNotFound: + title: "Aggiungi il documento al Portafoglio" + subtitle: "Per usare i documenti su IO, prima aggiungili al Portafoglio. È facile e veloce." unsupportedDevice: text: Starting from 02.07.2024 your device may no longer be compatible with IO. moreInfo: More info diff --git a/ts/features/itwallet/common/components/ItwCredentialNotFound.tsx b/ts/features/itwallet/common/components/ItwCredentialNotFound.tsx new file mode 100644 index 00000000000..e91968b3a9b --- /dev/null +++ b/ts/features/itwallet/common/components/ItwCredentialNotFound.tsx @@ -0,0 +1,61 @@ +import React, { useEffect } from "react"; +import { OperationResultScreenContent } from "../../../../components/screens/OperationResultScreenContent"; +import I18n from "../../../../i18n"; +import { ItwCredentialIssuanceMachineContext } from "../../machine/provider"; +import { useIONavigation } from "../../../../navigation/params/AppParamsList"; +import { useItwDisableGestureNavigation } from "../hooks/useItwDisableGestureNavigation"; +import { useAvoidHardwareBackButton } from "../../../../utils/useAvoidHardwareBackButton"; + +const ItwCredentialNotFound = ({ + credentialType +}: { + credentialType: string; +}) => { + const machineRef = ItwCredentialIssuanceMachineContext.useActorRef(); + const navigation = useIONavigation(); + + // Disable the back gesture navigation and the hardware back button + useItwDisableGestureNavigation(); + useAvoidHardwareBackButton(); + + const navigateToCredential = () => { + machineRef.send({ + type: "select-credential", + credentialType + }); + }; + + const handleClose = () => { + navigation.pop(); + }; + + // Since this component could be used on a screen where the header is visible, we hide it. + useEffect(() => { + navigation.setOptions({ + headerShown: false + }); + }, [navigation]); + + return ( + + ); +}; + +export default ItwCredentialNotFound; diff --git a/ts/features/itwallet/navigation/ItwStackNavigator.tsx b/ts/features/itwallet/navigation/ItwStackNavigator.tsx index 910194bb201..488070b6b78 100644 --- a/ts/features/itwallet/navigation/ItwStackNavigator.tsx +++ b/ts/features/itwallet/navigation/ItwStackNavigator.tsx @@ -1,6 +1,6 @@ import { - TransitionPresets, - createStackNavigator + createStackNavigator, + TransitionPresets } from "@react-navigation/stack"; import * as React from "react"; import { Platform } from "react-native"; diff --git a/ts/features/itwallet/navigation/useItwLinkingOptions.tsx b/ts/features/itwallet/navigation/useItwLinkingOptions.tsx index 6820d3772a1..7be580454c1 100644 --- a/ts/features/itwallet/navigation/useItwLinkingOptions.tsx +++ b/ts/features/itwallet/navigation/useItwLinkingOptions.tsx @@ -22,7 +22,12 @@ export const useItwLinkingOptions = (): PathConfigMap => { "credential/issuance", [isItwValid ? ITW_ROUTES.DISCOVERY.ALREADY_ACTIVE_SCREEN - : ITW_ROUTES.DISCOVERY.INFO]: "discovery/info" + : ITW_ROUTES.DISCOVERY.INFO]: "discovery/info", + [isItwValid + ? ITW_ROUTES.PRESENTATION.CREDENTIAL_DETAIL + : ITW_ROUTES.ISSUANCE.CREDENTIAL_ASYNC_FLOW_CONTINUATION]: { + path: "presentation/credential-detail/:credentialType" + } }) } } diff --git a/ts/features/itwallet/presentation/screens/ItwPresentationCredentialDetailScreen.tsx b/ts/features/itwallet/presentation/screens/ItwPresentationCredentialDetailScreen.tsx index 82c99a17e16..8f0b90abc6a 100644 --- a/ts/features/itwallet/presentation/screens/ItwPresentationCredentialDetailScreen.tsx +++ b/ts/features/itwallet/presentation/screens/ItwPresentationCredentialDetailScreen.tsx @@ -14,7 +14,6 @@ import { trackCredentialDetail, trackWalletCredentialShowFAC_SIMILE } from "../../analytics"; -import { ItwGenericErrorContent } from "../../common/components/ItwGenericErrorContent"; import { WellKnownClaim } from "../../common/utils/itwClaimsUtils"; import { StoredCredential } from "../../common/utils/itwTypesUtils"; import { @@ -35,6 +34,7 @@ import { ItwPresentationDetailsScreenBase } from "../components/ItwPresentationDetailsScreenBase"; import { ItwCredentialTrustmark } from "../../trustmark/components/ItwCredentialTrustmark"; +import ItwCredentialNotFound from "../../common/components/ItwCredentialNotFound"; export type ItwPresentationCredentialDetailNavigationParams = { credentialType: string; @@ -55,9 +55,8 @@ export const ItwPresentationCredentialDetailScreen = ({ route }: Props) => { ); if (O.isNone(credentialOption)) { - // This is unlikely to happen, but we want to handle the case where the credential is not found - // because of inconsistencies in the state, and assert that the credential is O.some - return ; + // If the credential is not found, we render a screen that allows the user to request that credential. + return ; } return (