@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.
Files changed (187) hide show
  1. package/README.md +607 -0
  2. package/lib/commonjs/index.js +34 -0
  3. package/lib/commonjs/package.json +1 -0
  4. package/lib/commonjs/preset.js +94 -0
  5. package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +356 -0
  6. package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +29 -0
  7. package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +121 -0
  8. package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +419 -0
  9. package/lib/commonjs/storage/components/DiffViewer/themes/diffThemes.js +122 -0
  10. package/lib/commonjs/storage/components/GameUIStorageBrowser.js +924 -0
  11. package/lib/commonjs/storage/components/GameUIStorageStats.js +746 -0
  12. package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +257 -0
  13. package/lib/commonjs/storage/components/MMKVInstanceSelector.js +418 -0
  14. package/lib/commonjs/storage/components/SelectionActionBar.js +224 -0
  15. package/lib/commonjs/storage/components/StorageActionButtons.js +239 -0
  16. package/lib/commonjs/storage/components/StorageActions.js +192 -0
  17. package/lib/commonjs/storage/components/StorageBrowserMode.js +31 -0
  18. package/lib/commonjs/storage/components/StorageEventDetailContent.js +1025 -0
  19. package/lib/commonjs/storage/components/StorageEventFilterView.js +141 -0
  20. package/lib/commonjs/storage/components/StorageEventListener.js +357 -0
  21. package/lib/commonjs/storage/components/StorageEventsSection.js +24 -0
  22. package/lib/commonjs/storage/components/StorageFilterCards.js +345 -0
  23. package/lib/commonjs/storage/components/StorageFilterViewV2.js +42 -0
  24. package/lib/commonjs/storage/components/StorageKeyCard.js +516 -0
  25. package/lib/commonjs/storage/components/StorageKeyRow.js +356 -0
  26. package/lib/commonjs/storage/components/StorageKeySection.js +105 -0
  27. package/lib/commonjs/storage/components/StorageKeyStats.js +344 -0
  28. package/lib/commonjs/storage/components/StorageModalWithTabs.js +871 -0
  29. package/lib/commonjs/storage/components/StorageSection.js +43 -0
  30. package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +126 -0
  31. package/lib/commonjs/storage/hooks/useMMKVInstances.js +221 -0
  32. package/lib/commonjs/storage/hooks/useMMKVKeys.js +362 -0
  33. package/lib/commonjs/storage/hooks/useTickEverySecond.js +21 -0
  34. package/lib/commonjs/storage/index.js +148 -0
  35. package/lib/commonjs/storage/types.js +5 -0
  36. package/lib/commonjs/storage/utils/AsyncStorageListener.js +510 -0
  37. package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +202 -0
  38. package/lib/commonjs/storage/utils/MMKVListener.js +380 -0
  39. package/lib/commonjs/storage/utils/clearAllStorage.js +47 -0
  40. package/lib/commonjs/storage/utils/index.js +180 -0
  41. package/lib/commonjs/storage/utils/lineDiff.js +363 -0
  42. package/lib/commonjs/storage/utils/mmkvAvailability.js +62 -0
  43. package/lib/commonjs/storage/utils/mmkvTypeDetection.js +139 -0
  44. package/lib/commonjs/storage/utils/objectDiff.js +157 -0
  45. package/lib/commonjs/storage/utils/safeAsyncStorage.js +140 -0
  46. package/lib/commonjs/storage/utils/storageActionHelpers.js +46 -0
  47. package/lib/commonjs/storage/utils/storageQueryUtils.js +35 -0
  48. package/lib/commonjs/storage/utils/valueType.js +18 -0
  49. package/lib/module/index.js +7 -0
  50. package/lib/module/preset.js +89 -0
  51. package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +352 -0
  52. package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +25 -0
  53. package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +117 -0
  54. package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +415 -0
  55. package/lib/module/storage/components/DiffViewer/themes/diffThemes.js +118 -0
  56. package/lib/module/storage/components/GameUIStorageBrowser.js +922 -0
  57. package/lib/module/storage/components/GameUIStorageStats.js +742 -0
  58. package/lib/module/storage/components/MMKVInstanceInfoPanel.js +253 -0
  59. package/lib/module/storage/components/MMKVInstanceSelector.js +414 -0
  60. package/lib/module/storage/components/SelectionActionBar.js +221 -0
  61. package/lib/module/storage/components/StorageActionButtons.js +236 -0
  62. package/lib/module/storage/components/StorageActions.js +189 -0
  63. package/lib/module/storage/components/StorageBrowserMode.js +27 -0
  64. package/lib/module/storage/components/StorageEventDetailContent.js +1020 -0
  65. package/lib/module/storage/components/StorageEventFilterView.js +137 -0
  66. package/lib/module/storage/components/StorageEventListener.js +354 -0
  67. package/lib/module/storage/components/StorageEventsSection.js +20 -0
  68. package/lib/module/storage/components/StorageFilterCards.js +341 -0
  69. package/lib/module/storage/components/StorageFilterViewV2.js +38 -0
  70. package/lib/module/storage/components/StorageKeyCard.js +513 -0
  71. package/lib/module/storage/components/StorageKeyRow.js +353 -0
  72. package/lib/module/storage/components/StorageKeySection.js +101 -0
  73. package/lib/module/storage/components/StorageKeyStats.js +340 -0
  74. package/lib/module/storage/components/StorageModalWithTabs.js +867 -0
  75. package/lib/module/storage/components/StorageSection.js +40 -0
  76. package/lib/module/storage/hooks/useAsyncStorageKeys.js +121 -0
  77. package/lib/module/storage/hooks/useMMKVInstances.js +216 -0
  78. package/lib/module/storage/hooks/useMMKVKeys.js +359 -0
  79. package/lib/module/storage/hooks/useTickEverySecond.js +18 -0
  80. package/lib/module/storage/index.js +25 -0
  81. package/lib/module/storage/types.js +3 -0
  82. package/lib/module/storage/utils/AsyncStorageListener.js +500 -0
  83. package/lib/module/storage/utils/MMKVInstanceRegistry.js +196 -0
  84. package/lib/module/storage/utils/MMKVListener.js +367 -0
  85. package/lib/module/storage/utils/clearAllStorage.js +42 -0
  86. package/lib/module/storage/utils/index.js +22 -0
  87. package/lib/module/storage/utils/lineDiff.js +359 -0
  88. package/lib/module/storage/utils/mmkvAvailability.js +56 -0
  89. package/lib/module/storage/utils/mmkvTypeDetection.js +133 -0
  90. package/lib/module/storage/utils/objectDiff.js +153 -0
  91. package/lib/module/storage/utils/safeAsyncStorage.js +134 -0
  92. package/lib/module/storage/utils/storageActionHelpers.js +42 -0
  93. package/lib/module/storage/utils/storageQueryUtils.js +30 -0
  94. package/lib/module/storage/utils/valueType.js +14 -0
  95. package/lib/typescript/index.d.ts +3 -0
  96. package/lib/typescript/index.d.ts.map +1 -0
  97. package/lib/typescript/preset.d.ts +90 -0
  98. package/lib/typescript/preset.d.ts.map +1 -0
  99. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts +18 -0
  100. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +1 -0
  101. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts +7 -0
  102. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +1 -0
  103. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts +12 -0
  104. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts.map +1 -0
  105. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts +13 -0
  106. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +1 -0
  107. package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts +64 -0
  108. package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +1 -0
  109. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts +16 -0
  110. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -0
  111. package/lib/typescript/storage/components/GameUIStorageStats.d.ts +7 -0
  112. package/lib/typescript/storage/components/GameUIStorageStats.d.ts.map +1 -0
  113. package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts +42 -0
  114. package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +1 -0
  115. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts +35 -0
  116. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +1 -0
  117. package/lib/typescript/storage/components/SelectionActionBar.d.ts +21 -0
  118. package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +1 -0
  119. package/lib/typescript/storage/components/StorageActionButtons.d.ts +21 -0
  120. package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +1 -0
  121. package/lib/typescript/storage/components/StorageActions.d.ts +10 -0
  122. package/lib/typescript/storage/components/StorageActions.d.ts.map +1 -0
  123. package/lib/typescript/storage/components/StorageBrowserMode.d.ts +18 -0
  124. package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +1 -0
  125. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts +40 -0
  126. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -0
  127. package/lib/typescript/storage/components/StorageEventFilterView.d.ts +11 -0
  128. package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +1 -0
  129. package/lib/typescript/storage/components/StorageEventListener.d.ts +6 -0
  130. package/lib/typescript/storage/components/StorageEventListener.d.ts.map +1 -0
  131. package/lib/typescript/storage/components/StorageEventsSection.d.ts +7 -0
  132. package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +1 -0
  133. package/lib/typescript/storage/components/StorageFilterCards.d.ts +36 -0
  134. package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +1 -0
  135. package/lib/typescript/storage/components/StorageFilterViewV2.d.ts +9 -0
  136. package/lib/typescript/storage/components/StorageFilterViewV2.d.ts.map +1 -0
  137. package/lib/typescript/storage/components/StorageKeyCard.d.ts +17 -0
  138. package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +1 -0
  139. package/lib/typescript/storage/components/StorageKeyRow.d.ts +15 -0
  140. package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -0
  141. package/lib/typescript/storage/components/StorageKeySection.d.ts +25 -0
  142. package/lib/typescript/storage/components/StorageKeySection.d.ts.map +1 -0
  143. package/lib/typescript/storage/components/StorageKeyStats.d.ts +15 -0
  144. package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -0
  145. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts +13 -0
  146. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -0
  147. package/lib/typescript/storage/components/StorageSection.d.ts +10 -0
  148. package/lib/typescript/storage/components/StorageSection.d.ts.map +1 -0
  149. package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts +10 -0
  150. package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +1 -0
  151. package/lib/typescript/storage/hooks/useMMKVInstances.d.ts +114 -0
  152. package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +1 -0
  153. package/lib/typescript/storage/hooks/useMMKVKeys.d.ts +94 -0
  154. package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +1 -0
  155. package/lib/typescript/storage/hooks/useTickEverySecond.d.ts +6 -0
  156. package/lib/typescript/storage/hooks/useTickEverySecond.d.ts.map +1 -0
  157. package/lib/typescript/storage/index.d.ts +15 -0
  158. package/lib/typescript/storage/index.d.ts.map +1 -0
  159. package/lib/typescript/storage/types.d.ts +41 -0
  160. package/lib/typescript/storage/types.d.ts.map +1 -0
  161. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts +195 -0
  162. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +1 -0
  163. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts +224 -0
  164. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +1 -0
  165. package/lib/typescript/storage/utils/MMKVListener.d.ts +218 -0
  166. package/lib/typescript/storage/utils/MMKVListener.d.ts.map +1 -0
  167. package/lib/typescript/storage/utils/clearAllStorage.d.ts +11 -0
  168. package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +1 -0
  169. package/lib/typescript/storage/utils/index.d.ts +8 -0
  170. package/lib/typescript/storage/utils/index.d.ts.map +1 -0
  171. package/lib/typescript/storage/utils/lineDiff.d.ts +34 -0
  172. package/lib/typescript/storage/utils/lineDiff.d.ts.map +1 -0
  173. package/lib/typescript/storage/utils/mmkvAvailability.d.ts +23 -0
  174. package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +1 -0
  175. package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts +71 -0
  176. package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +1 -0
  177. package/lib/typescript/storage/utils/objectDiff.d.ts +35 -0
  178. package/lib/typescript/storage/utils/objectDiff.d.ts.map +1 -0
  179. package/lib/typescript/storage/utils/safeAsyncStorage.d.ts +56 -0
  180. package/lib/typescript/storage/utils/safeAsyncStorage.d.ts.map +1 -0
  181. package/lib/typescript/storage/utils/storageActionHelpers.d.ts +5 -0
  182. package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +1 -0
  183. package/lib/typescript/storage/utils/storageQueryUtils.d.ts +6 -0
  184. package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +1 -0
  185. package/lib/typescript/storage/utils/valueType.d.ts +3 -0
  186. package/lib/typescript/storage/utils/valueType.d.ts.map +1 -0
  187. 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
+ });