From ac1be077361a3fea399cfe3ab0021af59d327b8f Mon Sep 17 00:00:00 2001
From: Alice Di Rico <83651704+Ladirico@users.noreply.github.com>
Date: Mon, 24 Feb 2025 15:37:47 +0100
Subject: [PATCH 1/2] fix: [IOPID-2632] Identification modal regressions
(#6743)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Short description
This PR introduces several fixes and improvements for the Identification
Modal. These include both functional enhancements and graphical
adjustments, particularly for handling zoomed-in text from device
accessibility settings.
## List of changes proposed in this pull request
- Improved Identification Modal functionality and accessibility.
- Added a condition to hide the pictogram on small devices when bold
text is enabled.
- Fixed the close button ("X") positioning issue on Android.
- Improved text rendering with `IoMarkdown` to prevent overflow issues.
- Updated translations (English, German, Italian) to ensure consistency.
- Increased the version of the DS library to use the hook
`useIOFontDynamicScale` in order to check if the user has increased the
font size
## Demo
### Android
| A11Y | Large texts | Button Close in correct position |
| - | - | - |
|
|
|
|
### iOS
| A11Y | Large texts | Button Close in correct position |
| - | - | - |
|
|
|
|
### Set pin on login (video only on Android but works too on iOS)
| Before ❌ | Fixed ✅ |
| - | - |
|
|
|
## How to test
- Run the app on a physical device or an emulator (both development and
production environments work).
- Follow the steps shown in the demo videos attached to this PR.
- Test the Identification Modal with different text sizes, device sizes,
and accessibility settings. Verify that:
- The pictogram appears only when appropriate.
- The close button ("X") is correctly positioned on Android.
- The text does not overflow and is properly rendered inside the modal.
- Translations are correctly applied in all supported languages.
---
locales/de/index.json | 13 ++-
locales/en/index.json | 13 ++-
locales/it/index.json | 13 ++-
package.json | 2 +-
ts/screens/modal/IdentificationModal.tsx | 47 ++++----
ts/utils/identification/index.tsx | 130 +++++++++--------------
yarn.lock | 10 +-
7 files changed, 92 insertions(+), 136 deletions(-)
diff --git a/locales/de/index.json b/locales/de/index.json
index 29c85aae72a..53efbbfdcc3 100644
--- a/locales/de/index.json
+++ b/locales/de/index.json
@@ -2802,13 +2802,12 @@
},
"identification": {
"instructions": {
- "unlockCode": "Entsperrcode",
- "unlockCodepPrefix": "Benutze deinen",
- "fingerprint": "Fingerabdruck",
- "fingerprintPrefix": "benutze deinen",
- "faceId": "Gesicht",
- "faceIdPrefix": "benutze dein",
- "congiunction": "oder"
+ "useFingerPrintOrUnlockCode": "benutze deinen **Fingerabdruck** oder benutze deinen **Entsperrcode**",
+ "useFingerPrintOrUnlockCodeA11y": "benutze deinen Fingerabdruck oder benutze deinen Entsperrcode",
+ "useFaceIdOrUnlockCode": "benutze dein **Gesicht** oder benutze deinen **Entsperrcode**",
+ "useFaceIdOrUnlockCodeA11y": "benutze dein Gesicht oder benutze deinen Entsperrcode",
+ "useUnlockCode": "benutze deinen **Entsperrcode**",
+ "useUnlockCodeA11y": "benutze deinen Entsperrcode"
},
"title": "Hallo {{name}}!",
"titleProfileName": "Hallo {{profileName}}!",
diff --git a/locales/en/index.json b/locales/en/index.json
index 2bde92ccf19..38b966bb61d 100644
--- a/locales/en/index.json
+++ b/locales/en/index.json
@@ -2912,13 +2912,12 @@
},
"identification": {
"instructions": {
- "unlockCode": "unlock code",
- "unlockCodepPrefix": "use your",
- "fingerprint": "fingerprint",
- "fingerprintPrefix": "use your",
- "faceId": "face",
- "faceIdPrefix": "use your",
- "congiunction": "or"
+ "useFingerPrintOrUnlockCode": "use your **fingerprint** or use your **unlock code**",
+ "useFingerPrintOrUnlockCodeA11y": "use your fingerprint or use your unlock code",
+ "useFaceIdOrUnlockCode": "use your **face** or use your **unlock code**",
+ "useFaceIdOrUnlockCodeA11y": "use your face or use your unlock code",
+ "useUnlockCode":" use your **unlock code**",
+ "useUnlockCodeA11y": "use your unlock code"
},
"title": "Hi {{name}}!",
"titleProfileName": "Hi {{profileName}}!",
diff --git a/locales/it/index.json b/locales/it/index.json
index 73434eec922..680310d1a07 100644
--- a/locales/it/index.json
+++ b/locales/it/index.json
@@ -2912,13 +2912,12 @@
},
"identification": {
"instructions": {
- "unlockCode": "codice di sblocco",
- "unlockCodepPrefix": "inserisci il",
- "fingerprint": "impronta",
- "fingerprintPrefix": "usa l'",
- "faceId": "volto",
- "faceIdPrefix": "usa il",
- "congiunction": "o"
+ "useFingerPrintOrUnlockCode": "usa l'**impronta** o inserisci il **codice di sblocco**",
+ "useFingerPrintOrUnlockCodeA11y": "usa l'impronta o inserisci il codice di sblocco",
+ "useFaceIdOrUnlockCode": "usa il **volto** o inserisci il **codice di sblocco**",
+ "useFaceIdOrUnlockCodeA11y": "usa il volto o inserisci il codice di sblocco",
+ "useUnlockCode": "inserisci il **codice di sblocco**",
+ "useUnlockCodeA11y": "inserisci il codice di sblocco"
},
"title": "Ciao {{name}}!",
"titleProfileName": "Ciao {{profileName}}!",
diff --git a/package.json b/package.json
index 674236573b3..2024db94b15 100644
--- a/package.json
+++ b/package.json
@@ -57,7 +57,7 @@
"@babel/plugin-transform-private-property-in-object": "^7.25.9",
"@babel/plugin-transform-react-jsx": "^7.25.9",
"@gorhom/bottom-sheet": "^4.1.5",
- "@pagopa/io-app-design-system": "4.6.0",
+ "@pagopa/io-app-design-system": "4.6.1",
"@pagopa/io-pagopa-commons": "^3.1.0",
"@pagopa/io-react-native-cieid": "^0.3.5",
"@pagopa/io-react-native-crypto": "^1.0.1",
diff --git a/ts/screens/modal/IdentificationModal.tsx b/ts/screens/modal/IdentificationModal.tsx
index b87f7554a49..ed4f48d81a3 100644
--- a/ts/screens/modal/IdentificationModal.tsx
+++ b/ts/screens/modal/IdentificationModal.tsx
@@ -7,7 +7,8 @@ import {
IconButton,
Pictogram,
ToastNotification,
- VSpacer
+ VSpacer,
+ useIOFontDynamicScale
} from "@pagopa/io-app-design-system";
import { Millisecond } from "@pagopa/ts-commons/lib/units";
import * as O from "fp-ts/lib/Option";
@@ -37,7 +38,6 @@ import I18n from "../../i18n";
import {
identificationCancel,
identificationFailure,
- identificationForceLogout,
identificationPinReset,
identificationSuccess
} from "../../store/actions/identification";
@@ -76,8 +76,8 @@ const IdentificationModal = () => {
const errorStatusRef = useRef(null);
const colorScheme: ColorSchemeName = "light";
const numberPadVariant = colorScheme ? "dark" : "light";
-
const { isDeviceScreenSmall } = useDetectSmallScreen();
+ const { hugeFontEnabled } = useIOFontDynamicScale();
const blueColor = useAppBackgroundAccentColorName();
@@ -133,9 +133,11 @@ const IdentificationModal = () => {
},
[dispatch]
);
- const onIdentificationForceLogout = useCallback(() => {
- dispatch(identificationForceLogout());
+
+ const onPinResetHandler = useCallback(() => {
+ dispatch(identificationPinReset());
}, [dispatch]);
+
const onIdentificationFailure = useCallback(() => {
dispatch(identificationFailure());
}, [dispatch]);
@@ -158,15 +160,13 @@ const IdentificationModal = () => {
O.getOrElse(() => false)
);
if (forceLogout) {
- onIdentificationForceLogout();
+ // eslint-disable-next-line functional/immutable-data
+ showRetryText.current = false;
+ onPinResetHandler();
} else {
onIdentificationFailure();
}
- }, [
- identificationFailState,
- onIdentificationFailure,
- onIdentificationForceLogout
- ]);
+ }, [identificationFailState, onIdentificationFailure, onPinResetHandler]);
const onIdentificationSuccessHandler = useCallback(
(isBiometric: boolean) => {
@@ -237,10 +237,6 @@ const IdentificationModal = () => {
[biometricType, onFingerprintRequest]
);
- const onPinResetHandler = useCallback(() => {
- dispatch(identificationPinReset());
- }, [dispatch]);
-
const confirmResetAlert = useCallback(
() =>
Alert.alert(
@@ -296,7 +292,11 @@ const IdentificationModal = () => {
/>
));
- const { top: topInset } = useSafeAreaInsets();
+ const { top: safeAreaTop } = useSafeAreaInsets();
+ const topInset =
+ Platform.OS === "android"
+ ? safeAreaTop || StatusBar.currentHeight || 0
+ : safeAreaTop;
const pictogramKey: IOPictograms = isValidatingTask ? "passcode" : "key";
@@ -428,7 +428,8 @@ const IdentificationModal = () => {
variant="warning"
/>
- ) : isDeviceScreenSmall && isValidatingTask ? null : (
+ ) : (isDeviceScreenSmall || hugeFontEnabled) &&
+ isValidatingTask ? null : (
{
/>
- {isDeviceScreenSmall ? (
-
- ) : (
-
- )}
+
- {isDeviceScreenSmall ? (
-
- ) : (
-
- )}
+
{
- // We need a function to handle the translations when the language changes,
- // or is differnt between the device and the app
- const unlockCode = I18n.t("identification.instructions.unlockCode");
- const unlockCodePrefix = I18n.t(
- "identification.instructions.unlockCodepPrefix"
- );
- const fingerprint = I18n.t("identification.instructions.fingerprint");
- const fingerprintPrefix = I18n.t(
- "identification.instructions.fingerprintPrefix"
- );
- const faceId = I18n.t("identification.instructions.faceId");
- const faceIdPrefix = I18n.t("identification.instructions.faceIdPrefix");
- return {
- unlockCode,
- unlockCodePrefix,
- fingerprint,
- fingerprintPrefix,
- faceId,
- faceIdPrefix,
- congiunction: I18n.t("identification.instructions.congiunction"),
- unlockCodeInstruction: `${unlockCodePrefix} ${unlockCode}`,
- fingerprintInstruction: `${fingerprintPrefix} ${fingerprint}`,
- faceIdInstruction: `${faceIdPrefix} ${faceId}`
- };
-};
-
export const getAccessibiliyIdentificationInstructions = (
biometricType: BiometricsValidType | undefined,
isBimoetricIdentificatoinFailed: boolean = false
) => {
- const {
- unlockCodeInstruction,
- fingerprintInstruction,
- faceIdInstruction,
- congiunction
- } = getTranlations();
-
if (isBimoetricIdentificatoinFailed) {
- return unlockCodeInstruction;
+ return I18n.t("identification.instructions.useUnlockCodeA11y");
}
switch (biometricType) {
case "BIOMETRICS":
case "TOUCH_ID":
- return `${fingerprintInstruction} ${congiunction} ${unlockCodeInstruction}`;
+ return I18n.t(
+ "identification.instructions.useFingerPrintOrUnlockCodeA11y"
+ );
case "FACE_ID":
- return `${faceIdInstruction} ${congiunction} ${unlockCodeInstruction}`;
+ return I18n.t("identification.instructions.useFaceIdOrUnlockCodeA11y");
default:
- return unlockCodeInstruction;
+ return I18n.t("identification.instructions.useUnlockCodeA11y");
}
};
@@ -82,39 +54,33 @@ export const IdentificationInstructionsComponent = (props: {
biometricType,
isBimoetricIdentificatoinFailed
);
- const {
- unlockCode,
- unlockCodePrefix,
- fingerprint,
- fingerprintPrefix,
- faceId,
- faceIdPrefix,
- congiunction
- } = getTranlations();
- const instructionComponent = (
-
-
- {unlockCodePrefix}
-
- {` ${unlockCode}`}
+
+ const generatePragraphRule = () => ({
+ Paragraph(paragraph: TxtParagraphNode, render: Renderer) {
+ return (
+
+ {paragraph.children.map(render)}
-
-
- );
- const instructionComponentWithFingerprint = (
-
-
- {fingerprintPrefix}
- {` ${fingerprint}`}
-
-
- );
- const instructionComponentWithFaceId = (
-
-
- {faceIdPrefix}
- {` ${faceId}`}
-
+ );
+ }
+ });
+
+ const instructionComponent = (
+
+
);
@@ -131,12 +97,12 @@ export const IdentificationInstructionsComponent = (props: {
accessibilityLabel={a11yInstruction}
style={IOStyles.row}
>
- {instructionComponentWithFingerprint}
-
- {" "}
- {congiunction}{" "}
-
- {instructionComponent}
+
);
case "FACE_ID":
@@ -146,12 +112,12 @@ export const IdentificationInstructionsComponent = (props: {
accessibilityLabel={a11yInstruction}
style={IOStyles.row}
>
- {instructionComponentWithFaceId}
-
- {" "}
- {congiunction}{" "}
-
- {instructionComponent}
+
);
default:
diff --git a/yarn.lock b/yarn.lock
index 75987b5ade7..914be2f401e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3753,9 +3753,9 @@ __metadata:
languageName: node
linkType: hard
-"@pagopa/io-app-design-system@npm:4.6.0":
- version: 4.6.0
- resolution: "@pagopa/io-app-design-system@npm:4.6.0"
+"@pagopa/io-app-design-system@npm:4.6.1":
+ version: 4.6.1
+ resolution: "@pagopa/io-app-design-system@npm:4.6.1"
dependencies:
"@testing-library/jest-native": ^5.4.2
"@types/react-test-renderer": ^18.0.0
@@ -3779,7 +3779,7 @@ __metadata:
react-native-reanimated: "*"
react-native-safe-area-context: "*"
react-native-svg: "*"
- checksum: 1161c1f374267e35be7e3d569eb90d4c4a5e5fd8ce574d2333fc7747194d2e5cbb15f127f4470c006e1c8f68236ecc7f7dc1424d514233aca07c507c1a692429
+ checksum: 817424de77858b23889c7377f4a95d5401591bdc6cedf28d4832fa540d24fddc1425cbf7c82b2f5662a61eb96e3b1e3708aeeefbd7a30613e168f6327925ad29
languageName: node
linkType: hard
@@ -13657,7 +13657,7 @@ __metadata:
"@babel/runtime": ^7.20.0
"@gorhom/bottom-sheet": ^4.1.5
"@jambit/eslint-plugin-typed-redux-saga": ^0.4.0
- "@pagopa/io-app-design-system": 4.6.0
+ "@pagopa/io-app-design-system": 4.6.1
"@pagopa/io-pagopa-commons": ^3.1.0
"@pagopa/io-react-native-cieid": ^0.3.5
"@pagopa/io-react-native-crypto": ^1.0.1
From a80ec32bd1c9c7ad382eb07567bf57498b0c6b88 Mon Sep 17 00:00:00 2001
From: Alice Di Rico <83651704+Ladirico@users.noreply.github.com>
Date: Mon, 24 Feb 2025 16:43:59 +0100
Subject: [PATCH 2/2] chore: [IOPID-2612] edit publiccode.yml file (#6723)
## Short description
Since the IO showcase site will be deployed on the new domain (on
ioapp.it from io.italia.it), this PR may be merged
---
publiccode.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/publiccode.yml b/publiccode.yml
index 4bc2f6ceb87..c91884c68e4 100644
--- a/publiccode.yml
+++ b/publiccode.yml
@@ -8,11 +8,11 @@ logo: "img/io-app-icon.png"
releaseDate: "2024-11-21"
url: "https://github.com/pagopa/io-app"
applicationSuite: IO
-landingURL: "https://io.italia.it/"
+landingURL: "https://ioapp.it/"
softwareVersion: 2.83.0-rc.7
developmentStatus: beta
softwareType: standalone/mobile
-roadmap: "https://io.italia.it/"
+roadmap: "https://ioapp.it/"
platforms:
- ios
- android