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,