Skip to content

Commit

Permalink
chore(IT Wallet): [SIW-675] Add QR Code screen during proximity flow (#…
Browse files Browse the repository at this point in the history
…5238)

## Short description
This PR adds the QRCode screen during proximity flow (for testing
purposes the qr-code content is mocked with a fake mDoc payload). Having
created the proximity package that uses an event manager on the UX/UI
side, messages can be conveyed based on the progress of the
presentation. I therefore used a loading message, a message that can
vary based on the progress of the presentation.


https://github.com/pagopa/io-app/assets/49342144/f55ffed6-0562-4bf1-880c-da7efc72eb2d

## List of changes proposed in this pull request
- Add ItwPresentationQrCodeScreen.tsx

## How to test
Open the credential details and tap "Show QR Code". The new screen
should appear.

---------

Co-authored-by: LazyAfternoons <[email protected]>
  • Loading branch information
hevelius and LazyAfternoons authored Nov 29, 2023
1 parent 485bc99 commit b732ece
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 2 deletions.
2 changes: 2 additions & 0 deletions locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3432,6 +3432,8 @@ features:
success:
title: "Done!"
subtitle: "Go back to the {{organizationName}} website to continue."
qrCodeScreen:
loading: "Wait a few seconds for the verification request..."
missingFeatureScreen:
headerTitle: "Screen not available"
title: "This screen will be available soon."
Expand Down
2 changes: 2 additions & 0 deletions locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3433,6 +3433,8 @@ features:
success:
title: "Fatto!"
subtitle: "Torna sul sito di {{organizationName}} per continuare."
qrCodeScreen:
loading: "Attendi qualche secondo la richiesta di verifica..."
missingFeatureScreen:
headerTitle: "Schermata non disponibile"
title: "Questa schermata sarà presto disponibile"
Expand Down
3 changes: 3 additions & 0 deletions ts/features/it-wallet/navigation/ItwParamsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export type ItwParamsList = {
[ITW_ROUTES.PRESENTATION.CREDENTIAL.REMOTE.DATA]: undefined;
[ITW_ROUTES.PRESENTATION.CREDENTIAL.REMOTE.RESULT]: undefined;

// PRESENTATION PROXIMITY
[ITW_ROUTES.PRESENTATION.PROXIMITY.QRCODE]: undefined;

// GENERIC
[ITW_ROUTES.GENERIC.NOT_AVAILABLE]: undefined;
};
3 changes: 3 additions & 0 deletions ts/features/it-wallet/navigation/ItwRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export const ITW_ROUTES = {
DATA: "ITW_PRESENTATION_CREDENTIAL_DATA",
RESULT: "ITW_PRESETATION_CREDENTIAL_RESULT"
} as const
} as const,
PROXIMITY: {
QRCODE: "ITW_PRESENTATION_CROSS_DEVICE_QRCODE"
} as const
} as const,
GENERIC: {
Expand Down
7 changes: 7 additions & 0 deletions ts/features/it-wallet/navigation/ItwStackNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import ItwCredentialsChecksScreen from "../screens/issuing/credential/ItwCredent
import ItwCredentialCatalogScreen from "../screens/issuing/credential/ItwCredentialCatalogScreen";
import ItwPrCredentialDetailsScreen from "../screens/presentation/ItwPrCredentialDetails";
import ItwPrPidDataScreen from "../screens/presentation/remote/pid/ItwPrPidDataScreen";
import ItwPrProximityQrCodeScreen from "../screens/presentation/ItwPrProximityQrCodeScreen";
import { ItwParamsList } from "./ItwParamsList";
import { ITW_ROUTES } from "./ItwRoutes";

Expand Down Expand Up @@ -137,6 +138,12 @@ export const ItwStackNavigator = () => (
component={ItwPrCredentialResultScreen}
/>

{/* PRESENTATION PROXIMITY */}
<Stack.Screen
name={ITW_ROUTES.PRESENTATION.PROXIMITY.QRCODE}
component={ItwPrProximityQrCodeScreen}
/>

{/* GENERIC */}
<Stack.Screen
name={ITW_ROUTES.GENERIC.NOT_AVAILABLE}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ const ItwPrCredentialDetailsScreen = () => {
accessibilityLabel: I18n.t(
"features.itWallet.presentation.credentialDetails.buttons.qrCode"
),
onPress: () => navigation.navigate(ITW_ROUTES.GENERIC.NOT_AVAILABLE)
onPress: () =>
navigation.navigate(ITW_ROUTES.PRESENTATION.PROXIMITY.QRCODE)
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ const ItwPrPidDetails = () => {
),
icon: "qrCode",
iconPosition: "end",
onPress: () => navigation.navigate(ITW_ROUTES.GENERIC.NOT_AVAILABLE)
onPress: () =>
navigation.navigate(ITW_ROUTES.PRESENTATION.PROXIMITY.QRCODE)
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import * as React from "react";
import { Image, SafeAreaView, View } from "react-native";
import RNQRGenerator from "rn-qr-generator";
import { IOStyles, LabelSmall, VSpacer } from "@pagopa/io-app-design-system";
import { useNavigation } from "@react-navigation/native";
import ItwLoadingSpinner from "../../components/ItwLoadingSpinner";
import { useOnFirstRender } from "../../../../utils/hooks/useOnFirstRender";
import { IOStackNavigationProp } from "../../../../navigation/params/AppParamsList";
import { ItwParamsList } from "../../navigation/ItwParamsList";
import I18n from "../../../../i18n";
import BaseScreenComponent from "../../../../components/screens/BaseScreenComponent";
import ItwKoView from "../../components/ItwKoView";
import { getItwGenericMappedError } from "../../utils/errors/itwErrorsMapping";

// A mocked QR code to be used in the proximity flow
// TODO: remove this mocked QR code after the proximity flow is implemented [SIW-688]
const mockedQrCode =
"mdoc:owBjMS4wAYIB2BhYS6QBAiABIVggUCnUgO0nCmTWOkqZLpQJh1uO2Q0YCTbYtUowBJU6ltEiWCBPkYpJZpEY4emfmR_2eFS5XQN68wihmgEoiMVEf8M3_gKBgwIBowD0AfULUJr9sL_rAkZCk114baNK4rY";

/**
* A screen that shows a QR code to be scanned by the other device
* in order to start the proximity flow.
*/
const ItwPrProximityQrCodeScreen = () => {
const [qrCodeUri, setQrCodeUri] = React.useState("");
const [isLoading, setIsLoading] = React.useState(false);
const [isError, setIsError] = React.useState(false);
const navigation = useNavigation<IOStackNavigationProp<ItwParamsList>>();
useOnFirstRender(() => {
RNQRGenerator.generate({
value: mockedQrCode,
height: 300,
width: 300,
correctionLevel: "H"
})
.then(({ uri }) => {
setQrCodeUri(uri);
setIsLoading(true);
})
.catch(_ => {
setIsError(true);
});
});

/**
* This component is used to display a loading spinner and a text.
* It is used during proximity flow. After proximity integration [SIW-688] this
* component could show a message to the user related to the several steps
* of the proximity flow.
* @returns a loading component which displays a loading spinner and a text.
*/
const LoadingComponent = () => (
<View style={IOStyles.alignCenter}>
<ItwLoadingSpinner />
<VSpacer size={8} />
<LabelSmall color={"black"} weight="Regular">
{I18n.t("features.itWallet.presentation.qrCodeScreen.loading")}
</LabelSmall>
</View>
);

/**
* Error view component which currently displays a generic error.
*/
const ErrorView = () => {
const mappedError = getItwGenericMappedError(() => navigation.goBack());
return <ItwKoView {...mappedError} />;
};

if (isError) {
return <ErrorView />;
}

return (
<BaseScreenComponent goBack={true}>
<SafeAreaView style={(IOStyles.flex, IOStyles.alignCenter)}>
<View
style={{
marginTop: 48,
alignItems: "center"
}}
>
{qrCodeUri !== "" && (
<>
<LabelSmall color={"black"}>
{"Il tuo codice QR personale"}
</LabelSmall>
<VSpacer size={16} />
<Image
style={{ width: 300, height: 300 }}
source={{ uri: qrCodeUri }}
/>
<VSpacer size={32} />
{isLoading && <LoadingComponent />}
</>
)}
</View>
</SafeAreaView>
</BaseScreenComponent>
);
};

export default ItwPrProximityQrCodeScreen;

0 comments on commit b732ece

Please sign in to comment.