mirror of https://github.com/tooot-app/app
Only one API call when app just started
This commit is contained in:
parent
2bd9e6be2f
commit
436b0ab4dd
87
App.tsx
87
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 (
|
||||
<ThemeManager>
|
||||
<Index localCorrupt={localCorrupt} />
|
||||
</ThemeManager>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
[appLoaded]
|
||||
)
|
||||
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Provider store={store}>
|
||||
<PersistGate
|
||||
persistor={persistor}
|
||||
onBeforeLift={async () => {
|
||||
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 (
|
||||
<ThemeManager>
|
||||
<Index />
|
||||
</ThemeManager>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}}
|
||||
</PersistGate>
|
||||
onBeforeLift={onBeforeLift}
|
||||
children={main}
|
||||
/>
|
||||
</Provider>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
|
|
|
@ -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<Props> = ({ 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 (
|
||||
<>
|
||||
<StatusBar barStyle={barStyle[mode]} />
|
||||
|
|
|
@ -63,13 +63,21 @@ const ToastBase = ({ config }: { config: Config }) => {
|
|||
>
|
||||
<View style={styles.container}>
|
||||
<Feather
|
||||
// @ts-ignore
|
||||
name={iconSet[config.type]}
|
||||
color={theme[config.type]}
|
||||
size={StyleConstants.Font.Size.M + 2}
|
||||
/>
|
||||
<Text style={[styles.text, { color: theme.primary }]}>
|
||||
{config.text1}
|
||||
</Text>
|
||||
<View style={styles.texts}>
|
||||
<Text style={[styles.text1, { color: theme.primary }]}>
|
||||
{config.text1}
|
||||
</Text>
|
||||
{config.text2 && (
|
||||
<Text style={[styles.text2, { color: theme.secondary }]}>
|
||||
{config.text2}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)
|
||||
|
@ -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
|
||||
}
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue