Viktoriia 10 months ago
parent
commit
cf49869884

+ 1 - 2
.gitignore

@@ -38,5 +38,4 @@ package-lock.json
 .vscode
 .vscode
 temp
 temp
 android
 android
-ios
+ios
-google-services.json

+ 0 - 48
App.tsx

@@ -15,8 +15,6 @@ import { setupInterceptors } from 'src/utils/request';
 import { ErrorModal } from 'src/components';
 import { ErrorModal } from 'src/components';
 import { NotificationProvider } from 'src/contexts/NotificationContext';
 import { NotificationProvider } from 'src/contexts/NotificationContext';
 import React from 'react';
 import React from 'react';
-import * as Notifications from 'expo-notifications';
-import { Platform } from 'react-native';
 
 
 const routingInstrumentation = new Sentry.ReactNavigationInstrumentation({
 const routingInstrumentation = new Sentry.ReactNavigationInstrumentation({
   enableTimeToInitialDisplay: true
   enableTimeToInitialDisplay: true
@@ -30,52 +28,6 @@ Sentry.init({
 });
 });
 
 
 const App = () => {
 const App = () => {
-  async function setupNotificationChannels() {
-    if (Platform.OS === 'android') {
-      await Notifications.setNotificationChannelAsync('default', {
-        name: 'default',
-        importance: Notifications.AndroidImportance.MAX,
-        vibrationPattern: [0, 250, 250, 250],
-        lightColor: '#FF231F7C'
-      });
-    }
-  }
-
-  useEffect(() => {
-    setupNotificationChannels();
-  }, []);
-
-  useEffect(() => {
-    let notificationListener: any;
-    let responseListener: any;
-
-    const checkLastNotificationResponse = async () => {
-      const lastNotificationResponse = await Notifications.getLastNotificationResponseAsync();
-      if (lastNotificationResponse) {
-        const data = lastNotificationResponse.notification.request.content.data;
-        console.log('lastNotificationResponse', lastNotificationResponse.notification.request);
-        console.log('dataLast', data);
-      }
-    };
-
-    checkLastNotificationResponse();
-
-    notificationListener = Notifications.addNotificationReceivedListener((notification) => {
-      console.log('notification', notification.request);
-    });
-
-    responseListener = Notifications.addNotificationResponseReceivedListener((response) => {
-      const data = response.notification.request.content.data;
-      console.log('payload', response.notification.request.trigger?.payload);
-      console.log('data', data);
-    });
-
-    return () => {
-      if (notificationListener) notificationListener.remove();
-      if (responseListener) responseListener.remove();
-    };
-  }, []);
-
   return (
   return (
     <QueryClientProvider client={queryClient}>
     <QueryClientProvider client={queryClient}>
       <NotificationProvider>
       <NotificationProvider>

+ 48 - 39
Route.tsx

@@ -84,6 +84,7 @@ import { userApi } from '@api/user';
 import axios from 'axios';
 import axios from 'axios';
 import { useNotification } from 'src/contexts/NotificationContext';
 import { useNotification } from 'src/contexts/NotificationContext';
 import PreviewScreen from 'src/screens/InAppScreens/ProfileScreen/ShareScreen';
 import PreviewScreen from 'src/screens/InAppScreens/ProfileScreen/ShareScreen';
+import { PushNotificationProvider } from 'src/contexts/PushNotificationContext';
 
 
 enableScreens();
 enableScreens();
 
 
@@ -410,45 +411,53 @@ const Route = () => {
   );
   );
 
 
   return (
   return (
-    <ScreenStack.Navigator
+    <PushNotificationProvider>
-      screenOptions={{ headerShown: false, cardStyle: { backgroundColor: 'white' } }}
+      <ScreenStack.Navigator
-      initialRouteName={token ? NAVIGATION_PAGES.IN_APP : NAVIGATION_PAGES.WELCOME}
+        screenOptions={{ headerShown: false, cardStyle: { backgroundColor: 'white' } }}
-    >
+        initialRouteName={token ? NAVIGATION_PAGES.IN_APP : NAVIGATION_PAGES.WELCOME}
-      <ScreenStack.Screen name={NAVIGATION_PAGES.WELCOME} component={WelcomeScreen} />
+      >
-      <ScreenStack.Screen name={NAVIGATION_PAGES.LOGIN} component={LoginScreen} />
+        <ScreenStack.Screen name={NAVIGATION_PAGES.WELCOME} component={WelcomeScreen} />
-      <ScreenStack.Screen name={NAVIGATION_PAGES.REGISTER} component={JoinUsScreen} />
+        <ScreenStack.Screen name={NAVIGATION_PAGES.LOGIN} component={LoginScreen} />
-      <ScreenStack.Screen name={NAVIGATION_PAGES.REGISTER_ACCOUNT_DATA} component={EditAccount} />
+        <ScreenStack.Screen name={NAVIGATION_PAGES.REGISTER} component={JoinUsScreen} />
-      <ScreenStack.Screen name={NAVIGATION_PAGES.RESET_PASSWORD} component={ResetPasswordScreen} />
+        <ScreenStack.Screen name={NAVIGATION_PAGES.REGISTER_ACCOUNT_DATA} component={EditAccount} />
-      <ScreenStack.Screen
+        <ScreenStack.Screen
-        name={NAVIGATION_PAGES.RESET_PASSWORD_DEEP}
+          name={NAVIGATION_PAGES.RESET_PASSWORD}
-        component={ResetPasswordDeepScreen}
+          component={ResetPasswordScreen}
-      />
+        />
-      <ScreenStack.Screen name={NAVIGATION_PAGES.INFO} component={InfoScreen} />
+        <ScreenStack.Screen
-      <ScreenStack.Screen name={NAVIGATION_PAGES.JOIN_INFO} component={JoinInfoScreen} />
+          name={NAVIGATION_PAGES.RESET_PASSWORD_DEEP}
-      <ScreenStack.Screen name={NAVIGATION_PAGES.DISCOVER_INFO} component={DiscoverInfoScreen} />
+          component={ResetPasswordDeepScreen}
-      <ScreenStack.Screen name={NAVIGATION_PAGES.PLAN_INFO} component={PlanInfoScreen} />
+        />
-      <ScreenStack.Screen
+        <ScreenStack.Screen name={NAVIGATION_PAGES.INFO} component={InfoScreen} />
-        name={NAVIGATION_PAGES.FIRST_STEPS_INFO}
+        <ScreenStack.Screen name={NAVIGATION_PAGES.JOIN_INFO} component={JoinInfoScreen} />
-        component={FirstStepsInfoScreen}
+        <ScreenStack.Screen name={NAVIGATION_PAGES.DISCOVER_INFO} component={DiscoverInfoScreen} />
-      />
+        <ScreenStack.Screen name={NAVIGATION_PAGES.PLAN_INFO} component={PlanInfoScreen} />
-      <ScreenStack.Screen name={NAVIGATION_PAGES.COUNTRIES_INFO} component={CountriesInfoScreen} />
+        <ScreenStack.Screen
-      <ScreenStack.Screen name={NAVIGATION_PAGES.DARE_INFO} component={DareInfoScreen} />
+          name={NAVIGATION_PAGES.FIRST_STEPS_INFO}
-      <ScreenStack.Screen name={NAVIGATION_PAGES.REGIONS_INFO} component={RegionsInfoScreen} />
+          component={FirstStepsInfoScreen}
-      <ScreenStack.Screen name={NAVIGATION_PAGES.TRIPS_INFO} component={TripsInfoScreen} />
+        />
-      <ScreenStack.Screen name={NAVIGATION_PAGES.FIXERS_INFO} component={FixersInfoScreen} />
+        <ScreenStack.Screen
-      <ScreenStack.Screen name={NAVIGATION_PAGES.EARTH_INFO} component={EarthInfoScreen} />
+          name={NAVIGATION_PAGES.COUNTRIES_INFO}
-      <ScreenStack.Screen name={NAVIGATION_PAGES.IN_APP}>
+          component={CountriesInfoScreen}
-        {() => (
+        />
-          <MapDrawer.Navigator drawerContent={(props) => <MenuDrawer {...props} />}>
+        <ScreenStack.Screen name={NAVIGATION_PAGES.DARE_INFO} component={DareInfoScreen} />
-            <MapDrawer.Screen
+        <ScreenStack.Screen name={NAVIGATION_PAGES.REGIONS_INFO} component={RegionsInfoScreen} />
-              name="DrawerApp"
+        <ScreenStack.Screen name={NAVIGATION_PAGES.TRIPS_INFO} component={TripsInfoScreen} />
-              component={BottomTabNavigator}
+        <ScreenStack.Screen name={NAVIGATION_PAGES.FIXERS_INFO} component={FixersInfoScreen} />
-              options={{ headerShown: false }}
+        <ScreenStack.Screen name={NAVIGATION_PAGES.EARTH_INFO} component={EarthInfoScreen} />
-            />
+        <ScreenStack.Screen name={NAVIGATION_PAGES.IN_APP}>
-          </MapDrawer.Navigator>
+          {() => (
-        )}
+            <MapDrawer.Navigator drawerContent={(props) => <MenuDrawer {...props} />}>
-      </ScreenStack.Screen>
+              <MapDrawer.Screen
-    </ScreenStack.Navigator>
+                name="DrawerApp"
+                component={BottomTabNavigator}
+                options={{ headerShown: false }}
+              />
+            </MapDrawer.Navigator>
+          )}
+        </ScreenStack.Screen>
+      </ScreenStack.Navigator>
+    </PushNotificationProvider>
   );
   );
 };
 };
 
 

+ 18 - 7
app.config.ts

@@ -1,12 +1,14 @@
 import 'dotenv/config';
 import 'dotenv/config';
-import { env } from 'process';
 import path from 'path';
 import path from 'path';
 import dotenv from 'dotenv';
 import dotenv from 'dotenv';
 
 
 import type { ConfigContext, ExpoConfig } from 'expo/config';
 import type { ConfigContext, ExpoConfig } from 'expo/config';
 
 
+const env = process.env;
+
 const API_HOST = env.ENV === 'production' ? env.PRODUCTION_API_HOST : env.DEVELOPMENT_API_HOST;
 const API_HOST = env.ENV === 'production' ? env.PRODUCTION_API_HOST : env.DEVELOPMENT_API_HOST;
 const MAP_HOST = env.ENV === 'production' ? env.PRODUCTION_MAP_HOST : env.DEVELOPMENT_MAP_HOST;
 const MAP_HOST = env.ENV === 'production' ? env.PRODUCTION_MAP_HOST : env.DEVELOPMENT_MAP_HOST;
+
 const GOOGLE_MAP_PLACES_APIKEY = env.GOOGLE_MAP_PLACES_APIKEY;
 const GOOGLE_MAP_PLACES_APIKEY = env.GOOGLE_MAP_PLACES_APIKEY;
 
 
 dotenv.config({
 dotenv.config({
@@ -67,6 +69,14 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
         'Enable NomadMania.com to access your photo library to upload your profile picture. Any violence, excess of nudity, stolen picture, or scam is forbidden',
         'Enable NomadMania.com to access your photo library to upload your profile picture. Any violence, excess of nudity, stolen picture, or scam is forbidden',
       NSPushNotificationsDescription:
       NSPushNotificationsDescription:
         'This will allow NomadMania.com to send you notifications. Also you can disable it in app settings'
         'This will allow NomadMania.com to send you notifications. Also you can disable it in app settings'
+    },
+    privacyManifests: {
+      NSPrivacyAccessedAPITypes: [
+        {
+          NSPrivacyAccessedAPIType: 'NSPrivacyAccessedAPICategoryUserDefaults',
+          NSPrivacyAccessedAPITypeReasons: ['CA92.1']
+        }
+      ]
     }
     }
   },
   },
   android: {
   android: {
@@ -74,7 +84,7 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
     config: {
     config: {
       googleMaps: {
       googleMaps: {
         apiKey: env.ANDROID_GOOGLE_MAP_APIKEY
         apiKey: env.ANDROID_GOOGLE_MAP_APIKEY
-      },
+      }
     },
     },
     googleServicesFile: './google-services.json',
     googleServicesFile: './google-services.json',
     permissions: [
     permissions: [
@@ -99,22 +109,23 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
       }
       }
     ],
     ],
     [
     [
-      "expo-build-properties",
+      'expo-build-properties',
       {
       {
         android: {
         android: {
           minSdkVersion: 24,
           minSdkVersion: 24,
-          targetSdkVersion: 34,
+          targetSdkVersion: 34
           // kotlinVersion: '1.7.1'
           // kotlinVersion: '1.7.1'
         }
         }
       }
       }
     ],
     ],
     [
     [
-      "@sentry/react-native/expo",
+      '@sentry/react-native/expo',
       {
       {
         organization: env.SENTRY_ORG,
         organization: env.SENTRY_ORG,
         project: env.SENTRY_PROJECT,
         project: env.SENTRY_PROJECT,
-        url: "https://sentry.io/"
+        url: 'https://sentry.io/'
       }
       }
-    ]
+    ],
+    ['expo-asset', 'expo-font']
   ]
   ]
 });
 });

+ 30 - 30
package.json

@@ -12,63 +12,63 @@
     "postinstall": "patch-package"
     "postinstall": "patch-package"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@react-native-community/datetimepicker": "7.2.0",
+    "@react-native-community/datetimepicker": "8.0.1",
-    "@react-native-community/netinfo": "9.3.10",
+    "@react-native-community/netinfo": "11.3.1",
     "@react-navigation/bottom-tabs": "^6.5.11",
     "@react-navigation/bottom-tabs": "^6.5.11",
     "@react-navigation/drawer": "^6.6.15",
     "@react-navigation/drawer": "^6.6.15",
     "@react-navigation/material-top-tabs": "^6.6.5",
     "@react-navigation/material-top-tabs": "^6.6.5",
     "@react-navigation/native": "^6.1.9",
     "@react-navigation/native": "^6.1.9",
     "@react-navigation/native-stack": "^6.9.17",
     "@react-navigation/native-stack": "^6.9.17",
     "@react-navigation/stack": "^6.3.20",
     "@react-navigation/stack": "^6.3.20",
-    "@sentry/react-native": "^5.29.0",
+    "@sentry/react-native": "~5.22.0",
-    "@shopify/flash-list": "1.4.3",
+    "@shopify/flash-list": "1.6.4",
     "@tanstack/react-query": "latest",
     "@tanstack/react-query": "latest",
     "@turf/turf": "^6.5.0",
     "@turf/turf": "^6.5.0",
     "axios": "^1.6.1",
     "axios": "^1.6.1",
     "better-react-native-image-viewing": "^0.2.7",
     "better-react-native-image-viewing": "^0.2.7",
     "dotenv": "^16.3.1",
     "dotenv": "^16.3.1",
-    "expo": "~49.0.15",
+    "expo": "^51.0.9",
-    "expo-asset": "8.10.1",
+    "expo-asset": "~10.0.10",
-    "expo-build-properties": "~0.8.3",
+    "expo-build-properties": "~0.12.5",
-    "expo-checkbox": "~2.4.0",
+    "expo-checkbox": "~3.0.0",
-    "expo-constants": "14.4.2",
+    "expo-constants": "~16.0.2",
-    "expo-dev-client": "~2.4.12",
+    "expo-dev-client": "~4.0.26",
-    "expo-file-system": "15.4.5",
+    "expo-file-system": "~17.0.1",
-    "expo-font": "11.4.0",
+    "expo-font": "~12.0.10",
-    "expo-image": "~1.3.5",
+    "expo-image": "~1.12.15",
-    "expo-image-picker": "~14.3.2",
+    "expo-image-picker": "~15.0.7",
-    "expo-location": "~16.1.0",
+    "expo-location": "~17.0.1",
-    "expo-notifications": "~0.20.1",
+    "expo-notifications": "~0.28.16",
-    "expo-splash-screen": "~0.20.5",
+    "expo-splash-screen": "~0.27.5",
-    "expo-sqlite": "~11.3.3",
+    "expo-sqlite": "~14.0.6",
-    "expo-updates": "~0.18.19",
+    "expo-updates": "~0.25.24",
     "formik": "^2.4.5",
     "formik": "^2.4.5",
     "moment": "^2.29.4",
     "moment": "^2.29.4",
     "patch-package": "^8.0.0",
     "patch-package": "^8.0.0",
     "promise": "^8.3.0",
     "promise": "^8.3.0",
     "react": "18.2.0",
     "react": "18.2.0",
-    "react-native": "0.72.10",
+    "react-native": "0.74.5",
     "react-native-animated-pagination-dot": "^0.4.0",
     "react-native-animated-pagination-dot": "^0.4.0",
     "react-native-calendars": "^1.1304.1",
     "react-native-calendars": "^1.1304.1",
     "react-native-device-detection": "^0.2.1",
     "react-native-device-detection": "^0.2.1",
-    "react-native-gesture-handler": "~2.12.0",
+    "react-native-gesture-handler": "~2.16.1",
     "react-native-google-places-autocomplete": "^2.5.6",
     "react-native-google-places-autocomplete": "^2.5.6",
     "react-native-image-viewing": "^0.2.2",
     "react-native-image-viewing": "^0.2.2",
     "react-native-keyboard-aware-scroll-view": "^0.9.5",
     "react-native-keyboard-aware-scroll-view": "^0.9.5",
     "react-native-map-clustering": "^3.4.2",
     "react-native-map-clustering": "^3.4.2",
-    "react-native-maps": "1.7.1",
+    "react-native-maps": "1.14.0",
     "react-native-mmkv": "^2.11.0",
     "react-native-mmkv": "^2.11.0",
     "react-native-modal": "^13.0.1",
     "react-native-modal": "^13.0.1",
-    "react-native-pager-view": "6.2.0",
+    "react-native-pager-view": "6.3.0",
     "react-native-paper": "^5.12.3",
     "react-native-paper": "^5.12.3",
     "react-native-progress": "^5.0.1",
     "react-native-progress": "^5.0.1",
-    "react-native-reanimated": "~3.3.0",
+    "react-native-reanimated": "~3.10.1",
     "react-native-reanimated-carousel": "^3.5.1",
     "react-native-reanimated-carousel": "^3.5.1",
-    "react-native-safe-area-context": "4.6.3",
+    "react-native-safe-area-context": "4.10.5",
-    "react-native-screens": "~3.22.0",
+    "react-native-screens": "3.31.1",
     "react-native-searchable-dropdown-kj": "^1.9.1",
     "react-native-searchable-dropdown-kj": "^1.9.1",
     "react-native-share": "^10.2.1",
     "react-native-share": "^10.2.1",
-    "react-native-svg": "13.9.0",
+    "react-native-svg": "15.2.0",
     "react-native-tab-view": "^3.5.2",
     "react-native-tab-view": "^3.5.2",
     "react-native-view-shot": "^3.7.0",
     "react-native-view-shot": "^3.7.0",
     "react-native-walkthrough-tooltip": "^1.6.0",
     "react-native-walkthrough-tooltip": "^1.6.0",
@@ -76,11 +76,11 @@
     "zustand": "^4.4.7"
     "zustand": "^4.4.7"
   },
   },
   "devDependencies": {
   "devDependencies": {
-    "@babel/core": "^7.20.0",
+    "@babel/core": "^7.25.2",
     "@types/react": "~18.2.14",
     "@types/react": "~18.2.14",
     "prettier": "^3.1.0",
     "prettier": "^3.1.0",
-    "react-native-svg-transformer": "^1.1.0",
+    "react-native-svg-transformer": "^1.5.0",
-    "typescript": "^5.1.3"
+    "typescript": "~5.3.3"
   },
   },
   "private": true
   "private": true
 }
 }

+ 5 - 31
src/components/MenuDrawer/index.tsx

@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React, { useState } from 'react';
 import { View, Image, Linking, Text, Switch, Platform } from 'react-native';
 import { View, Image, Linking, Text, Switch, Platform } from 'react-native';
 import { CommonActions, useNavigation } from '@react-navigation/native';
 import { CommonActions, useNavigation } from '@react-navigation/native';
 import * as Notifications from 'expo-notifications';
 import * as Notifications from 'expo-notifications';
@@ -20,6 +20,7 @@ import InfoIcon from 'assets/icons/info-solid.svg';
 import { APP_VERSION, FASTEST_MAP_HOST } from 'src/constants';
 import { APP_VERSION, FASTEST_MAP_HOST } from 'src/constants';
 import { useNotification } from 'src/contexts/NotificationContext';
 import { useNotification } from 'src/contexts/NotificationContext';
 import { usePostSaveNotificationTokenMutation } from '@api/user';
 import { usePostSaveNotificationTokenMutation } from '@api/user';
+import { usePushNotification } from 'src/contexts/PushNotificationContext';
 
 
 export const MenuDrawer = (props: any) => {
 export const MenuDrawer = (props: any) => {
   const { mutate: deleteUser } = useDeleteUserMutation();
   const { mutate: deleteUser } = useDeleteUserMutation();
@@ -33,10 +34,8 @@ export const MenuDrawer = (props: any) => {
   });
   });
   const { updateNotificationStatus } = useNotification();
   const { updateNotificationStatus } = useNotification();
   const { mutateAsync: saveNotificationToken } = usePostSaveNotificationTokenMutation();
   const { mutateAsync: saveNotificationToken } = usePostSaveNotificationTokenMutation();
-  const [isSubscribed, setIsSubscribed] = useState(
-    (storage.get('subscribed', StoreType.BOOLEAN) as boolean) ?? false
-  );
   const [shouldOpenWarningModal, setShouldOpenWarningModal] = useState(false);
   const [shouldOpenWarningModal, setShouldOpenWarningModal] = useState(false);
+  const { isSubscribed, toggleSubscription } = usePushNotification();
 
 
   const openModal = (type: string, message: string, action: any) => {
   const openModal = (type: string, message: string, action: any) => {
     setModalInfo({
     setModalInfo({
@@ -74,8 +73,7 @@ export const MenuDrawer = (props: any) => {
     const deviceData = await registerForPushNotificationsAsync();
     const deviceData = await registerForPushNotificationsAsync();
 
 
     if (deviceData?.notificationToken) {
     if (deviceData?.notificationToken) {
-      storage.set('subscribed', true);
+      toggleSubscription();
-      setIsSubscribed(true);
       await saveNotificationToken({
       await saveNotificationToken({
         token,
         token,
         platform: deviceData.platform,
         platform: deviceData.platform,
@@ -84,33 +82,9 @@ export const MenuDrawer = (props: any) => {
     }
     }
   };
   };
 
 
-  useEffect(() => {
-    let notificationListener: any;
-    let responseListener: any;
-
-    if (isSubscribed) {
-      notificationListener = Notifications.addNotificationReceivedListener((notification) => {
-        console.log('notification', notification.request);
-      });
-
-      responseListener = Notifications.addNotificationResponseReceivedListener((response) => {
-        const data = response.notification.request.content.data;
-        console.log('payload', response.notification.request.trigger?.payload);
-        console.log('data', data);
-      });
-    }
-
-    return () => {
-      if (notificationListener) Notifications.removeNotificationSubscription(notificationListener);
-      if (responseListener) Notifications.removeNotificationSubscription(responseListener);
-    };
-  }, [isSubscribed]);
-
   const toggleSwitch = async () => {
   const toggleSwitch = async () => {
     if (isSubscribed) {
     if (isSubscribed) {
-      storage.set('subscribed', false);
+      toggleSubscription();
-      storage.remove('deviceToken');
-      setIsSubscribed(false);
     } else {
     } else {
       const { status } = await Notifications.getPermissionsAsync();
       const { status } = await Notifications.getPermissionsAsync();
       if (status !== 'granted') {
       if (status !== 'granted') {

+ 95 - 0
src/contexts/PushNotificationContext.tsx

@@ -0,0 +1,95 @@
+import React, { useEffect, useState, useContext, createContext } from 'react';
+import * as Notifications from 'expo-notifications';
+import { storage, StoreType } from 'src/storage';
+import { Linking, Platform } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
+
+const PushNotificationContext = createContext(null);
+
+export const usePushNotification = () => useContext(PushNotificationContext);
+
+export const PushNotificationProvider = ({ children }) => {
+  const [isSubscribed, setIsSubscribed] = useState(
+    (storage.get('subscribed', StoreType.BOOLEAN) as boolean) ?? false
+  );
+  const navigation = useNavigation();
+
+  const lastNotificationResponse = Notifications.useLastNotificationResponse();
+
+  useEffect(() => {
+    if (lastNotificationResponse && Platform.OS === 'android') {
+      console.log(
+        'lastNotificationResponse',
+        lastNotificationResponse.notification.request.content.data
+      );
+      const data = lastNotificationResponse.notification.request.content.data;
+
+      if (data?.screen) {
+        navigation.navigate(data.screen as never);
+      }
+      if (data?.url) {
+        Linking.openURL(data.url);
+      }
+    }
+  }, [lastNotificationResponse]);
+
+  useEffect(() => {
+    if (isSubscribed) {
+      const notificationListener = Notifications.addNotificationReceivedListener((notification) => {
+        console.log('Notification received', notification.request);
+      });
+
+      const responseListener = Notifications.addNotificationResponseReceivedListener((response) => {
+        console.log('Notification response received', response.notification.request);
+
+        let screenName;
+        let url;
+        if (Platform.OS === 'ios') {
+          console.log('data ios', response.notification.request.trigger?.payload);
+          screenName = response.notification.request.trigger?.payload?.screen;
+          url = response.notification.request.trigger?.payload?.url;
+        }
+
+        if (screenName) {
+          navigation.navigate(screenName as never);
+        }
+        if (url) {
+          Linking.openURL(url);
+        }
+      });
+
+      return () => {
+        notificationListener.remove();
+        responseListener.remove();
+      };
+    }
+  }, [isSubscribed]);
+
+  const subscribeToNotifications = async () => {
+    storage.set('subscribed', true);
+    setIsSubscribed(true);
+  };
+
+  const unsubscribeFromNotifications = async () => {
+    await removeNotificationTokenFromServer();
+    storage.remove('deviceToken');
+    storage.set('subscribed', false);
+    setIsSubscribed(false);
+  };
+
+  const toggleSubscription = async () => {
+    if (isSubscribed) {
+      await unsubscribeFromNotifications();
+    } else {
+      await subscribeToNotifications();
+    }
+  };
+
+  return (
+    <PushNotificationContext.Provider value={{ isSubscribed, toggleSubscription }}>
+      {children}
+    </PushNotificationContext.Provider>
+  );
+};
+
+async function removeNotificationTokenFromServer() {}

+ 1 - 1
src/database/index.ts

@@ -1,4 +1,4 @@
-import * as SQLite from 'expo-sqlite';
+import * as SQLite from 'expo-sqlite/legacy';
 import NetInfo, { NetInfoState } from '@react-native-community/netinfo';
 import NetInfo, { NetInfoState } from '@react-native-community/netinfo';
 import { StoreType, storage } from 'src/storage';
 import { StoreType, storage } from 'src/storage';
 import { fetchLimitedRanking, fetchLpi, fetchInHistory, fetchInMemoriam } from '@api/ranking';
 import { fetchLimitedRanking, fetchLpi, fetchInHistory, fetchInMemoriam } from '@api/ranking';

+ 1 - 1
src/db/index.ts

@@ -1,4 +1,4 @@
-import * as SQLite from 'expo-sqlite';
+import * as SQLite from 'expo-sqlite/legacy';
 import * as FileSystem from 'expo-file-system';
 import * as FileSystem from 'expo-file-system';
 import { Asset } from 'expo-asset';
 import { Asset } from 'expo-asset';
 import { API_HOST } from 'src/constants';
 import { API_HOST } from 'src/constants';

+ 1 - 1
src/modules/map/regionData.ts

@@ -1,4 +1,4 @@
-import { SQLiteDatabase } from 'expo-sqlite';
+import { SQLiteDatabase } from 'expo-sqlite/legacy';
 
 
 export const getData = async (
 export const getData = async (
   db: SQLiteDatabase | null, 
   db: SQLiteDatabase | null,