diff --git a/app/components/Views/Settings/NotificationsSettings/__snapshots__/index.test.tsx.snap b/app/components/Views/Settings/NotificationsSettings/__snapshots__/index.test.tsx.snap index 1cde78a543d..1859f635317 100644 --- a/app/components/Views/Settings/NotificationsSettings/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/Settings/NotificationsSettings/__snapshots__/index.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`NotificationsSettings should render correctly 1`] = ` +exports[`NotificationsSettings render matches snapshot 1`] = ` { mockGetState = jest.fn(); @@ -57,130 +50,10 @@ jest.mock('../../../../util/notifications/services/NotificationService', () => ( getAllPermissions: jest.fn(), })); -jest.mock('../../../../core/Analytics/MetaMetrics.events', () => ({ - MetaMetricsEvents: { - NOTIFICATIONS_SETTINGS_UPDATED: 'NOTIFICATIONS_SETTINGS_UPDATED', - }, -})); - -const mockDisableNotifications = jest.fn(); -const mockEnableNotifications = jest.fn(); -const mockSetUiNotificationStatus = jest.fn(); -const mockTrackEvent = jest.fn(); - -const mockNavigation = { - navigate: jest.fn(), -} as unknown as NavigationProp; - const setOptions = jest.fn(); -describe('toggleNotificationsEnabled', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - const setup = (basicFunctionalityEnabled: boolean, isMetamaskNotificationsEnabled: boolean, isProfileSyncingEnabled: boolean) => renderHook(() => - useCallback(async () => { - if (!basicFunctionalityEnabled) { - mockNavigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, { - screen: Routes.SHEET.BASIC_FUNCTIONALITY, - params: { - caller: Routes.SETTINGS.NOTIFICATIONS, - }, - }); - } else if (isMetamaskNotificationsEnabled) { - mockDisableNotifications(); - mockSetUiNotificationStatus(false); - } else { - const { permission } = await NotificationsService.getAllPermissions(false); - if (permission !== 'authorized') { - return; - } - - mockEnableNotifications(); - mockSetUiNotificationStatus(true); - } - mockTrackEvent(MetaMetricsEvents.NOTIFICATIONS_SETTINGS_UPDATED, { - settings_type: 'notifications', - old_value: isMetamaskNotificationsEnabled, - new_value: !isMetamaskNotificationsEnabled, - was_profile_syncing_on: isMetamaskNotificationsEnabled ? true : isProfileSyncingEnabled, - }); - }, []) - ); - - it('should navigate to basic functionality screen if basicFunctionalityEnabled is false', async () => { - const { result } = setup(false, false, false); - - await act(async () => { - await result.current(); - }); - - expect(mockNavigation.navigate).toHaveBeenCalledWith(Routes.MODAL.ROOT_MODAL_FLOW, { - screen: Routes.SHEET.BASIC_FUNCTIONALITY, - params: { - caller: Routes.SETTINGS.NOTIFICATIONS, - }, - }); - }); - - it('should disable notifications if isMetamaskNotificationsEnabled is true', async () => { - const { result } = setup(true, true, false); - - await act(async () => { - await result.current(); - }); - - expect(mockDisableNotifications).toHaveBeenCalled(); - expect(mockSetUiNotificationStatus).toHaveBeenCalledWith(false); - }); - - it('should enable notifications if isMetamaskNotificationsEnabled is false and permission is authorized', async () => { - (NotificationsService.getAllPermissions as jest.Mock).mockResolvedValue({ permission: 'authorized' }); - - const { result } = setup(true, false, false); - - await act(async () => { - await result.current(); - }); - - expect(mockEnableNotifications).toHaveBeenCalled(); - expect(mockSetUiNotificationStatus).toHaveBeenCalledWith(true); - }); - - it('should not enable notifications if permission is not authorized', async () => { - (NotificationsService.getAllPermissions as jest.Mock).mockResolvedValue({ permission: 'denied' }); - - const { result } = setup(true, false, false); - - await act(async () => { - await result.current(); - }); - - expect(mockEnableNotifications).not.toHaveBeenCalled(); - expect(mockSetUiNotificationStatus).not.toHaveBeenCalled(); - }); - - it('should track event when notifications settings are updated', async () => { - (NotificationsService.getAllPermissions as jest.Mock).mockResolvedValue({ permission: 'authorized' }); - - const { result } = setup(true, false, true); - - await act(async () => { - await result.current(); - }); - - expect(mockTrackEvent).toHaveBeenCalledWith(MetaMetricsEvents.NOTIFICATIONS_SETTINGS_UPDATED, { - settings_type: 'notifications', - old_value: false, - new_value: true, - was_profile_syncing_on: true, - }); - }); -}); - describe('NotificationsSettings', () => { - it('should render correctly', () => { + it('render matches snapshot', () => { mockGetState.mockImplementation(() => ({ notifications: {}, })); @@ -199,21 +72,4 @@ describe('NotificationsSettings', () => { ); expect(toJSON()).toMatchSnapshot(); }); - - it('should toggle notifications and handle permission correctly', async () => { - const isMetamaskNotificationsEnabled = true; - const basicFunctionalityEnabled = true; - const isProfileSyncingEnabled = true; - - const toggleNotificationsEnabledImpl = jest.fn(() => Promise.resolve({ - isMetamaskNotificationsEnabled, - basicFunctionalityEnabled, - isProfileSyncingEnabled, - })); - - await toggleNotificationsEnabledImpl(); - - expect(NotificationsService.getAllPermissions).toHaveBeenCalledTimes(1); - expect(NotificationsService.getAllPermissions).toHaveBeenCalledWith(false); - }); }); diff --git a/app/components/Views/Settings/NotificationsSettings/index.tsx b/app/components/Views/Settings/NotificationsSettings/index.tsx index 34e9da18047..e046b203c2e 100644 --- a/app/components/Views/Settings/NotificationsSettings/index.tsx +++ b/app/components/Views/Settings/NotificationsSettings/index.tsx @@ -31,7 +31,6 @@ import { selectIsProfileSyncingEnabled, } from '../../../../selectors/notifications'; -import NotificationsService from '../../../../util/notifications/services/NotificationService'; import Routes from '../../../../constants/navigation/Routes'; import ButtonIcon, { @@ -57,6 +56,7 @@ import AppConstants from '../../../../core/AppConstants'; import notificationsRows from './notificationsRows'; import { IconName } from '../../../../component-library/components/Icons/Icon'; import { MetaMetricsEvents } from '../../../../core/Analytics/MetaMetrics.events'; +import { useToggleNotifications } from './useToggleNotifications'; interface MainNotificationSettingsProps extends Props { toggleNotificationsEnabled: () => void; @@ -109,6 +109,7 @@ const NotificationsSettings = ({ navigation, route }: Props) => { const { accounts } = useAccounts(); const { trackEvent } = useMetrics(); const theme = useTheme(); + const isMetamaskNotificationsEnabled = useSelector( selectIsMetamaskNotificationsEnabled, ); @@ -177,42 +178,15 @@ const NotificationsSettings = ({ navigation, route }: Props) => { * it will request the push notifications permission and enable the notifications * if the permission is granted. */ - const toggleNotificationsEnabled = useCallback(async () => { - if (!basicFunctionalityEnabled) { - navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, { - screen: Routes.SHEET.BASIC_FUNCTIONALITY, - params: { - caller: Routes.SETTINGS.NOTIFICATIONS, - }, - }); - } else if (isMetamaskNotificationsEnabled) { - disableNotifications(); - setUiNotificationStatus(false); - } else { - const { permission } = await NotificationsService.getAllPermissions(false); - if (permission !== 'authorized') { - return; - } - enableNotifications(); - setUiNotificationStatus(true); - } - trackEvent(MetaMetricsEvents.NOTIFICATIONS_SETTINGS_UPDATED, { - settings_type: 'notifications', - old_value: isMetamaskNotificationsEnabled, - new_value: !isMetamaskNotificationsEnabled, - was_profile_syncing_on: isMetamaskNotificationsEnabled - ? true - : isProfileSyncingEnabled, - }); - }, [ + const { toggleNotificationsEnabled } = useToggleNotifications({ + navigation, basicFunctionalityEnabled, - disableNotifications, - enableNotifications, isMetamaskNotificationsEnabled, - navigation, - trackEvent, isProfileSyncingEnabled, - ]); + disableNotifications, + enableNotifications, + setUiNotificationStatus, + }); const toggleCustomNotificationsEnabled = useCallback(async () => { setPlatformAnnouncementsState(!platformAnnouncementsState); diff --git a/app/components/Views/Settings/NotificationsSettings/useToggleNotifications.test.tsx b/app/components/Views/Settings/NotificationsSettings/useToggleNotifications.test.tsx new file mode 100644 index 00000000000..54c7addc69b --- /dev/null +++ b/app/components/Views/Settings/NotificationsSettings/useToggleNotifications.test.tsx @@ -0,0 +1,125 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import { useToggleNotifications } from './useToggleNotifications'; +import NotificationsService from '../../../../util/notifications/services/NotificationService'; +import Routes from '../../../../constants/navigation/Routes'; +import { NavigationProp, ParamListBase } from '@react-navigation/native'; + +jest.mock( + '../../../../util/notifications/services/NotificationService', + () => ({ + getAllPermissions: jest.fn(), + }), +); + +const mockNavigation = { + navigate: jest.fn(), +} as unknown as NavigationProp; + +const mockDisableNotifications = jest.fn(); +const mockEnableNotifications = jest.fn(); +const mockSetUiNotificationStatus = jest.fn(); + +describe('useToggleNotifications', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('navigates to basic functionality screen if basic functionality is disabled', async () => { + const { result } = renderHook(() => + useToggleNotifications({ + navigation: mockNavigation, + basicFunctionalityEnabled: false, + isMetamaskNotificationsEnabled: false, + isProfileSyncingEnabled: false, + disableNotifications: mockDisableNotifications, + enableNotifications: mockEnableNotifications, + setUiNotificationStatus: mockSetUiNotificationStatus, + }), + ); + + await act(async () => { + await result.current.toggleNotificationsEnabled(); + }); + + expect(mockNavigation.navigate).toHaveBeenCalledWith( + Routes.MODAL.ROOT_MODAL_FLOW, + { + screen: Routes.SHEET.BASIC_FUNCTIONALITY, + params: { + caller: Routes.SETTINGS.NOTIFICATIONS, + }, + }, + ); + }); + + it('switches notifications OFF if notifications previously enabled', async () => { + const { result } = renderHook(() => + useToggleNotifications({ + navigation: mockNavigation, + basicFunctionalityEnabled: true, + isMetamaskNotificationsEnabled: true, + isProfileSyncingEnabled: false, + disableNotifications: mockDisableNotifications, + enableNotifications: mockEnableNotifications, + setUiNotificationStatus: mockSetUiNotificationStatus, + }), + ); + + await act(async () => { + await result.current.toggleNotificationsEnabled(); + }); + + expect(mockDisableNotifications).toHaveBeenCalled(); + expect(mockSetUiNotificationStatus).toHaveBeenCalledWith(false); + }); + + it('switches notifications ON if notifications previously disabled and permission is authorized', async () => { + (NotificationsService.getAllPermissions as jest.Mock).mockResolvedValue({ + permission: 'authorized', + }); + + const { result } = renderHook(() => + useToggleNotifications({ + navigation: mockNavigation, + basicFunctionalityEnabled: true, + isMetamaskNotificationsEnabled: false, + isProfileSyncingEnabled: false, + disableNotifications: mockDisableNotifications, + enableNotifications: mockEnableNotifications, + setUiNotificationStatus: mockSetUiNotificationStatus, + }), + ); + + await act(async () => { + await result.current.toggleNotificationsEnabled(); + }); + + expect(mockEnableNotifications).toHaveBeenCalled(); + expect(mockSetUiNotificationStatus).toHaveBeenCalledWith(true); + }); + + it('switches notifications OFF if device permission is not authorized', async () => { + (NotificationsService.getAllPermissions as jest.Mock).mockResolvedValue({ + permission: 'denied', + }); + + const { result } = renderHook(() => + useToggleNotifications({ + navigation: mockNavigation, + basicFunctionalityEnabled: true, + isMetamaskNotificationsEnabled: false, + isProfileSyncingEnabled: false, + disableNotifications: mockDisableNotifications, + enableNotifications: mockEnableNotifications, + setUiNotificationStatus: mockSetUiNotificationStatus, + }), + ); + + await act(async () => { + await result.current.toggleNotificationsEnabled(); + }); + + expect(mockEnableNotifications).not.toHaveBeenCalled(); + expect(mockSetUiNotificationStatus).not.toHaveBeenCalled(); + }); +}); diff --git a/app/components/Views/Settings/NotificationsSettings/useToggleNotifications.ts b/app/components/Views/Settings/NotificationsSettings/useToggleNotifications.ts new file mode 100644 index 00000000000..f5fff6ee5b6 --- /dev/null +++ b/app/components/Views/Settings/NotificationsSettings/useToggleNotifications.ts @@ -0,0 +1,70 @@ +import { useCallback } from 'react'; +import { NavigationProp, ParamListBase } from '@react-navigation/native'; +import Routes from '../../../../constants/navigation/Routes'; +import NotificationsService from '../../../../util/notifications/services/NotificationService'; +import { MetaMetricsEvents } from '../../../../core/Analytics/MetaMetrics.events'; +import { useMetrics } from '../../../hooks/useMetrics'; + +interface Props { + navigation: NavigationProp; + basicFunctionalityEnabled: boolean; + isMetamaskNotificationsEnabled: boolean; + isProfileSyncingEnabled: boolean | null; + disableNotifications: () => Promise; + enableNotifications: () => Promise; + setUiNotificationStatus: (status: boolean) => void; +} + +export function useToggleNotifications({ + navigation, + basicFunctionalityEnabled, + isMetamaskNotificationsEnabled, + isProfileSyncingEnabled, + disableNotifications, + enableNotifications, + setUiNotificationStatus, +}: Props) { + const { trackEvent } = useMetrics(); + const toggleNotificationsEnabled = useCallback(async () => { + if (!basicFunctionalityEnabled) { + navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, { + screen: Routes.SHEET.BASIC_FUNCTIONALITY, + params: { + caller: Routes.SETTINGS.NOTIFICATIONS, + }, + }); + } else if (isMetamaskNotificationsEnabled) { + disableNotifications(); + setUiNotificationStatus(false); + } else { + const { permission } = await NotificationsService.getAllPermissions( + false, + ); + if (permission !== 'authorized') { + return; + } + + enableNotifications(); + setUiNotificationStatus(true); + } + trackEvent(MetaMetricsEvents.NOTIFICATIONS_SETTINGS_UPDATED, { + settings_type: 'notifications', + old_value: isMetamaskNotificationsEnabled, + new_value: !isMetamaskNotificationsEnabled, + was_profile_syncing_on: isMetamaskNotificationsEnabled + ? true + : isProfileSyncingEnabled, + }); + }, [ + basicFunctionalityEnabled, + isMetamaskNotificationsEnabled, + trackEvent, + isProfileSyncingEnabled, + navigation, + disableNotifications, + setUiNotificationStatus, + enableNotifications, + ]); + + return { toggleNotificationsEnabled }; +} diff --git a/app/util/notifications/androidChannels.test.ts b/app/util/notifications/androidChannels.test.ts index c0cb6a45412..debc8448ab3 100644 --- a/app/util/notifications/androidChannels.test.ts +++ b/app/util/notifications/androidChannels.test.ts @@ -6,11 +6,11 @@ import { } from './androidChannels'; describe('notificationChannels', () => { - it('should have two channels', () => { + it('contains two channels', () => { expect(notificationChannels).toHaveLength(2); }); - it('should have the correct properties for the first channel', () => { + it('first channel has DEFAULT_NOTIFICATION_CHANNEL_ID', () => { const firstChannel: MetaMaskAndroidChannel = notificationChannels[0]; expect(firstChannel).toEqual({ id: ChannelId.DEFAULT_NOTIFICATION_CHANNEL_ID, @@ -23,7 +23,7 @@ describe('notificationChannels', () => { }); }); - it('should have the correct properties for the second channel', () => { + it('second channel should have the correct properties for DEFAULT_NOTIFICATION_CHANNEL_ID', () => { const secondChannel: MetaMaskAndroidChannel = notificationChannels[1]; expect(secondChannel).toEqual({ id: ChannelId.ANNOUNCEMENT_NOTIFICATION_CHANNEL_ID, @@ -36,13 +36,13 @@ describe('notificationChannels', () => { }); }); - it('should have unique titles for each channel', () => { + it('channels have unique titles', () => { const titles = notificationChannels.map((channel) => channel.title); const uniqueTitles = new Set(titles); expect(uniqueTitles.size).toBe(titles.length); }); - it('should have unique subtitles for each channel', () => { + it('channels have unique subtitles ', () => { const subtitles = notificationChannels.map((channel) => channel.subtitle); const uniqueSubtitles = new Set(subtitles); expect(uniqueSubtitles.size).toBe(subtitles.length); diff --git a/app/util/notifications/hooks/index.test.ts b/app/util/notifications/hooks/index.test.ts index bbe94a97dc3..ff4b9fd77aa 100644 --- a/app/util/notifications/hooks/index.test.ts +++ b/app/util/notifications/hooks/index.test.ts @@ -1,19 +1,13 @@ -import { renderHook, act } from '@testing-library/react-hooks'; -import notifee, { - EventType, - Event as NotifeeEvent, -} from '@notifee/react-native'; - +import { act, renderHook } from '@testing-library/react-hooks'; +// eslint-disable-next-line import/no-namespace +import * as constants from '../constants'; import useNotificationHandler from './index'; import { NavigationProp, ParamListBase } from '@react-navigation/native'; import Routes from '../../../constants/navigation/Routes'; import { Notification } from '../../../util/notifications/types'; import { TRIGGER_TYPES } from '../constants'; +import NotificationsService from '../services/NotificationService'; -jest.mock('../../../util/device'); -jest.mock('../../../core/NotificationManager', () => ({ - setTransactionToView: jest.fn(), -})); jest.mock('@notifee/react-native', () => ({ setBadgeCount: jest.fn(), decrementBadgeCount: jest.fn(), @@ -29,12 +23,9 @@ jest.mock('@notifee/react-native', () => ({ }, })); -jest.mock('../../../core/NotificationManager', () => ({ - setTransactionToView: jest.fn(), -})); - -jest.mock('../../../util/device', () => ({ - isAndroid: jest.fn(), +jest.mock('../constants', () => ({ + ...jest.requireActual('../constants'), + isNotificationsFeatureEnabled: jest.fn(), })); const mockNavigate = jest.fn(); @@ -43,10 +34,10 @@ const mockNavigation = { } as unknown as NavigationProp; const notification = { - id: 1, + id: '123', type: TRIGGER_TYPES.ERC1155_RECEIVED, data: { - id: 1, + id: '123', trigger_id: '1', chain_id: 1, block_number: 1, @@ -62,22 +53,22 @@ const notification = { }, } as unknown as Notification; -const mockNotificationEvent = (event: NotifeeEvent) => ({ - type: event.type, - detail: { - notification, - }, -}); - +jest.mock('../services/NotificationService', () => ({ + onForegroundEvent: jest.fn(), + onBackgroundEvent: jest.fn(), + handleNotificationEvent: jest.fn(), +})); describe('useNotificationHandler', () => { beforeEach(() => { jest.clearAllMocks(); }); - it('should navigate to NOTIFICATIONS.DETAILS if notification is pressed', async () => { + it('navigates to NOTIFICATIONS.DETAILS when notification is pressed', async () => { const { result } = renderHook(() => useNotificationHandler(mockNavigation)); - await result.current.handlePressedNotification(notification); + await act(async () => { + result.current.handlePressedNotification(notification); + }); expect(mockNavigation.navigate).toHaveBeenCalledWith( Routes.NOTIFICATIONS.DETAILS, @@ -87,163 +78,32 @@ describe('useNotificationHandler', () => { ); }); - it('should handle notifications correctly', async () => { - const { waitFor } = renderHook(() => - useNotificationHandler(mockNavigation), - ); + it('does not navigates when notification is null', async () => { - await act(async () => { - notifee.onForegroundEvent(() => - mockNotificationEvent({ - type: EventType.PRESS, - detail: { - notification: { - body: 'notificationTest', - data: { - action: 'tx', - id: '123', - }, - }, - }, - }), - ); - await waitFor(() => { - expect(notifee.onForegroundEvent).toHaveBeenCalled(); - }); - }); - }); - it('should do nothing if the EventType is DISMISSED', async () => { - const { waitFor } = renderHook(() => + const { result } = renderHook(() => useNotificationHandler(mockNavigation), ); await act(async () => { - notifee.onForegroundEvent(() => - mockNotificationEvent({ - type: EventType.DISMISSED, - detail: { - notification: { - body: 'notificationTest', - data: { - action: 'tx', - id: '123', - }, - }, - }, - }), - ); - - await waitFor(() => { - expect(notifee.onForegroundEvent).toHaveBeenCalled(); - }); + result.current.handlePressedNotification(); }); - }); - - it('should do nothing if data.action is not tx', async () => { - const { waitFor } = renderHook(() => - useNotificationHandler(mockNavigation), - ); - await act(async () => { - notifee.onForegroundEvent(() => - mockNotificationEvent({ - type: EventType.DELIVERED, - detail: { - notification: { - body: 'notificationTest', - data: { - action: 'no-tx', - id: '123', - }, - }, - }, - }), - ); - - await waitFor(() => { - expect(notifee.onForegroundEvent).toHaveBeenCalled(); - }); - - expect(mockNavigate).not.toHaveBeenCalled(); - }); + expect(mockNavigation.navigate).not.toHaveBeenCalled(); }); - it('handleOpenedNotification should do nothing if notification is null', async () => { - const { waitFor } = renderHook(() => - useNotificationHandler(mockNavigation), - ); - - await act(async () => { - notifee.onForegroundEvent(() => - mockNotificationEvent({ - type: EventType.DELIVERED, - detail: { - notification: undefined, - }, - }), - ); - await waitFor(() => { - expect(notifee.onForegroundEvent).toHaveBeenCalled(); - }); - - expect(mockNavigate).not.toHaveBeenCalled(); - }); - }); + it('does nothing if the isNotificationsFeatureEnabled is false', async () => { + jest.spyOn(constants, 'isNotificationsFeatureEnabled').mockReturnValue(false); - it('should navigate to the transaction view when the notification action is "tx"', async () => { - const { waitFor } = renderHook(() => - useNotificationHandler(mockNavigation), - ); + const { result } = renderHook(() => useNotificationHandler(mockNavigation)); await act(async () => { - notifee.onForegroundEvent(() => - mockNotificationEvent({ - type: EventType.DELIVERED, - detail: { - notification: { - body: 'notificationTest', - data: { - action: 'tx', - id: '123', - }, - }, - }, - }), - ); - await waitFor(() => { - expect(notifee.onForegroundEvent).toHaveBeenCalled(); - }); + result.current.handlePressedNotification(notification); }); - }, 10000); - it('should process notification on Android', async () => { - jest.doMock('react-native/Libraries/Utilities/Platform', () => ({ - OS: 'android', - })); + expect(NotificationsService.onForegroundEvent).not.toHaveBeenCalled(); + expect(NotificationsService.onBackgroundEvent).not.toHaveBeenCalled(); - const { waitFor } = renderHook(() => - useNotificationHandler(mockNavigation), - ); - - await act(async () => { - notifee.onForegroundEvent(() => - mockNotificationEvent({ - type: EventType.PRESS, - detail: { - notification: { - body: 'notificationTest', - data: { - action: 'tx', - id: '123', - }, - }, - }, - }), - ); - await waitFor(() => { - expect(notifee.onForegroundEvent).toHaveBeenCalled(); - }); - }); + jest.restoreAllMocks(); }); }); diff --git a/app/util/notifications/hooks/index.ts b/app/util/notifications/hooks/index.ts index e91fe593eaf..3f6bb98c9a3 100644 --- a/app/util/notifications/hooks/index.ts +++ b/app/util/notifications/hooks/index.ts @@ -4,9 +4,11 @@ import NotificationsService from '../../../util/notifications/services/Notificat import Routes from '../../../constants/navigation/Routes'; import { isNotificationsFeatureEnabled, - TRIGGER_TYPES, } from '../../../util/notifications'; import { Notification } from '../../../util/notifications/types'; +import { + TRIGGER_TYPES, +} from '../../../util/notifications/constants'; import { Linking } from 'react-native'; const useNotificationHandler = (navigation: NavigationProp) => {