From bac973fb3d933c383cc69612c7ffc45ece837dde Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sun, 29 Sep 2024 13:19:11 +0530 Subject: Switch to jotai atom with storage + suspense for favorites list --- src/AppView.tsx | 27 +++++++++++++++++++ src/View.tsx | 30 --------------------- src/components/AppMenu.tsx | 5 +++- src/components/Favorites.tsx | 4 +-- src/hooks/useFavorites.ts | 64 +++++++++++++++----------------------------- 5 files changed, 55 insertions(+), 75 deletions(-) create mode 100644 src/AppView.tsx delete mode 100644 src/View.tsx (limited to 'src') diff --git a/src/AppView.tsx b/src/AppView.tsx new file mode 100644 index 0000000..cca64f6 --- /dev/null +++ b/src/AppView.tsx @@ -0,0 +1,27 @@ +import React, {useEffect, useState} from 'react'; +import Swiper from 'react-native-swiper'; +import {AppList} from './screens/AppList'; +import {Home} from './screens/Home'; +import {useInstalledApps} from './hooks/useInstalledApps'; + +export const AppView: React.FC = React.memo(() => { + const {refreshApps} = useInstalledApps(); + const [screenIndex, setScreenIndex] = useState(0); + + useEffect(() => { + refreshApps(); + }, [screenIndex, refreshApps]); + + return ( + } + activeDot={<>} + onIndexChanged={setScreenIndex}> + + + + ); +}); diff --git a/src/View.tsx b/src/View.tsx deleted file mode 100644 index 110e3fe..0000000 --- a/src/View.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React, {useEffect, useState} from 'react'; -import Swiper from 'react-native-swiper'; -import {AppList} from './screens/AppList'; -import {Home} from './screens/Home'; -import {useInstalledApps} from './hooks/useInstalledApps'; -import {useFavorites} from './hooks/useFavorites'; - -export const View: React.FC = React.memo(() => { - const {refreshApps} = useInstalledApps(); - const {refreshFavorites} = useFavorites(); - const [screenIndex, setScreenIndex] = useState(0); - - useEffect(() => { - refreshApps(); - refreshFavorites(); - }, [screenIndex, refreshApps, refreshFavorites]); - - return ( - } - activeDot={<>} - onIndexChanged={setScreenIndex}> - - - - ); -}); diff --git a/src/components/AppMenu.tsx b/src/components/AppMenu.tsx index 4c994ab..8938bb9 100644 --- a/src/components/AppMenu.tsx +++ b/src/components/AppMenu.tsx @@ -63,7 +63,10 @@ export const AppMenu: React.FC> = ({ return ( <> - + {children} diff --git a/src/components/Favorites.tsx b/src/components/Favorites.tsx index ed81a6b..4c8dc37 100644 --- a/src/components/Favorites.tsx +++ b/src/components/Favorites.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useEffect, useMemo} from 'react'; +import React, {useCallback, useMemo} from 'react'; import {Text, TouchableOpacity, View} from 'react-native'; import {AppDetail} from 'react-native-launcher-kit/typescript/Interfaces/InstalledApps'; import {useFavorites} from '../hooks/useFavorites'; @@ -39,7 +39,7 @@ export const Favorites: React.FC<{active: boolean}> = (_) => { const onDragEnd = useCallback( ({data}: DragEndParams) => { - setFavorites(data.map((app) => app.packageName)); + setFavorites(() => data.map((app) => app.packageName)); }, [setFavorites], ); diff --git a/src/hooks/useFavorites.ts b/src/hooks/useFavorites.ts index 24684aa..fa96211 100644 --- a/src/hooks/useFavorites.ts +++ b/src/hooks/useFavorites.ts @@ -1,55 +1,37 @@ -import {useAsyncStorage} from '@react-native-async-storage/async-storage'; +import AsyncStorage from '@react-native-async-storage/async-storage/src/AsyncStorage'; import {useStableCallback} from './useStableCallback'; -import {atom, useAtom} from 'jotai'; +import {useAtom} from 'jotai'; +import {createJSONStorage, atomWithStorage} from 'jotai/utils'; -const favoriteAppNamesAtom = atom([]); +const jsonStorage = createJSONStorage(() => AsyncStorage); +const favoriteAppNamesAtom = atomWithStorage( + 'favorites', + [], + jsonStorage, +); -const serialize = (packageNames: string[]) => JSON.stringify(packageNames); - -const deserialize = (packageNames: string): string[] => { - try { - const apps = JSON.parse(packageNames); - if (!Array.isArray(apps)) return []; - return apps; - } catch (err) { - console.error(err); - return []; - } -}; +const serialize = (packageNames: string[]) => packageNames.join(','); export const useFavorites = () => { - const favoritesStorage = useAsyncStorage('favorites'); const [favoriteAppNames, setFavoriteAppNames] = useAtom(favoriteAppNamesAtom); - const getFavoriteAppNames = useStableCallback(async (): Promise => { - const result = await favoritesStorage.getItem(); - return deserialize(result ?? 'null'); - }); - - const setFavoritesState = useStableCallback((packageNames: string[]) => { - const newNames = [...new Set(packageNames)]; - if (serialize(newNames) === serialize(favoriteAppNames)) return newNames; - - setFavoriteAppNames(newNames); - return newNames; - }); - - const setFavorites = useStableCallback(async (packageNames: string[]) => { - const newNames = setFavoritesState(packageNames); - await favoritesStorage.setItem(serialize(newNames)); - }); + const setFavorites = useStableCallback( + async ( + updater: (packageNames: string[]) => Promise | string[], + ) => { + const newNames = [...new Set(await updater(favoriteAppNames))]; + if (serialize(newNames) === serialize(favoriteAppNames)) return newNames; - const refreshFavorites = useStableCallback(async () => { - getFavoriteAppNames().then(setFavoritesState); - }); + setFavoriteAppNames(newNames); + return newNames; + }, + ); const addToFavorites = useStableCallback(async (packageName: string) => { - const names = await getFavoriteAppNames(); - setFavorites([...names, packageName]); + setFavorites((names) => [...names, packageName]); }); const removeFromFavorites = useStableCallback(async (packageName: string) => { - const names = await getFavoriteAppNames(); - setFavorites(names.filter((name) => name !== packageName)); + setFavorites((names) => names.filter((name) => name !== packageName)); }); const isFavorite = useStableCallback((packageName: string) => @@ -59,9 +41,7 @@ export const useFavorites = () => { return { addToFavorites, favoriteAppNames, - getFavoriteAppNames, isFavorite, - refreshFavorites, removeFromFavorites, setFavorites, }; -- cgit v1.3.1