feat(mobile): cache rsshub query (#2900)

This commit is contained in:
Stephen Zhou 2025-02-27 13:38:01 +08:00 committed by GitHub
parent 0c761925b1
commit 5126a6ff89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 73 additions and 27 deletions

View File

@ -31,7 +31,9 @@
"@react-navigation/drawer": "7.1.1",
"@react-navigation/native": "7.0.14",
"@shopify/flash-list": "1.7.3",
"@tanstack/query-sync-storage-persister": "5.66.4",
"@tanstack/react-query": "5.66.7",
"@tanstack/react-query-persist-client": "5.66.7",
"better-auth": "1.1.18",
"cookie-es": "1.2.2",
"dayjs": "1.11.13",

View File

@ -1,2 +1,21 @@
import { persistQueryClient } from "@tanstack/react-query-persist-client"
import { kvStoragePersister, queryClient } from "../lib/query-client"
export { hydrateDatabaseToStore } from "../services"
export const hydrateSettings = () => {}
export const hydrateQueryClient = () => {
persistQueryClient({
queryClient,
persister: kvStoragePersister,
dehydrateOptions: {
shouldDehydrateQuery(query) {
return query.queryKey.includes("cache")
},
shouldDehydrateMutation() {
return false
},
},
maxAge: 1000 * 60 * 60 * 24 * 1,
})
}

View File

@ -1,6 +1,6 @@
import { initializeDb } from "../database"
import { initializeDayjs } from "./dayjs"
import { hydrateDatabaseToStore, hydrateSettings } from "./hydrate"
import { hydrateDatabaseToStore, hydrateQueryClient, hydrateSettings } from "./hydrate"
import { migrateDatabase } from "./migration"
import { initializePlayer } from "./player"
/* eslint-disable no-console */
@ -14,6 +14,7 @@ export const initializeApp = async () => {
await apm("hydrateSettings", hydrateSettings)
await apm("hydrateDatabaseToStore", hydrateDatabaseToStore)
await apm("hydrateQueryClient", hydrateQueryClient)
const loadingTime = Date.now() - now
console.log(`Initialize done,`, `${loadingTime}ms`)

View File

@ -1,3 +1,20 @@
import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"
import { QueryClient } from "@tanstack/react-query"
export const queryClient = new QueryClient()
import { kv } from "./kv"
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24,
},
},
})
export const kvStoragePersister = createSyncStoragePersister({
storage: {
getItem: (key: string) => kv.getSync(key),
setItem: (key: string, value: string) => kv.setSync(key, value),
removeItem: (key: string) => kv.delete(key),
},
})

View File

@ -108,7 +108,7 @@ const Tab: TabComponent = ({ tab, isSelected, ...rest }) => {
const tabHeight = useBottomTabBarHeight()
const { data, isLoading } = useQuery({
queryKey: ["rsshub-popular", tab.value],
queryKey: ["rsshub-popular", "cache", tab.value],
queryFn: () => fetchRsshubPopular(tab.value, "all").then((res) => res.data),
})
const keys = useMemo(() => {

View File

@ -180,6 +180,7 @@ class Morph {
// TODO: handle inboxHandle
inboxHandle: "",
read: false,
sources: null,
}
}

View File

@ -470,9 +470,15 @@ importers:
'@shopify/flash-list':
specifier: 1.7.3
version: 1.7.3(@babel/runtime@7.26.9)(react-native@0.77.0(@babel/core@7.26.9)(@babel/preset-env@7.26.9(@babel/core@7.26.9))(@types/react@18.3.12)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@6.0.5))(react@18.3.1)
'@tanstack/query-sync-storage-persister':
specifier: 5.66.4
version: 5.66.4
'@tanstack/react-query':
specifier: 5.66.7
version: 5.66.7(react@18.3.1)
'@tanstack/react-query-persist-client':
specifier: 5.66.7
version: 5.66.7(@tanstack/react-query@5.66.7(react@18.3.1))(react@18.3.1)
better-auth:
specifier: 1.1.18
version: 1.1.18
@ -3998,8 +4004,8 @@ packages:
'@radix-ui/react-avatar@1.1.3':
resolution: {integrity: sha512-Paen00T4P8L8gd9bNsRMw7Cbaz85oxiv+hzomsRZgFm2byltPFDtfcoqlWJ8GyZlIBWgLssJlzLCnKU0G0302g==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
@ -4064,7 +4070,7 @@ packages:
'@radix-ui/react-context@1.1.1':
resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==}
peerDependencies:
'@types/react': '*'
'@types/react': npm:@types/react@^18.3.12
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
@ -4095,8 +4101,8 @@ packages:
'@radix-ui/react-dismissable-layer@1.1.5':
resolution: {integrity: sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
@ -4121,7 +4127,7 @@ packages:
'@radix-ui/react-focus-guards@1.1.1':
resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==}
peerDependencies:
'@types/react': '*'
'@types/react': npm:@types/react@^18.3.12
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
@ -4178,8 +4184,8 @@ packages:
'@radix-ui/react-menu@2.1.6':
resolution: {integrity: sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
@ -4217,8 +4223,8 @@ packages:
'@radix-ui/react-popper@1.2.2':
resolution: {integrity: sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
@ -4230,8 +4236,8 @@ packages:
'@radix-ui/react-portal@1.1.4':
resolution: {integrity: sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
@ -4282,8 +4288,8 @@ packages:
'@radix-ui/react-roving-focus@1.1.2':
resolution: {integrity: sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
@ -4400,7 +4406,7 @@ packages:
'@radix-ui/react-use-callback-ref@1.1.0':
resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==}
peerDependencies:
'@types/react': '*'
'@types/react': npm:@types/react@^18.3.12
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
@ -4409,7 +4415,7 @@ packages:
'@radix-ui/react-use-controllable-state@1.1.0':
resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==}
peerDependencies:
'@types/react': '*'
'@types/react': npm:@types/react@^18.3.12
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
@ -4463,8 +4469,8 @@ packages:
'@radix-ui/react-visually-hidden@1.1.2':
resolution: {integrity: sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
'@types/react': 18.3.12
'@types/react-dom': 18.3.1
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
@ -4546,7 +4552,7 @@ packages:
'@react-native-menu/menu@1.2.2':
resolution: {integrity: sha512-Uk65PAhwNkCVBAqJu5t2H9biV+m0JLwJc7m3v2X2A/W8SFJmUqYabBsLH4fOWKI3a7kkR9QDT6HruliIKSfM8w==}
peerDependencies:
react: '*'
react: 18.3.1
react-native: '*'
'@react-native-picker/picker@2.11.0':
@ -8483,7 +8489,7 @@ packages:
resolution: {integrity: sha512-LUnfrddmee1xLOkyG2NN1l9xQbtvMX3fbM1brEGHg0SKSndvjod3FQdhTzZEYAariqW2RSxQR8v1IsheIoLQXg==}
peerDependencies:
expo: '*'
react-native: npm:react-native@0.77.0
react-native: '*'
expo-module-scripts@4.0.4:
resolution: {integrity: sha512-ytFufVi7HTFLxxf8fbtz3DJuegq3489WPk9pz8Yqm3tYfZ+6/yufPYxLvk6N8b4yBW05oNr/Cqp7MWLpm0xPcA==}
@ -12419,7 +12425,7 @@ packages:
resolution: {integrity: sha512-sc5qgX4YtM6IxjtosjgQLdsal120MvU+YWs0F2MdgQWijps22AXLDCUoBnZZ8vxVhVyJ2WnnIPrmtVBvVJjSuQ==}
engines: {node: '>= 18.0.0'}
peerDependencies:
react: '*'
react: 18.3.1
react-native: '*'
react-native-gesture-handler: '>=2.0.0'
react-native-reanimated: '>=3.0.0'
@ -12539,7 +12545,7 @@ packages:
resolution: {integrity: sha512-9PPREdwH3tMR8otUK1voiFw9AFNtC37Del2fZwbCMBKjOyClC+f3Fwp7KqUouP0A5c3zjEc3T8TetBGQGPQE9A==}
peerDependencies:
react: '*'
react-native: '*'
react-native: npm:react-native@0.77.0
react-native-gesture-handler: '*'
react-native-reanimated: '*'
@ -12553,7 +12559,7 @@ packages:
resolution: {integrity: sha512-E5N/eK/+HtAVJUAzXpm1cWz8ROheV9jb0TI6h2bM+333U+DWibTTnT2T1122FkCoXLXIYavtm2FR2if+5jH8cA==}
peerDependencies:
react: '>=16.8.6'
react-native: '>=0.60.0-rc.2'
react-native: npm:react-native@0.77.0
react-native-windows: '>=0.63.0'
shaka-player: ^4.7.9
peerDependenciesMeta:
@ -12573,7 +12579,7 @@ packages:
react-native-volume-manager@2.0.8:
resolution: {integrity: sha512-aZM47/mYkdQ4CbXpKYO6Ajiczv7fxbQXZ9c0H8gRuQUaS3OCz/MZABer6o9aDWq0KMNsQ7q7GVFLRPnSSeeMmw==}
peerDependencies:
react: '*'
react: 18.3.1
react-native: '*'
react-native-web@0.19.13: