diff --git a/App.tsx b/App.tsx index 67a67c16..a736e37f 100644 --- a/App.tsx +++ b/App.tsx @@ -1,5 +1,5 @@ import * as SplashScreen from 'expo-splash-screen' -import React, { useEffect, useState } from 'react' +import React, { useCallback, useEffect, useState } from 'react' import { QueryClient, QueryClientProvider } from 'react-query' import { Provider } from 'react-redux' import { PersistGate } from 'redux-persist/integration/react' @@ -8,6 +8,7 @@ import { Index } from '@root/Index' import { persistor, store } from '@root/store' import ThemeManager from '@utils/styles/ThemeManager' import { resetLocal, updateLocal } from '@root/utils/slices/instancesSlice' +import client from '@root/api/client' const queryClient = new QueryClient() @@ -22,6 +23,8 @@ const queryClient = new QueryClient() const App: React.FC = () => { const [appLoaded, setAppLoaded] = useState(false) + const [startVerification, setStartVerification] = useState(false) + const [localCorrupt, setLocalCorrupt] = useState(false) useEffect(() => { const delaySplash = async () => { try { @@ -45,38 +48,66 @@ const App: React.FC = () => { } }, [appLoaded]) + const onBeforeLift = useCallback(() => setStartVerification(true), []) + useEffect(() => { + const verifyCredentials = async () => { + const localUrl = store.getState().instances.local.url + const localToken = store.getState().instances.local.token + + if (localUrl && localToken) { + client({ + method: 'get', + instance: 'remote', + instanceDomain: localUrl, + url: `accounts/verify_credentials`, + headers: { Authorization: `Bearer ${localToken}` } + }) + .then(res => { + if (res.body.id !== store.getState().instances.local.account.id) { + store.dispatch(resetLocal()) + setLocalCorrupt(true) + setAppLoaded(true) + } + }) + .catch(() => { + store.dispatch(resetLocal()) + setLocalCorrupt(true) + setAppLoaded(true) + }) + } else { + setAppLoaded(true) + } + } + + if (startVerification) { + verifyCredentials() + } + }, [startVerification]) + + const main = useCallback( + bootstrapped => { + if (bootstrapped && appLoaded) { + require('@root/i18n/i18n') + return ( + + + + ) + } else { + return null + } + }, + [appLoaded] + ) + return ( { - const localUrl = store.getState().instances.local.url - const localToken = store.getState().instances.local.token - if (localUrl && localToken) { - const dispatchStatus = await store.dispatch( - updateLocal({ url: localUrl, token: localToken }) - ) - if (dispatchStatus.type.includes('/rejected')) { - store.dispatch(resetLocal()) - } - } - setAppLoaded(true) - }} - > - {bootstrapped => { - if (bootstrapped) { - require('@root/i18n/i18n') - return ( - - - - ) - } else { - return null - } - }} - + onBeforeLift={onBeforeLift} + children={main} + /> ) diff --git a/src/Index.tsx b/src/Index.tsx index 320fa505..98cd674d 100644 --- a/src/Index.tsx +++ b/src/Index.tsx @@ -3,7 +3,7 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' import { NavigationContainer } from '@react-navigation/native' import { enableScreens } from 'react-native-screens' -import React from 'react' +import React, { useEffect } from 'react' import { StatusBar } from 'react-native' import Toast from 'react-native-toast-message' import { Feather } from '@expo/vector-icons' @@ -16,7 +16,7 @@ import ScreenMe from '@screens/Me' import { themes } from '@utils/styles/themes' import { useTheme } from '@utils/styles/ThemeManager' import getCurrentTab from '@utils/getCurrentTab' -import { toastConfig } from '@components/toast' +import { toast, toastConfig } from '@components/toast' import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' import { getLocalUrl } from './utils/slices/instancesSlice' @@ -32,7 +32,11 @@ export type RootStackParamList = { 'Screen-Me': undefined } -export const Index: React.FC = () => { +export interface Props { + localCorrupt: boolean +} + +export const Index: React.FC = ({ localCorrupt }) => { const localInstance = useSelector(getLocalUrl) const { i18n } = useTranslation() const { mode, theme } = useTheme() @@ -41,6 +45,18 @@ export const Index: React.FC = () => { dark = 'light-content' } + useEffect(() => { + const showLocalCorrect = localCorrupt + ? toast({ + type: 'error', + content: '登录已过期', + description: '请重新登录', + autoHide: false + }) + : undefined + return showLocalCorrect + }, [localCorrupt]) + return ( <> diff --git a/src/components/toast.tsx b/src/components/toast.tsx index 26fe3fca..bd39b7b6 100644 --- a/src/components/toast.tsx +++ b/src/components/toast.tsx @@ -63,13 +63,21 @@ const ToastBase = ({ config }: { config: Config }) => { > - - {config.text1} - + + + {config.text1} + + {config.text2 && ( + + {config.text2} + + )} + ) @@ -91,11 +99,18 @@ const styles = StyleSheet.create({ flex: 1, flexDirection: 'row', justifyContent: 'center', + alignItems: 'center', padding: StyleConstants.Spacing.M }, - text: { - fontSize: StyleConstants.Font.Size.M, + texts: { marginLeft: StyleConstants.Spacing.S + }, + text1: { + fontSize: StyleConstants.Font.Size.M + }, + text2: { + fontSize: StyleConstants.Font.Size.S, + marginTop: StyleConstants.Spacing.S } })