@planningcenter/chat-react-native 3.21.2-rc.2 → 3.21.2-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/hooks/use_async_storage.d.ts.map +1 -1
- package/build/hooks/use_async_storage.js +3 -44
- package/build/hooks/use_async_storage.js.map +1 -1
- package/build/hooks/use_jolt.d.ts.map +1 -1
- package/build/hooks/use_jolt.js +6 -8
- package/build/hooks/use_jolt.js.map +1 -1
- package/build/hooks/use_storage.d.ts +9 -0
- package/build/hooks/use_storage.d.ts.map +1 -0
- package/build/hooks/use_storage.js +53 -0
- package/build/hooks/use_storage.js.map +1 -0
- package/build/utils/native_adapters/configuration.d.ts +2 -0
- package/build/utils/native_adapters/configuration.d.ts.map +1 -1
- package/build/utils/native_adapters/configuration.js +7 -0
- package/build/utils/native_adapters/configuration.js.map +1 -1
- package/build/utils/native_adapters/index.d.ts +1 -0
- package/build/utils/native_adapters/index.d.ts.map +1 -1
- package/build/utils/native_adapters/index.js +1 -0
- package/build/utils/native_adapters/index.js.map +1 -1
- package/build/utils/native_adapters/storage_adapter.d.ts +17 -0
- package/build/utils/native_adapters/storage_adapter.d.ts.map +1 -0
- package/build/utils/native_adapters/storage_adapter.js +16 -0
- package/build/utils/native_adapters/storage_adapter.js.map +1 -0
- package/package.json +2 -2
- package/src/hooks/use_async_storage.ts +3 -52
- package/src/hooks/use_jolt.ts +6 -9
- package/src/hooks/use_storage.ts +69 -0
- package/src/utils/native_adapters/configuration.ts +8 -0
- package/src/utils/native_adapters/index.ts +1 -0
- package/src/utils/native_adapters/storage_adapter.ts +23 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_async_storage.d.ts","sourceRoot":"","sources":["../../src/hooks/use_async_storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use_async_storage.d.ts","sourceRoot":"","sources":["../../src/hooks/use_async_storage.ts"],"names":[],"mappings":"AAGA,KAAK,QAAQ,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAE7E,wBAAgB,eAAe,CAAC,UAAU,EACxC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,UAAU,EACxB,YAAY,GAAE,OAAe,GAC5B,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAEpC"}
|
|
@@ -1,47 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { noop } from 'lodash';
|
|
4
|
-
import { useCallback } from 'react';
|
|
5
|
-
const cacheKeyGenerator = (key) => [`AsyncStorageResource:${key}`];
|
|
1
|
+
import { Storage } from '../utils/native_adapters';
|
|
2
|
+
import { useStorage } from './use_storage';
|
|
6
3
|
export function useAsyncStorage(key, initialValue, throwOnError = false) {
|
|
7
|
-
|
|
8
|
-
const { data: value, refetch } = useSuspenseQuery({
|
|
9
|
-
queryKey: cacheKey,
|
|
10
|
-
queryFn: () => AsyncStorage.getItem(key)
|
|
11
|
-
.then(storedValue => {
|
|
12
|
-
if (!storedValue)
|
|
13
|
-
return initialValue;
|
|
14
|
-
try {
|
|
15
|
-
return JSON.parse(storedValue);
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
return storedValue;
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
.catch(e => {
|
|
22
|
-
if (!throwOnError)
|
|
23
|
-
return initialValue;
|
|
24
|
-
return Promise.reject(e);
|
|
25
|
-
}),
|
|
26
|
-
});
|
|
27
|
-
const setValue = useCallback(itemValue => {
|
|
28
|
-
if (itemValue === null || itemValue === undefined) {
|
|
29
|
-
return AsyncStorage.removeItem(key)
|
|
30
|
-
.then(() => {
|
|
31
|
-
refetch();
|
|
32
|
-
})
|
|
33
|
-
.catch(noop);
|
|
34
|
-
}
|
|
35
|
-
return AsyncStorage.setItem(key, JSON.stringify(itemValue))
|
|
36
|
-
.then(() => {
|
|
37
|
-
refetch();
|
|
38
|
-
})
|
|
39
|
-
.catch(e => {
|
|
40
|
-
if (!throwOnError)
|
|
41
|
-
return;
|
|
42
|
-
return Promise.reject(e);
|
|
43
|
-
});
|
|
44
|
-
}, [throwOnError, key, refetch]);
|
|
45
|
-
return [value || initialValue, setValue];
|
|
4
|
+
return useStorage(Storage, key, initialValue, throwOnError);
|
|
46
5
|
}
|
|
47
6
|
//# sourceMappingURL=use_async_storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_async_storage.js","sourceRoot":"","sources":["../../src/hooks/use_async_storage.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"use_async_storage.js","sourceRoot":"","sources":["../../src/hooks/use_async_storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAI1C,MAAM,UAAU,eAAe,CAC7B,GAAW,EACX,YAAwB,EACxB,eAAwB,KAAK;IAE7B,OAAO,UAAU,CAAa,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,YAAY,CAAC,CAAA;AACzE,CAAC","sourcesContent":["import { Storage } from '../utils/native_adapters'\nimport { useStorage } from './use_storage'\n\ntype SetValue<TCacheData> = (_itemValue?: TCacheData | null) => Promise<void>\n\nexport function useAsyncStorage<TCacheData>(\n key: string,\n initialValue: TCacheData,\n throwOnError: boolean = false\n): [TCacheData, SetValue<TCacheData>] {\n return useStorage<TCacheData>(Storage, key, initialValue, throwOnError)\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_jolt.d.ts","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,EACL,aAAa,EAEd,MAAM,uDAAuD,CAAA;AAC9D,OAAO,EAEL,gBAAgB,EACjB,MAAM,yDAAyD,CAAA;
|
|
1
|
+
{"version":3,"file":"use_jolt.d.ts","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,EACL,aAAa,EAEd,MAAM,uDAAuD,CAAA;AAC9D,OAAO,EAEL,gBAAgB,EACjB,MAAM,yDAAyD,CAAA;AAahE,eAAO,MAAM,aAAa,QAAO,UAAU,GAAG,SAmG7C,CAAA;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAc,GACtB,gBAAgB,GAAG,SAAS,GAAG,IAAI,CAoCrC;AAED,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAA;AAE5C,wBAAgB,YAAY,CAAC,CAAC,SAAS,aAAa,EAClD,OAAO,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,EAC5C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,QAO5B"}
|
package/build/hooks/use_jolt.js
CHANGED
|
@@ -3,7 +3,6 @@ import { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-quer
|
|
|
3
3
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
4
4
|
import { useChatContext } from '../contexts/chat_context';
|
|
5
5
|
import { Client, Uri } from '../utils';
|
|
6
|
-
import { useAppState } from './use_app_state';
|
|
7
6
|
export const useJoltClient = () => {
|
|
8
7
|
const { session } = useChatContext();
|
|
9
8
|
const sessionAccessToken = session.token?.access_token;
|
|
@@ -37,6 +36,7 @@ export const useJoltClient = () => {
|
|
|
37
36
|
queryFn: () => fetchJoltToken().then(res => res.data.wssUrl),
|
|
38
37
|
staleTime: Infinity,
|
|
39
38
|
gcTime: Infinity,
|
|
39
|
+
refetchOnWindowFocus: false,
|
|
40
40
|
});
|
|
41
41
|
const fetchAuthTokenFn = () => {
|
|
42
42
|
return queryClient.fetchQuery({
|
|
@@ -78,6 +78,7 @@ export const useJoltClient = () => {
|
|
|
78
78
|
fetchSubscribeTokenFn,
|
|
79
79
|
}, { logToConsole: false });
|
|
80
80
|
},
|
|
81
|
+
refetchOnWindowFocus: false,
|
|
81
82
|
staleTime: Infinity,
|
|
82
83
|
gcTime: Infinity,
|
|
83
84
|
});
|
|
@@ -85,9 +86,8 @@ export const useJoltClient = () => {
|
|
|
85
86
|
};
|
|
86
87
|
export function useJoltChannel(channelName, enabled = true) {
|
|
87
88
|
const jolt = useJoltClient();
|
|
88
|
-
const appState = useAppState();
|
|
89
89
|
const queryClient = useQueryClient();
|
|
90
|
-
const ready = Boolean(jolt) &&
|
|
90
|
+
const ready = Boolean(jolt) && enabled;
|
|
91
91
|
const handleSubscribe = useCallback(async () => {
|
|
92
92
|
if (!jolt)
|
|
93
93
|
return null;
|
|
@@ -100,6 +100,7 @@ export function useJoltChannel(channelName, enabled = true) {
|
|
|
100
100
|
const { data: subscription } = useQuery({
|
|
101
101
|
queryKey: ['jolt-subscription', channelName],
|
|
102
102
|
queryFn: handleSubscribe,
|
|
103
|
+
refetchOnWindowFocus: false,
|
|
103
104
|
enabled: ready,
|
|
104
105
|
});
|
|
105
106
|
const handleUnsubscribe = useCallback(() => {
|
|
@@ -110,11 +111,8 @@ export function useJoltChannel(channelName, enabled = true) {
|
|
|
110
111
|
jolt?.unsubscribe(channelName);
|
|
111
112
|
}, [queryClient, channelName, jolt]);
|
|
112
113
|
useEffect(() => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
handleUnsubscribe();
|
|
116
|
-
return () => null;
|
|
117
|
-
}, [appState, handleUnsubscribe]);
|
|
114
|
+
return handleUnsubscribe;
|
|
115
|
+
}, [handleUnsubscribe]);
|
|
118
116
|
return subscription;
|
|
119
117
|
}
|
|
120
118
|
export function useJoltEvent(channel, eventName, callback) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_jolt.js","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,6BAA6B,CAAA;AASpD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAClF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"use_jolt.js","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"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","sourcesContent":["import JoltClient from '@planningcenter/jolt-client'\nimport {\n CustomMessage,\n FetchAuthToken,\n} from '@planningcenter/jolt-client/dist/types/JoltConnection'\nimport {\n FetchSubscribeToken,\n JoltSubscription,\n} from '@planningcenter/jolt-client/dist/types/JoltSubscription'\nimport { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { useChatContext } from '../contexts/chat_context'\nimport { ApiResource } from '../types'\nimport { Client, Uri } from '../utils'\n\ninterface JoltResponse {\n type: 'JoltToken'\n id: string\n wssUrl: string\n}\n\nexport const useJoltClient = (): JoltClient | undefined => {\n const { session } = useChatContext()\n const sessionAccessToken = session.token?.access_token\n const queryClient = useQueryClient()\n const uri = useMemo(() => new Uri({ session }), [session])\n const apiClient = useMemo(\n () =>\n new Client({\n root: uri.api(`/chat/v2`),\n defaultHeaders: uri.headers,\n version: '2018-11-01',\n }),\n [uri]\n )\n\n const fetchJoltToken = async () => {\n return queryClient.fetchQuery({\n queryKey: ['jolt-token'],\n queryFn: () => {\n return apiClient.post<ApiResource<JoltResponse>>({\n url: '/me/jolt_authorize',\n data: {\n data: {\n type: 'JoltToken',\n attributes: {},\n },\n },\n })\n },\n staleTime: 5000, // 5 seconds\n })\n }\n\n /** The wssUrl is static and doesn't change so we can cache it to infinity and beyond */\n const { data: wssUrl } = useSuspenseQuery<string>({\n queryKey: ['wss-url'],\n queryFn: () => fetchJoltToken().then(res => res.data.wssUrl),\n staleTime: Infinity,\n gcTime: Infinity,\n refetchOnWindowFocus: false,\n })\n\n const fetchAuthTokenFn: FetchAuthToken = () => {\n return queryClient.fetchQuery({\n queryKey: ['jolt-auth-token'],\n queryFn: () => fetchJoltToken().then(res => res.data.id),\n })\n }\n\n const fetchSubscribeToken: FetchSubscribeToken = (channel: string, connectionId: string) => {\n return apiClient\n .post<ApiResource<JoltResponse>>({\n url: '/me/jolt_subscribe',\n data: {\n data: {\n type: 'JoltSubscribeToken',\n attributes: { channel, cid: connectionId },\n },\n },\n })\n .then(res => res.data.id)\n .catch((res: unknown) => {\n console.error('failed to subscribe to Jolt channel', res)\n return ''\n })\n }\n\n const fetchSubscribeTokenFn: FetchSubscribeToken = (\n channel: string,\n connectionId: string,\n options\n ) => {\n return queryClient.fetchQuery({\n queryKey: ['jolt-subscribe-token', channel, connectionId],\n queryFn: () => fetchSubscribeToken(channel, connectionId, options),\n })\n }\n\n const { data: joltClient } = useQuery({\n enabled: Boolean(wssUrl),\n queryKey: ['jolt-client', wssUrl, sessionAccessToken],\n queryFn: async () => {\n if (!wssUrl) return undefined\n\n return new JoltClient(\n wssUrl,\n {\n fetchAuthTokenFn,\n fetchSubscribeTokenFn,\n },\n { logToConsole: false }\n )\n },\n refetchOnWindowFocus: false,\n staleTime: Infinity,\n gcTime: Infinity,\n })\n\n return joltClient\n}\n\nexport function useJoltChannel(\n channelName: string,\n enabled: boolean = true\n): JoltSubscription | undefined | null {\n const jolt = useJoltClient()\n const queryClient = useQueryClient()\n const ready = Boolean(jolt) && enabled\n\n const handleSubscribe = useCallback(async () => {\n if (!jolt) return null\n\n // If the subscription already exists, we don't need to subscribe again\n const alreadySubscribed = jolt.subscriptions.find(c => c.channel === channelName)\n if (alreadySubscribed) return alreadySubscribed\n\n return jolt.subscribe(channelName)\n }, [channelName, jolt])\n\n const { data: subscription } = useQuery<JoltSubscription | null>({\n queryKey: ['jolt-subscription', channelName],\n queryFn: handleSubscribe,\n refetchOnWindowFocus: false,\n enabled: ready,\n })\n\n const handleUnsubscribe = useCallback(() => {\n queryClient.removeQueries({\n queryKey: ['jolt-subscription', channelName],\n exact: true,\n })\n\n jolt?.unsubscribe(channelName)\n }, [queryClient, channelName, jolt])\n\n useEffect(() => {\n return handleUnsubscribe\n }, [handleUnsubscribe])\n\n return subscription\n}\n\ntype UserCallbackFn<T> = (_event: T) => void\n\nexport function useJoltEvent<T extends CustomMessage>(\n channel: JoltSubscription | undefined | null,\n eventName: string,\n callback: UserCallbackFn<T>\n) {\n useEffect(() => {\n if (!channel) return () => {}\n\n return channel.bind(eventName, e => callback(e as T))\n }, [channel, eventName, callback])\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StorageAdapter } from '../utils/native_adapters';
|
|
2
|
+
type SetValue<TCacheData> = (_itemValue?: TCacheData | null) => Promise<any>;
|
|
3
|
+
/**
|
|
4
|
+
* Hook for using a storage adapter with React Query caching.
|
|
5
|
+
* Similar to useAsyncStorage but accepts a StorageAdapter instead of using AsyncStorage directly.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useStorage<TCacheData>(storage: StorageAdapter, key: string, initialValue: TCacheData, throwOnError?: boolean): [TCacheData, SetValue<TCacheData>];
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=use_storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_storage.d.ts","sourceRoot":"","sources":["../../src/hooks/use_storage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAIzD,KAAK,QAAQ,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAE5E;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,EACnC,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,UAAU,EACxB,YAAY,GAAE,OAAe,GAC5B,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAkDpC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useSuspenseQuery } from '@tanstack/react-query';
|
|
2
|
+
import { noop } from 'lodash';
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
const cacheKeyGenerator = (key) => [`StorageResource:${key}`];
|
|
5
|
+
/**
|
|
6
|
+
* Hook for using a storage adapter with React Query caching.
|
|
7
|
+
* Similar to useAsyncStorage but accepts a StorageAdapter instead of using AsyncStorage directly.
|
|
8
|
+
*/
|
|
9
|
+
export function useStorage(storage, key, initialValue, throwOnError = false) {
|
|
10
|
+
const cacheKey = cacheKeyGenerator(key);
|
|
11
|
+
const { data: value, refetch } = useSuspenseQuery({
|
|
12
|
+
queryKey: cacheKey,
|
|
13
|
+
queryFn: () => storage
|
|
14
|
+
.getItem(key)
|
|
15
|
+
.then(storedValue => {
|
|
16
|
+
if (!storedValue)
|
|
17
|
+
return initialValue;
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(storedValue);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return storedValue;
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
.catch(e => {
|
|
26
|
+
if (!throwOnError)
|
|
27
|
+
return initialValue;
|
|
28
|
+
return Promise.reject(e);
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
const setValue = useCallback(itemValue => {
|
|
32
|
+
if (itemValue === null || itemValue === undefined) {
|
|
33
|
+
return storage
|
|
34
|
+
.removeItem(key)
|
|
35
|
+
.then(() => {
|
|
36
|
+
refetch();
|
|
37
|
+
})
|
|
38
|
+
.catch(noop);
|
|
39
|
+
}
|
|
40
|
+
return storage
|
|
41
|
+
.setItem(key, JSON.stringify(itemValue))
|
|
42
|
+
.then(() => {
|
|
43
|
+
refetch();
|
|
44
|
+
})
|
|
45
|
+
.catch(e => {
|
|
46
|
+
if (!throwOnError)
|
|
47
|
+
return;
|
|
48
|
+
return Promise.reject(e);
|
|
49
|
+
});
|
|
50
|
+
}, [throwOnError, key, refetch, storage]);
|
|
51
|
+
return [value || initialValue, setValue];
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=use_storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_storage.js","sourceRoot":"","sources":["../../src/hooks/use_storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAA;AAIrE;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,OAAuB,EACvB,GAAW,EACX,YAAwB,EACxB,eAAwB,KAAK;IAE7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAA;IAEvC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAa;QAC5D,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,GAAG,EAAE,CACZ,OAAO;aACJ,OAAO,CAAC,GAAG,CAAC;aACZ,IAAI,CAAC,WAAW,CAAC,EAAE;YAClB,IAAI,CAAC,WAAW;gBAAE,OAAO,YAAY,CAAA;YAErC,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,WAAW,CAAA;YACpB,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAC,EAAE;YACT,IAAI,CAAC,YAAY;gBAAE,OAAO,YAAY,CAAA;YAEtC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC,CAAC;KACP,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAyB,WAAW,CAChD,SAAS,CAAC,EAAE;QACV,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAClD,OAAO,OAAO;iBACX,UAAU,CAAC,GAAG,CAAC;iBACf,IAAI,CAAC,GAAG,EAAE;gBACT,OAAO,EAAE,CAAA;YACX,CAAC,CAAC;iBACD,KAAK,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC;QAED,OAAO,OAAO;aACX,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;aACvC,IAAI,CAAC,GAAG,EAAE;YACT,OAAO,EAAE,CAAA;QACX,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAC,EAAE;YACT,IAAI,CAAC,YAAY;gBAAE,OAAM;YAEzB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC,CAAC,CAAA;IACN,CAAC,EACD,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CACtC,CAAA;IAED,OAAO,CAAC,KAAK,IAAI,YAAY,EAAE,QAAQ,CAAC,CAAA;AAC1C,CAAC","sourcesContent":["import { useSuspenseQuery } from '@tanstack/react-query'\nimport { noop } from 'lodash'\nimport { useCallback } from 'react'\nimport { StorageAdapter } from '../utils/native_adapters'\n\nconst cacheKeyGenerator = (key: string) => [`StorageResource:${key}`]\n\ntype SetValue<TCacheData> = (_itemValue?: TCacheData | null) => Promise<any>\n\n/**\n * Hook for using a storage adapter with React Query caching.\n * Similar to useAsyncStorage but accepts a StorageAdapter instead of using AsyncStorage directly.\n */\nexport function useStorage<TCacheData>(\n storage: StorageAdapter,\n key: string,\n initialValue: TCacheData,\n throwOnError: boolean = false\n): [TCacheData, SetValue<TCacheData>] {\n const cacheKey = cacheKeyGenerator(key)\n\n const { data: value, refetch } = useSuspenseQuery<TCacheData>({\n queryKey: cacheKey,\n queryFn: () =>\n storage\n .getItem(key)\n .then(storedValue => {\n if (!storedValue) return initialValue\n\n try {\n return JSON.parse(storedValue)\n } catch {\n return storedValue\n }\n })\n .catch(e => {\n if (!throwOnError) return initialValue\n\n return Promise.reject(e)\n }),\n })\n\n const setValue: SetValue<TCacheData> = useCallback(\n itemValue => {\n if (itemValue === null || itemValue === undefined) {\n return storage\n .removeItem(key)\n .then(() => {\n refetch()\n })\n .catch(noop)\n }\n\n return storage\n .setItem(key, JSON.stringify(itemValue))\n .then(() => {\n refetch()\n })\n .catch(e => {\n if (!throwOnError) return\n\n return Promise.reject(e)\n })\n },\n [throwOnError, key, refetch, storage]\n )\n\n return [value || initialValue, setValue]\n}\n"]}
|
|
@@ -5,6 +5,7 @@ import { ImagePickerAdapter } from './image_picker';
|
|
|
5
5
|
import { VideoAdapter } from './video';
|
|
6
6
|
import { LinkingAdapter } from './linking';
|
|
7
7
|
import { HapticAdapter } from './haptic';
|
|
8
|
+
import { StorageAdapter } from './storage_adapter';
|
|
8
9
|
type ChatConfigurations = {
|
|
9
10
|
clipboard: ClipboardAdapter;
|
|
10
11
|
audio: AudioAdapter;
|
|
@@ -24,5 +25,6 @@ export declare let ImagePicker: ImagePickerAdapter;
|
|
|
24
25
|
export declare let Log: LogAdapter;
|
|
25
26
|
export declare let Linking: LinkingAdapter;
|
|
26
27
|
export declare let Haptic: HapticAdapter;
|
|
28
|
+
export declare let Storage: StorageAdapter;
|
|
27
29
|
export {};
|
|
28
30
|
//# sourceMappingURL=configuration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../../src/utils/native_adapters/configuration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../../src/utils/native_adapters/configuration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAGlD,KAAK,kBAAkB,GAAG;IACxB,SAAS,EAAE,gBAAgB,CAAA;IAC3B,KAAK,EAAE,YAAY,CAAA;IACnB,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,kBAAkB,CAAA;IAC/B,GAAG,CAAC,EAAE,UAAU,CAAA;IAChB,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,MAAM,CAAC,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,qBAAa,YAAY;IACvB,MAAM,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB;CASpD;AAMD,eAAO,IAAI,SAAS,EAAE,gBAMpB,CAAA;AAEF,eAAO,IAAI,KAAK,EAAE,YAKhB,CAAA;AAEF,eAAO,IAAI,KAAK,EAAE,YAQhB,CAAA;AAEF,eAAO,IAAI,WAAW,EAAE,kBAStB,CAAA;AAEF,eAAO,IAAI,GAAG,EAAE,UAA6B,CAAA;AAE7C,eAAO,IAAI,OAAO,EAAE,cAA8C,CAAA;AAElE,eAAO,IAAI,MAAM,EAAE,aAAmC,CAAA;AAEtD,eAAO,IAAI,OAAO,gBAIhB,CAAA"}
|
|
@@ -6,6 +6,8 @@ import { VideoAdapter } from './video';
|
|
|
6
6
|
import { Linking as RNLinking } from 'react-native';
|
|
7
7
|
import { LinkingAdapter } from './linking';
|
|
8
8
|
import { HapticAdapter } from './haptic';
|
|
9
|
+
import { StorageAdapter } from './storage_adapter';
|
|
10
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
9
11
|
export class ChatAdapters {
|
|
10
12
|
static configure(configurations) {
|
|
11
13
|
Clipboard = configurations.clipboard;
|
|
@@ -52,4 +54,9 @@ export let ImagePicker = new ImagePickerAdapter({
|
|
|
52
54
|
export let Log = new LogAdapter();
|
|
53
55
|
export let Linking = new LinkingAdapter(RNLinking);
|
|
54
56
|
export let Haptic = new HapticAdapter();
|
|
57
|
+
export let Storage = new StorageAdapter({
|
|
58
|
+
getItem: AsyncStorage.getItem,
|
|
59
|
+
setItem: AsyncStorage.setItem,
|
|
60
|
+
removeItem: AsyncStorage.removeItem,
|
|
61
|
+
});
|
|
55
62
|
//# sourceMappingURL=configuration.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configuration.js","sourceRoot":"","sources":["../../../src/utils/native_adapters/configuration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"configuration.js","sourceRoot":"","sources":["../../../src/utils/native_adapters/configuration.ts"],"names":[],"mappings":"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","sourcesContent":["import { LogAdapter } from './log'\nimport { AudioAdapter } from './audio'\nimport { ClipboardAdapter } from './clipboard'\nimport { ImagePickerAdapter } from './image_picker'\nimport { VideoAdapter } from './video'\nimport { Linking as RNLinking } from 'react-native'\nimport { LinkingAdapter } from './linking'\nimport { HapticAdapter } from './haptic'\nimport { StorageAdapter } from './storage_adapter'\nimport AsyncStorage from '@react-native-async-storage/async-storage'\n\ntype ChatConfigurations = {\n clipboard: ClipboardAdapter\n audio: AudioAdapter\n video: VideoAdapter\n imagePicker: ImagePickerAdapter\n log?: LogAdapter\n linking?: LinkingAdapter\n haptic?: HapticAdapter\n}\n\nexport class ChatAdapters {\n static configure(configurations: ChatConfigurations) {\n Clipboard = configurations.clipboard\n Audio = configurations.audio\n Video = configurations.video\n ImagePicker = configurations.imagePicker\n Log = configurations.log || new LogAdapter()\n Linking = configurations.linking || new LinkingAdapter(RNLinking)\n Haptic = configurations.haptic || new HapticAdapter()\n }\n}\n\nconst methodMissing = () => {\n console.warn('ChatAdapters.configure() must be called before using any adapters')\n}\n\nexport let Clipboard: ClipboardAdapter = new ClipboardAdapter({\n getStringAsync: async () => {\n methodMissing()\n return ''\n },\n setStringAsync: async (_: string) => methodMissing(),\n})\n\nexport let Audio: AudioAdapter = new AudioAdapter({\n useAudio: (_: string) => {\n methodMissing()\n return {} as any\n },\n})\n\nexport let Video: VideoAdapter = new VideoAdapter({\n Player: Object.assign(\n () => {\n methodMissing()\n return null\n },\n { $$typeof: Symbol.for('react.forward_ref') }\n ),\n})\n\nexport let ImagePicker: ImagePickerAdapter = new ImagePickerAdapter({\n openCameraAsync: async () => {\n methodMissing()\n return { canceled: true, assets: null }\n },\n openImageLibraryAsync: async () => {\n methodMissing()\n return { canceled: true, assets: null }\n },\n})\n\nexport let Log: LogAdapter = new LogAdapter()\n\nexport let Linking: LinkingAdapter = new LinkingAdapter(RNLinking)\n\nexport let Haptic: HapticAdapter = new HapticAdapter()\n\nexport let Storage = new StorageAdapter({\n getItem: AsyncStorage.getItem,\n setItem: AsyncStorage.setItem,\n removeItem: AsyncStorage.removeItem,\n})\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/native_adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/native_adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,mBAAmB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/native_adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA","sourcesContent":["export * from './audio'\nexport * from './clipboard'\nexport * from './configuration'\nexport * from './image_picker'\nexport * from './linking'\nexport * from './log'\nexport * from './video'\nexport * from './haptic'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/native_adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,mBAAmB,CAAA","sourcesContent":["export * from './audio'\nexport * from './clipboard'\nexport * from './configuration'\nexport * from './image_picker'\nexport * from './linking'\nexport * from './log'\nexport * from './video'\nexport * from './haptic'\nexport * from './storage_adapter'\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage adapter interface for abstracting storage implementations.
|
|
3
|
+
* Allows apps to use different storage backends (AsyncStorage, expo-secure-store, etc.)
|
|
4
|
+
* without requiring those dependencies in the shared package.
|
|
5
|
+
*/
|
|
6
|
+
export type StorageAdapterMethods = {
|
|
7
|
+
getItem: (key: string) => Promise<string | null>;
|
|
8
|
+
setItem: (key: string, value: string) => Promise<void>;
|
|
9
|
+
removeItem: (key: string) => Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
export declare class StorageAdapter {
|
|
12
|
+
getItem: (key: string) => Promise<string | null>;
|
|
13
|
+
setItem: (key: string, value: string) => Promise<void>;
|
|
14
|
+
removeItem: (key: string) => Promise<void>;
|
|
15
|
+
constructor(methods: StorageAdapterMethods);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=storage_adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage_adapter.d.ts","sourceRoot":"","sources":["../../../src/utils/native_adapters/storage_adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAChD,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3C,CAAA;AAED,qBAAa,cAAc;IACzB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAChD,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;gBAE9B,OAAO,EAAE,qBAAqB;CAK3C"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage adapter interface for abstracting storage implementations.
|
|
3
|
+
* Allows apps to use different storage backends (AsyncStorage, expo-secure-store, etc.)
|
|
4
|
+
* without requiring those dependencies in the shared package.
|
|
5
|
+
*/
|
|
6
|
+
export class StorageAdapter {
|
|
7
|
+
getItem;
|
|
8
|
+
setItem;
|
|
9
|
+
removeItem;
|
|
10
|
+
constructor(methods) {
|
|
11
|
+
this.getItem = methods.getItem;
|
|
12
|
+
this.setItem = methods.setItem;
|
|
13
|
+
this.removeItem = methods.removeItem;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=storage_adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage_adapter.js","sourceRoot":"","sources":["../../../src/utils/native_adapters/storage_adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,OAAO,cAAc;IACzB,OAAO,CAAyC;IAChD,OAAO,CAA+C;IACtD,UAAU,CAAgC;IAE1C,YAAY,OAA8B;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAA;IACtC,CAAC;CACF","sourcesContent":["/**\n * Storage adapter interface for abstracting storage implementations.\n * Allows apps to use different storage backends (AsyncStorage, expo-secure-store, etc.)\n * without requiring those dependencies in the shared package.\n */\n\nexport type StorageAdapterMethods = {\n getItem: (key: string) => Promise<string | null>\n setItem: (key: string, value: string) => Promise<void>\n removeItem: (key: string) => Promise<void>\n}\n\nexport class StorageAdapter {\n getItem: (key: string) => Promise<string | null>\n setItem: (key: string, value: string) => Promise<void>\n removeItem: (key: string) => Promise<void>\n\n constructor(methods: StorageAdapterMethods) {\n this.getItem = methods.getItem\n this.setItem = methods.setItem\n this.removeItem = methods.removeItem\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.21.2-rc.
|
|
3
|
+
"version": "3.21.2-rc.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"react-native-url-polyfill": "^2.0.0",
|
|
59
59
|
"typescript": "<5.6.0"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "243ecc2da2b0a74b66db045af3f30655ea57a55c"
|
|
62
62
|
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { noop } from 'lodash'
|
|
4
|
-
import { useCallback } from 'react'
|
|
5
|
-
|
|
6
|
-
const cacheKeyGenerator = (key: string) => [`AsyncStorageResource:${key}`]
|
|
1
|
+
import { Storage } from '../utils/native_adapters'
|
|
2
|
+
import { useStorage } from './use_storage'
|
|
7
3
|
|
|
8
4
|
type SetValue<TCacheData> = (_itemValue?: TCacheData | null) => Promise<void>
|
|
9
5
|
|
|
@@ -12,50 +8,5 @@ export function useAsyncStorage<TCacheData>(
|
|
|
12
8
|
initialValue: TCacheData,
|
|
13
9
|
throwOnError: boolean = false
|
|
14
10
|
): [TCacheData, SetValue<TCacheData>] {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const { data: value, refetch } = useSuspenseQuery<TCacheData>({
|
|
18
|
-
queryKey: cacheKey,
|
|
19
|
-
queryFn: () =>
|
|
20
|
-
AsyncStorage.getItem(key)
|
|
21
|
-
.then(storedValue => {
|
|
22
|
-
if (!storedValue) return initialValue
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
return JSON.parse(storedValue)
|
|
26
|
-
} catch {
|
|
27
|
-
return storedValue
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
.catch(e => {
|
|
31
|
-
if (!throwOnError) return initialValue
|
|
32
|
-
|
|
33
|
-
return Promise.reject(e)
|
|
34
|
-
}),
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const setValue: SetValue<TCacheData> = useCallback(
|
|
38
|
-
itemValue => {
|
|
39
|
-
if (itemValue === null || itemValue === undefined) {
|
|
40
|
-
return AsyncStorage.removeItem(key)
|
|
41
|
-
.then(() => {
|
|
42
|
-
refetch()
|
|
43
|
-
})
|
|
44
|
-
.catch(noop)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return AsyncStorage.setItem(key, JSON.stringify(itemValue))
|
|
48
|
-
.then(() => {
|
|
49
|
-
refetch()
|
|
50
|
-
})
|
|
51
|
-
.catch(e => {
|
|
52
|
-
if (!throwOnError) return
|
|
53
|
-
|
|
54
|
-
return Promise.reject(e)
|
|
55
|
-
})
|
|
56
|
-
},
|
|
57
|
-
[throwOnError, key, refetch]
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
return [value || initialValue, setValue]
|
|
11
|
+
return useStorage<TCacheData>(Storage, key, initialValue, throwOnError)
|
|
61
12
|
}
|
package/src/hooks/use_jolt.ts
CHANGED
|
@@ -12,7 +12,6 @@ import { useCallback, useEffect, useMemo } from 'react'
|
|
|
12
12
|
import { useChatContext } from '../contexts/chat_context'
|
|
13
13
|
import { ApiResource } from '../types'
|
|
14
14
|
import { Client, Uri } from '../utils'
|
|
15
|
-
import { useAppState } from './use_app_state'
|
|
16
15
|
|
|
17
16
|
interface JoltResponse {
|
|
18
17
|
type: 'JoltToken'
|
|
@@ -59,6 +58,7 @@ export const useJoltClient = (): JoltClient | undefined => {
|
|
|
59
58
|
queryFn: () => fetchJoltToken().then(res => res.data.wssUrl),
|
|
60
59
|
staleTime: Infinity,
|
|
61
60
|
gcTime: Infinity,
|
|
61
|
+
refetchOnWindowFocus: false,
|
|
62
62
|
})
|
|
63
63
|
|
|
64
64
|
const fetchAuthTokenFn: FetchAuthToken = () => {
|
|
@@ -112,6 +112,7 @@ export const useJoltClient = (): JoltClient | undefined => {
|
|
|
112
112
|
{ logToConsole: false }
|
|
113
113
|
)
|
|
114
114
|
},
|
|
115
|
+
refetchOnWindowFocus: false,
|
|
115
116
|
staleTime: Infinity,
|
|
116
117
|
gcTime: Infinity,
|
|
117
118
|
})
|
|
@@ -124,9 +125,8 @@ export function useJoltChannel(
|
|
|
124
125
|
enabled: boolean = true
|
|
125
126
|
): JoltSubscription | undefined | null {
|
|
126
127
|
const jolt = useJoltClient()
|
|
127
|
-
const appState = useAppState()
|
|
128
128
|
const queryClient = useQueryClient()
|
|
129
|
-
const ready = Boolean(jolt) &&
|
|
129
|
+
const ready = Boolean(jolt) && enabled
|
|
130
130
|
|
|
131
131
|
const handleSubscribe = useCallback(async () => {
|
|
132
132
|
if (!jolt) return null
|
|
@@ -141,6 +141,7 @@ export function useJoltChannel(
|
|
|
141
141
|
const { data: subscription } = useQuery<JoltSubscription | null>({
|
|
142
142
|
queryKey: ['jolt-subscription', channelName],
|
|
143
143
|
queryFn: handleSubscribe,
|
|
144
|
+
refetchOnWindowFocus: false,
|
|
144
145
|
enabled: ready,
|
|
145
146
|
})
|
|
146
147
|
|
|
@@ -154,12 +155,8 @@ export function useJoltChannel(
|
|
|
154
155
|
}, [queryClient, channelName, jolt])
|
|
155
156
|
|
|
156
157
|
useEffect(() => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
handleUnsubscribe()
|
|
160
|
-
|
|
161
|
-
return () => null
|
|
162
|
-
}, [appState, handleUnsubscribe])
|
|
158
|
+
return handleUnsubscribe
|
|
159
|
+
}, [handleUnsubscribe])
|
|
163
160
|
|
|
164
161
|
return subscription
|
|
165
162
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useSuspenseQuery } from '@tanstack/react-query'
|
|
2
|
+
import { noop } from 'lodash'
|
|
3
|
+
import { useCallback } from 'react'
|
|
4
|
+
import { StorageAdapter } from '../utils/native_adapters'
|
|
5
|
+
|
|
6
|
+
const cacheKeyGenerator = (key: string) => [`StorageResource:${key}`]
|
|
7
|
+
|
|
8
|
+
type SetValue<TCacheData> = (_itemValue?: TCacheData | null) => Promise<any>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Hook for using a storage adapter with React Query caching.
|
|
12
|
+
* Similar to useAsyncStorage but accepts a StorageAdapter instead of using AsyncStorage directly.
|
|
13
|
+
*/
|
|
14
|
+
export function useStorage<TCacheData>(
|
|
15
|
+
storage: StorageAdapter,
|
|
16
|
+
key: string,
|
|
17
|
+
initialValue: TCacheData,
|
|
18
|
+
throwOnError: boolean = false
|
|
19
|
+
): [TCacheData, SetValue<TCacheData>] {
|
|
20
|
+
const cacheKey = cacheKeyGenerator(key)
|
|
21
|
+
|
|
22
|
+
const { data: value, refetch } = useSuspenseQuery<TCacheData>({
|
|
23
|
+
queryKey: cacheKey,
|
|
24
|
+
queryFn: () =>
|
|
25
|
+
storage
|
|
26
|
+
.getItem(key)
|
|
27
|
+
.then(storedValue => {
|
|
28
|
+
if (!storedValue) return initialValue
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(storedValue)
|
|
32
|
+
} catch {
|
|
33
|
+
return storedValue
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
.catch(e => {
|
|
37
|
+
if (!throwOnError) return initialValue
|
|
38
|
+
|
|
39
|
+
return Promise.reject(e)
|
|
40
|
+
}),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const setValue: SetValue<TCacheData> = useCallback(
|
|
44
|
+
itemValue => {
|
|
45
|
+
if (itemValue === null || itemValue === undefined) {
|
|
46
|
+
return storage
|
|
47
|
+
.removeItem(key)
|
|
48
|
+
.then(() => {
|
|
49
|
+
refetch()
|
|
50
|
+
})
|
|
51
|
+
.catch(noop)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return storage
|
|
55
|
+
.setItem(key, JSON.stringify(itemValue))
|
|
56
|
+
.then(() => {
|
|
57
|
+
refetch()
|
|
58
|
+
})
|
|
59
|
+
.catch(e => {
|
|
60
|
+
if (!throwOnError) return
|
|
61
|
+
|
|
62
|
+
return Promise.reject(e)
|
|
63
|
+
})
|
|
64
|
+
},
|
|
65
|
+
[throwOnError, key, refetch, storage]
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return [value || initialValue, setValue]
|
|
69
|
+
}
|
|
@@ -6,6 +6,8 @@ import { VideoAdapter } from './video'
|
|
|
6
6
|
import { Linking as RNLinking } from 'react-native'
|
|
7
7
|
import { LinkingAdapter } from './linking'
|
|
8
8
|
import { HapticAdapter } from './haptic'
|
|
9
|
+
import { StorageAdapter } from './storage_adapter'
|
|
10
|
+
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
9
11
|
|
|
10
12
|
type ChatConfigurations = {
|
|
11
13
|
clipboard: ClipboardAdapter
|
|
@@ -74,3 +76,9 @@ export let Log: LogAdapter = new LogAdapter()
|
|
|
74
76
|
export let Linking: LinkingAdapter = new LinkingAdapter(RNLinking)
|
|
75
77
|
|
|
76
78
|
export let Haptic: HapticAdapter = new HapticAdapter()
|
|
79
|
+
|
|
80
|
+
export let Storage = new StorageAdapter({
|
|
81
|
+
getItem: AsyncStorage.getItem,
|
|
82
|
+
setItem: AsyncStorage.setItem,
|
|
83
|
+
removeItem: AsyncStorage.removeItem,
|
|
84
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage adapter interface for abstracting storage implementations.
|
|
3
|
+
* Allows apps to use different storage backends (AsyncStorage, expo-secure-store, etc.)
|
|
4
|
+
* without requiring those dependencies in the shared package.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type StorageAdapterMethods = {
|
|
8
|
+
getItem: (key: string) => Promise<string | null>
|
|
9
|
+
setItem: (key: string, value: string) => Promise<void>
|
|
10
|
+
removeItem: (key: string) => Promise<void>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class StorageAdapter {
|
|
14
|
+
getItem: (key: string) => Promise<string | null>
|
|
15
|
+
setItem: (key: string, value: string) => Promise<void>
|
|
16
|
+
removeItem: (key: string) => Promise<void>
|
|
17
|
+
|
|
18
|
+
constructor(methods: StorageAdapterMethods) {
|
|
19
|
+
this.getItem = methods.getItem
|
|
20
|
+
this.setItem = methods.setItem
|
|
21
|
+
this.removeItem = methods.removeItem
|
|
22
|
+
}
|
|
23
|
+
}
|