Bladeren bron

feat: migrate to MMKV || async-storage.ts deleting

Oleksandr Honcharov 1 jaar geleden
bovenliggende
commit
ebf1875e24

+ 1 - 1
.gitignore

@@ -37,5 +37,5 @@ yarn-error.*
 # dev
 .idea
 .vscode
-.env
 temp
+android

+ 2 - 11
Route.tsx

@@ -21,7 +21,7 @@ import TravellersScreen from './src/screens/InAppScreens/TravellersScreen';
 import { EditPersonalInfo } from './src/screens/InAppScreens/ProfileScreen/Profile/edit-personal-info';
 
 import { NAVIGATION_PAGES } from './src/types';
-import { storageGet } from './src/storage';
+import { storage, StoreType } from './src/storage';
 import { openDatabases } from './src/db';
 
 import TabBarButton from './src/components/TabBarButton';
@@ -33,7 +33,7 @@ const BottomTab = createBottomTabNavigator();
 SplashScreen.preventAutoHideAsync();
 
 const Route = () => {
-  const [token, setToken] = useState<string>('');
+  const token = storage.get('token', StoreType.STRING);
 
   const [fontsLoaded] = useFonts({
     'redhat-900': require('./assets/fonts/RedHatDisplay-Black-900.ttf'),
@@ -61,15 +61,6 @@ const Route = () => {
     hideSplashScreen();
   }, [fontsLoaded, dbLoaded]);
 
-  useEffect(() => {
-    async function getToken() {
-      const tokenStorage = await storageGet('token');
-      setToken(tokenStorage as unknown as string);
-    }
-
-    getToken();
-  }, []);
-
   if (!fontsLoaded) {
     return null;
   }

+ 1 - 1
app.config.ts

@@ -20,7 +20,7 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
   // Should be updated after every production release (deploy to AppStore/PlayMarket)
   version: '1.0.0',
   // Should be updated after every dependency change
-  runtimeVersion: '1.1',
+  runtimeVersion: '1.2',
   orientation: 'portrait',
   icon: './assets/icon.png',
   userInterfaceStyle: 'light',

+ 1 - 1
package.json

@@ -11,7 +11,6 @@
     "publish:prod": "ENV=production eas update --branch production"
   },
   "dependencies": {
-    "@react-native-async-storage/async-storage": "1.18.2",
     "@react-native-community/datetimepicker": "7.2.0",
     "@react-native-community/masked-view": "^0.1.11",
     "@react-native-community/netinfo": "9.3.10",
@@ -44,6 +43,7 @@
     "react-native-gesture-handler": "~2.12.0",
     "react-native-keyboard-aware-scroll-view": "^0.9.5",
     "react-native-maps": "1.7.1",
+    "react-native-mmkv": "^2.11.0",
     "react-native-pager-view": "6.2.0",
     "react-native-reanimated": "~3.3.0",
     "react-native-render-html": "^6.3.4",

+ 18 - 29
src/screens/InAppScreens/MapScreen/index.tsx

@@ -1,10 +1,10 @@
-import { View, Platform, TouchableOpacity, Text, Linking, Animated } from 'react-native';
-import React, { useEffect, useState, useRef, useMemo } from 'react';
-import MapView, { UrlTile, Geojson, Marker } from 'react-native-maps';
+import { Animated, Linking, Platform, Text, TouchableOpacity, View } from 'react-native';
+import React, { useEffect, useMemo, useRef, useState } from 'react';
+import MapView, { Geojson, Marker, UrlTile } from 'react-native-maps';
 import * as turf from '@turf/turf';
 import * as FileSystem from 'expo-file-system';
 import * as Location from 'expo-location';
-import { storageGet } from '../../../storage';
+import { storage, StoreType } from '../../../storage';
 
 import MenuIcon from '../../../../assets/icons/menu.svg';
 import SearchIcon from '../../../../assets/icons/search.svg';
@@ -17,31 +17,32 @@ import dareRegions from '../../../../assets/geojson/mqp.json';
 
 import NetInfo from '@react-native-community/netinfo';
 import { getFirstDatabase, getSecondDatabase } from '../../../db';
-import { RegionPopup, LocationPopup } from '../../../components';
+import { LocationPopup, RegionPopup } from '../../../components';
 
 import { styles } from './style';
 import {
-  findRegionInDataset,
   calculateMapRegion,
   clusterMarkers,
   filterCandidates,
-  processMarkerData,
+  filterCandidatesMarkers,
+  findRegionInDataset,
   processIconUrl,
-  filterCandidatesMarkers
+  processMarkerData
 } from '../../../utils/mapHelpers';
 import { getData } from '../../../modules/map/regionData';
 import { fetchSeriesData } from '../../../modules/map/series/queries/use-post-get-series';
 import MarkerItem from './MarkerItem';
 import ClusterItem from './ClusterItem';
 import {
-  Region,
-  Series,
-  ItemSeries,
-  MarkerData,
   ClusterData,
+  FeatureCollection,
+  ItemSeries,
   MapScreenProps,
-  FeatureCollection
+  MarkerData,
+  Region,
+  Series
 } from '../../../types/map';
+
 const MAP_HOST = 'https://maps.nomadmania.eu';
 
 const tilesBaseURL = `${MAP_HOST}/tiles_osm`;
@@ -58,8 +59,8 @@ const localDareDir = `${FileSystem.cacheDirectory}tiles/regions_mqp`;
 const AnimatedMarker = Animated.createAnimatedComponent(Marker);
 
 const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
-  const [userId, setUserId] = useState<string | null>('');
-  const [token, setToken] = useState<string | null>('');
+  const userId = storage.get('uid', StoreType.STRING);
+  const token = storage.get('token', StoreType.STRING);
   const visitedTiles = `${MAP_HOST}/tiles_nm/user_visited/${userId}`;
 
   const mapRef = useRef<MapView>(null);
@@ -82,18 +83,6 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
   const currentTokenRef = useRef(0);
   const strokeWidthAnim = useRef(new Animated.Value(2)).current;
 
-  useEffect(() => {
-    const fetchData = async () => {
-      const fetchedUserId = await storageGet('uid');
-      const fetchedToken = await storageGet('token');
-
-      setUserId(fetchedUserId);
-      setToken(fetchedToken);
-    };
-
-    fetchData();
-  }, []);
-
   useEffect(() => {
     Animated.loop(
       Animated.sequence([
@@ -193,7 +182,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
     const regionIds = regionsFound.map(
       (region: { properties: { id: any } }) => region.properties.id
     );
-    const candidatesMarkers = await fetchSeriesData(token, JSON.stringify(regionIds));
+    const candidatesMarkers = await fetchSeriesData(String(token), JSON.stringify(regionIds));
 
     if (thisToken !== currentTokenRef.current) return;
 
@@ -325,7 +314,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
       mapRef.current?.animateToRegion(region, 1000);
 
       if (tableName === 'regions') {
-        const seriesData = await fetchSeriesData(token, JSON.stringify([id]));
+        const seriesData = await fetchSeriesData(String(token), JSON.stringify([id]));
         setSeries(seriesData.series);
         const allMarkers = seriesData.items.map(processMarkerData);
         setProcessedMarkers(allMarkers);

+ 5 - 14
src/screens/InAppScreens/ProfileScreen/Profile/edit-personal-info.tsx

@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React from 'react';
 import { ScrollView, View, Text } from 'react-native';
 import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
 import { Formik } from 'formik';
@@ -20,7 +20,7 @@ import { userQueryKeys } from '../../../../modules/auth/user/user-query-keys';
 
 import type { PostSetProfileData } from '../../../../modules/auth/user/user-api';
 
-import { storageGet } from '../../../../storage';
+import { storage, StoreType } from '../../../../storage';
 import { Colors } from '../../../../theme';
 
 import FacebookIcon from '../../../../../assets/icons/facebook.svg';
@@ -48,23 +48,14 @@ const ProfileSchema = yup.object({
 });
 
 export const EditPersonalInfo = () => {
-  const [token, setToken] = useState<string>('');
+  const token = storage.get('token', StoreType.STRING);
 
   const { mutate: updateProfile, data: updateResponse, reset } = usePostSetProfileMutation();
 
-  useEffect(() => {
-    async function getToken() {
-      setToken((await storageGet('token')) as unknown as string);
-    }
-    reset();
-
-    getToken();
-  }, []);
-
   const navigation = useNavigation();
   const queryClient = useQueryClient();
 
-  const { data, error } = usePostGetProfileQuery(token!, true);
+  const { data, error } = usePostGetProfileQuery(String(token), true);
 
   const regions = useGetRegionsWithFlagQuery(true);
 
@@ -103,7 +94,7 @@ export const EditPersonalInfo = () => {
             }}
             onSubmit={async (values) => {
               const profileData: PostSetProfileData = {
-                token: token,
+                token: String(token),
                 user: {
                   username: values.username,
                   email: values.email,

+ 4 - 13
src/screens/InAppScreens/ProfileScreen/index.tsx

@@ -1,4 +1,4 @@
-import React, { FC, ReactNode, useEffect, useState } from 'react';
+import React, { FC, ReactNode } from 'react';
 import { Text, TouchableOpacity, View } from 'react-native';
 import { Image } from 'expo-image';
 import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
@@ -15,7 +15,7 @@ import { usePostGetProfileQuery } from '../../../modules/auth/user/queries/use-p
 import { NAVIGATION_PAGES } from '../../../types';
 import { navigationOpts } from './navigation-opts';
 
-import { storageGet } from '../../../storage';
+import { storage, StoreType } from '../../../storage';
 
 import PenIcon from '../../../../assets/icons/pen.svg';
 
@@ -57,18 +57,9 @@ type Props = {
 };
 
 const ProfileScreen: FC<Props> = ({ navigation }) => {
-  const [token, setToken] = useState<string>('');
+  const token = storage.get('token', StoreType.STRING);
 
-  const { data, error } = usePostGetProfileQuery(token!, true);
-
-  useEffect(() => {
-    async function getToken() {
-      const storageToken = await storageGet('token');
-      setToken(storageToken as unknown as string);
-    }
-
-    getToken();
-  }, []);
+  const { data, error } = usePostGetProfileQuery(String(token), true);
 
   if (!data) return <Text>Loading</Text>;
 

+ 3 - 3
src/screens/LoginScreen/index.tsx

@@ -7,7 +7,7 @@ import * as yup from 'yup';
 import { Header, Input, Button, BigText, PageWrapper } from '../../components';
 
 import { ButtonVariants } from '../../types/components';
-import { storageSet } from '../../storage';
+import { storage } from '../../storage';
 import { NAVIGATION_PAGES } from '../../types';
 
 import { useLoginMutation } from '../../modules/auth/api/queries/use-post-login';
@@ -28,8 +28,8 @@ const LoginScreen: FC<Props> = ({ navigation }) => {
 
   if (data) {
     if (data.token) {
-      storageSet('token', data.token);
-      storageSet('uid', data.uid.toString());
+      storage.set('token', data.token);
+      storage.set('uid', data.uid);
       dispatch(
         CommonActions.reset({
           index: 1,

+ 3 - 3
src/screens/RegisterScreen/EditAccount/index.tsx

@@ -9,7 +9,7 @@ import { AvatarPicker, BigText, Button, Header, Input, PageWrapper } from '../..
 import { InputDatePicker } from '../../../components/Calendar/InputDatePicker';
 import { ModalFlatList } from '../../../components/FlatList/modal-flatlist';
 import { useRegisterMutation } from '../../../modules/auth/api/queries/use-post-register';
-import { storageSet } from '../../../storage';
+import { storage } from '../../../storage';
 
 import store from '../../../storage/zustand';
 import { NAVIGATION_PAGES } from '../../../types';
@@ -33,8 +33,8 @@ const EditAccount = () => {
 
   if (data) {
     if (data.token) {
-      storageSet('token', data.token);
-      storageSet('uid', data.uid.toString());
+      storage.set('token', data.token);
+      storage.set('uid', data.uid.toString());
       dispatch(
         CommonActions.reset({
           index: 1,

+ 0 - 13
src/storage/async-storage.ts

@@ -1,13 +0,0 @@
-import AsyncStorage from '@react-native-async-storage/async-storage';
-
-export const storageGet = (key: string) => {
-  return AsyncStorage.getItem(key);
-};
-
-export const storageSet = (key: string, value: string) => {
-  AsyncStorage.setItem(key, value).then();
-};
-
-export const storageDelete = (key: string) => {
-  AsyncStorage.removeItem(key).then();
-};

+ 1 - 9
src/storage/index.ts

@@ -1,9 +1 @@
-/*
- * MMKV library needs prebuild
- * with expo EAS build.
- * For now it's disabled and
- * waiting for dev build.
- */
-
-// export * from './mmkv';
-export * from './async-storage';
+export * from './mmkv';

+ 29 - 35
src/storage/mmkv.ts

@@ -1,36 +1,30 @@
-/*
- * !WARNING
- * CURRENTLY DISABLED
- * TODO
- * */
+import { MMKV } from 'react-native-mmkv';
 
-// import { MMKV } from 'react-native-mmkv';
-//
-// const storageMMKV = new MMKV();
-//
-// const get = (key: string, type: StoreType) => {
-//   switch (type) {
-//     case StoreType.STRING:
-//       return storageMMKV.getString(key);
-//     case StoreType.BOOLEAN:
-//       return storageMMKV.getBoolean(key);
-//     case StoreType.NUMBER:
-//       return storageMMKV.getNumber(key);
-//   }
-// };
-//
-// const set = (key: string, value: string | boolean | number) => {
-//   storageMMKV.set(key, value);
-// };
-//
-// const remove = (key: string) => {
-//   storageMMKV.delete(key);
-// };
-//
-// export const storage = { get, set, remove };
-//
-// export enum StoreType {
-//   STRING = 'string',
-//   NUMBER = 'number',
-//   BOOLEAN = 'boolean'
-// }
+const storageMMKV = new MMKV();
+
+const get = (key: string, type: StoreType) => {
+  switch (type) {
+    case StoreType.STRING:
+      return storageMMKV.getString(key);
+    case StoreType.BOOLEAN:
+      return storageMMKV.getBoolean(key);
+    case StoreType.NUMBER:
+      return storageMMKV.getNumber(key);
+  }
+};
+
+const set = (key: string, value: string | boolean | number) => {
+  storageMMKV.set(key, value);
+};
+
+const remove = (key: string) => {
+  storageMMKV.delete(key);
+};
+
+export const storage = { get, set, remove };
+
+export enum StoreType {
+  STRING = 'string',
+  NUMBER = 'number',
+  BOOLEAN = 'boolean'
+}