From d15e769cd4168cde2733b63ce70b7d09791ee3ad Mon Sep 17 00:00:00 2001 From: Alessandro Mazzon Date: Mon, 3 Mar 2025 09:25:47 +0100 Subject: [PATCH 1/3] feat(IT Wallet): [SIW-2042] Use IOMarkdown when displaying a remote message inside credential presentation (#6768) ## Short description Replaced the `Body` component with `IOMarkdown` to support markdown formatted errors descriptions when using EC error messages ## List of changes proposed in this pull request - Replaced the `Body` component with `IOMarkdown` inside `IssuerDynamicErrorAlert` ## How to test Simulate a remote dynamic error checking that the error description is displayed correctly --- .../components/ItwPresentationCredentialStatusAlert.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/features/itwallet/presentation/details/components/ItwPresentationCredentialStatusAlert.tsx b/ts/features/itwallet/presentation/details/components/ItwPresentationCredentialStatusAlert.tsx index d5eb82bab05..94709d7d05f 100644 --- a/ts/features/itwallet/presentation/details/components/ItwPresentationCredentialStatusAlert.tsx +++ b/ts/features/itwallet/presentation/details/components/ItwPresentationCredentialStatusAlert.tsx @@ -1,5 +1,5 @@ import { memo } from "react"; -import { Alert, Body } from "@pagopa/io-app-design-system"; +import { Alert } from "@pagopa/io-app-design-system"; import I18n from "../../../../../i18n.ts"; import { StoredCredential } from "../../../common/utils/itwTypesUtils.ts"; import { @@ -121,7 +121,7 @@ const IssuerDynamicErrorAlert = ({ message }: IssuerDynamicErrorAlertProps) => { const bottomSheet = useIOBottomSheetAutoresizableModal( { title: localizedMessage.title, - component: {localizedMessage.description} + component: }, 128 ); From b27c69f305429ff78d8a4e1552b8b6c026230c07 Mon Sep 17 00:00:00 2001 From: Cristian Matteu <94987118+ChrisMattew@users.noreply.github.com> Date: Mon, 3 Mar 2025 09:41:54 +0100 Subject: [PATCH 2/3] refactor: [IOPID-2671] Updated `landingScreenBannerMap` config (#6760) ## Short description This PR removes all the `SETTINGS_DISCOVERY` banner occurrences ## List of changes proposed in this pull request - Removed `SettingsDiscoveryBanner` and its related config in `ts/features/landingScreenMultiBanner/utils/landingScreenBannerMap.tsx` - Removed `hasUserAcknowledgedSettingsBanner` references from `profileSettings` reducer, actions and selectors and all the occurrences associated to them ## Demo
Demo https://github.com/user-attachments/assets/9d7922d5-9e78-4733-9623-6d0619dc0473
## How to test Perform a fresh install of the app, pointing to the local environment, ensuring that `SETTINGS_DISCOVERY` is present in the `landing_banners` remote config, and verify that it does not appear in the messages section. --- .../__snapshots__/index.test.ts.snap | 5 +- .../__snapshots__/reducer.test.ts.snap | 1 - .../store/__tests__/selectors.test.tsx | 3 +- .../utils/landingScreenBannerMap.tsx | 10 - .../profileSettings/store/actions/index.ts | 12 - .../profileSettings/store/reducers/index.ts | 28 +- .../profileSettings/store/selectors/index.ts | 4 - .../components/SettingsDiscoveryBanner.tsx | 67 -- .../__test__/SettingsDiscoveryBanner.test.tsx | 69 -- .../SettingsDiscoveryBanner.test.tsx.snap | 744 ------------------ ts/store/actions/types.ts | 2 - ts/store/reducers/index.ts | 3 - 12 files changed, 13 insertions(+), 935 deletions(-) delete mode 100644 ts/features/profileSettings/store/actions/index.ts delete mode 100644 ts/features/profileSettings/store/selectors/index.ts delete mode 100644 ts/screens/profile/components/SettingsDiscoveryBanner.tsx delete mode 100644 ts/screens/profile/components/__test__/SettingsDiscoveryBanner.test.tsx delete mode 100644 ts/screens/profile/components/__test__/__snapshots__/SettingsDiscoveryBanner.test.tsx.snap diff --git a/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap b/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap index ba66eba0a2d..604267fc407 100644 --- a/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap +++ b/ts/features/common/store/reducers/__tests__/__snapshots__/index.test.ts.snap @@ -148,7 +148,6 @@ exports[`featuresPersistor should match snapshot 1`] = ` "LV_EXPIRATION_REMINDER": true, "PUSH_NOTIFICATIONS_REMINDER": true, "SEND_ACTIVATION_REMINDER": false, - "SETTINGS_DISCOVERY": true, }, "loginFeatures": { "cieLogin": { @@ -297,9 +296,7 @@ exports[`featuresPersistor should match snapshot 1`] = ` "kind": "PotNone", }, }, - "profileSettings": { - "hasUserAcknowledgedSettingsBanner": false, - }, + "profileSettings": {}, "services": { "details": { "byId": {}, diff --git a/ts/features/landingScreenMultiBanner/store/__tests__/__snapshots__/reducer.test.ts.snap b/ts/features/landingScreenMultiBanner/store/__tests__/__snapshots__/reducer.test.ts.snap index 645180a9b9c..b75842196e2 100644 --- a/ts/features/landingScreenMultiBanner/store/__tests__/__snapshots__/reducer.test.ts.snap +++ b/ts/features/landingScreenMultiBanner/store/__tests__/__snapshots__/reducer.test.ts.snap @@ -6,6 +6,5 @@ exports[`landingScreenBannersReducer should match snapshot: undefined_no_action "LV_EXPIRATION_REMINDER": true, "PUSH_NOTIFICATIONS_REMINDER": true, "SEND_ACTIVATION_REMINDER": false, - "SETTINGS_DISCOVERY": true, } `; diff --git a/ts/features/landingScreenMultiBanner/store/__tests__/selectors.test.tsx b/ts/features/landingScreenMultiBanner/store/__tests__/selectors.test.tsx index d5e22579f1b..1d94f47833c 100644 --- a/ts/features/landingScreenMultiBanner/store/__tests__/selectors.test.tsx +++ b/ts/features/landingScreenMultiBanner/store/__tests__/selectors.test.tsx @@ -9,8 +9,7 @@ process.env.NODE_ENV = "test"; const mockState = { features: { landingBanners: { - ITW_DISCOVERY: true, - SETTINGS_DISCOVERY: false + ITW_DISCOVERY: true } } } as GlobalState; diff --git a/ts/features/landingScreenMultiBanner/utils/landingScreenBannerMap.tsx b/ts/features/landingScreenMultiBanner/utils/landingScreenBannerMap.tsx index 36a6b7b7d11..437e248ddc8 100644 --- a/ts/features/landingScreenMultiBanner/utils/landingScreenBannerMap.tsx +++ b/ts/features/landingScreenMultiBanner/utils/landingScreenBannerMap.tsx @@ -1,12 +1,10 @@ import { ReactElement } from "react"; -import { SettingsDiscoveryBanner } from "../../../screens/profile/components/SettingsDiscoveryBanner"; import { GlobalState } from "../../../store/reducers/types"; import { ItwDiscoveryBanner } from "../../itwallet/common/components/discoveryBanner/ItwDiscoveryBanner"; import { isItwPersistedDiscoveryBannerRenderableSelector } from "../../itwallet/common/store/selectors"; import { LoginExpirationBanner } from "../../login/preferences/components/LoginExpirationBanner"; import { isSessionExpirationBannerRenderableSelector } from "../../login/preferences/store/selectors"; import { PNActivationReminderBanner } from "../../pn/components/PNActivationReminderBanner"; -import { hasUserAcknowledgedSettingsBannerSelector } from "../../profileSettings/store/selectors"; import { PushNotificationsBanner } from "../../pushNotifications/components/PushNotificationsBanner"; import { isPushNotificationsBannerRenderableSelector } from "../../pushNotifications/store/selectors"; @@ -25,7 +23,6 @@ export type LandingScreenBannerId = export const LANDING_SCREEN_BANNERS_ENABLED_MAP = { PUSH_NOTIFICATIONS_REMINDER: true, ITW_DISCOVERY: true, - SETTINGS_DISCOVERY: true, LV_EXPIRATION_REMINDER: true, SEND_ACTIVATION_REMINDER: false } as const; @@ -43,13 +40,6 @@ export const landingScreenBannerMap: BannerMapById = { ), isRenderableSelector: isItwPersistedDiscoveryBannerRenderableSelector }, - SETTINGS_DISCOVERY: { - component: closeHandler => ( - - ), - isRenderableSelector: (state: GlobalState) => - !hasUserAcknowledgedSettingsBannerSelector(state) - }, LV_EXPIRATION_REMINDER: { component: closeHandler => ( diff --git a/ts/features/profileSettings/store/actions/index.ts b/ts/features/profileSettings/store/actions/index.ts deleted file mode 100644 index ace066303e9..00000000000 --- a/ts/features/profileSettings/store/actions/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Action types and action creator related to the Profile settings. - */ -import { ActionType, createStandardAction } from "typesafe-actions"; - -export const setHasUserAcknowledgedSettingsBanner = createStandardAction( - "SET_HAS_USER_ACKNOWLEDGE_SETTINGS_BANNER" -)(); - -export type ProfileSettingsActions = ActionType< - typeof setHasUserAcknowledgedSettingsBanner ->; diff --git a/ts/features/profileSettings/store/reducers/index.ts b/ts/features/profileSettings/store/reducers/index.ts index 70f5f218653..7a12ccc4d89 100644 --- a/ts/features/profileSettings/store/reducers/index.ts +++ b/ts/features/profileSettings/store/reducers/index.ts @@ -8,18 +8,14 @@ import { } from "redux-persist"; import AsyncStorage from "@react-native-async-storage/async-storage"; import _ from "lodash"; -import { setHasUserAcknowledgedSettingsBanner } from "../actions"; import { Action } from "../../../../store/actions/types"; import { differentProfileLoggedIn } from "../../../../store/actions/crossSessions"; import { isDevEnv } from "../../../../utils/environment"; -export type ProfileSettingsState = { - hasUserAcknowledgedSettingsBanner: boolean; -}; +// eslint-disable-next-line @typescript-eslint/ban-types +export type ProfileSettingsState = {}; -export const profileSettingsReducerInitialState = { - hasUserAcknowledgedSettingsBanner: false -}; +export const profileSettingsReducerInitialState = {}; const profileSettingsReducer = ( state: ProfileSettingsState = profileSettingsReducerInitialState, @@ -29,30 +25,28 @@ const profileSettingsReducer = ( case getType(differentProfileLoggedIn): { return profileSettingsReducerInitialState; } - case getType(setHasUserAcknowledgedSettingsBanner): { - return { - ...state, - hasUserAcknowledgedSettingsBanner: action.payload - }; - } default: return state; } }; -const CURRENT_REDUX_PROFILE_SETTINGS_STORE_VERSION = 1; +const CURRENT_REDUX_PROFILE_SETTINGS_STORE_VERSION = 2; const migrations: MigrationManifest = { // we changed the way we compute the installation ID - "0": (state): ProfileSettingsState & PersistPartial => { + "0": state => { const prevState = state as ProfileSettingsState & PersistPartial; return { ...prevState, hasUserAcknowledgedSettingsBanner: false }; }, - "1": (state): ProfileSettingsState & PersistPartial => { + "1": state => { const prevState = state as ProfileSettingsState & PersistPartial; return _.omit(prevState, "showProfileBanner"); + }, + "2": state => { + const prevState = state as ProfileSettingsState & PersistPartial; + return _.omit(prevState, "hasUserAcknowledgedSettingsBanner"); } }; const persistConfig: PersistConfig = { @@ -60,7 +54,7 @@ const persistConfig: PersistConfig = { storage: AsyncStorage, migrate: createMigrate(migrations, { debug: isDevEnv }), version: CURRENT_REDUX_PROFILE_SETTINGS_STORE_VERSION, - whitelist: ["hasUserAcknowledgedSettingsBanner"] + whitelist: [] }; export const profileSettingsReducerPersistor = persistReducer( diff --git a/ts/features/profileSettings/store/selectors/index.ts b/ts/features/profileSettings/store/selectors/index.ts deleted file mode 100644 index 5b638fe6e7a..00000000000 --- a/ts/features/profileSettings/store/selectors/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { GlobalState } from "../../../../store/reducers/types"; - -export const hasUserAcknowledgedSettingsBannerSelector = (state: GlobalState) => - state.features.profileSettings.hasUserAcknowledgedSettingsBanner; diff --git a/ts/screens/profile/components/SettingsDiscoveryBanner.tsx b/ts/screens/profile/components/SettingsDiscoveryBanner.tsx deleted file mode 100644 index a3ddc2c2185..00000000000 --- a/ts/screens/profile/components/SettingsDiscoveryBanner.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Banner, IOVisualCostants } from "@pagopa/io-app-design-system"; -import { createRef, useCallback, useEffect } from "react"; -import { StyleSheet, View } from "react-native"; -import { setHasUserAcknowledgedSettingsBanner } from "../../../features/profileSettings/store/actions"; -import I18n from "../../../i18n"; -import { useIONavigation } from "../../../navigation/params/AppParamsList"; -import ROUTES from "../../../navigation/routes"; -import { useIODispatch } from "../../../store/hooks"; -import { - trackSettingsDiscoverBannerClosure, - trackSettingsDiscoverBannerTap, - trackSettingsDiscoverBannerVisualized -} from "../analytics"; - -type SettingsDiscoveryBannerProps = { - handleOnClose: () => void; -}; - -/** - * to use in case the banner's visibility has to be handled externally - * (see MultiBanner feature for the landing screen) - */ -export const SettingsDiscoveryBanner = ({ - handleOnClose -}: SettingsDiscoveryBannerProps) => { - const bannerRef = createRef(); - const navigation = useIONavigation(); - const dispatch = useIODispatch(); - const handleOnPress = () => { - trackSettingsDiscoverBannerTap(); - navigation.navigate(ROUTES.PROFILE_NAVIGATOR, { - screen: ROUTES.SETTINGS_MAIN - }); - }; - const closeHandler = useCallback(() => { - trackSettingsDiscoverBannerClosure(); - dispatch(setHasUserAcknowledgedSettingsBanner(true)); - handleOnClose(); - }, [dispatch, handleOnClose]); - - useEffect(() => { - trackSettingsDiscoverBannerVisualized(); - }, []); - - return ( - - - - ); -}; - -const styles = StyleSheet.create({ - margins: { - marginHorizontal: IOVisualCostants.appMarginDefault, - marginVertical: 16 - } -}); diff --git a/ts/screens/profile/components/__test__/SettingsDiscoveryBanner.test.tsx b/ts/screens/profile/components/__test__/SettingsDiscoveryBanner.test.tsx deleted file mode 100644 index b2052ef6775..00000000000 --- a/ts/screens/profile/components/__test__/SettingsDiscoveryBanner.test.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { ReactElement } from "react"; -import { createStore } from "redux"; -import { constUndefined } from "fp-ts/lib/function"; -import { fireEvent } from "@testing-library/react-native"; -import ROUTES from "../../../../navigation/routes"; -import { applicationChangeState } from "../../../../store/actions/application"; -import { appReducer } from "../../../../store/reducers"; -import { GlobalState } from "../../../../store/reducers/types"; -import { renderScreenWithNavigationStoreContext } from "../../../../utils/testWrapper"; -import { SettingsDiscoveryBanner } from "../SettingsDiscoveryBanner"; -import * as analytics from "../../analytics"; -import I18n from "../../../../i18n"; - -describe("settingsDiscoveryBanner", () => { - afterEach(() => { - jest.restoreAllMocks(); - }); - it("should match snapshot", () => { - const component = renderComponent( - null} /> - ); - expect(component.toJSON()).toMatchSnapshot(); - }); - it("should have called 'trackSettingsDiscoverBannerVisualized' on first rendering", () => { - const spyOnMockedTrackSettingsDiscoverBannerVisualized = jest - .spyOn(analytics, "trackSettingsDiscoverBannerVisualized") - .mockImplementation(constUndefined); - renderComponent( null} />); - expect( - spyOnMockedTrackSettingsDiscoverBannerVisualized - ).toHaveBeenCalledTimes(1); - }); - it("should have called 'trackSettingsDiscoverBannerTap' on first rendering", () => { - const spyOnMockedTrackSettingsDiscoverBannerTap = jest - .spyOn(analytics, "trackSettingsDiscoverBannerTap") - .mockImplementation(constUndefined); - const component = renderComponent( - null} /> - ); - const cta = component.getByTestId("settingsDiscoveryBannerCTA"); - fireEvent(cta, "onPress"); - expect(spyOnMockedTrackSettingsDiscoverBannerTap).toHaveBeenCalledTimes(1); - }); - it("should have called 'trackSettingsDiscoverBannerClosure' on first rendering", () => { - const spyOnMockedTrackSettingsDiscoverBannerClosure = jest - .spyOn(analytics, "trackSettingsDiscoverBannerClosure") - .mockImplementation(constUndefined); - const component = renderComponent( - null} /> - ); - const closeButton = component.getByA11yLabel( - I18n.t("global.buttons.close") - ); - fireEvent(closeButton, "onPress"); - expect(spyOnMockedTrackSettingsDiscoverBannerClosure).toHaveBeenCalledTimes( - 1 - ); - }); -}); - -const renderComponent = (component: ReactElement) => { - const globalState = appReducer(undefined, applicationChangeState("active")); - return renderScreenWithNavigationStoreContext( - () => component, - ROUTES.SETTINGS_MAIN, - {}, - createStore(appReducer, globalState as any) - ); -}; diff --git a/ts/screens/profile/components/__test__/__snapshots__/SettingsDiscoveryBanner.test.tsx.snap b/ts/screens/profile/components/__test__/__snapshots__/SettingsDiscoveryBanner.test.tsx.snap deleted file mode 100644 index 3f3d011ce23..00000000000 --- a/ts/screens/profile/components/__test__/__snapshots__/SettingsDiscoveryBanner.test.tsx.snap +++ /dev/null @@ -1,744 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`settingsDiscoveryBanner should match snapshot 1`] = ` - - - - - - - - - - - - - - - SETTINGS_MAIN - - - - - - - - - - - - - - - - - - - - - - Looking for your profile? We have moved it, it is now in the top right corner! - - - - - - Go to Settings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -`; diff --git a/ts/store/actions/types.ts b/ts/store/actions/types.ts index 3583a9e22e3..9912f942601 100644 --- a/ts/store/actions/types.ts +++ b/ts/store/actions/types.ts @@ -23,7 +23,6 @@ import { MessagesActions } from "../../features/messages/store/actions"; import { MixpanelFeatureActions } from "../../features/mixpanel/store/actions"; import { PaymentsActions as PaymentsFeatureActions } from "../../features/payments/common/store/actions"; import { PnActions } from "../../features/pn/store/actions"; -import { ProfileSettingsActions } from "../../features/profileSettings/store/actions"; import { NotificationPermissionsActions } from "../../features/pushNotifications/store/actions/environment"; import { NotificationsActions } from "../../features/pushNotifications/store/actions/installation"; import { PendingMessageActions } from "../../features/pushNotifications/store/actions/pendingMessage"; @@ -107,7 +106,6 @@ export type Action = | FimsActions | ItwActions | TrialSystemActions - | ProfileSettingsActions | AppearanceSettingsActions | IngressScreenActions | MixpanelFeatureActions diff --git a/ts/store/reducers/index.ts b/ts/store/reducers/index.ts index a173df031ac..8f0bf496cac 100644 --- a/ts/store/reducers/index.ts +++ b/ts/store/reducers/index.ts @@ -254,9 +254,6 @@ export function createRootReducer( }, profileSettings: { ...profileSettingsReducerInitialState, - hasUserAcknowledgedSettingsBanner: - state.features.profileSettings - .hasUserAcknowledgedSettingsBanner, _persist: state.features.profileSettings._persist }, appearanceSettings: { From 8e2626195acde1aa763b3d54019540b009608ffa Mon Sep 17 00:00:00 2001 From: Cristian Matteu <94987118+ChrisMattew@users.noreply.github.com> Date: Mon, 3 Mar 2025 09:41:59 +0100 Subject: [PATCH 3/3] fix: [IOPID-2484] Fix `MIXPANEL_SET_ENABLED` event tracking in the onBoarding flow (#6766) ## Short description This PR replaces the wrong `flow` property set in the `MIXPANEL_SET_ENABLED` event in the onBoarding flow with the correct one. ## How to test Perform a fresh install of the app and, once in the `OnboardingShareDataScreen`, consent to data sharing. The `flow` property associated with the `MIXPANEL_SET_ENABLED` event should be set to `onBoarding`. Co-authored-by: Fabio Bombardi <16268789+shadowsheep1@users.noreply.github.com> --- ts/screens/onboarding/OnboardingShareDataScreen.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ts/screens/onboarding/OnboardingShareDataScreen.tsx b/ts/screens/onboarding/OnboardingShareDataScreen.tsx index e8e11163b4a..c1bc06f3685 100644 --- a/ts/screens/onboarding/OnboardingShareDataScreen.tsx +++ b/ts/screens/onboarding/OnboardingShareDataScreen.tsx @@ -68,17 +68,13 @@ const OnboardingShareDataScreen = (): ReactElement => { // We wait some time to allow mixpanel to be enabled // before tracking the event setTimeout(() => { - void trackMixpanelSetEnabled( - true, - getFlowType(false, isFirstOnBoarding), - store.getState() - ); + void trackMixpanelSetEnabled(true, flow, store.getState()); }, 1000); }, testID: "share-data-confirm-button" } }), - [isFirstOnBoarding, present, store, dispatch] + [flow, present, store, dispatch] ); return (