123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- import React, { useCallback, useEffect, useState } from 'react';
- import { View, Linking, Text, Switch, Platform, TouchableOpacity, AppState } from 'react-native';
- import * as Notifications from 'expo-notifications';
- import { Header, Loading, MenuButton, PageWrapper, WarningModal } from 'src/components';
- import { usePushNotification } from 'src/contexts/PushNotificationContext';
- import { usePostSaveNotificationTokenMutation } from '@api/user';
- import { styles } from 'src/components/MenuButton/style';
- import { StoreType, storage } from 'src/storage';
- import { Colors } from 'src/theme';
- import { NAVIGATION_PAGES } from 'src/types';
- import ListIcon from 'assets/icons/notifications/list-check.svg';
- import PeopleIcon from 'assets/icons/notifications/people-group-solid.svg';
- import ChatIcon from 'assets/icons/notifications/messages.svg';
- import GearIcon from 'assets/icons/notifications/gear-solid.svg';
- import BellIcon from 'assets/icons/notifications/bell-solid.svg';
- import { useGetSettingsQuery } from '@api/notifications';
- import { useFocusEffect } from '@react-navigation/native';
- const NotificationsScreen = ({ navigation }: { navigation: any }) => {
- const token = storage.get('token', StoreType.STRING) as string;
- const { data: notificationsSettings, refetch } = useGetSettingsQuery(token, !!token);
- const { mutateAsync: saveNotificationToken } = usePostSaveNotificationTokenMutation();
- const { isSubscribed, toggleSubscription, unsubscribeFromNotifications } = usePushNotification();
- const [modalInfo, setModalInfo] = useState({
- visible: false,
- type: 'confirm',
- message: '',
- action: () => {}
- });
- const [shouldOpenWarningModal, setShouldOpenWarningModal] = useState(false);
- const [initialPermissionStatus, setInitialPermissionStatus] = useState<
- 'granted' | 'denied' | 'undetermined' | null
- >(null);
- const closeModal = () => {
- setModalInfo({ ...modalInfo, visible: false });
- };
- useEffect(() => {
- if (notificationsSettings) {
- const { settings } = notificationsSettings;
- const isServerSubscribed =
- Platform.OS === 'ios'
- ? settings.some((setting) => setting.name === 'app-ios' && setting.active === 1)
- : settings.some((setting) => setting.name === 'app-android' && setting.active === 1);
- // if (isServerSubscribed !== isSubscribed) {
- // toggleSubscription();
- // }
- }
- }, [notificationsSettings]);
- useEffect(() => {
- const subscription = AppState.addEventListener('change', async (nextAppState) => {
- if (nextAppState === 'active' && initialPermissionStatus !== null) {
- const currentStatus = await checkNotificationPermissions();
- if (initialPermissionStatus !== 'granted' && currentStatus === 'granted') {
- await handleSubscribe();
- setInitialPermissionStatus(currentStatus);
- } else if (
- currentStatus !== 'granted' &&
- (isSubscribed || initialPermissionStatus === 'granted')
- ) {
- unsubscribeFromNotifications();
- }
- }
- });
- return () => {
- subscription.remove();
- };
- }, [initialPermissionStatus]);
- useEffect(() => {
- const getInitialPermissionsStatus = async () => {
- const status = await checkNotificationPermissions();
- if (status !== 'granted' && isSubscribed) {
- unsubscribeFromNotifications();
- }
- setInitialPermissionStatus(status);
- };
- getInitialPermissionsStatus();
- }, []);
- useFocusEffect(() => {
- refetchData();
- });
- const checkNotificationPermissions = async () => {
- const { status } = await Notifications.getPermissionsAsync();
- return status;
- };
- const refetchData = async () => {
- await refetch();
- };
- if (!notificationsSettings) return <Loading />;
- const toggleSwitch = async () => {
- if (isSubscribed) {
- toggleSubscription();
- } else {
- const status = await checkNotificationPermissions();
- if (status !== 'granted') {
- setModalInfo({
- visible: true,
- type: 'success',
- message:
- 'To use this feature we need your permission to access your notifications. If you press OK your system will ask you to confirm permission to receive notifications from NomadMania.',
- action: () => setShouldOpenWarningModal(true)
- });
- } else {
- handleSubscribe();
- }
- }
- };
- const handleSubscribe = async () => {
- const deviceData = await registerForPushNotificationsAsync();
- if (deviceData?.notificationToken) {
- toggleSubscription();
- await saveNotificationToken({
- token,
- platform: deviceData.platform,
- n_token: deviceData.notificationToken
- });
- refetchData();
- }
- };
- async function registerForPushNotificationsAsync() {
- const existingStatus = await checkNotificationPermissions();
- let finalStatus = existingStatus;
- if (existingStatus !== 'granted') {
- const { status } = await Notifications.requestPermissionsAsync();
- finalStatus = status;
- }
- if (finalStatus !== 'granted') {
- setModalInfo({
- visible: true,
- type: 'success',
- message:
- 'NomadMania app needs notification permissions to function properly. Open settings?',
- action: () =>
- Platform.OS === 'ios' ? Linking.openURL('app-settings:') : Linking.openSettings()
- });
- return null;
- }
- const deviceData = await Notifications.getDevicePushTokenAsync();
- console.log('deviceData', deviceData);
- if (Platform.OS === 'android') {
- Notifications.setNotificationChannelAsync('default', {
- name: 'default',
- importance: Notifications.AndroidImportance.MAX,
- vibrationPattern: [0, 250, 250, 250],
- lightColor: '#FF231F7C'
- });
- }
- storage.set('deviceToken', deviceData.data);
- return { notificationToken: deviceData.data ?? '', platform: deviceData.type ?? '' };
- }
- return (
- <PageWrapper>
- <Header label="Notifications" />
- <TouchableOpacity
- style={[
- styles.alignStyle,
- styles.buttonWrapper,
- {
- justifyContent: 'space-between'
- }
- ]}
- onPress={toggleSwitch}
- >
- <View style={styles.alignStyle}>
- <BellIcon fill={Colors.DARK_BLUE} width={20} height={20} />
- <Text style={styles.buttonLabel}>Enable notifications</Text>
- </View>
- <View>
- <Switch
- trackColor={{ false: Colors.LIGHT_GRAY, true: Colors.DARK_BLUE }}
- thumbColor={Colors.WHITE}
- onValueChange={toggleSwitch}
- value={isSubscribed}
- style={{ transform: 'scale(0.8)' }}
- />
- </View>
- </TouchableOpacity>
- {/* <MenuButton
- label="Notifications list"
- icon={
- <ListIcon
- fill={isSubscribed ? Colors.DARK_BLUE : Colors.LIGHT_GRAY}
- width={20}
- height={20}
- />
- }
- red={false}
- buttonFn={() => navigation.navigate(NAVIGATION_PAGES.NOTIFICATIONS_LIST as never)}
- disabled={!isSubscribed}
- /> */}
- <MenuButton
- label="Friends"
- icon={
- <PeopleIcon
- fill={isSubscribed ? Colors.DARK_BLUE : Colors.LIGHT_GRAY}
- width={20}
- height={20}
- />
- }
- red={false}
- buttonFn={() =>
- navigation.navigate(NAVIGATION_PAGES.FRIENDS_NOTIFICATIONS, {
- settings: notificationsSettings.settings,
- token
- } as never)
- }
- disabled={!isSubscribed}
- />
- {/* <MenuButton
- label="Messages"
- icon={
- <ChatIcon
- fill={isSubscribed ? Colors.DARK_BLUE : Colors.LIGHT_GRAY}
- width={20}
- height={20}
- />
- }
- red={false}
- buttonFn={() => navigation.navigate(NAVIGATION_PAGES.MESSAGES_NOTIFICATIONS as never)}
- disabled={!isSubscribed}
- /> */}
- {/* <MenuButton
- label="System"
- icon={
- <GearIcon
- fill={isSubscribed ? Colors.DARK_BLUE : Colors.LIGHT_GRAY}
- width={20}
- height={20}
- />
- }
- red={false}
- buttonFn={() => navigation.navigate(NAVIGATION_PAGES.SYSTEM_NOTIFICATIONS as never)}
- disabled={!isSubscribed}
- /> */}
- <WarningModal
- isVisible={modalInfo.visible}
- onClose={closeModal}
- type={modalInfo.type}
- message={modalInfo.message}
- action={() => {
- modalInfo.action();
- closeModal();
- }}
- onModalHide={() => {
- if (shouldOpenWarningModal) {
- setShouldOpenWarningModal(false);
- handleSubscribe();
- }
- }}
- />
- </PageWrapper>
- );
- };
- export default NotificationsScreen;
|