@buoy-gg/storage 1.7.2
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/README.md +607 -0
- package/lib/commonjs/index.js +34 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/preset.js +94 -0
- package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +356 -0
- package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +29 -0
- package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +121 -0
- package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +419 -0
- package/lib/commonjs/storage/components/DiffViewer/themes/diffThemes.js +122 -0
- package/lib/commonjs/storage/components/GameUIStorageBrowser.js +924 -0
- package/lib/commonjs/storage/components/GameUIStorageStats.js +746 -0
- package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +257 -0
- package/lib/commonjs/storage/components/MMKVInstanceSelector.js +418 -0
- package/lib/commonjs/storage/components/SelectionActionBar.js +224 -0
- package/lib/commonjs/storage/components/StorageActionButtons.js +239 -0
- package/lib/commonjs/storage/components/StorageActions.js +192 -0
- package/lib/commonjs/storage/components/StorageBrowserMode.js +31 -0
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +1025 -0
- package/lib/commonjs/storage/components/StorageEventFilterView.js +141 -0
- package/lib/commonjs/storage/components/StorageEventListener.js +357 -0
- package/lib/commonjs/storage/components/StorageEventsSection.js +24 -0
- package/lib/commonjs/storage/components/StorageFilterCards.js +345 -0
- package/lib/commonjs/storage/components/StorageFilterViewV2.js +42 -0
- package/lib/commonjs/storage/components/StorageKeyCard.js +516 -0
- package/lib/commonjs/storage/components/StorageKeyRow.js +356 -0
- package/lib/commonjs/storage/components/StorageKeySection.js +105 -0
- package/lib/commonjs/storage/components/StorageKeyStats.js +344 -0
- package/lib/commonjs/storage/components/StorageModalWithTabs.js +871 -0
- package/lib/commonjs/storage/components/StorageSection.js +43 -0
- package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +126 -0
- package/lib/commonjs/storage/hooks/useMMKVInstances.js +221 -0
- package/lib/commonjs/storage/hooks/useMMKVKeys.js +362 -0
- package/lib/commonjs/storage/hooks/useTickEverySecond.js +21 -0
- package/lib/commonjs/storage/index.js +148 -0
- package/lib/commonjs/storage/types.js +5 -0
- package/lib/commonjs/storage/utils/AsyncStorageListener.js +510 -0
- package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +202 -0
- package/lib/commonjs/storage/utils/MMKVListener.js +380 -0
- package/lib/commonjs/storage/utils/clearAllStorage.js +47 -0
- package/lib/commonjs/storage/utils/index.js +180 -0
- package/lib/commonjs/storage/utils/lineDiff.js +363 -0
- package/lib/commonjs/storage/utils/mmkvAvailability.js +62 -0
- package/lib/commonjs/storage/utils/mmkvTypeDetection.js +139 -0
- package/lib/commonjs/storage/utils/objectDiff.js +157 -0
- package/lib/commonjs/storage/utils/safeAsyncStorage.js +140 -0
- package/lib/commonjs/storage/utils/storageActionHelpers.js +46 -0
- package/lib/commonjs/storage/utils/storageQueryUtils.js +35 -0
- package/lib/commonjs/storage/utils/valueType.js +18 -0
- package/lib/module/index.js +7 -0
- package/lib/module/preset.js +89 -0
- package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +352 -0
- package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +25 -0
- package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +117 -0
- package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +415 -0
- package/lib/module/storage/components/DiffViewer/themes/diffThemes.js +118 -0
- package/lib/module/storage/components/GameUIStorageBrowser.js +922 -0
- package/lib/module/storage/components/GameUIStorageStats.js +742 -0
- package/lib/module/storage/components/MMKVInstanceInfoPanel.js +253 -0
- package/lib/module/storage/components/MMKVInstanceSelector.js +414 -0
- package/lib/module/storage/components/SelectionActionBar.js +221 -0
- package/lib/module/storage/components/StorageActionButtons.js +236 -0
- package/lib/module/storage/components/StorageActions.js +189 -0
- package/lib/module/storage/components/StorageBrowserMode.js +27 -0
- package/lib/module/storage/components/StorageEventDetailContent.js +1020 -0
- package/lib/module/storage/components/StorageEventFilterView.js +137 -0
- package/lib/module/storage/components/StorageEventListener.js +354 -0
- package/lib/module/storage/components/StorageEventsSection.js +20 -0
- package/lib/module/storage/components/StorageFilterCards.js +341 -0
- package/lib/module/storage/components/StorageFilterViewV2.js +38 -0
- package/lib/module/storage/components/StorageKeyCard.js +513 -0
- package/lib/module/storage/components/StorageKeyRow.js +353 -0
- package/lib/module/storage/components/StorageKeySection.js +101 -0
- package/lib/module/storage/components/StorageKeyStats.js +340 -0
- package/lib/module/storage/components/StorageModalWithTabs.js +867 -0
- package/lib/module/storage/components/StorageSection.js +40 -0
- package/lib/module/storage/hooks/useAsyncStorageKeys.js +121 -0
- package/lib/module/storage/hooks/useMMKVInstances.js +216 -0
- package/lib/module/storage/hooks/useMMKVKeys.js +359 -0
- package/lib/module/storage/hooks/useTickEverySecond.js +18 -0
- package/lib/module/storage/index.js +25 -0
- package/lib/module/storage/types.js +3 -0
- package/lib/module/storage/utils/AsyncStorageListener.js +500 -0
- package/lib/module/storage/utils/MMKVInstanceRegistry.js +196 -0
- package/lib/module/storage/utils/MMKVListener.js +367 -0
- package/lib/module/storage/utils/clearAllStorage.js +42 -0
- package/lib/module/storage/utils/index.js +22 -0
- package/lib/module/storage/utils/lineDiff.js +359 -0
- package/lib/module/storage/utils/mmkvAvailability.js +56 -0
- package/lib/module/storage/utils/mmkvTypeDetection.js +133 -0
- package/lib/module/storage/utils/objectDiff.js +153 -0
- package/lib/module/storage/utils/safeAsyncStorage.js +134 -0
- package/lib/module/storage/utils/storageActionHelpers.js +42 -0
- package/lib/module/storage/utils/storageQueryUtils.js +30 -0
- package/lib/module/storage/utils/valueType.js +14 -0
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/preset.d.ts +90 -0
- package/lib/typescript/preset.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts +18 -0
- package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts +7 -0
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts +12 -0
- package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts +13 -0
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts +64 -0
- package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +1 -0
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts +16 -0
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -0
- package/lib/typescript/storage/components/GameUIStorageStats.d.ts +7 -0
- package/lib/typescript/storage/components/GameUIStorageStats.d.ts.map +1 -0
- package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts +42 -0
- package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +1 -0
- package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts +35 -0
- package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +1 -0
- package/lib/typescript/storage/components/SelectionActionBar.d.ts +21 -0
- package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageActionButtons.d.ts +21 -0
- package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageActions.d.ts +10 -0
- package/lib/typescript/storage/components/StorageActions.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts +18 -0
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts +40 -0
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventFilterView.d.ts +11 -0
- package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventListener.d.ts +6 -0
- package/lib/typescript/storage/components/StorageEventListener.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventsSection.d.ts +7 -0
- package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageFilterCards.d.ts +36 -0
- package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageFilterViewV2.d.ts +9 -0
- package/lib/typescript/storage/components/StorageFilterViewV2.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeyCard.d.ts +17 -0
- package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeyRow.d.ts +15 -0
- package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeySection.d.ts +25 -0
- package/lib/typescript/storage/components/StorageKeySection.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeyStats.d.ts +15 -0
- package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts +13 -0
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageSection.d.ts +10 -0
- package/lib/typescript/storage/components/StorageSection.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts +10 -0
- package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useMMKVInstances.d.ts +114 -0
- package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useMMKVKeys.d.ts +94 -0
- package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useTickEverySecond.d.ts +6 -0
- package/lib/typescript/storage/hooks/useTickEverySecond.d.ts.map +1 -0
- package/lib/typescript/storage/index.d.ts +15 -0
- package/lib/typescript/storage/index.d.ts.map +1 -0
- package/lib/typescript/storage/types.d.ts +41 -0
- package/lib/typescript/storage/types.d.ts.map +1 -0
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts +195 -0
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +1 -0
- package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts +224 -0
- package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +1 -0
- package/lib/typescript/storage/utils/MMKVListener.d.ts +218 -0
- package/lib/typescript/storage/utils/MMKVListener.d.ts.map +1 -0
- package/lib/typescript/storage/utils/clearAllStorage.d.ts +11 -0
- package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +1 -0
- package/lib/typescript/storage/utils/index.d.ts +8 -0
- package/lib/typescript/storage/utils/index.d.ts.map +1 -0
- package/lib/typescript/storage/utils/lineDiff.d.ts +34 -0
- package/lib/typescript/storage/utils/lineDiff.d.ts.map +1 -0
- package/lib/typescript/storage/utils/mmkvAvailability.d.ts +23 -0
- package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +1 -0
- package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts +71 -0
- package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +1 -0
- package/lib/typescript/storage/utils/objectDiff.d.ts +35 -0
- package/lib/typescript/storage/utils/objectDiff.d.ts.map +1 -0
- package/lib/typescript/storage/utils/safeAsyncStorage.d.ts +56 -0
- package/lib/typescript/storage/utils/safeAsyncStorage.d.ts.map +1 -0
- package/lib/typescript/storage/utils/storageActionHelpers.d.ts +5 -0
- package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +1 -0
- package/lib/typescript/storage/utils/storageQueryUtils.d.ts +6 -0
- package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +1 -0
- package/lib/typescript/storage/utils/valueType.d.ts +3 -0
- package/lib/typescript/storage/utils/valueType.d.ts.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.FREE_TIER_EVENT_LIMIT = void 0;
|
|
7
|
+
exports.StorageModalWithTabs = StorageModalWithTabs;
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _reactNative = require("react-native");
|
|
10
|
+
var _asyncStorage = _interopRequireDefault(require("@react-native-async-storage/async-storage"));
|
|
11
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
12
|
+
var _StorageBrowserMode = require("./StorageBrowserMode");
|
|
13
|
+
var _clearAllStorage = require("../utils/clearAllStorage");
|
|
14
|
+
var _AsyncStorageListener = require("../utils/AsyncStorageListener");
|
|
15
|
+
var _StorageEventDetailContent = require("./StorageEventDetailContent");
|
|
16
|
+
var _StorageFilterViewV = require("./StorageFilterViewV2");
|
|
17
|
+
var _StorageEventFilterView = require("./StorageEventFilterView");
|
|
18
|
+
var _storageActionHelpers = require("../utils/storageActionHelpers");
|
|
19
|
+
var _mmkvAvailability = require("../utils/mmkvAvailability");
|
|
20
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
21
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
|
+
// Conditionally import MMKV listener
|
|
23
|
+
let addMMKVListener;
|
|
24
|
+
if ((0, _mmkvAvailability.isMMKVAvailable)()) {
|
|
25
|
+
const mmkvListener = require("../utils/MMKVListener");
|
|
26
|
+
addMMKVListener = mmkvListener.addMMKVListener;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Unified storage event type
|
|
30
|
+
|
|
31
|
+
// Lazy load the license hooks to avoid circular dependencies
|
|
32
|
+
let _useIsPro = null;
|
|
33
|
+
let _licenseLoadAttempted = false;
|
|
34
|
+
function loadLicenseModule() {
|
|
35
|
+
if (_licenseLoadAttempted) return;
|
|
36
|
+
_licenseLoadAttempted = true;
|
|
37
|
+
try {
|
|
38
|
+
const mod = require("@buoy-gg/license");
|
|
39
|
+
if (mod) {
|
|
40
|
+
_useIsPro = mod.useIsPro ?? null;
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
// License package not available
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function getUseIsPro() {
|
|
47
|
+
loadLicenseModule();
|
|
48
|
+
return _useIsPro ?? (() => false);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Free tier limit for storage events/conversations
|
|
52
|
+
const FREE_TIER_EVENT_LIMIT = exports.FREE_TIER_EVENT_LIMIT = 25;
|
|
53
|
+
function StorageModalWithTabs({
|
|
54
|
+
visible,
|
|
55
|
+
onClose,
|
|
56
|
+
onBack,
|
|
57
|
+
onMinimize,
|
|
58
|
+
enableSharedModalDimensions = false,
|
|
59
|
+
requiredStorageKeys = []
|
|
60
|
+
}) {
|
|
61
|
+
// Check Pro status internally
|
|
62
|
+
const useIsPro = getUseIsPro();
|
|
63
|
+
const isPro = useIsPro();
|
|
64
|
+
const [activeTab, setActiveTab] = (0, _react.useState)("browser");
|
|
65
|
+
|
|
66
|
+
// Storage Browser state
|
|
67
|
+
const [showStorageFilters, setShowStorageFilters] = (0, _react.useState)(false);
|
|
68
|
+
const [storageIgnoredPatterns, setStorageIgnoredPatterns] = (0, _react.useState)(new Set(["@react_buoy"]) // Auto-hide dev tool keys by default
|
|
69
|
+
);
|
|
70
|
+
const [searchQuery, setSearchQuery] = (0, _react.useState)("");
|
|
71
|
+
const [isSearchActive, setIsSearchActive] = (0, _react.useState)(false);
|
|
72
|
+
const hasLoadedStorageFilters = (0, _react.useRef)(false);
|
|
73
|
+
|
|
74
|
+
// Event Listener state
|
|
75
|
+
const [events, setEvents] = (0, _react.useState)([]);
|
|
76
|
+
const [isListening, setIsListening] = (0, _react.useState)(false);
|
|
77
|
+
const [selectedConversationKey, setSelectedConversationKey] = (0, _react.useState)(null);
|
|
78
|
+
const [selectedEventIndex, setSelectedEventIndex] = (0, _react.useState)(0);
|
|
79
|
+
const [showFilters, setShowFilters] = (0, _react.useState)(false);
|
|
80
|
+
const [ignoredPatterns, setIgnoredPatterns] = (0, _react.useState)(new Set(["@RNAsyncStorage", "redux-persist", "persist:"]) // Only show @react_buoy events by default
|
|
81
|
+
);
|
|
82
|
+
const [enabledStorageTypes, setEnabledStorageTypes] = (0, _react.useState)(new Set(['async', 'mmkv', 'secure']) // All enabled by default
|
|
83
|
+
);
|
|
84
|
+
const lastEventRef = (0, _react.useRef)(null);
|
|
85
|
+
const hasLoadedFilters = (0, _react.useRef)(false);
|
|
86
|
+
const hasLoadedTabState = (0, _react.useRef)(false);
|
|
87
|
+
const hasLoadedMonitoringState = (0, _react.useRef)(false);
|
|
88
|
+
const handleModeChange = (0, _react.useCallback)(_mode => {
|
|
89
|
+
// Mode changes handled by JsModal
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
92
|
+
// Timer removed - using useTickEveryMinute hook instead
|
|
93
|
+
|
|
94
|
+
// Load persisted tab state on mount
|
|
95
|
+
(0, _react.useEffect)(() => {
|
|
96
|
+
if (!visible || hasLoadedTabState.current) return;
|
|
97
|
+
const loadTabState = async () => {
|
|
98
|
+
try {
|
|
99
|
+
const storedTab = await _asyncStorage.default.getItem(_sharedUi.devToolsStorageKeys.storage.activeTab());
|
|
100
|
+
if (storedTab && (storedTab === "browser" || storedTab === "events")) {
|
|
101
|
+
setActiveTab(storedTab);
|
|
102
|
+
}
|
|
103
|
+
hasLoadedTabState.current = true;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
// Failed to load tab state
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
loadTabState();
|
|
109
|
+
}, [visible]);
|
|
110
|
+
|
|
111
|
+
// Load persisted monitoring state on mount
|
|
112
|
+
(0, _react.useEffect)(() => {
|
|
113
|
+
if (!visible || hasLoadedMonitoringState.current) return;
|
|
114
|
+
const loadMonitoringState = async () => {
|
|
115
|
+
try {
|
|
116
|
+
const storedMonitoring = await _asyncStorage.default.getItem(_sharedUi.devToolsStorageKeys.storage.isMonitoring());
|
|
117
|
+
if (storedMonitoring !== null) {
|
|
118
|
+
const shouldMonitor = storedMonitoring === "true";
|
|
119
|
+
if (shouldMonitor && !(0, _AsyncStorageListener.isListening)()) {
|
|
120
|
+
await (0, _AsyncStorageListener.startListening)();
|
|
121
|
+
setIsListening(true);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
hasLoadedMonitoringState.current = true;
|
|
125
|
+
} catch (error) {
|
|
126
|
+
// Failed to load monitoring state
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
loadMonitoringState();
|
|
130
|
+
}, [visible]);
|
|
131
|
+
|
|
132
|
+
// Note: Conversations will appear when storage events are triggered
|
|
133
|
+
// Click on any conversation to see the unified view with toggle cards
|
|
134
|
+
|
|
135
|
+
// Save tab state when it changes
|
|
136
|
+
(0, _react.useEffect)(() => {
|
|
137
|
+
if (!hasLoadedTabState.current) return; // Don't save on initial load
|
|
138
|
+
|
|
139
|
+
const saveTabState = async () => {
|
|
140
|
+
try {
|
|
141
|
+
await _asyncStorage.default.setItem(_sharedUi.devToolsStorageKeys.storage.activeTab(), activeTab);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
// Failed to save tab state
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
saveTabState();
|
|
147
|
+
}, [activeTab]);
|
|
148
|
+
|
|
149
|
+
// Save monitoring state when it changes
|
|
150
|
+
(0, _react.useEffect)(() => {
|
|
151
|
+
if (!hasLoadedMonitoringState.current) return; // Don't save on initial load
|
|
152
|
+
|
|
153
|
+
const saveMonitoringState = async () => {
|
|
154
|
+
try {
|
|
155
|
+
await _asyncStorage.default.setItem(_sharedUi.devToolsStorageKeys.storage.isMonitoring(), isListening.toString());
|
|
156
|
+
} catch (error) {
|
|
157
|
+
// Failed to save monitoring state
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
saveMonitoringState();
|
|
161
|
+
}, [isListening]);
|
|
162
|
+
|
|
163
|
+
// Load persisted filters on mount
|
|
164
|
+
(0, _react.useEffect)(() => {
|
|
165
|
+
if (!visible || hasLoadedFilters.current) return;
|
|
166
|
+
const loadFilters = async () => {
|
|
167
|
+
try {
|
|
168
|
+
const storedFilters = await _asyncStorage.default.getItem(_sharedUi.devToolsStorageKeys.storage.eventFilters());
|
|
169
|
+
if (storedFilters) {
|
|
170
|
+
const filters = JSON.parse(storedFilters);
|
|
171
|
+
setIgnoredPatterns(new Set(filters));
|
|
172
|
+
}
|
|
173
|
+
hasLoadedFilters.current = true;
|
|
174
|
+
} catch (error) {
|
|
175
|
+
// Failed to load filters
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
loadFilters();
|
|
179
|
+
}, [visible]);
|
|
180
|
+
|
|
181
|
+
// Save filters when they change
|
|
182
|
+
(0, _react.useEffect)(() => {
|
|
183
|
+
if (!hasLoadedFilters.current) return; // Don't save on initial load
|
|
184
|
+
|
|
185
|
+
const saveFilters = async () => {
|
|
186
|
+
try {
|
|
187
|
+
const filters = Array.from(ignoredPatterns);
|
|
188
|
+
await _asyncStorage.default.setItem(_sharedUi.devToolsStorageKeys.storage.eventFilters(), JSON.stringify(filters));
|
|
189
|
+
} catch (error) {
|
|
190
|
+
// Failed to save filters
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
saveFilters();
|
|
194
|
+
}, [ignoredPatterns]);
|
|
195
|
+
|
|
196
|
+
// Sync isListening state with actual listener state on mount
|
|
197
|
+
(0, _react.useEffect)(() => {
|
|
198
|
+
if (!visible) return;
|
|
199
|
+
|
|
200
|
+
// Check if already listening and sync state
|
|
201
|
+
const listening = (0, _AsyncStorageListener.isListening)();
|
|
202
|
+
setIsListening(listening);
|
|
203
|
+
}, [visible]);
|
|
204
|
+
|
|
205
|
+
// Event listener setup - only collect events when isListening is true
|
|
206
|
+
(0, _react.useEffect)(() => {
|
|
207
|
+
if (!visible || !isListening) return;
|
|
208
|
+
|
|
209
|
+
// Set up AsyncStorage event listener
|
|
210
|
+
const unsubscribeAsync = (0, _AsyncStorageListener.addListener)(event => {
|
|
211
|
+
const storageEvent = {
|
|
212
|
+
...event,
|
|
213
|
+
storageType: 'async'
|
|
214
|
+
};
|
|
215
|
+
lastEventRef.current = storageEvent;
|
|
216
|
+
setEvents(prev => {
|
|
217
|
+
const updated = [storageEvent, ...prev];
|
|
218
|
+
return updated.slice(0, 500);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Set up MMKV event listener (if available)
|
|
223
|
+
let unsubscribeMMKV = () => {};
|
|
224
|
+
if ((0, _mmkvAvailability.isMMKVAvailable)() && addMMKVListener) {
|
|
225
|
+
unsubscribeMMKV = addMMKVListener(event => {
|
|
226
|
+
const storageEvent = {
|
|
227
|
+
...event,
|
|
228
|
+
storageType: 'mmkv'
|
|
229
|
+
};
|
|
230
|
+
lastEventRef.current = storageEvent;
|
|
231
|
+
setEvents(prev => {
|
|
232
|
+
const updated = [storageEvent, ...prev];
|
|
233
|
+
return updated.slice(0, 500);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return () => {
|
|
238
|
+
unsubscribeAsync();
|
|
239
|
+
unsubscribeMMKV();
|
|
240
|
+
};
|
|
241
|
+
}, [visible, isListening]);
|
|
242
|
+
const handleToggleListening = (0, _react.useCallback)(async () => {
|
|
243
|
+
if (isListening) {
|
|
244
|
+
(0, _AsyncStorageListener.stopListening)();
|
|
245
|
+
setIsListening(false);
|
|
246
|
+
} else {
|
|
247
|
+
await (0, _AsyncStorageListener.startListening)();
|
|
248
|
+
setIsListening(true);
|
|
249
|
+
}
|
|
250
|
+
}, [isListening]);
|
|
251
|
+
const handleClearEvents = (0, _react.useCallback)(() => {
|
|
252
|
+
setEvents([]);
|
|
253
|
+
setSelectedConversationKey(null);
|
|
254
|
+
}, []);
|
|
255
|
+
const handleConversationPress = (0, _react.useCallback)(conversation => {
|
|
256
|
+
setSelectedConversationKey(conversation.key);
|
|
257
|
+
setSelectedEventIndex(0);
|
|
258
|
+
}, []);
|
|
259
|
+
const handleTogglePattern = (0, _react.useCallback)(pattern => {
|
|
260
|
+
setIgnoredPatterns(prev => {
|
|
261
|
+
const next = new Set(prev);
|
|
262
|
+
if (next.has(pattern)) {
|
|
263
|
+
next.delete(pattern);
|
|
264
|
+
} else {
|
|
265
|
+
next.add(pattern);
|
|
266
|
+
}
|
|
267
|
+
return next;
|
|
268
|
+
});
|
|
269
|
+
}, []);
|
|
270
|
+
const handleAddPattern = (0, _react.useCallback)(pattern => {
|
|
271
|
+
setIgnoredPatterns(prev => new Set([...prev, pattern]));
|
|
272
|
+
}, []);
|
|
273
|
+
const handleToggleFilters = (0, _react.useCallback)(() => {
|
|
274
|
+
setShowFilters(!showFilters);
|
|
275
|
+
}, [showFilters]);
|
|
276
|
+
const handleToggleStorageType = (0, _react.useCallback)(type => {
|
|
277
|
+
setEnabledStorageTypes(prev => {
|
|
278
|
+
const next = new Set(prev);
|
|
279
|
+
if (next.has(type)) {
|
|
280
|
+
next.delete(type);
|
|
281
|
+
} else {
|
|
282
|
+
next.add(type);
|
|
283
|
+
}
|
|
284
|
+
return next;
|
|
285
|
+
});
|
|
286
|
+
}, []);
|
|
287
|
+
|
|
288
|
+
// Storage Browser handlers
|
|
289
|
+
const storageDataRef = (0, _react.useRef)([]);
|
|
290
|
+
const handleToggleStorageFilters = (0, _react.useCallback)(() => {
|
|
291
|
+
setShowStorageFilters(!showStorageFilters);
|
|
292
|
+
}, [showStorageFilters]);
|
|
293
|
+
const handleToggleStoragePattern = (0, _react.useCallback)(pattern => {
|
|
294
|
+
setStorageIgnoredPatterns(prev => {
|
|
295
|
+
const next = new Set(prev);
|
|
296
|
+
if (next.has(pattern)) {
|
|
297
|
+
next.delete(pattern);
|
|
298
|
+
} else {
|
|
299
|
+
next.add(pattern);
|
|
300
|
+
}
|
|
301
|
+
return next;
|
|
302
|
+
});
|
|
303
|
+
}, []);
|
|
304
|
+
const handleAddStoragePattern = (0, _react.useCallback)(pattern => {
|
|
305
|
+
setStorageIgnoredPatterns(prev => new Set([...prev, pattern]));
|
|
306
|
+
}, []);
|
|
307
|
+
const handlePurgeStorage = (0, _react.useCallback)(async () => {
|
|
308
|
+
_reactNative.Alert.alert("Clear Storage", "Choose what to clear:", [{
|
|
309
|
+
text: "Cancel",
|
|
310
|
+
style: "cancel"
|
|
311
|
+
}, {
|
|
312
|
+
text: "Clear App Storage",
|
|
313
|
+
onPress: async () => {
|
|
314
|
+
try {
|
|
315
|
+
await (0, _clearAllStorage.clearAllAppStorage)();
|
|
316
|
+
// Refresh will be handled by GameUIStorageBrowser
|
|
317
|
+
} catch (error) {
|
|
318
|
+
_reactNative.Alert.alert("Error", "Failed to clear app storage");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}, {
|
|
322
|
+
text: "Clear All (Including Dev Tools)",
|
|
323
|
+
style: "destructive",
|
|
324
|
+
onPress: async () => {
|
|
325
|
+
try {
|
|
326
|
+
await (0, _clearAllStorage.clearAllStorageIncludingDevTools)();
|
|
327
|
+
// Refresh will be handled by GameUIStorageBrowser
|
|
328
|
+
} catch (error) {
|
|
329
|
+
_reactNative.Alert.alert("Error", "Failed to clear all storage");
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}]);
|
|
333
|
+
}, []);
|
|
334
|
+
const getValueType = value => {
|
|
335
|
+
const parsed = (0, _sharedUi.parseValue)(value);
|
|
336
|
+
if (parsed === null) return "null";
|
|
337
|
+
if (parsed === undefined) return "undefined";
|
|
338
|
+
if (Array.isArray(parsed)) return "array";
|
|
339
|
+
if (typeof parsed === "boolean") return "boolean";
|
|
340
|
+
if (typeof parsed === "number") return "number";
|
|
341
|
+
if (typeof parsed === "string") return "string";
|
|
342
|
+
if (typeof parsed === "object") return "object";
|
|
343
|
+
return "undefined";
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// Get all unique keys from events AND from AsyncStorage for filter view
|
|
347
|
+
const [allStorageKeys, setAllStorageKeys] = (0, _react.useState)([]);
|
|
348
|
+
(0, _react.useEffect)(() => {
|
|
349
|
+
const fetchAllKeys = async () => {
|
|
350
|
+
try {
|
|
351
|
+
const keys = await _asyncStorage.default.getAllKeys();
|
|
352
|
+
setAllStorageKeys([...keys].sort());
|
|
353
|
+
} catch (error) {
|
|
354
|
+
// Failed to fetch keys
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// Fetch all keys for both tabs when visible
|
|
359
|
+
if (visible) {
|
|
360
|
+
fetchAllKeys();
|
|
361
|
+
}
|
|
362
|
+
}, [visible]);
|
|
363
|
+
const allEventKeys = (0, _react.useMemo)(() => {
|
|
364
|
+
// Combine storage keys with event keys for comprehensive filter view
|
|
365
|
+
const keys = new Set(allStorageKeys);
|
|
366
|
+
events.forEach(event => {
|
|
367
|
+
if (event.data?.key) {
|
|
368
|
+
keys.add(event.data.key);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
return Array.from(keys).sort();
|
|
372
|
+
}, [events, allStorageKeys]);
|
|
373
|
+
|
|
374
|
+
// Group events by key and create conversations
|
|
375
|
+
const conversations = (0, _react.useMemo)(() => {
|
|
376
|
+
const keyMap = new Map();
|
|
377
|
+
events.forEach(event => {
|
|
378
|
+
if (!event.data?.key) return;
|
|
379
|
+
const key = event.data.key;
|
|
380
|
+
|
|
381
|
+
// Filter by enabled storage types
|
|
382
|
+
if (!enabledStorageTypes.has(event.storageType)) return;
|
|
383
|
+
|
|
384
|
+
// Filter out keys that match ignored patterns
|
|
385
|
+
const shouldIgnore = Array.from(ignoredPatterns).some(pattern => key.includes(pattern));
|
|
386
|
+
if (shouldIgnore) return;
|
|
387
|
+
const existing = keyMap.get(key);
|
|
388
|
+
if (!existing) {
|
|
389
|
+
keyMap.set(key, {
|
|
390
|
+
key,
|
|
391
|
+
lastEvent: event,
|
|
392
|
+
events: [event],
|
|
393
|
+
totalOperations: 1,
|
|
394
|
+
currentValue: event.data.value,
|
|
395
|
+
valueType: getValueType(event.data.value),
|
|
396
|
+
storageTypes: new Set([event.storageType])
|
|
397
|
+
});
|
|
398
|
+
} else {
|
|
399
|
+
existing.events.push(event);
|
|
400
|
+
existing.totalOperations++;
|
|
401
|
+
existing.storageTypes.add(event.storageType);
|
|
402
|
+
|
|
403
|
+
// Update last event if this one is newer
|
|
404
|
+
if (event.timestamp > existing.lastEvent.timestamp) {
|
|
405
|
+
existing.lastEvent = event;
|
|
406
|
+
existing.currentValue = event.data.value;
|
|
407
|
+
existing.valueType = getValueType(event.data.value);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// Convert to array and sort by last updated
|
|
413
|
+
return Array.from(keyMap.values()).sort((a, b) => b.lastEvent.timestamp.getTime() - a.lastEvent.timestamp.getTime());
|
|
414
|
+
}, [events, ignoredPatterns, enabledStorageTypes]);
|
|
415
|
+
|
|
416
|
+
// Get the live selected conversation from the current conversations array
|
|
417
|
+
const selectedConversation = (0, _react.useMemo)(() => {
|
|
418
|
+
if (!selectedConversationKey) return null;
|
|
419
|
+
return conversations.find(c => c.key === selectedConversationKey) || null;
|
|
420
|
+
}, [selectedConversationKey, conversations]);
|
|
421
|
+
|
|
422
|
+
// For free users, limit visible conversations
|
|
423
|
+
const visibleConversations = (0, _react.useMemo)(() => {
|
|
424
|
+
if (isPro) return conversations;
|
|
425
|
+
return conversations.slice(0, FREE_TIER_EVENT_LIMIT);
|
|
426
|
+
}, [conversations, isPro]);
|
|
427
|
+
const lockedConversationCount = (0, _react.useMemo)(() => {
|
|
428
|
+
if (isPro) return 0;
|
|
429
|
+
return Math.max(0, conversations.length - FREE_TIER_EVENT_LIMIT);
|
|
430
|
+
}, [conversations.length, isPro]);
|
|
431
|
+
const getActionColor = action => {
|
|
432
|
+
switch (action) {
|
|
433
|
+
// AsyncStorage - Set operations
|
|
434
|
+
case "setItem":
|
|
435
|
+
case "multiSet":
|
|
436
|
+
// MMKV - Set operations
|
|
437
|
+
// falls through
|
|
438
|
+
case "set.string":
|
|
439
|
+
case "set.number":
|
|
440
|
+
case "set.boolean":
|
|
441
|
+
case "set.buffer":
|
|
442
|
+
return _sharedUi.macOSColors.semantic.success;
|
|
443
|
+
|
|
444
|
+
// AsyncStorage - Remove operations
|
|
445
|
+
case "removeItem":
|
|
446
|
+
case "multiRemove":
|
|
447
|
+
case "clear":
|
|
448
|
+
// MMKV - Delete operations
|
|
449
|
+
// falls through
|
|
450
|
+
case "delete":
|
|
451
|
+
case "clearAll":
|
|
452
|
+
return _sharedUi.macOSColors.semantic.error;
|
|
453
|
+
|
|
454
|
+
// AsyncStorage - Merge operations
|
|
455
|
+
case "mergeItem":
|
|
456
|
+
case "multiMerge":
|
|
457
|
+
return _sharedUi.macOSColors.semantic.info;
|
|
458
|
+
|
|
459
|
+
// MMKV - Get operations
|
|
460
|
+
case "get.string":
|
|
461
|
+
case "get.number":
|
|
462
|
+
case "get.boolean":
|
|
463
|
+
case "get.buffer":
|
|
464
|
+
return _sharedUi.macOSColors.semantic.warning;
|
|
465
|
+
default:
|
|
466
|
+
return _sharedUi.macOSColors.text.muted;
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
// FlatList optimization constants
|
|
471
|
+
const END_REACHED_THRESHOLD = 0.8;
|
|
472
|
+
|
|
473
|
+
// Stable keyExtractor for FlatList
|
|
474
|
+
const keyExtractor = (0, _react.useCallback)(item => {
|
|
475
|
+
return item.key;
|
|
476
|
+
}, []);
|
|
477
|
+
|
|
478
|
+
// Removed getItemType as it's FlatList-specific
|
|
479
|
+
|
|
480
|
+
// Create stable ref for event handler
|
|
481
|
+
const selectConversationRef = (0, _react.useRef)(undefined);
|
|
482
|
+
selectConversationRef.current = handleConversationPress;
|
|
483
|
+
|
|
484
|
+
// Stable renderItem with ref pattern
|
|
485
|
+
const renderConversationItem = (0, _react.useCallback)(({
|
|
486
|
+
item
|
|
487
|
+
}) => {
|
|
488
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
489
|
+
onPress: () => selectConversationRef.current?.(item),
|
|
490
|
+
style: styles.conversationItem,
|
|
491
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
492
|
+
style: styles.conversationHeader,
|
|
493
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
494
|
+
style: styles.keyText,
|
|
495
|
+
numberOfLines: 1,
|
|
496
|
+
children: item.key
|
|
497
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
498
|
+
style: [styles.actionText, {
|
|
499
|
+
color: getActionColor(item.lastEvent.action)
|
|
500
|
+
}],
|
|
501
|
+
children: (0, _storageActionHelpers.translateStorageAction)(item.lastEvent.action)
|
|
502
|
+
})]
|
|
503
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
504
|
+
style: styles.conversationDetails,
|
|
505
|
+
children: [item.storageTypes && Array.from(item.storageTypes).map(storageType => /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.StorageTypeBadge, {
|
|
506
|
+
type: storageType
|
|
507
|
+
}, storageType)), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ValueTypeBadge, {
|
|
508
|
+
type: item.valueType
|
|
509
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
510
|
+
style: styles.operationCount,
|
|
511
|
+
children: [item.totalOperations, " operation", item.totalOperations !== 1 ? "s" : ""]
|
|
512
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
513
|
+
style: styles.timestamp,
|
|
514
|
+
children: (0, _sharedUi.formatRelativeTime)(item.lastEvent.timestamp)
|
|
515
|
+
})]
|
|
516
|
+
})]
|
|
517
|
+
});
|
|
518
|
+
}, []);
|
|
519
|
+
if (!visible) return null;
|
|
520
|
+
const persistenceKey = enableSharedModalDimensions ? _sharedUi.devToolsStorageKeys.modal.root() : _sharedUi.devToolsStorageKeys.storage.modal();
|
|
521
|
+
const renderContent = () => {
|
|
522
|
+
if (activeTab === "browser") {
|
|
523
|
+
if (showStorageFilters) {
|
|
524
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageFilterViewV.StorageFilterViewV2, {
|
|
525
|
+
ignoredPatterns: storageIgnoredPatterns,
|
|
526
|
+
onTogglePattern: handleToggleStoragePattern,
|
|
527
|
+
onAddPattern: handleAddStoragePattern,
|
|
528
|
+
availableKeys: allStorageKeys
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageBrowserMode.StorageBrowserMode, {
|
|
532
|
+
requiredStorageKeys: requiredStorageKeys,
|
|
533
|
+
showFilters: showStorageFilters,
|
|
534
|
+
ignoredPatterns: storageIgnoredPatterns,
|
|
535
|
+
onTogglePattern: handleToggleStoragePattern,
|
|
536
|
+
onAddPattern: handleAddStoragePattern,
|
|
537
|
+
searchQuery: searchQuery,
|
|
538
|
+
storageDataRef: storageDataRef
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Events tab content
|
|
543
|
+
if (selectedConversation) {
|
|
544
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
545
|
+
style: styles.contentWrapper,
|
|
546
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageEventDetailContent.StorageEventDetailContent, {
|
|
547
|
+
conversation: selectedConversation,
|
|
548
|
+
selectedEventIndex: selectedEventIndex,
|
|
549
|
+
onEventIndexChange: setSelectedEventIndex,
|
|
550
|
+
disableInternalFooter: true
|
|
551
|
+
})
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
if (showFilters) {
|
|
555
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageEventFilterView.StorageEventFilterView, {
|
|
556
|
+
ignoredPatterns: ignoredPatterns,
|
|
557
|
+
onTogglePattern: handleTogglePattern,
|
|
558
|
+
onAddPattern: handleAddPattern,
|
|
559
|
+
availableKeys: allEventKeys,
|
|
560
|
+
enabledStorageTypes: enabledStorageTypes,
|
|
561
|
+
onToggleStorageType: handleToggleStorageType
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
if (conversations.length === 0) {
|
|
565
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
566
|
+
style: styles.emptyState,
|
|
567
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Database, {
|
|
568
|
+
size: 48,
|
|
569
|
+
color: _sharedUi.macOSColors.text.muted
|
|
570
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
571
|
+
style: styles.emptyTitle,
|
|
572
|
+
children: isListening ? "No storage events yet" : "Event listener is paused"
|
|
573
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
574
|
+
style: styles.emptySubtitle,
|
|
575
|
+
children: isListening ? "Storage operations will appear here" : "Press play to start monitoring"
|
|
576
|
+
})]
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
|
|
580
|
+
data: visibleConversations,
|
|
581
|
+
renderItem: renderConversationItem,
|
|
582
|
+
keyExtractor: keyExtractor,
|
|
583
|
+
onEndReachedThreshold: END_REACHED_THRESHOLD,
|
|
584
|
+
contentContainerStyle: styles.listContent,
|
|
585
|
+
ItemSeparatorComponent: () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
586
|
+
style: styles.separator
|
|
587
|
+
}),
|
|
588
|
+
ListFooterComponent: lockedConversationCount > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
589
|
+
style: styles.lockedBannerContainer,
|
|
590
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ProFeatureBanner, {
|
|
591
|
+
featureName: `${lockedConversationCount} event${lockedConversationCount > 1 ? 's' : ''} locked`,
|
|
592
|
+
description: "Upgrade to Pro to unlock full event history"
|
|
593
|
+
})
|
|
594
|
+
}) : null,
|
|
595
|
+
initialNumToRender: 10,
|
|
596
|
+
maxToRenderPerBatch: 10,
|
|
597
|
+
windowSize: 10,
|
|
598
|
+
scrollEnabled: false
|
|
599
|
+
});
|
|
600
|
+
};
|
|
601
|
+
const footerNode = selectedConversation ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageEventDetailContent.StorageEventDetailFooter, {
|
|
602
|
+
conversation: selectedConversation,
|
|
603
|
+
selectedEventIndex: selectedEventIndex,
|
|
604
|
+
onEventIndexChange: setSelectedEventIndex
|
|
605
|
+
}) : null;
|
|
606
|
+
|
|
607
|
+
// Determine the appropriate back handler based on current view state
|
|
608
|
+
const currentBackHandler = showStorageFilters ? () => setShowStorageFilters(false) : showFilters ? () => setShowFilters(false) : selectedConversation ? () => {
|
|
609
|
+
setSelectedConversationKey(null);
|
|
610
|
+
setSelectedEventIndex(0);
|
|
611
|
+
} : onBack;
|
|
612
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
|
|
613
|
+
visible: visible,
|
|
614
|
+
onClose: onClose,
|
|
615
|
+
onBack: currentBackHandler,
|
|
616
|
+
onMinimize: onMinimize,
|
|
617
|
+
persistenceKey: persistenceKey,
|
|
618
|
+
header: {
|
|
619
|
+
showToggleButton: true,
|
|
620
|
+
customContent: showStorageFilters ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
|
|
621
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
|
|
622
|
+
onBack: () => setShowStorageFilters(false)
|
|
623
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
|
|
624
|
+
title: "Filters"
|
|
625
|
+
})]
|
|
626
|
+
}) : showFilters ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
|
|
627
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
|
|
628
|
+
onBack: () => setShowFilters(false)
|
|
629
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
|
|
630
|
+
title: "Event Filters"
|
|
631
|
+
})]
|
|
632
|
+
}) : selectedConversation ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
|
|
633
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
|
|
634
|
+
onBack: () => {
|
|
635
|
+
setSelectedConversationKey(null);
|
|
636
|
+
setSelectedEventIndex(0);
|
|
637
|
+
}
|
|
638
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
|
|
639
|
+
title: selectedConversation.key
|
|
640
|
+
})]
|
|
641
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
|
|
642
|
+
children: [onBack && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
|
|
643
|
+
onBack: onBack
|
|
644
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
|
|
645
|
+
title: "",
|
|
646
|
+
children: isSearchActive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SearchBar, {
|
|
647
|
+
value: searchQuery,
|
|
648
|
+
onChange: setSearchQuery,
|
|
649
|
+
onClear: () => {
|
|
650
|
+
setSearchQuery("");
|
|
651
|
+
setIsSearchActive(false);
|
|
652
|
+
},
|
|
653
|
+
placeholder: "Search storage keys...",
|
|
654
|
+
autoFocus: true,
|
|
655
|
+
onSubmitEditing: () => setIsSearchActive(false),
|
|
656
|
+
returnKeyType: "search",
|
|
657
|
+
suggestions: allStorageKeys,
|
|
658
|
+
containerStyle: styles.headerSearchContainer
|
|
659
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.TabSelector, {
|
|
660
|
+
tabs: [{
|
|
661
|
+
key: "browser",
|
|
662
|
+
label: "Storage"
|
|
663
|
+
}, {
|
|
664
|
+
key: "events",
|
|
665
|
+
label: `Events${events.length > 0 && activeTab !== "events" ? ` (${events.length})` : ""}`
|
|
666
|
+
}],
|
|
667
|
+
activeTab: activeTab,
|
|
668
|
+
onTabChange: tab => setActiveTab(tab)
|
|
669
|
+
})
|
|
670
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions, {
|
|
671
|
+
children: [activeTab === "browser" && !isSearchActive && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
672
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
673
|
+
onPress: () => setIsSearchActive(true),
|
|
674
|
+
style: styles.iconButton,
|
|
675
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
|
|
676
|
+
size: 14,
|
|
677
|
+
color: _sharedUi.macOSColors.text.secondary
|
|
678
|
+
})
|
|
679
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
680
|
+
onPress: handleToggleStorageFilters,
|
|
681
|
+
style: [styles.iconButton, storageIgnoredPatterns.size > 0 && styles.activeFilterButton],
|
|
682
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Filter, {
|
|
683
|
+
size: 14,
|
|
684
|
+
color: storageIgnoredPatterns.size > 0 ? _sharedUi.macOSColors.semantic.debug : _sharedUi.macOSColors.text.secondary
|
|
685
|
+
})
|
|
686
|
+
})]
|
|
687
|
+
}), activeTab === "events" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
688
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
689
|
+
onPress: handleToggleFilters,
|
|
690
|
+
style: [styles.iconButton, ignoredPatterns.size > 0 && styles.activeFilterButton],
|
|
691
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Filter, {
|
|
692
|
+
size: 14,
|
|
693
|
+
color: ignoredPatterns.size > 0 ? _sharedUi.macOSColors.semantic.debug : _sharedUi.macOSColors.text.secondary
|
|
694
|
+
})
|
|
695
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
696
|
+
onPress: handleToggleListening,
|
|
697
|
+
style: [styles.iconButton, isListening && styles.activeButton],
|
|
698
|
+
children: isListening ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Pause, {
|
|
699
|
+
size: 14,
|
|
700
|
+
color: _sharedUi.macOSColors.semantic.success
|
|
701
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Play, {
|
|
702
|
+
size: 14,
|
|
703
|
+
color: _sharedUi.macOSColors.semantic.success
|
|
704
|
+
})
|
|
705
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
706
|
+
onPress: handleClearEvents,
|
|
707
|
+
style: styles.iconButton,
|
|
708
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Trash2, {
|
|
709
|
+
size: 14,
|
|
710
|
+
color: _sharedUi.macOSColors.semantic.error
|
|
711
|
+
})
|
|
712
|
+
})]
|
|
713
|
+
})]
|
|
714
|
+
})]
|
|
715
|
+
})
|
|
716
|
+
},
|
|
717
|
+
onModeChange: handleModeChange,
|
|
718
|
+
enablePersistence: true,
|
|
719
|
+
initialMode: "bottomSheet",
|
|
720
|
+
enableGlitchEffects: true,
|
|
721
|
+
styles: {},
|
|
722
|
+
footer: footerNode,
|
|
723
|
+
footerHeight: footerNode ? 68 : 0,
|
|
724
|
+
children: renderContent()
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
const styles = _reactNative.StyleSheet.create({
|
|
728
|
+
headerSearchContainer: {
|
|
729
|
+
flex: 1
|
|
730
|
+
},
|
|
731
|
+
iconButton: {
|
|
732
|
+
width: 32,
|
|
733
|
+
height: 32,
|
|
734
|
+
borderRadius: 8,
|
|
735
|
+
backgroundColor: _sharedUi.macOSColors.background.hover,
|
|
736
|
+
borderWidth: 1,
|
|
737
|
+
borderColor: _sharedUi.macOSColors.border.default,
|
|
738
|
+
alignItems: "center",
|
|
739
|
+
justifyContent: "center"
|
|
740
|
+
},
|
|
741
|
+
activeButton: {
|
|
742
|
+
backgroundColor: _sharedUi.macOSColors.semantic.successBackground
|
|
743
|
+
},
|
|
744
|
+
activeFilterButton: {
|
|
745
|
+
backgroundColor: _sharedUi.macOSColors.semantic.infoBackground
|
|
746
|
+
},
|
|
747
|
+
conversationItem: {
|
|
748
|
+
padding: 12,
|
|
749
|
+
backgroundColor: _sharedUi.macOSColors.background.card,
|
|
750
|
+
borderRadius: 8,
|
|
751
|
+
marginHorizontal: 16
|
|
752
|
+
},
|
|
753
|
+
conversationHeader: {
|
|
754
|
+
flexDirection: "row",
|
|
755
|
+
justifyContent: "space-between",
|
|
756
|
+
alignItems: "center",
|
|
757
|
+
marginBottom: 8
|
|
758
|
+
},
|
|
759
|
+
keyText: {
|
|
760
|
+
color: _sharedUi.macOSColors.text.primary,
|
|
761
|
+
fontSize: 14,
|
|
762
|
+
fontWeight: "600",
|
|
763
|
+
flex: 1,
|
|
764
|
+
marginRight: 8,
|
|
765
|
+
fontFamily: "monospace"
|
|
766
|
+
},
|
|
767
|
+
actionText: {
|
|
768
|
+
fontSize: 11,
|
|
769
|
+
fontWeight: "600",
|
|
770
|
+
fontFamily: "monospace",
|
|
771
|
+
textTransform: "uppercase"
|
|
772
|
+
},
|
|
773
|
+
conversationDetails: {
|
|
774
|
+
flexDirection: "row",
|
|
775
|
+
alignItems: "center",
|
|
776
|
+
gap: 8
|
|
777
|
+
},
|
|
778
|
+
operationCount: {
|
|
779
|
+
color: _sharedUi.macOSColors.text.secondary,
|
|
780
|
+
fontSize: 11,
|
|
781
|
+
flex: 1,
|
|
782
|
+
fontFamily: "monospace"
|
|
783
|
+
},
|
|
784
|
+
timestamp: {
|
|
785
|
+
color: _sharedUi.macOSColors.text.muted,
|
|
786
|
+
fontSize: 11,
|
|
787
|
+
fontFamily: "monospace"
|
|
788
|
+
},
|
|
789
|
+
separator: {
|
|
790
|
+
height: 8
|
|
791
|
+
},
|
|
792
|
+
listContent: {
|
|
793
|
+
paddingVertical: 16
|
|
794
|
+
},
|
|
795
|
+
lockedBannerContainer: {
|
|
796
|
+
marginTop: 8,
|
|
797
|
+
marginHorizontal: 16
|
|
798
|
+
},
|
|
799
|
+
emptyState: {
|
|
800
|
+
flex: 1,
|
|
801
|
+
justifyContent: "center",
|
|
802
|
+
alignItems: "center",
|
|
803
|
+
padding: 32
|
|
804
|
+
},
|
|
805
|
+
emptyTitle: {
|
|
806
|
+
color: _sharedUi.macOSColors.text.primary,
|
|
807
|
+
fontSize: 16,
|
|
808
|
+
fontWeight: "600",
|
|
809
|
+
marginTop: 16,
|
|
810
|
+
marginBottom: 8,
|
|
811
|
+
fontFamily: "monospace",
|
|
812
|
+
letterSpacing: 0.5,
|
|
813
|
+
textTransform: "uppercase"
|
|
814
|
+
},
|
|
815
|
+
emptySubtitle: {
|
|
816
|
+
color: _sharedUi.macOSColors.text.secondary,
|
|
817
|
+
fontSize: 14,
|
|
818
|
+
textAlign: "center",
|
|
819
|
+
fontFamily: "monospace"
|
|
820
|
+
},
|
|
821
|
+
eventNavigation: {
|
|
822
|
+
flexDirection: "row",
|
|
823
|
+
alignItems: "center",
|
|
824
|
+
gap: 8,
|
|
825
|
+
paddingHorizontal: 8
|
|
826
|
+
},
|
|
827
|
+
navButton: {
|
|
828
|
+
padding: 4,
|
|
829
|
+
borderRadius: 4
|
|
830
|
+
},
|
|
831
|
+
navButtonDisabled: {
|
|
832
|
+
opacity: 0.3
|
|
833
|
+
},
|
|
834
|
+
eventCounter: {
|
|
835
|
+
color: _sharedUi.macOSColors.text.primary,
|
|
836
|
+
fontSize: 12,
|
|
837
|
+
fontWeight: "600",
|
|
838
|
+
fontFamily: "monospace",
|
|
839
|
+
paddingHorizontal: 8
|
|
840
|
+
},
|
|
841
|
+
headerTopRow: {
|
|
842
|
+
flexDirection: "row",
|
|
843
|
+
alignItems: "center",
|
|
844
|
+
gap: 8,
|
|
845
|
+
marginBottom: 12
|
|
846
|
+
},
|
|
847
|
+
keyNameContainer: {
|
|
848
|
+
flex: 1,
|
|
849
|
+
flexDirection: "row",
|
|
850
|
+
alignItems: "center",
|
|
851
|
+
gap: 6,
|
|
852
|
+
backgroundColor: _sharedUi.macOSColors.background.input,
|
|
853
|
+
paddingHorizontal: 10,
|
|
854
|
+
paddingVertical: 4,
|
|
855
|
+
borderRadius: 6,
|
|
856
|
+
borderWidth: 1,
|
|
857
|
+
borderColor: _sharedUi.macOSColors.border.input,
|
|
858
|
+
height: 28
|
|
859
|
+
},
|
|
860
|
+
keyNameText: {
|
|
861
|
+
flex: 1,
|
|
862
|
+
fontSize: 13,
|
|
863
|
+
fontWeight: "600",
|
|
864
|
+
color: _sharedUi.macOSColors.semantic.debug,
|
|
865
|
+
fontFamily: "monospace",
|
|
866
|
+
letterSpacing: 0.5
|
|
867
|
+
},
|
|
868
|
+
contentWrapper: {
|
|
869
|
+
flex: 1
|
|
870
|
+
}
|
|
871
|
+
});
|