@buoy-gg/network 7.0.32 → 7.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/index.js +6 -0
- package/lib/commonjs/network/components/NetworkCopySettingsView.js +10 -121
- package/lib/commonjs/network/components/NetworkHeaderLive.js +16 -0
- package/lib/commonjs/network/components/NetworkListScreen.js +34 -46
- package/lib/commonjs/network/components/NetworkModal.js +24 -53
- package/lib/commonjs/network/components/NetworkOverridesScreen.js +11 -2
- package/lib/commonjs/network/components/NetworkSavedScreen.js +19 -38
- package/lib/commonjs/network/hooks/useNetworkEventList.js +7 -4
- package/lib/commonjs/network/sync/networkSyncAdapter.js +8 -0
- package/lib/commonjs/preset.js +6 -21
- package/lib/module/index.js +1 -1
- package/lib/module/network/components/NetworkCopySettingsView.js +13 -124
- package/lib/module/network/components/NetworkHeaderLive.js +15 -0
- package/lib/module/network/components/NetworkListScreen.js +35 -47
- package/lib/module/network/components/NetworkModal.js +26 -55
- package/lib/module/network/components/NetworkOverridesScreen.js +12 -3
- package/lib/module/network/components/NetworkSavedScreen.js +20 -39
- package/lib/module/network/hooks/useNetworkEventList.js +7 -4
- package/lib/module/network/sync/networkSyncAdapter.js +8 -0
- package/lib/module/preset.js +6 -20
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkCopySettingsView.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkHeaderLive.d.ts +11 -0
- package/lib/typescript/network/components/NetworkHeaderLive.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkSavedScreen.d.ts.map +1 -1
- package/lib/typescript/network/hooks/useNetworkEventList.d.ts +11 -0
- package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +1 -1
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts +4 -0
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +1 -1
- package/lib/typescript/preset.d.ts +2 -8
- package/lib/typescript/preset.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/commonjs/index.js
CHANGED
|
@@ -63,6 +63,12 @@ Object.defineProperty(exports, "NetworkEventItemCompact", {
|
|
|
63
63
|
return _NetworkEventItemCompact.NetworkEventItemCompact;
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
|
+
Object.defineProperty(exports, "NetworkHeaderBadgesView", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return _NetworkHeaderLive.NetworkHeaderBadgesView;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
66
72
|
Object.defineProperty(exports, "NetworkModal", {
|
|
67
73
|
enumerable: true,
|
|
68
74
|
get: function () {
|
|
@@ -546,62 +546,16 @@ function NetworkCopySettingsView({
|
|
|
546
546
|
const generatePreviewContent = (0, _react.useCallback)(() => {
|
|
547
547
|
const dataSource = hasLiveData ? events : [mockRequestData];
|
|
548
548
|
const requestCount = dataSource.length;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
style: styles.expandButtonContent,
|
|
560
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Eye, {
|
|
561
|
-
size: 16,
|
|
562
|
-
color: _sharedUi.macOSColors.semantic.info
|
|
563
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
564
|
-
style: styles.expandButtonTextContainer,
|
|
565
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
566
|
-
style: styles.expandButtonTitle,
|
|
567
|
-
children: "Show Preview"
|
|
568
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
569
|
-
style: styles.expandButtonSubtitle,
|
|
570
|
-
children: [requestCount, " request", requestCount !== 1 ? 's' : '', " \u2022 ~", formatBytes(estimatedSize)]
|
|
571
|
-
})]
|
|
572
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronDown, {
|
|
573
|
-
size: 16,
|
|
574
|
-
color: _sharedUi.macOSColors.text.muted
|
|
575
|
-
})]
|
|
576
|
-
})
|
|
577
|
-
}), sizeWarningLevel !== 'none' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
578
|
-
style: [styles.sizeWarning, sizeWarningLevel === 'danger' && styles.sizeWarningDanger],
|
|
579
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertTriangle, {
|
|
580
|
-
size: 12,
|
|
581
|
-
color: warningColor
|
|
582
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
583
|
-
style: [styles.sizeWarningText, {
|
|
584
|
-
color: warningColor
|
|
585
|
-
}],
|
|
586
|
-
children: sizeWarningLevel === 'danger' ? 'Very large payload - may cause performance issues' : 'Large payload - preview may be slow'
|
|
587
|
-
})]
|
|
588
|
-
})]
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// Expanded state - show collapse button + actual content
|
|
593
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
594
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
595
|
-
style: styles.collapseButton,
|
|
596
|
-
onPress: () => setIsPreviewExpanded(false),
|
|
597
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
598
|
-
style: styles.collapseButtonText,
|
|
599
|
-
children: "Hide Preview"
|
|
600
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChevronUp, {
|
|
601
|
-
size: 14,
|
|
602
|
-
color: _sharedUi.macOSColors.text.secondary
|
|
603
|
-
})]
|
|
604
|
-
}), generateExpandedPreviewContent()]
|
|
549
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ExportPreview, {
|
|
550
|
+
expanded: isPreviewExpanded,
|
|
551
|
+
onExpandedChange: setIsPreviewExpanded,
|
|
552
|
+
summary: `${requestCount} request${requestCount !== 1 ? "s" : ""} • ~${formatBytes(estimatedSize)}`,
|
|
553
|
+
warningLevel: sizeWarningLevel,
|
|
554
|
+
warningText: {
|
|
555
|
+
warning: "Large payload - preview may be slow",
|
|
556
|
+
danger: "Very large payload - may cause performance issues"
|
|
557
|
+
},
|
|
558
|
+
renderBody: generateExpandedPreviewContent
|
|
605
559
|
});
|
|
606
560
|
}, [settings, hasLiveData, events, mockRequestData, isPreviewExpanded, estimatedSize, sizeWarningLevel, generateExpandedPreviewContent]);
|
|
607
561
|
|
|
@@ -790,71 +744,6 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
790
744
|
marginRight: 8
|
|
791
745
|
},
|
|
792
746
|
// Collapsible preview styles
|
|
793
|
-
collapsedPreview: {
|
|
794
|
-
gap: 8
|
|
795
|
-
},
|
|
796
|
-
expandButton: {
|
|
797
|
-
backgroundColor: _sharedUi.macOSColors.background.input,
|
|
798
|
-
borderRadius: 8,
|
|
799
|
-
borderWidth: 1,
|
|
800
|
-
borderColor: _sharedUi.macOSColors.border.default,
|
|
801
|
-
padding: 12
|
|
802
|
-
},
|
|
803
|
-
expandButtonContent: {
|
|
804
|
-
flexDirection: 'row',
|
|
805
|
-
alignItems: 'center',
|
|
806
|
-
gap: 10
|
|
807
|
-
},
|
|
808
|
-
expandButtonTextContainer: {
|
|
809
|
-
flex: 1
|
|
810
|
-
},
|
|
811
|
-
expandButtonTitle: {
|
|
812
|
-
fontSize: 13,
|
|
813
|
-
fontWeight: '600',
|
|
814
|
-
color: _sharedUi.macOSColors.text.primary
|
|
815
|
-
},
|
|
816
|
-
expandButtonSubtitle: {
|
|
817
|
-
fontSize: 11,
|
|
818
|
-
color: _sharedUi.macOSColors.text.secondary,
|
|
819
|
-
marginTop: 2
|
|
820
|
-
},
|
|
821
|
-
collapseButton: {
|
|
822
|
-
flexDirection: 'row',
|
|
823
|
-
alignItems: 'center',
|
|
824
|
-
justifyContent: 'center',
|
|
825
|
-
gap: 6,
|
|
826
|
-
paddingVertical: 8,
|
|
827
|
-
marginBottom: 8,
|
|
828
|
-
backgroundColor: _sharedUi.macOSColors.background.hover,
|
|
829
|
-
borderRadius: 6,
|
|
830
|
-
borderWidth: 1,
|
|
831
|
-
borderColor: _sharedUi.macOSColors.border.default
|
|
832
|
-
},
|
|
833
|
-
collapseButtonText: {
|
|
834
|
-
fontSize: 12,
|
|
835
|
-
fontWeight: '500',
|
|
836
|
-
color: _sharedUi.macOSColors.text.secondary
|
|
837
|
-
},
|
|
838
|
-
sizeWarning: {
|
|
839
|
-
flexDirection: 'row',
|
|
840
|
-
alignItems: 'center',
|
|
841
|
-
gap: 6,
|
|
842
|
-
paddingHorizontal: 10,
|
|
843
|
-
paddingVertical: 6,
|
|
844
|
-
backgroundColor: _sharedUi.macOSColors.semantic.warningBackground,
|
|
845
|
-
borderRadius: 6,
|
|
846
|
-
borderWidth: 1,
|
|
847
|
-
borderColor: _sharedUi.macOSColors.semantic.warning + '30'
|
|
848
|
-
},
|
|
849
|
-
sizeWarningDanger: {
|
|
850
|
-
backgroundColor: _sharedUi.macOSColors.semantic.errorBackground,
|
|
851
|
-
borderColor: _sharedUi.macOSColors.semantic.error + '30'
|
|
852
|
-
},
|
|
853
|
-
sizeWarningText: {
|
|
854
|
-
fontSize: 11,
|
|
855
|
-
fontWeight: '500',
|
|
856
|
-
flex: 1
|
|
857
|
-
},
|
|
858
747
|
// Gated container styles for free users
|
|
859
748
|
gatedContainer: {
|
|
860
749
|
flex: 1,
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.NetworkClearButton = NetworkClearButton;
|
|
7
7
|
exports.NetworkDetailPinActions = NetworkDetailPinActions;
|
|
8
8
|
exports.NetworkHeaderBadges = NetworkHeaderBadges;
|
|
9
|
+
exports.NetworkHeaderBadgesView = NetworkHeaderBadgesView;
|
|
9
10
|
exports.NetworkHeaderCopyButton = NetworkHeaderCopyButton;
|
|
10
11
|
exports.NetworkSavedButton = NetworkSavedButton;
|
|
11
12
|
var _reactNative = require("react-native");
|
|
@@ -48,6 +49,21 @@ function NetworkHeaderBadges({
|
|
|
48
49
|
ignoredPatterns,
|
|
49
50
|
paused
|
|
50
51
|
});
|
|
52
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(NetworkHeaderBadgesView, {
|
|
53
|
+
counts: counts,
|
|
54
|
+
activeStatus: activeStatus,
|
|
55
|
+
onToggleStatus: onToggleStatus
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The chips themselves, fed by props — what the parity sheet renders with
|
|
60
|
+
* fixture counts (`NetworkHeaderBadges` reads the live store).
|
|
61
|
+
*/
|
|
62
|
+
function NetworkHeaderBadgesView({
|
|
63
|
+
counts,
|
|
64
|
+
activeStatus,
|
|
65
|
+
onToggleStatus
|
|
66
|
+
}) {
|
|
51
67
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
52
68
|
style: styles.headerChipRow,
|
|
53
69
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
@@ -27,23 +27,6 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
27
27
|
* `paused || !visible` so a hidden list doesn't subscribe at all.
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
function EmptyState({
|
|
31
|
-
isEnabled
|
|
32
|
-
}) {
|
|
33
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
34
|
-
style: styles.emptyState,
|
|
35
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Globe, {
|
|
36
|
-
size: 32,
|
|
37
|
-
color: _sharedUi.macOSColors.text.muted
|
|
38
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
39
|
-
style: styles.emptyTitle,
|
|
40
|
-
children: "No network events"
|
|
41
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
42
|
-
style: styles.emptyText,
|
|
43
|
-
children: isEnabled ? "Network requests will appear here" : "Enable interception to start capturing"
|
|
44
|
-
})]
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
30
|
const keyExtractor = item => item.id;
|
|
48
31
|
|
|
49
32
|
/**
|
|
@@ -164,7 +147,8 @@ function NetworkListScreen({
|
|
|
164
147
|
const {
|
|
165
148
|
visibleEvents,
|
|
166
149
|
hasLockedEvents,
|
|
167
|
-
lockedEventCount
|
|
150
|
+
lockedEventCount,
|
|
151
|
+
totalEvents
|
|
168
152
|
} = (0, _useNetworkEventList.useNetworkEventList)({
|
|
169
153
|
filter,
|
|
170
154
|
ignoredPatterns,
|
|
@@ -226,6 +210,34 @@ function NetworkListScreen({
|
|
|
226
210
|
onLongPress: handleLongPress,
|
|
227
211
|
saved: savedLiveIds.has(item.id)
|
|
228
212
|
});
|
|
213
|
+
|
|
214
|
+
// Which flavour of "nothing here" this is. Pins and overrides render
|
|
215
|
+
// outside the list, so a screen showing only those is not empty at all.
|
|
216
|
+
const renderEmpty = () => {
|
|
217
|
+
// Pins and overrides render outside the list, so a screen showing only
|
|
218
|
+
// those is not empty at all.
|
|
219
|
+
if (pinnedRows.length > 0 || overridden.length > 0) return null;
|
|
220
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
|
|
221
|
+
testID: "buoy-network-empty",
|
|
222
|
+
...(0, _sharedUi.resolveListEmptyState)({
|
|
223
|
+
subject: "requests",
|
|
224
|
+
search: searchText,
|
|
225
|
+
total: totalEvents,
|
|
226
|
+
capturing: isEnabled,
|
|
227
|
+
waiting: {
|
|
228
|
+
// fishing = capture is on and nothing has arrived.
|
|
229
|
+
otto: "fishing",
|
|
230
|
+
title: "No network events",
|
|
231
|
+
message: "Network requests will appear here"
|
|
232
|
+
},
|
|
233
|
+
paused: {
|
|
234
|
+
// paused = capture off. Both are literally what the copy says.
|
|
235
|
+
title: "No network events",
|
|
236
|
+
message: "Enable interception to start capturing"
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
});
|
|
240
|
+
};
|
|
229
241
|
const renderListFooter = () => {
|
|
230
242
|
if (!hasLockedEvents) return null;
|
|
231
243
|
const isSearching = searchText.length > 0;
|
|
@@ -270,10 +282,8 @@ function NetworkListScreen({
|
|
|
270
282
|
showsVerticalScrollIndicator: true
|
|
271
283
|
// Clipped cells falsely fail Detox's hittability check (known
|
|
272
284
|
// RN+Detox issue), so e2e bundles (Metro started with
|
|
273
|
-
// EXPO_PUBLIC_E2E=1) turn clipping off
|
|
274
|
-
// guarded so a non-inlining bundler keeps the prod behavior.
|
|
285
|
+
// EXPO_PUBLIC_E2E=1) turn clipping off — see EVENT_LIST_PRESET.
|
|
275
286
|
,
|
|
276
|
-
removeClippedSubviews: !(typeof process !== "undefined" && process.env?.EXPO_PUBLIC_E2E),
|
|
277
287
|
onEndReachedThreshold: 0.8
|
|
278
288
|
// The list OWNS scrolling (NetworkModal passes
|
|
279
289
|
// disableScrollWrapper while this screen is visible) so FlatList
|
|
@@ -282,24 +292,18 @@ function NetworkListScreen({
|
|
|
282
292
|
// rows: at the store's 500-event cap that measured 17 JS FPS /
|
|
283
293
|
// 133% CPU / 1.4GB vs ~53 JS FPS / 52% / 360MB virtualized
|
|
284
294
|
// (buoy-optimize batch 2026-07-06, batch-1783396983529-6l7w).
|
|
285
|
-
// Window/batch values are the batch's "tuned" winner.
|
|
295
|
+
// Window/batch values are the batch's "tuned" winner (EVENT_LIST_PRESET).
|
|
286
296
|
,
|
|
287
297
|
scrollEnabled: true,
|
|
288
|
-
|
|
289
|
-
maxToRenderPerBatch: 8,
|
|
290
|
-
windowSize: 5,
|
|
291
|
-
updateCellsBatchingPeriod: 50
|
|
298
|
+
..._sharedUi.EVENT_LIST_PRESET,
|
|
292
299
|
// Saving a request from the detail view changes a row's glyph
|
|
293
300
|
// without changing `data`. VirtualizedList is a PureComponent, so
|
|
294
301
|
// the Set has to be declared as a re-render marker rather than
|
|
295
302
|
// relying on `renderItem` getting a fresh identity.
|
|
296
|
-
,
|
|
297
303
|
extraData: savedLiveIds,
|
|
298
304
|
"sentry-label": "ignore network events list",
|
|
299
305
|
ListFooterComponent: renderListFooter
|
|
300
|
-
}) :
|
|
301
|
-
isEnabled: isEnabled
|
|
302
|
-
})]
|
|
306
|
+
}) : renderEmpty()]
|
|
303
307
|
});
|
|
304
308
|
}
|
|
305
309
|
const styles = _reactNative.StyleSheet.create({
|
|
@@ -396,21 +400,5 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
396
400
|
},
|
|
397
401
|
listContent: {
|
|
398
402
|
paddingTop: 8
|
|
399
|
-
},
|
|
400
|
-
emptyState: {
|
|
401
|
-
alignItems: "center",
|
|
402
|
-
paddingVertical: 40
|
|
403
|
-
},
|
|
404
|
-
emptyTitle: {
|
|
405
|
-
color: _sharedUi.macOSColors.text.primary,
|
|
406
|
-
fontSize: 14,
|
|
407
|
-
fontWeight: "600",
|
|
408
|
-
marginTop: 12,
|
|
409
|
-
marginBottom: 6
|
|
410
|
-
},
|
|
411
|
-
emptyText: {
|
|
412
|
-
color: _sharedUi.macOSColors.text.muted,
|
|
413
|
-
fontSize: 12,
|
|
414
|
-
textAlign: "center"
|
|
415
403
|
}
|
|
416
404
|
});
|
|
@@ -235,6 +235,12 @@ function NetworkModalInner({
|
|
|
235
235
|
const [activeTab, setActiveTab] = (0, _react.useState)("filters");
|
|
236
236
|
const [searchText, setSearchText] = (0, _react.useState)("");
|
|
237
237
|
const [isSearchActive, setIsSearchActive] = (0, _react.useState)(false);
|
|
238
|
+
// True while the header's clear ✕ is being pressed. With a mouse, pressing
|
|
239
|
+
// the ✕ blurs the input FIRST, and the blur handler below closes search —
|
|
240
|
+
// which unmounts the ✕ before its own press can fire, so the query was
|
|
241
|
+
// never cleared (desktop). Press-in lands before the blur, so the blur
|
|
242
|
+
// handler can tell this dismissal apart from a click elsewhere.
|
|
243
|
+
const clearPressRef = (0, _react.useRef)(false);
|
|
238
244
|
// The Saved screen's search box lives HERE, not in that screen, because the
|
|
239
245
|
// detail footer steps through the same list the user was just looking at —
|
|
240
246
|
// and the Saved screen is unmounted while a detail is open.
|
|
@@ -446,38 +452,24 @@ function NetworkModalInner({
|
|
|
446
452
|
onBack: onBack
|
|
447
453
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
|
|
448
454
|
title: "",
|
|
449
|
-
children: isSearchActive ? /*#__PURE__*/(0, _jsxRuntime.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
autoCorrect: false,
|
|
468
|
-
returnKeyType: "search"
|
|
469
|
-
}), searchText.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
470
|
-
onPress: () => {
|
|
471
|
-
handleSearch("");
|
|
472
|
-
setIsSearchActive(false);
|
|
473
|
-
},
|
|
474
|
-
"sentry-label": "ignore clear search header",
|
|
475
|
-
style: styles.headerSearchClear,
|
|
476
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.X, {
|
|
477
|
-
size: 14,
|
|
478
|
-
color: _sharedUi.night.color.textSecondary
|
|
479
|
-
})
|
|
480
|
-
}) : null]
|
|
455
|
+
children: isSearchActive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Search, {
|
|
456
|
+
value: searchText,
|
|
457
|
+
onChangeText: handleSearch,
|
|
458
|
+
onCancel: () => {
|
|
459
|
+
handleSearch("");
|
|
460
|
+
setIsSearchActive(false);
|
|
461
|
+
},
|
|
462
|
+
onDismiss: () => setIsSearchActive(false),
|
|
463
|
+
dismissOnBlur: true,
|
|
464
|
+
clearOnlyWhenText: true,
|
|
465
|
+
placeholder: "Search URL, method, operation, error...",
|
|
466
|
+
accessibilityLabel: "Search network requests",
|
|
467
|
+
iconSize: 14,
|
|
468
|
+
testID: "buoy-network-search-input",
|
|
469
|
+
clearTestID: "buoy-network-search-clear",
|
|
470
|
+
inputProps: {
|
|
471
|
+
"sentry-label": "ignore network search header"
|
|
472
|
+
}
|
|
481
473
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_NetworkHeaderLive.NetworkHeaderBadges, {
|
|
482
474
|
activeStatus: filter.status,
|
|
483
475
|
onToggleStatus: toggleStatusFilter,
|
|
@@ -722,27 +714,6 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
722
714
|
},
|
|
723
715
|
// Night chrome — the header is glass over the star field, so the search
|
|
724
716
|
// field and action chips sit on the Everlights dark-glass fill.
|
|
725
|
-
headerSearchContainer: {
|
|
726
|
-
flexDirection: "row",
|
|
727
|
-
alignItems: "center",
|
|
728
|
-
backgroundColor: _sharedUi.night.color.surfaceElevated,
|
|
729
|
-
borderRadius: _sharedUi.night.radius.row,
|
|
730
|
-
borderWidth: 1,
|
|
731
|
-
borderColor: _sharedUi.night.color.border,
|
|
732
|
-
paddingHorizontal: 12,
|
|
733
|
-
paddingVertical: 5
|
|
734
|
-
},
|
|
735
|
-
headerSearchInput: {
|
|
736
|
-
flex: 1,
|
|
737
|
-
color: _sharedUi.night.color.text,
|
|
738
|
-
fontSize: 13,
|
|
739
|
-
marginLeft: 6,
|
|
740
|
-
paddingVertical: 2
|
|
741
|
-
},
|
|
742
|
-
headerSearchClear: {
|
|
743
|
-
marginLeft: 6,
|
|
744
|
-
padding: 4
|
|
745
|
-
},
|
|
746
717
|
menuCopyRow: {
|
|
747
718
|
paddingHorizontal: 6
|
|
748
719
|
},
|
|
@@ -365,8 +365,17 @@ function OverridesBody({
|
|
|
365
365
|
})]
|
|
366
366
|
}), !hasRules ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
367
367
|
style: styles.emptyWrap,
|
|
368
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EmptyState
|
|
369
|
-
|
|
368
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EmptyState
|
|
369
|
+
// Otto instead of the flask: nothing is faked yet, so he peers
|
|
370
|
+
// into an empty box. Truthful by construction — this branch only
|
|
371
|
+
// renders when the rule list is genuinely empty, and the master
|
|
372
|
+
// switch bar above is hidden in exactly that case.
|
|
373
|
+
, {
|
|
374
|
+
otto: "empty"
|
|
375
|
+
// 32 → pixelSize 2, the size the saved/list screens use, so the
|
|
376
|
+
// three network empties read as one family.
|
|
377
|
+
,
|
|
378
|
+
iconSize: 32,
|
|
370
379
|
title: "Nothing overridden"
|
|
371
380
|
// Names the control that actually exists. This said "tap Force 500"
|
|
372
381
|
// — a button from the deleted preset list, which sent anyone
|
|
@@ -32,21 +32,6 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
const keyExtractor = item => item.id;
|
|
35
|
-
function EmptyState() {
|
|
36
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
37
|
-
style: styles.emptyState,
|
|
38
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Bookmark, {
|
|
39
|
-
size: 32,
|
|
40
|
-
color: _sharedUi.macOSColors.text.muted
|
|
41
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
42
|
-
style: styles.emptyTitle,
|
|
43
|
-
children: "No saved requests"
|
|
44
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
45
|
-
style: styles.emptyText,
|
|
46
|
-
children: "Open a request and tap the bookmark to keep it here \u2014 saved requests survive Clear and app restarts."
|
|
47
|
-
})]
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
35
|
function NetworkSavedScreen({
|
|
51
36
|
visible,
|
|
52
37
|
isPro,
|
|
@@ -146,17 +131,31 @@ function NetworkSavedScreen({
|
|
|
146
131
|
autoCorrect: false,
|
|
147
132
|
returnKeyType: "search"
|
|
148
133
|
})]
|
|
149
|
-
}) : null, savedRecords.length === 0
|
|
134
|
+
}) : null, savedRecords.length === 0 ||
|
|
135
|
+
// lockedCount > 0 falls through to the list so the upgrade banner (its
|
|
136
|
+
// ListFooterComponent) still renders — "0 shown, N locked" is an
|
|
137
|
+
// answer, not an empty screen.
|
|
138
|
+
search.trim().length > 0 && filtered.length === 0 && lockedCount === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
|
|
139
|
+
testID: "buoy-network-saved-empty",
|
|
140
|
+
...(0, _sharedUi.resolveListEmptyState)({
|
|
141
|
+
subject: "saved requests",
|
|
142
|
+
verb: "kept",
|
|
143
|
+
search: savedRecords.length === 0 ? "" : search,
|
|
144
|
+
total: savedRecords.length,
|
|
145
|
+
waiting: {
|
|
146
|
+
otto: "empty",
|
|
147
|
+
title: "No saved requests",
|
|
148
|
+
message: "Open a request and tap the bookmark to keep it here — saved requests survive Clear and app restarts."
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
|
|
150
152
|
data: filtered,
|
|
151
153
|
renderItem: renderItem,
|
|
152
154
|
keyExtractor: keyExtractor,
|
|
153
155
|
contentContainerStyle: styles.listContent,
|
|
154
156
|
showsVerticalScrollIndicator: true,
|
|
155
|
-
removeClippedSubviews: true,
|
|
156
157
|
scrollEnabled: true,
|
|
157
|
-
|
|
158
|
-
maxToRenderPerBatch: 8,
|
|
159
|
-
windowSize: 5,
|
|
158
|
+
..._sharedUi.EVENT_LIST_PRESET,
|
|
160
159
|
extraData: pinnedLiveIds,
|
|
161
160
|
"sentry-label": "ignore saved requests list",
|
|
162
161
|
ListFooterComponent: renderListFooter
|
|
@@ -223,23 +222,5 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
223
222
|
},
|
|
224
223
|
listContent: {
|
|
225
224
|
paddingTop: 4
|
|
226
|
-
},
|
|
227
|
-
emptyState: {
|
|
228
|
-
alignItems: "center",
|
|
229
|
-
paddingVertical: 40,
|
|
230
|
-
paddingHorizontal: 24
|
|
231
|
-
},
|
|
232
|
-
emptyTitle: {
|
|
233
|
-
color: _sharedUi.macOSColors.text.primary,
|
|
234
|
-
fontSize: 14,
|
|
235
|
-
fontWeight: "600",
|
|
236
|
-
marginTop: 12,
|
|
237
|
-
marginBottom: 6
|
|
238
|
-
},
|
|
239
|
-
emptyText: {
|
|
240
|
-
color: _sharedUi.macOSColors.text.muted,
|
|
241
|
-
fontSize: 12,
|
|
242
|
-
textAlign: "center",
|
|
243
|
-
lineHeight: 17
|
|
244
225
|
}
|
|
245
226
|
});
|
|
@@ -78,9 +78,11 @@ function useNetworkEventList(options) {
|
|
|
78
78
|
|
|
79
79
|
// Derivations are plain useMemo over the subscribed array — linear
|
|
80
80
|
// passes over ≤maxEvents items, recomputed only when inputs change.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
// Split in two so the pre-filter count is observable: `totalEvents` below
|
|
82
|
+
// is the denominator the empty state needs, and recomputing it separately
|
|
83
|
+
// would mean a second pass over the same array.
|
|
84
|
+
const candidateEvents = (0, _react.useMemo)(() => (0, _filterNetworkEvents.applyIgnoredPatterns)(events, ignoredPatterns), [events, ignoredPatterns]);
|
|
85
|
+
const filteredEvents = (0, _react.useMemo)(() => (0, _filterNetworkEvents.filterNetworkEvents)(candidateEvents, filter), [candidateEvents, filter]);
|
|
84
86
|
|
|
85
87
|
// Free tier: events beyond the limit in the ORIGINAL order are locked,
|
|
86
88
|
// so locked events stay locked even when searching (ported verbatim).
|
|
@@ -100,6 +102,7 @@ function useNetworkEventList(options) {
|
|
|
100
102
|
events: filteredEvents,
|
|
101
103
|
visibleEvents,
|
|
102
104
|
hasLockedEvents: lockedEventCount > 0,
|
|
103
|
-
lockedEventCount
|
|
105
|
+
lockedEventCount,
|
|
106
|
+
totalEvents: candidateEvents.length
|
|
104
107
|
};
|
|
105
108
|
}
|
|
@@ -431,6 +431,14 @@ const networkSyncAdapter = exports.networkSyncAdapter = {
|
|
|
431
431
|
const event = resolveEvent(id);
|
|
432
432
|
if (!event) return null;
|
|
433
433
|
return {
|
|
434
|
+
// Identity + the override mark ride along so a caller (Ask Buoy's
|
|
435
|
+
// receipt, an MCP session) can say WHOSE body this is and whether an
|
|
436
|
+
// override rule produced it — a mocked response rendered as "live"
|
|
437
|
+
// is the fabrication problem wearing a chrome suit.
|
|
438
|
+
url: event.url ?? null,
|
|
439
|
+
method: event.method ?? null,
|
|
440
|
+
status: event.status ?? null,
|
|
441
|
+
override: event.override ?? null,
|
|
434
442
|
requestData: event.requestData ?? null,
|
|
435
443
|
responseData: event.responseData ?? null,
|
|
436
444
|
requestHeaders: event.requestHeaders ?? null,
|
package/lib/commonjs/preset.js
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.createNetworkTool =
|
|
7
|
-
exports.networkToolPreset = void 0;
|
|
6
|
+
exports.networkToolPreset = exports.createNetworkTool = void 0;
|
|
8
7
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
9
8
|
var _NetworkModal = require("./network/components/NetworkModal");
|
|
10
9
|
var _overrideRulesStore = require("./network/overrides/overrideRulesStore");
|
|
@@ -66,7 +65,7 @@ if (isReactNativeRuntime && typeof __DEV__ !== "undefined" && __DEV__) {
|
|
|
66
65
|
* - Filter by status, method, URL
|
|
67
66
|
* - Timing information
|
|
68
67
|
*/
|
|
69
|
-
const networkToolPreset = exports.networkToolPreset = {
|
|
68
|
+
const networkToolPreset = exports.networkToolPreset = (0, _sharedUi.defineToolPreset)({
|
|
70
69
|
id: "network",
|
|
71
70
|
name: "NET",
|
|
72
71
|
description: "Network request logger",
|
|
@@ -80,7 +79,7 @@ const networkToolPreset = exports.networkToolPreset = {
|
|
|
80
79
|
props: {
|
|
81
80
|
enableSharedModalDimensions: false
|
|
82
81
|
}
|
|
83
|
-
};
|
|
82
|
+
});
|
|
84
83
|
|
|
85
84
|
/**
|
|
86
85
|
* Create a custom network monitoring tool configuration.
|
|
@@ -97,20 +96,6 @@ const networkToolPreset = exports.networkToolPreset = {
|
|
|
97
96
|
* });
|
|
98
97
|
* ```
|
|
99
98
|
*/
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
name: options?.name || "NET",
|
|
104
|
-
description: options?.description || "Network request logger",
|
|
105
|
-
slot: "both",
|
|
106
|
-
icon: ({
|
|
107
|
-
size
|
|
108
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.NetworkIcon, {
|
|
109
|
-
size: size
|
|
110
|
-
}),
|
|
111
|
-
component: _NetworkModal.NetworkModal,
|
|
112
|
-
props: {
|
|
113
|
-
enableSharedModalDimensions: options?.enableSharedModalDimensions !== undefined ? options.enableSharedModalDimensions : false
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
}
|
|
99
|
+
const createNetworkTool = exports.createNetworkTool = (0, _sharedUi.createToolFactory)(networkToolPreset, options => ({
|
|
100
|
+
enableSharedModalDimensions: options.enableSharedModalDimensions ?? false
|
|
101
|
+
}));
|
package/lib/module/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export { NetworkModal, NetworkToolView } from "./network/components/NetworkModal
|
|
|
24
24
|
export { NetworkEventDetailView } from "./network/components/NetworkEventDetailView";
|
|
25
25
|
export { NetworkEventItemCompact } from "./network/components/NetworkEventItemCompact";
|
|
26
26
|
export { NetworkSavedScreen } from "./network/components/NetworkSavedScreen";
|
|
27
|
-
export { NetworkSavedButton, NetworkDetailPinActions } from "./network/components/NetworkHeaderLive";
|
|
27
|
+
export { NetworkSavedButton, NetworkDetailPinActions, NetworkHeaderBadgesView } from "./network/components/NetworkHeaderLive";
|
|
28
28
|
|
|
29
29
|
// =============================================================================
|
|
30
30
|
// HOOKS (For consuming network data in custom components)
|