@buoy-gg/storage 7.0.3 → 7.0.5

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 (148) hide show
  1. package/lib/commonjs/index.js +77 -1
  2. package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +10 -3
  3. package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +26 -8
  4. package/lib/commonjs/storage/components/GameUIStorageBrowser.js +263 -115
  5. package/lib/commonjs/storage/components/GameUIStorageStats.js +7 -7
  6. package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -1
  7. package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -1
  8. package/lib/commonjs/storage/components/SelectionActionBar.js +2 -36
  9. package/lib/commonjs/storage/components/StorageActions.js +6 -6
  10. package/lib/commonjs/storage/components/StorageBrowserMode.js +16 -2
  11. package/lib/commonjs/storage/components/StorageEventDetailContent.js +106 -149
  12. package/lib/commonjs/storage/components/StorageEventListener.js +13 -13
  13. package/lib/commonjs/storage/components/StorageFilterCards.js +13 -135
  14. package/lib/commonjs/storage/components/StorageKeyCard.js +1 -1
  15. package/lib/commonjs/storage/components/StorageKeyEditorScreen.js +392 -0
  16. package/lib/commonjs/storage/components/StorageKeyRow.js +53 -15
  17. package/lib/commonjs/storage/components/StorageKeySection.js +10 -4
  18. package/lib/commonjs/storage/components/StorageKeyStats.js +10 -10
  19. package/lib/commonjs/storage/components/StorageModalWithTabs.js +272 -129
  20. package/lib/commonjs/storage/components/StorageScalarKeyEditor.js +46 -0
  21. package/lib/commonjs/storage/components/StorageTypeFilterBar.js +141 -0
  22. package/lib/commonjs/storage/components/StorageValueEditModal.js +361 -0
  23. package/lib/commonjs/storage/hooks/useKeyEditor.js +104 -0
  24. package/lib/commonjs/storage/hooks/useMeasuredWidth.js +74 -0
  25. package/lib/commonjs/storage/hooks/useSecureStoreKeys.js +70 -15
  26. package/lib/commonjs/storage/hooks/useTreeDraft.js +107 -0
  27. package/lib/commonjs/storage/index.js +29 -0
  28. package/lib/commonjs/storage/stores/storageEventStore.js +4 -2
  29. package/lib/commonjs/storage/sync/storageSyncAdapter.js +125 -3
  30. package/lib/commonjs/storage/utils/AsyncStorageListener.js +76 -12
  31. package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +10 -9
  32. package/lib/commonjs/storage/utils/MMKVListener.js +40 -4
  33. package/lib/commonjs/storage/utils/SecureStoreRegistry.js +52 -1
  34. package/lib/commonjs/storage/utils/deleteStorageKeys.js +53 -0
  35. package/lib/commonjs/storage/utils/index.js +13 -0
  36. package/lib/commonjs/storage/utils/lineDiff.js +21 -354
  37. package/lib/commonjs/storage/utils/setStorageValue.js +218 -0
  38. package/lib/commonjs/storage/utils/storageBrowserRefresh.js +49 -0
  39. package/lib/commonjs/storage/utils/storageOps.js +53 -0
  40. package/lib/commonjs/storage/utils/storageTimeTravelUtils.js +60 -38
  41. package/lib/commonjs/storage/utils/valueType.js +24 -0
  42. package/lib/module/index.js +18 -1
  43. package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +10 -3
  44. package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +26 -8
  45. package/lib/module/storage/components/GameUIStorageBrowser.js +266 -118
  46. package/lib/module/storage/components/GameUIStorageStats.js +7 -7
  47. package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -1
  48. package/lib/module/storage/components/MMKVInstanceSelector.js +1 -1
  49. package/lib/module/storage/components/SelectionActionBar.js +2 -36
  50. package/lib/module/storage/components/StorageActions.js +7 -7
  51. package/lib/module/storage/components/StorageBrowserMode.js +16 -2
  52. package/lib/module/storage/components/StorageEventDetailContent.js +110 -151
  53. package/lib/module/storage/components/StorageEventListener.js +14 -14
  54. package/lib/module/storage/components/StorageFilterCards.js +13 -135
  55. package/lib/module/storage/components/StorageKeyCard.js +1 -1
  56. package/lib/module/storage/components/StorageKeyEditorScreen.js +388 -0
  57. package/lib/module/storage/components/StorageKeyRow.js +55 -17
  58. package/lib/module/storage/components/StorageKeySection.js +11 -5
  59. package/lib/module/storage/components/StorageKeyStats.js +11 -10
  60. package/lib/module/storage/components/StorageModalWithTabs.js +272 -130
  61. package/lib/module/storage/components/StorageScalarKeyEditor.js +42 -0
  62. package/lib/module/storage/components/StorageTypeFilterBar.js +136 -0
  63. package/lib/module/storage/components/StorageValueEditModal.js +357 -0
  64. package/lib/module/storage/hooks/useKeyEditor.js +100 -0
  65. package/lib/module/storage/hooks/useMeasuredWidth.js +71 -0
  66. package/lib/module/storage/hooks/useSecureStoreKeys.js +71 -16
  67. package/lib/module/storage/hooks/useTreeDraft.js +103 -0
  68. package/lib/module/storage/index.js +3 -0
  69. package/lib/module/storage/stores/storageEventStore.js +4 -2
  70. package/lib/module/storage/sync/storageSyncAdapter.js +125 -3
  71. package/lib/module/storage/utils/AsyncStorageListener.js +76 -12
  72. package/lib/module/storage/utils/MMKVInstanceRegistry.js +8 -7
  73. package/lib/module/storage/utils/MMKVListener.js +40 -4
  74. package/lib/module/storage/utils/SecureStoreRegistry.js +52 -1
  75. package/lib/module/storage/utils/deleteStorageKeys.js +49 -0
  76. package/lib/module/storage/utils/index.js +3 -0
  77. package/lib/module/storage/utils/lineDiff.js +7 -354
  78. package/lib/module/storage/utils/setStorageValue.js +209 -0
  79. package/lib/module/storage/utils/storageBrowserRefresh.js +44 -0
  80. package/lib/module/storage/utils/storageOps.js +46 -0
  81. package/lib/module/storage/utils/storageTimeTravelUtils.js +61 -40
  82. package/lib/module/storage/utils/valueType.js +23 -0
  83. package/lib/typescript/index.d.ts +12 -1
  84. package/lib/typescript/index.d.ts.map +1 -1
  85. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts +4 -1
  86. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +1 -1
  87. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts +7 -1
  88. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +1 -1
  89. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts +27 -1
  90. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -1
  91. package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +1 -1
  92. package/lib/typescript/storage/components/StorageBrowserMode.d.ts +17 -1
  93. package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +1 -1
  94. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts +4 -1
  95. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -1
  96. package/lib/typescript/storage/components/StorageFilterCards.d.ts +9 -3
  97. package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +1 -1
  98. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts +42 -0
  99. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts.map +1 -0
  100. package/lib/typescript/storage/components/StorageKeyRow.d.ts +17 -0
  101. package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -1
  102. package/lib/typescript/storage/components/StorageKeySection.d.ts +7 -1
  103. package/lib/typescript/storage/components/StorageKeySection.d.ts.map +1 -1
  104. package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -1
  105. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts +28 -1
  106. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -1
  107. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts +24 -0
  108. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts.map +1 -0
  109. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts +29 -0
  110. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +1 -0
  111. package/lib/typescript/storage/components/StorageValueEditModal.d.ts +36 -0
  112. package/lib/typescript/storage/components/StorageValueEditModal.d.ts.map +1 -0
  113. package/lib/typescript/storage/hooks/useKeyEditor.d.ts +51 -0
  114. package/lib/typescript/storage/hooks/useKeyEditor.d.ts.map +1 -0
  115. package/lib/typescript/storage/hooks/useMeasuredWidth.d.ts +37 -0
  116. package/lib/typescript/storage/hooks/useMeasuredWidth.d.ts.map +1 -0
  117. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts +8 -1
  118. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +1 -1
  119. package/lib/typescript/storage/hooks/useTreeDraft.d.ts +67 -0
  120. package/lib/typescript/storage/hooks/useTreeDraft.d.ts.map +1 -0
  121. package/lib/typescript/storage/index.d.ts +2 -0
  122. package/lib/typescript/storage/index.d.ts.map +1 -1
  123. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts +41 -0
  124. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +1 -1
  125. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts +15 -0
  126. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +1 -1
  127. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +1 -1
  128. package/lib/typescript/storage/utils/MMKVListener.d.ts +7 -0
  129. package/lib/typescript/storage/utils/MMKVListener.d.ts.map +1 -1
  130. package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts +20 -0
  131. package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts.map +1 -1
  132. package/lib/typescript/storage/utils/deleteStorageKeys.d.ts +27 -0
  133. package/lib/typescript/storage/utils/deleteStorageKeys.d.ts.map +1 -0
  134. package/lib/typescript/storage/utils/index.d.ts +1 -0
  135. package/lib/typescript/storage/utils/index.d.ts.map +1 -1
  136. package/lib/typescript/storage/utils/lineDiff.d.ts +7 -31
  137. package/lib/typescript/storage/utils/lineDiff.d.ts.map +1 -1
  138. package/lib/typescript/storage/utils/setStorageValue.d.ts +64 -0
  139. package/lib/typescript/storage/utils/setStorageValue.d.ts.map +1 -0
  140. package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts +28 -0
  141. package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts.map +1 -0
  142. package/lib/typescript/storage/utils/storageOps.d.ts +25 -0
  143. package/lib/typescript/storage/utils/storageOps.d.ts.map +1 -0
  144. package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts +15 -5
  145. package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts.map +1 -1
  146. package/lib/typescript/storage/utils/valueType.d.ts +13 -0
  147. package/lib/typescript/storage/utils/valueType.d.ts.map +1 -1
  148. package/package.json +5 -5
@@ -19,10 +19,17 @@ function StorageBrowserMode({
19
19
  searchQuery = "",
20
20
  storageDataRef,
21
21
  eventCountByKey,
22
+ lastWriteByKey,
22
23
  onViewHistory,
23
24
  enabledStorageTypes,
25
+ statusFilter,
26
+ onStatusFilterChange,
27
+ onStatusCountsChange,
24
28
  pinnedKeys,
25
- onTogglePin
29
+ onTogglePin,
30
+ applySafeAreaInset,
31
+ storageTypeFilter,
32
+ onStorageTypeFilterChange
26
33
  }) {
27
34
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_GameUIStorageBrowser.GameUIStorageBrowser, {
28
35
  requiredStorageKeys: requiredStorageKeys,
@@ -33,9 +40,16 @@ function StorageBrowserMode({
33
40
  searchQuery: searchQuery,
34
41
  storageDataRef: storageDataRef,
35
42
  eventCountByKey: eventCountByKey,
43
+ lastWriteByKey: lastWriteByKey,
36
44
  onViewHistory: onViewHistory,
37
45
  enabledStorageTypes: enabledStorageTypes,
46
+ statusFilter: statusFilter,
47
+ onStatusFilterChange: onStatusFilterChange,
48
+ onStatusCountsChange: onStatusCountsChange,
38
49
  pinnedKeys: pinnedKeys,
39
- onTogglePin: onTogglePin
50
+ onTogglePin: onTogglePin,
51
+ applySafeAreaInset: applySafeAreaInset,
52
+ storageTypeFilter: storageTypeFilter,
53
+ onStorageTypeFilterChange: onStorageTypeFilterChange
40
54
  });
41
55
  }
@@ -10,7 +10,7 @@ var _react = require("react");
10
10
  var _asyncStorage = _interopRequireDefault(require("@react-native-async-storage/async-storage"));
11
11
  var _sharedUi = require("@buoy-gg/shared-ui");
12
12
  var _license = require("@buoy-gg/license");
13
- var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
13
+ var _lineDiff = require("../utils/lineDiff");
14
14
  var _ThemedSplitView = require("./DiffViewer/modes/ThemedSplitView");
15
15
  var _diffThemes = require("./DiffViewer/themes/diffThemes");
16
16
  var _TreeDiffViewer = require("./DiffViewer/TreeDiffViewer");
@@ -25,6 +25,36 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
25
25
  * Detail view for storage events using the shared EventHistoryViewer component.
26
26
  */
27
27
 
28
+ /**
29
+ * Compare-bar index for "the state before the oldest event".
30
+ *
31
+ * Not an event — it's reconstructed from that event's own `prevValue`, which
32
+ * every write records. Without it a key's first event had nothing to diff
33
+ * against and both panes showed the same value.
34
+ */const ORIGIN_INDEX = -1;
35
+
36
+ /** Compare-bar copy for each origin state. Kept in sync with the Flutter port. */
37
+ const ORIGIN_LABELS = {
38
+ prior: {
39
+ label: "BEFORE #1",
40
+ timestamp: "value before first event",
41
+ relativeTime: "not captured",
42
+ badge: "PRIOR"
43
+ },
44
+ absent: {
45
+ label: "NO PRIOR VALUE",
46
+ timestamp: "key did not exist",
47
+ relativeTime: "created here",
48
+ badge: "ABSENT"
49
+ },
50
+ scanned: {
51
+ label: "ALREADY PRESENT",
52
+ timestamp: "value found at startup",
53
+ relativeTime: "not a write",
54
+ badge: "SCANNED"
55
+ }
56
+ };
57
+
28
58
  // Unified storage event type (supports both AsyncStorage and MMKV)
29
59
 
30
60
  /**
@@ -86,12 +116,16 @@ function StorageEventDetailContent({
86
116
  const isPro = (0, _license.useIsPro)();
87
117
  const [showProModal, setShowProModal] = (0, _react.useState)(false);
88
118
 
89
- // View state
90
- const [activeView, setActiveView] = (0, _react.useState)("current");
91
- const [diffMode, setDiffMode] = (0, _react.useState)("tree");
119
+ // There is only the diff view now. The current stored value is what the Keys
120
+ // table shows — repeating it behind a toggle here meant two places to look for
121
+ // one fact, and the toggle was the first thing between you and the diff you
122
+ // opened this screen for.
123
+ const [diffMode, setDiffMode] = (0, _react.useState)("split");
92
124
 
93
125
  // Compare indices for diff view
94
- const [leftIndex, setLeftIndex] = (0, _react.useState)(Math.max(0, selectedEventIndex - 1));
126
+ // Matches what the sync effect below computes, so the first frame doesn't
127
+ // briefly pair the oldest event with itself.
128
+ const [leftIndex, setLeftIndex] = (0, _react.useState)(Math.max(ORIGIN_INDEX, selectedEventIndex - 1));
95
129
  const [rightIndex, setRightIndex] = (0, _react.useState)(selectedEventIndex);
96
130
 
97
131
  // Track if preferences have been loaded
@@ -106,10 +140,6 @@ function StorageEventDetailContent({
106
140
  if (hasLoadedPreferences.current) return;
107
141
  const loadPreferences = async () => {
108
142
  try {
109
- const savedDetailView = await _asyncStorage.default.getItem(_sharedUi.devToolsStorageKeys.storage.detailView());
110
- if (savedDetailView === "current" || savedDetailView === "diff") {
111
- setActiveView(savedDetailView);
112
- }
113
143
  const savedDiffMode = await _asyncStorage.default.getItem(_sharedUi.devToolsStorageKeys.storage.diffViewerMode());
114
144
  if (savedDiffMode === "split" || savedDiffMode === "tree") {
115
145
  setDiffMode(savedDiffMode);
@@ -122,24 +152,15 @@ function StorageEventDetailContent({
122
152
  loadPreferences();
123
153
  }, []);
124
154
 
125
- // Keep compare indices synced to selection
155
+ // Keep compare indices synced to selection. Left may land on ORIGIN_INDEX,
156
+ // which is not an event — it's the state the oldest event overwrote.
126
157
  (0, _react.useEffect)(() => {
127
158
  const newRight = Math.min(totalEvents - 1, Math.max(0, selectedEventIndex));
128
- const newLeft = Math.max(0, Math.min(newRight - 1, selectedEventIndex - 1));
159
+ const newLeft = Math.max(ORIGIN_INDEX, Math.min(newRight - 1, selectedEventIndex - 1));
129
160
  setLeftIndex(newLeft);
130
161
  setRightIndex(newRight);
131
162
  }, [selectedEventIndex, totalEvents]);
132
163
 
133
- // Save view preference when changed
134
- const handleViewChange = (0, _react.useCallback)(async view => {
135
- setActiveView(view);
136
- try {
137
- await _asyncStorage.default.setItem(_sharedUi.devToolsStorageKeys.storage.detailView(), view);
138
- } catch {
139
- // Failed to save preference
140
- }
141
- }, []);
142
-
143
164
  // Save diff mode preference when changed
144
165
  const handleDiffModeChange = (0, _react.useCallback)(async mode => {
145
166
  setDiffMode(mode);
@@ -152,18 +173,53 @@ function StorageEventDetailContent({
152
173
 
153
174
  // Get current event
154
175
  const selectedEvent = navigationItems[selectedEventIndex];
155
- const valueToShow = selectedEvent?.data?.value ?? conversation.currentValue;
156
176
  const action = selectedEvent?.action;
157
177
  // Compute type from the parsed value so it matches what we actually render
158
- const valueType = getValueType((0, _sharedUi.parseValue)(valueToShow));
159
- const actionColor = getActionColor(action || "");
160
178
 
161
- // Get events for diff comparison
162
- const leftEvent = navigationItems[Math.max(0, Math.min(totalEvents - 1, leftIndex))];
179
+ // Get events for diff comparison. leftIndex === ORIGIN_INDEX means "the state
180
+ // before the oldest event", which has no event object of its own.
181
+ const isOriginLeft = leftIndex === ORIGIN_INDEX;
182
+ const leftEvent = isOriginLeft ? undefined : navigationItems[Math.max(0, Math.min(totalEvents - 1, leftIndex))];
163
183
  const rightEvent = navigationItems[Math.max(0, Math.min(totalEvents - 1, rightIndex))];
164
184
 
185
+ // Every write records the value it overwrote (for time travel), so even the
186
+ // very first event can be diffed against what was actually there. Three
187
+ // distinct origins, and conflating them would misinform:
188
+ // PRIOR — the write replaced a real value (including `[]`, `""`, `null`)
189
+ // ABSENT — the write created the key; there was nothing before it
190
+ // SCANNED — not a write at all, just the startup snapshot of a key that
191
+ // already existed, so nothing changed at this event
192
+ const originKind = (0, _react.useMemo)(() => {
193
+ const data = rightEvent?.data;
194
+ if (data?.initialScan) return "scanned";
195
+ return data?.prevValue === null || data?.prevValue === undefined ? "absent" : "prior";
196
+ }, [rightEvent]);
197
+ const originValue = (0, _react.useMemo)(() => {
198
+ if (originKind === "absent") return _lineDiff.ABSENT_VALUE;
199
+ // A scanned key was already holding the event's own value, so diffing
200
+ // against it correctly reports no change.
201
+ if (originKind === "scanned") return (0, _sharedUi.parseValue)(rightEvent?.data?.value);
202
+ return (0, _sharedUi.parseValue)(rightEvent?.data?.prevValue);
203
+ }, [originKind, rightEvent]);
204
+
165
205
  // Create event display info for compare bar
166
- const leftEventInfo = (0, _react.useMemo)(() => ({
206
+ const leftEventInfo = (0, _react.useMemo)(() => isOriginLeft ? {
207
+ index: ORIGIN_INDEX,
208
+ label: ORIGIN_LABELS[originKind].label,
209
+ timestamp: ORIGIN_LABELS[originKind].timestamp,
210
+ relativeTime: ORIGIN_LABELS[originKind].relativeTime,
211
+ badge: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
212
+ style: [styles.actionBadgeSmall, {
213
+ backgroundColor: `${_sharedUi.macOSColors.text.muted}20`
214
+ }],
215
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
216
+ style: [styles.actionTextSmall, {
217
+ color: _sharedUi.macOSColors.text.muted
218
+ }],
219
+ children: ORIGIN_LABELS[originKind].badge
220
+ })
221
+ })
222
+ } : {
167
223
  index: leftIndex,
168
224
  label: `#${leftIndex + 1} / ${totalEvents}`,
169
225
  timestamp: leftEvent ? formatTimeWithMs(leftEvent.timestamp) : "",
@@ -179,7 +235,7 @@ function StorageEventDetailContent({
179
235
  children: (0, _storageActionHelpers.translateStorageAction)(leftEvent.action)
180
236
  })
181
237
  }) : undefined
182
- }), [leftIndex, leftEvent, totalEvents]);
238
+ }, [leftIndex, leftEvent, totalEvents, isOriginLeft, originKind]);
183
239
  const rightEventInfo = (0, _react.useMemo)(() => ({
184
240
  index: rightIndex,
185
241
  label: `#${rightIndex + 1} / ${totalEvents}`,
@@ -209,7 +265,8 @@ function StorageEventDetailContent({
209
265
 
210
266
  // Navigation handlers for compare bar
211
267
  const handleLeftPrevious = (0, _react.useCallback)(() => {
212
- if (leftIndex > 0) {
268
+ // Stops at ORIGIN_INDEX — one step past event #1 is the state it overwrote.
269
+ if (leftIndex > ORIGIN_INDEX) {
213
270
  setLeftIndex(leftIndex - 1);
214
271
  }
215
272
  }, [leftIndex]);
@@ -229,54 +286,11 @@ function StorageEventDetailContent({
229
286
  }
230
287
  }, [rightIndex, totalEvents]);
231
288
 
232
- // Render current value view
233
- const renderCurrentView = (0, _react.useCallback)(() => {
234
- const parsed = (0, _sharedUi.parseValue)(valueToShow);
235
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
236
- style: styles.contentCard,
237
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
238
- style: styles.valueHeader,
239
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
240
- style: styles.valueLabel,
241
- children: "CURRENT VALUE"
242
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
243
- style: styles.valueHeaderBadges,
244
- children: [action ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
245
- style: [styles.actionBadge, {
246
- backgroundColor: `${actionColor}20`
247
- }],
248
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
249
- style: [styles.actionText, {
250
- color: actionColor
251
- }],
252
- children: (0, _storageActionHelpers.translateStorageAction)(action)
253
- })
254
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
255
- style: styles.typeBadge,
256
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
257
- style: styles.typeText,
258
- children: valueType.toUpperCase()
259
- })
260
- })]
261
- })]
262
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
263
- style: styles.dataViewerContainer,
264
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
265
- title: "",
266
- data: parsed,
267
- showTypeFilter: true,
268
- rawMode: true,
269
- initialExpanded: true
270
- })
271
- })]
272
- });
273
- }, [valueToShow, action, actionColor, valueType]);
274
-
275
289
  // Memoized so the diff viewers don't see new oldValue/newValue refs on every
276
290
  // re-render. parseValue runs JSON.parse, which would otherwise produce fresh
277
291
  // object identities every time and force expensive recomputations downstream
278
292
  // (line diff, tree diff, expansion-state effects, etc.).
279
- const previousValue = (0, _react.useMemo)(() => (0, _sharedUi.parseValue)(leftEvent?.data?.value ?? null), [leftEvent]);
293
+ const previousValue = (0, _react.useMemo)(() => isOriginLeft ? originValue : (0, _sharedUi.parseValue)(leftEvent?.data?.value ?? null), [isOriginLeft, originValue, leftEvent]);
280
294
  const currentValue = (0, _react.useMemo)(() => (0, _sharedUi.parseValue)(rightEvent?.data?.value), [rightEvent]);
281
295
 
282
296
  // Render diff content
@@ -288,12 +302,17 @@ function StorageEventDetailContent({
288
302
  differences: SPLIT_VIEW_DIFFERENCES,
289
303
  theme: _diffThemes.diffThemes.devToolsDefault,
290
304
  options: SPLIT_VIEW_OPTIONS,
291
- showThemeName: false
305
+ showThemeName: false,
306
+ scrollEnabled: false
292
307
  });
293
308
  }
309
+
310
+ // Inline: the whole diff section scrolls as one page (see
311
+ // `scrollDiffSection` below), so the tree must not scroll itself.
294
312
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_TreeDiffViewer.TreeDiffViewer, {
295
313
  oldValue: previousValue,
296
- newValue: currentValue
314
+ newValue: currentValue,
315
+ scrollEnabled: false
297
316
  });
298
317
  }, [previousValue, currentValue, diffMode]);
299
318
 
@@ -366,25 +385,23 @@ function StorageEventDetailContent({
366
385
  onPress: handleCopy
367
386
  })]
368
387
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventHistoryViewer
369
- // View Toggle
388
+ // Diff only: no `renderCurrentView`, so the viewer drops the toggle
389
+ // cards entirely rather than showing a one-option switch.
370
390
  , {
371
- activeView: activeView,
372
- onViewChange: handleViewChange,
373
- currentViewLabel: "CURRENT VALUE",
374
- currentViewDescription: "View the current stored value",
375
- currentViewIcon: _sharedUi.Database,
391
+ activeView: "diff",
376
392
  diffViewLabel: "DIFF VIEW",
377
393
  diffViewDescription: "Compare changes between versions",
378
394
  diffViewIcon: _sharedUi.GitBranch
379
- // Current View
380
- ,
381
- renderCurrentView: renderCurrentView
382
395
  // Diff View
383
396
  ,
384
397
  diffModeTabs: diffModeTabs,
385
398
  activeDiffMode: diffMode,
386
399
  onDiffModeChange: handleDiffModeChange,
387
400
  renderDiffContent: renderDiffContent
401
+ // Both diff modes render inline now, so the whole section scrolls as
402
+ // one page rather than confining the rows to a nested pane.
403
+ ,
404
+ scrollDiffSection: true
388
405
  // Compare Bar
389
406
  ,
390
407
  leftEvent: leftEventInfo,
@@ -394,7 +411,7 @@ function StorageEventDetailContent({
394
411
  onLeftNext: handleLeftNext,
395
412
  onRightPrevious: handleRightPrevious,
396
413
  onRightNext: handleRightNext,
397
- canLeftPrevious: leftIndex > 0,
414
+ canLeftPrevious: leftIndex > ORIGIN_INDEX,
398
415
  canLeftNext: leftIndex < rightIndex - 1,
399
416
  canRightPrevious: rightIndex > leftIndex + 1,
400
417
  canRightNext: rightIndex < totalEvents - 1
@@ -421,7 +438,8 @@ function StorageEventDetailContent({
421
438
  function StorageEventDetailFooter({
422
439
  conversation,
423
440
  selectedEventIndex = 0,
424
- onEventIndexChange = () => {}
441
+ onEventIndexChange = () => {},
442
+ applySafeAreaInset = true
425
443
  }) {
426
444
  const navigationItems = conversation.events.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
427
445
  const totalEvents = navigationItems.length;
@@ -431,7 +449,8 @@ function StorageEventDetailFooter({
431
449
  onPrevious: () => onEventIndexChange(Math.max(0, selectedEventIndex - 1)),
432
450
  onNext: () => onEventIndexChange(Math.min(totalEvents - 1, selectedEventIndex + 1)),
433
451
  itemLabel: "Event",
434
- subtitle: (0, _sharedUi.formatRelativeTime)(navigationItems[selectedEventIndex]?.timestamp)
452
+ subtitle: (0, _sharedUi.formatRelativeTime)(navigationItems[selectedEventIndex]?.timestamp),
453
+ applySafeAreaInset: applySafeAreaInset
435
454
  });
436
455
  }
437
456
  const styles = _reactNative.StyleSheet.create({
@@ -448,63 +467,6 @@ const styles = _reactNative.StyleSheet.create({
448
467
  borderBottomColor: _sharedUi.buoyColors.border
449
468
  },
450
469
  // Content Card
451
- contentCard: {
452
- backgroundColor: _sharedUi.macOSColors.background.card,
453
- borderRadius: 14,
454
- padding: 14,
455
- borderWidth: 1,
456
- borderColor: _sharedUi.macOSColors.border.default,
457
- shadowColor: _sharedUi.macOSColors.semantic.info,
458
- shadowOffset: {
459
- width: 0,
460
- height: 2
461
- },
462
- shadowOpacity: 0.04,
463
- shadowRadius: 16,
464
- elevation: 2
465
- },
466
- valueHeader: {
467
- flexDirection: "row",
468
- alignItems: "center",
469
- justifyContent: "space-between",
470
- marginBottom: 8
471
- },
472
- valueLabel: {
473
- fontSize: 10,
474
- color: _sharedUi.macOSColors.text.secondary,
475
- fontFamily: "monospace",
476
- letterSpacing: 0.5,
477
- fontWeight: "600",
478
- textTransform: "uppercase"
479
- },
480
- valueHeaderBadges: {
481
- flexDirection: "row",
482
- alignItems: "center",
483
- gap: 6
484
- },
485
- actionBadge: {
486
- paddingHorizontal: 8,
487
- paddingVertical: 2,
488
- borderRadius: 4
489
- },
490
- actionText: {
491
- fontSize: 9,
492
- fontWeight: "700",
493
- fontFamily: "monospace",
494
- letterSpacing: 0.3
495
- },
496
- typeBadge: {
497
- paddingHorizontal: 8,
498
- paddingVertical: 2,
499
- borderRadius: 4,
500
- backgroundColor: _sharedUi.macOSColors.background.input
501
- },
502
- typeText: {
503
- fontSize: 9,
504
- fontWeight: "600",
505
- color: _sharedUi.macOSColors.text.muted,
506
- fontFamily: "monospace"
507
- },
508
470
  valueBox: {
509
471
  backgroundColor: _sharedUi.macOSColors.background.base,
510
472
  borderRadius: 6,
@@ -528,10 +490,5 @@ const styles = _reactNative.StyleSheet.create({
528
490
  fontSize: 8,
529
491
  fontWeight: "700",
530
492
  fontFamily: "monospace"
531
- },
532
- dataViewerContainer: {
533
- marginTop: -12,
534
- marginHorizontal: -12,
535
- marginBottom: -12
536
493
  }
537
494
  });
@@ -152,7 +152,7 @@ function StorageEventListener() {
152
152
  return "#3B82F6";
153
153
  // Blue for merge
154
154
  default:
155
- return "#6B7280";
155
+ return _sharedUi.macOSColors.text.icon;
156
156
  }
157
157
  };
158
158
  if (!isAsyncStorageAvailable) {
@@ -198,7 +198,7 @@ function StorageEventListener() {
198
198
  disabled: events.length === 0,
199
199
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Trash2, {
200
200
  size: 14,
201
- color: events.length > 0 ? "#6B7280" : "#374151"
201
+ color: events.length > 0 ? _sharedUi.macOSColors.text.icon : _sharedUi.macOSColors.border.toggle
202
202
  })
203
203
  })]
204
204
  })]
@@ -241,10 +241,10 @@ function StorageEventListener() {
241
241
  }
242
242
  const styles = _reactNative.StyleSheet.create({
243
243
  container: {
244
- backgroundColor: "rgba(255, 255, 255, 0.03)",
244
+ backgroundColor: "rgba(128, 128, 128, 0.06)",
245
245
  borderRadius: 8,
246
246
  borderWidth: 1,
247
- borderColor: "rgba(255, 255, 255, 0.08)",
247
+ borderColor: "rgba(128, 128, 128, 0.16)",
248
248
  marginBottom: 12,
249
249
  maxHeight: 200
250
250
  },
@@ -255,7 +255,7 @@ const styles = _reactNative.StyleSheet.create({
255
255
  paddingHorizontal: 12,
256
256
  paddingVertical: 8,
257
257
  borderBottomWidth: 1,
258
- borderBottomColor: "rgba(255, 255, 255, 0.06)"
258
+ borderBottomColor: "rgba(128, 128, 128, 0.12)"
259
259
  },
260
260
  headerLeft: {
261
261
  flexDirection: "row",
@@ -265,7 +265,7 @@ const styles = _reactNative.StyleSheet.create({
265
265
  title: {
266
266
  fontSize: 12,
267
267
  fontWeight: "500",
268
- color: "#9CA3AF",
268
+ color: _sharedUi.buoyColors.textSecondary,
269
269
  textTransform: "uppercase",
270
270
  letterSpacing: 0.5
271
271
  },
@@ -280,7 +280,7 @@ const styles = _reactNative.StyleSheet.create({
280
280
  },
281
281
  statsText: {
282
282
  fontSize: 11,
283
- color: "#6B7280",
283
+ color: _sharedUi.macOSColors.text.icon,
284
284
  fontWeight: "500"
285
285
  },
286
286
  listeningIndicator: {
@@ -298,9 +298,9 @@ const styles = _reactNative.StyleSheet.create({
298
298
  width: 28,
299
299
  height: 28,
300
300
  borderRadius: 6,
301
- backgroundColor: "rgba(255, 255, 255, 0.03)",
301
+ backgroundColor: "rgba(128, 128, 128, 0.06)",
302
302
  borderWidth: 1,
303
- borderColor: "rgba(255, 255, 255, 0.08)",
303
+ borderColor: "rgba(128, 128, 128, 0.16)",
304
304
  alignItems: "center",
305
305
  justifyContent: "center"
306
306
  },
@@ -321,7 +321,7 @@ const styles = _reactNative.StyleSheet.create({
321
321
  },
322
322
  emptyText: {
323
323
  fontSize: 11,
324
- color: "#6B7280",
324
+ color: _sharedUi.macOSColors.text.icon,
325
325
  fontStyle: "italic"
326
326
  },
327
327
  eventItem: {
@@ -331,7 +331,7 @@ const styles = _reactNative.StyleSheet.create({
331
331
  paddingHorizontal: 12,
332
332
  paddingVertical: 6,
333
333
  borderBottomWidth: 1,
334
- borderBottomColor: "rgba(255, 255, 255, 0.03)"
334
+ borderBottomColor: "rgba(128, 128, 128, 0.06)"
335
335
  },
336
336
  eventLeft: {
337
337
  flex: 1,
@@ -347,11 +347,11 @@ const styles = _reactNative.StyleSheet.create({
347
347
  },
348
348
  eventData: {
349
349
  fontSize: 11,
350
- color: "#9CA3AF",
350
+ color: _sharedUi.buoyColors.textSecondary,
351
351
  flex: 1
352
352
  },
353
353
  eventTime: {
354
354
  fontSize: 10,
355
- color: "#6B7280"
355
+ color: _sharedUi.macOSColors.text.icon
356
356
  }
357
357
  });