@buoy-gg/react-query 1.7.8 → 2.1.1
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/lib/commonjs/index.js +619 -24
- package/lib/commonjs/preset.js +1 -1
- package/lib/commonjs/react-query/components/ReactQueryDevToolsModal.js +12 -0
- package/lib/commonjs/react-query/components/modals/MutationBrowserModal.js +2 -1
- package/lib/commonjs/react-query/components/modals/QueryBrowserModal.js +8 -14
- package/lib/commonjs/react-query/hooks/useAllMutations.js +65 -15
- package/lib/commonjs/react-query/hooks/useWifiState.js +3 -3
- package/lib/commonjs/react-query/index.js +11 -0
- package/lib/commonjs/react-query/stores/index.js +48 -0
- package/lib/commonjs/react-query/stores/reactQueryEventStore.js +311 -0
- package/lib/commonjs/react-query/utils/modalStorageOperations.js +2 -2
- package/lib/module/index.js +113 -8
- package/lib/module/preset.js +2 -2
- package/lib/module/react-query/components/ReactQueryDevToolsModal.js +13 -1
- package/lib/module/react-query/components/modals/MutationBrowserModal.js +2 -1
- package/lib/module/react-query/components/modals/QueryBrowserModal.js +9 -15
- package/lib/module/react-query/hooks/useAllMutations.js +66 -16
- package/lib/module/react-query/hooks/useWifiState.js +4 -4
- package/lib/module/react-query/index.js +2 -1
- package/lib/module/react-query/stores/index.js +3 -0
- package/lib/module/react-query/stores/reactQueryEventStore.js +302 -0
- package/lib/module/react-query/utils/modalStorageOperations.js +3 -3
- package/lib/typescript/index.d.ts +61 -5
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/react-query/components/ReactQueryDevToolsModal.d.ts.map +1 -1
- package/lib/typescript/react-query/components/modals/MutationBrowserModal.d.ts.map +1 -1
- package/lib/typescript/react-query/components/modals/QueryBrowserModal.d.ts.map +1 -1
- package/lib/typescript/react-query/hooks/useAllMutations.d.ts +2 -2
- package/lib/typescript/react-query/hooks/useAllMutations.d.ts.map +1 -1
- package/lib/typescript/react-query/hooks/useWifiState.d.ts +1 -1
- package/lib/typescript/react-query/hooks/useWifiState.d.ts.map +1 -1
- package/lib/typescript/react-query/index.d.ts +1 -0
- package/lib/typescript/react-query/index.d.ts.map +1 -1
- package/lib/typescript/react-query/stores/index.d.ts +2 -0
- package/lib/typescript/react-query/stores/index.d.ts.map +1 -0
- package/lib/typescript/react-query/stores/reactQueryEventStore.d.ts +99 -0
- package/lib/typescript/react-query/stores/reactQueryEventStore.d.ts.map +1 -0
- package/package.json +17 -3
package/lib/module/index.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @buoy-gg/react-query
|
|
5
|
+
*
|
|
6
|
+
* React Query DevTools for React Native.
|
|
7
|
+
*
|
|
8
|
+
* PUBLIC API - Only these exports are supported for external use.
|
|
9
|
+
* Internal stores and event subscription mechanisms are not exported
|
|
10
|
+
* to prevent bypassing the tool's intended usage patterns.
|
|
11
|
+
*/
|
|
12
|
+
|
|
3
13
|
// Check if @tanstack/react-query is installed
|
|
4
14
|
try {
|
|
5
15
|
require("@tanstack/react-query");
|
|
@@ -7,13 +17,108 @@ try {
|
|
|
7
17
|
throw new Error("\n\n[@buoy-gg/react-query] ERROR: Missing required peer dependency\n\n" + "This package requires @tanstack/react-query to be installed.\n\n" + "Install it with:\n" + " npm install @tanstack/react-query\n" + " or\n" + " pnpm add @tanstack/react-query\n" + " or\n" + " yarn add @tanstack/react-query\n\n" + "For more information, visit: https://tanstack.com/query/latest\n");
|
|
8
18
|
}
|
|
9
19
|
|
|
10
|
-
//
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// PRESET (Primary entry point for users)
|
|
22
|
+
// =============================================================================
|
|
11
23
|
export { reactQueryToolPreset, createReactQueryTool, wifiTogglePreset, createWifiToggleTool } from "./preset";
|
|
12
24
|
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// QUERY CLIENT CONNECTION (Required for users to connect their QueryClient)
|
|
27
|
+
// =============================================================================
|
|
28
|
+
export { setQueryClient, disconnectQueryClient } from "./react-query/stores/reactQueryEventStore";
|
|
29
|
+
|
|
30
|
+
// =============================================================================
|
|
31
|
+
// COMPONENTS (For custom UI implementations)
|
|
32
|
+
// =============================================================================
|
|
33
|
+
|
|
34
|
+
// Main modals
|
|
35
|
+
export { ReactQueryModal } from "./react-query/components/modals/ReactQueryModal";
|
|
36
|
+
export { ReactQueryModalHeader } from "./react-query/components/modals/ReactQueryModalHeader";
|
|
37
|
+
export { QueryBrowserModal } from "./react-query/components/modals/QueryBrowserModal";
|
|
38
|
+
export { MutationBrowserModal } from "./react-query/components/modals/MutationBrowserModal";
|
|
39
|
+
export { MutationEditorModal } from "./react-query/components/modals/MutationEditorModal";
|
|
40
|
+
export { DataEditorModal } from "./react-query/components/modals/DataEditorModal";
|
|
41
|
+
export { QueryBrowserFooter } from "./react-query/components/modals/QueryBrowserFooter";
|
|
42
|
+
export { MutationBrowserFooter } from "./react-query/components/modals/MutationBrowserFooter";
|
|
43
|
+
export { SwipeIndicator } from "./react-query/components/modals/SwipeIndicator";
|
|
44
|
+
|
|
45
|
+
// Query browser components
|
|
46
|
+
export { Explorer, QueryBrowser, QueryDetails, QueryInformation, QueryActions, QueryRow, QueryStatus, QueryStatusCount, QueryDetailsChip, MutationsList, MutationDetails, MutationInformation, MutationButton, MutationStatusCount, MutationDetailsChips, ActionButton, ClearCacheButton, NetworkToggleButton, StorageStatusCount } from "./react-query/components/query-browser";
|
|
47
|
+
|
|
48
|
+
// Mode components
|
|
49
|
+
export { QueryBrowserMode } from "./react-query/components/QueryBrowserMode";
|
|
50
|
+
export { MutationBrowserMode } from "./react-query/components/MutationBrowserMode";
|
|
51
|
+
export { MutationEditorMode } from "./react-query/components/MutationEditorMode";
|
|
52
|
+
export { DataEditorMode } from "./react-query/components/DataEditorMode";
|
|
53
|
+
export { QuerySelector } from "./react-query/components/QuerySelector";
|
|
54
|
+
export { QueryDebugInfo } from "./react-query/components/QueryDebugInfo";
|
|
55
|
+
export { WifiToggle } from "./react-query/components/WifiToggle";
|
|
56
|
+
export { ReactQuerySection } from "./react-query/components/ReactQuerySection";
|
|
57
|
+
export { ReactQueryDevToolsModal } from "./react-query/components/ReactQueryDevToolsModal";
|
|
58
|
+
|
|
59
|
+
// Shared data viewer components
|
|
60
|
+
export { VirtualizedDataExplorer, DataViewer, TypeLegend } from "@buoy-gg/shared-ui/dataViewer";
|
|
61
|
+
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// HOOKS (For consuming React Query data)
|
|
64
|
+
// =============================================================================
|
|
65
|
+
export { default as useAllQueries } from "./react-query/hooks/useAllQueries";
|
|
66
|
+
export { default as useAllMutations } from "./react-query/hooks/useAllMutations";
|
|
67
|
+
export { useGetQueryByQueryKey, useGetQueryByQueryKeyWithVersion } from "./react-query/hooks/useSelectedQuery";
|
|
68
|
+
export { useGetMutationById } from "./react-query/hooks/useSelectedMutation";
|
|
69
|
+
export { default as useQueryStatusCounts } from "./react-query/hooks/useQueryStatusCounts";
|
|
70
|
+
export { useStorageQueryCounts } from "./react-query/hooks/useStorageQueryCounts";
|
|
71
|
+
export { useReactQueryState } from "./react-query/hooks/useReactQueryState";
|
|
72
|
+
export { useActionButtons } from "./react-query/hooks/useActionButtons";
|
|
73
|
+
export { useMutationActionButtons } from "./react-query/hooks/useMutationActionButtons";
|
|
74
|
+
export { useModalManager } from "./react-query/hooks/useModalManager";
|
|
75
|
+
export { useModalPersistence } from "./react-query/hooks/useModalPersistence";
|
|
76
|
+
export { useWifiState } from "./react-query/hooks/useWifiState";
|
|
77
|
+
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// UTILITIES (Public helpers only)
|
|
80
|
+
// =============================================================================
|
|
81
|
+
|
|
82
|
+
// Action utilities
|
|
83
|
+
export { default as invalidate } from "./react-query/utils/actions/invalidate";
|
|
84
|
+
export { default as refetch } from "./react-query/utils/actions/refetch";
|
|
85
|
+
export { default as reset } from "./react-query/utils/actions/reset";
|
|
86
|
+
export { default as remove } from "./react-query/utils/actions/remove";
|
|
87
|
+
export { default as deleteItem } from "./react-query/utils/actions/deleteItem";
|
|
88
|
+
export { default as triggerError } from "./react-query/utils/actions/triggerError";
|
|
89
|
+
export { default as triggerLoading } from "./react-query/utils/actions/triggerLoading";
|
|
90
|
+
|
|
91
|
+
// Query status utilities
|
|
92
|
+
export * from "./react-query/utils/getQueryStatusLabel";
|
|
93
|
+
export * from "./react-query/utils/getQueryStatusColor";
|
|
94
|
+
|
|
95
|
+
// Storage utilities
|
|
96
|
+
export * from "./react-query/utils/getStorageQueryCounts";
|
|
97
|
+
export * from "./react-query/utils/storageQueryUtils";
|
|
98
|
+
export * from "./react-query/utils/modalStorageOperations";
|
|
99
|
+
|
|
100
|
+
// Data manipulation utilities
|
|
101
|
+
export * from "./react-query/utils/updateNestedDataByPath";
|
|
102
|
+
export * from "./react-query/utils/deleteNestedDataByPath";
|
|
103
|
+
export { safeStringify, displayValue, parseDisplayValue } from "@buoy-gg/shared-ui";
|
|
104
|
+
|
|
105
|
+
// =============================================================================
|
|
106
|
+
// TYPES
|
|
107
|
+
// =============================================================================
|
|
108
|
+
|
|
109
|
+
export { isPlainObject } from "./react-query/types/types";
|
|
110
|
+
|
|
111
|
+
// =============================================================================
|
|
112
|
+
// INTERNAL EXPORTS (For @buoy-gg/* packages only - not part of public API)
|
|
113
|
+
// =============================================================================
|
|
114
|
+
/** @internal */
|
|
115
|
+
export { reactQueryEventStore } from "./react-query/stores/reactQueryEventStore";
|
|
116
|
+
|
|
117
|
+
// =============================================================================
|
|
118
|
+
// NOT EXPORTED (Internal controls)
|
|
119
|
+
// =============================================================================
|
|
120
|
+
// The following are intentionally NOT exported to prevent bypassing:
|
|
121
|
+
// - getReactQueryEvents (internal store access)
|
|
122
|
+
// - subscribeToReactQueryEvents (internal subscription)
|
|
123
|
+
// - clearReactQueryEvents (internal store control)
|
|
124
|
+
// - isReactQueryConnected (internal state query)
|
package/lib/module/preset.js
CHANGED
|
@@ -21,7 +21,7 @@ import { QueryIcon } from "@buoy-gg/floating-tools-core";
|
|
|
21
21
|
import { Wifi } from "@buoy-gg/shared-ui";
|
|
22
22
|
import { ReactQueryDevToolsModal } from "./react-query/components/ReactQueryDevToolsModal";
|
|
23
23
|
import { onlineManager } from "@tanstack/react-query";
|
|
24
|
-
import { devToolsStorageKeys,
|
|
24
|
+
import { devToolsStorageKeys, persistentStorage } from "@buoy-gg/shared-ui";
|
|
25
25
|
|
|
26
26
|
// Empty component for toggle-only mode
|
|
27
27
|
const EmptyComponent = () => null;
|
|
@@ -29,7 +29,7 @@ const EmptyComponent = () => null;
|
|
|
29
29
|
// Save WiFi state to storage
|
|
30
30
|
const saveWifiState = async enabled => {
|
|
31
31
|
try {
|
|
32
|
-
await
|
|
32
|
+
await persistentStorage.setItem(devToolsStorageKeys.settings.wifiEnabled(), enabled.toString());
|
|
33
33
|
} catch (error) {
|
|
34
34
|
// Failed to save WiFi state
|
|
35
35
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useState } from "react";
|
|
3
|
+
import { useCallback, useState, useEffect } from "react";
|
|
4
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
4
5
|
import { ReactQueryModal } from "./modals/ReactQueryModal";
|
|
6
|
+
import { reactQueryEventStore } from "../stores/reactQueryEventStore";
|
|
5
7
|
|
|
6
8
|
/** Configuration options for the high-level React Query dev tools modal wrapper. */
|
|
7
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -15,6 +17,16 @@ export function ReactQueryDevToolsModal({
|
|
|
15
17
|
onMinimize,
|
|
16
18
|
enableSharedModalDimensions = true
|
|
17
19
|
}) {
|
|
20
|
+
// Get QueryClient and connect to event store for unified Events DevTools
|
|
21
|
+
const queryClient = useQueryClient();
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
// Connect the QueryClient to the event store so events flow to unified Events DevTools
|
|
24
|
+
// Only connect if not already connected (to preserve connection across modal open/close)
|
|
25
|
+
if (!reactQueryEventStore.isConnected()) {
|
|
26
|
+
reactQueryEventStore.setQueryClient(queryClient);
|
|
27
|
+
}
|
|
28
|
+
// Don't disconnect on unmount - keep the connection for unified Events DevTools
|
|
29
|
+
}, [queryClient]);
|
|
18
30
|
const [selectedQueryKey, setSelectedQueryKey] = useState(undefined);
|
|
19
31
|
const [selectedMutationId, setSelectedMutationId] = useState(undefined);
|
|
20
32
|
const [activeFilter, setActiveFilter] = useState(null);
|
|
@@ -37,7 +37,8 @@ export function MutationBrowserModal({
|
|
|
37
37
|
// Clear mutation cache handler
|
|
38
38
|
const handleClearCache = useCallback(() => {
|
|
39
39
|
queryClient.getMutationCache().clear();
|
|
40
|
-
|
|
40
|
+
onMutationSelect(undefined);
|
|
41
|
+
}, [queryClient, onMutationSelect]);
|
|
41
42
|
|
|
42
43
|
// Track modal mode for conditional styling
|
|
43
44
|
// Initialize with bottomSheet but it will be updated from persisted state if available
|
|
@@ -9,7 +9,7 @@ import { QueryBrowserFooter } from "./QueryBrowserFooter";
|
|
|
9
9
|
import { QueryFilterViewV3 } from "../QueryFilterViewV3";
|
|
10
10
|
import { useState, useCallback, useEffect } from "react";
|
|
11
11
|
import { View, StyleSheet } from "react-native";
|
|
12
|
-
import { devToolsStorageKeys,
|
|
12
|
+
import { devToolsStorageKeys, persistentStorage, buoyColors } from "@buoy-gg/shared-ui";
|
|
13
13
|
import useAllQueries from "../../hooks/useAllQueries";
|
|
14
14
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
15
|
/**
|
|
@@ -48,17 +48,11 @@ export function QueryBrowserModal({
|
|
|
48
48
|
const [ignoredPatterns, setIgnoredPatterns] = useState(new Set());
|
|
49
49
|
const [includedPatterns, setIncludedPatterns] = useState(new Set());
|
|
50
50
|
|
|
51
|
-
// AsyncStorage for persisting ignored patterns
|
|
52
|
-
const {
|
|
53
|
-
getItem: safeGetItem,
|
|
54
|
-
setItem: safeSetItem
|
|
55
|
-
} = useSafeAsyncStorage();
|
|
56
|
-
|
|
57
51
|
// Load ignored patterns from storage on mount
|
|
58
52
|
useEffect(() => {
|
|
59
53
|
const loadFilters = async () => {
|
|
60
54
|
try {
|
|
61
|
-
const stored = await
|
|
55
|
+
const stored = await persistentStorage.getItem(devToolsStorageKeys.reactQuery.ignoredPatterns());
|
|
62
56
|
if (stored) {
|
|
63
57
|
const patterns = JSON.parse(stored);
|
|
64
58
|
if (Array.isArray(patterns)) {
|
|
@@ -70,13 +64,13 @@ export function QueryBrowserModal({
|
|
|
70
64
|
}
|
|
71
65
|
};
|
|
72
66
|
loadFilters();
|
|
73
|
-
}, [
|
|
67
|
+
}, []);
|
|
74
68
|
|
|
75
69
|
// Load included patterns from storage on mount
|
|
76
70
|
useEffect(() => {
|
|
77
71
|
const loadFilters = async () => {
|
|
78
72
|
try {
|
|
79
|
-
const stored = await
|
|
73
|
+
const stored = await persistentStorage.getItem(devToolsStorageKeys.reactQuery.includedPatterns());
|
|
80
74
|
if (stored) {
|
|
81
75
|
const patterns = JSON.parse(stored);
|
|
82
76
|
if (Array.isArray(patterns)) {
|
|
@@ -88,33 +82,33 @@ export function QueryBrowserModal({
|
|
|
88
82
|
}
|
|
89
83
|
};
|
|
90
84
|
loadFilters();
|
|
91
|
-
}, [
|
|
85
|
+
}, []);
|
|
92
86
|
|
|
93
87
|
// Save ignored patterns to storage when they change
|
|
94
88
|
useEffect(() => {
|
|
95
89
|
const saveFilters = async () => {
|
|
96
90
|
try {
|
|
97
91
|
const patterns = Array.from(ignoredPatterns);
|
|
98
|
-
await
|
|
92
|
+
await persistentStorage.setItem(devToolsStorageKeys.reactQuery.ignoredPatterns(), JSON.stringify(patterns));
|
|
99
93
|
} catch (error) {
|
|
100
94
|
console.error("Failed to save ignored patterns:", error);
|
|
101
95
|
}
|
|
102
96
|
};
|
|
103
97
|
saveFilters();
|
|
104
|
-
}, [ignoredPatterns
|
|
98
|
+
}, [ignoredPatterns]);
|
|
105
99
|
|
|
106
100
|
// Save included patterns to storage when they change
|
|
107
101
|
useEffect(() => {
|
|
108
102
|
const saveFilters = async () => {
|
|
109
103
|
try {
|
|
110
104
|
const patterns = Array.from(includedPatterns);
|
|
111
|
-
await
|
|
105
|
+
await persistentStorage.setItem(devToolsStorageKeys.reactQuery.includedPatterns(), JSON.stringify(patterns));
|
|
112
106
|
} catch (error) {
|
|
113
107
|
console.error("Failed to save included patterns:", error);
|
|
114
108
|
}
|
|
115
109
|
};
|
|
116
110
|
saveFilters();
|
|
117
|
-
}, [includedPatterns
|
|
111
|
+
}, [includedPatterns]);
|
|
118
112
|
|
|
119
113
|
// Toggle pattern in ignored set
|
|
120
114
|
const handlePatternToggle = useCallback(pattern => {
|
|
@@ -1,30 +1,80 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { useQueryClient } from "@tanstack/react-query";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Tracks all active React Query mutations with lightweight change detection.
|
|
8
|
-
*
|
|
7
|
+
* Tracks all active React Query mutations with lightweight change detection.
|
|
8
|
+
* Mirrors the pattern used in useAllQueries for consistency.
|
|
9
9
|
*/
|
|
10
10
|
function useAllMutations() {
|
|
11
11
|
const queryClient = useQueryClient();
|
|
12
|
-
const [mutations, setMutations] = useState(
|
|
13
|
-
|
|
12
|
+
const [mutations, setMutations] = useState(() => {
|
|
13
|
+
// Initialize with current mutations to avoid flash
|
|
14
|
+
return queryClient.getMutationCache().getAll();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Track mutation states using a Map for O(1) lookups
|
|
18
|
+
const mutationStatesRef = useRef(new Map());
|
|
19
|
+
const updateTimerRef = useRef(undefined);
|
|
20
|
+
|
|
21
|
+
// Check if mutations have changed
|
|
22
|
+
const hasMutationsChanged = useCallback(newMutations => {
|
|
23
|
+
const statesMap = mutationStatesRef.current;
|
|
24
|
+
|
|
25
|
+
// Quick length check first
|
|
26
|
+
if (newMutations.length !== statesMap.size) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Check if any mutation state has changed
|
|
31
|
+
for (const mutation of newMutations) {
|
|
32
|
+
const prevState = statesMap.get(mutation.mutationId);
|
|
33
|
+
if (!prevState) return true;
|
|
34
|
+
if (prevState.status !== mutation.state.status || prevState.submittedAt !== mutation.state.submittedAt || prevState.isPaused !== mutation.state.isPaused) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
// Update function
|
|
42
|
+
const updateMutations = useCallback(() => {
|
|
43
|
+
const allMutations = queryClient.getMutationCache().getAll();
|
|
44
|
+
if (hasMutationsChanged(allMutations)) {
|
|
45
|
+
// Update states map
|
|
46
|
+
const newStatesMap = new Map();
|
|
47
|
+
allMutations.forEach(m => {
|
|
48
|
+
newStatesMap.set(m.mutationId, m.state);
|
|
49
|
+
});
|
|
50
|
+
mutationStatesRef.current = newStatesMap;
|
|
51
|
+
setMutations(allMutations);
|
|
52
|
+
}
|
|
53
|
+
}, [queryClient, hasMutationsChanged]);
|
|
14
54
|
useEffect(() => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
55
|
+
// Initial update
|
|
56
|
+
updateMutations();
|
|
57
|
+
|
|
58
|
+
// Subscribe with event filtering (matching useAllQueries pattern)
|
|
59
|
+
const unsubscribe = queryClient.getMutationCache().subscribe(event => {
|
|
60
|
+
// Process events that affect mutation list
|
|
61
|
+
if (event.type === "added" || event.type === "removed" || event.type === "updated") {
|
|
62
|
+
// Debounce updates to batch rapid changes
|
|
63
|
+
if (updateTimerRef.current) {
|
|
64
|
+
clearTimeout(updateTimerRef.current);
|
|
65
|
+
}
|
|
66
|
+
updateTimerRef.current = setTimeout(() => {
|
|
67
|
+
updateMutations();
|
|
68
|
+
}, 10);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return () => {
|
|
72
|
+
unsubscribe();
|
|
73
|
+
if (updateTimerRef.current) {
|
|
74
|
+
clearTimeout(updateTimerRef.current);
|
|
22
75
|
}
|
|
23
76
|
};
|
|
24
|
-
|
|
25
|
-
const unsubscribe = queryClient.getMutationCache().subscribe(updateMutations);
|
|
26
|
-
return () => unsubscribe();
|
|
27
|
-
}, [queryClient]);
|
|
77
|
+
}, [queryClient, updateMutations]);
|
|
28
78
|
return {
|
|
29
79
|
mutations
|
|
30
80
|
};
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useState, useRef } from "react";
|
|
4
4
|
import { onlineManager } from "@tanstack/react-query";
|
|
5
|
-
import { devToolsStorageKeys,
|
|
5
|
+
import { devToolsStorageKeys, persistentStorage } from "@buoy-gg/shared-ui";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Synchronizes a local Wi-Fi toggle with React Query
|
|
8
|
+
* Synchronizes a local Wi-Fi toggle with React Query's `onlineManager`, persisting the selection
|
|
9
9
|
* so developers can simulate offline mode across reloads.
|
|
10
10
|
*/
|
|
11
11
|
export function useWifiState() {
|
|
@@ -17,7 +17,7 @@ export function useWifiState() {
|
|
|
17
17
|
if (hasLoadedPersistedState.current) return;
|
|
18
18
|
const loadPersistedState = async () => {
|
|
19
19
|
try {
|
|
20
|
-
const savedState = await
|
|
20
|
+
const savedState = await persistentStorage.getItem(devToolsStorageKeys.settings.wifiEnabled());
|
|
21
21
|
if (savedState !== null) {
|
|
22
22
|
const isEnabled = savedState === "true";
|
|
23
23
|
setIsOnline(isEnabled);
|
|
@@ -34,7 +34,7 @@ export function useWifiState() {
|
|
|
34
34
|
// Save WiFi state when it changes
|
|
35
35
|
const saveWifiState = async enabled => {
|
|
36
36
|
try {
|
|
37
|
-
await
|
|
37
|
+
await persistentStorage.setItem(devToolsStorageKeys.settings.wifiEnabled(), enabled.toString());
|
|
38
38
|
} catch (error) {
|
|
39
39
|
// Failed to save WiFi state
|
|
40
40
|
}
|