@buoy-gg/storage 7.0.33 → 7.0.35
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/preset.js +8 -22
- package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +10 -10
- package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +4 -3
- package/lib/commonjs/storage/components/GameUIStorageBrowser.js +5 -5
- package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -1
- package/lib/commonjs/storage/components/MMKVInstanceSelector.js +2 -2
- package/lib/commonjs/storage/components/SelectionActionBar.js +1 -1
- package/lib/commonjs/storage/components/StorageActionButtons.js +1 -1
- package/lib/commonjs/storage/components/StorageEventActionButton.js +1 -1
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +2 -2
- package/lib/commonjs/storage/components/StorageFilterCards.js +1 -1
- package/lib/commonjs/storage/components/StorageKeyCard.js +4 -4
- package/lib/commonjs/storage/components/StorageKeyDetailScreen.js +8 -8
- package/lib/commonjs/storage/components/StorageKeyEditorScreen.js +3 -3
- package/lib/commonjs/storage/components/StorageKeyRow.js +6 -6
- package/lib/commonjs/storage/components/StorageModalWithTabs.js +45 -147
- package/lib/commonjs/storage/components/StorageTypeFilterBar.js +1 -1
- package/lib/commonjs/storage/hooks/useStorageEvents.js +15 -52
- package/lib/commonjs/storage/utils/snapshotProvider.js +37 -100
- package/lib/module/preset.js +7 -20
- package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +11 -11
- package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +4 -3
- package/lib/module/storage/components/GameUIStorageBrowser.js +6 -6
- package/lib/module/storage/components/MMKVInstanceInfoPanel.js +2 -2
- package/lib/module/storage/components/MMKVInstanceSelector.js +3 -3
- package/lib/module/storage/components/SelectionActionBar.js +2 -2
- package/lib/module/storage/components/StorageActionButtons.js +2 -2
- package/lib/module/storage/components/StorageEventActionButton.js +2 -2
- package/lib/module/storage/components/StorageEventDetailContent.js +3 -3
- package/lib/module/storage/components/StorageFilterCards.js +2 -2
- package/lib/module/storage/components/StorageKeyCard.js +5 -5
- package/lib/module/storage/components/StorageKeyDetailScreen.js +9 -9
- package/lib/module/storage/components/StorageKeyEditorScreen.js +4 -4
- package/lib/module/storage/components/StorageKeyRow.js +7 -7
- package/lib/module/storage/components/StorageModalWithTabs.js +46 -148
- package/lib/module/storage/components/StorageTypeFilterBar.js +2 -2
- package/lib/module/storage/hooks/useStorageEvents.js +16 -53
- package/lib/module/storage/utils/snapshotProvider.js +38 -101
- package/lib/typescript/preset.d.ts +2 -8
- package/lib/typescript/preset.d.ts.map +1 -1
- package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +1 -1
- package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageKeyDetailScreen.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -1
- package/lib/typescript/storage/hooks/useStorageEvents.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useState, useCallback, useEffect, useRef, useMemo } from "react";
|
|
4
4
|
import { View, TouchableOpacity, StyleSheet, FlatList, Alert } from "react-native";
|
|
5
5
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
6
|
-
import { JsModal, ModalHeader, TabSelector, parseValue, devToolsStorageKeys, macOSColors, night, ToolEmptyState, Filter, RefreshCw, Search, SearchBar, PowerToggleButton, ToolbarCopyButton, ToolbarClearButton, truncatePayload, TickProvider, useLimit, TIER_LIMITS, windowDragProps } from "@buoy-gg/shared-ui";
|
|
6
|
+
import { JsModal, ModalHeader, TabSelector, parseValue, devToolsStorageKeys, macOSColors, night, ToolEmptyState, Filter, RefreshCw, Search, SearchBar, PowerToggleButton, ToolbarCopyButton, ToolbarClearButton, truncatePayload, TickProvider, useLimit, TIER_LIMITS, windowDragProps, usePersistedState, monoFont } from "@buoy-gg/shared-ui";
|
|
7
7
|
import { StorageBrowserMode } from "./StorageBrowserMode";
|
|
8
8
|
import { StorageTypeFilterBar, countByStorageType } from "./StorageTypeFilterBar";
|
|
9
9
|
import { clearAllAppStorage, clearAllStorageIncludingDevTools } from "../utils/clearAllStorage";
|
|
@@ -24,6 +24,41 @@ import { useIsPro } from "@buoy-gg/license";
|
|
|
24
24
|
*/
|
|
25
25
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
26
26
|
export const FREE_TIER_EVENT_LIMIT = TIER_LIMITS["storage.events"].free;
|
|
27
|
+
/**
|
|
28
|
+
* Persistence recipes. These keys were always written straight to
|
|
29
|
+
* AsyncStorage (not the FileSystem-first persistentStorage), so they keep
|
|
30
|
+
* that backend — a user's saved tab, filters and pins survive the upgrade.
|
|
31
|
+
*/
|
|
32
|
+
const ASYNC_STORAGE_BACKEND = {
|
|
33
|
+
getItem: key => AsyncStorage.getItem(key),
|
|
34
|
+
setItem: (key, value) => AsyncStorage.setItem(key, value)
|
|
35
|
+
};
|
|
36
|
+
const TAB_PERSISTENCE = {
|
|
37
|
+
storage: ASYNC_STORAGE_BACKEND,
|
|
38
|
+
// Stored as the bare tab name, not JSON.
|
|
39
|
+
parse: raw => raw === "browser" || raw === "events" ? raw : undefined,
|
|
40
|
+
serialize: tab => tab
|
|
41
|
+
};
|
|
42
|
+
const BOOLEAN_PERSISTENCE = {
|
|
43
|
+
storage: ASYNC_STORAGE_BACKEND,
|
|
44
|
+
// Stored as "true" / "false".
|
|
45
|
+
parse: raw => raw === "true",
|
|
46
|
+
serialize: value => value.toString()
|
|
47
|
+
};
|
|
48
|
+
const STRING_SET_PERSISTENCE = {
|
|
49
|
+
storage: ASYNC_STORAGE_BACKEND,
|
|
50
|
+
parse: raw => new Set(JSON.parse(raw)),
|
|
51
|
+
serialize: set => JSON.stringify(Array.from(set))
|
|
52
|
+
};
|
|
53
|
+
const IGNORED_PATTERNS_PERSISTENCE = {
|
|
54
|
+
...STRING_SET_PERSISTENCE,
|
|
55
|
+
parse: raw => {
|
|
56
|
+
const filters = JSON.parse(raw);
|
|
57
|
+
// Always ensure @react_buoy is included to hide dev tool keys
|
|
58
|
+
if (!filters.includes("@react_buoy")) filters.push("@react_buoy");
|
|
59
|
+
return new Set(filters);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
27
62
|
export function StorageModalWithTabs({
|
|
28
63
|
visible,
|
|
29
64
|
onClose,
|
|
@@ -38,7 +73,7 @@ export function StorageModalWithTabs({
|
|
|
38
73
|
}) {
|
|
39
74
|
const isPro = useIsPro();
|
|
40
75
|
const eventLimit = useLimit("storage.events");
|
|
41
|
-
const [activeTab, setActiveTab] =
|
|
76
|
+
const [activeTab, setActiveTab] = usePersistedState(devToolsStorageKeys.storage.activeTab(), "browser", TAB_PERSISTENCE);
|
|
42
77
|
useEffect(() => {
|
|
43
78
|
onTabChange?.(activeTab);
|
|
44
79
|
}, [activeTab, onTabChange]);
|
|
@@ -54,7 +89,7 @@ export function StorageModalWithTabs({
|
|
|
54
89
|
const [isSearchActive, setIsSearchActive] = useState(false);
|
|
55
90
|
|
|
56
91
|
// Local state to control subscription (true = subscribed, false = unsubscribed)
|
|
57
|
-
const [isListeningEnabled, setIsListeningEnabled] =
|
|
92
|
+
const [isListeningEnabled, setIsListeningEnabled] = usePersistedState(devToolsStorageKeys.storage.isMonitoring(), true, BOOLEAN_PERSISTENCE);
|
|
58
93
|
|
|
59
94
|
// Event Listener state - using centralized store via hook
|
|
60
95
|
// Pass enabled option to control subscription - this allows events tool to
|
|
@@ -71,8 +106,9 @@ export function StorageModalWithTabs({
|
|
|
71
106
|
const [selectedHistoryEventIndex, setSelectedHistoryEventIndex] = useState(null);
|
|
72
107
|
const [selectedEventIndex, setSelectedEventIndex] = useState(0);
|
|
73
108
|
const [showFilters, setShowFilters] = useState(false);
|
|
74
|
-
const [ignoredPatterns, setIgnoredPatterns] =
|
|
75
|
-
|
|
109
|
+
const [ignoredPatterns, setIgnoredPatterns] = usePersistedState(devToolsStorageKeys.storage.eventFilters(),
|
|
110
|
+
// Auto-hide dev tool keys by default
|
|
111
|
+
new Set(["@react_buoy", "@RNAsyncStorage", "redux-persist", "persist:"]), IGNORED_PATTERNS_PERSISTENCE);
|
|
76
112
|
/**
|
|
77
113
|
* Which backend both tabs are looking at.
|
|
78
114
|
*
|
|
@@ -88,12 +124,8 @@ export function StorageModalWithTabs({
|
|
|
88
124
|
const [storageTypeFilter, setStorageTypeFilter] = useState("all");
|
|
89
125
|
const [enabledStorageTypes, setEnabledStorageTypes] = useState(new Set(['async', 'mmkv', 'secure']) // All enabled by default
|
|
90
126
|
);
|
|
91
|
-
const [pinnedKeys, setPinnedKeys] =
|
|
127
|
+
const [pinnedKeys, setPinnedKeys] = usePersistedState(devToolsStorageKeys.storage.pinnedKeys(), new Set(), STRING_SET_PERSISTENCE);
|
|
92
128
|
const lastEventRef = useRef(null);
|
|
93
|
-
const hasLoadedFilters = useRef(false);
|
|
94
|
-
const hasLoadedPins = useRef(false);
|
|
95
|
-
const hasLoadedTabState = useRef(false);
|
|
96
|
-
const hasLoadedMonitoringState = useRef(false);
|
|
97
129
|
|
|
98
130
|
// isListening = enabled and capturing (has subscribers)
|
|
99
131
|
const isListening = isListeningEnabled && isCapturing;
|
|
@@ -108,140 +140,6 @@ export function StorageModalWithTabs({
|
|
|
108
140
|
|
|
109
141
|
// Timer removed - using useTickEveryMinute hook instead
|
|
110
142
|
|
|
111
|
-
// Load persisted tab state on mount
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
if (!visible || hasLoadedTabState.current) return;
|
|
114
|
-
const loadTabState = async () => {
|
|
115
|
-
try {
|
|
116
|
-
const storedTab = await AsyncStorage.getItem(devToolsStorageKeys.storage.activeTab());
|
|
117
|
-
if (storedTab && (storedTab === "browser" || storedTab === "events")) {
|
|
118
|
-
setActiveTab(storedTab);
|
|
119
|
-
}
|
|
120
|
-
hasLoadedTabState.current = true;
|
|
121
|
-
} catch (error) {
|
|
122
|
-
// Failed to load tab state
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
loadTabState();
|
|
126
|
-
}, [visible]);
|
|
127
|
-
|
|
128
|
-
// Load persisted monitoring state on mount
|
|
129
|
-
useEffect(() => {
|
|
130
|
-
if (!visible || hasLoadedMonitoringState.current) return;
|
|
131
|
-
const loadMonitoringState = async () => {
|
|
132
|
-
try {
|
|
133
|
-
const storedMonitoring = await AsyncStorage.getItem(devToolsStorageKeys.storage.isMonitoring());
|
|
134
|
-
if (storedMonitoring !== null) {
|
|
135
|
-
const shouldMonitor = storedMonitoring === "true";
|
|
136
|
-
setIsListeningEnabled(shouldMonitor);
|
|
137
|
-
}
|
|
138
|
-
hasLoadedMonitoringState.current = true;
|
|
139
|
-
} catch (error) {
|
|
140
|
-
// Failed to load monitoring state
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
loadMonitoringState();
|
|
144
|
-
}, [visible]);
|
|
145
|
-
|
|
146
|
-
// Note: Conversations will appear when storage events are triggered
|
|
147
|
-
// Click on any conversation to see the unified view with toggle cards
|
|
148
|
-
|
|
149
|
-
// Save tab state when it changes
|
|
150
|
-
useEffect(() => {
|
|
151
|
-
if (!hasLoadedTabState.current) return; // Don't save on initial load
|
|
152
|
-
|
|
153
|
-
const saveTabState = async () => {
|
|
154
|
-
try {
|
|
155
|
-
await AsyncStorage.setItem(devToolsStorageKeys.storage.activeTab(), activeTab);
|
|
156
|
-
} catch (error) {
|
|
157
|
-
// Failed to save tab state
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
saveTabState();
|
|
161
|
-
}, [activeTab]);
|
|
162
|
-
|
|
163
|
-
// Save monitoring state when it changes
|
|
164
|
-
useEffect(() => {
|
|
165
|
-
if (!hasLoadedMonitoringState.current) return; // Don't save on initial load
|
|
166
|
-
|
|
167
|
-
const saveMonitoringState = async () => {
|
|
168
|
-
try {
|
|
169
|
-
await AsyncStorage.setItem(devToolsStorageKeys.storage.isMonitoring(), isListening.toString());
|
|
170
|
-
} catch (error) {
|
|
171
|
-
// Failed to save monitoring state
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
saveMonitoringState();
|
|
175
|
-
}, [isListening]);
|
|
176
|
-
|
|
177
|
-
// Load persisted filters on mount
|
|
178
|
-
useEffect(() => {
|
|
179
|
-
if (!visible || hasLoadedFilters.current) return;
|
|
180
|
-
const loadFilters = async () => {
|
|
181
|
-
try {
|
|
182
|
-
const storedFilters = await AsyncStorage.getItem(devToolsStorageKeys.storage.eventFilters());
|
|
183
|
-
if (storedFilters) {
|
|
184
|
-
const filters = JSON.parse(storedFilters);
|
|
185
|
-
// Always ensure @react_buoy is included to hide dev tool keys
|
|
186
|
-
if (!filters.includes("@react_buoy")) {
|
|
187
|
-
filters.push("@react_buoy");
|
|
188
|
-
}
|
|
189
|
-
setIgnoredPatterns(new Set(filters));
|
|
190
|
-
}
|
|
191
|
-
hasLoadedFilters.current = true;
|
|
192
|
-
} catch (error) {
|
|
193
|
-
// Failed to load filters
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
loadFilters();
|
|
197
|
-
}, [visible]);
|
|
198
|
-
|
|
199
|
-
// Save filters when they change
|
|
200
|
-
useEffect(() => {
|
|
201
|
-
if (!hasLoadedFilters.current) return; // Don't save on initial load
|
|
202
|
-
|
|
203
|
-
const saveFilters = async () => {
|
|
204
|
-
try {
|
|
205
|
-
const filters = Array.from(ignoredPatterns);
|
|
206
|
-
await AsyncStorage.setItem(devToolsStorageKeys.storage.eventFilters(), JSON.stringify(filters));
|
|
207
|
-
} catch (error) {
|
|
208
|
-
// Failed to save filters
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
saveFilters();
|
|
212
|
-
}, [ignoredPatterns]);
|
|
213
|
-
|
|
214
|
-
// Load persisted pinned keys on mount
|
|
215
|
-
useEffect(() => {
|
|
216
|
-
if (!visible || hasLoadedPins.current) return;
|
|
217
|
-
const loadPins = async () => {
|
|
218
|
-
try {
|
|
219
|
-
const stored = await AsyncStorage.getItem(devToolsStorageKeys.storage.pinnedKeys());
|
|
220
|
-
if (stored) {
|
|
221
|
-
setPinnedKeys(new Set(JSON.parse(stored)));
|
|
222
|
-
}
|
|
223
|
-
hasLoadedPins.current = true;
|
|
224
|
-
} catch (error) {
|
|
225
|
-
// Failed to load pinned keys
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
loadPins();
|
|
229
|
-
}, [visible]);
|
|
230
|
-
|
|
231
|
-
// Save pinned keys when they change
|
|
232
|
-
useEffect(() => {
|
|
233
|
-
if (!hasLoadedPins.current) return; // Don't save on initial load
|
|
234
|
-
|
|
235
|
-
const savePins = async () => {
|
|
236
|
-
try {
|
|
237
|
-
await AsyncStorage.setItem(devToolsStorageKeys.storage.pinnedKeys(), JSON.stringify(Array.from(pinnedKeys)));
|
|
238
|
-
} catch (error) {
|
|
239
|
-
// Failed to save pinned keys
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
savePins();
|
|
243
|
-
}, [pinnedKeys]);
|
|
244
|
-
|
|
245
143
|
// Event listener setup - now handled by useStorageEvents hook
|
|
246
144
|
// The hook subscribes to the centralized storageEventStore
|
|
247
145
|
|
|
@@ -988,7 +886,7 @@ const styles = StyleSheet.create({
|
|
|
988
886
|
fontWeight: "600",
|
|
989
887
|
marginTop: 16,
|
|
990
888
|
marginBottom: 8,
|
|
991
|
-
fontFamily:
|
|
889
|
+
fontFamily: monoFont,
|
|
992
890
|
letterSpacing: 0.5,
|
|
993
891
|
textTransform: "uppercase"
|
|
994
892
|
},
|
|
@@ -996,7 +894,7 @@ const styles = StyleSheet.create({
|
|
|
996
894
|
color: night.color.textSecondary,
|
|
997
895
|
fontSize: 14,
|
|
998
896
|
textAlign: "center",
|
|
999
|
-
fontFamily:
|
|
897
|
+
fontFamily: monoFont
|
|
1000
898
|
},
|
|
1001
899
|
eventNavigation: {
|
|
1002
900
|
flexDirection: "row",
|
|
@@ -1015,7 +913,7 @@ const styles = StyleSheet.create({
|
|
|
1015
913
|
color: night.color.text,
|
|
1016
914
|
fontSize: 12,
|
|
1017
915
|
fontWeight: "600",
|
|
1018
|
-
fontFamily:
|
|
916
|
+
fontFamily: monoFont,
|
|
1019
917
|
paddingHorizontal: 8
|
|
1020
918
|
},
|
|
1021
919
|
headerTopRow: {
|
|
@@ -1042,7 +940,7 @@ const styles = StyleSheet.create({
|
|
|
1042
940
|
fontSize: 13,
|
|
1043
941
|
fontWeight: "600",
|
|
1044
942
|
color: night.color.accent,
|
|
1045
|
-
fontFamily:
|
|
943
|
+
fontFamily: monoFont,
|
|
1046
944
|
letterSpacing: 0.5
|
|
1047
945
|
},
|
|
1048
946
|
contentWrapper: {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
20
|
-
import { macOSColors, night } from "@buoy-gg/shared-ui";
|
|
20
|
+
import { macOSColors, night, monoFont } from "@buoy-gg/shared-ui";
|
|
21
21
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
22
22
|
/**
|
|
23
23
|
* One entry per pill. This was four near-identical blocks of JSX differing only
|
|
@@ -132,7 +132,7 @@ const styles = StyleSheet.create({
|
|
|
132
132
|
value: {
|
|
133
133
|
fontSize: 12,
|
|
134
134
|
fontWeight: "600",
|
|
135
|
-
fontFamily:
|
|
135
|
+
fontFamily: monoFont,
|
|
136
136
|
lineHeight: 14
|
|
137
137
|
}
|
|
138
138
|
});
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import { useMemo } from "react";
|
|
29
|
+
import { useEventStoreEvents } from "@buoy-gg/shared-ui";
|
|
29
30
|
import { storageEventStore } from "../stores/storageEventStore";
|
|
30
31
|
|
|
31
32
|
// Re-export StorageEvent for convenience
|
|
@@ -36,60 +37,22 @@ export function useStorageEvents(options = {}) {
|
|
|
36
37
|
maxEvents = 500,
|
|
37
38
|
enabled = true
|
|
38
39
|
} = options;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Frame-coalesced (same pattern as network's useNetworkEventList):
|
|
53
|
-
// bursts of storage writes land as ONE commit per frame instead of
|
|
54
|
-
// one per emission — the dominant live-churn cost measured on the
|
|
55
|
-
// network tool (tool-bench 2026-07-06).
|
|
56
|
-
let rafId = null;
|
|
57
|
-
let pending = null;
|
|
58
|
-
const unsubscribe = storageEventStore.subscribeToEvents(allEvents => {
|
|
59
|
-
pending = allEvents;
|
|
60
|
-
if (rafId != null) return;
|
|
61
|
-
rafId = requestAnimationFrame(() => {
|
|
62
|
-
rafId = null;
|
|
63
|
-
if (!pending) return;
|
|
64
|
-
// Filter by storage type if specified
|
|
65
|
-
let filtered = pending;
|
|
66
|
-
pending = null;
|
|
67
|
-
if (storageType !== "all") {
|
|
68
|
-
filtered = filtered.filter(e => e.storageType === storageType);
|
|
69
|
-
}
|
|
70
|
-
// Limit events
|
|
71
|
-
if (filtered.length > maxEvents) {
|
|
72
|
-
filtered = filtered.slice(0, maxEvents);
|
|
73
|
-
}
|
|
74
|
-
setEvents(filtered);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Mark as capturing after successful subscription
|
|
79
|
-
setIsCapturing(true);
|
|
80
|
-
return () => {
|
|
81
|
-
unsubscribe();
|
|
82
|
-
if (rafId != null) cancelAnimationFrame(rafId);
|
|
83
|
-
// Note: Don't set isCapturing=false here because we might be
|
|
84
|
-
// re-subscribing due to dependency change, not actually stopping
|
|
85
|
-
};
|
|
86
|
-
}, [storageType, maxEvents, enabled]);
|
|
87
|
-
const clearEvents = useCallback(() => {
|
|
88
|
-
storageEventStore.clearEvents();
|
|
89
|
-
}, []);
|
|
40
|
+
// Stable per storageType so the shared hook doesn't resubscribe every render.
|
|
41
|
+
const select = useMemo(() => storageType === "all" ? undefined : events => events.filter(e => e.storageType === storageType), [storageType]);
|
|
42
|
+
// Subscribing auto-starts the storage listener (Subscribable pattern), and
|
|
43
|
+
// the shared hook frame-coalesces write bursts into one commit.
|
|
44
|
+
const {
|
|
45
|
+
events,
|
|
46
|
+
clearEvents,
|
|
47
|
+
isActive
|
|
48
|
+
} = useEventStoreEvents(storageEventStore, {
|
|
49
|
+
maxEvents,
|
|
50
|
+
enabled,
|
|
51
|
+
select
|
|
52
|
+
});
|
|
90
53
|
return {
|
|
91
54
|
events,
|
|
92
55
|
clearEvents,
|
|
93
|
-
isCapturing
|
|
56
|
+
isCapturing: isActive
|
|
94
57
|
};
|
|
95
58
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* - SecureStore keys outside the registered descriptor list are invisible.
|
|
19
19
|
*/
|
|
20
20
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
21
|
-
import { isDevToolsStorageKey, registerStateSnapshotProvider } from "@buoy-gg/shared-ui";
|
|
21
|
+
import { classifyPreviewItem, createRestoreScope, emptyRestoreResult, failedRestore, isDevToolsStorageKey, registerStateSnapshotProvider, unionKeys, wontApply } from "@buoy-gg/shared-ui";
|
|
22
22
|
import { readMany, writeMany, removeMany } from "./asyncStorageCompat";
|
|
23
23
|
import { clearAllAppStorage } from "./clearAllStorage";
|
|
24
24
|
import { mmkvInstanceRegistry } from "./MMKVInstanceRegistry";
|
|
@@ -106,24 +106,12 @@ async function capture() {
|
|
|
106
106
|
}
|
|
107
107
|
async function restore(data, options) {
|
|
108
108
|
const snapshot = data;
|
|
109
|
-
const
|
|
110
|
-
const includedSet = options?.includeKeys ? new Set(options.includeKeys) : null;
|
|
109
|
+
const scope = createRestoreScope(options);
|
|
111
110
|
/** True when this item may be touched (scope + exclusions agree). */
|
|
112
|
-
const touch =
|
|
113
|
-
|
|
114
|
-
const result = {
|
|
115
|
-
ok: true,
|
|
116
|
-
applied: 0,
|
|
117
|
-
skipped: [],
|
|
118
|
-
warnings: []
|
|
119
|
-
};
|
|
111
|
+
const touch = scope.touch;
|
|
112
|
+
const result = emptyRestoreResult();
|
|
120
113
|
if (!snapshot) {
|
|
121
|
-
return
|
|
122
|
-
ok: false,
|
|
123
|
-
applied: 0,
|
|
124
|
-
skipped: [],
|
|
125
|
-
warnings: ["empty storage snapshot"]
|
|
126
|
-
};
|
|
114
|
+
return failedRestore("empty storage snapshot");
|
|
127
115
|
}
|
|
128
116
|
|
|
129
117
|
// ── AsyncStorage: delete app keys missing from the snapshot, write the rest ──
|
|
@@ -132,7 +120,7 @@ async function restore(data, options) {
|
|
|
132
120
|
const snapKeys = new Set(snapPairs.map(([k]) => k));
|
|
133
121
|
const liveKeys = (await AsyncStorage.getAllKeys()).filter(k => !isDevToolsStorageKey(k));
|
|
134
122
|
const toRemove = liveKeys.filter(k => !snapKeys.has(k) && touch(`async:${k}`));
|
|
135
|
-
|
|
123
|
+
scope.countExcluded((snapshot.async ?? []).length - snapPairs.length);
|
|
136
124
|
if (toRemove.length > 0) await removeMany(toRemove);
|
|
137
125
|
if (snapPairs.length > 0) await writeMany(snapPairs);
|
|
138
126
|
result.applied += snapPairs.length + toRemove.length;
|
|
@@ -165,10 +153,7 @@ async function restore(data, options) {
|
|
|
165
153
|
const snapKeys = new Set(entries.map(e => e.key));
|
|
166
154
|
const liveKeys = instance.getAllKeys().filter(key => !isDevToolsStorageKey(key));
|
|
167
155
|
for (const key of liveKeys) {
|
|
168
|
-
if (!
|
|
169
|
-
excludedHits += 1;
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
156
|
+
if (!scope.allows(`mmkv:${id}/${key}`)) continue;
|
|
172
157
|
if (!snapKeys.has(key)) {
|
|
173
158
|
deleteMMKVKey(instance, key);
|
|
174
159
|
result.applied += 1;
|
|
@@ -199,10 +184,7 @@ async function restore(data, options) {
|
|
|
199
184
|
key,
|
|
200
185
|
options
|
|
201
186
|
} of secureStoreRegistry.getAll()) {
|
|
202
|
-
if (!
|
|
203
|
-
excludedHits += 1;
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
187
|
+
if (!scope.allows(`secure:${key}`)) continue;
|
|
206
188
|
if (options.requireAuthentication) {
|
|
207
189
|
if (key in secureSnap) {
|
|
208
190
|
result.skipped.push({
|
|
@@ -235,20 +217,14 @@ async function restore(data, options) {
|
|
|
235
217
|
});
|
|
236
218
|
}
|
|
237
219
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
220
|
+
const excludedWarning = scope.excludedWarning("item(s)");
|
|
221
|
+
if (excludedWarning) result.warnings.push(excludedWarning);
|
|
241
222
|
return result;
|
|
242
223
|
}
|
|
243
224
|
|
|
244
225
|
/** Wipe to fresh-install state (Buoy keys preserved). Used by baseline restore. */
|
|
245
226
|
async function clear() {
|
|
246
|
-
const result =
|
|
247
|
-
ok: true,
|
|
248
|
-
applied: 0,
|
|
249
|
-
skipped: [],
|
|
250
|
-
warnings: []
|
|
251
|
-
};
|
|
227
|
+
const result = emptyRestoreResult();
|
|
252
228
|
try {
|
|
253
229
|
await clearAllAppStorage();
|
|
254
230
|
result.applied += 1;
|
|
@@ -299,40 +275,24 @@ async function clear() {
|
|
|
299
275
|
return result;
|
|
300
276
|
}
|
|
301
277
|
const ITEM_RENDER_CHAR_LIMIT = 256 * 1024;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Storage values are strings (or MMKV primitives): identity equality and a
|
|
281
|
+
* character-length size gate are the right tests, not a deep walk.
|
|
282
|
+
*/
|
|
302
283
|
function classifyValue(key, label, oldValue, newValue, inOld, inNew) {
|
|
303
|
-
|
|
284
|
+
return classifyPreviewItem({
|
|
304
285
|
key,
|
|
305
286
|
label,
|
|
306
|
-
verdict: "removed",
|
|
307
|
-
oldValue
|
|
308
|
-
};
|
|
309
|
-
if (!inOld) return {
|
|
310
|
-
key,
|
|
311
|
-
label,
|
|
312
|
-
verdict: "added",
|
|
313
|
-
newValue
|
|
314
|
-
};
|
|
315
|
-
if (Object.is(oldValue, newValue)) return {
|
|
316
|
-
key,
|
|
317
|
-
label,
|
|
318
|
-
verdict: "unchanged"
|
|
319
|
-
};
|
|
320
|
-
const tooLarge = typeof oldValue === "string" && oldValue.length > ITEM_RENDER_CHAR_LIMIT || typeof newValue === "string" && newValue.length > ITEM_RENDER_CHAR_LIMIT;
|
|
321
|
-
if (tooLarge) {
|
|
322
|
-
return {
|
|
323
|
-
key,
|
|
324
|
-
label,
|
|
325
|
-
verdict: "too-large",
|
|
326
|
-
reason: "value too large to render a diff — restore still applies it"
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
return {
|
|
330
|
-
key,
|
|
331
|
-
label,
|
|
332
|
-
verdict: "changed",
|
|
333
287
|
oldValue,
|
|
334
|
-
newValue
|
|
335
|
-
|
|
288
|
+
newValue,
|
|
289
|
+
inOld,
|
|
290
|
+
inNew
|
|
291
|
+
}, {
|
|
292
|
+
equal: Object.is,
|
|
293
|
+
tooLarge: value => typeof value === "string" && value.length > ITEM_RENDER_CHAR_LIMIT,
|
|
294
|
+
tooLargeReason: "value too large to render a diff — restore still applies it"
|
|
295
|
+
});
|
|
336
296
|
}
|
|
337
297
|
|
|
338
298
|
/** Per-key restore preview across all three backends. */
|
|
@@ -354,46 +314,31 @@ async function previewItems(target, base) {
|
|
|
354
314
|
// ── AsyncStorage ──
|
|
355
315
|
const oldAsync = new Map(baseData.async ?? []);
|
|
356
316
|
const newAsync = new Map(targetData.async ?? []);
|
|
357
|
-
for (const key of
|
|
317
|
+
for (const key of unionKeys(oldAsync, newAsync)) {
|
|
358
318
|
if (isDevToolsStorageKey(key)) continue;
|
|
359
319
|
items.push(classifyValue(`async:${key}`, key, oldAsync.get(key), newAsync.get(key), oldAsync.has(key), newAsync.has(key)));
|
|
360
320
|
}
|
|
361
321
|
|
|
362
322
|
// ── MMKV ──
|
|
363
|
-
const
|
|
364
|
-
for (const id of instanceIds) {
|
|
323
|
+
for (const id of unionKeys(baseData.mmkv, targetData.mmkv)) {
|
|
365
324
|
const registered = liveMode ? mmkvInstanceRegistry.get(id) : null;
|
|
366
325
|
const instanceUnavailable = liveMode && !registered;
|
|
367
326
|
const readOnly = liveMode && registered?.instance.isReadOnly === true;
|
|
368
327
|
const oldEntries = new Map((baseData.mmkv?.[id] ?? []).map(e => [e.key, e]));
|
|
369
328
|
const newEntries = new Map((targetData.mmkv?.[id] ?? []).map(e => [e.key, e]));
|
|
370
|
-
for (const key of
|
|
329
|
+
for (const key of unionKeys(oldEntries, newEntries)) {
|
|
371
330
|
if (isDevToolsStorageKey(key)) continue;
|
|
372
331
|
const itemKey = `mmkv:${id}/${key}`;
|
|
373
332
|
const label = `${id} · ${key}`;
|
|
374
333
|
const oldE = oldEntries.get(key);
|
|
375
334
|
const newE = newEntries.get(key);
|
|
376
335
|
let item = classifyValue(itemKey, label, oldE?.value, newE?.value, oldEntries.has(key), newEntries.has(key));
|
|
377
|
-
if (
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
};
|
|
384
|
-
} else if (readOnly) {
|
|
385
|
-
item = {
|
|
386
|
-
...item,
|
|
387
|
-
verdict: "wont-apply",
|
|
388
|
-
reason: "MMKV instance registered read-only"
|
|
389
|
-
};
|
|
390
|
-
} else if (newE?.valueType === "buffer" || oldE?.valueType === "buffer") {
|
|
391
|
-
item = {
|
|
392
|
-
...item,
|
|
393
|
-
verdict: "wont-apply",
|
|
394
|
-
reason: "ArrayBuffer values cannot be restored"
|
|
395
|
-
};
|
|
396
|
-
}
|
|
336
|
+
if (instanceUnavailable) {
|
|
337
|
+
item = wontApply(item, "MMKV instance not registered");
|
|
338
|
+
} else if (readOnly) {
|
|
339
|
+
item = wontApply(item, "MMKV instance registered read-only");
|
|
340
|
+
} else if (newE?.valueType === "buffer" || oldE?.valueType === "buffer") {
|
|
341
|
+
item = wontApply(item, "ArrayBuffer values cannot be restored");
|
|
397
342
|
}
|
|
398
343
|
items.push(item);
|
|
399
344
|
}
|
|
@@ -403,22 +348,14 @@ async function previewItems(target, base) {
|
|
|
403
348
|
const oldSecure = baseData.secure ?? {};
|
|
404
349
|
const newSecure = targetData.secure ?? {};
|
|
405
350
|
const registeredSecure = liveMode ? new Map(secureStoreRegistry.getAll().map(e => [e.key, e])) : null;
|
|
406
|
-
for (const key of
|
|
351
|
+
for (const key of unionKeys(oldSecure, newSecure)) {
|
|
407
352
|
let item = classifyValue(`secure:${key}`, key, oldSecure[key], newSecure[key], key in oldSecure, key in newSecure);
|
|
408
|
-
if (liveMode
|
|
353
|
+
if (liveMode) {
|
|
409
354
|
const entry = registeredSecure?.get(key);
|
|
410
355
|
if (!entry) {
|
|
411
|
-
item =
|
|
412
|
-
...item,
|
|
413
|
-
verdict: "wont-apply",
|
|
414
|
-
reason: "key no longer registered with registerSecureStoreKeys"
|
|
415
|
-
};
|
|
356
|
+
item = wontApply(item, "key no longer registered with registerSecureStoreKeys");
|
|
416
357
|
} else if (entry.options.requireAuthentication) {
|
|
417
|
-
item =
|
|
418
|
-
...item,
|
|
419
|
-
verdict: "wont-apply",
|
|
420
|
-
reason: "biometric-protected keys are never written"
|
|
421
|
-
};
|
|
358
|
+
item = wontApply(item, "biometric-protected keys are never written");
|
|
422
359
|
}
|
|
423
360
|
}
|
|
424
361
|
items.push(item);
|
|
@@ -62,18 +62,12 @@ export declare const storageToolPreset: {
|
|
|
62
62
|
* });
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
|
-
export declare
|
|
66
|
-
/** Tool name (default: "STORAGE") */
|
|
67
|
-
name?: string;
|
|
68
|
-
/** Tool description */
|
|
69
|
-
description?: string;
|
|
70
|
-
/** Custom tool ID (default: "storage") */
|
|
71
|
-
id?: string;
|
|
65
|
+
export declare const createStorageTool: (options?: ({
|
|
72
66
|
/** Array of required storage keys to validate */
|
|
73
67
|
requiredStorageKeys?: RequiredStorageKey[];
|
|
74
68
|
/** Enable shared modal dimensions */
|
|
75
69
|
enableSharedModalDimensions?: boolean;
|
|
76
|
-
})
|
|
70
|
+
} & import("@buoy-gg/shared-ui").ToolPresetOverrides) | undefined) => {
|
|
77
71
|
id: string;
|
|
78
72
|
name: string;
|
|
79
73
|
description: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB;;;;;qBAKX;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;;6BAGJ,kBAAkB,EAAE;;;CAGjD,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,iBAAiB;IAG1B,iDAAiD;0BAC3B,kBAAkB,EAAE;IAC1C,qCAAqC;kCACP,OAAO;;;;;;qBAtCtB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;;6BAGJ,kBAAkB,EAAE;;;CAwClD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiffOptionsPanel.d.ts","sourceRoot":"","sources":["../../../../../src/storage/components/DiffViewer/DiffOptionsPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DiffOptionsPanel.d.ts","sourceRoot":"","sources":["../../../../../src/storage/components/DiffViewer/DiffOptionsPanel.tsx"],"names":[],"mappings":"AAUA,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,cAAc,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,iBAAiB,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,eAAe,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AA+BD,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,eAAe,EACf,UAAU,EACV,gBAAgB,GACjB,EAAE,qBAAqB,+BAwMvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiffSummary.d.ts","sourceRoot":"","sources":["../../../../../../src/storage/components/DiffViewer/components/DiffSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0B,SAAS,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"DiffSummary.d.ts","sourceRoot":"","sources":["../../../../../../src/storage/components/DiffViewer/components/DiffSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0B,SAAS,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAO,EACP,QAAQ,EACR,KAAK,EACL,KAAK,GACN,EAAE,gBAAgB,sCAiElB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageEventDetailContent.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageEventDetailContent.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"StorageEventDetailContent.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageEventDetailContent.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AA4DlE,KAAK,SAAS,GAAG;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,GAAG,CAAC;QACZ,SAAS,CAAC,EAAE,GAAG,CAAC;QAChB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,KAAK,YAAY,GACb,CAAC,iBAAiB,GAAG;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAC/C,CAAC,SAAS,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3C,UAAU,sBAAsB;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,YAAY,CAAC;IACxB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EACL,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,MAAM,GACN,WAAW,GACX,QAAQ,GACR,OAAO,CAAC;IACZ,YAAY,CAAC,EAAE,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;CACtC;AAED,UAAU,8BAA8B;IACtC,YAAY,EAAE,sBAAsB,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAsDD,wBAAgB,yBAAyB,CAAC,EACxC,YAAY,EACZ,kBAAsB,EACtB,kBAA6B,EAC7B,qBAA6B,GAC9B,EAAE,8BAA8B,+BAuZhC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,YAAY,EACZ,kBAAsB,EACtB,kBAA6B,EAC7B,kBAAyB,GAC1B,EAAE;IACD,YAAY,EAAE,sBAAsB,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,+BAmBA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageKeyCard.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageKeyCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StorageKeyCard.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageKeyCard.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA8B1C,UAAU,mBAAmB;IAC3B,UAAU,EAAE,cAAc,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAiED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,UAAU,EACV,QAAQ,GACT,EAAE,mBAAmB,+BAiMrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageKeyDetailScreen.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageKeyDetailScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;
|
|
1
|
+
{"version":3,"file":"StorageKeyDetailScreen.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageKeyDetailScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAgCH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAwC/C,UAAU,2BAA2B;IACnC,UAAU,EAAE,cAAc,CAAC;IAC3B,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAC;IACnD,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,aAAa,EACb,WAAW,EACX,SAAS,EACT,QAAgB,EAChB,WAAW,EACX,kBAAkB,GACnB,EAAE,2BAA2B,+BAyV7B"}
|