mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {AppState, AppStateStatus} from 'react-native'
3import AsyncStorage from '@react-native-async-storage/async-storage'
4import {createAsyncStoragePersister} from '@tanstack/query-async-storage-persister'
5import {focusManager, QueryClient} from '@tanstack/react-query'
6import {
7 PersistQueryClientProvider,
8 PersistQueryClientProviderProps,
9} from '@tanstack/react-query-persist-client'
10
11import {isNative} from '#/platform/detection'
12
13// any query keys in this array will be persisted to AsyncStorage
14const STORED_CACHE_QUERY_KEYS = ['labelers-detailed-info']
15
16focusManager.setEventListener(onFocus => {
17 if (isNative) {
18 const subscription = AppState.addEventListener(
19 'change',
20 (status: AppStateStatus) => {
21 focusManager.setFocused(status === 'active')
22 },
23 )
24
25 return () => subscription.remove()
26 } else if (typeof window !== 'undefined' && window.addEventListener) {
27 // these handlers are a bit redundant but focus catches when the browser window
28 // is blurred/focused while visibilitychange seems to only handle when the
29 // window minimizes (both of them catch tab changes)
30 // there's no harm to redundant fires because refetchOnWindowFocus is only
31 // used with queries that employ stale data times
32 const handler = () => onFocus()
33 window.addEventListener('focus', handler, false)
34 window.addEventListener('visibilitychange', handler, false)
35 return () => {
36 window.removeEventListener('visibilitychange', handler)
37 window.removeEventListener('focus', handler)
38 }
39 }
40})
41
42const queryClient = new QueryClient({
43 defaultOptions: {
44 queries: {
45 // NOTE
46 // refetchOnWindowFocus breaks some UIs (like feeds)
47 // so we only selectively want to enable this
48 // -prf
49 refetchOnWindowFocus: false,
50 // Structural sharing between responses makes it impossible to rely on
51 // "first seen" timestamps on objects to determine if they're fresh.
52 // Disable this optimization so that we can rely on "first seen" timestamps.
53 structuralSharing: false,
54 // We don't want to retry queries by default, because in most cases we
55 // want to fail early and show a response to the user. There are
56 // exceptions, and those can be made on a per-query basis. For others, we
57 // should give users controls to retry.
58 retry: false,
59 },
60 },
61})
62
63const asyncStoragePersister = createAsyncStoragePersister({
64 storage: AsyncStorage,
65 key: 'queryCache',
66})
67
68const dehydrateOptions: PersistQueryClientProviderProps['persistOptions']['dehydrateOptions'] =
69 {
70 shouldDehydrateMutation: (_: any) => false,
71 shouldDehydrateQuery: query => {
72 return STORED_CACHE_QUERY_KEYS.includes(String(query.queryKey[0]))
73 },
74 }
75
76const persistOptions = {
77 persister: asyncStoragePersister,
78 dehydrateOptions,
79}
80
81export function QueryProvider({children}: {children: React.ReactNode}) {
82 return (
83 <PersistQueryClientProvider
84 client={queryClient}
85 persistOptions={persistOptions}>
86 {children}
87 </PersistQueryClientProvider>
88 )
89}