From ac42770eb092f06ae5fd0fd431ee31d537ca4c05 Mon Sep 17 00:00:00 2001 From: Ritesh Shukla Date: Mon, 10 Nov 2025 01:57:16 +0530 Subject: [PATCH] Switch QueryClient to use AsyncStorage as Persister (#656) Switching the Tanstack Queryclient to use `react-native-async-storage` as the client persister This will cause users' API response data to be refreshed, so some data may disappear on update --- ios/Jellify/PrivacyInfo.xcprivacy | 20 ++++++------- ios/Podfile.lock | 32 +++++++++++++++++++++ package.json | 3 +- src/components/Player/components/lyrics.tsx | 4 +-- src/constants/storage.ts | 20 +++++++++++-- src/stores/index.ts | 4 +-- yarn.lock | 19 ++++++++++++ 7 files changed, 85 insertions(+), 17 deletions(-) diff --git a/ios/Jellify/PrivacyInfo.xcprivacy b/ios/Jellify/PrivacyInfo.xcprivacy index ffa95231..e9291c44 100644 --- a/ios/Jellify/PrivacyInfo.xcprivacy +++ b/ios/Jellify/PrivacyInfo.xcprivacy @@ -4,6 +4,16 @@ NSPrivacyAccessedAPITypes + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + 0A2A.1 + 3B52.1 + + NSPrivacyAccessedAPIType NSPrivacyAccessedAPICategorySystemBootTime @@ -21,16 +31,6 @@ C56D.1 - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp - NSPrivacyAccessedAPITypeReasons - - C617.1 - 0A2A.1 - 3B52.1 - - NSPrivacyAccessedAPIType NSPrivacyAccessedAPICategoryDiskSpace diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 40162375..f6b7279b 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2658,6 +2658,34 @@ PODS: - React-perflogger (= 0.82.1) - React-utils (= 0.82.1) - SocketRocket + - RNCAsyncStorage (2.2.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga - RNCMaskedView (0.3.2): - boost - DoubleConversion @@ -3117,6 +3145,7 @@ DEPENDENCIES: - ReactAppDependencyProvider (from `build/generated/ios`) - ReactCodegen (from `build/generated/ios`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)" - RNDeviceInfo (from `../node_modules/react-native-device-info`) - RNDnsLookup (from `../node_modules/react-native-dns-lookup`) @@ -3320,6 +3349,8 @@ EXTERNAL SOURCES: :path: build/generated/ios ReactCommon: :path: "../node_modules/react-native/ReactCommon" + RNCAsyncStorage: + :path: "../node_modules/@react-native-async-storage/async-storage" RNCMaskedView: :path: "../node_modules/@react-native-masked-view/masked-view" RNDeviceInfo: @@ -3435,6 +3466,7 @@ SPEC CHECKSUMS: ReactAppDependencyProvider: a45ef34bb22dc1c9b2ac1f74167d9a28af961176 ReactCodegen: 878add6c7d8ff8cea87697c44d29c03b79b6f2d9 ReactCommon: 804dc80944fa90b86800b43c871742ec005ca424 + RNCAsyncStorage: 29f0230e1a25f36c20b05f65e2eb8958d6526e82 RNCMaskedView: 5ef8c95cbab95334a32763b72896a7b7d07e6299 RNDeviceInfo: bcce8752b5043a623fe3c26789679b473f705d3c RNDnsLookup: db4a89381b80ec1a5153088518d2c4f8e51f2521 diff --git a/package.json b/package.json index a37f0bb3..0222a3b6 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "dependencies": { "@jellyfin/sdk": "0.13.0", + "@react-native-async-storage/async-storage": "^2.2.0", "@react-native-community/cli": "20.0.0", "@react-native-community/netinfo": "^11.4.1", "@react-native-masked-view/masked-view": "^0.3.2", @@ -142,4 +143,4 @@ "node": ">=18" }, "packageManager": "yarn@1.22.22" -} \ No newline at end of file +} diff --git a/src/components/Player/components/lyrics.tsx b/src/components/Player/components/lyrics.tsx index 9fa94069..39c70ad6 100644 --- a/src/components/Player/components/lyrics.tsx +++ b/src/components/Player/components/lyrics.tsx @@ -20,6 +20,7 @@ import Animated, { import { FlatList, ListRenderItem } from 'react-native' import { trigger } from 'react-native-haptic-feedback' import Icon from '../../Global/components/icon' +import useRawLyrics from '../../../api/queries/lyrics' interface LyricLine { Text: string @@ -169,8 +170,7 @@ export default function Lyrics({ }: { navigation: NativeStackNavigationProp }): React.JSX.Element { - const route = useRoute>() - const { lyrics } = route.params + const { data: lyrics } = useRawLyrics() const { width, height } = useWindowDimensions() const { position } = useProgress(UPDATE_INTERVAL) const seekTo = useSeekTo() diff --git a/src/constants/storage.ts b/src/constants/storage.ts index 7da6bf6f..b217d71a 100644 --- a/src/constants/storage.ts +++ b/src/constants/storage.ts @@ -1,13 +1,27 @@ import { MMKV } from 'react-native-mmkv' import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' -import { AsyncStorage } from '@tanstack/react-query-persist-client' +import { AsyncStorage as TanstackAsyncStorage } from '@tanstack/react-query-persist-client' import { StateStorage } from 'zustand/middleware' +import AsyncStorage from '@react-native-async-storage/async-storage' console.debug(`Building MMKV storage`) export const storage = new MMKV() const storageFunctions = { + setItem: async (key: string, value: string) => { + await AsyncStorage.setItem(key, value) + }, + getItem: async (key: string) => { + const value = await AsyncStorage.getItem(key) + return value === undefined ? null : value + }, + removeItem: async (key: string) => { + await AsyncStorage.removeItem(key) + }, +} + +const mmkvStorageFunctions = { setItem: (key: string, value: string) => { storage.set(key, value) }, @@ -20,10 +34,12 @@ const storageFunctions = { }, } -const clientStorage: AsyncStorage = storageFunctions +const clientStorage: TanstackAsyncStorage = storageFunctions export const queryClientPersister = createAsyncStoragePersister({ storage: clientStorage, }) export const stateStorage: StateStorage = storageFunctions + +export const mmkvStateStorage: StateStorage = mmkvStorageFunctions diff --git a/src/stores/index.ts b/src/stores/index.ts index ba63a3b9..8fd9b7d6 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -4,7 +4,7 @@ import { JellifyLibrary } from '../types/JellifyLibrary' import { JellifyServer } from '../types/JellifyServer' import { JellifyUser } from '../types/JellifyUser' import { createJSONStorage, devtools, persist } from 'zustand/middleware' -import { stateStorage, storage } from '../constants/storage' +import { mmkvStateStorage, stateStorage, storage } from '../constants/storage' import { MMKVStorageKeys } from '../enums/mmkv-storage-keys' import { Api } from '@jellyfin/sdk' import { useCallback, useMemo } from 'react' @@ -47,7 +47,7 @@ const useJellifyStore = create()( }), { name: 'jellify-context-storage', - storage: createJSONStorage(() => stateStorage), + storage: createJSONStorage(() => mmkvStateStorage), }, ), ), diff --git a/yarn.lock b/yarn.lock index 428c8b74..e1917e4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1753,6 +1753,13 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.7.tgz#eb5014dfd0b03e7f3ba2eeeff506eed89b028058" integrity sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg== +"@react-native-async-storage/async-storage@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz#a3aa565253e46286655560172f4e366e8969f5ad" + integrity sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw== + dependencies: + merge-options "^3.0.4" + "@react-native-community/cli-clean@20.0.0": version "20.0.0" resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-20.0.0.tgz#e685f5404195ded69c81d1394e8c5eb332b780bc" @@ -6259,6 +6266,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -7352,6 +7364,13 @@ memoize-one@^5.0.0: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"