From a53e4337ac7f1f773dc3c6f214d66908c483a890 Mon Sep 17 00:00:00 2001 From: hoangvu12 Date: Sat, 7 Sep 2024 17:25:04 +0700 Subject: [PATCH] feat: module updater --- src/navigation/root-navigator.tsx | 2 + src/ui/module-updater.tsx | 116 ++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 src/ui/module-updater.tsx diff --git a/src/navigation/root-navigator.tsx b/src/navigation/root-navigator.tsx index 4d504d5..ff515a5 100644 --- a/src/navigation/root-navigator.tsx +++ b/src/navigation/root-navigator.tsx @@ -10,6 +10,7 @@ import { AnimeDetailsScreen } from '@/screens/anime/details/screen'; import RecentlyWatchedScreen from '@/screens/anime/recently-watched/screen'; import { AnimeWatchScreen } from '@/screens/anime/watch/screen'; import CharacterDetailsScreen from '@/screens/character-details/screen'; +import ModuleUpdater from '@/ui/module-updater'; import Updater from '@/ui/updater'; import { NavigationContainer } from './navigation-container'; @@ -93,6 +94,7 @@ export const RootNavigator = () => { + diff --git a/src/ui/module-updater.tsx b/src/ui/module-updater.tsx new file mode 100644 index 0000000..6766055 --- /dev/null +++ b/src/ui/module-updater.tsx @@ -0,0 +1,116 @@ +import type { BottomSheetModal } from '@gorhom/bottom-sheet'; +import axios from 'axios'; +import { useAtomValue } from 'jotai/react'; +import React, { useCallback, useEffect, useRef } from 'react'; +import { ToastAndroid } from 'react-native'; +import { FlatList } from 'react-native-gesture-handler'; + +import IndexSchema from '@/core/remote-index'; +import useModules from '@/hooks/use-modules'; +import RemoteModuleItem from '@/screens/module/screens/remote/components/remote-module-item'; +import type { IndexWithUrl } from '@/screens/module/screens/remote/store'; +import { indexListAtom } from '@/screens/module/screens/remote/store'; +import type { Module } from '@/types'; + +import { Text, View } from './core'; +import BottomSheet from './core/bottom-sheet'; + +interface ModuleWithUrl extends Module { + url: string; +} + +const ModuleUpdater = () => { + const indexList = useAtomValue(indexListAtom); + const { data: modules, isLoading } = useModules({ variables: null }); + const [updatedModules, setUpdatedModules] = React.useState( + [] + ); + + const bottomSheetRef = useRef(null); + + const refreshIndex = useCallback(async (index: IndexWithUrl) => { + try { + const { data } = await axios.get(index.url); + + const validation = IndexSchema.safeParse(data); + + if (!validation.success) { + return; + } + + return validation.data; + } catch (error) { + if (error instanceof Error) { + ToastAndroid.show( + `Something went wrong when updating the index (${error.message})`, + ToastAndroid.SHORT + ); + } + } + }, []); + + const checkIndex = useCallback( + async (modules: Module[]) => { + if (!modules?.length) return; + + const updatedModules: ModuleWithUrl[] = []; + + for (const index of indexList) { + const validationData = await refreshIndex(index); + + if (!validationData?.modules?.length) continue; + + for (const module of modules) { + const indexModule = validationData.modules.find( + (m) => + m.name === module.name && + m.info.author === module.info.author && + m.version !== module.version + ); + + if (!indexModule) continue; + + updatedModules.push(indexModule); + } + } + + if (!updatedModules.length) return; + + setUpdatedModules(updatedModules); + + bottomSheetRef.current?.present(); + }, + [indexList, refreshIndex] + ); + + useEffect(() => { + if (isLoading) return; + + if (!modules?.length) return; + + checkIndex(modules); + }, [checkIndex, isLoading, modules]); + + return ( + + + + New module update available + + + item.id} + renderItem={({ item }) => { + return ( + + ); + }} + ItemSeparatorComponent={() => } + /> + + + ); +}; + +export default ModuleUpdater;