Skip to content

Commit

Permalink
feat: new architecture for reuqest & ui optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
liaoliao666 committed Dec 27, 2022
1 parent 50d8365 commit f9147ad
Show file tree
Hide file tree
Showing 33 changed files with 680 additions and 490 deletions.
9 changes: 4 additions & 5 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { focusManager } from '@tanstack/react-query'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { StatusBar } from 'expo-status-bar'
import { Provider, useAtom, useAtomValue } from 'jotai'
import { waitForAll } from 'jotai/utils'
import { Suspense, useMemo } from 'react'
import { AppStateStatus, Platform } from 'react-native'
import 'react-native-gesture-handler'
Expand All @@ -15,7 +14,7 @@ import '@/utils/dayjsPlugins'

import StyledImageViewer from './components/StyledImageViewer'
import StyledToast from './components/StyledToast'
import { cookieAtom } from './jotai/cookieAtom'
import V2exWebview from './components/V2exWebview'
import { imageViewerAtom } from './jotai/imageViewerAtom'
import { profileAtom } from './jotai/profileAtom'
import { store } from './jotai/store'
Expand Down Expand Up @@ -47,9 +46,7 @@ export default function AppWithSuspense() {
}

function App() {
const [colorScheme] = useAtomValue(
waitForAll([colorSchemeAtom, cookieAtom, profileAtom])
)
const colorScheme = useAtomValue(colorSchemeAtom)

useMemo(() => {
tw.setColorScheme(colorScheme)
Expand All @@ -76,6 +73,8 @@ function App() {
</SafeAreaProvider>

<StyledToast />

<V2exWebview />
</PersistQueryClientProvider>
</Provider>
</ActionSheetProvider>
Expand Down
4 changes: 2 additions & 2 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"expo": {
"name": "AwesomeV2ex",
"slug": "v2ex",
"version": "1.0.3",
"version": "1.0.4",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "automatic",
Expand All @@ -18,7 +18,7 @@
"ios": {
"supportsTablet": false,
"bundleIdentifier": "com.liaoliao666.v2ex",
"buildNumber": "1.0.3.2"
"buildNumber": "1.0.4.1"
},
"android": {
"adaptiveIcon": {
Expand Down
6 changes: 3 additions & 3 deletions components/Html/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ export default function Html({
h1: tw`text-body-3 border-b border-solid border-tint-border`,
h2: tw`text-body-4 border-b border-solid border-tint-border`,
h3: tw`text-body-4 border-b border-solid border-tint-border`,
h4: tw`text-body-4 border-b border-solid border-tint-border`,
h5: tw`text-body-4 border-b border-solid border-tint-border`,
h6: tw`text-body-4 border-b border-solid border-tint-border`,
h4: tw`text-body-4`,
h5: tw`text-body-5`,
h6: tw`text-body-6`,
p: tw`text-body-5`,
a: tw`text-tint-secondary no-underline`,
hr: {
Expand Down
6 changes: 3 additions & 3 deletions components/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { SafeAreaView } from 'react-native-safe-area-context'
import Money from '@/components/Money'
import Space from '@/components/Space'
import StyledImage from '@/components/StyledImage'
import { cookieAtom } from '@/jotai/cookieAtom'
import { profileAtom } from '@/jotai/profileAtom'
import { colorSchemeAtom, themeAtom } from '@/jotai/themeAtom'
import { useSignout } from '@/servicies/authentication'
Expand All @@ -33,6 +32,7 @@ import { openURL } from '@/utils/url'
import Badge from './Badge'
import { withQuerySuspense } from './QuerySuspense'
import RadioButtonGroup from './RadioButtonGroup'
import v2exMessage from './V2exWebview/v2exMessage'

export default withQuerySuspense(memo(Profile))

Expand Down Expand Up @@ -296,7 +296,6 @@ function SignoutItem({ once }: { once: string }) {
onError: () => {},
})

const setCookieAtom = useSetAtom(cookieAtom)
const setProfileAtom = useSetAtom(profileAtom)

async function logout() {
Expand All @@ -306,8 +305,9 @@ function SignoutItem({ once }: { once: string }) {
} catch (error) {
// empty
} finally {
setCookieAtom(RESET)
setProfileAtom(RESET)
v2exMessage.clear()

// asyncStoragePersister.removeClient()
// queryClient.removeQueries()
}
Expand Down
15 changes: 13 additions & 2 deletions components/QuerySuspense.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import tw from '@/utils/tw'

import LoadingIndicator from './LoadingIndicator'
import StyledButton from './StyledButton'
import v2exMessage from './V2exWebview/v2exMessage'

export type QuerySuspenseProps = Partial<ErrorBoundaryProps> & {
Loading?: FC
Expand All @@ -24,6 +25,16 @@ export function FallbackComponent({
error,
resetErrorBoundary,
}: FallbackProps) {
async function reset() {
try {
await v2exMessage.loadedV2exWebviewPromise
} catch {
v2exMessage.reload()
}

resetErrorBoundary()
}

return (
<View style={tw`flex-1 p-8`}>
<Text style={tw`text-[31px] leading-9 font-extrabold text-tint-primary`}>
Expand All @@ -36,7 +47,7 @@ export function FallbackComponent({
</Text>
<StyledButton
style={tw`h-[52px] mt-7`}
onPress={resetErrorBoundary}
onPress={reset}
size="large"
shape="rounded"
>
Expand Down Expand Up @@ -67,7 +78,7 @@ export function FallbackComponent({
)

queryClient.removeQueries()
resetErrorBoundary()
reset()
}}
style={tw`h-[52px] mt-7`}
ghost
Expand Down
113 changes: 113 additions & 0 deletions components/V2exWebview/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// import CookieManager from '@react-native-cookies/cookies'
import 'axios/dist/axios.min.js'
import { noop } from 'lodash-es'
import { useEffect, useReducer, useRef } from 'react'
import { View } from 'react-native'
import WebView from 'react-native-webview'

import { baseURL } from '@/utils/request/baseURL'
import tw from '@/utils/tw'

import v2exMessage from './v2exMessage'

let outterResolve: () => void
let outterReject: (error: Error) => void

v2exMessage.loadedV2exWebviewPromise = new Promise((resolve, reject) => {
outterResolve = resolve
outterReject = reject
})

export default function V2exWebview() {
const webViewRef = useRef<WebView>(null)

const [forceRenderKey, updateForceRenderKey] = useReducer(
(num: number): number => num + 1,
1
)

v2exMessage.clear = () => {
webViewRef.current?.clearCache?.(true)
// CookieManager.clearAll(true)
}

v2exMessage.reload = () => {
v2exMessage.loadedV2exWebviewPromise = new Promise((resolve, reject) => {
outterResolve = resolve
outterReject = reject
})
updateForceRenderKey()
}

useEffect(() => {
v2exMessage.inject = ({ id, config }) => {
const run = `window.axios(${JSON.stringify(config)})
.then(response => {
window.ReactNativeWebView.postMessage(
JSON.stringify({
id: ${JSON.stringify(id)},
response: response,
})
)
})
.catch(error => {
window.ReactNativeWebView.postMessage(
JSON.stringify({
id: ${JSON.stringify(id)},
error: JSON.parse(
JSON.stringify(error, Object.getOwnPropertyNames(error))
),
})
)
}); void(0);`

webViewRef.current?.injectJavaScript(run)
}

return () => {
v2exMessage.inject = noop
}
}, [])

return (
<View
key={forceRenderKey}
style={tw`absolute w-0 h-0`}
pointerEvents="none"
>
<WebView
ref={webViewRef}
originWhitelist={['*']}
source={{ uri: `${baseURL}/signin` }}
onLoadEnd={() => outterResolve()}
onError={() => outterReject(new Error('应用初始化失败'))}
javaScriptEnabled={true}
domStorageEnabled={true}
decelerationRate="normal"
sharedCookiesEnabled={true}
startInLoadingState={true}
scalesPageToFit={true}
onMessage={event => {
let result = event.nativeEvent.data as any

try {
result = JSON.parse(result)
} catch (error) {
// empty
}

if (typeof result === 'object' && result !== null) {
const listener = v2exMessage.linsteners.get(result.id)

listener?.(
result.error != null
? Promise.reject(result.error)
: Promise.resolve(result.response)
)
}
}}
userAgent={`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36`}
/>
</View>
)
}
49 changes: 49 additions & 0 deletions components/V2exWebview/v2exMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { AxiosRequestConfig, AxiosResponse } from 'axios'
import { noop, pick, uniqueId } from 'lodash-es'

import { timeout } from '@/utils/timeout'

class V2exMessage {
linsteners: Map<string, (response: any) => void> = new Map()
loadedV2exWebviewPromise: Promise<void> = Promise.resolve()
inject: (arg: { id: string; config: AxiosRequestConfig }) => void = noop
clear: () => void = noop
reload: () => void = noop

constructor() {
this.sendMessage = this.sendMessage.bind(this)
}

async sendMessage(
config: AxiosRequestConfig
): Promise<AxiosResponse<any, any>> {
await this.loadedV2exWebviewPromise

const id = uniqueId()

return timeout(
new Promise<AxiosResponse<any, any>>(async resolve => {
const pickedConfig = pick(config, [
'timeout',
'baseURL',
'responseType',
'method',
'url',
'headers',
'withCredentials',
'data',
])

this.linsteners.set(id, resolve)

this.inject({
id,
config: pickedConfig,
})
}).finally(() => this.linsteners.delete(id)),
10 * 1000
)
}
}

export default new V2exMessage()
6 changes: 3 additions & 3 deletions components/topic/ReplyItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function ReplyItem({
return (
<View
style={tw.style(
`px-4 py-3 bg-body-1 border-b border-solid border-tint-border`,
`px-4 py-3 bg-body-1 border-t border-solid border-tint-border`,
hightlight && `bg-[#f0f3f5] dark:bg-[#262626]`,
isBoolean(related) && !related && `opacity-64`
)}
Expand Down Expand Up @@ -98,7 +98,7 @@ function ReplyItem({
{reply.mod && (
<StyledButton
size="mini"
type="primary"
type="secondary"
pressable={false}
style={tw.style(`py-0`, reply.op && `rounded-r-none`)}
>
Expand All @@ -110,7 +110,7 @@ function ReplyItem({
ghost
size="mini"
pressable={false}
type="primary"
type="secondary"
style={tw.style(`py-0`, reply.mod && `rounded-l-none`)}
>
OP
Expand Down
2 changes: 1 addition & 1 deletion components/topic/TopicInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function TopicInfo({ topic, onReply }: { topic: Topic; onReply: () => void }) {
useNavigation<NativeStackNavigationProp<RootStackParamList>>()

return (
<View style={tw`py-3 px-4 border-b border-solid border-tint-border`}>
<View style={tw`py-3 px-4`}>
<View style={tw`flex-row items-center`}>
<View style={tw`mr-3`}>
<Pressable
Expand Down
5 changes: 0 additions & 5 deletions jotai/cookieAtom.ts

This file was deleted.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@hookform/resolvers": "^2.9.10",
"@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/netinfo": "9.3.5",
"@react-native-cookies/cookies": "^6.2.1",
"@react-navigation/drawer": "^6.5.0",
"@react-navigation/native": "^6.0.13",
"@react-navigation/native-stack": "^6.9.1",
Expand All @@ -34,7 +35,7 @@
"expo-updates": "~0.15.6",
"highlight.js": "^11.6.0",
"immer": "^9.0.15",
"jotai": "^1.9.2",
"jotai": "^1.12.0",
"lodash-es": "^4.17.21",
"react": "18.1.0",
"react-dom": "18.1.0",
Expand Down
1 change: 0 additions & 1 deletion screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ const MemoTabTopics = memo(withQuerySuspense(TabTopics))
export default withQuerySuspense(HomeScreen)

let isSwiping = false

function isDisabledPress() {
return isSwiping
}
Expand Down
Loading

0 comments on commit f9147ad

Please sign in to comment.