From 456669b160670599a89e788c8e49676c62370bbf Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Tue, 30 Apr 2024 12:32:25 +0200 Subject: [PATCH 01/17] Push notification feature refactoring --- ts/RootContainer.tsx | 2 +- ts/boot/configureStoreAndPersistor.ts | 4 +- .../pushNotifications/analytics/index.ts | 51 ++++++++++++ .../components/NotificationPreviewSample.tsx | 0 .../NotificationsPreferencesPreview.tsx | 0 .../NotificationPreviewSample.test.tsx | 0 .../hooks/usePreviewMoreInfo.tsx | 13 +-- ...checkNotificationsPermissionsSaga.test.tsx | 82 +++++++++++++++++++ .../sagas/__tests__/notifications.test.ts | 22 ++--- .../checkNotificationsPermissionsSaga.ts | 10 +-- .../checkNotificationsPreferencesSaga.ts | 16 ++-- .../pushNotifications}/sagas/notifications.ts | 32 ++++---- ...boardingNotificationsInfoScreenConsent.tsx | 32 ++++---- ...boardingNotificationsPreferencesScreen.tsx | 56 ++++++------- ...ingNotificationsInfoScreenConsent.test.tsx | 16 ++-- ...ingNotificationsPreferencesScreen.test.tsx | 16 ++-- .../store/actions/notifications.ts | 2 +- .../pushNotifications/store/reducers/index.ts | 20 +++++ .../store/reducers}/installation.ts | 27 +++--- .../store/reducers}/pendingMessage.ts | 10 +-- .../reactNativePushNotificationiOS.test.ts | 0 .../utils}/configurePushNotification.ts | 18 ++-- .../pushNotifications/utils/index.ts} | 33 +++++++- ts/navigation/OnboardingNavigator.tsx | 4 +- ts/navigation/params/OnboardingParamsList.ts | 2 +- .../initializeApplicationSaga.test.ts | 10 +-- ts/sagas/identification.ts | 2 +- ts/sagas/installation.ts | 2 +- ts/sagas/startup.ts | 30 ++----- ...checkNotificationsPermissionsSaga.test.tsx | 6 +- .../startup/watchApplicationActivitySaga.ts | 2 +- ts/screens/profile/DeveloperModeSection.tsx | 2 +- .../NotificationsPreferencesScreen.tsx | 2 +- ts/store/actions/types.ts | 2 +- ts/store/middlewares/analytics.ts | 10 +-- ts/store/reducers/index.ts | 2 +- ts/store/reducers/notifications/index.ts | 20 ----- ts/store/reducers/types.ts | 2 +- ts/utils/analytics.ts | 53 ------------ ts/utils/installation.ts | 21 ----- 40 files changed, 348 insertions(+), 286 deletions(-) create mode 100644 ts/features/pushNotifications/analytics/index.ts rename ts/{screens/onboarding => features/pushNotifications}/components/NotificationPreviewSample.tsx (100%) rename ts/{screens/onboarding => features/pushNotifications}/components/NotificationsPreferencesPreview.tsx (100%) rename ts/{screens/onboarding => features/pushNotifications}/components/__tests__/NotificationPreviewSample.test.tsx (100%) rename ts/{utils => features/pushNotifications}/hooks/usePreviewMoreInfo.tsx (67%) create mode 100644 ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx rename ts/{ => features/pushNotifications}/sagas/__tests__/notifications.test.ts (94%) rename ts/{sagas/startup => features/pushNotifications/sagas}/checkNotificationsPermissionsSaga.ts (79%) rename ts/{sagas/startup => features/pushNotifications/sagas}/checkNotificationsPreferencesSaga.ts (82%) rename ts/{ => features/pushNotifications}/sagas/notifications.ts (85%) rename ts/{screens/onboarding => features/pushNotifications/screens}/OnboardingNotificationsInfoScreenConsent.tsx (86%) rename ts/{screens/onboarding => features/pushNotifications/screens}/OnboardingNotificationsPreferencesScreen.tsx (81%) rename ts/{screens/onboarding => features/pushNotifications/screens}/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx (88%) rename ts/{screens/onboarding => features/pushNotifications/screens}/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx (88%) rename ts/{ => features/pushNotifications}/store/actions/notifications.ts (94%) create mode 100644 ts/features/pushNotifications/store/reducers/index.ts rename ts/{store/reducers/notifications => features/pushNotifications/store/reducers}/installation.ts (79%) rename ts/{store/reducers/notifications => features/pushNotifications/store/reducers}/pendingMessage.ts (79%) rename ts/{ => features/pushNotifications}/utils/__tests__/reactNativePushNotificationiOS.test.ts (100%) rename ts/{boot => features/pushNotifications/utils}/configurePushNotification.ts (94%) rename ts/{utils/notification.ts => features/pushNotifications/utils/index.ts} (69%) delete mode 100644 ts/store/reducers/notifications/index.ts delete mode 100644 ts/utils/installation.ts diff --git a/ts/RootContainer.tsx b/ts/RootContainer.tsx index 06a7ef813b8..287e26b47a3 100644 --- a/ts/RootContainer.tsx +++ b/ts/RootContainer.tsx @@ -11,7 +11,7 @@ import { } from "react-native"; import SplashScreen from "react-native-splash-screen"; import { connect } from "react-redux"; -import configurePushNotifications from "./boot/configurePushNotification"; +import configurePushNotifications from "./features/pushNotifications/utils/configurePushNotification"; import DebugInfoOverlay from "./components/DebugInfoOverlay"; import FlagSecureComponent from "./components/FlagSecure"; import PagoPATestIndicatorOverlay from "./components/PagoPATestIndicatorOverlay"; diff --git a/ts/boot/configureStoreAndPersistor.ts b/ts/boot/configureStoreAndPersistor.ts index e8e325ea21d..d83c2dc3b2c 100644 --- a/ts/boot/configureStoreAndPersistor.ts +++ b/ts/boot/configureStoreAndPersistor.ts @@ -41,8 +41,8 @@ import { INSTALLATION_INITIAL_STATE, InstallationState } from "../store/reducers/installation"; -import { NotificationsState } from "../store/reducers/notifications"; -import { getInitialState as getInstallationInitialState } from "../store/reducers/notifications/installation"; +import { NotificationsState } from "../features/pushNotifications/store/reducers"; +import { getInitialState as getInstallationInitialState } from "../features/pushNotifications/store/reducers/installation"; import { GlobalState, PersistedGlobalState } from "../store/reducers/types"; import { walletsPersistConfig } from "../store/reducers/wallet"; import { DateISO8601Transform } from "../store/transforms/dateISO8601Tranform"; diff --git a/ts/features/pushNotifications/analytics/index.ts b/ts/features/pushNotifications/analytics/index.ts new file mode 100644 index 00000000000..eaea115ea88 --- /dev/null +++ b/ts/features/pushNotifications/analytics/index.ts @@ -0,0 +1,51 @@ +import { PushNotificationsContentTypeEnum } from "../../../../definitions/backend/PushNotificationsContentType"; +import { ReminderStatusEnum } from "../../../../definitions/backend/ReminderStatus"; +import { mixpanelTrack } from "../../../mixpanel"; +import { buildEventProperties } from "../../../utils/analytics"; + +export function trackNotificationInstallationTokenNotChanged() { + void mixpanelTrack("NOTIFICATIONS_INSTALLATION_TOKEN_NOT_CHANGED"); +} + +export function trackNotificationsOptInPreviewStatus( + contentType: PushNotificationsContentTypeEnum +) { + void mixpanelTrack( + "NOTIFICATIONS_OPTIN_PREVIEW_STATUS", + buildEventProperties("UX", "action", { + enabled: contentType === PushNotificationsContentTypeEnum.FULL + }) + ); +} + +export function trackNotificationsOptInReminderStatus( + reminderStatus: ReminderStatusEnum +) { + void mixpanelTrack( + "NOTIFICATIONS_OPTIN_REMINDER_STATUS", + buildEventProperties("UX", "action", { + enabled: reminderStatus === ReminderStatusEnum.ENABLED + }) + ); +} + +export function trackNotificationsOptInReminderOnPermissionsOff() { + void mixpanelTrack( + "NOTIFICATIONS_OPTIN_REMINDER_ON_PERMISSIONS_OFF", + buildEventProperties("UX", "control") + ); +} + +export function trackNotificationsOptInOpenSettings() { + void mixpanelTrack( + "NOTIFICATIONS_OPTIN_OPEN_SETTINGS", + buildEventProperties("UX", "action") + ); +} + +export function trackNotificationsOptInSkipSystemPermissions() { + void mixpanelTrack( + "NOTIFICATIONS_OPTIN_SKIP_SYSTEM_PERMISSIONS", + buildEventProperties("UX", "action") + ); +} diff --git a/ts/screens/onboarding/components/NotificationPreviewSample.tsx b/ts/features/pushNotifications/components/NotificationPreviewSample.tsx similarity index 100% rename from ts/screens/onboarding/components/NotificationPreviewSample.tsx rename to ts/features/pushNotifications/components/NotificationPreviewSample.tsx diff --git a/ts/screens/onboarding/components/NotificationsPreferencesPreview.tsx b/ts/features/pushNotifications/components/NotificationsPreferencesPreview.tsx similarity index 100% rename from ts/screens/onboarding/components/NotificationsPreferencesPreview.tsx rename to ts/features/pushNotifications/components/NotificationsPreferencesPreview.tsx diff --git a/ts/screens/onboarding/components/__tests__/NotificationPreviewSample.test.tsx b/ts/features/pushNotifications/components/__tests__/NotificationPreviewSample.test.tsx similarity index 100% rename from ts/screens/onboarding/components/__tests__/NotificationPreviewSample.test.tsx rename to ts/features/pushNotifications/components/__tests__/NotificationPreviewSample.test.tsx diff --git a/ts/utils/hooks/usePreviewMoreInfo.tsx b/ts/features/pushNotifications/hooks/usePreviewMoreInfo.tsx similarity index 67% rename from ts/utils/hooks/usePreviewMoreInfo.tsx rename to ts/features/pushNotifications/hooks/usePreviewMoreInfo.tsx index 7c1e2f4f31e..7613b151801 100644 --- a/ts/utils/hooks/usePreviewMoreInfo.tsx +++ b/ts/features/pushNotifications/hooks/usePreviewMoreInfo.tsx @@ -1,9 +1,12 @@ import * as React from "react"; -import I18n from "../../i18n"; -import { Body } from "../../components/core/typography/Body"; -import FooterWithButtons from "../../components/ui/FooterWithButtons"; -import { confirmButtonProps } from "../../components/buttons/ButtonConfigurations"; -import { IOBottomSheetModal, useLegacyIOBottomSheetModal } from "./bottomSheet"; +import I18n from "../../../i18n"; +import { Body } from "../../../components/core/typography/Body"; +import FooterWithButtons from "../../../components/ui/FooterWithButtons"; +import { confirmButtonProps } from "../../../components/buttons/ButtonConfigurations"; +import { + IOBottomSheetModal, + useLegacyIOBottomSheetModal +} from "../../../utils/hooks/bottomSheet"; /** * Return on object to open an IO bottom sheet modal diff --git a/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx b/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx new file mode 100644 index 00000000000..cb703740c2e --- /dev/null +++ b/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx @@ -0,0 +1,82 @@ +import { CommonActions, StackActions } from "@react-navigation/native"; +import { testSaga } from "redux-saga-test-plan"; +import NavigationService from "../../../../navigation/NavigationService"; +import ROUTES from "../../../../navigation/routes"; +import { + checkNotificationPermissions, + requestNotificationPermissions +} from "../../utils"; +import { checkNotificationsPermissionsSaga } from "../checkNotificationsPermissionsSaga"; +import { notificationsInfoScreenConsent } from "../../store/actions/notifications"; + +describe("checkNotificationsPermissionsSaga", () => { + it("upon saga startup, it should ask for push notifications permission", () => { + testSaga(checkNotificationsPermissionsSaga) + .next() + .call(checkNotificationPermissions); + }); + + it("if the push notifications permission was given, the saga will terminate ", () => { + testSaga(checkNotificationsPermissionsSaga) + .next() + .call(checkNotificationPermissions) + .next(true) + .isDone(); + }); + + it("if the push notifications permission was not given and is first onboarding, the saga will request push notification permissions", () => { + testSaga(checkNotificationsPermissionsSaga) + .next() + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions); + }); + + it("if the saga asks for push permissions and the user give them, the saga will terminate", () => { + testSaga(checkNotificationsPermissionsSaga) + .next() + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(true) + .isDone(); + }); + + it("if the saga asks for push permissions and the user does not give them, the saga navigates to the Info Screen and waits for the notificationsInfoScreenConsent action", () => { + testSaga(checkNotificationsPermissionsSaga) + .next() + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(false) + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + }) + ) + .next() + .take(notificationsInfoScreenConsent); + }); + + it("if the saga is waiting for the notificationsInfoScreenConsent action and the latter is received, the saga terminates", () => { + testSaga(checkNotificationsPermissionsSaga) + .next() + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(false) + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + }) + ) + .next() + .take(notificationsInfoScreenConsent) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); + }); +}); diff --git a/ts/sagas/__tests__/notifications.test.ts b/ts/features/pushNotifications/sagas/__tests__/notifications.test.ts similarity index 94% rename from ts/sagas/__tests__/notifications.test.ts rename to ts/features/pushNotifications/sagas/__tests__/notifications.test.ts index 419e193b61a..9ee11fcfe87 100644 --- a/ts/sagas/__tests__/notifications.test.ts +++ b/ts/features/pushNotifications/sagas/__tests__/notifications.test.ts @@ -2,8 +2,8 @@ import * as E from "fp-ts/lib/Either"; import { Action } from "redux"; import { expectSaga, testSaga } from "redux-saga-test-plan"; import * as matchers from "redux-saga-test-plan/matchers"; -import { applicationChangeState } from "../../store/actions/application"; -import { appReducer } from "../../store/reducers"; +import { applicationChangeState } from "../../../../store/actions/application"; +import { appReducer } from "../../../../store/reducers"; import { handlePendingMessageStateIfAllowedSaga, notificationsPlatform, @@ -15,7 +15,7 @@ import { logoutRequest, sessionExpired, sessionInvalid -} from "../../store/actions/authentication"; +} from "../../../../store/actions/authentication"; import { clearNotificationPendingMessage, notificationsInstallationTokenRegistered, @@ -24,16 +24,16 @@ import { import { PendingMessageState, pendingMessageStateSelector -} from "../../store/reducers/notifications/pendingMessage"; -import NavigationService from "../../navigation/NavigationService"; -import { isPaymentOngoingSelector } from "../../store/reducers/wallet/payment"; -import { navigateToMainNavigatorAction } from "../../store/actions/navigation"; -import { navigateToMessageRouterAction } from "../../features/messages/store/actions/navigation"; -import { UIMessageId } from "../../features/messages/types"; -import * as Analytics from "../../features/messages/analytics"; +} from "../../store/reducers/pendingMessage"; +import NavigationService from "../../../../navigation/NavigationService"; +import { isPaymentOngoingSelector } from "../../../../store/reducers/wallet/payment"; +import { navigateToMainNavigatorAction } from "../../../../store/actions/navigation"; +import { navigateToMessageRouterAction } from "../../../messages/store/actions/navigation"; +import { UIMessageId } from "../../../messages/types"; +import * as Analytics from "../../../messages/analytics"; const installationId = "installationId"; -jest.mock("../../utils/installation", () => ({ +jest.mock("../../utils/index", () => ({ generateInstallationId: () => installationId })); diff --git a/ts/sagas/startup/checkNotificationsPermissionsSaga.ts b/ts/features/pushNotifications/sagas/checkNotificationsPermissionsSaga.ts similarity index 79% rename from ts/sagas/startup/checkNotificationsPermissionsSaga.ts rename to ts/features/pushNotifications/sagas/checkNotificationsPermissionsSaga.ts index 63f776f13ad..e94f4337c74 100644 --- a/ts/sagas/startup/checkNotificationsPermissionsSaga.ts +++ b/ts/features/pushNotifications/sagas/checkNotificationsPermissionsSaga.ts @@ -1,14 +1,14 @@ import { CommonActions, StackActions } from "@react-navigation/native"; import { call, take } from "typed-redux-saga/macro"; import { ActionType } from "typesafe-actions"; -import NavigationService from "../../navigation/NavigationService"; -import ROUTES from "../../navigation/routes"; -import { notificationsInfoScreenConsent } from "../../store/actions/notifications"; -import { SagaCallReturnType } from "../../types/utils"; +import NavigationService from "../../../navigation/NavigationService"; +import ROUTES from "../../../navigation/routes"; +import { SagaCallReturnType } from "../../../types/utils"; import { checkNotificationPermissions, requestNotificationPermissions -} from "../../utils/notification"; +} from "../utils"; +import { notificationsInfoScreenConsent } from "../store/actions/notifications"; export function* checkNotificationsPermissionsSaga() { const authorizationStatus: SagaCallReturnType< diff --git a/ts/sagas/startup/checkNotificationsPreferencesSaga.ts b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts similarity index 82% rename from ts/sagas/startup/checkNotificationsPreferencesSaga.ts rename to ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts index b09e08125ca..dd19ba224f8 100644 --- a/ts/sagas/startup/checkNotificationsPreferencesSaga.ts +++ b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts @@ -1,17 +1,17 @@ import { CommonActions, StackActions } from "@react-navigation/native"; import { call, take } from "typed-redux-saga/macro"; import { ActionType } from "typesafe-actions"; -import { InitializedProfile } from "../../../definitions/backend/InitializedProfile"; -import { remindersOptInEnabled } from "../../config"; -import NavigationService from "../../navigation/NavigationService"; -import ROUTES from "../../navigation/routes"; -import { profileUpsert } from "../../store/actions/profile"; -import { isProfileFirstOnBoarding } from "../../store/reducers/profile"; +import { InitializedProfile } from "../../../../definitions/backend/InitializedProfile"; +import { remindersOptInEnabled } from "../../../config"; +import NavigationService from "../../../navigation/NavigationService"; +import ROUTES from "../../../navigation/routes"; +import { profileUpsert } from "../../../store/actions/profile"; +import { isProfileFirstOnBoarding } from "../../../store/reducers/profile"; +import { requestNotificationPermissions } from "../utils"; import { trackNotificationsOptInPreviewStatus, trackNotificationsOptInReminderStatus -} from "../../utils/analytics"; -import { requestNotificationPermissions } from "../../utils/notification"; +} from "../analytics"; import { checkNotificationsPermissionsSaga } from "./checkNotificationsPermissionsSaga"; export function* checkNotificationsPreferencesSaga( diff --git a/ts/sagas/notifications.ts b/ts/features/pushNotifications/sagas/notifications.ts similarity index 85% rename from ts/sagas/notifications.ts rename to ts/features/pushNotifications/sagas/notifications.ts index 38a6f933470..2b35f2f83ed 100644 --- a/ts/sagas/notifications.ts +++ b/ts/features/pushNotifications/sagas/notifications.ts @@ -9,27 +9,27 @@ import { Platform } from "react-native"; import { SagaIterator } from "redux-saga"; import { call, put, select } from "typed-redux-saga/macro"; import { NonEmptyString } from "@pagopa/ts-commons/lib/strings"; -import { PlatformEnum } from "../../definitions/backend/Platform"; -import { BackendClient } from "../api/backend"; +import { PlatformEnum } from "../../../../definitions/backend/Platform"; +import { BackendClient } from "../../../api/backend"; +import { notificationsInstallationSelector } from "../store/reducers/installation"; +import { SagaCallReturnType } from "../../../types/utils"; +import { convertUnknownToError } from "../../../utils/errors"; +import { + PendingMessageState, + pendingMessageStateSelector +} from "../store/reducers/pendingMessage"; +import { isPaymentOngoingSelector } from "../../../store/reducers/wallet/payment"; +import { navigateToMainNavigatorAction } from "../../../store/actions/navigation"; +import { navigateToMessageRouterAction } from "../../messages/store/actions/navigation"; +import NavigationService from "../../../navigation/NavigationService"; +import { UIMessageId } from "../../messages/types"; +import { trackMessageNotificationTap } from "../../messages/analytics"; +import { trackNotificationInstallationTokenNotChanged } from "../analytics"; import { clearNotificationPendingMessage, notificationsInstallationTokenRegistered, updateNotificationInstallationFailure } from "../store/actions/notifications"; -import { notificationsInstallationSelector } from "../store/reducers/notifications/installation"; -import { SagaCallReturnType } from "../types/utils"; -import { convertUnknownToError } from "../utils/errors"; -import { trackNotificationInstallationTokenNotChanged } from "../utils/analytics"; -import { - PendingMessageState, - pendingMessageStateSelector -} from "../store/reducers/notifications/pendingMessage"; -import { isPaymentOngoingSelector } from "../store/reducers/wallet/payment"; -import { navigateToMainNavigatorAction } from "../store/actions/navigation"; -import { navigateToMessageRouterAction } from "../features/messages/store/actions/navigation"; -import NavigationService from "../navigation/NavigationService"; -import { UIMessageId } from "../features/messages/types"; -import { trackMessageNotificationTap } from "../features/messages/analytics"; export const notificationsPlatform: PlatformEnum = Platform.select({ diff --git a/ts/screens/onboarding/OnboardingNotificationsInfoScreenConsent.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx similarity index 86% rename from ts/screens/onboarding/OnboardingNotificationsInfoScreenConsent.tsx rename to ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx index deef170f34b..2f866020596 100644 --- a/ts/screens/onboarding/OnboardingNotificationsInfoScreenConsent.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx @@ -17,24 +17,24 @@ import { } from "@pagopa/io-app-design-system"; import BaseScreenComponent, { ContextualHelpPropsMarkdown -} from "../../components/screens/BaseScreenComponent"; -import I18n from "../../i18n"; -import { IOStyles } from "../../components/core/variables/IOStyles"; -import { BlockButtonProps } from "../../components/ui/BlockButtons"; -import { FooterStackButton } from "../../components/buttons/FooterStackButtons"; -import { openAppSettings } from "../../utils/appSettings"; -import { useIODispatch } from "../../store/hooks"; -import { notificationsInfoScreenConsent } from "../../store/actions/notifications"; -import { checkNotificationPermissions } from "../../utils/notification"; -import { profilePreferencesSelector } from "../../store/reducers/profile"; +} from "../../../components/screens/BaseScreenComponent"; +import I18n from "../../../i18n"; +import { IOStyles } from "../../../components/core/variables/IOStyles"; +import { BlockButtonProps } from "../../../components/ui/BlockButtons"; +import { FooterStackButton } from "../../../components/buttons/FooterStackButtons"; +import { openAppSettings } from "../../../utils/appSettings"; +import { useIODispatch } from "../../../store/hooks"; +import { checkNotificationPermissions } from "../utils"; +import { profilePreferencesSelector } from "../../../store/reducers/profile"; +import { H2 } from "../../../components/core/typography/H2"; +import { H1 } from "../../../components/core/typography/H1"; +import { Body } from "../../../components/core/typography/Body"; +import { notificationsInfoScreenConsent } from "../store/actions/notifications"; import { trackNotificationsOptInOpenSettings, trackNotificationsOptInReminderOnPermissionsOff, trackNotificationsOptInSkipSystemPermissions -} from "../../utils/analytics"; -import { H2 } from "../../components/core/typography/H2"; -import { H1 } from "../../components/core/typography/H1"; -import { Body } from "../../components/core/typography/Body"; +} from "../analytics"; const contextualHelpMarkdown: ContextualHelpPropsMarkdown = { title: "onboarding.infoConsent.contextualHelpTitle", @@ -135,7 +135,7 @@ const instructions = Platform.select>({ ] }); -const OnboardingNotificationsInfoScreenConsent = () => { +export const OnboardingNotificationsInfoScreenConsent = () => { const dispatch = useIODispatch(); const optInPreferencesPot = useSelector(profilePreferencesSelector); @@ -229,5 +229,3 @@ const OnboardingNotificationsInfoScreenConsent = () => { ); }; - -export default OnboardingNotificationsInfoScreenConsent; diff --git a/ts/screens/onboarding/OnboardingNotificationsPreferencesScreen.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx similarity index 81% rename from ts/screens/onboarding/OnboardingNotificationsPreferencesScreen.tsx rename to ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx index 7ad3e8ff07f..4f5840ff4d7 100644 --- a/ts/screens/onboarding/OnboardingNotificationsPreferencesScreen.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx @@ -11,39 +11,39 @@ import { ContentWrapper, IOVisualCostants } from "@pagopa/io-app-design-system"; -import { PushNotificationsContentTypeEnum } from "../../../definitions/backend/PushNotificationsContentType"; -import { ReminderStatusEnum } from "../../../definitions/backend/ReminderStatus"; -import { InfoBox } from "../../components/box/InfoBox"; -import { IOBadge } from "../../components/core/IOBadge"; -import { Body } from "../../components/core/typography/Body"; -import { H1 } from "../../components/core/typography/H1"; -import { H5 } from "../../components/core/typography/H5"; -import { IOStyles } from "../../components/core/variables/IOStyles"; -import { PreferencesListItem } from "../../components/PreferencesListItem"; +import { PushNotificationsContentTypeEnum } from "../../../../definitions/backend/PushNotificationsContentType"; +import { ReminderStatusEnum } from "../../../../definitions/backend/ReminderStatus"; +import { InfoBox } from "../../../components/box/InfoBox"; +import { IOBadge } from "../../../components/core/IOBadge"; +import { Body } from "../../../components/core/typography/Body"; +import { H1 } from "../../../components/core/typography/H1"; +import { H5 } from "../../../components/core/typography/H5"; +import { IOStyles } from "../../../components/core/variables/IOStyles"; +import { PreferencesListItem } from "../../../components/PreferencesListItem"; import BaseScreenComponent, { ContextualHelpPropsMarkdown -} from "../../components/screens/BaseScreenComponent"; -import { BlockButtonProps } from "../../components/ui/BlockButtons"; -import FooterWithButtons from "../../components/ui/FooterWithButtons"; -import Switch from "../../components/ui/Switch"; -import I18n from "../../i18n"; -import { IOStackNavigationRouteProps } from "../../navigation/params/AppParamsList"; -import { OnboardingParamsList } from "../../navigation/params/OnboardingParamsList"; -import { profileUpsert } from "../../store/actions/profile"; -import { useIODispatch } from "../../store/hooks"; -import { profilePreferencesSelector } from "../../store/reducers/profile"; -import customVariables from "../../theme/variables"; -import { usePreviewMoreInfo } from "../../utils/hooks/usePreviewMoreInfo"; -import { showToast } from "../../utils/showToast"; -import { useOnFirstRender } from "../../utils/hooks/useOnFirstRender"; -import { getFlowType } from "../../utils/analytics"; +} from "../../../components/screens/BaseScreenComponent"; +import { BlockButtonProps } from "../../../components/ui/BlockButtons"; +import FooterWithButtons from "../../../components/ui/FooterWithButtons"; +import Switch from "../../../components/ui/Switch"; +import I18n from "../../../i18n"; +import { IOStackNavigationRouteProps } from "../../../navigation/params/AppParamsList"; +import { OnboardingParamsList } from "../../../navigation/params/OnboardingParamsList"; +import { profileUpsert } from "../../../store/actions/profile"; +import { useIODispatch } from "../../../store/hooks"; +import { profilePreferencesSelector } from "../../../store/reducers/profile"; +import customVariables from "../../../theme/variables"; +import { usePreviewMoreInfo } from "../hooks/usePreviewMoreInfo"; +import { showToast } from "../../../utils/showToast"; +import { useOnFirstRender } from "../../../utils/hooks/useOnFirstRender"; +import { getFlowType } from "../../../utils/analytics"; import { trackNotificationPreferenceConfiguration, trackNotificationScreen, trackNotificationsPreferencesPreviewStatus, trackNotificationsPreferencesReminderStatus -} from "../profile/analytics"; -import { NotificationsPreferencesPreview } from "./components/NotificationsPreferencesPreview"; +} from "../../../screens/profile/analytics"; +import { NotificationsPreferencesPreview } from "../components/NotificationsPreferencesPreview"; const styles = StyleSheet.create({ containerActions: { @@ -137,7 +137,7 @@ const Header = memo(({ isFirstOnboarding }: { isFirstOnboarding: boolean }) => { ); }); -const OnboardingNotificationsPreferencesScreen = (props: Props) => { +export const OnboardingNotificationsPreferencesScreen = (props: Props) => { const dispatch = useIODispatch(); const [previewEnabled, setPreviewEnabled] = useState(true); @@ -303,5 +303,3 @@ const OnboardingNotificationsPreferencesScreen = (props: Props) => { ); }; - -export default OnboardingNotificationsPreferencesScreen; diff --git a/ts/screens/onboarding/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx similarity index 88% rename from ts/screens/onboarding/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx rename to ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx index 8dd0d79a383..dc8eb0e3777 100644 --- a/ts/screens/onboarding/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx +++ b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx @@ -1,14 +1,14 @@ import configureMockStore from "redux-mock-store"; import { AppState } from "react-native"; import { fireEvent, waitFor } 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 OnboardingNotificationsInfoScreenConsent from "../OnboardingNotificationsInfoScreenConsent"; -import * as notificationsActions from "../../../store/actions/notifications"; -import * as notification from "../../../utils/notification"; +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 { OnboardingNotificationsInfoScreenConsent } from "../OnboardingNotificationsInfoScreenConsent"; +import * as notificationsActions from "../../store/actions/notifications"; +import * as notification from "../../utils"; const checkNotificationPermissions = jest.spyOn( notification, diff --git a/ts/screens/onboarding/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx similarity index 88% rename from ts/screens/onboarding/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx rename to ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx index b1d5a7dbb90..b7952ab7293 100644 --- a/ts/screens/onboarding/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx +++ b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx @@ -1,15 +1,15 @@ import * as pot from "@pagopa/ts-commons/lib/pot"; import _ from "lodash"; import configureMockStore from "redux-mock-store"; -import I18n from "../../../../ts/i18n"; -import ROUTES from "../../../navigation/routes"; -import { applicationChangeState } from "../../../store/actions/application"; -import { appReducer } from "../../../store/reducers"; -import { GlobalState } from "../../../store/reducers/types"; +import I18n from "../../../../i18n"; +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 mockedProfile from "../../../__mocks__/initializedProfile"; -import OnboardingNotificationsPreferencesScreen from "../OnboardingNotificationsPreferencesScreen"; +import { renderScreenWithNavigationStoreContext } from "../../../../utils/testWrapper"; +import mockedProfile from "../../../../__mocks__/initializedProfile"; +import { OnboardingNotificationsPreferencesScreen } from "../OnboardingNotificationsPreferencesScreen"; describe("OnboardingNotificationsPreferencesScreen", () => { describe("given an onboarded user", () => { diff --git a/ts/store/actions/notifications.ts b/ts/features/pushNotifications/store/actions/notifications.ts similarity index 94% rename from ts/store/actions/notifications.ts rename to ts/features/pushNotifications/store/actions/notifications.ts index 1a53d761883..bb80c20123f 100644 --- a/ts/store/actions/notifications.ts +++ b/ts/features/pushNotifications/store/actions/notifications.ts @@ -3,7 +3,7 @@ */ import { ActionType, createStandardAction } from "typesafe-actions"; -import { PendingMessageState } from "../reducers/notifications/pendingMessage"; +import { PendingMessageState } from "../reducers/pendingMessage"; export const updateNotificationsInstallationToken = createStandardAction( "NOTIFICATIONS_INSTALLATION_TOKEN_UPDATE" diff --git a/ts/features/pushNotifications/store/reducers/index.ts b/ts/features/pushNotifications/store/reducers/index.ts new file mode 100644 index 00000000000..b8fc94c5638 --- /dev/null +++ b/ts/features/pushNotifications/store/reducers/index.ts @@ -0,0 +1,20 @@ +/** + * Notifications reducer + */ + +import { combineReducers } from "redux"; +import { Action } from "../../../../store/actions/types"; +import { InstallationState, installationReducer } from "./installation"; +import { PendingMessageState, pendingMessageReducer } from "./pendingMessage"; + +export type NotificationsState = { + installation: InstallationState; + pendingMessage: PendingMessageState; +}; + +export const notificationsReducer = combineReducers( + { + installation: installationReducer, + pendingMessage: pendingMessageReducer + } +); diff --git a/ts/store/reducers/notifications/installation.ts b/ts/features/pushNotifications/store/reducers/installation.ts similarity index 79% rename from ts/store/reducers/notifications/installation.ts rename to ts/features/pushNotifications/store/reducers/installation.ts index 63ac8f0d0a0..92e5bf7f732 100644 --- a/ts/store/reducers/notifications/installation.ts +++ b/ts/features/pushNotifications/store/reducers/installation.ts @@ -1,22 +1,17 @@ -/** - * Notifications installation reducer - */ - import { getType } from "typesafe-actions"; - -import { generateInstallationId } from "../../../utils/installation"; -import { - notificationsInstallationTokenRegistered, - updateNotificationsInstallationToken -} from "../../actions/notifications"; -import { Action } from "../../actions/types"; -import { GlobalState } from "../types"; +import { Action } from "../../../../store/actions/types"; +import { GlobalState } from "../../../../store/reducers/types"; import { logoutRequest, sessionExpired, sessionInvalid -} from "../../actions/authentication"; -import { clearCache } from "../../actions/profile"; +} from "../../../../store/actions/authentication"; +import { clearCache } from "../../../../store/actions/profile"; +import { + notificationsInstallationTokenRegistered, + updateNotificationsInstallationToken +} from "../actions/notifications"; +import { generateInstallationId } from "../../utils"; export type InstallationState = Readonly<{ id: string; @@ -34,7 +29,7 @@ export function getInitialState(): InstallationState { }; } -const reducer = ( +export const installationReducer = ( state: InstallationState = getInitialState(), action: Action ): InstallationState => { @@ -58,5 +53,3 @@ const reducer = ( // Selectors export const notificationsInstallationSelector = (state: GlobalState) => state.notifications.installation; - -export default reducer; diff --git a/ts/store/reducers/notifications/pendingMessage.ts b/ts/features/pushNotifications/store/reducers/pendingMessage.ts similarity index 79% rename from ts/store/reducers/notifications/pendingMessage.ts rename to ts/features/pushNotifications/store/reducers/pendingMessage.ts index 5124e5da1bf..80689cb9527 100644 --- a/ts/store/reducers/notifications/pendingMessage.ts +++ b/ts/features/pushNotifications/store/reducers/pendingMessage.ts @@ -3,12 +3,12 @@ */ import { getType } from "typesafe-actions"; +import { Action } from "../../../../store/actions/types"; +import { GlobalState } from "../../../../store/reducers/types"; import { clearNotificationPendingMessage, updateNotificationsPendingMessage -} from "../../actions/notifications"; -import { Action } from "../../actions/types"; -import { GlobalState } from "../types"; +} from "../actions/notifications"; export type PendingMessageState = Readonly<{ id: string; @@ -18,7 +18,7 @@ export type PendingMessageState = Readonly<{ const INITIAL_STATE: PendingMessageState = null; -const reducer = ( +export const pendingMessageReducer = ( state: PendingMessageState = INITIAL_STATE, action: Action ): PendingMessageState => { @@ -34,8 +34,6 @@ const reducer = ( } }; -export default reducer; - // Selector export const pendingMessageStateSelector = (state: GlobalState) => state.notifications.pendingMessage; diff --git a/ts/utils/__tests__/reactNativePushNotificationiOS.test.ts b/ts/features/pushNotifications/utils/__tests__/reactNativePushNotificationiOS.test.ts similarity index 100% rename from ts/utils/__tests__/reactNativePushNotificationiOS.test.ts rename to ts/features/pushNotifications/utils/__tests__/reactNativePushNotificationiOS.test.ts diff --git a/ts/boot/configurePushNotification.ts b/ts/features/pushNotifications/utils/configurePushNotification.ts similarity index 94% rename from ts/boot/configurePushNotification.ts rename to ts/features/pushNotifications/utils/configurePushNotification.ts index a501f9a8264..08d03b30b30 100644 --- a/ts/boot/configurePushNotification.ts +++ b/ts/features/pushNotifications/utils/configurePushNotification.ts @@ -16,22 +16,22 @@ import { maximumItemsFromAPI, pageSize, remindersOptInEnabled -} from "../config"; +} from "../../../config"; import { loadPreviousPageMessages, reloadAllMessages -} from "../features/messages/store/actions"; +} from "../../messages/store/actions"; +import { getCursors } from "../../messages/store/reducers/allPaginated"; +import { isDevEnv } from "../../../utils/environment"; +import { + trackMessageNotificationParsingFailure, + trackMessageNotificationTap +} from "../../messages/analytics"; +import { store } from "../../../boot/configureStoreAndPersistor"; import { updateNotificationsInstallationToken, updateNotificationsPendingMessage } from "../store/actions/notifications"; -import { getCursors } from "../features/messages/store/reducers/allPaginated"; -import { isDevEnv } from "../utils/environment"; -import { - trackMessageNotificationParsingFailure, - trackMessageNotificationTap -} from "../features/messages/analytics"; -import { store } from "./configureStoreAndPersistor"; /** * Helper type used to validate the notification payload. diff --git a/ts/utils/notification.ts b/ts/features/pushNotifications/utils/index.ts similarity index 69% rename from ts/utils/notification.ts rename to ts/features/pushNotifications/utils/index.ts index 0d858359a45..98728c58d8a 100644 --- a/ts/utils/notification.ts +++ b/ts/features/pushNotifications/utils/index.ts @@ -3,9 +3,14 @@ import * as B from "fp-ts/lib/boolean"; import * as E from "fp-ts/lib/Either"; import * as T from "fp-ts/lib/Task"; import * as TE from "fp-ts/lib/TaskEither"; +import { v4 as uuid } from "uuid"; import { Platform, PermissionsAndroid } from "react-native"; import PushNotificationIOS from "@react-native-community/push-notification-ios"; -import { isIos } from "./platform"; +import PushNotification from "react-native-push-notification"; +import { isIos } from "../../../utils/platform"; + +// DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU ARE DOING +const UUID_VERSION_PREFIX = "001"; export enum AuthorizationStatus { NotDetermined = 0, @@ -101,3 +106,29 @@ export const requestNotificationPermissions = () => ), TE.getOrElse(() => T.of(false)) )(); + +/** + * Remove all the local notifications related to authentication with spid. + * + * With the previous library version (7.3.1 - now 8.1.1), cancelLocalNotifications + * did not work. At the moment, the "first access spid" is the only kind of + * scheduled notification and for this reason it is safe to use + * PushNotification.cancelAllLocalNotifications(); + * If we add more scheduled notifications, we need to investigate if + * cancelLocalNotifications works with the new library version + */ +export const cancellAllLocalNotifications = () => + PushNotification.cancelAllLocalNotifications(); + +/** + * Generates a new random installation ID with the following format: + * + * + * + * Where: + * VERSION_PREFIX is \d{3} + * UUID is [a-z0-9]{32} + */ +export function generateInstallationId(): string { + return `${UUID_VERSION_PREFIX}${uuid().replace(/-/g, "")}`; +} diff --git a/ts/navigation/OnboardingNavigator.tsx b/ts/navigation/OnboardingNavigator.tsx index e875501196b..7400561c721 100644 --- a/ts/navigation/OnboardingNavigator.tsx +++ b/ts/navigation/OnboardingNavigator.tsx @@ -1,8 +1,8 @@ import { createStackNavigator } from "@react-navigation/stack"; import * as React from "react"; import OnboardingCompletedScreen from "../screens/onboarding/OnboardingCompletedScreen"; -import OnboardingNotificationsInfoScreenConsent from "../screens/onboarding/OnboardingNotificationsInfoScreenConsent"; -import OnboardingNotificationsPreferencesScreen from "../screens/onboarding/OnboardingNotificationsPreferencesScreen"; +import { OnboardingNotificationsInfoScreenConsent } from "../features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent"; +import { OnboardingNotificationsPreferencesScreen } from "../features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen"; import OnboardingPinScreen from "../screens/onboarding/OnboardingPinScreen"; import OnboardingServicesPreferenceScreen from "../screens/onboarding/OnboardingServicesPreferenceScreen"; import OnboardingShareDataScreen from "../screens/onboarding/OnboardingShareDataScreen"; diff --git a/ts/navigation/params/OnboardingParamsList.ts b/ts/navigation/params/OnboardingParamsList.ts index dada8c7e052..a44b73e2651 100644 --- a/ts/navigation/params/OnboardingParamsList.ts +++ b/ts/navigation/params/OnboardingParamsList.ts @@ -1,4 +1,4 @@ -import { OnboardingNotificationsPreferencesScreenNavigationParams } from "../../screens/onboarding/OnboardingNotificationsPreferencesScreen"; +import { OnboardingNotificationsPreferencesScreenNavigationParams } from "../../features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen"; import { OnboardingServicesPreferenceScreenNavigationParams } from "../../screens/onboarding/OnboardingServicesPreferenceScreen"; import { EmailInsertScreenNavigationParams } from "../../screens/profile/EmailInsertScreen"; import { SendEmailValidationScreenProp } from "../../screens/profile/EmailValidationSendEmailScreen"; diff --git a/ts/sagas/__tests__/initializeApplicationSaga.test.ts b/ts/sagas/__tests__/initializeApplicationSaga.test.ts index d4291bfedc1..233e4b3d9a2 100644 --- a/ts/sagas/__tests__/initializeApplicationSaga.test.ts +++ b/ts/sagas/__tests__/initializeApplicationSaga.test.ts @@ -26,7 +26,6 @@ import { } from "../profile"; import { initializeApplicationSaga, - testCancellAllLocalNotifications, testWaitForNavigatorServiceInitialization } from "../startup"; import { watchSessionExpiredSaga } from "../startup/watchSessionExpiredSaga"; @@ -43,6 +42,7 @@ import { isFastLoginEnabledSelector } from "../../features/fastLogin/store/selec import { refreshSessionToken } from "../../features/fastLogin/store/actions/tokenRefreshActions"; import { backendStatusSelector } from "../../store/reducers/backendStatus"; import { watchLogoutSaga } from "../startup/watchLogoutSaga"; +import { cancellAllLocalNotifications } from "../../features/pushNotifications/utils"; const aSessionToken = "a_session_token" as SessionToken; @@ -74,7 +74,7 @@ describe("initializeApplicationSaga", () => { .next() .call(testWaitForNavigatorServiceInitialization!) .next() - .call(testCancellAllLocalNotifications!) + .call(cancellAllLocalNotifications) .next() .call(previousInstallationDataDeleteSaga) .next() @@ -126,7 +126,7 @@ describe("initializeApplicationSaga", () => { .next() .call(testWaitForNavigatorServiceInitialization!) .next() - .call(testCancellAllLocalNotifications!) + .call(cancellAllLocalNotifications) .next() .call(previousInstallationDataDeleteSaga) .next() @@ -168,7 +168,7 @@ describe("initializeApplicationSaga", () => { .next() .call(testWaitForNavigatorServiceInitialization!) .next() - .call(testCancellAllLocalNotifications!) + .call(cancellAllLocalNotifications) .next() .call(previousInstallationDataDeleteSaga) .next() @@ -215,7 +215,7 @@ describe("initializeApplicationSaga", () => { .next() .call(testWaitForNavigatorServiceInitialization!) .next() - .call(testCancellAllLocalNotifications!) + .call(cancellAllLocalNotifications) .next() .call(previousInstallationDataDeleteSaga) .next() diff --git a/ts/sagas/identification.ts b/ts/sagas/identification.ts index 92fedfde3ae..8913acce829 100644 --- a/ts/sagas/identification.ts +++ b/ts/sagas/identification.ts @@ -29,8 +29,8 @@ import { paymentsCurrentStateSelector } from "../store/reducers/payments/current import { PinString } from "../types/PinString"; import { ReduxSagaEffect, SagaCallReturnType } from "../types/utils"; import { deletePin, getPin } from "../utils/keychain"; +import { handlePendingMessageStateIfAllowedSaga } from "../features/pushNotifications/sagas/notifications"; import { isFastLoginEnabledSelector } from "./../features/fastLogin/store/selectors/index"; -import { handlePendingMessageStateIfAllowedSaga } from "./notifications"; type ResultAction = | ActionType diff --git a/ts/sagas/installation.ts b/ts/sagas/installation.ts index e906b9c9db2..ffb33ba0623 100644 --- a/ts/sagas/installation.ts +++ b/ts/sagas/installation.ts @@ -1,5 +1,5 @@ /** - * A saga to manage notifications + * A saga to manage session invalidation */ import { put, select } from "typed-redux-saga/macro"; import { sessionInvalid } from "../store/actions/authentication"; diff --git a/ts/sagas/startup.ts b/ts/sagas/startup.ts index e1cc53bdc51..b148f98ef3d 100644 --- a/ts/sagas/startup.ts +++ b/ts/sagas/startup.ts @@ -3,7 +3,6 @@ import { Millisecond } from "@pagopa/ts-commons/lib/units"; import * as O from "fp-ts/lib/Option"; import { pipe } from "fp-ts/lib/function"; import { Alert } from "react-native"; -import PushNotification from "react-native-push-notification"; import { channel } from "redux-saga"; import { call, @@ -99,6 +98,12 @@ import { watchEmailValidationSaga } from "../store/sagas/emailValidationPollingS import { handleIsKeyStrongboxBacked } from "../features/lollipop/utils/crypto"; import { watchWalletSaga as watchNewWalletSaga } from "../features/newWallet/saga"; import { watchServicesSaga } from "../features/services/common/saga"; +import { + handlePendingMessageStateIfAllowedSaga, + updateInstallationSaga +} from "../features/pushNotifications/sagas/notifications"; +import { checkNotificationsPreferencesSaga } from "../features/pushNotifications/sagas/checkNotificationsPreferencesSaga"; +import { cancellAllLocalNotifications } from "../features/pushNotifications/utils"; import { clearKeychainError, keychainError @@ -111,10 +116,6 @@ import { initMixpanel, watchForActionsDifferentFromRequestLogoutThatMustResetMixpanel } from "./mixpanel"; -import { - handlePendingMessageStateIfAllowedSaga, - updateInstallationSaga -} from "./notifications"; import { setLanguageFromProfileIfExists } from "./preferences"; import { loadProfile, @@ -131,7 +132,6 @@ import { checkAcknowledgedEmailSaga } from "./startup/checkAcknowledgedEmailSaga import { checkConfiguredPinSaga } from "./startup/checkConfiguredPinSaga"; import { watchEmailNotificationPreferencesSaga } from "./startup/checkEmailNotificationPreferencesSaga"; import { checkEmailSaga } from "./startup/checkEmailSaga"; -import { checkNotificationsPreferencesSaga } from "./startup/checkNotificationsPreferencesSaga"; import { checkProfileEnabledSaga } from "./startup/checkProfileEnabledSaga"; import { completeOnboardingSaga } from "./startup/completeOnboardingSaga"; import { loadSessionInformationSaga } from "./startup/loadSessionInformationSaga"; @@ -707,20 +707,6 @@ function* waitForMainNavigator() { }); } -/** - * Remove all the local notifications related to authentication with spid. - * - * With the previous library version (7.3.1 - now 8.1.1), cancelLocalNotifications - * did not work. At the moment, the "first access spid" is the only kind of - * scheduled notification and for this reason it is safe to use - * PushNotification.cancelAllLocalNotifications(); - * If we add more scheduled notifications, we need to investigate if - * cancelLocalNotifications works with the new library version - */ -function cancellAllLocalNotifications() { - PushNotification.cancelAllLocalNotifications(); -} - export function* startupSaga(): IterableIterator { // Wait until the IngressScreen gets mounted yield* takeLatest( @@ -732,7 +718,3 @@ export function* startupSaga(): IterableIterator { export const testWaitForNavigatorServiceInitialization = isTestEnv ? waitForNavigatorServiceInitialization : undefined; - -export const testCancellAllLocalNotifications = isTestEnv - ? cancellAllLocalNotifications - : undefined; diff --git a/ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx b/ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx index b0fe64df966..00ef80cf310 100644 --- a/ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx +++ b/ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx @@ -2,12 +2,12 @@ import { CommonActions, StackActions } from "@react-navigation/native"; import { testSaga } from "redux-saga-test-plan"; import NavigationService from "../../../navigation/NavigationService"; import ROUTES from "../../../navigation/routes"; -import { notificationsInfoScreenConsent } from "../../../store/actions/notifications"; import { checkNotificationPermissions, requestNotificationPermissions -} from "../../../utils/notification"; -import { checkNotificationsPermissionsSaga } from "../checkNotificationsPermissionsSaga"; +} from "../../../features/pushNotifications/utils"; +import { checkNotificationsPermissionsSaga } from "../../../features/pushNotifications/sagas/checkNotificationsPermissionsSaga"; +import { notificationsInfoScreenConsent } from "../../../features/pushNotifications/store/actions/notifications"; describe("checkNotificationsPermissionsSaga", () => { it("upon saga startup, it should ask for push notifications permission", () => { diff --git a/ts/sagas/startup/watchApplicationActivitySaga.ts b/ts/sagas/startup/watchApplicationActivitySaga.ts index 513cefba582..6bcb2ef4c67 100644 --- a/ts/sagas/startup/watchApplicationActivitySaga.ts +++ b/ts/sagas/startup/watchApplicationActivitySaga.ts @@ -10,7 +10,7 @@ import { StartupStatusEnum, isStartupLoaded } from "../../store/reducers/startup"; -import { handlePendingMessageStateIfAllowedSaga } from "../notifications"; +import { handlePendingMessageStateIfAllowedSaga } from "../../features/pushNotifications/sagas/notifications"; /** * Listen to APP_STATE_CHANGE_ACTION and: diff --git a/ts/screens/profile/DeveloperModeSection.tsx b/ts/screens/profile/DeveloperModeSection.tsx index db31a56484d..915e0269a22 100644 --- a/ts/screens/profile/DeveloperModeSection.tsx +++ b/ts/screens/profile/DeveloperModeSection.tsx @@ -43,7 +43,7 @@ import { walletTokenSelector } from "../../store/reducers/authentication"; import { isDebugModeEnabledSelector } from "../../store/reducers/debug"; -import { notificationsInstallationSelector } from "../../store/reducers/notifications/installation"; +import { notificationsInstallationSelector } from "../../features/pushNotifications/store/reducers/installation"; import { isIdPayTestEnabledSelector, isItWalletTestEnabledSelector, diff --git a/ts/screens/profile/NotificationsPreferencesScreen.tsx b/ts/screens/profile/NotificationsPreferencesScreen.tsx index b1cbc875396..2d1700b56c2 100644 --- a/ts/screens/profile/NotificationsPreferencesScreen.tsx +++ b/ts/screens/profile/NotificationsPreferencesScreen.tsx @@ -15,7 +15,7 @@ import { useIODispatch } from "../../store/hooks"; import { profilePreferencesSelector } from "../../store/reducers/profile"; import { getFlowType } from "../../utils/analytics"; import { useOnFirstRender } from "../../utils/hooks/useOnFirstRender"; -import { usePreviewMoreInfo } from "../../utils/hooks/usePreviewMoreInfo"; +import { usePreviewMoreInfo } from "../../features/pushNotifications/hooks/usePreviewMoreInfo"; import { showToast } from "../../utils/showToast"; import { trackNotificationScreen, diff --git a/ts/store/actions/types.ts b/ts/store/actions/types.ts index 9866cf30620..275f2e47f08 100644 --- a/ts/store/actions/types.ts +++ b/ts/store/actions/types.ts @@ -26,6 +26,7 @@ import { PayPalOnboardingActions } from "../../features/wallet/onboarding/paypal import { ServicesActions as NewServicesActions } from "../../features/services/common/store/actions"; import { WhatsNewActions } from "../../features/whatsnew/store/actions"; import { ZendeskSupportActions } from "../../features/zendesk/store/actions"; +import { NotificationsActions } from "../../features/pushNotifications/store/actions/notifications"; import { GlobalState } from "../reducers/types"; import { AnalyticsActions } from "./analytics"; import { ApplicationActions } from "./application"; @@ -39,7 +40,6 @@ import { DebugActions } from "./debug"; import { IdentificationActions } from "./identification"; import { InstallationActions } from "./installation"; import { MixpanelActions } from "./mixpanel"; -import { NotificationsActions } from "./notifications"; import { OnboardingActions } from "./onboarding"; import { OrganizationsActions } from "./organizations"; import { PaymentsActions } from "./payments"; diff --git a/ts/store/middlewares/analytics.ts b/ts/store/middlewares/analytics.ts index cd5ed8c5807..28cfcb71197 100644 --- a/ts/store/middlewares/analytics.ts +++ b/ts/store/middlewares/analytics.ts @@ -47,11 +47,6 @@ import { identificationStart, identificationSuccess } from "../actions/identification"; -import { - notificationsInstallationTokenRegistered, - updateNotificationInstallationFailure, - updateNotificationsInstallationToken -} from "../actions/notifications"; import { profileFirstLogin, profileLoadFailure, @@ -107,6 +102,11 @@ import { updatePaymentStatus } from "../actions/wallet/wallets"; import { buildEventProperties } from "../../utils/analytics"; +import { + notificationsInstallationTokenRegistered, + updateNotificationInstallationFailure, + updateNotificationsInstallationToken +} from "../../features/pushNotifications/store/actions/notifications"; import { trackContentAction } from "./contentAnalytics"; import { trackServiceAction } from "./serviceAnalytics"; diff --git a/ts/store/reducers/index.ts b/ts/store/reducers/index.ts index 50b1da8ee2e..fb8ef4461dc 100644 --- a/ts/store/reducers/index.ts +++ b/ts/store/reducers/index.ts @@ -29,6 +29,7 @@ import { DateISO8601Transform } from "../transforms/dateISO8601Tranform"; import { whatsNewInitialState } from "../../features/whatsnew/store/reducers"; import { fastLoginOptInInitialState } from "../../features/fastLogin/store/reducers/optInReducer"; import { isDevEnv } from "../../utils/environment"; +import { notificationsReducer } from "../../features/pushNotifications/store/reducers"; import appStateReducer from "./appState"; import assistanceToolsReducer from "./assistanceTools"; import authenticationReducer, { @@ -55,7 +56,6 @@ import identificationReducer, { } from "./identification"; import installationReducer from "./installation"; import { navigationReducer } from "./navigation"; -import notificationsReducer from "./notifications"; import onboardingReducer from "./onboarding"; import paymentsReducer from "./payments"; import persistedPreferencesReducer, { diff --git a/ts/store/reducers/notifications/index.ts b/ts/store/reducers/notifications/index.ts deleted file mode 100644 index 9e5550667cb..00000000000 --- a/ts/store/reducers/notifications/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Notifications reducer - */ - -import { combineReducers } from "redux"; -import { Action } from "../../actions/types"; -import installationReducer, { InstallationState } from "./installation"; -import pendingMessageReducer, { PendingMessageState } from "./pendingMessage"; - -export type NotificationsState = { - installation: InstallationState; - pendingMessage: PendingMessageState; -}; - -const reducer = combineReducers({ - installation: installationReducer, - pendingMessage: pendingMessageReducer -}); - -export default reducer; diff --git a/ts/store/reducers/types.ts b/ts/store/reducers/types.ts index 62677fbe2b8..47debb63c2c 100644 --- a/ts/store/reducers/types.ts +++ b/ts/store/reducers/types.ts @@ -4,6 +4,7 @@ import { VersionInfoState } from "../../common/versionInfo/store/reducers/versio import { BonusState } from "../../features/bonus/common/store/reducers"; import { PersistedFeaturesState } from "../../features/common/store/reducers"; import { PersistedLollipopState } from "../../features/lollipop/store"; +import { NotificationsState } from "../../features/pushNotifications/store/reducers"; import { AppState } from "./appState"; import { AssistanceToolsState } from "./assistanceTools"; import { PersistedAuthenticationState } from "./authentication"; @@ -18,7 +19,6 @@ import { PersistedEntitiesState } from "./entities"; import { PersistedIdentificationState } from "./identification"; import { InstallationState } from "./installation"; import { NavigationState } from "./navigation"; -import { NotificationsState } from "./notifications"; import { OnboardingState } from "./onboarding"; import { PaymentsState } from "./payments"; import { PersistedPreferencesState } from "./persistedPreferences"; diff --git a/ts/utils/analytics.ts b/ts/utils/analytics.ts index a33877960dc..0e1e6afeb3a 100644 --- a/ts/utils/analytics.ts +++ b/ts/utils/analytics.ts @@ -8,9 +8,7 @@ import { import URLParse from "url-parse"; import EUCOVIDCERT_ROUTES from "../features/euCovidCert/navigation/routes"; import { euCovidCertificateEnabled } from "../config"; -import { PushNotificationsContentTypeEnum } from "../../definitions/backend/PushNotificationsContentType"; import { mixpanelTrack } from "../mixpanel"; -import { ReminderStatusEnum } from "../../definitions/backend/ReminderStatus"; import { isLoginUtilsError } from "../features/lollipop/utils/login"; import { ServicesDetailLoadTrack } from "../sagas/startup/loadServiceDetailRequestHandler"; @@ -95,57 +93,6 @@ export const buildEventProperties = ( flow }); -// Notifications related events - -export function trackNotificationInstallationTokenNotChanged() { - void mixpanelTrack("NOTIFICATIONS_INSTALLATION_TOKEN_NOT_CHANGED"); -} - -export function trackNotificationsOptInPreviewStatus( - contentType: PushNotificationsContentTypeEnum -) { - void mixpanelTrack( - "NOTIFICATIONS_OPTIN_PREVIEW_STATUS", - buildEventProperties("UX", "action", { - enabled: contentType === PushNotificationsContentTypeEnum.FULL - }) - ); -} - -export function trackNotificationsOptInReminderStatus( - reminderStatus: ReminderStatusEnum -) { - void mixpanelTrack( - "NOTIFICATIONS_OPTIN_REMINDER_STATUS", - buildEventProperties("UX", "action", { - enabled: reminderStatus === ReminderStatusEnum.ENABLED - }) - ); -} - -export function trackNotificationsOptInReminderOnPermissionsOff() { - void mixpanelTrack( - "NOTIFICATIONS_OPTIN_REMINDER_ON_PERMISSIONS_OFF", - buildEventProperties("UX", "control") - ); -} - -export function trackNotificationsOptInOpenSettings() { - void mixpanelTrack( - "NOTIFICATIONS_OPTIN_OPEN_SETTINGS", - buildEventProperties("UX", "action") - ); -} - -export function trackNotificationsOptInSkipSystemPermissions() { - void mixpanelTrack( - "NOTIFICATIONS_OPTIN_SKIP_SYSTEM_PERMISSIONS", - buildEventProperties("UX", "action") - ); -} - -// End of Notifications related events - // Services related events export function trackServiceDetailLoadingStatistics( diff --git a/ts/utils/installation.ts b/ts/utils/installation.ts deleted file mode 100644 index 13e71dbbe28..00000000000 --- a/ts/utils/installation.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Utility methods for generating installation IDs for Notification Hubs - */ - -import { v4 as uuid } from "uuid"; - -// DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU ARE DOING -const UUID_VERSION_PREFIX = "001"; - -/** - * Generates a new random installation ID with the following format: - * - * - * - * Where: - * VERSION_PREFIX is \d{3} - * UUID is [a-z0-9]{32} - */ -export function generateInstallationId(): string { - return `${UUID_VERSION_PREFIX}${uuid().replace(/-/g, "")}`; -} From 76ff2836348d8289a07763536c5f7f0293672709 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Wed, 1 May 2024 23:32:46 +0200 Subject: [PATCH 02/17] WiP --- img/onboarding/notification_blue.png | Bin 2746 -> 0 bytes img/onboarding/notification_blue@2x.png | Bin 6256 -> 0 bytes img/onboarding/notification_blue@3x.png | Bin 9371 -> 0 bytes img/onboarding/notification_white.png | Bin 2709 -> 2474 bytes img/onboarding/notification_white@2x.png | Bin 6027 -> 5602 bytes img/onboarding/notification_white@3x.png | Bin 9046 -> 8769 bytes locales/it/index.yml | 16 +- .../components/NotificationPreviewSample.tsx | 24 +- .../NotificationsPreferencesPreview.tsx | 7 +- .../hooks/usePreviewMoreInfo.tsx | 33 +- ...boardingNotificationsPreferencesScreen.tsx | 282 +++++------------- ts/navigation/OnboardingNavigator.tsx | 2 - 12 files changed, 113 insertions(+), 251 deletions(-) delete mode 100644 img/onboarding/notification_blue.png delete mode 100644 img/onboarding/notification_blue@2x.png delete mode 100644 img/onboarding/notification_blue@3x.png diff --git a/img/onboarding/notification_blue.png b/img/onboarding/notification_blue.png deleted file mode 100644 index 378ce65d796a741c7fab02ea32d564065a2e0e1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2746 zcmbVOc{mj69-giuNt-Rk&PbCjBl|ki5N1SqL+rVM`C&W$w004dq^Q*QT z&E$}LoSU;gV9EX92yeK#V*~)eC-5&G0TdLS=Nul1u!TVZ_+jy7&gQ7UiM0s;(45J~ z_B;jvoIqGyHMxm7vPQ8E7F?1T*cd?V%Zm6fCe=k{{ZW;xEpPJVq&Qec+92H02Ob_^ zIVfYR`k;KSPB>z@($;&_H0)S~sgU2#cR;;x z>5xQ<*^HWu?_sQN$?;y-G#SS)oGDSn0|tSETm?q(G+GtBJx9fYwu_GX`h|Xq(`@&WtZ=X%;!Xyv8oE8wB@Y^>M8|fFiAymqp3Zsr zt(gC>L$SN$15=XDq@Ge7V|enDiA+<j?{+HQXrN(*tC_nL{oX+2C}z7gQ0IGm zIeQ~(eJb+(St^%$eb$$3b_e-!9ai;;=k7>;-|fjuIGvK9x3J!Ep!7rj z4YqmY%UiFoNa>D6PI`{9mBiij2>Ti@KRl+dOZ6FnM>&(!Lel6pkr?B<)a#m;C#@fP zMxF@1A5=jv*y+};Kt}WS$<+hM!7&qnm$L{Fpoo^?slIHb*fTY1dxun|Ss-hwH`6&% zC6Ok6JJJTm*a=b#U}TxJw&~*!V~pz)x%G#InJ5d)EKL;|5|z9=LxyKDd&Z33`o%nT z18T&N9I&!x3yJwtPmj&@80D+UajhwQqPyOZPGeoD5?M2`q15I9mv-0aQ3ZAmB~y>h z_Kh?gvFL?cB|Ef$Wmy)m78J4J7t#193BSJ;Wr=YivaAgyAq^YZv9q?z*xkJGU;WHqk(3>cWAT#2bov z6}_{PIzj<0AP>iSqwL96sAorExjF3aV4nBhTEhyI#j%4*XolFKnU zraBN8ck{4&e(*MKvlE9;suOPWKu$D!HXaK?os&fKQx}6-Xy@mR(Rvk=OxY#>st^ZR zk#0~75cqEB_oI8+5}_|m#w)06GR!@MVcorg0i1_b^pTtmJ4nHZp!4eMZ7VJ)w8tZ9 z&mD8*yu>%fd+>kAdRGRumPf$4i8kfG{dPU?%Cl7^qjYyq6}kcX%LJxPzj>J;%>H0b zv?Xd0-Rd=_dI&6eX?5Z05+zF6xvE7%EOrvCZz`r2z%yShAmlnyBlXAy$0DlV7g28t zy;e3KvZjrA)ide05jeCbp)wI**6pq0mNqsoupiTFyt6_X)#$$R!S|jom&hrPTMAP1 zT=+8l44L5Ny>erYaE^kfWzA`4*DG*Hd0SLD({Y}03^*1<6e#X{bxa=Y2y4R)l1H)9;I=2 zCFq?H;@oWov49DxG-~1OsO@-=@&Oy(M^W)v8BqaBD5lWZTn&36Xw5>r;kxLLt}*SR zQ(#HYVZxwnpNFndNrQn3Hn6+x7UOyr5qXsy`|lb2%e-nR5+qzQNN){T<)2H8P4w;Q`dvRJ2xVE&vTP%z<(KsnPN(>{VIe- zi>+So%>O*^ET^td3&TB{42KBqpGv_lL^HF+8xU#HyKxgP&r9Gh1Jw(43FUE|1c)7war2AAvH_CNR4lKzONFw(J^94QR2~uWBK1YJW ziV1-yKw4Nu#=~>jwzGj?|F4ijHIGxNdS?qJ)lf|XukLQu;E-m=9#P>n()~DmaaD&v zjw0jel~g@X%d?U-zlIyLyg`C!sJ$RM;Y2?U^&msgY5H*n6+Wd&BK(~ivf7$Z+n-AS z_T!q)a;n5QDkF&QOSbvDvoBXx-$w42@VrA{oa45R<3T7@?@CR6sw(F;&HqisakjRW zPb~z*u_yN*o2Hy{{<43!DVzQ3lU_q!sNoE<=MdZsW{g`M%Ti?AOyoUbOp!VG>D5A{g+C!k0|Hvj+t diff --git a/img/onboarding/notification_blue@2x.png b/img/onboarding/notification_blue@2x.png deleted file mode 100644 index 0aaf19be83f28b79a86192cfcc4186938531e705..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6256 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

*z+(=~msg$(V2XvHbVE?J8va-B#Y&%O1Y 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 diff --git a/img/onboarding/notification_white.png b/img/onboarding/notification_white.png index b3458b5a9a62419e4a7cb5b22f71b602c381f6cd..d719c33999dadb3a6d7a978be09b8a726319caf5 100644 GIT binary patch literal 2474 zcmd^BX*3%O77h)yR7q1Rm14Ts!dR+8X@jaFq^MFwtgm)zEn49*efC-&A(qnGUTsn9 zONH3g-YSi~wNwzXCiWy_PXEn$XJ-D-k9+UA_nhy3_kQR8xN)YadjfnH`2YZbfT4k& z`AJMUv5!35C;oJf+vStM`_#ZX007_z|I0W4*}0-8MUDXTd%A$CA?V6U0(8|e(E$M7 zC-WaWa-9GWhI%>{Asn=s8Q%w#ORZbqG%)<#rDnzeT!FldT;HSXrT`O*K(VIpPKwRB z4erkjsCMkEb&s-7!Cz3TW230wf0O#a3(PJM<`TZEV|Mv`c3MeMYUSuwTzJ^)g0Rkl*%`_75ZkKOh@V>z0S z8mX?HY3f%ahwGj)m~6BgvpIGnVLV+D%8YUz#sE+s!%0{ZWcbr zf~%sVBICQHqdDoVerJJ&rb3^x^X6)}!psdP+7g9<=>t~-IOzpT6Kw@x;9?cQ*l{_D zf+2C&R37$w&C6sMaj}UX@f(XZiuC8>0<41qBEcj(;^8enc?SOrwD?l*%>WMr)GP4} z+Xl?YXppDMQHa^PR#vK$dp)H`%ThE2c>&dTd|YEox&;YkOS}?U9Q%C5Tz!PJ)sn^z zk}w|ZWyaih!S84(?n{UPU98bw`jXO_sc^-7-gf2BTG{B78fu@zZL0{~O&j}fZ#_FVn&2aGYeIBqym@&QIDFDtdL(|LUg>LJ<~ zS|Q6m%CUKbZ62s|R;(nv55=MK5kW8S(-~9A7w464=fAkT!}|S6Nyb7>309^jnfpt# z@t{@`abtgc>wCkPh5IaP|4H~FPW}32KL^39Gvmhg2W^KFvGYa*TKM{Gj(|^0OcP== zSN#@r8g*ExpZ)(Srl&7WwBcTqc`@w}J8%kjP?%Li>(AD>aStn~W!%4W3FaJ#h0Z#qrm-#r0b8w|Rf8NM6UN!SVt=k% z%_S&lI)aiKRP5H|k^c+rUrv+CLCduN7E6mexl=AF5qO|t z)fp2yL|S#)TwX06Y`mR^9Wk=*zP~lO|L1j*%SKy=1_42c#wWoCP6Zzoj3dT+Uyk@w$Di;|B4WmlQ{xVNQz!jHs{Sw7 e{@YEpoXWXlwFZ5BmwNJA0Sxb=^s00nqW%fuScSO& literal 2709 zcmbVOX*3(?8V+g@ON$z!BwE|hP7OsEp|xF1Ns3ZSZLQb^wS^)@Ewxq^EkaRSt+j`! zwPP7XC`whRB|;N>gII2Q@0|PVo-=pukLP>O^PTg(@B6&ZIq&(N+=3hM0!4uU0D#xX zP|u7RQ<>=J{DFBAwdxF*fy>v>+8+Sm7W@ttKz6PO^OD8i%s>ZFJt9V7k~6N_CfWeN z+f?o&Cw2e;C~u^veH+a}{fsewP8a9cB+x_VZ*AHL4RZYoY%>)7%xnJ3~Mh1CB;Tz zu2wl;&TdUcL|$8w7%Z5uwP1iF&(-w$hSTtp?aibOG9zr`Ah%Gu)`!%5ROESw;f8

~*R-iZxndwxe4X~6Dhb7oF z_h;kPks#gRzTdksjB!Y;JB!}J^zmM4;;>QuSY47w@jXePGXzIKXI8NqFrc-8iw|%9yBV;7g zJkdd#TiD<7DV}=b=^DG7%3%a00ybp*4jTpRTGCcueqdNtKBTao6LLmfSI)vw{;~+q zggJ(E;QOYpnCC2q!D*RvKXRGE>Z~TdRGx57EWUg>=GnNoe|OJ&zjuQ^5|7U4s`y=9 z5z7njbg;6j_~IJL@?uPbMPFaP%>{x067JaM$&HsbRd6|~77w~09E=v;mXxe6l+FT5oyW3RFr>XW0JO9W2U#laY2xPt^h7+?CbMN=G{Si1+H?M{;^*&q4NBCIp( z61Y0qYkKMLv#3F6%PRY18xAE^Q9`14UYI1Lh|l?Ip0EbYG+X}SBc5gAYdc6E&_%aO z_7RV?Rvb#}WZ#d}q8OVV{Zz5t&IwgD6FS{uzIpwF#xFi$fk{sPFoA?vxevH%Nbam> zWmZZOK&4;sTq+UyPM{^}g1D&NWVVN8bsmD4-#WD>G1U8OU)Ks~c{@^mM;r(u88U0A zaI#H5#8sDud)?qz>71(>Ez($bGdbFuZaZzcQ4<_6Hb07y`&16Icv>30Se{m@AGb2v z)&7mjefrLrZL0gw;pF(Xg{ihd$7iopR`F6efh;Gt*%|6l#!ZxkqLAlvv+}Rs>wtgR zJ4pXxA+)^P|IPdSjF}1HWXWQRY)w&vh7jF8_=wDjgrF1V=XuT=tWIay6Mb%}QQj>Q zVD2Q$R?p=R!R6N%$;&tDpmsWacLW>WvxRiy+hkGq!#s3M(MG}30@7U;xcql(zLc+gnH2gJ{I*UT+ zlS5DSCDRON`X+nXw&>?C*6-%;9BLs?t1rmqY~jE@7K47!AACyjJ`!4&EG!~gu~V

RO+D|b;c-dc#AF%dw^gMF&^^vTgUuM+;QGdBMk*W4*J9%j)j72ne)Hv#VFJ zJPOLkl5hnJ{e{il)@iU{kfK6lPS6J;4Z9ZOio%rkm2@5T$aOjU znVsDiYf_G{(4Tkj*W20SGi*l;uaE^Rz_PI7nBB7XKAVbmBCq@8w&WZijerX7p0Nj319+=P`I#$5h=5@{YSTH57Lh6_1pRV2& zVmMf~qBN6zsppf$J09%aXSnwCTwH^FUfiE8h*SM^ef(!~edM-HS1w3g>FQ z#~MY17sz)!>B%`$$X`3MzlXIcf-4~C+egFl9-Oip8A^1i-kJ^8!!2|q?5 zWSa8Tj1%cO$4ajM9d-ft>R39K~Ze0D8rAs<^9ZyT)w&4aJz;i)q$Z+vemTY zs$Lepuz@*V?W-AG(B&vEPfMg7QW$D2M~8TmFYIra+w^h>55hF^86%J?z|Eh(4l*{E zP!IxBr>CNr6Zxkr7RhqXf?Ht1NRF$>5>AxW$zfXgu84@zj|+FuyevuTf#zP z#ObLDbzk1I!H*x!3RVVeKpsbd#E@f0z`rW?S3M1>z-EIWoliW``xmw)=(*JP)kBe~ z&7;C&lO!$ml@Y9|$HrPsEKX3jtK#gh4IcC}yP^Npx=!qZyh7RO0WN%T=lP_|+ RpZSXf80o|Hs&yQr{t2LY8+8Bx diff --git a/img/onboarding/notification_white@2x.png b/img/onboarding/notification_white@2x.png index f1ee1212389ffc44fb0ce434df42245b9891ea1e..fd6a244f85cdc35f7172b9e4b36c50251a2d43f5 100644 GIT binary patch literal 5602 zcmc&&XHb({yM3b|A|g#ex(bNE0S*Gv2?EkPcmyGVBS`NALP979^&m(uQlu#;q5^sl zklwoxI?^G42~`3KNq{6b-XHhRoqJ}!Z{|Dq$DVhdy=V43&sy(#_Fg;Q%EFNSoWMB% z0N9O<^lbnDB+3}6XU{NZvOl@$Fg~n-Mh+nWz$@`{fQ)U#_ZX9)5F0~XpmJDfgAp)! z+%~@r0H0FWPJU+wfJ<;={o8iopq+)K07opM4Ih_zW8j=x);Te~w6^=4+w~STOvz7r zZjZR!GvUdjme!lY-6RunC@$cUrw?kvvEM8iC9GIERT!>-NnowSUKWi5v!>EESOKCJkWXt!#JD{(*Wmg}1%7KxxxnSV~Gr+^d(p082NJNHaRY8iJ3Y)<}!B&B2{ z506g)y_sVk2;t>6@_dupfqK~lDF5kF@*@KK#XF%FS%*j6kpyv=3;vlz;^f{)U+2B z-#7vJ?-65T&$BV(Vp?YPfNFN?EKRJah`Jpmx}^nJ7+#xenyZ)4&Kel_Bm%Gly=g;* zbHdcmU1f{W$=&WinY%{TeDmrgcaev3N*YIut!;ofJUjG0W;_EobQZ`@|9%HM<;C}G z2(Yj&84X9YQzS)~+y|JK?KV2s;bH1OdL*Z}h^#>VUv6V;?)Ht01cQ@_B0$-&#5r zSEy8DjR=XRF7`MQ?A8Cl3dROQ9Q9;Ne#Q<6X? z>+e3$kdOqn6zXNaeg{F(p~3K#trumcgAxw+rQ&4-=IbgG2l^&*l ze1rPel-p=08c@9>^qaI4H-2*0oKJnCQ&HYGQtVtBsnsId94eAkkNNBCFgU$hiPGaa zNcut!yz4~K0;^A7@1+95C+>|JRqfsJzf&+Pw%0C-X+%UaYBo~(GAZJU9EG&1U+oPI z{p*UJ-s%0SI?+CdKKC)%mGUFLlhv{ry~zorV=%Pbk^!T4qCKabOdhL z=-qlx)!{T%PpZe$vYw+6Pzdh{SNG;-L*|rBJNAgWVKmG!^ccJ@l~}vWKUqYp+m-9{ zVq?M7(tkJ+=nK}(5q{S$_bWRROAc{CQsL~koIl{*SdJtz%m*E_+0qBun+U{l#e-83 zSXe5Z zt(=A)zS^=Hg6&92L%`?aJcf%*hL3CqJ}xUGq}zS={-k>>HXagv%EbN(Fi-5O60$fQ z6x<%2yX~J`B^4c6g0OZdQy5q5)+^&c;;Dl>4+gP|1?sfVJF0{Ze;PFO^ZJ9lkcqv= z3(odw=qUWJ1UP;oNA=s~)L%Laa@bPDVGEeIb!kQ9@kGp{tc4Us+70jR)b7n29a{?B z@*<{o5fxX3B{VgZbl#i$Sg1vF9Vt1V7BY7qkI^ww|#^3Gkd-mmqy#k0IPcw&La8V}2Dl)%MB~>cal!v zQ4QUpXe`BQ!pXBxWRtXkxsW}8ZJ}9)403E3`_K8rn63}(_No)rlYmv+XSGCBgN~FE zm4BeI;9(qJ9%O#SMm@`C(d?~QPKIm;4dVd zdn6v^rK#2*mIb@Yvi3hDn?^n~#zXqt9SuDlxrTl2lET@YJ{YgK2@rQ+oJGir;gmlv zpR=qEmduxX!dGrfjo=7BKDLz=%PBE4?_e8>lTC7Dzfcp;Y+bP3WKzY#$8D8;wfH^VgO00g9ZSto zK_pUp^6DfNF649m#T|aihd2XmuPM}5W=ixS=BWne;ZQ4N0hMhapHr?PZL{Vj)YRPyGtCDHZL25qeStJI7R`zW+wfc_<@ zr<`0veRCA=5kDozM9JIX4MYLHf!KyCFrN5QkF1E9j6w7w<1?C2W@BaRAxv8^z);Rnn;?s~tLco5` z-H^s(RQO}>Ca)L*LbD;xKvY2i88uSm&i;8mYP!wt-HY}=8-nYv(VLwXwH_lYqnz(5&sQog@>dL;JB$!h}X`NEV4viv|{Me;IJ43!L)sVZ#pR2Go{hG&7*p8Y2HhcoFD($#QhG{mb+UKpg zc*Tv@*-b%4hc3)L$tUqW3}tu6PQRtY?Z-olC?jGHt)$)cE7EbJRio3zh!-G@Pph|= zY6ui<(Zvd-DJAiS-ws;09OL9_cbifo$ltmT;E}2?sH&Au&~+QSL=HMZ!^X*e=75TW zFAhfT@7tS(&r+0eN=KEi%^DwASUS`3qGq)yf9%_?@6YQRZB<@uaPYd3kQ@ig%`LO! zir7$sV#smJd^kPnIZ-AOEKjYe4l7OR$61ygYFfQ_uAUZ@?YMxCuWv4_YtlHS+TnT= z7DPTQcv9PnYdJra2i10Yuk=NXrHL=Q=U!*XgkH6(V3*|gCO&vJ0U~rLFu6_ffF?2# zsP774BYqFrap03x^dm|2&7Ph#y~UFNZ1a5dy8QhJp|Yn1%R1A}^o6qM>rb^HgJgq` zqm_nds%c=VRL?L%62h~8;$`pUSK<@Zv9*Q2?|&s+_GT{jIQrcr`^@|Y7I^1bizbDA zFEOM-q(fBHZLJ{E=ds$?RdLDN;j*(l8u_4{E82h=rzmj!DF?vQ#S+7cIo-yD2f4(O zfnRTH|821$q zA8mEaRZSg_ai0@m`h9r2G3u{eC0p5IQ`}ik-*Br}jQe+ae-LOy>l|&U^lg5ZB)AL4 zhP%G%st|7}r*Z{oFucwa$;STT{Qn|()5S9eRq4;Z5gH6huUN0&e&6vF)~yAt^tRmZ?W8M)(wHk_UUfWNyxjdZ8_EHHcE zX9$|Pg}EL~Ot2fxwPhX&7|L`5TQes03~qQ{PfAYvIRn0aj)&sef}FsP@ej8xb_vMz z{PMVMo_~3tU+MvL^q<+ z{qKJOwWwYhB~8)!obxT#Kmj%Z{Pwao7`Kheu2vQm#&e1kS8piOlA|jcm&LVb%<{^4 zMa&*giEye{a4;>acN0BVjl)c;P{P62RrW5Y?IV7 zf$?oeRDRh;pDy9(2Dv63 z9IwBS?cZGQl>ld^Ir-}VpCy|!DpWFIkbBwpoPq_4gw;ixLgBXo7x3TU7jHX*RlJp+ z(Sb`%&<=CY!Z+pf1>*CtTSYaK~4YEoG11!-<*qNAJ1#R98^4?dG;zqZdqje)6`#Jx)9{BI` z-(ie;C+K*pI3jcK?oXenr8J-Kwk*Iy~G^evfbcM%M>l7rAx5ylwv5|`~(9ww-^NB#dxlzc_&WOwfubADh zTA3J(Yi^!U_KB52a6Je#Qb@3w+m0bTt;W;7`aOvX@Yt~UsxYpCPe`G`9!gN$Ph0~Sh_ zm&_6vU=c?7frehPy&0xcF(PI+yV|K0O?ny9Y?Qmc2 zXK;Tm^(WU{cu>QDZ;H~bW4=sXI>t(JHq*xfWvbk`K7Xtf$ AIRF3v literal 6027 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 F{{qa|Q?LL4 diff --git a/img/onboarding/notification_white@3x.png b/img/onboarding/notification_white@3x.png index 4abe84597d93eb4bfd5b6efbc2fb08a6cdedcb97..31d60439c221f0a62c77f01595ea27c52f71a204 100644 GIT binary patch literal 8769 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 literal 9046 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 Preferenze" + profileSettings: "Potrai modificare questa scelta in ogni momento su Profilo > Preferenze" cta: shareData: "Condividi" dontShareData: "Non condividere dati" @@ -521,19 +521,19 @@ profile: contextualHelpContent: !include profile/profile_preferences_notifications.md header: Notifiche push title: Personalizza le notifiche - subtitle: Scegli come ricevere aggiornamenti sui messaggi e promemoria. + subtitle: Scegli se mostrare le anteprime e ricevere promemoria, come in questo esempio. titleExistingUser: Personalizza le notifiche subtitleExistingUser: Ora puoi vedere subito chi ti ha scritto o ricevere promemoria da messaggi importanti, come in questo esempio. reminders: - title: Consenti i promemoria + title: Consenti promemoria description: Su richiesta dell'ente, ricevi notifiche push in prossimità di scadenze o quando hai dei messaggi non letti preview: - title: Mostra un'anteprima - description: Includi nella notifica push il mittente e l’oggetto del messaggio - link: Più info + title: Mostra anteprime + description: Includi nella notifica push il mittente e l’oggetto del messaggio. + link: Scopri di più bottomSheet: - title: Mostra un'anteprima - content: Se l’opzione è attiva le notifiche push mostrano il mittente e l’oggetto dei messaggi, anche quando lo schermo è bloccato. Queste informazioni vengono trattate dal gestore del tuo sistema operativo e da app di terze parti eventualmente in esecuzione. + title: Mostra anteprime + content: "Una notifica push è un messaggio che ricevi sul tuo dispositivo anche quando non usi l'app. Se attivi questa opzione, riceverai notifiche push che ti mostreranno il mittente e l'oggetto del messaggio.\nQueste informazioni sono gestite dal sistema operativo del tuo dispositivo e dalle eventuali app di terze parti che stai utilizzando." cta: Ho capito! error: Si è verificato un errore con la tua richiesta userMetadata: diff --git a/ts/features/pushNotifications/components/NotificationPreviewSample.tsx b/ts/features/pushNotifications/components/NotificationPreviewSample.tsx index 35fca896d9f..a7be328b20f 100644 --- a/ts/features/pushNotifications/components/NotificationPreviewSample.tsx +++ b/ts/features/pushNotifications/components/NotificationPreviewSample.tsx @@ -5,18 +5,15 @@ import { Icon, HSpacer, IOSpacingScale, - IOVisualCostants + Label, + IOStyles } from "@pagopa/io-app-design-system"; -import { H4 } from "../../../components/core/typography/H4"; -import { H5 } from "../../../components/core/typography/H5"; -import customVariables from "../../../theme/variables"; import I18n from "../../../i18n"; import { TranslationKeys } from "../../../../locales/locales"; -import { IOStyles } from "../../../components/core/variables/IOStyles"; const notificationMarginVertical: IOSpacingScale = 4; const notificationPaddingVertical: IOSpacingScale = 8; -const notificationPaddingHorizontal: IOSpacingScale = 16; +const notificationPaddingHorizontal: IOSpacingScale = 24; const styles = StyleSheet.create({ notification: { @@ -25,10 +22,9 @@ const styles = StyleSheet.create({ backgroundColor: IOColors.white, borderWidth: 1, borderColor: IOColors.bluegreyLight, - borderRadius: customVariables.borderRadiusBase, - minHeight: 72, + borderRadius: 8, + minHeight: 90, marginVertical: notificationMarginVertical, - marginHorizontal: IOVisualCostants.appMarginDefault, paddingVertical: notificationPaddingVertical, paddingHorizontal: notificationPaddingHorizontal } @@ -77,15 +73,13 @@ export const NotificationPreviewSample = ({ return ( - + -

- {I18n.t(titleKey)} -

-
+ +
+ ); diff --git a/ts/features/pushNotifications/components/NotificationsPreferencesPreview.tsx b/ts/features/pushNotifications/components/NotificationsPreferencesPreview.tsx index 9890bcf567f..a4c97827aff 100644 --- a/ts/features/pushNotifications/components/NotificationsPreferencesPreview.tsx +++ b/ts/features/pushNotifications/components/NotificationsPreferencesPreview.tsx @@ -1,6 +1,5 @@ import React from "react"; import { StyleSheet, ImageBackground } from "react-native"; -import NotificationBlueBg from "../../../../img/onboarding/notification_blue.png"; import NotificationWhiteBg from "../../../../img/onboarding/notification_white.png"; import { NotificationPreviewSample } from "./NotificationPreviewSample"; @@ -14,16 +13,14 @@ const styles = StyleSheet.create({ type Props = { previewEnabled: boolean; remindersEnabled: boolean; - isFirstOnboarding: boolean; }; export const NotificationsPreferencesPreview = ({ previewEnabled, - remindersEnabled, - isFirstOnboarding + remindersEnabled }: Props) => ( diff --git a/ts/features/pushNotifications/hooks/usePreviewMoreInfo.tsx b/ts/features/pushNotifications/hooks/usePreviewMoreInfo.tsx index 7613b151801..0b4118f0771 100644 --- a/ts/features/pushNotifications/hooks/usePreviewMoreInfo.tsx +++ b/ts/features/pushNotifications/hooks/usePreviewMoreInfo.tsx @@ -1,11 +1,9 @@ import * as React from "react"; +import { Body } from "@pagopa/io-app-design-system"; import I18n from "../../../i18n"; -import { Body } from "../../../components/core/typography/Body"; -import FooterWithButtons from "../../../components/ui/FooterWithButtons"; -import { confirmButtonProps } from "../../../components/buttons/ButtonConfigurations"; import { IOBottomSheetModal, - useLegacyIOBottomSheetModal + useIOBottomSheetModal } from "../../../utils/hooks/bottomSheet"; /** @@ -14,19 +12,16 @@ import { * preferences views */ export const usePreviewMoreInfo = (): IOBottomSheetModal => { - const { present, bottomSheet, dismiss } = useLegacyIOBottomSheetModal( - - {I18n.t("profile.preferences.notifications.preview.bottomSheet.content")} - , - I18n.t("profile.preferences.notifications.preview.bottomSheet.title"), - 400, - { - dismiss(); - }, I18n.t("profile.preferences.notifications.preview.bottomSheet.cta"))} - /> - ); - - return { present, bottomSheet, dismiss }; + const { bottomSheet, dismiss, present } = useIOBottomSheetModal({ + component: ( + + {I18n.t( + "profile.preferences.notifications.preview.bottomSheet.content" + )} + + ), + snapPoint: [340], + title: I18n.t("profile.preferences.notifications.preview.bottomSheet.title") + }); + return { bottomSheet, dismiss, present }; }; diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx index 4f5840ff4d7..067bbe26187 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx @@ -1,40 +1,28 @@ import * as pot from "@pagopa/ts-commons/lib/pot"; -import { pipe } from "fp-ts/lib/function"; -import * as B from "fp-ts/lib/boolean"; -import React, { memo, useEffect, useState } from "react"; -import { SafeAreaView, ScrollView, StyleSheet, View } from "react-native"; -import { useSelector, useStore } from "react-redux"; +import React, { useEffect, useState } from "react"; +import { ScrollView, StyleSheet, View } from "react-native"; import { - IOColors, Divider, VSpacer, ContentWrapper, - IOVisualCostants + IOStyles, + ButtonSolid, + ListItemSwitch, + FeatureInfo, + useIOToast, + H1, + Body } from "@pagopa/io-app-design-system"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; import { PushNotificationsContentTypeEnum } from "../../../../definitions/backend/PushNotificationsContentType"; import { ReminderStatusEnum } from "../../../../definitions/backend/ReminderStatus"; -import { InfoBox } from "../../../components/box/InfoBox"; -import { IOBadge } from "../../../components/core/IOBadge"; -import { Body } from "../../../components/core/typography/Body"; -import { H1 } from "../../../components/core/typography/H1"; -import { H5 } from "../../../components/core/typography/H5"; -import { IOStyles } from "../../../components/core/variables/IOStyles"; -import { PreferencesListItem } from "../../../components/PreferencesListItem"; -import BaseScreenComponent, { - ContextualHelpPropsMarkdown -} from "../../../components/screens/BaseScreenComponent"; -import { BlockButtonProps } from "../../../components/ui/BlockButtons"; -import FooterWithButtons from "../../../components/ui/FooterWithButtons"; -import Switch from "../../../components/ui/Switch"; import I18n from "../../../i18n"; import { IOStackNavigationRouteProps } from "../../../navigation/params/AppParamsList"; import { OnboardingParamsList } from "../../../navigation/params/OnboardingParamsList"; import { profileUpsert } from "../../../store/actions/profile"; -import { useIODispatch } from "../../../store/hooks"; +import { useIODispatch, useIOSelector, useIOStore } from "../../../store/hooks"; import { profilePreferencesSelector } from "../../../store/reducers/profile"; -import customVariables from "../../../theme/variables"; import { usePreviewMoreInfo } from "../hooks/usePreviewMoreInfo"; -import { showToast } from "../../../utils/showToast"; import { useOnFirstRender } from "../../../utils/hooks/useOnFirstRender"; import { getFlowType } from "../../../utils/analytics"; import { @@ -44,25 +32,14 @@ import { trackNotificationsPreferencesReminderStatus } from "../../../screens/profile/analytics"; import { NotificationsPreferencesPreview } from "../components/NotificationsPreferencesPreview"; +import { useHeaderSecondLevel } from "../../../hooks/useHeaderSecondLevel"; const styles = StyleSheet.create({ - containerActions: { - backgroundColor: IOColors.white, - borderTopLeftRadius: 16, - borderTopRightRadius: 16, - paddingHorizontal: IOVisualCostants.appMarginDefault, - paddingBottom: customVariables.contentPadding - }, - containerActionsBlueBg: { - paddingTop: customVariables.contentPadding + scrollViewContainer: { + flexGrow: 1 } }); -const contextualHelpMarkdown: ContextualHelpPropsMarkdown = { - title: "onboarding.notifications.contextualHelpTitle", - body: "onboarding.notifications.contextualHelpContent" -}; - export type OnboardingNotificationsPreferencesScreenNavigationParams = { isFirstOnboarding: boolean; }; @@ -72,78 +49,15 @@ type Props = IOStackNavigationRouteProps< "ONBOARDING_NOTIFICATIONS_PREFERENCES" >; -const continueButtonProps = ( - isLoading: boolean, - onPress: () => void -): BlockButtonProps => ({ - block: true, - onPress, - title: I18n.t("onboarding.notifications.continue"), - isLoading -}); - -const loadingButtonProps = (): BlockButtonProps => ({ - block: true, - onPress: undefined, - title: "", - disabled: true, - style: { backgroundColor: IOColors.greyLight, width: "100%" }, - isLoading: true, - iconColor: "bluegreyDark" -}); - -const CustomGoBack = memo( - ({ isFirstOnboarding }: { isFirstOnboarding: boolean }) => - pipe( - isFirstOnboarding, - B.fold( - () => ( - - ), - () => null - ) - ) -); - -const Header = memo(({ isFirstOnboarding }: { isFirstOnboarding: boolean }) => { - const { title, subtitle } = pipe( - isFirstOnboarding, - B.fold( - () => ({ - title: I18n.t("profile.preferences.notifications.titleExistingUser"), - subtitle: I18n.t( - "profile.preferences.notifications.subtitleExistingUser" - ) - }), - () => ({ - title: I18n.t("profile.preferences.notifications.title"), - subtitle: I18n.t("profile.preferences.notifications.subtitle") - }) - ) - ); - - return ( - -

{title}

- - {subtitle} - - -
- ); -}); - export const OnboardingNotificationsPreferencesScreen = (props: Props) => { const dispatch = useIODispatch(); + const safeAreaInsets = useSafeAreaInsets(); + const toast = useIOToast(); const [previewEnabled, setPreviewEnabled] = useState(true); const [remindersEnabled, setRemindersEnabled] = useState(true); - const preferences = useSelector(profilePreferencesSelector); + const preferences = useIOSelector(profilePreferencesSelector); const { present, bottomSheet } = usePreviewMoreInfo(); const isError = pot.isError(preferences); @@ -171,11 +85,11 @@ export const OnboardingNotificationsPreferencesScreen = (props: Props) => { useEffect(() => { if (isError && !isUpdating) { - showToast(I18n.t("profile.preferences.notifications.error")); + toast.error(I18n.t("profile.preferences.notifications.error")); } - }, [isError, isUpdating]); + }, [isError, isUpdating, toast]); - const store = useStore(); + const store = useIOStore(); const upsertPreferences = () => { void trackNotificationPreferenceConfiguration( @@ -196,110 +110,74 @@ export const OnboardingNotificationsPreferencesScreen = (props: Props) => { ); }; + useHeaderSecondLevel({ + canGoBack: false, + supportRequest: true, + title: "" + }); + return ( - } - headerTitle={ - isFirstOnboarding - ? I18n.t("onboarding.notifications.headerTitle") - : undefined - } - contextualHelpMarkdown={contextualHelpMarkdown} - primary={!isFirstOnboarding} - > - - -
+ <> + + +

{I18n.t("profile.preferences.notifications.title")}

+ + {I18n.t("profile.preferences.notifications.subtitle")} + - - {isFirstOnboarding && } - - } - /> - - - } - /> - - - -
- {I18n.t( - "profile.main.privacy.shareData.screen.profileSettings" - )} -
-
-
- {/* This extra View has been added to avoid displaying the IOColors.blue - background when the ScrollView bounces */} - + -
- - {bottomSheet} - + + + + + + + + - - + + {bottomSheet} + ); }; diff --git a/ts/navigation/OnboardingNavigator.tsx b/ts/navigation/OnboardingNavigator.tsx index 7400561c721..a4ad407b431 100644 --- a/ts/navigation/OnboardingNavigator.tsx +++ b/ts/navigation/OnboardingNavigator.tsx @@ -81,12 +81,10 @@ const OnboardingNavigator = () => ( component={OnboardingCompletedScreen} /> From 5ec21f916788353b30d9ccde405736765aca1308 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Wed, 1 May 2024 23:40:48 +0200 Subject: [PATCH 03/17] Removed deprecated test --- ...ingNotificationsPreferencesScreen.test.tsx | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx index b7952ab7293..5ca20d977d1 100644 --- a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx +++ b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx @@ -12,26 +12,6 @@ import mockedProfile from "../../../../__mocks__/initializedProfile"; import { OnboardingNotificationsPreferencesScreen } from "../OnboardingNotificationsPreferencesScreen"; describe("OnboardingNotificationsPreferencesScreen", () => { - describe("given an onboarded user", () => { - it("then the title should match the 'profile.preferences.notifications.titleExistingUser' key and the subtitle should match 'profile.preferences.notifications.subtitleExistingUser'", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore(globalState, false); - expect(screen).not.toBeNull(); - - const headerH1Title = screen.component.queryByText( - I18n.t("profile.preferences.notifications.titleExistingUser") - ); - expect(headerH1Title).not.toBeNull(); - - const bodySubtitle = screen.component.queryByText( - I18n.t("profile.preferences.notifications.subtitleExistingUser") - ); - expect(bodySubtitle).not.toBeNull(); - }); - }); describe("given an user that is doing the onboarding for the first time", () => { it("then the title should match the 'profile.preferences.notifications.title' key and the subtitle should match 'profile.preferences.notifications.subtitle'", () => { From 91f88aa526b88304df97170efd6ab3681108a2cd Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Thu, 2 May 2024 09:30:00 +0200 Subject: [PATCH 04/17] Label replaced with H6 --- .../components/NotificationPreviewSample.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ts/features/pushNotifications/components/NotificationPreviewSample.tsx b/ts/features/pushNotifications/components/NotificationPreviewSample.tsx index a7be328b20f..13d53bf3506 100644 --- a/ts/features/pushNotifications/components/NotificationPreviewSample.tsx +++ b/ts/features/pushNotifications/components/NotificationPreviewSample.tsx @@ -6,7 +6,8 @@ import { HSpacer, IOSpacingScale, Label, - IOStyles + IOStyles, + H6 } from "@pagopa/io-app-design-system"; import I18n from "../../../i18n"; import { TranslationKeys } from "../../../../locales/locales"; @@ -76,7 +77,7 @@ export const NotificationPreviewSample = ({ - +
{I18n.t(titleKey)}
From 71ba2ef21a0b7d17c6a2743b948caf15c63cf528 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Thu, 2 May 2024 09:33:04 +0200 Subject: [PATCH 05/17] Prettify --- .../__tests__/OnboardingNotificationsPreferencesScreen.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx index 5ca20d977d1..931309d5b16 100644 --- a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx +++ b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx @@ -12,7 +12,6 @@ import mockedProfile from "../../../../__mocks__/initializedProfile"; import { OnboardingNotificationsPreferencesScreen } from "../OnboardingNotificationsPreferencesScreen"; describe("OnboardingNotificationsPreferencesScreen", () => { - describe("given an user that is doing the onboarding for the first time", () => { it("then the title should match the 'profile.preferences.notifications.title' key and the subtitle should match 'profile.preferences.notifications.subtitle'", () => { const globalState = appReducer( From 70bcc672127c904ab87f99d0d769941c8e9da75a Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Thu, 2 May 2024 09:50:00 +0200 Subject: [PATCH 06/17] testId --- package.json | 2 +- .../screens/OnboardingNotificationsPreferencesScreen.tsx | 2 ++ yarn.lock | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4a5579ed7ea..af36ff022ac 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "dependencies": { "@babel/plugin-transform-regenerator": "^7.18.6", "@gorhom/bottom-sheet": "^4.1.5", - "@pagopa/io-app-design-system": "1.36.1", + "@pagopa/io-app-design-system": "1.36.3", "@pagopa/io-pagopa-commons": "^3.1.0", "@pagopa/io-react-native-crypto": "^0.3.0", "@pagopa/io-react-native-http-client": "^0.1.3", diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx index 067bbe26187..56acaa68086 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx @@ -141,6 +141,7 @@ export const OnboardingNotificationsPreferencesScreen = (props: Props) => { value={previewEnabled} disabled={isUpdating} onSwitchValueChange={setPreviewEnabled} + testID={"previewsPreferenceSwitch"} /> { value={remindersEnabled} disabled={isUpdating} onSwitchValueChange={setRemindersEnabled} + testID={"remindersPreferenceSwitch"} /> = 8" -"@pagopa/io-app-design-system@1.36.1": - version "1.36.1" - resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.1.tgz#a301bf3e06a77fdb82a45a4283ae9919747e71ab" - integrity sha512-ZxdDfpeXN6bsFHfSpJsIo7I8mGhzuzIPKywCHTov3Ssaxe+F2zCZm4sw0lrTdao4LTb4am98bJg8Gxf9rAkNIg== +"@pagopa/io-app-design-system@1.36.3": + version "1.36.3" + resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.3.tgz#4ef7788960456f6048d76ccb60ec1da2003ca55d" + integrity sha512-iwPxxbrbzvELcmHKJUkGQnEcNHTMVptzsDciu29txEvbxWtHG9uFJmUkMPq6Va+oAqkFd8r7mM3iRx0E+S8Rew== dependencies: "@pagopa/ts-commons" "^12.0.0" "@testing-library/jest-native" "^5.4.2" From 2ba94561f072a93a9e607216fe7b004b9d3ee683 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Thu, 2 May 2024 10:49:29 +0200 Subject: [PATCH 07/17] Updated DS --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index af36ff022ac..d2369a4d293 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "dependencies": { "@babel/plugin-transform-regenerator": "^7.18.6", "@gorhom/bottom-sheet": "^4.1.5", - "@pagopa/io-app-design-system": "1.36.3", + "@pagopa/io-app-design-system": "1.36.6", "@pagopa/io-pagopa-commons": "^3.1.0", "@pagopa/io-react-native-crypto": "^0.3.0", "@pagopa/io-react-native-http-client": "^0.1.3", diff --git a/yarn.lock b/yarn.lock index 3d406c7ffe7..b5cb90cb20e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3279,10 +3279,10 @@ dependencies: "@types/node" ">= 8" -"@pagopa/io-app-design-system@1.36.3": - version "1.36.3" - resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.3.tgz#4ef7788960456f6048d76ccb60ec1da2003ca55d" - integrity sha512-iwPxxbrbzvELcmHKJUkGQnEcNHTMVptzsDciu29txEvbxWtHG9uFJmUkMPq6Va+oAqkFd8r7mM3iRx0E+S8Rew== +"@pagopa/io-app-design-system@1.36.6": + version "1.36.6" + resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.6.tgz#2434b56d2e5d070fb816ed4a6dd34e6e5d150659" + integrity sha512-eoIzoHVPTkEoWfkEPbBvSY5OsYyxna73nq5xs6NiAYHS4AWjCSI/zvo6AQpvf/0kEZFRae7ZYRq/RQh6+gX3wg== dependencies: "@pagopa/ts-commons" "^12.0.0" "@testing-library/jest-native" "^5.4.2" From 00abd7da5210eb6d3e115bba038e00be7bd4d186 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Thu, 2 May 2024 13:16:02 +0200 Subject: [PATCH 08/17] switchTestId on --- .../screens/OnboardingNotificationsPreferencesScreen.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx index 56acaa68086..152c0931807 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx @@ -141,7 +141,7 @@ export const OnboardingNotificationsPreferencesScreen = (props: Props) => { value={previewEnabled} disabled={isUpdating} onSwitchValueChange={setPreviewEnabled} - testID={"previewsPreferenceSwitch"} + switchTestID={"previewsPreferenceSwitch"} /> { value={remindersEnabled} disabled={isUpdating} onSwitchValueChange={setRemindersEnabled} - testID={"remindersPreferenceSwitch"} + switchTestID={"remindersPreferenceSwitch"} /> Date: Fri, 3 May 2024 09:51:20 +0200 Subject: [PATCH 09/17] Latest DS --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d2369a4d293..6d6707bf10e 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "dependencies": { "@babel/plugin-transform-regenerator": "^7.18.6", "@gorhom/bottom-sheet": "^4.1.5", - "@pagopa/io-app-design-system": "1.36.6", + "@pagopa/io-app-design-system": "1.36.8", "@pagopa/io-pagopa-commons": "^3.1.0", "@pagopa/io-react-native-crypto": "^0.3.0", "@pagopa/io-react-native-http-client": "^0.1.3", diff --git a/yarn.lock b/yarn.lock index b5cb90cb20e..1d6497456a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3279,10 +3279,10 @@ dependencies: "@types/node" ">= 8" -"@pagopa/io-app-design-system@1.36.6": - version "1.36.6" - resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.6.tgz#2434b56d2e5d070fb816ed4a6dd34e6e5d150659" - integrity sha512-eoIzoHVPTkEoWfkEPbBvSY5OsYyxna73nq5xs6NiAYHS4AWjCSI/zvo6AQpvf/0kEZFRae7ZYRq/RQh6+gX3wg== +"@pagopa/io-app-design-system@1.36.8": + version "1.36.8" + resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.8.tgz#71238774ebcb8820478b5c3656e298309862db80" + integrity sha512-C1AaVmzEoBRvQJCSrfd4Rqy3Sw/r5nZkVRiELbzzOmtJhXV5/qJ7z9RHmU6xswnculyvSRYDGTEDGAmHYpcwCQ== dependencies: "@pagopa/ts-commons" "^12.0.0" "@testing-library/jest-native" "^5.4.2" From f0c147f43c9907fa2f2c22c34fb30d0d5492cfba Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Fri, 3 May 2024 15:16:33 +0200 Subject: [PATCH 10/17] WiP --- .../checkNotificationsPermissionsSaga.ts | 43 --- .../checkNotificationsPreferencesSaga.ts | 38 ++- ...boardingNotificationsInfoScreenConsent.tsx | 306 +++++++++--------- ...boardingNotificationsPreferencesScreen.tsx | 3 + ts/navigation/OnboardingNavigator.tsx | 16 +- ts/store/reducers/profile.ts | 18 ++ 6 files changed, 210 insertions(+), 214 deletions(-) delete mode 100644 ts/features/pushNotifications/sagas/checkNotificationsPermissionsSaga.ts diff --git a/ts/features/pushNotifications/sagas/checkNotificationsPermissionsSaga.ts b/ts/features/pushNotifications/sagas/checkNotificationsPermissionsSaga.ts deleted file mode 100644 index e94f4337c74..00000000000 --- a/ts/features/pushNotifications/sagas/checkNotificationsPermissionsSaga.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { CommonActions, StackActions } from "@react-navigation/native"; -import { call, take } from "typed-redux-saga/macro"; -import { ActionType } from "typesafe-actions"; -import NavigationService from "../../../navigation/NavigationService"; -import ROUTES from "../../../navigation/routes"; -import { SagaCallReturnType } from "../../../types/utils"; -import { - checkNotificationPermissions, - requestNotificationPermissions -} from "../utils"; -import { notificationsInfoScreenConsent } from "../store/actions/notifications"; - -export function* checkNotificationsPermissionsSaga() { - const authorizationStatus: SagaCallReturnType< - typeof checkNotificationPermissions - > = yield* call(checkNotificationPermissions); - - if (!authorizationStatus) { - const permissionStatus: SagaCallReturnType< - typeof requestNotificationPermissions - > = yield* call(requestNotificationPermissions); - - if (permissionStatus) { - return; - } - - yield* call( - NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT - }) - ); - - yield* take>( - notificationsInfoScreenConsent - ); - - yield* call( - NavigationService.dispatchNavigationAction, - StackActions.popToTop() - ); - } -} diff --git a/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts index dd19ba224f8..44cf9c69135 100644 --- a/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts +++ b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts @@ -7,12 +7,13 @@ import NavigationService from "../../../navigation/NavigationService"; import ROUTES from "../../../navigation/routes"; import { profileUpsert } from "../../../store/actions/profile"; import { isProfileFirstOnBoarding } from "../../../store/reducers/profile"; -import { requestNotificationPermissions } from "../utils"; +import { checkNotificationPermissions, requestNotificationPermissions } from "../utils"; import { trackNotificationsOptInPreviewStatus, trackNotificationsOptInReminderStatus } from "../analytics"; -import { checkNotificationsPermissionsSaga } from "./checkNotificationsPermissionsSaga"; +import { SagaCallReturnType } from "../../../types/utils"; +import { notificationsInfoScreenConsent } from "../store/actions/notifications"; export function* checkNotificationsPreferencesSaga( userProfile: InitializedProfile @@ -65,11 +66,38 @@ export function* checkNotificationsPreferencesSaga( } } + // check if the user has given system notification permissions + const authorizationStatus: SagaCallReturnType< + typeof checkNotificationPermissions + > = yield* call(checkNotificationPermissions); + + if (!authorizationStatus) { + const permissionStatus: SagaCallReturnType< + typeof requestNotificationPermissions + > = yield* call(requestNotificationPermissions); + + if (permissionStatus) { + yield* call( + NavigationService.dispatchNavigationAction, + StackActions.popToTop() + ); + return; + } + + yield* call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + }) + ); + + yield* take>( + notificationsInfoScreenConsent + ); + } + yield* call( NavigationService.dispatchNavigationAction, StackActions.popToTop() ); - - // check if the user has given system notification permissions - yield* call(checkNotificationsPermissionsSaga); } diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx index 2f866020596..b6cb7a1a8fc 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx @@ -1,34 +1,32 @@ -import React, { useEffect } from "react"; +import React, { useCallback, useEffect, useMemo } from "react"; import { AppState, FlatList, - SafeAreaView, View, Platform, ListRenderItemInfo } from "react-native"; -import { useSelector } from "react-redux"; -import * as pot from "@pagopa/ts-commons/lib/pot"; import { + Body, Divider, + FooterWithButtons, + H2, + H6, + IOStyles, IOVisualCostants, + IconButton, ListItemInfo, VSpacer } from "@pagopa/io-app-design-system"; -import BaseScreenComponent, { - ContextualHelpPropsMarkdown -} from "../../../components/screens/BaseScreenComponent"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; import I18n from "../../../i18n"; -import { IOStyles } from "../../../components/core/variables/IOStyles"; -import { BlockButtonProps } from "../../../components/ui/BlockButtons"; -import { FooterStackButton } from "../../../components/buttons/FooterStackButtons"; import { openAppSettings } from "../../../utils/appSettings"; -import { useIODispatch } from "../../../store/hooks"; +import { useIODispatch, useIOSelector } from "../../../store/hooks"; import { checkNotificationPermissions } from "../utils"; -import { profilePreferencesSelector } from "../../../store/reducers/profile"; -import { H2 } from "../../../components/core/typography/H2"; -import { H1 } from "../../../components/core/typography/H1"; -import { Body } from "../../../components/core/typography/Body"; +import { + pushNotificationPreviewEnabledSelector, + pushNotificationRemindersEnabledSelector +} from "../../../store/reducers/profile"; import { notificationsInfoScreenConsent } from "../store/actions/notifications"; import { trackNotificationsOptInOpenSettings, @@ -36,108 +34,88 @@ import { trackNotificationsOptInSkipSystemPermissions } from "../analytics"; -const contextualHelpMarkdown: ContextualHelpPropsMarkdown = { - title: "onboarding.infoConsent.contextualHelpTitle", - body: "onboarding.infoConsent.contextualHelpContent" -}; - -const settingsButtonProps = ( - isLoading: boolean, - onPress: () => void -): BlockButtonProps => ({ - block: true, - onPress, - title: I18n.t("onboarding.infoConsent.openSettings"), - isLoading, - primary: true -}); - -const continueButtonProps = ( - isLoading: boolean, - onPress: () => void -): BlockButtonProps => ({ - block: true, - onPress, - title: I18n.t("onboarding.infoConsent.continue"), - isLoading, - bordered: true, - testID: "continue-btn" -}); - -const instructions = Platform.select>({ - ios: [ - { - icon: "systemSettingsiOS", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.ios.step1"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.ios.step1" - ) - }, - { - icon: "systemNotificationsInstructions", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.ios.step2"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.ios.step2" - ) - }, - { - icon: "systemToggleInstructions", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.ios.step3"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.ios.step3" - ) - } - ], - android: [ - { - icon: "systemSettingsAndroid", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.android.step1"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.android.step1" - ) - }, - { - icon: "systemAppsAndroid", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.android.step2"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.android.step2" - ) - }, - { - icon: "productIOAppBlueBg", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.android.step3"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.android.step3" - ) - }, - { - icon: "systemNotificationsInstructions", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.android.step4"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.android.step4" - ) - }, - { - icon: "systemToggleInstructions", - label: I18n.t("onboarding.infoConsent.instructions.label"), - value: I18n.t("onboarding.infoConsent.instructions.android.step5"), - accessibilityLabel: I18n.t( - "onboarding.infoConsent.instructions.android.step5" - ) - } - ] -}); - export const OnboardingNotificationsInfoScreenConsent = () => { const dispatch = useIODispatch(); - const optInPreferencesPot = useSelector(profilePreferencesSelector); + const safeAreaInsets = useSafeAreaInsets(); + const remindersEnabled = useIOSelector( + pushNotificationRemindersEnabledSelector + ); + const previewEnabled = useIOSelector(pushNotificationPreviewEnabledSelector); + + const instructions = useMemo( + () => + Platform.select>({ + ios: [ + { + icon: "systemSettingsiOS", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.ios.step1"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.ios.step1" + ) + }, + { + icon: "systemNotificationsInstructions", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.ios.step2"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.ios.step2" + ) + }, + { + icon: "systemToggleInstructions", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.ios.step3"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.ios.step3" + ) + } + ], + android: [ + { + icon: "systemSettingsAndroid", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.android.step1"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.android.step1" + ) + }, + { + icon: "systemAppsAndroid", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.android.step2"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.android.step2" + ) + }, + { + icon: "productIOAppBlueBg", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.android.step3"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.android.step3" + ) + }, + { + icon: "systemNotificationsInstructions", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.android.step4"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.android.step4" + ) + }, + { + icon: "systemToggleInstructions", + label: I18n.t("onboarding.infoConsent.instructions.label"), + value: I18n.t("onboarding.infoConsent.instructions.android.step5"), + accessibilityLabel: I18n.t( + "onboarding.infoConsent.instructions.android.step5" + ) + } + ] + }), + [] + ); useEffect(() => { const subscription = AppState.addEventListener( @@ -158,74 +136,78 @@ export const OnboardingNotificationsInfoScreenConsent = () => { }; }, [dispatch]); - const goNext = () => { + const goNext = useCallback(() => { // When this code executes, we know for sure that system notifications permissions are disabled, // otherwise the component would either have been skipped by the saga or it would have automatically // handled the given permission using the AppState listener (registered on the useEffect) trackNotificationsOptInSkipSystemPermissions(); - if (pot.isSome(optInPreferencesPot)) { - const optInPreferences = optInPreferencesPot.value; - if (optInPreferences.preview || optInPreferences.reminder) { - trackNotificationsOptInReminderOnPermissionsOff(); - } + if (remindersEnabled || previewEnabled) { + trackNotificationsOptInReminderOnPermissionsOff(); } dispatch(notificationsInfoScreenConsent()); - }; + }, [dispatch, previewEnabled, remindersEnabled]); - const openSettings = () => { + const openSettings = useCallback(() => { trackNotificationsOptInOpenSettings(); openAppSettings(); - }; + }, []); - const headerComponent = ( + const ListHeader = ( +

{I18n.t("onboarding.infoConsent.title")}

-

- {I18n.t("onboarding.infoConsent.title")} -

{I18n.t("onboarding.infoConsent.subTitle")} - -

+ +
{I18n.t("onboarding.infoConsent.instructions.title")} -
+

+
); - const renderItem = ({ item, index }: ListRenderItemInfo) => ( - - ); - return ( - } - > - - + + + + + + ) => ( + + )} + contentContainerStyle={{ + marginHorizontal: IOVisualCostants.appMarginDefault + }} + ItemSeparatorComponent={() => } + ListHeaderComponent={ListHeader} + /> + + } - ListHeaderComponent={headerComponent} - /> - - - +
+ ); }; diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx index 152c0931807..bb9a2eb35bb 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx @@ -33,6 +33,7 @@ import { } from "../../../screens/profile/analytics"; import { NotificationsPreferencesPreview } from "../components/NotificationsPreferencesPreview"; import { useHeaderSecondLevel } from "../../../hooks/useHeaderSecondLevel"; +import { useHardwareBackButton } from "../../../hooks/useHardwareBackButton"; const styles = StyleSheet.create({ scrollViewContainer: { @@ -110,6 +111,8 @@ export const OnboardingNotificationsPreferencesScreen = (props: Props) => { ); }; + useHardwareBackButton(() => true); + useHeaderSecondLevel({ canGoBack: false, supportRequest: true, diff --git a/ts/navigation/OnboardingNavigator.tsx b/ts/navigation/OnboardingNavigator.tsx index 110e23e2fd7..69696235cd2 100644 --- a/ts/navigation/OnboardingNavigator.tsx +++ b/ts/navigation/OnboardingNavigator.tsx @@ -84,10 +84,18 @@ const OnboardingNavigator = () => ( name={ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES} component={OnboardingNotificationsPreferencesScreen} /> - + + + ); diff --git a/ts/store/reducers/profile.ts b/ts/store/reducers/profile.ts index c113f7c627d..567c93f2c7e 100644 --- a/ts/store/reducers/profile.ts +++ b/ts/store/reducers/profile.ts @@ -199,6 +199,24 @@ export const profilePreferencesSelector = createSelector( })) ); +export const pushNotificationRemindersEnabledSelector = (state: GlobalState) => +pipe( + state.profile, + pot.toOption, + O.chainNullableK(profile => profile.reminder_status), + O.map(reminderStatus => reminderStatus === ReminderStatusEnum.ENABLED), + O.getOrElse(() => false) +); + +export const pushNotificationPreviewEnabledSelector = (state: GlobalState) => +pipe( + state.profile, + pot.toOption, + O.chainNullableK(profile => profile.push_notifications_content_type), + O.map(pushNotificationContentType => pushNotificationContentType === PushNotificationsContentTypeEnum.FULL), + O.getOrElse(() => false) +); + // return the profile notification settings actual state or undefined if ProfileState pot is in an Error state export const profileNotificationSettingsSelector = createSelector( profileSelector, From 127098bfc1b7a972a7194927c570539fb298d8d6 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Fri, 3 May 2024 17:30:31 +0200 Subject: [PATCH 11/17] WiP --- .env.local | 2 - .env.production | 2 - ts/config.ts | 3 - ...checkNotificationsPermissionsSaga.test.tsx | 82 ------- ...checkNotificationsPreferencesSaga.test.tsx | 205 ++++++++++++++++++ .../checkNotificationsPreferencesSaga.ts | 24 +- ...boardingNotificationsInfoScreenConsent.tsx | 71 +++--- .../utils/configurePushNotification.ts | 8 +- ts/navigation/ProfileNavigator.tsx | 11 +- ...checkNotificationsPermissionsSaga.test.tsx | 82 ------- ts/screens/profile/PreferencesScreen.tsx | 2 - ts/store/reducers/profile.ts | 13 +- 12 files changed, 267 insertions(+), 238 deletions(-) delete mode 100644 ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx create mode 100644 ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx delete mode 100644 ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx diff --git a/.env.local b/.env.local index 14dab675003..b748bf88d3b 100644 --- a/.env.local +++ b/.env.local @@ -59,8 +59,6 @@ PREMIUM_MESSAGES_OPT_IN_ENABLED=YES CDC_ENABLED = YES # Scan additional barcodes (E.g. Data Matrix) in the payment section SCAN_ADDITIONAL_BARCODES_ENABLED = YES -# Opt-in for reminder push notifications -REMINDERS_OPT_IN_ENABLED=YES # FCI (Firma con IO) feature FCI_ENABLED=YES # IDPay diff --git a/.env.production b/.env.production index a17b711a25b..98049503f0d 100644 --- a/.env.production +++ b/.env.production @@ -59,8 +59,6 @@ PREMIUM_MESSAGES_OPT_IN_ENABLED=YES CDC_ENABLED = YES # Scan additional barcodes (E.g. Data Matrix) in the payment section SCAN_ADDITIONAL_BARCODES_ENABLED = YES -# Opt-in for reminder push notifications -REMINDERS_OPT_IN_ENABLED=YES # FCI (Firma con IO) feature FCI_ENABLED=YES # IDPay diff --git a/ts/config.ts b/ts/config.ts index e764daacaa9..e6164c3f9ed 100644 --- a/ts/config.ts +++ b/ts/config.ts @@ -109,9 +109,6 @@ export const cieLoginFlowWithDevServerEnabled = // Native Login Feature Flag export const nativeLoginEnabled = Config.NATIVE_LOGIN_ENABLED === "YES"; -// Opt-in for reminder push notifications -export const remindersOptInEnabled = Config.REMINDERS_OPT_IN_ENABLED === "YES"; - export const isNewServicesEnabled = Config.NEW_SERVICES_ENABLED === "YES"; export const fetchTimeout = pipe( diff --git a/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx b/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx deleted file mode 100644 index cb703740c2e..00000000000 --- a/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPermissionsSaga.test.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { CommonActions, StackActions } from "@react-navigation/native"; -import { testSaga } from "redux-saga-test-plan"; -import NavigationService from "../../../../navigation/NavigationService"; -import ROUTES from "../../../../navigation/routes"; -import { - checkNotificationPermissions, - requestNotificationPermissions -} from "../../utils"; -import { checkNotificationsPermissionsSaga } from "../checkNotificationsPermissionsSaga"; -import { notificationsInfoScreenConsent } from "../../store/actions/notifications"; - -describe("checkNotificationsPermissionsSaga", () => { - it("upon saga startup, it should ask for push notifications permission", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions); - }); - - it("if the push notifications permission was given, the saga will terminate ", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(true) - .isDone(); - }); - - it("if the push notifications permission was not given and is first onboarding, the saga will request push notification permissions", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions); - }); - - it("if the saga asks for push permissions and the user give them, the saga will terminate", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions) - .next(true) - .isDone(); - }); - - it("if the saga asks for push permissions and the user does not give them, the saga navigates to the Info Screen and waits for the notificationsInfoScreenConsent action", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions) - .next(false) - .call( - NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT - }) - ) - .next() - .take(notificationsInfoScreenConsent); - }); - - it("if the saga is waiting for the notificationsInfoScreenConsent action and the latter is received, the saga terminates", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions) - .next(false) - .call( - NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT - }) - ) - .next() - .take(notificationsInfoScreenConsent) - .next() - .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) - .next() - .isDone(); - }); -}); diff --git a/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx b/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx new file mode 100644 index 00000000000..433e02f9e7c --- /dev/null +++ b/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx @@ -0,0 +1,205 @@ +import { CommonActions, StackActions } from "@react-navigation/native"; +import { testSaga } from "redux-saga-test-plan"; +import NavigationService from "../../../../navigation/NavigationService"; +import ROUTES from "../../../../navigation/routes"; +import { + checkNotificationPermissions, + requestNotificationPermissions +} from "../../utils"; +import { notificationsInfoScreenConsent } from "../../store/actions/notifications"; +import { checkNotificationsPreferencesSaga } from "../checkNotificationsPreferencesSaga"; +import { InitializedProfile } from "../../../../../definitions/backend/InitializedProfile"; +import { ServicesPreferencesModeEnum } from "../../../../../definitions/backend/ServicesPreferencesMode"; +import { profileUpsert } from "../../../../store/actions/profile"; +import { PushNotificationsContentTypeEnum } from "../../../../../definitions/backend/PushNotificationsContentType"; +import { ReminderStatusEnum } from "../../../../../definitions/backend/ReminderStatus"; + +const userProfile = { + service_preferences_settings: { + mode: ServicesPreferencesModeEnum.LEGACY + } +} as InitializedProfile; + +describe("checkNotificationsPreferencesSaga", () => { + it("upon saga startup, it should ask for push notifications permission", () => { + testSaga(checkNotificationsPreferencesSaga, userProfile) + .next() + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding: true } + }) + ) + .next() + .take(profileUpsert.success) + .next({ + payload: { + newValue: { + push_notifications_content_type: + PushNotificationsContentTypeEnum.FULL, + reminder_status: ReminderStatusEnum.ENABLED + } + } + }) + .call(checkNotificationPermissions); + }); + + it("if the push notifications permission was given, the saga will terminate ", () => { + testSaga(checkNotificationsPreferencesSaga, userProfile) + .next() + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding: true } + }) + ) + .next() + .take(profileUpsert.success) + .next({ + payload: { + newValue: { + push_notifications_content_type: + PushNotificationsContentTypeEnum.FULL, + reminder_status: ReminderStatusEnum.ENABLED + } + } + }) + .call(checkNotificationPermissions) + .next(true) + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); + }); + + it("if the push notifications permission was not given and is first onboarding, the saga will request push notification permissions", () => { + testSaga(checkNotificationsPreferencesSaga, userProfile) + .next() + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding: true } + }) + ) + .next() + .take(profileUpsert.success) + .next({ + payload: { + newValue: { + push_notifications_content_type: + PushNotificationsContentTypeEnum.FULL, + reminder_status: ReminderStatusEnum.ENABLED + } + } + }) + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions); + }); + + it("if the saga asks for push permissions and the user give them, the saga will terminate", () => { + testSaga(checkNotificationsPreferencesSaga, userProfile) + .next() + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding: true } + }) + ) + .next() + .take(profileUpsert.success) + .next({ + payload: { + newValue: { + push_notifications_content_type: + PushNotificationsContentTypeEnum.FULL, + reminder_status: ReminderStatusEnum.ENABLED + } + } + }) + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(true) + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); + }); + + it("if the saga asks for push permissions and the user does not give them, the saga navigates to the Info Screen and waits for the notificationsInfoScreenConsent action", () => { + testSaga(checkNotificationsPreferencesSaga, userProfile) + .next() + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding: true } + }) + ) + .next() + .take(profileUpsert.success) + .next({ + payload: { + newValue: { + push_notifications_content_type: + PushNotificationsContentTypeEnum.FULL, + reminder_status: ReminderStatusEnum.ENABLED + } + } + }) + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(false) + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + }) + ) + .next() + .take(notificationsInfoScreenConsent); + }); + + it("if the saga is waiting for the notificationsInfoScreenConsent action and the latter is received, the saga terminates", () => { + testSaga(checkNotificationsPreferencesSaga, userProfile) + .next() + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding: true } + }) + ) + .next() + .take(profileUpsert.success) + .next({ + payload: { + newValue: { + push_notifications_content_type: + PushNotificationsContentTypeEnum.FULL, + reminder_status: ReminderStatusEnum.ENABLED + } + } + }) + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(false) + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + }) + ) + .next() + .take(notificationsInfoScreenConsent) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); + }); +}); diff --git a/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts index 44cf9c69135..76704efcf5c 100644 --- a/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts +++ b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts @@ -2,12 +2,14 @@ import { CommonActions, StackActions } from "@react-navigation/native"; import { call, take } from "typed-redux-saga/macro"; import { ActionType } from "typesafe-actions"; import { InitializedProfile } from "../../../../definitions/backend/InitializedProfile"; -import { remindersOptInEnabled } from "../../../config"; import NavigationService from "../../../navigation/NavigationService"; import ROUTES from "../../../navigation/routes"; import { profileUpsert } from "../../../store/actions/profile"; import { isProfileFirstOnBoarding } from "../../../store/reducers/profile"; -import { checkNotificationPermissions, requestNotificationPermissions } from "../utils"; +import { + checkNotificationPermissions, + requestNotificationPermissions +} from "../utils"; import { trackNotificationsOptInPreviewStatus, trackNotificationsOptInReminderStatus @@ -18,11 +20,6 @@ import { notificationsInfoScreenConsent } from "../store/actions/notifications"; export function* checkNotificationsPreferencesSaga( userProfile: InitializedProfile ) { - if (!remindersOptInEnabled) { - // the feature flag is disabled - return; - } - const isFirstOnboarding = isProfileFirstOnBoarding(userProfile); // Check if the user has already set a preference for push notification opt-in @@ -42,13 +39,12 @@ export function* checkNotificationsPreferencesSaga( } // show the opt-in screen - yield* call(() => - NavigationService.dispatchNavigationAction( - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, - params: { isFirstOnboarding } - }) - ) + yield* call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding } + }) ); // wait for the notifications preferences to be set diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx index b6cb7a1a8fc..e3a024684b4 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx @@ -1,11 +1,5 @@ import React, { useCallback, useEffect, useMemo } from "react"; -import { - AppState, - FlatList, - View, - Platform, - ListRenderItemInfo -} from "react-native"; +import { AppState, FlatList, View, Platform, StyleSheet } from "react-native"; import { Body, Divider, @@ -18,7 +12,7 @@ import { ListItemInfo, VSpacer } from "@pagopa/io-app-design-system"; -import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { useNavigation } from "@react-navigation/native"; import I18n from "../../../i18n"; import { openAppSettings } from "../../../utils/appSettings"; import { useIODispatch, useIOSelector } from "../../../store/hooks"; @@ -34,9 +28,23 @@ import { trackNotificationsOptInSkipSystemPermissions } from "../analytics"; +const styles = StyleSheet.create({ + footer: { paddingBottom: IOStyles.footer.paddingBottom }, + header: { + alignSelf: "flex-end", + flexDirection: "row", + paddingBottom: 18, + paddingRight: IOVisualCostants.appMarginDefault, + paddingTop: 24 + }, + listContainer: { + marginHorizontal: IOVisualCostants.appMarginDefault + } +}); + export const OnboardingNotificationsInfoScreenConsent = () => { + const navigation = useNavigation(); const dispatch = useIODispatch(); - const safeAreaInsets = useSafeAreaInsets(); const remindersEnabled = useIOSelector( pushNotificationRemindersEnabledSelector ); @@ -117,6 +125,13 @@ export const OnboardingNotificationsInfoScreenConsent = () => { [] ); + const closeModalAndScreen = useCallback(() => { + // Dismiss the modal + navigation.goBack(); + + dispatch(notificationsInfoScreenConsent()); + }, [dispatch, navigation]); + useEffect(() => { const subscription = AppState.addEventListener( "change", @@ -125,7 +140,7 @@ export const OnboardingNotificationsInfoScreenConsent = () => { const authorizationStatus = await checkNotificationPermissions(); if (authorizationStatus) { - dispatch(notificationsInfoScreenConsent()); + closeModalAndScreen(); } } } @@ -134,7 +149,7 @@ export const OnboardingNotificationsInfoScreenConsent = () => { return () => { subscription.remove(); }; - }, [dispatch]); + }, [closeModalAndScreen]); const goNext = useCallback(() => { // When this code executes, we know for sure that system notifications permissions are disabled, @@ -146,8 +161,8 @@ export const OnboardingNotificationsInfoScreenConsent = () => { trackNotificationsOptInReminderOnPermissionsOff(); } - dispatch(notificationsInfoScreenConsent()); - }, [dispatch, previewEnabled, remindersEnabled]); + closeModalAndScreen(); + }, [closeModalAndScreen, previewEnabled, remindersEnabled]); const openSettings = useCallback(() => { trackNotificationsOptInOpenSettings(); @@ -169,34 +184,24 @@ export const OnboardingNotificationsInfoScreenConsent = () => { return ( <> - - - - + + ) => ( + renderItem={({ item, index }) => ( )} - contentContainerStyle={{ - marginHorizontal: IOVisualCostants.appMarginDefault - }} + contentContainerStyle={styles.listContainer} ItemSeparatorComponent={() => } ListHeaderComponent={ListHeader} /> - + ( name={ROUTES.PROFILE_REMOVE_ACCOUNT_SUCCESS} component={RemoveAccountSuccess} /> - {remindersOptInEnabled && ( - - )} + ); diff --git a/ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx b/ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx deleted file mode 100644 index 00ef80cf310..00000000000 --- a/ts/sagas/startup/__tests__/checkNotificationsPermissionsSaga.test.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { CommonActions, StackActions } from "@react-navigation/native"; -import { testSaga } from "redux-saga-test-plan"; -import NavigationService from "../../../navigation/NavigationService"; -import ROUTES from "../../../navigation/routes"; -import { - checkNotificationPermissions, - requestNotificationPermissions -} from "../../../features/pushNotifications/utils"; -import { checkNotificationsPermissionsSaga } from "../../../features/pushNotifications/sagas/checkNotificationsPermissionsSaga"; -import { notificationsInfoScreenConsent } from "../../../features/pushNotifications/store/actions/notifications"; - -describe("checkNotificationsPermissionsSaga", () => { - it("upon saga startup, it should ask for push notifications permission", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions); - }); - - it("if the push notifications permission was given, the saga will terminate ", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(true) - .isDone(); - }); - - it("if the push notifications permission was not given and is first onboarding, the saga will request push notification permissions", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions); - }); - - it("if the saga asks for push permissions and the user give them, the saga will terminate", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions) - .next(true) - .isDone(); - }); - - it("if the saga asks for push permissions and the user does not give them, the saga navigates to the Info Screen and waits for the notificationsInfoScreenConsent action", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions) - .next(false) - .call( - NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT - }) - ) - .next() - .take(notificationsInfoScreenConsent); - }); - - it("if the saga is waiting for the notificationsInfoScreenConsent action and the latter is received, the saga terminates", () => { - testSaga(checkNotificationsPermissionsSaga) - .next() - .call(checkNotificationPermissions) - .next(false) - .call(requestNotificationPermissions) - .next(false) - .call( - NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT - }) - ) - .next() - .take(notificationsInfoScreenConsent) - .next() - .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) - .next() - .isDone(); - }); -}); diff --git a/ts/screens/profile/PreferencesScreen.tsx b/ts/screens/profile/PreferencesScreen.tsx index f00725e221d..cbcc9310c15 100644 --- a/ts/screens/profile/PreferencesScreen.tsx +++ b/ts/screens/profile/PreferencesScreen.tsx @@ -21,7 +21,6 @@ import { LightModalContextInterface } from "../../components/ui/LightModal"; import { RNavScreenWithLargeHeader } from "../../components/ui/RNavScreenWithLargeHeader"; -import { remindersOptInEnabled } from "../../config"; import I18n from "../../i18n"; import { AppParamsList, @@ -178,7 +177,6 @@ class PreferencesScreen extends React.Component { const preferencesNavListItems: ReadonlyArray = [ { // Notifications - condition: remindersOptInEnabled, value: I18n.t("profile.preferences.list.notifications.title"), description: I18n.t("profile.preferences.list.notifications.subtitle"), onPress: () => { diff --git a/ts/store/reducers/profile.ts b/ts/store/reducers/profile.ts index 567c93f2c7e..950b2acc8f4 100644 --- a/ts/store/reducers/profile.ts +++ b/ts/store/reducers/profile.ts @@ -200,22 +200,25 @@ export const profilePreferencesSelector = createSelector( ); export const pushNotificationRemindersEnabledSelector = (state: GlobalState) => -pipe( + pipe( state.profile, pot.toOption, O.chainNullableK(profile => profile.reminder_status), O.map(reminderStatus => reminderStatus === ReminderStatusEnum.ENABLED), O.getOrElse(() => false) -); + ); export const pushNotificationPreviewEnabledSelector = (state: GlobalState) => -pipe( + pipe( state.profile, pot.toOption, O.chainNullableK(profile => profile.push_notifications_content_type), - O.map(pushNotificationContentType => pushNotificationContentType === PushNotificationsContentTypeEnum.FULL), + O.map( + pushNotificationContentType => + pushNotificationContentType === PushNotificationsContentTypeEnum.FULL + ), O.getOrElse(() => false) -); + ); // return the profile notification settings actual state or undefined if ProfileState pot is in an Error state export const profileNotificationSettingsSelector = createSelector( From ab5bd1806d93e203c6cfed618f9da3823e0b70fc Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Fri, 3 May 2024 18:06:15 +0200 Subject: [PATCH 12/17] Working tests --- .../screens/OnboardingNotificationsInfoScreenConsent.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx index e3a024684b4..8201ae2404b 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx @@ -126,8 +126,12 @@ export const OnboardingNotificationsInfoScreenConsent = () => { ); const closeModalAndScreen = useCallback(() => { - // Dismiss the modal - navigation.goBack(); + // Dismiss the modal (the check on `canGoBack` avoids + // a logged error when running tests, since in that + // case there is no screen below on the navigation stack) + if (navigation.canGoBack()) { + navigation.goBack(); + } dispatch(notificationsInfoScreenConsent()); }, [dispatch, navigation]); @@ -189,6 +193,7 @@ export const OnboardingNotificationsInfoScreenConsent = () => { icon="closeLarge" color="neutral" onPress={goNext} + testID="continue-btn" accessibilityLabel={I18n.t("global.buttons.close")} /> From 2a9b5eeb75ae2e1d259da0e60758f12396d697dd Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Sat, 4 May 2024 23:48:59 +0200 Subject: [PATCH 13/17] Tests --- ...ingNotificationsInfoScreenConsent.test.tsx | 56 +- ...ingNotificationsPreferencesScreen.test.tsx | 168 +- ...tificationsInfoScreenConsent.test.tsx.snap | 1489 ++++ ...tificationsPreferencesScreen.test.tsx.snap | 7582 +++++++++++++++++ ts/store/reducers/__tests__/profile.test.ts | 322 +- 5 files changed, 9510 insertions(+), 107 deletions(-) create mode 100644 ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsInfoScreenConsent.test.tsx.snap create mode 100644 ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap diff --git a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx index dc8eb0e3777..3f9c381e7b9 100644 --- a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx +++ b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsInfoScreenConsent.test.tsx @@ -1,14 +1,14 @@ -import configureMockStore from "redux-mock-store"; +import { createStore } from "redux"; import { AppState } from "react-native"; import { fireEvent, waitFor } 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 { OnboardingNotificationsInfoScreenConsent } from "../OnboardingNotificationsInfoScreenConsent"; import * as notificationsActions from "../../store/actions/notifications"; import * as notification from "../../utils"; +import { preferencesDesignSystemSetEnabled } from "../../../../store/actions/persistedPreferences"; const checkNotificationPermissions = jest.spyOn( notification, @@ -27,10 +27,9 @@ describe("OnboardingNotificationsInfoScreenConsent", () => { }); it("Click on the button continue check that the NOTIFICATIONS_INFO_SCREEN_CONSENT action is triggered", () => { - const globalState = appReducer(undefined, applicationChangeState("active")); - const { component } = renderComponentMockStore(globalState); + const screen = renderScreen(); - const continueButton = component.queryByTestId("continue-btn"); + const continueButton = screen.queryByTestId("continue-btn"); expect(continueButton).not.toBeNull(); if (continueButton) { @@ -43,11 +42,10 @@ describe("OnboardingNotificationsInfoScreenConsent", () => { checkNotificationPermissions.mockImplementation(() => Promise.resolve(true) ); - const globalState = appReducer(undefined, applicationChangeState("active")); const appStateSpy = jest.spyOn(AppState, "addEventListener"); - const { component } = renderComponentMockStore(globalState); - expect(component).not.toBeNull(); + const screen = renderScreen(); + expect(screen).not.toBeNull(); appStateSpy.mock.calls[0][1]("active"); @@ -61,11 +59,10 @@ describe("OnboardingNotificationsInfoScreenConsent", () => { checkNotificationPermissions.mockImplementation(() => Promise.resolve(false) ); - const globalState = appReducer(undefined, applicationChangeState("active")); const appStateSpy = jest.spyOn(AppState, "addEventListener"); - const { component } = renderComponentMockStore(globalState); - expect(component).not.toBeNull(); + const screen = renderScreen(); + expect(screen).not.toBeNull(); appStateSpy.mock.calls[0][1]("active"); @@ -76,11 +73,10 @@ describe("OnboardingNotificationsInfoScreenConsent", () => { }); it("If AppState is not active doesn't trigger NOTIFICATIONS_INFO_SCREEN_CONSENT action", () => { - const globalState = appReducer(undefined, applicationChangeState("active")); const appStateSpy = jest.spyOn(AppState, "addEventListener"); - const { component } = renderComponentMockStore(globalState); - expect(component).not.toBeNull(); + const screen = renderScreen(); + expect(screen).not.toBeNull(); appStateSpy.mock.calls[0][1]("background"); expect(checkNotificationPermissions).not.toBeCalled(); @@ -98,21 +94,25 @@ describe("OnboardingNotificationsInfoScreenConsent", () => { expect(checkNotificationPermissions).not.toBeCalled(); expect(notificationsInfoScreenConsentSpy).not.toBeCalled(); }); + + it("should match snapshot", () => { + const screen = renderScreen(); + expect(screen.toJSON()).toMatchSnapshot(); + }); }); -const renderComponentMockStore = (state: GlobalState) => { - const mockStore = configureMockStore(); - const store: ReturnType = mockStore({ - ...state - } as GlobalState); - - return { - component: renderScreenWithNavigationStoreContext( - OnboardingNotificationsInfoScreenConsent, - ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT, - {}, - store - ), +const renderScreen = () => { + const globalState = appReducer(undefined, applicationChangeState("active")); + const dsEnabledState = appReducer( + globalState, + preferencesDesignSystemSetEnabled({ isDesignSystemEnabled: true }) + ); + const store = createStore(appReducer, dsEnabledState as any); + + return renderScreenWithNavigationStoreContext( + OnboardingNotificationsInfoScreenConsent, + ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT, + {}, store - }; + ); }; diff --git a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx index 931309d5b16..e361e26b2c2 100644 --- a/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx +++ b/ts/features/pushNotifications/screens/__tests__/OnboardingNotificationsPreferencesScreen.test.tsx @@ -1,101 +1,113 @@ import * as pot from "@pagopa/ts-commons/lib/pot"; import _ from "lodash"; -import configureMockStore from "redux-mock-store"; +import { act, fireEvent } from "@testing-library/react-native"; +import { createStore } from "redux"; import I18n from "../../../../i18n"; 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 mockedProfile from "../../../../__mocks__/initializedProfile"; import { OnboardingNotificationsPreferencesScreen } from "../OnboardingNotificationsPreferencesScreen"; +import { preferencesDesignSystemSetEnabled } from "../../../../store/actions/persistedPreferences"; +import { GlobalState } from "../../../../store/reducers/types"; describe("OnboardingNotificationsPreferencesScreen", () => { - describe("given an user that is doing the onboarding for the first time", () => { - it("then the title should match the 'profile.preferences.notifications.title' key and the subtitle should match 'profile.preferences.notifications.subtitle'", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore(globalState, true); - expect(screen).not.toBeNull(); - - const headerH1Title = screen.component.queryByText( - I18n.t("profile.preferences.notifications.title") - ); - expect(headerH1Title).not.toBeNull(); - - const bodySubtitle = screen.component.queryByText( - I18n.t("profile.preferences.notifications.subtitle") - ); - expect(bodySubtitle).not.toBeNull(); + it("given an user that is doing the onboarding for the first time then the title should match the 'profile.preferences.notifications.title' key and the subtitle should match 'profile.preferences.notifications.subtitle'", () => { + const screen = renderScreen(true); + expect(screen).not.toBeNull(); + + const headerH1Title = screen.queryByText( + I18n.t("profile.preferences.notifications.title") + ); + expect(headerH1Title).not.toBeNull(); + + const bodySubtitle = screen.queryByText( + I18n.t("profile.preferences.notifications.subtitle") + ); + expect(bodySubtitle).not.toBeNull(); + }); + + it("given an onboarded user and an undefined 'reminder_status' then the reminders switch should be on", () => { + const screen = renderScreen(false); + expect(screen).not.toBeNull(); + + const toggle = screen.getByTestId("remindersPreferenceSwitch"); + expect(toggle.props.value).toBeTruthy(); + }); + + it("given an onboarded user and an undefined 'push_notifications_content_type' then the previews switch should be on", () => { + const screen = renderScreen(false); + expect(screen).not.toBeNull(); + + const toggle = screen.getByTestId("previewsPreferenceSwitch"); + expect(toggle.props.value).toBeTruthy(); + }); + + it("should match snapshot when updating the profile", () => { + const screen = renderScreen(true, true); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot when not updating the profile", () => { + const screen = renderScreen(false); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot when not updating the profile, disabled previews switch", async () => { + const screen = renderScreen(false); + + const previewSwitch = screen.getByTestId("previewsPreferenceSwitch"); + await act(() => { + fireEvent(previewSwitch, "onValueChange", false); }); + + expect(screen.toJSON()).toMatchSnapshot(); }); + it("should match snapshot when not updating the profile, disabled reminder switch", async () => { + const screen = renderScreen(false); - describe("given an onboarded user and an undefined 'reminder_status'", () => { - it("then the reminders switch should be on", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore( - { - ...globalState, - profile: pot.some({ - ..._.omit(mockedProfile, "reminder_status") - }) - }, - false - ); - expect(screen).not.toBeNull(); - - const toggle = screen.component.getByTestId("remindersPreferenceSwitch"); - expect(toggle.props.value).toBeTruthy(); + const reminderSwitch = screen.getByTestId("remindersPreferenceSwitch"); + await act(() => { + fireEvent(reminderSwitch, "onValueChange", false); }); + + expect(screen.toJSON()).toMatchSnapshot(); }); - describe("given an onboarded user and an undefined 'push_notifications_content_type'", () => { - it("then the previews switch should be on", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore( - { - ...globalState, - profile: pot.some({ - ..._.omit(mockedProfile, "push_notifications_content_type") - }) - }, - false - ); - expect(screen).not.toBeNull(); - - const toggle = screen.component.getByTestId("previewsPreferenceSwitch"); - expect(toggle.props.value).toBeTruthy(); + it("should match snapshot when not updating the profile, disabled previews and reminder switches", async () => { + const screen = renderScreen(false); + + const previewSwitch = screen.getByTestId("previewsPreferenceSwitch"); + + const reminderSwitch = screen.getByTestId("remindersPreferenceSwitch"); + await act(() => { + fireEvent(previewSwitch, "onValueChange", false); + fireEvent(reminderSwitch, "onValueChange", false); }); + + expect(screen.toJSON()).toMatchSnapshot(); }); }); -const renderComponentMockStore = ( - state: GlobalState, - isFirstOnboarding: boolean +const renderScreen = ( + isFirstOnboarding: boolean, + isUpdatingProfile: boolean = false ) => { - const mockStore = configureMockStore(); - const store: ReturnType = mockStore({ - ...state - } as GlobalState); - - return { - component: renderScreenWithNavigationStoreContext( - OnboardingNotificationsPreferencesScreen, - ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, - { - isFirstOnboarding - }, - store - ), + const globalState = appReducer(undefined, applicationChangeState("active")); + const dsEnabledState = appReducer( + globalState, + preferencesDesignSystemSetEnabled({ isDesignSystemEnabled: true }) + ); + const finalState = { + ...dsEnabledState, + profile: isUpdatingProfile ? pot.noneUpdating({}) : pot.some({}) + } as GlobalState; + const store = createStore(appReducer, finalState as any); + + return renderScreenWithNavigationStoreContext( + OnboardingNotificationsPreferencesScreen, + ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + { + isFirstOnboarding + }, store - }; + ); }; diff --git a/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsInfoScreenConsent.test.tsx.snap b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsInfoScreenConsent.test.tsx.snap new file mode 100644 index 00000000000..714d997d73b --- /dev/null +++ b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsInfoScreenConsent.test.tsx.snap @@ -0,0 +1,1489 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OnboardingNotificationsInfoScreenConsent should match snapshot 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Enable push notifications not to miss important messages! +

+ + + To do so, you'll have to edit the preferences in your device settings. + + +
+ Here's how: +
+ +
+ } + contentContainerStyle={ + Object { + "marginHorizontal": 24, + } + } + data={ + Array [ + Object { + "accessibilityLabel": "Go to \\"Settings\\"", + "icon": "systemSettingsiOS", + "label": "Step", + "value": "Go to \\"Settings\\"", + }, + Object { + "accessibilityLabel": "Select \\"Notifications\\"", + "icon": "systemNotificationsInstructions", + "label": "Step", + "value": "Select \\"Notifications\\"", + }, + Object { + "accessibilityLabel": "Enable \\"Allow Notifications\\"", + "icon": "systemToggleInstructions", + "label": "Step", + "value": "Enable \\"Allow Notifications\\"", + }, + ] + } + getItem={[Function]} + getItemCount={[Function]} + keyExtractor={[Function]} + onContentSizeChange={[Function]} + onLayout={[Function]} + onMomentumScrollBegin={[Function]} + onMomentumScrollEnd={[Function]} + onScroll={[Function]} + onScrollBeginDrag={[Function]} + onScrollEndDrag={[Function]} + removeClippedSubviews={false} + renderItem={[Function]} + scrollEventThrottle={50} + stickyHeaderIndices={Array []} + viewabilityConfigCallbackPairs={Array []} + > + + + + + Enable push notifications not to miss important messages! + + + + To do so, you'll have to edit the preferences in your device settings. + + + + Here's how: + + + + + + + + + + + + + + + + + + + + + + + + + + + Step 1 + + + Go to "Settings" + + + + + + + + + + + + + + + + + + + + + + + Step 2 + + + Select "Notifications" + + + + + + + + + + + + + + + + + + + + + Step 3 + + + Enable "Allow Notifications" + + + + + + + + + + + + + + + + + + Go to Settings + + + + + + + + + + + + + + +
+
+
+
+
+
+`; diff --git a/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap new file mode 100644 index 00000000000..431d528aeca --- /dev/null +++ b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap @@ -0,0 +1,7582 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not updating the profile 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + Continue + + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not updating the profile, disabled previews and reminder switches 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + Continue + + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not updating the profile, disabled previews switch 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + Continue + + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not updating the profile, disabled reminder switch 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + Continue + + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`OnboardingNotificationsPreferencesScreen should match snapshot when updating the profile 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; diff --git a/ts/store/reducers/__tests__/profile.test.ts b/ts/store/reducers/__tests__/profile.test.ts index 2c26f7336df..d64d065d749 100644 --- a/ts/store/reducers/__tests__/profile.test.ts +++ b/ts/store/reducers/__tests__/profile.test.ts @@ -7,10 +7,15 @@ import { isProfileEmailValidatedSelector, isProfileFirstOnBoarding, profileEmailSelector, - ProfileState + ProfileState, + pushNotificationPreviewEnabledSelector, + pushNotificationRemindersEnabledSelector } from "../profile"; import { ServicesPreferencesModeEnum } from "../../../../definitions/backend/ServicesPreferencesMode"; import { GlobalState } from "../types"; +import { ReminderStatusEnum } from "../../../../definitions/backend/ReminderStatus"; +import { ProfileError } from "../profileErrorType"; +import { PushNotificationsContentTypeEnum } from "../../../../definitions/backend/PushNotificationsContentType"; describe("email profile selector", () => { const potProfile: ProfileState = pot.some(mockedProfile); @@ -288,3 +293,318 @@ describe("isProfileEmailValidatedSelector", () => { expect(isProfileEmailValidated).toBe(true); }); }); + +describe("pushNotificationRemindersEnabledSelector", () => { + it("should return false for a pot.none profile", () => { + const globalState = { + profile: pot.none + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.noneLoading profile", () => { + const globalState = { + profile: pot.noneLoading + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.noneUpdating profile", () => { + const globalState = { + profile: pot.noneUpdating({ + reminder_status: ReminderStatusEnum.ENABLED + }) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.noneError profile", () => { + const globalState = { + profile: pot.noneError(new ProfileError("test error")) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.some profile with undefined reminder_status", () => { + const globalState = { + profile: pot.some({ reminder_status: undefined }) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.some profile with DISABLED reminder_status", () => { + const globalState = { + profile: pot.some({ reminder_status: ReminderStatusEnum.DISABLED }) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return true for a pot.some profile with ENABLED reminder_status", () => { + const globalState = { + profile: pot.some({ reminder_status: ReminderStatusEnum.ENABLED }) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(true); + }); + it("should return false for a pot.someLoading profile with undefined reminder_status", () => { + const globalState = { + profile: pot.someLoading({ reminder_status: undefined }) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.someLoading profile with DISABLED reminder_status", () => { + const globalState = { + profile: pot.someLoading({ reminder_status: ReminderStatusEnum.DISABLED }) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return true for a pot.someLoading profile with ENABLED reminder_status", () => { + const globalState = { + profile: pot.someLoading({ reminder_status: ReminderStatusEnum.ENABLED }) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(true); + }); + it("should return false for a pot.someUpdating profile with undefined reminder_status", () => { + const globalState = { + profile: pot.someUpdating( + { reminder_status: undefined }, + { reminder_status: ReminderStatusEnum.ENABLED } + ) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.someUpdating profile with DISABLED reminder_status", () => { + const globalState = { + profile: pot.someUpdating( + { reminder_status: ReminderStatusEnum.DISABLED }, + { reminder_status: ReminderStatusEnum.ENABLED } + ) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return true for a pot.someUpdating profile with ENABLED reminder_status", () => { + const globalState = { + profile: pot.someUpdating( + { reminder_status: ReminderStatusEnum.ENABLED }, + { reminder_status: ReminderStatusEnum.DISABLED } + ) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(true); + }); + it("should return false for a pot.someError profile with undefined reminder_status", () => { + const globalState = { + profile: pot.someError( + { reminder_status: undefined }, + new ProfileError("test error") + ) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return false for a pot.someError profile with DISABLED reminder_status", () => { + const globalState = { + profile: pot.someError( + { reminder_status: ReminderStatusEnum.DISABLED }, + new ProfileError("test error") + ) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(false); + }); + it("should return true for a pot.someError profile with ENABLED reminder_status", () => { + const globalState = { + profile: pot.someError( + { reminder_status: ReminderStatusEnum.ENABLED }, + new ProfileError("test error") + ) + } as GlobalState; + const remindersEnabled = + pushNotificationRemindersEnabledSelector(globalState); + expect(remindersEnabled).toBe(true); + }); +}); + +describe("pushNotificationPreviewEnabledSelector", () => { + it("should return false for a pot.none profile", () => { + const globalState = { + profile: pot.none + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.noneLoading profile", () => { + const globalState = { + profile: pot.noneLoading + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.noneUpdating profile", () => { + const globalState = { + profile: pot.noneUpdating({ + reminder_status: ReminderStatusEnum.ENABLED + }) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.noneError profile", () => { + const globalState = { + profile: pot.noneError(new ProfileError("test error")) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.some profile with undefined push_notifications_content_type", () => { + const globalState = { + profile: pot.some({ push_notifications_content_type: undefined }) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.some profile with ANONYMOUS push_notifications_content_type", () => { + const globalState = { + profile: pot.some({ + push_notifications_content_type: + PushNotificationsContentTypeEnum.ANONYMOUS + }) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return true for a pot.some profile with FULL push_notifications_content_type", () => { + const globalState = { + profile: pot.some({ + push_notifications_content_type: PushNotificationsContentTypeEnum.FULL + }) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(true); + }); + it("should return false for a pot.someLoading profile with undefined push_notifications_content_type", () => { + const globalState = { + profile: pot.someLoading({ push_notifications_content_type: undefined }) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.someLoading profile with ANONYMOUS push_notifications_content_type", () => { + const globalState = { + profile: pot.someLoading({ + push_notifications_content_type: + PushNotificationsContentTypeEnum.ANONYMOUS + }) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return true for a pot.someLoading profile with FULL push_notifications_content_type", () => { + const globalState = { + profile: pot.someLoading({ + push_notifications_content_type: PushNotificationsContentTypeEnum.FULL + }) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(true); + }); + it("should return false for a pot.someUpdating profile with undefined push_notifications_content_type", () => { + const globalState = { + profile: pot.someUpdating( + { push_notifications_content_type: undefined }, + { + push_notifications_content_type: + PushNotificationsContentTypeEnum.ANONYMOUS + } + ) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.someUpdating profile with ANONYMOUS push_notifications_content_type", () => { + const globalState = { + profile: pot.someUpdating( + { + push_notifications_content_type: + PushNotificationsContentTypeEnum.ANONYMOUS + }, + { + push_notifications_content_type: + PushNotificationsContentTypeEnum.ANONYMOUS + } + ) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return true for a pot.someUpdating profile with FULL push_notifications_content_type", () => { + const globalState = { + profile: pot.someUpdating( + { + push_notifications_content_type: PushNotificationsContentTypeEnum.FULL + }, + { + push_notifications_content_type: + PushNotificationsContentTypeEnum.ANONYMOUS + } + ) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(true); + }); + it("should return false for a pot.someError profile with undefined push_notifications_content_type", () => { + const globalState = { + profile: pot.someError( + { push_notifications_content_type: undefined }, + new ProfileError("test error") + ) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return false for a pot.someError profile with ANONYMOUS push_notifications_content_type", () => { + const globalState = { + profile: pot.someError( + { + push_notifications_content_type: + PushNotificationsContentTypeEnum.ANONYMOUS + }, + new ProfileError("test error") + ) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(false); + }); + it("should return true for a pot.someError profile with FULL push_notifications_content_type", () => { + const globalState = { + profile: pot.someError( + { + push_notifications_content_type: PushNotificationsContentTypeEnum.FULL + }, + new ProfileError("test error") + ) + } as GlobalState; + const previewEnabled = pushNotificationPreviewEnabledSelector(globalState); + expect(previewEnabled).toBe(true); + }); +}); From 352d09315abbd7bccfd860bd175c23d3ee351f77 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Sat, 4 May 2024 23:59:02 +0200 Subject: [PATCH 14/17] More tests --- .../NotificationPreviewSample.test.tsx | 161 +- .../NotificationsPreferencesPreview.test.tsx | 48 + .../NotificationPreviewSample.test.tsx.snap | 2157 ++++++++++++++++ ...ificationsPreferencesPreview.test.tsx.snap | 2293 +++++++++++++++++ 4 files changed, 4598 insertions(+), 61 deletions(-) create mode 100644 ts/features/pushNotifications/components/__tests__/NotificationsPreferencesPreview.test.tsx create mode 100644 ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationPreviewSample.test.tsx.snap create mode 100644 ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationsPreferencesPreview.test.tsx.snap diff --git a/ts/features/pushNotifications/components/__tests__/NotificationPreviewSample.test.tsx b/ts/features/pushNotifications/components/__tests__/NotificationPreviewSample.test.tsx index 63298a77d96..949611858de 100644 --- a/ts/features/pushNotifications/components/__tests__/NotificationPreviewSample.test.tsx +++ b/ts/features/pushNotifications/components/__tests__/NotificationPreviewSample.test.tsx @@ -1,72 +1,90 @@ import * as React from "react"; +import { createStore } from "redux"; import { render } from "@testing-library/react-native"; import I18n from "../../../../i18n"; import { NotificationPreviewSample } from "../NotificationPreviewSample"; +import { appReducer } from "../../../../store/reducers"; +import { applicationChangeState } from "../../../../store/actions/application"; +import { preferencesDesignSystemSetEnabled } from "../../../../store/actions/persistedPreferences"; +import { renderScreenWithNavigationStoreContext } from "../../../../utils/testWrapper"; +import ROUTES from "../../../../navigation/routes"; -describe("renderNotificationPreviewSample", () => { - describe("Given enabled previews and enabled reminders", () => { - it("then title should match 'onboarding.notifications.preview.reminderOnPreviewOnTitle' key and message should match 'onboarding.notifications.preview.reminderOnPreviewOnMessage' key", () => { - const screen = renderNotificationPreviewSample(true, true); - expect(screen).not.toBeNull(); - - const h4Title = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOnPreviewOnTitle") - ); - expect(h4Title).not.toBeNull(); - - const h5Message = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOnPreviewOnMessage") - ); - expect(h5Message).not.toBeNull(); - }); +describe("NotificationPreviewSample", () => { + it("Given enabled previews and enabled reminders then title should match 'onboarding.notifications.preview.reminderOnPreviewOnTitle' key and message should match 'onboarding.notifications.preview.reminderOnPreviewOnMessage' key", () => { + const screen = renderNotificationPreviewSample(true, true); + expect(screen).not.toBeNull(); + + const h4Title = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOnPreviewOnTitle") + ); + expect(h4Title).not.toBeNull(); + + const h5Message = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOnPreviewOnMessage") + ); + expect(h5Message).not.toBeNull(); }); - describe("Given disabled previews and enabled reminders", () => { - it("then title should match 'onboarding.notifications.preview.reminderOnPreviewOffTitle' key and message should match 'onboarding.notifications.preview.reminderOnPreviewOffMessage' key", () => { - const screen = renderNotificationPreviewSample(false, true); - expect(screen).not.toBeNull(); - - const h4Title = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOnPreviewOffTitle") - ); - expect(h4Title).not.toBeNull(); - - const h5Message = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOnPreviewOffMessage") - ); - expect(h5Message).not.toBeNull(); - }); + + it("Given disabled previews and enabled reminders then title should match 'onboarding.notifications.preview.reminderOnPreviewOffTitle' key and message should match 'onboarding.notifications.preview.reminderOnPreviewOffMessage' key", () => { + const screen = renderNotificationPreviewSample(false, true); + expect(screen).not.toBeNull(); + + const h4Title = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOnPreviewOffTitle") + ); + expect(h4Title).not.toBeNull(); + + const h5Message = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOnPreviewOffMessage") + ); + expect(h5Message).not.toBeNull(); }); - describe("Given enabled previews and disabled reminders", () => { - it("then title should match 'onboarding.notifications.preview.reminderOffPreviewOnTitle' key and message should match 'onboarding.notifications.preview.reminderOffPreviewOnMessage' key", () => { - const screen = renderNotificationPreviewSample(true, false); - expect(screen).not.toBeNull(); - - const h4Title = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOffPreviewOnTitle") - ); - expect(h4Title).not.toBeNull(); - - const h5Message = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOffPreviewOnMessage") - ); - expect(h5Message).not.toBeNull(); - }); + + it("Given enabled previews and disabled reminders then title should match 'onboarding.notifications.preview.reminderOffPreviewOnTitle' key and message should match 'onboarding.notifications.preview.reminderOffPreviewOnMessage' key", () => { + const screen = renderNotificationPreviewSample(true, false); + expect(screen).not.toBeNull(); + + const h4Title = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOffPreviewOnTitle") + ); + expect(h4Title).not.toBeNull(); + + const h5Message = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOffPreviewOnMessage") + ); + expect(h5Message).not.toBeNull(); }); - describe("Given disabled previews and disabled reminders", () => { - it("then title should match 'onboarding.notifications.preview.reminderOffPreviewOffTitle' key and message should match 'onboarding.notifications.preview.reminderOnPreviewOffMessage' key", () => { - const screen = renderNotificationPreviewSample(false, false); - expect(screen).not.toBeNull(); - - const h4Title = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOffPreviewOffTitle") - ); - expect(h4Title).not.toBeNull(); - - const h5Message = screen.queryByText( - I18n.t("onboarding.notifications.preview.reminderOffPreviewOffMessage") - ); - expect(h5Message).not.toBeNull(); - }); + + it("Given disabled previews and disabled reminders then title should match 'onboarding.notifications.preview.reminderOffPreviewOffTitle' key and message should match 'onboarding.notifications.preview.reminderOnPreviewOffMessage' key", () => { + const screen = renderNotificationPreviewSample(false, false); + expect(screen).not.toBeNull(); + + const h4Title = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOffPreviewOffTitle") + ); + expect(h4Title).not.toBeNull(); + + const h5Message = screen.queryByText( + I18n.t("onboarding.notifications.preview.reminderOffPreviewOffMessage") + ); + expect(h5Message).not.toBeNull(); + }); + + it("should match snapshot, preview on, reminder on", () => { + const component = renderComponent(true, true); + expect(component.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, preview on, reminder off", () => { + const component = renderComponent(true, false); + expect(component.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, preview off, reminder on", () => { + const component = renderComponent(false, true); + expect(component.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, preview off, reminder off", () => { + const component = renderComponent(false, false); + expect(component.toJSON()).toMatchSnapshot(); }); }); @@ -82,3 +100,24 @@ const renderNotificationPreviewSample = ( ); return render(component); }; + +const renderComponent = (previewOn: boolean, reminderOn: boolean) => { + const globalState = appReducer(undefined, applicationChangeState("active")); + const dsEnabledState = appReducer( + globalState, + preferencesDesignSystemSetEnabled({ isDesignSystemEnabled: true }) + ); + const store = createStore(appReducer, dsEnabledState as any); + + return renderScreenWithNavigationStoreContext( + () => ( + + ), + ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + {}, + store + ); +}; diff --git a/ts/features/pushNotifications/components/__tests__/NotificationsPreferencesPreview.test.tsx b/ts/features/pushNotifications/components/__tests__/NotificationsPreferencesPreview.test.tsx new file mode 100644 index 00000000000..cdef0455bad --- /dev/null +++ b/ts/features/pushNotifications/components/__tests__/NotificationsPreferencesPreview.test.tsx @@ -0,0 +1,48 @@ +import React from "react"; +import { createStore } from "redux"; +import { applicationChangeState } from "../../../../store/actions/application"; +import { preferencesDesignSystemSetEnabled } from "../../../../store/actions/persistedPreferences"; +import { appReducer } from "../../../../store/reducers"; +import { renderScreenWithNavigationStoreContext } from "../../../../utils/testWrapper"; +import { NotificationsPreferencesPreview } from "../NotificationsPreferencesPreview"; +import ROUTES from "../../../../navigation/routes"; + +describe("NotificationsPreferencesPreview", () => { + it("should match snapshot, preview on, reminder on", () => { + const component = renderComponent(true, true); + expect(component.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, preview on, reminder off", () => { + const component = renderComponent(true, false); + expect(component.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, preview off, reminder on", () => { + const component = renderComponent(false, true); + expect(component.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, preview off, reminder off", () => { + const component = renderComponent(false, false); + expect(component.toJSON()).toMatchSnapshot(); + }); +}); + +const renderComponent = (previewOn: boolean, reminderOn: boolean) => { + const globalState = appReducer(undefined, applicationChangeState("active")); + const dsEnabledState = appReducer( + globalState, + preferencesDesignSystemSetEnabled({ isDesignSystemEnabled: true }) + ); + const store = createStore(appReducer, dsEnabledState as any); + + return renderScreenWithNavigationStoreContext( + () => ( + + ), + ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + {}, + store + ); +}; diff --git a/ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationPreviewSample.test.tsx.snap b/ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationPreviewSample.test.tsx.snap new file mode 100644 index 00000000000..a91890c3a6d --- /dev/null +++ b/ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationPreviewSample.test.tsx.snap @@ -0,0 +1,2157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NotificationPreviewSample should match snapshot, preview off, reminder off 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + + + + + +`; + +exports[`NotificationPreviewSample should match snapshot, preview off, reminder on 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + + + + + +`; + +exports[`NotificationPreviewSample should match snapshot, preview on, reminder off 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + + + + + +`; + +exports[`NotificationPreviewSample should match snapshot, preview on, reminder on 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + + + + + +`; diff --git a/ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationsPreferencesPreview.test.tsx.snap b/ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationsPreferencesPreview.test.tsx.snap new file mode 100644 index 00000000000..4041733bb9f --- /dev/null +++ b/ts/features/pushNotifications/components/__tests__/__snapshots__/NotificationsPreferencesPreview.test.tsx.snap @@ -0,0 +1,2293 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NotificationsPreferencesPreview should match snapshot, preview off, reminder off 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesPreview should match snapshot, preview off, reminder on 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesPreview should match snapshot, preview on, reminder off 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesPreview should match snapshot, preview on, reminder on 1`] = ` + + + + + + + + + + + + + + + ONBOARDING_NOTIFICATIONS_PREFERENCES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + + + + + + +`; From 12c916172c87af8b1e1686f337336ce1f79744b6 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Sun, 5 May 2024 22:35:50 +0200 Subject: [PATCH 15/17] Profile and tests --- .../ui/RNavScreenWithLargeHeader.tsx | 2 +- .../ProfileNotificationsSettings.tsx | 82 + .../ProfileNotificationsSettings.test.tsx | 77 + ...ProfileNotificationsSettings.test.tsx.snap | 162113 +++++++++++++++ ...boardingNotificationsPreferencesScreen.tsx | 68 +- ...tificationsPreferencesScreen.test.tsx.snap | 1148 +- .../NotificationsPreferencesScreen.tsx | 189 +- .../NotificationsPreferencesScreen.test.tsx | 295 +- ...tificationsPreferencesScreen.test.tsx.snap | 24715 +++ ts/store/reducers/__tests__/profile.test.ts | 120 + ts/store/reducers/profile.ts | 18 +- 11 files changed, 188114 insertions(+), 713 deletions(-) create mode 100644 ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx create mode 100644 ts/features/pushNotifications/components/__tests__/ProfileNotificationsSettings.test.tsx create mode 100644 ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap create mode 100644 ts/screens/profile/__test__/__snapshots__/NotificationsPreferencesScreen.test.tsx.snap diff --git a/ts/components/ui/RNavScreenWithLargeHeader.tsx b/ts/components/ui/RNavScreenWithLargeHeader.tsx index 59320a8de5d..05e5e6734c7 100644 --- a/ts/components/ui/RNavScreenWithLargeHeader.tsx +++ b/ts/components/ui/RNavScreenWithLargeHeader.tsx @@ -135,7 +135,7 @@ export const RNavScreenWithLargeHeader = ({ {description && ( - + {description} )} diff --git a/ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx b/ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx new file mode 100644 index 00000000000..d92a3631159 --- /dev/null +++ b/ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx @@ -0,0 +1,82 @@ +import { + Divider, + FeatureInfo, + ListItemSwitch, + VSpacer +} from "@pagopa/io-app-design-system"; +import React from "react"; +import I18n from "../../../i18n"; +import { usePreviewMoreInfo } from "../hooks/usePreviewMoreInfo"; +import { NotificationsPreferencesPreview } from "./NotificationsPreferencesPreview"; + +type ProfileNotificationSettingsProps = { + disablePreviewSetting: boolean; + disableRemindersSetting: boolean; + isUpdatingPreviewSetting: boolean; + isUpdatingRemindersSetting: boolean; + onPreviewValueChanged?: (value: boolean) => void; + onReminderValueChanged?: (value: boolean) => void; + previewSwitchValue: boolean; + remindersSwitchValue: boolean; + showSettingsPath: boolean; +}; + +export const ProfileNotificationSettings = ({ + disablePreviewSetting, + disableRemindersSetting, + isUpdatingPreviewSetting, + isUpdatingRemindersSetting, + onPreviewValueChanged, + onReminderValueChanged, + previewSwitchValue, + remindersSwitchValue, + showSettingsPath +}: ProfileNotificationSettingsProps) => { + const { present, bottomSheet } = usePreviewMoreInfo(); + return ( + <> + + + + + + + {showSettingsPath && } + {showSettingsPath && ( + + )} + + {bottomSheet} + + ); +}; diff --git a/ts/features/pushNotifications/components/__tests__/ProfileNotificationsSettings.test.tsx b/ts/features/pushNotifications/components/__tests__/ProfileNotificationsSettings.test.tsx new file mode 100644 index 00000000000..d3455c06f4e --- /dev/null +++ b/ts/features/pushNotifications/components/__tests__/ProfileNotificationsSettings.test.tsx @@ -0,0 +1,77 @@ +/* eslint-disable no-bitwise */ +import React from "react"; +import { createStore } from "redux"; +import { ProfileNotificationSettings } from "../ProfileNotificationsSettings"; +import { appReducer } from "../../../../store/reducers"; +import { applicationChangeState } from "../../../../store/actions/application"; +import { preferencesDesignSystemSetEnabled } from "../../../../store/actions/persistedPreferences"; +import { renderScreenWithNavigationStoreContext } from "../../../../utils/testWrapper"; +import ROUTES from "../../../../navigation/routes"; + +describe("ProfileNotificationSettings", () => { + [...Array(128).keys()].forEach(index => { + const previewSwitchDisabled = !!(index & 0b00000001); + const previewSwitchIsUpdating = !!(index & 0b00000010); + const previewSwitchValue = !!(index & 0b00000100); + const reminderSwitchDisabled = !!(index & 0b00001000); + const reminderSwitchIsUpdating = !!(index & 0b00010000); + const reminderSwitchValue = !!(index & 0b00100000); + const showSettingsPath = !!(index & 0b01000000); + it(`should match snapshot, preview ${ + previewSwitchDisabled ? "disabled" : "enabled " + }, preview ${ + previewSwitchIsUpdating ? "updating " : "not updating" + }, preview ${previewSwitchValue ? "on " : "off"}, reminder ${ + reminderSwitchDisabled ? "disabled" : "enabled " + }, reminder ${ + reminderSwitchIsUpdating ? "updating " : "not updating" + }, reminder ${reminderSwitchValue ? "on " : "off"}, settings path ${ + showSettingsPath ? "shown" : "hidden" + }`, () => { + const component = renderComponent( + previewSwitchDisabled, + previewSwitchIsUpdating, + previewSwitchValue, + reminderSwitchDisabled, + reminderSwitchIsUpdating, + reminderSwitchValue, + showSettingsPath + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + }); +}); + +const renderComponent = ( + previewSwitchDisabled: boolean, + previewSwitchIsUpdating: boolean, + previewSwitchValue: boolean, + reminderSwitchDisabled: boolean, + reminderSwitchIsUpdating: boolean, + reminderSwitchValue: boolean, + showSettingsPath: boolean +) => { + const globalState = appReducer(undefined, applicationChangeState("active")); + const dsEnabledState = appReducer( + globalState, + preferencesDesignSystemSetEnabled({ isDesignSystemEnabled: true }) + ); + const store = createStore(appReducer, dsEnabledState as any); + + return renderScreenWithNavigationStoreContext( + () => ( + + ), + ROUTES.PROFILE_PREFERENCES_NOTIFICATIONS, + {}, + store + ); +}; diff --git a/ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap b/ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap new file mode 100644 index 00000000000..0cef56ee170 --- /dev/null +++ b/ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap @@ -0,0 +1,162113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview off, reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview not updating, preview on , reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview off, reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview disabled, preview updating , preview on , reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview off, reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview not updating, preview on , reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview off, reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder disabled, reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder not updating, reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder not updating, reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder not updating, reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder not updating, reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder updating , reminder off, settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder updating , reminder off, settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder updating , reminder on , settings path hidden 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; + +exports[`ProfileNotificationSettings should match snapshot, preview enabled , preview updating , preview on , reminder enabled , reminder updating , reminder on , settings path shown 1`] = ` + + + + + + + + + + + + + + + PROFILE_PREFERENCES_NOTIFICATIONS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + + + + + + + + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + + + + + + + + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + + + + + + You can change this choice anytime in Profile > Preferences + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + +`; diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx index bb9a2eb35bb..692ab9a00c6 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsPreferencesScreen.tsx @@ -1,14 +1,10 @@ -import * as pot from "@pagopa/ts-commons/lib/pot"; import React, { useEffect, useState } from "react"; import { ScrollView, StyleSheet, View } from "react-native"; import { - Divider, VSpacer, ContentWrapper, IOStyles, ButtonSolid, - ListItemSwitch, - FeatureInfo, useIOToast, H1, Body @@ -21,8 +17,10 @@ import { IOStackNavigationRouteProps } from "../../../navigation/params/AppParam import { OnboardingParamsList } from "../../../navigation/params/OnboardingParamsList"; import { profileUpsert } from "../../../store/actions/profile"; import { useIODispatch, useIOSelector, useIOStore } from "../../../store/hooks"; -import { profilePreferencesSelector } from "../../../store/reducers/profile"; -import { usePreviewMoreInfo } from "../hooks/usePreviewMoreInfo"; +import { + profileHasErrorSelector, + profileIsUpdatingSelector +} from "../../../store/reducers/profile"; import { useOnFirstRender } from "../../../utils/hooks/useOnFirstRender"; import { getFlowType } from "../../../utils/analytics"; import { @@ -31,9 +29,9 @@ import { trackNotificationsPreferencesPreviewStatus, trackNotificationsPreferencesReminderStatus } from "../../../screens/profile/analytics"; -import { NotificationsPreferencesPreview } from "../components/NotificationsPreferencesPreview"; import { useHeaderSecondLevel } from "../../../hooks/useHeaderSecondLevel"; import { useHardwareBackButton } from "../../../hooks/useHardwareBackButton"; +import { ProfileNotificationSettings } from "../components/ProfileNotificationsSettings"; const styles = StyleSheet.create({ scrollViewContainer: { @@ -58,11 +56,8 @@ export const OnboardingNotificationsPreferencesScreen = (props: Props) => { const [previewEnabled, setPreviewEnabled] = useState(true); const [remindersEnabled, setRemindersEnabled] = useState(true); - const preferences = useIOSelector(profilePreferencesSelector); - const { present, bottomSheet } = usePreviewMoreInfo(); - - const isError = pot.isError(preferences); - const isUpdating = pot.isUpdating(preferences); + const isError = useIOSelector(profileHasErrorSelector); + const isUpdating = useIOSelector(profileIsUpdatingSelector); const { isFirstOnboarding } = props.route.params; @@ -126,45 +121,17 @@ export const OnboardingNotificationsPreferencesScreen = (props: Props) => {

{I18n.t("profile.preferences.notifications.title")}

{I18n.t("profile.preferences.notifications.subtitle")} - - - - - - - - - { onPress={upsertPreferences} /> - {bottomSheet} ); }; diff --git a/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap index 431d528aeca..92466e39514 100644 --- a/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap +++ b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap @@ -1041,6 +1041,77 @@ exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not } } /> + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + +
@@ -1176,77 +1247,6 @@ exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not - - - - - If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. - - - - + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + @@ -2665,77 +2736,6 @@ exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not - - - - - If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. - - - - + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + @@ -4154,92 +4225,21 @@ exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not - + + - - - - If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. - - - - - - - - + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + @@ -5643,77 +5714,6 @@ exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not - - - - - If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. - - - - - + + "transform": Array [ + Object { + "rotateZ": "0deg", + }, + ], + } + } + testID="LoadingSpinnerAnimatedTestID" + > + + + + + + + + + + + + + + + - + + "transform": Array [ + Object { + "rotateZ": "0deg", + }, + ], + } + } + testID="LoadingSpinnerAnimatedTestID" + > + + + + + + + + + + + + + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + @@ -7269,77 +7634,6 @@ exports[`OnboardingNotificationsPreferencesScreen should match snapshot when upd - - - - - If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. - - - - { const dispatch = useIODispatch(); - const [isUpserting, setIsUpserting] = useState(false); - const preferences = useSelector(profilePreferencesSelector); + const toast = useIOToast(); + const [isUpsertingPreview, setIsUpsertingPreview] = useState(false); + const [isUpsertingReminders, setIsUpsertingReminders] = useState(false); - const reminder = pot.map(preferences, p => p.reminder); - const preview = pot.map(preferences, p => p.preview); - const isError = pot.isError(preferences); - const isUpdating = pot.isUpdating(preferences); - - const { present, bottomSheet } = usePreviewMoreInfo(); + const profileHasError = useIOSelector(profileHasErrorSelector); + const profileIsUpdating = useIOSelector(profileIsUpdatingSelector); + const previewSwitchIsOn = useIOSelector( + pushNotificationPreviewEnabledSelector + ); + const remindersSwitchIsOn = useIOSelector( + pushNotificationRemindersEnabledSelector + ); useOnFirstRender(() => { trackNotificationScreen(getFlowType(false, false)); }); useEffect(() => { - if (isError && isUpserting) { - showToast(I18n.t("profile.preferences.notifications.error")); + if (profileHasError && (isUpsertingPreview || isUpsertingReminders)) { + toast.error(I18n.t("profile.preferences.notifications.error")); } - if (!isUpdating) { - setIsUpserting(false); + if (!profileIsUpdating) { + if (isUpsertingPreview) { + setIsUpsertingPreview(false); + } + if (isUpsertingReminders) { + setIsUpsertingReminders(false); + } } - }, [isError, isUpdating, isUpserting]); + }, [ + isUpsertingPreview, + isUpsertingReminders, + profileHasError, + profileIsUpdating, + toast + ]); - const togglePreference = (type: string, value: T) => { - setIsUpserting(true); - dispatch(profileUpsert.request({ [type]: value })); - }; + const onPreviewValueChanged = useCallback( + (newValue: boolean) => { + trackNotificationsPreferencesPreviewStatus( + newValue, + getFlowType(false, false) + ); + setIsUpsertingPreview(true); + dispatch( + profileUpsert.request({ + push_notifications_content_type: newValue + ? PushNotificationsContentTypeEnum.FULL + : PushNotificationsContentTypeEnum.ANONYMOUS + }) + ); + }, + [dispatch] + ); + + const onReminderValueChanged = useCallback( + (newValue: boolean) => { + trackNotificationsPreferencesReminderStatus( + newValue, + getFlowType(false, false) + ); + setIsUpsertingReminders(true); + dispatch( + profileUpsert.request({ + reminder_status: newValue + ? ReminderStatusEnum.ENABLED + : ReminderStatusEnum.DISABLED + }) + ); + }, + [dispatch] + ); return ( - - { - trackNotificationsPreferencesPreviewStatus( - value, - getFlowType(false, false) - ); - togglePreference( - "push_notifications_content_type", - value - ? PushNotificationsContentTypeEnum.FULL - : PushNotificationsContentTypeEnum.ANONYMOUS - ); - }} - testID="previewPreferenceSwitch" - /> - } - /> - - { - trackNotificationsPreferencesReminderStatus( - value, - getFlowType(false, false) - ); - togglePreference( - "reminder_status", - value - ? ReminderStatusEnum.ENABLED - : ReminderStatusEnum.DISABLED - ); - }} - testID="remindersPreferenceSwitch" - /> - } + + - - - {bottomSheet} + ); }; diff --git a/ts/screens/profile/__test__/NotificationsPreferencesScreen.test.tsx b/ts/screens/profile/__test__/NotificationsPreferencesScreen.test.tsx index e7e20a576c0..e0ec7dcf761 100644 --- a/ts/screens/profile/__test__/NotificationsPreferencesScreen.test.tsx +++ b/ts/screens/profile/__test__/NotificationsPreferencesScreen.test.tsx @@ -1,151 +1,212 @@ import * as pot from "@pagopa/ts-commons/lib/pot"; import _ from "lodash"; -import configureMockStore from "redux-mock-store"; +import { createStore } from "redux"; import { PushNotificationsContentTypeEnum } from "../../../../definitions/backend/PushNotificationsContentType"; import { ReminderStatusEnum } from "../../../../definitions/backend/ReminderStatus"; 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 mockedProfile from "../../../__mocks__/initializedProfile"; import { NotificationsPreferencesScreen } from "../NotificationsPreferencesScreen"; +import { preferencesDesignSystemSetEnabled } from "../../../store/actions/persistedPreferences"; +import { InitializedProfile } from "../../../../definitions/backend/InitializedProfile"; describe("NotificationsPreferencesScreen", () => { - describe("given an undefined 'reminder_status'", () => { - it("then the switch should be off", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore({ - ...globalState, - profile: pot.some({ - ..._.omit(mockedProfile, "reminder_status") - }) - }); - expect(screen).not.toBeNull(); + it("given an undefined 'reminder_status' then the switch should be off", () => { + const screen = renderScreen(); + expect(screen).not.toBeNull(); - const toggle = screen.component.getByTestId("remindersPreferenceSwitch"); - expect(toggle.props.value).toBeFalsy(); - }); + const toggle = screen.getByTestId("remindersPreferenceSwitch"); + expect(toggle.props.value).toBeFalsy(); }); - describe("given an ENABLED 'reminder_status'", () => { - it("then the switch should be on", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore({ - ...globalState, - profile: pot.some({ - ...mockedProfile, - reminder_status: ReminderStatusEnum.ENABLED - }) - }); - expect(screen).not.toBeNull(); + it("given an ENABLED 'reminder_status'then the switch should be on", () => { + const screen = renderScreen(undefined, ReminderStatusEnum.ENABLED); + expect(screen).not.toBeNull(); - const toggle = screen.component.getByTestId("remindersPreferenceSwitch"); - expect(toggle.props.value).toBeTruthy(); - }); + const toggle = screen.getByTestId("remindersPreferenceSwitch"); + expect(toggle.props.value).toBeTruthy(); }); - describe("given a DISABLED 'reminder_status'", () => { - it("then the switch should be off", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore({ - ...globalState, - profile: pot.some({ - ...mockedProfile, - reminder_status: ReminderStatusEnum.DISABLED - }) - }); - expect(screen).not.toBeNull(); + it("given a DISABLED 'reminder_status' then the switch should be off", () => { + const screen = renderScreen(undefined, ReminderStatusEnum.DISABLED); + expect(screen).not.toBeNull(); - const toggle = screen.component.getByTestId("remindersPreferenceSwitch"); - expect(toggle.props.value).toBeFalsy(); - }); + const toggle = screen.getByTestId("remindersPreferenceSwitch"); + expect(toggle.props.value).toBeFalsy(); }); - describe("given an undefined 'push_notifications_content_type'", () => { - it("then the switch should be off", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore({ - ...globalState, - profile: pot.some({ - ..._.omit(mockedProfile, "push_notifications_content_type") - }) - }); - expect(screen).not.toBeNull(); + it("given an undefined 'push_notifications_content_type' then the switch should be off", () => { + const screen = renderScreen(); + expect(screen).not.toBeNull(); - const toggle = screen.component.getByTestId("previewPreferenceSwitch"); - expect(toggle.props.value).toBeFalsy(); - }); + const toggle = screen.getByTestId("previewsPreferenceSwitch"); + expect(toggle.props.value).toBeFalsy(); }); - describe("given a FULL 'push_notifications_content_type'", () => { - it("then the switch should be on", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore({ - ...globalState, - profile: pot.some({ - ...mockedProfile, - push_notifications_content_type: PushNotificationsContentTypeEnum.FULL - }) - }); - expect(screen).not.toBeNull(); + it("given a FULL 'push_notifications_content_type' then the switch should be on", () => { + const screen = renderScreen(PushNotificationsContentTypeEnum.FULL); + expect(screen).not.toBeNull(); - const toggle = screen.component.getByTestId("previewPreferenceSwitch"); - expect(toggle.props.value).toBeTruthy(); - }); + const toggle = screen.getByTestId("previewsPreferenceSwitch"); + expect(toggle.props.value).toBeTruthy(); }); - describe("given an ANONYMOUS 'push_notifications_content_type'", () => { - it("then the switch should be off", () => { - const globalState = appReducer( - undefined, - applicationChangeState("active") - ); - const screen = renderComponentMockStore({ - ...globalState, - profile: pot.some({ - ...mockedProfile, - push_notifications_content_type: - PushNotificationsContentTypeEnum.ANONYMOUS - }) - }); - expect(screen).not.toBeNull(); + it("given an ANONYMOUS 'push_notifications_content_type' then the switch should be off", () => { + const screen = renderScreen(PushNotificationsContentTypeEnum.ANONYMOUS); + expect(screen).not.toBeNull(); + + const toggle = screen.getByTestId("previewsPreferenceSwitch"); + expect(toggle.props.value).toBeFalsy(); + }); - const toggle = screen.component.getByTestId("previewPreferenceSwitch"); - expect(toggle.props.value).toBeFalsy(); - }); + it("should match snapshot, undefined preview, undefined reminder, not updating", () => { + const screen = renderScreen(undefined, undefined, false); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, undefined preview, undefined reminder, updating", () => { + const screen = renderScreen(undefined, undefined, true); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, undefined preview, disabled reminder, not updating", () => { + const screen = renderScreen(undefined, ReminderStatusEnum.DISABLED, false); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, undefined preview, disabled reminder, updating", () => { + const screen = renderScreen(undefined, ReminderStatusEnum.DISABLED, true); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, undefined preview, enabled reminder, not updating", () => { + const screen = renderScreen(undefined, ReminderStatusEnum.ENABLED, false); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, undefined preview, enabled reminder, updating", () => { + const screen = renderScreen(undefined, ReminderStatusEnum.ENABLED, true); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, disabled preview, undefined reminder, not updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.ANONYMOUS, + undefined, + false + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, disabled preview, undefined reminder, updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.ANONYMOUS, + undefined, + true + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, disabled preview, disabled reminder, not updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.ANONYMOUS, + ReminderStatusEnum.DISABLED, + false + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, disabled preview, disabled reminder, updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.ANONYMOUS, + ReminderStatusEnum.DISABLED, + true + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, disabled preview, enabled reminder, not updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.ANONYMOUS, + ReminderStatusEnum.ENABLED, + false + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, disabled preview, enabled reminder, updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.ANONYMOUS, + ReminderStatusEnum.ENABLED, + true + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, enabled preview, undefined reminder, not updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.FULL, + undefined, + false + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, enabled preview, undefined reminder, updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.FULL, + undefined, + true + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, enabled preview, disabled reminder, not updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.FULL, + ReminderStatusEnum.DISABLED, + false + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, enabled preview, disabled reminder, updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.FULL, + ReminderStatusEnum.DISABLED, + true + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, enabled preview, enabled reminder, not updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.FULL, + ReminderStatusEnum.ENABLED, + false + ); + expect(screen.toJSON()).toMatchSnapshot(); + }); + it("should match snapshot, enabled preview, enabled reminder, updating", () => { + const screen = renderScreen( + PushNotificationsContentTypeEnum.FULL, + ReminderStatusEnum.ENABLED, + true + ); + expect(screen.toJSON()).toMatchSnapshot(); }); }); -const renderComponentMockStore = (state: GlobalState) => { - const mockStore = configureMockStore(); - const store: ReturnType = mockStore({ - ...state - } as GlobalState); +const renderScreen = ( + previewValue?: PushNotificationsContentTypeEnum, + reminderValue?: ReminderStatusEnum, + isUpdatingProfile: boolean = false +) => { + const globalState = appReducer(undefined, applicationChangeState("active")); + const dsEnabledState = appReducer( + globalState, + preferencesDesignSystemSetEnabled({ isDesignSystemEnabled: true }) + ); + const profile = { + push_notifications_content_type: previewValue, + reminder_status: reminderValue + } as InitializedProfile; + const finalState = { + ...dsEnabledState, + profile: isUpdatingProfile ? pot.noneUpdating(profile) : pot.some(profile) + } as GlobalState; + const store = createStore(appReducer, finalState as any); - return { - component: renderScreenWithNavigationStoreContext( - NotificationsPreferencesScreen, - ROUTES.PROFILE_PREFERENCES_NOTIFICATIONS, - {}, - store - ), + return renderScreenWithNavigationStoreContext( + NotificationsPreferencesScreen, + ROUTES.PROFILE_PREFERENCES_NOTIFICATIONS, + {}, store - }; + ); }; diff --git a/ts/screens/profile/__test__/__snapshots__/NotificationsPreferencesScreen.test.tsx.snap b/ts/screens/profile/__test__/__snapshots__/NotificationsPreferencesScreen.test.tsx.snap new file mode 100644 index 00000000000..254d7838e79 --- /dev/null +++ b/ts/screens/profile/__test__/__snapshots__/NotificationsPreferencesScreen.test.tsx.snap @@ -0,0 +1,24715 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NotificationsPreferencesScreen should match snapshot, disabled preview, disabled reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, disabled preview, disabled reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, disabled preview, enabled reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, disabled preview, enabled reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, disabled preview, undefined reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, disabled preview, undefined reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, enabled preview, disabled reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, enabled preview, disabled reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, enabled preview, enabled reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, enabled preview, enabled reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a notice due soon + + + Log in to pay the notice issued by ACI + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, enabled preview, undefined reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, enabled preview, undefined reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + Comune di Ipazia + + + Summer camp registration is now open + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, undefined preview, disabled reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, undefined preview, disabled reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, undefined preview, enabled reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, undefined preview, enabled reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a notice due tomorrow + + + Log in to pay for it + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, undefined preview, undefined reminder, updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`NotificationsPreferencesScreen should match snapshot, undefined preview, undefined reminder, not updating 1`] = ` + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + Choose how to receive messages and reminders. + + + + + + + + + + + + + + + + + + + + + You have a new message + + + Open the app to read the content + + + + + + + + + + Show a preview + + + + + + + + + + Include the sender and subject of the message in the push notification + + + + More info + + + + + + + + Allow reminders + + + + + + + + + + Upon request of the sender, receive push notifications close to deadlines or when you have unread messages + + + + + + + + If this option is enabled, push notifications show the sender and subject of messages, even when the screen is locked. This information is processed by your OS manager and by third-party apps that may be running. + + + + + + + + + + + + + + + + + + + + + + + + Customize push notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; diff --git a/ts/store/reducers/__tests__/profile.test.ts b/ts/store/reducers/__tests__/profile.test.ts index d64d065d749..883e8081298 100644 --- a/ts/store/reducers/__tests__/profile.test.ts +++ b/ts/store/reducers/__tests__/profile.test.ts @@ -7,6 +7,8 @@ import { isProfileEmailValidatedSelector, isProfileFirstOnBoarding, profileEmailSelector, + profileHasErrorSelector, + profileIsUpdatingSelector, ProfileState, pushNotificationPreviewEnabledSelector, pushNotificationRemindersEnabledSelector @@ -608,3 +610,121 @@ describe("pushNotificationPreviewEnabledSelector", () => { expect(previewEnabled).toBe(true); }); }); + +describe("profileHasErrorSelector", () => { + it("should return false for a pot.none profile", () => { + const globalState = { + profile: pot.none + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(false); + }); + it("should return false for a pot.noneLoading profile", () => { + const globalState = { + profile: pot.noneLoading + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(false); + }); + it("should return false for a pot.noneUpdating profile", () => { + const globalState = { + profile: pot.noneUpdating({}) + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(false); + }); + it("should return true for a pot.error profile", () => { + const globalState = { + profile: pot.noneError(new ProfileError("test error")) + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(true); + }); + it("should return false for a pot.some profile", () => { + const globalState = { + profile: pot.some({}) + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(false); + }); + it("should return false for a pot.someLoading profile", () => { + const globalState = { + profile: pot.someLoading({}) + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(false); + }); + it("should return false for a pot.someUpdating profile", () => { + const globalState = { + profile: pot.someUpdating({}, {}) + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(false); + }); + it("should return true for a pot.none profile", () => { + const globalState = { + profile: pot.someError({}, new ProfileError("test error")) + } as GlobalState; + const hasError = profileHasErrorSelector(globalState); + expect(hasError).toBe(true); + }); +}); + +describe("profileIsUpdatingSelector", () => { + it("should return false for a pot.none profile", () => { + const globalState = { + profile: pot.none + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(false); + }); + it("should return false for a pot.noneLoading profile", () => { + const globalState = { + profile: pot.noneLoading + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(false); + }); + it("should return true for a pot.noneUpdating profile", () => { + const globalState = { + profile: pot.noneUpdating({}) + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(true); + }); + it("should return false for a pot.error profile", () => { + const globalState = { + profile: pot.noneError(new ProfileError("test error")) + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(false); + }); + it("should return false for a pot.some profile", () => { + const globalState = { + profile: pot.some({}) + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(false); + }); + it("should return false for a pot.someLoading profile", () => { + const globalState = { + profile: pot.someLoading({}) + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(false); + }); + it("should return true for a pot.someUpdating profile", () => { + const globalState = { + profile: pot.someUpdating({}, {}) + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(true); + }); + it("should return false for a pot.none profile", () => { + const globalState = { + profile: pot.someError({}, new ProfileError("test error")) + } as GlobalState; + const isUpdating = profileIsUpdatingSelector(globalState); + expect(isUpdating).toBe(false); + }); +}); diff --git a/ts/store/reducers/profile.ts b/ts/store/reducers/profile.ts index 950b2acc8f4..7372bbcfd89 100644 --- a/ts/store/reducers/profile.ts +++ b/ts/store/reducers/profile.ts @@ -185,19 +185,11 @@ export const isEmailValidatedSelector = createSelector( isEmailValidated => isEmailValidated ); -// return preferences -export const profilePreferencesSelector = createSelector( - profileSelector, - ( - profile: ProfileState - ): pot.Pot<{ reminder: boolean; preview: boolean }, Error> => - pot.map(profile, p => ({ - reminder: p.reminder_status === ReminderStatusEnum.ENABLED, - preview: - p.push_notifications_content_type === - PushNotificationsContentTypeEnum.FULL - })) -); +export const profileHasErrorSelector = (state: GlobalState) => + pipe(state.profile, pot.isError); + +export const profileIsUpdatingSelector = (state: GlobalState) => + pipe(state.profile, pot.isUpdating); export const pushNotificationRemindersEnabledSelector = (state: GlobalState) => pipe( From 4db3b1a54ed885b983637f795215aaffefdb2ec3 Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Tue, 7 May 2024 18:20:17 +0200 Subject: [PATCH 16/17] NOTIFICATION_PERMISSION profile/super property and checkNotificationsPreferencesSaga refactoring --- ...checkNotificationsPreferencesSaga.test.tsx | 382 +++++++++++++----- .../checkNotificationsPreferencesSaga.ts | 117 +++--- ...boardingNotificationsInfoScreenConsent.tsx | 11 +- ts/mixpanelConfig/profileProperties.ts | 9 +- ts/mixpanelConfig/superProperties.ts | 9 +- ts/screens/profile/analytics/index.ts | 5 + 6 files changed, 375 insertions(+), 158 deletions(-) diff --git a/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx b/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx index 433e02f9e7c..e3c9048b7b9 100644 --- a/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx +++ b/ts/features/pushNotifications/sagas/__tests__/checkNotificationsPreferencesSaga.test.tsx @@ -13,16 +13,46 @@ import { ServicesPreferencesModeEnum } from "../../../../../definitions/backend/ import { profileUpsert } from "../../../../store/actions/profile"; import { PushNotificationsContentTypeEnum } from "../../../../../definitions/backend/PushNotificationsContentType"; import { ReminderStatusEnum } from "../../../../../definitions/backend/ReminderStatus"; +import { + trackNotificationsOptInPreviewStatus, + trackNotificationsOptInReminderStatus +} from "../../analytics"; +import { updateMixpanelSuperProperties } from "../../../../mixpanelConfig/superProperties"; +import { updateMixpanelProfileProperties } from "../../../../mixpanelConfig/profileProperties"; + +const generateUserProfile = ( + hasDoneNotificationOptIn: boolean, + isFirstOnboarding: boolean +) => + ({ + push_notifications_content_type: hasDoneNotificationOptIn + ? PushNotificationsContentTypeEnum.FULL + : undefined, + reminder_status: hasDoneNotificationOptIn + ? ReminderStatusEnum.ENABLED + : undefined, + service_preferences_settings: { + mode: isFirstOnboarding + ? ServicesPreferencesModeEnum.LEGACY + : ServicesPreferencesModeEnum.AUTO + } + } as InitializedProfile); -const userProfile = { - service_preferences_settings: { - mode: ServicesPreferencesModeEnum.LEGACY +const profileUpsertResult = () => ({ + payload: { + newValue: { + push_notifications_content_type: PushNotificationsContentTypeEnum.FULL, + reminder_status: ReminderStatusEnum.ENABLED + } } -} as InitializedProfile; +}); describe("checkNotificationsPreferencesSaga", () => { - it("upon saga startup, it should ask for push notifications permission", () => { - testSaga(checkNotificationsPreferencesSaga, userProfile) + it("profile without notification settings, missing service configuration, device has no notification permissions, gives device notification permissions", () => { + const profile = generateUserProfile(false, true); + const profileUpsertOutput = profileUpsertResult(); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) .next() .call( NavigationService.dispatchNavigationAction, @@ -33,20 +63,36 @@ describe("checkNotificationsPreferencesSaga", () => { ) .next() .take(profileUpsert.success) - .next({ - payload: { - newValue: { - push_notifications_content_type: - PushNotificationsContentTypeEnum.FULL, - reminder_status: ReminderStatusEnum.ENABLED - } - } - }) - .call(checkNotificationPermissions); + .next(profileUpsertOutput) + .call( + trackNotificationsOptInPreviewStatus, + profileUpsertOutput.payload.newValue.push_notifications_content_type + ) + .next() + .call( + trackNotificationsOptInReminderStatus, + profileUpsertOutput.payload.newValue.reminder_status + ) + .next() + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); }); - - it("if the push notifications permission was given, the saga will terminate ", () => { - testSaga(checkNotificationsPreferencesSaga, userProfile) + it("profile without notification settings, missing service configuration, device has no notification permissions, denies device notification permissions", () => { + const profile = generateUserProfile(false, true); + const profileUpsertOutput = profileUpsertResult(); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) .next() .call( NavigationService.dispatchNavigationAction, @@ -57,24 +103,47 @@ describe("checkNotificationsPreferencesSaga", () => { ) .next() .take(profileUpsert.success) - .next({ - payload: { - newValue: { - push_notifications_content_type: - PushNotificationsContentTypeEnum.FULL, - reminder_status: ReminderStatusEnum.ENABLED - } - } - }) + .next(profileUpsertOutput) + .call( + trackNotificationsOptInPreviewStatus, + profileUpsertOutput.payload.newValue.push_notifications_content_type + ) + .next() + .call( + trackNotificationsOptInReminderStatus, + profileUpsertOutput.payload.newValue.reminder_status + ) + .next() .call(checkNotificationPermissions) - .next(true) + .next(false) + .call(requestNotificationPermissions) + .next(false) + .call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + }) + ) + .next() + .take(notificationsInfoScreenConsent) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.pop()) + .next() + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) .next() .isDone(); }); - - it("if the push notifications permission was not given and is first onboarding, the saga will request push notification permissions", () => { - testSaga(checkNotificationsPreferencesSaga, userProfile) + it("profile without notification settings, missing service configuration, device has notification permissions", () => { + const profile = generateUserProfile(false, true); + const profileUpsertOutput = profileUpsertResult(); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) .next() .call( NavigationService.dispatchNavigationAction, @@ -85,71 +154,144 @@ describe("checkNotificationsPreferencesSaga", () => { ) .next() .take(profileUpsert.success) - .next({ - payload: { - newValue: { - push_notifications_content_type: - PushNotificationsContentTypeEnum.FULL, - reminder_status: ReminderStatusEnum.ENABLED - } - } - }) + .next(profileUpsertOutput) + .call( + trackNotificationsOptInPreviewStatus, + profileUpsertOutput.payload.newValue.push_notifications_content_type + ) + .next() + .call( + trackNotificationsOptInReminderStatus, + profileUpsertOutput.payload.newValue.reminder_status + ) + .next() + .call(checkNotificationPermissions) + .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); + }); + it("profile has notification settings, missing service configuration, device has no notification permissions, gives device notification permissions", () => { + const profile = generateUserProfile(true, true); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) + .next() .call(checkNotificationPermissions) .next(false) - .call(requestNotificationPermissions); + .call(requestNotificationPermissions) + .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .isDone(); }); - - it("if the saga asks for push permissions and the user give them, the saga will terminate", () => { - testSaga(checkNotificationsPreferencesSaga, userProfile) + it("profile has notification settings, missing service configuration, device has no notification permissions, denies device notification permissions", () => { + const profile = generateUserProfile(true, true); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) + .next() + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(false) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .isDone(); + }); + it("profile has notification settings, missing service configuration, device has notification permissions", () => { + const profile = generateUserProfile(true, true); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) + .next() + .call(checkNotificationPermissions) + .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .isDone(); + }); + it("profile without notification settings, has service configuration, device has no notification permissions, gives device notification permissions", () => { + const profile = generateUserProfile(false, false); + const profileUpsertOutput = profileUpsertResult(); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) .next() .call( NavigationService.dispatchNavigationAction, CommonActions.navigate(ROUTES.ONBOARDING, { screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, - params: { isFirstOnboarding: true } + params: { isFirstOnboarding: false } }) ) .next() .take(profileUpsert.success) - .next({ - payload: { - newValue: { - push_notifications_content_type: - PushNotificationsContentTypeEnum.FULL, - reminder_status: ReminderStatusEnum.ENABLED - } - } - }) + .next(profileUpsertOutput) + .call( + trackNotificationsOptInPreviewStatus, + profileUpsertOutput.payload.newValue.push_notifications_content_type + ) + .next() + .call( + trackNotificationsOptInReminderStatus, + profileUpsertOutput.payload.newValue.reminder_status + ) + .next() .call(checkNotificationPermissions) .next(false) .call(requestNotificationPermissions) .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) .next() .isDone(); }); - - it("if the saga asks for push permissions and the user does not give them, the saga navigates to the Info Screen and waits for the notificationsInfoScreenConsent action", () => { - testSaga(checkNotificationsPreferencesSaga, userProfile) + it("profile without notification settings, has service configuration, device has no notification permissions, denies device notification permissions", () => { + const profile = generateUserProfile(false, false); + const profileUpsertOutput = profileUpsertResult(); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) .next() .call( NavigationService.dispatchNavigationAction, CommonActions.navigate(ROUTES.ONBOARDING, { screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, - params: { isFirstOnboarding: true } + params: { isFirstOnboarding: false } }) ) .next() .take(profileUpsert.success) - .next({ - payload: { - newValue: { - push_notifications_content_type: - PushNotificationsContentTypeEnum.FULL, - reminder_status: ReminderStatusEnum.ENABLED - } - } - }) + .next(profileUpsertOutput) + .call( + trackNotificationsOptInPreviewStatus, + profileUpsertOutput.payload.newValue.push_notifications_content_type + ) + .next() + .call( + trackNotificationsOptInReminderStatus, + profileUpsertOutput.payload.newValue.reminder_status + ) + .next() .call(checkNotificationPermissions) .next(false) .call(requestNotificationPermissions) @@ -161,44 +303,104 @@ describe("checkNotificationsPreferencesSaga", () => { }) ) .next() - .take(notificationsInfoScreenConsent); + .take(notificationsInfoScreenConsent) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.pop()) + .next() + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); }); - - it("if the saga is waiting for the notificationsInfoScreenConsent action and the latter is received, the saga terminates", () => { - testSaga(checkNotificationsPreferencesSaga, userProfile) + it("profile without notification settings, has service configuration, device has notification permissions", () => { + const profile = generateUserProfile(false, false); + const profileUpsertOutput = profileUpsertResult(); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) .next() .call( NavigationService.dispatchNavigationAction, CommonActions.navigate(ROUTES.ONBOARDING, { screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, - params: { isFirstOnboarding: true } + params: { isFirstOnboarding: false } }) ) .next() .take(profileUpsert.success) - .next({ - payload: { - newValue: { - push_notifications_content_type: - PushNotificationsContentTypeEnum.FULL, - reminder_status: ReminderStatusEnum.ENABLED - } - } - }) + .next(profileUpsertOutput) + .call( + trackNotificationsOptInPreviewStatus, + profileUpsertOutput.payload.newValue.push_notifications_content_type + ) + .next() + .call( + trackNotificationsOptInReminderStatus, + profileUpsertOutput.payload.newValue.reminder_status + ) + .next() + .call(checkNotificationPermissions) + .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .next() + .isDone(); + }); + it("profile has notification settings, has service configuration, device has no notification permissions, gives device notification permissions", () => { + const profile = generateUserProfile(true, false); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) + .next() + .call(checkNotificationPermissions) + .next(false) + .call(requestNotificationPermissions) + .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) + .next() + .isDone(); + }); + it("profile has notification settings, has service configuration, device has no notification permissions, denies device notification permissions", () => { + const profile = generateUserProfile(true, false); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) + .next() .call(checkNotificationPermissions) .next(false) .call(requestNotificationPermissions) .next(false) - .call( - NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT - }) - ) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) .next() - .take(notificationsInfoScreenConsent) + .call(updateMixpanelProfileProperties, globalState) .next() - .call(NavigationService.dispatchNavigationAction, StackActions.popToTop()) + .isDone(); + }); + it("profile has notification settings, has service configuration, device has notification permissions", () => { + const profile = generateUserProfile(true, false); + const globalState = {}; + testSaga(checkNotificationsPreferencesSaga, profile) + .next() + .call(checkNotificationPermissions) + .next(true) + .select() + .next(globalState) + .call(updateMixpanelSuperProperties, globalState) + .next() + .call(updateMixpanelProfileProperties, globalState) .next() .isDone(); }); diff --git a/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts index 76704efcf5c..be47582e899 100644 --- a/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts +++ b/ts/features/pushNotifications/sagas/checkNotificationsPreferencesSaga.ts @@ -1,5 +1,5 @@ import { CommonActions, StackActions } from "@react-navigation/native"; -import { call, take } from "typed-redux-saga/macro"; +import { call, select, take } from "typed-redux-saga/macro"; import { ActionType } from "typesafe-actions"; import { InitializedProfile } from "../../../../definitions/backend/InitializedProfile"; import NavigationService from "../../../navigation/NavigationService"; @@ -16,84 +16,89 @@ import { } from "../analytics"; import { SagaCallReturnType } from "../../../types/utils"; import { notificationsInfoScreenConsent } from "../store/actions/notifications"; +import { updateMixpanelSuperProperties } from "../../../mixpanelConfig/superProperties"; +import { GlobalState } from "../../../store/reducers/types"; +import { updateMixpanelProfileProperties } from "../../../mixpanelConfig/profileProperties"; export function* checkNotificationsPreferencesSaga( userProfile: InitializedProfile ) { - const isFirstOnboarding = isProfileFirstOnBoarding(userProfile); - - // Check if the user has already set a preference for push notification opt-in - if ( - userProfile.reminder_status !== undefined && - userProfile.push_notifications_content_type !== undefined - ) { - // Make sure to ask for push notification permissions. This call is needed - // since an existing user that has already opted-in may be running the - // application on a new device. To enable the push receival, the system - // permission must be asked explicitly and this is the first entry point - // where it makes sense to do so. If the user denies the permission, - // the popup dialog does not appear anymore (on following application restarts). - yield* call(requestNotificationPermissions); - - return; - } - - // show the opt-in screen - yield* call( - NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, - params: { isFirstOnboarding } - }) - ); - - // wait for the notifications preferences to be set - while (true) { - const action = yield* take>( - profileUpsert.success + const profileMissedPushSettings = + !userProfile.reminder_status || + !userProfile.push_notifications_content_type; + if (profileMissedPushSettings) { + // Show the opt-in screen (this properties are not related to the system + // permission to receive notifications) + const isFirstOnboarding = isProfileFirstOnBoarding(userProfile); + yield* call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_PREFERENCES, + params: { isFirstOnboarding } + }) ); - const contentType = action.payload.newValue.push_notifications_content_type; - const reminderStatus = action.payload.newValue.reminder_status; - if (reminderStatus !== undefined && contentType !== undefined) { - trackNotificationsOptInPreviewStatus(contentType); - trackNotificationsOptInReminderStatus(reminderStatus); - break; + // wait for the notifications preferences to be set + while (true) { + const action = yield* take>( + profileUpsert.success + ); + + const contentType = + action.payload.newValue.push_notifications_content_type; + const reminderStatus = action.payload.newValue.reminder_status; + if (reminderStatus !== undefined && contentType !== undefined) { + yield* call(trackNotificationsOptInPreviewStatus, contentType); + yield* call(trackNotificationsOptInReminderStatus, reminderStatus); + break; + } } } // check if the user has given system notification permissions - const authorizationStatus: SagaCallReturnType< + const hasNotificationPermission: SagaCallReturnType< typeof checkNotificationPermissions > = yield* call(checkNotificationPermissions); - if (!authorizationStatus) { - const permissionStatus: SagaCallReturnType< + if (!hasNotificationPermission) { + // Ask the user for notification permission + const userHasGivenNotificationPermission: SagaCallReturnType< typeof requestNotificationPermissions > = yield* call(requestNotificationPermissions); - if (permissionStatus) { + if (!userHasGivenNotificationPermission && profileMissedPushSettings) { + // Show how to enable notification permission from the settings + // Be aware that this is modal on top of the OptIn-Screen and + // it will never be shown if the user has not been through it + yield* call( + NavigationService.dispatchNavigationAction, + CommonActions.navigate(ROUTES.ONBOARDING, { + screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT + }) + ); + + yield* take>( + notificationsInfoScreenConsent + ); + + // Make sure to dismiss the modal yield* call( NavigationService.dispatchNavigationAction, - StackActions.popToTop() + StackActions.pop() ); - return; } + } + // Update mixpanel super and profile properties + // (mainly for the notification permission) + const state = (yield* select()) as GlobalState; + yield* call(updateMixpanelSuperProperties, state); + yield* call(updateMixpanelProfileProperties, state); + + if (profileMissedPushSettings) { yield* call( NavigationService.dispatchNavigationAction, - CommonActions.navigate(ROUTES.ONBOARDING, { - screen: ROUTES.ONBOARDING_NOTIFICATIONS_INFO_SCREEN_CONSENT - }) - ); - - yield* take>( - notificationsInfoScreenConsent + StackActions.popToTop() ); } - - yield* call( - NavigationService.dispatchNavigationAction, - StackActions.popToTop() - ); } diff --git a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx index 8201ae2404b..23f151cf962 100644 --- a/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx +++ b/ts/features/pushNotifications/screens/OnboardingNotificationsInfoScreenConsent.tsx @@ -12,7 +12,6 @@ import { ListItemInfo, VSpacer } from "@pagopa/io-app-design-system"; -import { useNavigation } from "@react-navigation/native"; import I18n from "../../../i18n"; import { openAppSettings } from "../../../utils/appSettings"; import { useIODispatch, useIOSelector } from "../../../store/hooks"; @@ -43,7 +42,6 @@ const styles = StyleSheet.create({ }); export const OnboardingNotificationsInfoScreenConsent = () => { - const navigation = useNavigation(); const dispatch = useIODispatch(); const remindersEnabled = useIOSelector( pushNotificationRemindersEnabledSelector @@ -126,15 +124,8 @@ export const OnboardingNotificationsInfoScreenConsent = () => { ); const closeModalAndScreen = useCallback(() => { - // Dismiss the modal (the check on `canGoBack` avoids - // a logged error when running tests, since in that - // case there is no screen below on the navigation stack) - if (navigation.canGoBack()) { - navigation.goBack(); - } - dispatch(notificationsInfoScreenConsent()); - }, [dispatch, navigation]); + }, [dispatch]); useEffect(() => { const subscription = AppState.addEventListener( diff --git a/ts/mixpanelConfig/profileProperties.ts b/ts/mixpanelConfig/profileProperties.ts index 1b04aec31f0..51eefe1c686 100644 --- a/ts/mixpanelConfig/profileProperties.ts +++ b/ts/mixpanelConfig/profileProperties.ts @@ -4,11 +4,14 @@ import { GlobalState } from "../store/reducers/types"; import { LoginSessionDuration } from "../features/fastLogin/analytics/optinAnalytics"; import { BiometricsType, getBiometricsType } from "../utils/biometrics"; import { + NotificationPermissionType, NotificationPreferenceConfiguration, - ServiceConfigurationTrackingType + ServiceConfigurationTrackingType, + getNotificationPermissionType } from "../screens/profile/analytics"; import { idpSelector } from "../store/reducers/authentication"; import { tosVersionSelector } from "../store/reducers/profile"; +import { checkNotificationPermissions } from "../features/pushNotifications/utils"; import { Property, PropertyToUpdate, @@ -23,6 +26,7 @@ type ProfileProperties = { TOS_ACCEPTED_VERSION: number | string; BIOMETRIC_TECHNOLOGY: BiometricsType; NOTIFICATION_CONFIGURATION: NotificationPreferenceConfiguration; + NOTIFICATION_PERMISSION: NotificationPermissionType; SERVICE_CONFIGURATION: ServiceConfigurationTrackingType; }; @@ -38,6 +42,7 @@ export const updateMixpanelProfileProperties = async ( const TOS_ACCEPTED_VERSION = tosVersionHandler(state); const BIOMETRIC_TECHNOLOGY = await getBiometricsType(); const NOTIFICATION_CONFIGURATION = notificationConfigurationHandler(state); + const notificationsEnabled = await checkNotificationPermissions(); const SERVICE_CONFIGURATION = serviceConfigHandler(state); const profilePropertiesObject: ProfileProperties = { @@ -46,6 +51,8 @@ export const updateMixpanelProfileProperties = async ( TOS_ACCEPTED_VERSION, BIOMETRIC_TECHNOLOGY, NOTIFICATION_CONFIGURATION, + NOTIFICATION_PERMISSION: + getNotificationPermissionType(notificationsEnabled), SERVICE_CONFIGURATION }; diff --git a/ts/mixpanelConfig/superProperties.ts b/ts/mixpanelConfig/superProperties.ts index c263b2285f2..c1e8cbea804 100644 --- a/ts/mixpanelConfig/superProperties.ts +++ b/ts/mixpanelConfig/superProperties.ts @@ -7,14 +7,17 @@ import { } from "../utils/device"; import { BiometricsType, getBiometricsType } from "../utils/biometrics"; import { + NotificationPermissionType, NotificationPreferenceConfiguration, - ServiceConfigurationTrackingType + ServiceConfigurationTrackingType, + getNotificationPermissionType } from "../screens/profile/analytics"; import { GlobalState } from "../store/reducers/types"; import { mixpanel } from "../mixpanel"; import { LoginSessionDuration } from "../features/fastLogin/analytics/optinAnalytics"; +import { checkNotificationPermissions } from "../features/pushNotifications/utils"; import { Property, PropertyToUpdate, @@ -32,6 +35,7 @@ type SuperProperties = { isScreenLockSet: boolean; LOGIN_SESSION: LoginSessionDuration; NOTIFICATION_CONFIGURATION: NotificationPreferenceConfiguration; + NOTIFICATION_PERMISSION: NotificationPermissionType; SERVICE_CONFIGURATION: ServiceConfigurationTrackingType; }; @@ -49,6 +53,7 @@ export const updateMixpanelSuperProperties = async ( const isScreenLockSet = await isScreenLockSetFunc(); const LOGIN_SESSION = loginSessionConfigHandler(state); const NOTIFICATION_CONFIGURATION = notificationConfigurationHandler(state); + const notificationsEnabled = await checkNotificationPermissions(); const SERVICE_CONFIGURATION = serviceConfigHandler(state); const superPropertiesObject: SuperProperties = { @@ -60,6 +65,8 @@ export const updateMixpanelSuperProperties = async ( isScreenLockSet, LOGIN_SESSION, NOTIFICATION_CONFIGURATION, + NOTIFICATION_PERMISSION: + getNotificationPermissionType(notificationsEnabled), SERVICE_CONFIGURATION }; diff --git a/ts/screens/profile/analytics/index.ts b/ts/screens/profile/analytics/index.ts index ec450dc03ae..4d3a2374fe3 100644 --- a/ts/screens/profile/analytics/index.ts +++ b/ts/screens/profile/analytics/index.ts @@ -191,6 +191,11 @@ export function getNotificationPreferenceConfiguration( return "none"; } +export type NotificationPermissionType = "enabled" | "disabled"; + +export const getNotificationPermissionType = (hasPermission: boolean) => + hasPermission ? "enabled" : "disabled"; + export async function trackNotificationPreferenceConfiguration( isReminderEnabled: boolean, isPreviewEnabled: boolean, From 4f282a856035fd5e7032d358d88611a34107c3fa Mon Sep 17 00:00:00 2001 From: Andrea Piai Date: Fri, 10 May 2024 12:11:23 +0200 Subject: [PATCH 17/17] Update settings component --- locales/it/index.yml | 2 +- package.json | 2 +- ...MessageDetailsAttachmentItem.test.tsx.snap | 8 +- .../MessageDetailsFooter.test.tsx.snap | 24 +- .../MessageDetailsPayment.test.tsx.snap | 2 +- .../MessageDetailsReminder.test.tsx.snap | 234 +- ...essageDetailsReminderExpired.test.tsx.snap | 117 +- ...ssageDetailsReminderExpiring.test.tsx.snap | 117 +- .../MessagePaymentItem.test.tsx.snap | 6 +- .../ShowMoreListItem.test.tsx.snap | 58 +- .../F24ListBottomSheetLink.test.tsx.snap | 22 +- .../__snapshots__/F24Section.test.tsx.snap | 6 +- .../LegacyMessageF24.test.tsx.snap | 2 +- .../LegacyMessagePayments.test.tsx.snap | 48 +- .../MessageBottomMenu.test.tsx.snap | 1280 +- .../MessageCancelledContent.test.tsx.snap | 1053 +- .../MessageDetails.test.tsx.snap | 14 +- .../__snapshots__/MessageInfo.test.tsx.snap | 2 +- .../MessagePaymentBottomSheet.test.tsx.snap | 14 +- .../MessagePayments.test.tsx.snap | 72 +- .../TimelineListItem.test.tsx.snap | 8 +- .../LegacyPaidPaymentScreen.test.tsx.snap | 6 +- .../MessageDetailsScreen.test.tsx.snap | 18 +- .../ProfileNotificationsSettings.tsx | 12 +- ...ProfileNotificationsSettings.test.tsx.snap | 17408 +++++++++++----- ...tificationsInfoScreenConsent.test.tsx.snap | 6 +- ...tificationsPreferencesScreen.test.tsx.snap | 1512 +- yarn.lock | 10 +- 28 files changed, 15180 insertions(+), 6883 deletions(-) diff --git a/locales/it/index.yml b/locales/it/index.yml index 6cfaf00d3c9..4e704690fe5 100644 --- a/locales/it/index.yml +++ b/locales/it/index.yml @@ -411,7 +411,7 @@ profile: additionalInformation: description: "Per maggiori informazioni, leggi " cta: "l’Informativa Privacy e i Termini e Condizioni d’uso" - profileSettings: "Potrai modificare questa scelta in ogni momento su Profilo > Preferenze" + profileSettings: "Puoi modificare la tua scelta in ogni momento da Profilo > Preferenze" cta: shareData: "Condividi" dontShareData: "Non condividere dati" diff --git a/package.json b/package.json index 60cb60371c1..18adce81b53 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "dependencies": { "@babel/plugin-transform-regenerator": "^7.18.6", "@gorhom/bottom-sheet": "^4.1.5", - "@pagopa/io-app-design-system": "1.36.9", + "@pagopa/io-app-design-system": "1.36.10", "@pagopa/io-pagopa-commons": "^3.1.0", "@pagopa/io-react-native-crypto": "^0.3.0", "@pagopa/io-react-native-http-client": "^0.1.3", diff --git a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsAttachmentItem.test.tsx.snap b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsAttachmentItem.test.tsx.snap index 4176e76694d..a50279b7929 100644 --- a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsAttachmentItem.test.tsx.snap +++ b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsAttachmentItem.test.tsx.snap @@ -473,7 +473,7 @@ exports[`MessageDetailsAttachmentItem Should match snapshot when is fetching the style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1143,7 +1143,7 @@ exports[`MessageDetailsAttachmentItem Should match snapshot when the attachment style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1696,7 +1696,7 @@ exports[`MessageDetailsAttachmentItem Should match snapshot with all parameters style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -2256,7 +2256,7 @@ exports[`MessageDetailsAttachmentItem Should match snapshot with required parame style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > diff --git a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsFooter.test.tsx.snap b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsFooter.test.tsx.snap index 127ae6521cd..89df265c7a1 100644 --- a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsFooter.test.tsx.snap +++ b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsFooter.test.tsx.snap @@ -394,7 +394,7 @@ exports[`MessageDetailsFooter component should match the snapshot, no service's @@ -896,7 +896,7 @@ exports[`MessageDetailsFooter component should match the snapshot, no service's @@ -1398,7 +1398,7 @@ exports[`MessageDetailsFooter component should match the snapshot, no service's @@ -1900,7 +1900,7 @@ exports[`MessageDetailsFooter component should match the snapshot, no service's @@ -2402,7 +2402,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' @@ -2550,7 +2550,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' @@ -3052,7 +3052,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' @@ -3200,7 +3200,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' @@ -3702,7 +3702,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' @@ -3850,7 +3850,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' @@ -4352,7 +4352,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' @@ -4500,7 +4500,7 @@ exports[`MessageDetailsFooter component should match the snapshot, with service' diff --git a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsPayment.test.tsx.snap b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsPayment.test.tsx.snap index f761539d0c9..a852f054a1a 100644 --- a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsPayment.test.tsx.snap +++ b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsPayment.test.tsx.snap @@ -882,7 +882,7 @@ exports[`MessageDetailsPayment Should match snapshot when there are payment data diff --git a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsReminder.test.tsx.snap b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsReminder.test.tsx.snap index 5ebf65189dc..9fbfd65244c 100644 --- a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsReminder.test.tsx.snap +++ b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/MessageDetailsReminder.test.tsx.snap @@ -1391,73 +1391,74 @@ exports[`MessageDetailsReminder should match snapshot when the reminder is visib ] } > - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + @@ -896,7 +896,7 @@ exports[`MessagePaymentItem component Should match the snapshot for a payable it "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1460,7 +1460,7 @@ exports[`MessagePaymentItem component Should match the snapshot for a processed "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, diff --git a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/ShowMoreListItem.test.tsx.snap b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/ShowMoreListItem.test.tsx.snap index faaec832402..01a988440c1 100644 --- a/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/ShowMoreListItem.test.tsx.snap +++ b/ts/features/messages/components/MessageDetail/__tests__/__snapshots__/ShowMoreListItem.test.tsx.snap @@ -373,7 +373,7 @@ exports[`ShowMoreListItem should match snapshot, no data 1`] = ` @@ -897,7 +897,7 @@ exports[`ShowMoreListItem should match snapshot, one section, no items 1`] = ` @@ -1489,7 +1489,7 @@ exports[`ShowMoreListItem should match snapshot, one section, one item, no icon @@ -1812,7 +1812,7 @@ exports[`ShowMoreListItem should match snapshot, one section, one item, no icon @@ -2270,7 +2270,7 @@ exports[`ShowMoreListItem should match snapshot, one section, one item, with ico @@ -2524,7 +2524,7 @@ exports[`ShowMoreListItem should match snapshot, one section, one item, with ico @@ -2661,7 +2661,7 @@ exports[`ShowMoreListItem should match snapshot, one section, one item, with ico @@ -3119,7 +3119,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, no icon @@ -3442,7 +3442,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, no icon @@ -3639,7 +3639,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, no icon @@ -4097,7 +4097,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, with ic @@ -4351,7 +4351,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, with ic @@ -4488,7 +4488,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, with ic @@ -4616,7 +4616,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, with ic @@ -4753,7 +4753,7 @@ exports[`ShowMoreListItem should match snapshot, one section, two items, with ic @@ -5211,7 +5211,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -5534,7 +5534,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -5790,7 +5790,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -5918,7 +5918,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -6055,7 +6055,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -6311,7 +6311,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -6439,7 +6439,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -6576,7 +6576,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -6773,7 +6773,7 @@ exports[`ShowMoreListItem should match snapshot, three sections, different item @@ -7231,7 +7231,7 @@ exports[`ShowMoreListItem should match snapshot, two sections, different item co @@ -7554,7 +7554,7 @@ exports[`ShowMoreListItem should match snapshot, two sections, different item co @@ -7810,7 +7810,7 @@ exports[`ShowMoreListItem should match snapshot, two sections, different item co @@ -7938,7 +7938,7 @@ exports[`ShowMoreListItem should match snapshot, two sections, different item co @@ -8075,7 +8075,7 @@ exports[`ShowMoreListItem should match snapshot, two sections, different item co diff --git a/ts/features/pn/components/__test__/__snapshots__/F24ListBottomSheetLink.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/F24ListBottomSheetLink.test.tsx.snap index 398ffe0de40..8118fb567e7 100644 --- a/ts/features/pn/components/__test__/__snapshots__/F24ListBottomSheetLink.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/F24ListBottomSheetLink.test.tsx.snap @@ -609,7 +609,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -837,7 +837,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1065,7 +1065,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1293,7 +1293,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1521,7 +1521,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1749,7 +1749,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1977,7 +1977,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -2205,7 +2205,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -2433,7 +2433,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -2661,7 +2661,7 @@ exports[`F24ListBottomSheetLink should be snapshot for a 10 items F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -3827,7 +3827,7 @@ exports[`F24ListBottomSheetLink should be snapshot for an 1 item F24 list 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > diff --git a/ts/features/pn/components/__test__/__snapshots__/F24Section.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/F24Section.test.tsx.snap index 887d8e39f3e..f52758e718e 100644 --- a/ts/features/pn/components/__test__/__snapshots__/F24Section.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/F24Section.test.tsx.snap @@ -781,7 +781,7 @@ exports[`F24Section should match snapshot when there are more than one F24 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1009,7 +1009,7 @@ exports[`F24Section should match snapshot when there are more than one F24 1`] = style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -2739,7 +2739,7 @@ exports[`F24Section should match snapshot when there is a single F24 1`] = ` style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > diff --git a/ts/features/pn/components/__test__/__snapshots__/LegacyMessageF24.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/LegacyMessageF24.test.tsx.snap index d032caefb76..661006dd614 100644 --- a/ts/features/pn/components/__test__/__snapshots__/LegacyMessageF24.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/LegacyMessageF24.test.tsx.snap @@ -1101,7 +1101,7 @@ exports[`MessageF24 component when there is only one F24 should match the snapsh "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, } } > diff --git a/ts/features/pn/components/__test__/__snapshots__/LegacyMessagePayments.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/LegacyMessagePayments.test.tsx.snap index a8efbdad88b..40711a1c1eb 100644 --- a/ts/features/pn/components/__test__/__snapshots__/LegacyMessagePayments.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/LegacyMessagePayments.test.tsx.snap @@ -962,7 +962,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for a cancell "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1208,7 +1208,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for a cancell "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1454,7 +1454,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for a cancell "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -2111,7 +2111,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for a single @@ -2681,7 +2681,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five load @@ -2797,7 +2797,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five load @@ -2913,7 +2913,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five load @@ -3029,7 +3029,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five load @@ -3145,7 +3145,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five load @@ -3715,7 +3715,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five paya @@ -3831,7 +3831,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five paya @@ -3947,7 +3947,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five paya @@ -4063,7 +4063,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five paya @@ -4179,7 +4179,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five paya @@ -4749,7 +4749,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five proc @@ -4865,7 +4865,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five proc @@ -4981,7 +4981,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five proc @@ -5097,7 +5097,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five proc @@ -5213,7 +5213,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for five proc @@ -5783,7 +5783,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for more than @@ -5899,7 +5899,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for more than @@ -6015,7 +6015,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for more than @@ -6131,7 +6131,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for more than @@ -6247,7 +6247,7 @@ exports[`LegacyMessagePayments component Should match the snapshot for more than diff --git a/ts/features/pn/components/__test__/__snapshots__/MessageBottomMenu.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/MessageBottomMenu.test.tsx.snap index e1301a96fce..907d4a8ff7b 100644 --- a/ts/features/pn/components/__test__/__snapshots__/MessageBottomMenu.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/MessageBottomMenu.test.tsx.snap @@ -383,7 +383,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -2666,7 +2666,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -2920,7 +2920,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -3057,7 +3057,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -3244,7 +3244,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -3381,7 +3381,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -3850,7 +3850,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -6133,7 +6133,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -6387,7 +6387,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -6524,7 +6524,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -6711,7 +6711,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -6848,7 +6848,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -7035,7 +7035,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -7172,7 +7172,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -7641,7 +7641,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -9924,7 +9924,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -10178,7 +10178,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -10315,7 +10315,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -10502,7 +10502,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -10639,7 +10639,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -11108,7 +11108,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -13391,7 +13391,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -13645,7 +13645,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -13782,7 +13782,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -13969,7 +13969,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -14106,7 +14106,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -14575,7 +14575,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -16858,7 +16858,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -17112,7 +17112,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -17249,7 +17249,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -17436,7 +17436,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -17573,7 +17573,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -18042,7 +18042,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -20325,7 +20325,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -20579,7 +20579,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -20716,7 +20716,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -20903,7 +20903,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -21040,7 +21040,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -21509,7 +21509,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -23792,7 +23792,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -24046,7 +24046,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -24183,7 +24183,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -24370,7 +24370,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -24507,7 +24507,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -24976,7 +24976,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -27259,7 +27259,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -27513,7 +27513,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -27650,7 +27650,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -27837,7 +27837,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -27974,7 +27974,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -28443,7 +28443,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -30726,7 +30726,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -30980,7 +30980,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -31117,7 +31117,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -31304,7 +31304,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -31441,7 +31441,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -31910,7 +31910,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -34193,7 +34193,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -34447,7 +34447,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -34584,7 +34584,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -34771,7 +34771,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -34908,7 +34908,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -35377,7 +35377,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -37660,7 +37660,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -37914,7 +37914,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -38051,7 +38051,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -38238,7 +38238,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -38375,7 +38375,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -38562,7 +38562,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -38699,7 +38699,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -39168,7 +39168,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -41451,7 +41451,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -41705,7 +41705,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -41842,7 +41842,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -42029,7 +42029,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -42166,7 +42166,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -42635,7 +42635,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -44918,7 +44918,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -45172,7 +45172,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -45309,7 +45309,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -45496,7 +45496,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -45633,7 +45633,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -45820,7 +45820,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -45957,7 +45957,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -46085,7 +46085,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -46222,7 +46222,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -46409,7 +46409,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -46546,7 +46546,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -46674,7 +46674,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -46811,7 +46811,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -46998,7 +46998,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -47135,7 +47135,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -47263,7 +47263,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -47400,7 +47400,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -47869,7 +47869,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -50152,7 +50152,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -50406,7 +50406,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -50543,7 +50543,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -50730,7 +50730,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -50867,7 +50867,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -51054,7 +51054,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -51191,7 +51191,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -51319,7 +51319,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -51456,7 +51456,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -51643,7 +51643,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -51780,7 +51780,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -51908,7 +51908,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -52045,7 +52045,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -52232,7 +52232,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -52369,7 +52369,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -52497,7 +52497,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -52634,7 +52634,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -53103,7 +53103,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -55386,7 +55386,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -55640,7 +55640,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -55777,7 +55777,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -55964,7 +55964,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -56101,7 +56101,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -56288,7 +56288,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -56425,7 +56425,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -56553,7 +56553,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -56690,7 +56690,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -56877,7 +56877,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -57014,7 +57014,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -57142,7 +57142,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -57279,7 +57279,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -57466,7 +57466,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -57603,7 +57603,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -57731,7 +57731,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -57868,7 +57868,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -58337,7 +58337,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -60620,7 +60620,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -60874,7 +60874,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -61011,7 +61011,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -61198,7 +61198,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -61335,7 +61335,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -61522,7 +61522,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -61659,7 +61659,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -61787,7 +61787,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -61924,7 +61924,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -62111,7 +62111,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -62248,7 +62248,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -62376,7 +62376,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -62513,7 +62513,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -62700,7 +62700,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -62837,7 +62837,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -62965,7 +62965,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -63102,7 +63102,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -63571,7 +63571,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -65854,7 +65854,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -66108,7 +66108,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -66245,7 +66245,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -66432,7 +66432,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -66569,7 +66569,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -66756,7 +66756,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -66893,7 +66893,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -67021,7 +67021,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -67158,7 +67158,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -67345,7 +67345,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -67482,7 +67482,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -67610,7 +67610,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -67747,7 +67747,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -67934,7 +67934,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -68071,7 +68071,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -68199,7 +68199,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -68336,7 +68336,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -68805,7 +68805,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -71088,7 +71088,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -71342,7 +71342,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -71479,7 +71479,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -71666,7 +71666,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -71803,7 +71803,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -71990,7 +71990,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -72127,7 +72127,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -72255,7 +72255,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -72392,7 +72392,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -72579,7 +72579,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -72716,7 +72716,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -72844,7 +72844,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -72981,7 +72981,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -73168,7 +73168,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -73305,7 +73305,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -73433,7 +73433,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -73570,7 +73570,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -74039,7 +74039,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -76322,7 +76322,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -76576,7 +76576,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -76713,7 +76713,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -76900,7 +76900,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -77037,7 +77037,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -77506,7 +77506,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -79789,7 +79789,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -80043,7 +80043,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -80180,7 +80180,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -80367,7 +80367,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -80504,7 +80504,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -80691,7 +80691,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -80828,7 +80828,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -81297,7 +81297,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -83580,7 +83580,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -83834,7 +83834,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -83971,7 +83971,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -84158,7 +84158,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -84295,7 +84295,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -84764,7 +84764,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -87047,7 +87047,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -87301,7 +87301,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -87438,7 +87438,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -87625,7 +87625,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -87762,7 +87762,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -87949,7 +87949,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -88086,7 +88086,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -88214,7 +88214,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -88351,7 +88351,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -88820,7 +88820,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -91103,7 +91103,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -91357,7 +91357,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -91494,7 +91494,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -91681,7 +91681,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -91818,7 +91818,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -92005,7 +92005,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -92142,7 +92142,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -92270,7 +92270,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -92407,7 +92407,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -92876,7 +92876,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -95159,7 +95159,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -95413,7 +95413,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -95550,7 +95550,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -95737,7 +95737,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -95874,7 +95874,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -96061,7 +96061,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -96198,7 +96198,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -96326,7 +96326,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -96463,7 +96463,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -96932,7 +96932,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -99215,7 +99215,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -99469,7 +99469,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -99606,7 +99606,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -99793,7 +99793,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -99930,7 +99930,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -100117,7 +100117,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -100254,7 +100254,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -100382,7 +100382,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -100519,7 +100519,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -100988,7 +100988,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -103271,7 +103271,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -103525,7 +103525,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -103662,7 +103662,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -103849,7 +103849,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -103986,7 +103986,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -104173,7 +104173,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -104310,7 +104310,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -104438,7 +104438,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -104575,7 +104575,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -105044,7 +105044,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -107327,7 +107327,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -107581,7 +107581,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -107718,7 +107718,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -107905,7 +107905,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -108042,7 +108042,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -108229,7 +108229,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -108366,7 +108366,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -108494,7 +108494,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -108631,7 +108631,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -109100,7 +109100,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -111383,7 +111383,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -111637,7 +111637,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -111774,7 +111774,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -111961,7 +111961,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -112098,7 +112098,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -112567,7 +112567,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -114850,7 +114850,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -115104,7 +115104,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -115241,7 +115241,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -115428,7 +115428,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -115565,7 +115565,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -115752,7 +115752,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -115889,7 +115889,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -116358,7 +116358,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -118641,7 +118641,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -118895,7 +118895,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -119032,7 +119032,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -119219,7 +119219,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -119356,7 +119356,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -119825,7 +119825,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -122108,7 +122108,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -122362,7 +122362,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -122499,7 +122499,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -122686,7 +122686,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -122823,7 +122823,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -123292,7 +123292,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -125575,7 +125575,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -125829,7 +125829,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -125966,7 +125966,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -126153,7 +126153,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -126290,7 +126290,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -126759,7 +126759,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -129042,7 +129042,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -129296,7 +129296,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -129433,7 +129433,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -129620,7 +129620,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -129757,7 +129757,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -130226,7 +130226,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -132509,7 +132509,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -132763,7 +132763,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -132900,7 +132900,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -133087,7 +133087,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -133224,7 +133224,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -133693,7 +133693,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -135976,7 +135976,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -136230,7 +136230,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -136367,7 +136367,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -136554,7 +136554,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -136691,7 +136691,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -137160,7 +137160,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -139443,7 +139443,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -139697,7 +139697,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -139834,7 +139834,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -140021,7 +140021,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -140158,7 +140158,7 @@ exports[`MessageBottomMenu should match snapshot, all handled-status items histo @@ -140627,7 +140627,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -140815,7 +140815,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -141069,7 +141069,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -141206,7 +141206,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -141393,7 +141393,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -141530,7 +141530,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -141999,7 +141999,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -142187,7 +142187,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -142441,7 +142441,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -142578,7 +142578,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -142765,7 +142765,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -142902,7 +142902,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -143089,7 +143089,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -143226,7 +143226,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -143695,7 +143695,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -143883,7 +143883,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -144137,7 +144137,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -144274,7 +144274,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -144461,7 +144461,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -144598,7 +144598,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, ca @@ -145067,7 +145067,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -145255,7 +145255,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -145509,7 +145509,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -145646,7 +145646,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -145833,7 +145833,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -145970,7 +145970,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -146439,7 +146439,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -146627,7 +146627,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -146881,7 +146881,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -147018,7 +147018,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -147205,7 +147205,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -147342,7 +147342,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -147811,7 +147811,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -147999,7 +147999,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -148253,7 +148253,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -148390,7 +148390,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -148577,7 +148577,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -148714,7 +148714,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, no @@ -149183,7 +149183,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -149371,7 +149371,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -149625,7 +149625,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -149762,7 +149762,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -149949,7 +149949,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -150086,7 +150086,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -150555,7 +150555,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -150743,7 +150743,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -150997,7 +150997,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -151134,7 +151134,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -151321,7 +151321,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -151458,7 +151458,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -151927,7 +151927,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -152115,7 +152115,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -152369,7 +152369,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -152506,7 +152506,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -152693,7 +152693,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -152830,7 +152830,7 @@ exports[`MessageBottomMenu should match snapshot, no history, empty payments, un @@ -153299,7 +153299,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -153487,7 +153487,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -153741,7 +153741,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -153878,7 +153878,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -154065,7 +154065,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -154202,7 +154202,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -154671,7 +154671,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -154859,7 +154859,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -155113,7 +155113,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -155250,7 +155250,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -155437,7 +155437,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -155574,7 +155574,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -155761,7 +155761,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -155898,7 +155898,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -156367,7 +156367,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -156555,7 +156555,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -156809,7 +156809,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -156946,7 +156946,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -157133,7 +157133,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -157270,7 +157270,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -157739,7 +157739,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -157927,7 +157927,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -158181,7 +158181,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -158318,7 +158318,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -158505,7 +158505,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -158642,7 +158642,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -158829,7 +158829,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -158966,7 +158966,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -159094,7 +159094,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -159231,7 +159231,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -159418,7 +159418,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -159555,7 +159555,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -159683,7 +159683,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -159820,7 +159820,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -160007,7 +160007,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -160144,7 +160144,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -160272,7 +160272,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -160409,7 +160409,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -160878,7 +160878,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -161066,7 +161066,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -161320,7 +161320,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -161457,7 +161457,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -161644,7 +161644,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -161781,7 +161781,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -161968,7 +161968,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -162105,7 +162105,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -162233,7 +162233,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -162370,7 +162370,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -162557,7 +162557,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -162694,7 +162694,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -162822,7 +162822,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -162959,7 +162959,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -163146,7 +163146,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -163283,7 +163283,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -163411,7 +163411,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -163548,7 +163548,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -164017,7 +164017,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -164205,7 +164205,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -164459,7 +164459,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -164596,7 +164596,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -164783,7 +164783,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -164920,7 +164920,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -165107,7 +165107,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -165244,7 +165244,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -165372,7 +165372,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -165509,7 +165509,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -165696,7 +165696,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -165833,7 +165833,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -165961,7 +165961,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -166098,7 +166098,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -166285,7 +166285,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -166422,7 +166422,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -166550,7 +166550,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -166687,7 +166687,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -167156,7 +167156,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -167344,7 +167344,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -167598,7 +167598,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -167735,7 +167735,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -167922,7 +167922,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -168059,7 +168059,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -168246,7 +168246,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -168383,7 +168383,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -168511,7 +168511,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -168648,7 +168648,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -168835,7 +168835,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -168972,7 +168972,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -169100,7 +169100,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -169237,7 +169237,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -169424,7 +169424,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -169561,7 +169561,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -169689,7 +169689,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -169826,7 +169826,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -170295,7 +170295,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -170483,7 +170483,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -170737,7 +170737,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -170874,7 +170874,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -171061,7 +171061,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -171198,7 +171198,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -171385,7 +171385,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -171522,7 +171522,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -171650,7 +171650,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -171787,7 +171787,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -171974,7 +171974,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -172111,7 +172111,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -172239,7 +172239,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -172376,7 +172376,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -172563,7 +172563,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -172700,7 +172700,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -172828,7 +172828,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -172965,7 +172965,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -173434,7 +173434,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -173622,7 +173622,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -173876,7 +173876,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -174013,7 +174013,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -174200,7 +174200,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -174337,7 +174337,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -174524,7 +174524,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -174661,7 +174661,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -174789,7 +174789,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -174926,7 +174926,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -175113,7 +175113,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -175250,7 +175250,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -175378,7 +175378,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -175515,7 +175515,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -175702,7 +175702,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -175839,7 +175839,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -175967,7 +175967,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -176104,7 +176104,7 @@ exports[`MessageBottomMenu should match snapshot, no history, multiple payments, @@ -176573,7 +176573,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -176761,7 +176761,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -177015,7 +177015,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -177152,7 +177152,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -177339,7 +177339,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -177476,7 +177476,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -177945,7 +177945,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -178133,7 +178133,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -178387,7 +178387,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -178524,7 +178524,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -178711,7 +178711,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -178848,7 +178848,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -179035,7 +179035,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -179172,7 +179172,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -179641,7 +179641,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -179829,7 +179829,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -180083,7 +180083,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -180220,7 +180220,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -180407,7 +180407,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -180544,7 +180544,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, cance @@ -181013,7 +181013,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -181201,7 +181201,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -181455,7 +181455,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -181592,7 +181592,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -181779,7 +181779,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -181916,7 +181916,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -182103,7 +182103,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -182240,7 +182240,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -182368,7 +182368,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -182505,7 +182505,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -182974,7 +182974,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -183162,7 +183162,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -183416,7 +183416,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -183553,7 +183553,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -183740,7 +183740,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -183877,7 +183877,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -184064,7 +184064,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -184201,7 +184201,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -184329,7 +184329,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -184466,7 +184466,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -184935,7 +184935,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -185123,7 +185123,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -185377,7 +185377,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -185514,7 +185514,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -185701,7 +185701,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -185838,7 +185838,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -186025,7 +186025,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -186162,7 +186162,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -186290,7 +186290,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -186427,7 +186427,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, not c @@ -186896,7 +186896,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -187084,7 +187084,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -187338,7 +187338,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -187475,7 +187475,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -187662,7 +187662,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -187799,7 +187799,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -187986,7 +187986,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -188123,7 +188123,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -188251,7 +188251,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -188388,7 +188388,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -188857,7 +188857,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -189045,7 +189045,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -189299,7 +189299,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -189436,7 +189436,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -189623,7 +189623,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -189760,7 +189760,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -189947,7 +189947,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -190084,7 +190084,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -190212,7 +190212,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -190349,7 +190349,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -190818,7 +190818,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -191006,7 +191006,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -191260,7 +191260,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -191397,7 +191397,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -191584,7 +191584,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -191721,7 +191721,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -191908,7 +191908,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -192045,7 +192045,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -192173,7 +192173,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -192310,7 +192310,7 @@ exports[`MessageBottomMenu should match snapshot, no history, one payment, undef @@ -192779,7 +192779,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -192967,7 +192967,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -193221,7 +193221,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -193358,7 +193358,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -193545,7 +193545,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -193682,7 +193682,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -194151,7 +194151,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -194339,7 +194339,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -194593,7 +194593,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -194730,7 +194730,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -194917,7 +194917,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -195054,7 +195054,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -195241,7 +195241,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -195378,7 +195378,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -195847,7 +195847,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -196035,7 +196035,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -196289,7 +196289,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -196426,7 +196426,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -196613,7 +196613,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -196750,7 +196750,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -197219,7 +197219,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -197407,7 +197407,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -197661,7 +197661,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -197798,7 +197798,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -197985,7 +197985,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -198122,7 +198122,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -198591,7 +198591,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -198779,7 +198779,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -199033,7 +199033,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -199170,7 +199170,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -199357,7 +199357,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -199494,7 +199494,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -199963,7 +199963,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -200151,7 +200151,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -200405,7 +200405,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -200542,7 +200542,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -200729,7 +200729,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -200866,7 +200866,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -201335,7 +201335,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -201523,7 +201523,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -201777,7 +201777,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -201914,7 +201914,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -202101,7 +202101,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -202238,7 +202238,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -202707,7 +202707,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -202895,7 +202895,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -203149,7 +203149,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -203286,7 +203286,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -203473,7 +203473,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -203610,7 +203610,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -204079,7 +204079,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -204267,7 +204267,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -204521,7 +204521,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -204658,7 +204658,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -204845,7 +204845,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments @@ -204982,7 +204982,7 @@ exports[`MessageBottomMenu should match snapshot, no history, undefined payments diff --git a/ts/features/pn/components/__test__/__snapshots__/MessageCancelledContent.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/MessageCancelledContent.test.tsx.snap index 5d95bae969d..c58b1ed30ad 100644 --- a/ts/features/pn/components/__test__/__snapshots__/MessageCancelledContent.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/MessageCancelledContent.test.tsx.snap @@ -347,73 +347,74 @@ exports[`MessageCancelledContent Should match snapshot, cancelled, empty paid no ] } > - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + - - - - - - + > + + + + @@ -1116,7 +1116,7 @@ exports[`MessageDetails component should match the snapshot with default props 1 @@ -1304,7 +1304,7 @@ exports[`MessageDetails component should match the snapshot with default props 1 @@ -1558,7 +1558,7 @@ exports[`MessageDetails component should match the snapshot with default props 1 @@ -1695,7 +1695,7 @@ exports[`MessageDetails component should match the snapshot with default props 1 @@ -1882,7 +1882,7 @@ exports[`MessageDetails component should match the snapshot with default props 1 @@ -2019,7 +2019,7 @@ exports[`MessageDetails component should match the snapshot with default props 1 diff --git a/ts/features/pn/components/__test__/__snapshots__/MessageInfo.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/MessageInfo.test.tsx.snap index 1d946c58f71..ed366107195 100644 --- a/ts/features/pn/components/__test__/__snapshots__/MessageInfo.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/MessageInfo.test.tsx.snap @@ -575,7 +575,7 @@ exports[`MessageInfo should match snapshot 1`] = ` diff --git a/ts/features/pn/components/__test__/__snapshots__/MessagePaymentBottomSheet.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/MessagePaymentBottomSheet.test.tsx.snap index aff339586ef..64b45853106 100644 --- a/ts/features/pn/components/__test__/__snapshots__/MessagePaymentBottomSheet.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/MessagePaymentBottomSheet.test.tsx.snap @@ -853,7 +853,7 @@ exports[`MessagePaymentBottomSheet should match snapshot, six payments 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1085,7 +1085,7 @@ exports[`MessagePaymentBottomSheet should match snapshot, six payments 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1330,7 +1330,7 @@ exports[`MessagePaymentBottomSheet should match snapshot, six payments 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1575,7 +1575,7 @@ exports[`MessagePaymentBottomSheet should match snapshot, six payments 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1820,7 +1820,7 @@ exports[`MessagePaymentBottomSheet should match snapshot, six payments 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -2065,7 +2065,7 @@ exports[`MessagePaymentBottomSheet should match snapshot, six payments 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -2310,7 +2310,7 @@ exports[`MessagePaymentBottomSheet should match snapshot, six payments 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, diff --git a/ts/features/pn/components/__test__/__snapshots__/MessagePayments.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/MessagePayments.test.tsx.snap index a578befcf99..ecb9c396353 100644 --- a/ts/features/pn/components/__test__/__snapshots__/MessagePayments.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/MessagePayments.test.tsx.snap @@ -925,7 +925,7 @@ exports[`MessagePayments should match snapshot when cancelled, with payments, wi "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1171,7 +1171,7 @@ exports[`MessagePayments should match snapshot when cancelled, with payments, wi "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1417,7 +1417,7 @@ exports[`MessagePayments should match snapshot when cancelled, with payments, wi "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1663,7 +1663,7 @@ exports[`MessagePayments should match snapshot when cancelled, with payments, wi "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -1909,7 +1909,7 @@ exports[`MessagePayments should match snapshot when cancelled, with payments, wi "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -2155,7 +2155,7 @@ exports[`MessagePayments should match snapshot when cancelled, with payments, wi "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -2401,7 +2401,7 @@ exports[`MessagePayments should match snapshot when cancelled, with payments, wi "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -3124,7 +3124,7 @@ exports[`MessagePayments should match snapshot when cancelled, without payments, "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -3370,7 +3370,7 @@ exports[`MessagePayments should match snapshot when cancelled, without payments, "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -3616,7 +3616,7 @@ exports[`MessagePayments should match snapshot when cancelled, without payments, "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -3862,7 +3862,7 @@ exports[`MessagePayments should match snapshot when cancelled, without payments, "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -4108,7 +4108,7 @@ exports[`MessagePayments should match snapshot when cancelled, without payments, "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -4354,7 +4354,7 @@ exports[`MessagePayments should match snapshot when cancelled, without payments, "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -4600,7 +4600,7 @@ exports[`MessagePayments should match snapshot when cancelled, without payments, "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -5646,7 +5646,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -5878,7 +5878,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -6123,7 +6123,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -6368,7 +6368,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -6613,7 +6613,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -7328,7 +7328,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -7560,7 +7560,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -7805,7 +7805,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -8050,7 +8050,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -8295,7 +8295,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with five (ma "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -9010,7 +9010,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -9242,7 +9242,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -9487,7 +9487,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -9732,7 +9732,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -9977,7 +9977,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -10800,7 +10800,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -11032,7 +11032,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -11277,7 +11277,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -11522,7 +11522,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -11767,7 +11767,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with more-tha "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -12590,7 +12590,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with one paya "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, @@ -13292,7 +13292,7 @@ exports[`MessagePayments should match snapshot when not cancelled, with one paya "alignItems": "center", "flexDirection": "row", "justifyContent": "flex-end", - "marginLeft": 16, + "marginLeft": 12, }, Object { "flexShrink": 1, diff --git a/ts/features/pn/components/__test__/__snapshots__/TimelineListItem.test.tsx.snap b/ts/features/pn/components/__test__/__snapshots__/TimelineListItem.test.tsx.snap index 093bfc7deff..5553ce1d8d4 100644 --- a/ts/features/pn/components/__test__/__snapshots__/TimelineListItem.test.tsx.snap +++ b/ts/features/pn/components/__test__/__snapshots__/TimelineListItem.test.tsx.snap @@ -372,7 +372,7 @@ exports[`TimelineListItem Should match snapshot, all handled-status items histor @@ -2986,7 +2986,7 @@ exports[`TimelineListItem Should match snapshot, all handled-status items histor @@ -5600,7 +5600,7 @@ exports[`TimelineListItem Should match snapshot, no history, no link 1`] = ` @@ -6119,7 +6119,7 @@ exports[`TimelineListItem Should match snapshot, no history, with link 1`] = ` diff --git a/ts/features/pn/screens/__test__/__snapshots__/LegacyPaidPaymentScreen.test.tsx.snap b/ts/features/pn/screens/__test__/__snapshots__/LegacyPaidPaymentScreen.test.tsx.snap index 6a8d90a38d7..ffd90a48318 100644 --- a/ts/features/pn/screens/__test__/__snapshots__/LegacyPaidPaymentScreen.test.tsx.snap +++ b/ts/features/pn/screens/__test__/__snapshots__/LegacyPaidPaymentScreen.test.tsx.snap @@ -939,7 +939,7 @@ exports[`LegacyPaidPaymentScreen should render with back button, title, help but @@ -1963,7 +1963,7 @@ exports[`LegacyPaidPaymentScreen should render with back button, title, help but @@ -2152,7 +2152,7 @@ exports[`LegacyPaidPaymentScreen should render with back button, title, help but diff --git a/ts/features/pn/screens/__test__/__snapshots__/MessageDetailsScreen.test.tsx.snap b/ts/features/pn/screens/__test__/__snapshots__/MessageDetailsScreen.test.tsx.snap index bc81587098f..d3857485592 100644 --- a/ts/features/pn/screens/__test__/__snapshots__/MessageDetailsScreen.test.tsx.snap +++ b/ts/features/pn/screens/__test__/__snapshots__/MessageDetailsScreen.test.tsx.snap @@ -1000,7 +1000,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1228,7 +1228,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin style={ Object { "alignItems": "center", - "marginLeft": 16, + "marginLeft": 12, } } > @@ -1572,7 +1572,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin @@ -1705,7 +1705,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin @@ -1893,7 +1893,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin @@ -2147,7 +2147,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin @@ -2284,7 +2284,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin @@ -2471,7 +2471,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin @@ -2608,7 +2608,7 @@ exports[`MessageDetailsScreen should match the snapshot when everything went fin diff --git a/ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx b/ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx index d92a3631159..e1080ba4331 100644 --- a/ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx +++ b/ts/features/pushNotifications/components/ProfileNotificationsSettings.tsx @@ -1,6 +1,6 @@ import { + Banner, Divider, - FeatureInfo, ListItemSwitch, VSpacer } from "@pagopa/io-app-design-system"; @@ -70,9 +70,13 @@ export const ProfileNotificationSettings = ({ /> {showSettingsPath && } {showSettingsPath && ( - )} diff --git a/ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap b/ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap index 0cef56ee170..8c487590b2d 100644 --- a/ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap +++ b/ts/features/pushNotifications/components/__tests__/__snapshots__/ProfileNotificationsSettings.test.tsx.snap @@ -2027,111 +2027,55 @@ exports[`ProfileNotificationSettings should match snapshot, preview disabled, pr } /> - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + @@ -937,7 +937,7 @@ exports[`OnboardingNotificationsInfoScreenConsent should match snapshot 1`] = ` @@ -1161,7 +1161,7 @@ exports[`OnboardingNotificationsInfoScreenConsent should match snapshot 1`] = ` diff --git a/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap index 92466e39514..aeca4d74333 100644 --- a/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap +++ b/ts/features/pushNotifications/screens/__tests__/__snapshots__/OnboardingNotificationsPreferencesScreen.test.tsx.snap @@ -913,111 +913,55 @@ exports[`OnboardingNotificationsPreferencesScreen should match snapshot when not } /> - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences - - - + + + + + + + + + + + + + + + + + - - - - - - - You can change this choice anytime in Profile > Preferences - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + - - - - - - You can change this choice anytime in Profile > Preferences - + propList={ + Array [ + "fill", + ] + } + /> + + - - - - - - - You can change this choice anytime in Profile > Preferences + + + + + + + + + + + + + + + = 8" - -"@pagopa/io-app-design-system@1.36.9": - version "1.36.9" - resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.9.tgz#fa8cbb03ddf6030131e2cc2c9c042771febd7aa4" - integrity sha512-JvDBzY8AaxyBJRSc0Syus8mNUARKxcklmlMskayNgyTlvHBx1KaxvEgbMk/qpxPa8jm1J5mk/5EIQeQB9wpdxA== + +"@pagopa/io-app-design-system@1.36.10": + version "1.36.10" + resolved "https://registry.yarnpkg.com/@pagopa/io-app-design-system/-/io-app-design-system-1.36.10.tgz#b53725cb9df0ea363830231b608f5b9caea83bf7" + integrity sha512-X38yztDWyvmYqTh/EdnZtJJ2XKzReuidDaQRVRUPrt64XGI2sy7sfaj2HbQ4NXJ015Zn4kA+6J8B4hoWWVIEQA== dependencies: "@pagopa/ts-commons" "^12.0.0" "@testing-library/jest-native" "^5.4.2"