@buoy-gg/network 7.0.11 → 7.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/commonjs/network/components/NetworkDetailStepper.js +3 -1
- package/lib/commonjs/network/components/NetworkModal.js +66 -11
- package/lib/commonjs/network/components/NetworkSavedScreen.js +12 -15
- package/lib/module/network/components/NetworkDetailStepper.js +3 -1
- package/lib/module/network/components/NetworkModal.js +66 -11
- package/lib/module/network/components/NetworkSavedScreen.js +13 -16
- package/lib/typescript/network/components/NetworkDetailStepper.d.ts +2 -0
- package/lib/typescript/network/components/NetworkDetailStepper.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkSavedScreen.d.ts +12 -1
- package/lib/typescript/network/components/NetworkSavedScreen.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@ Want a different label or color? Build the tool with `createNetworkTool({ name,
|
|
|
40
40
|
- **Full request detail** — request/response headers, payloads, HTTP status, and duration for every call, with status-colored rows.
|
|
41
41
|
- **Filter and search** — narrow by status code, HTTP method, or URL pattern; search captured events; pause/resume capture; clear history.
|
|
42
42
|
- **Pin the one that failed** — pin a request to hold it at the top of the list (ignoring your filters), or save it to a separate favorites list. Both keep a full snapshot, so it survives Clear, the 500-request cap, and an app restart. Long-press a row, or use the buttons in the request detail header.
|
|
43
|
+
- **Step between requests** — the detail view has a Previous/Next footer that walks exactly what the list was showing (same pins, filters, and search — or your Saved list), so comparing two calls doesn't mean going back and finding your place.
|
|
43
44
|
- **Ignore the noise** — a shared ignored-domains/URL filter (`useIgnoredPatterns`) hides endpoints you never want to see, shared with the Events tool.
|
|
44
45
|
- **Hooks for custom UIs** — `useNetworkEvents`, `useNetworkEventList`, `useNetworkBadgeCounts`, and `useNetworkSaved` expose the capture stream with narrow per-consumer subscriptions.
|
|
45
46
|
|
|
@@ -39,7 +39,8 @@ const NetworkDetailStepper = exports.NetworkDetailStepper = /*#__PURE__*/(0, _re
|
|
|
39
39
|
isPro,
|
|
40
40
|
fromSaved,
|
|
41
41
|
savedSearch,
|
|
42
|
-
onSelect
|
|
42
|
+
onSelect,
|
|
43
|
+
applySafeAreaInset
|
|
43
44
|
}) {
|
|
44
45
|
const {
|
|
45
46
|
visibleEvents
|
|
@@ -80,6 +81,7 @@ const NetworkDetailStepper = exports.NetworkDetailStepper = /*#__PURE__*/(0, _re
|
|
|
80
81
|
currentIndex: index,
|
|
81
82
|
totalItems: ordered.length,
|
|
82
83
|
itemLabel: "Request",
|
|
84
|
+
applySafeAreaInset: applySafeAreaInset,
|
|
83
85
|
onPrevious: () => {
|
|
84
86
|
const target = ordered[index - 1];
|
|
85
87
|
if (target) onSelect(target.id);
|
|
@@ -15,6 +15,7 @@ var _NetworkCopySettingsView = require("./NetworkCopySettingsView");
|
|
|
15
15
|
var _NetworkHeaderLive = require("./NetworkHeaderLive");
|
|
16
16
|
var _NetworkListScreen = require("./NetworkListScreen");
|
|
17
17
|
var _NetworkSavedScreen = require("./NetworkSavedScreen");
|
|
18
|
+
var _NetworkDetailStepper = require("./NetworkDetailStepper");
|
|
18
19
|
var _useNetworkEventList = require("../hooks/useNetworkEventList");
|
|
19
20
|
var _useLiveNetworkEvent = require("../hooks/useLiveNetworkEvent");
|
|
20
21
|
var _networkSavedStore = require("../utils/networkSavedStore");
|
|
@@ -31,7 +32,14 @@ function NetworkDetailScreen({
|
|
|
31
32
|
eventId,
|
|
32
33
|
paused,
|
|
33
34
|
ignoredPatternValues,
|
|
34
|
-
onTogglePattern
|
|
35
|
+
onTogglePattern,
|
|
36
|
+
isPro,
|
|
37
|
+
filter,
|
|
38
|
+
ignoredPatterns,
|
|
39
|
+
fromSaved,
|
|
40
|
+
savedSearch,
|
|
41
|
+
onSelectEvent,
|
|
42
|
+
applySafeAreaInset
|
|
35
43
|
}) {
|
|
36
44
|
// Resolve the ID to the live event so a request opened while pending picks
|
|
37
45
|
// up its response/error in place instead of freezing on the snapshot taken
|
|
@@ -40,10 +48,26 @@ function NetworkDetailScreen({
|
|
|
40
48
|
paused: paused || !visible
|
|
41
49
|
});
|
|
42
50
|
if (!visible || !event) return null;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
// Column: the detail body scrolls, the stepper stays pinned under it. The
|
|
52
|
+
// body owns its scroll here (see `bodyOwnsScroll`) — inside JsModal's
|
|
53
|
+
// wrapper the footer would scroll away with the content.
|
|
54
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
55
|
+
style: styles.detailRoot,
|
|
56
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_NetworkEventDetailView.NetworkEventDetailView, {
|
|
57
|
+
event: event,
|
|
58
|
+
ignoredPatterns: ignoredPatternValues,
|
|
59
|
+
onTogglePattern: onTogglePattern
|
|
60
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_NetworkDetailStepper.NetworkDetailStepper, {
|
|
61
|
+
eventId: event.id,
|
|
62
|
+
paused: paused,
|
|
63
|
+
filter: filter,
|
|
64
|
+
ignoredPatterns: ignoredPatterns,
|
|
65
|
+
isPro: isPro,
|
|
66
|
+
fromSaved: fromSaved,
|
|
67
|
+
savedSearch: savedSearch,
|
|
68
|
+
onSelect: onSelectEvent,
|
|
69
|
+
applySafeAreaInset: applySafeAreaInset
|
|
70
|
+
})]
|
|
47
71
|
});
|
|
48
72
|
}
|
|
49
73
|
function NetworkFilterScreen({
|
|
@@ -144,6 +168,10 @@ function NetworkModalInner({
|
|
|
144
168
|
const [activeTab, setActiveTab] = (0, _react.useState)("filters");
|
|
145
169
|
const [searchText, setSearchText] = (0, _react.useState)("");
|
|
146
170
|
const [isSearchActive, setIsSearchActive] = (0, _react.useState)(false);
|
|
171
|
+
// The Saved screen's search box lives HERE, not in that screen, because the
|
|
172
|
+
// detail footer steps through the same list the user was just looking at —
|
|
173
|
+
// and the Saved screen is unmounted while a detail is open.
|
|
174
|
+
const [savedSearch, setSavedSearch] = (0, _react.useState)("");
|
|
147
175
|
const searchInputRef = (0, _react.useRef)(null);
|
|
148
176
|
// Ignored domains/URL patterns live in a shared, persisted singleton store
|
|
149
177
|
// (@buoy-gg/shared-ui) so the Network tool and the Events tool stay in sync.
|
|
@@ -228,8 +256,13 @@ function NetworkModalInner({
|
|
|
228
256
|
status: prev.status === status ? undefined : status
|
|
229
257
|
}));
|
|
230
258
|
};
|
|
231
|
-
|
|
232
|
-
|
|
259
|
+
|
|
260
|
+
// JsModal owns the mode; the only thing this modal needs it for is the
|
|
261
|
+
// detail footer's bottom inset — a bottom sheet sits on the home indicator,
|
|
262
|
+
// a floating window does not (same call StorageModalWithTabs makes).
|
|
263
|
+
const [modalMode, setModalMode] = (0, _react.useState)("bottomSheet");
|
|
264
|
+
const handleModeChange = mode => {
|
|
265
|
+
setModalMode(mode);
|
|
233
266
|
};
|
|
234
267
|
(0, _react.useEffect)(() => {
|
|
235
268
|
if (isSearchActive) {
|
|
@@ -386,8 +419,10 @@ function NetworkModalInner({
|
|
|
386
419
|
// it — inside JsModal's ScrollView wrapper every row mounts, which at
|
|
387
420
|
// the 500-event cap measured 17 JS FPS / 133% CPU / 1.4GB; see
|
|
388
421
|
// NetworkListScreen). The Saved screen is a FlatList too, so it takes the
|
|
389
|
-
// same deal.
|
|
390
|
-
|
|
422
|
+
// same deal. The DETAIL screen owns it as well, so its prev/next footer
|
|
423
|
+
// stays pinned instead of scrolling away with the body. Filter/copy still
|
|
424
|
+
// use the wrapper.
|
|
425
|
+
const bodyOwnsScroll = selectedEventId != null || !showFilterView;
|
|
391
426
|
const body = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
392
427
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
393
428
|
style: styles.container,
|
|
@@ -396,7 +431,19 @@ function NetworkModalInner({
|
|
|
396
431
|
eventId: selectedEventId,
|
|
397
432
|
paused: paused,
|
|
398
433
|
ignoredPatternValues: ignoredPatternValues,
|
|
399
|
-
onTogglePattern: toggleIgnoredPattern
|
|
434
|
+
onTogglePattern: toggleIgnoredPattern,
|
|
435
|
+
isPro: isPro,
|
|
436
|
+
filter: filter,
|
|
437
|
+
ignoredPatterns: ignoredPatterns
|
|
438
|
+
// `showSavedView` is what Back returns to, so it is also which list
|
|
439
|
+
// the user came from — and therefore which one to step through.
|
|
440
|
+
,
|
|
441
|
+
fromSaved: showSavedView,
|
|
442
|
+
savedSearch: savedSearch,
|
|
443
|
+
onSelectEvent: setSelectedEventId
|
|
444
|
+
// Inline (desktop panel) has no home indicator to clear.
|
|
445
|
+
,
|
|
446
|
+
applySafeAreaInset: !inline && modalMode === "bottomSheet"
|
|
400
447
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(NetworkFilterScreen, {
|
|
401
448
|
visible: showFilterView && activeTab === "filters" && !selectedEventId,
|
|
402
449
|
paused: paused,
|
|
@@ -419,6 +466,8 @@ function NetworkModalInner({
|
|
|
419
466
|
visible: showSavedView && selectedEventId == null && !showFilterView,
|
|
420
467
|
isPro: isPro,
|
|
421
468
|
copySettings: copySettings,
|
|
469
|
+
search: savedSearch,
|
|
470
|
+
onSearchChange: setSavedSearch,
|
|
422
471
|
onEventPress: handleEventPress,
|
|
423
472
|
onUpgradePress: () => showUpgrade("saved")
|
|
424
473
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_NetworkListScreen.NetworkListScreen, {
|
|
@@ -464,7 +513,7 @@ function NetworkModalInner({
|
|
|
464
513
|
enablePersistence: true,
|
|
465
514
|
initialMode: "bottomSheet",
|
|
466
515
|
enableGlitchEffects: true,
|
|
467
|
-
disableScrollWrapper:
|
|
516
|
+
disableScrollWrapper: bodyOwnsScroll,
|
|
468
517
|
styles: {},
|
|
469
518
|
children: body
|
|
470
519
|
});
|
|
@@ -474,6 +523,12 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
474
523
|
flex: 1,
|
|
475
524
|
backgroundColor: _sharedUi.macOSColors.background.base
|
|
476
525
|
},
|
|
526
|
+
/** Detail = scrolling body + pinned stepper footer. `minHeight: 0` so the
|
|
527
|
+
* body's ScrollView scrolls instead of stretching the column. */
|
|
528
|
+
detailRoot: {
|
|
529
|
+
flex: 1,
|
|
530
|
+
minHeight: 0
|
|
531
|
+
},
|
|
477
532
|
/** Inline shell — fills the host panel; `minHeight: 0` so the list's own
|
|
478
533
|
* FlatList can scroll instead of stretching the column. */
|
|
479
534
|
inlineRoot: {
|
|
@@ -10,7 +10,7 @@ var _sharedUi = require("@buoy-gg/shared-ui");
|
|
|
10
10
|
var _NetworkEventItemCompact = require("./NetworkEventItemCompact");
|
|
11
11
|
var _NetworkUpgradeBanner = require("./NetworkUpgradeBanner");
|
|
12
12
|
var _generateNetworkCopyText = require("../utils/generateNetworkCopyText");
|
|
13
|
-
var
|
|
13
|
+
var _selectSavedEvents = require("../utils/selectSavedEvents");
|
|
14
14
|
var _useNetworkSaved = require("../hooks/useNetworkSaved");
|
|
15
15
|
var _networkSavedStore = require("../utils/networkSavedStore");
|
|
16
16
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -51,6 +51,8 @@ function NetworkSavedScreen({
|
|
|
51
51
|
visible,
|
|
52
52
|
isPro,
|
|
53
53
|
copySettings,
|
|
54
|
+
search: searchProp,
|
|
55
|
+
onSearchChange,
|
|
54
56
|
onEventPress,
|
|
55
57
|
onUpgradePress
|
|
56
58
|
}) {
|
|
@@ -60,22 +62,17 @@ function NetworkSavedScreen({
|
|
|
60
62
|
toggleSave,
|
|
61
63
|
clearSaved
|
|
62
64
|
} = (0, _useNetworkSaved.useNetworkSaved)();
|
|
63
|
-
const [
|
|
65
|
+
const [searchState, setSearchState] = (0, _react.useState)("");
|
|
66
|
+
const controlled = searchProp != null && onSearchChange != null;
|
|
67
|
+
const search = controlled ? searchProp : searchState;
|
|
68
|
+
const setSearch = controlled ? onSearchChange : setSearchState;
|
|
64
69
|
if (!visible) return null;
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
*/
|
|
72
|
-
const limit = isPro ? _networkSavedStore.MAX_SAVED : _networkSavedStore.FREE_TIER_SAVED_LIMIT;
|
|
73
|
-
const unlocked = savedRecords.slice(0, limit);
|
|
74
|
-
const lockedCount = savedRecords.length - unlocked.length;
|
|
75
|
-
const events = unlocked.map(record => record.event);
|
|
76
|
-
const filtered = search ? (0, _filterNetworkEvents.filterNetworkEvents)(events, {
|
|
77
|
-
searchText: search
|
|
78
|
-
}) : events;
|
|
71
|
+
// Shared with the detail footer, so "Next" can't disagree with the row below.
|
|
72
|
+
const {
|
|
73
|
+
events: filtered,
|
|
74
|
+
lockedCount
|
|
75
|
+
} = (0, _selectSavedEvents.selectSavedEvents)(savedRecords, isPro, search);
|
|
79
76
|
const handleLongPress = event => {
|
|
80
77
|
toggleSave(event);
|
|
81
78
|
};
|
|
@@ -35,7 +35,8 @@ export const NetworkDetailStepper = /*#__PURE__*/memo(function NetworkDetailStep
|
|
|
35
35
|
isPro,
|
|
36
36
|
fromSaved,
|
|
37
37
|
savedSearch,
|
|
38
|
-
onSelect
|
|
38
|
+
onSelect,
|
|
39
|
+
applySafeAreaInset
|
|
39
40
|
}) {
|
|
40
41
|
const {
|
|
41
42
|
visibleEvents
|
|
@@ -76,6 +77,7 @@ export const NetworkDetailStepper = /*#__PURE__*/memo(function NetworkDetailStep
|
|
|
76
77
|
currentIndex: index,
|
|
77
78
|
totalItems: ordered.length,
|
|
78
79
|
itemLabel: "Request",
|
|
80
|
+
applySafeAreaInset: applySafeAreaInset,
|
|
79
81
|
onPrevious: () => {
|
|
80
82
|
const target = ordered[index - 1];
|
|
81
83
|
if (target) onSelect(target.id);
|
|
@@ -10,6 +10,7 @@ import { NetworkCopySettingsView, DEFAULT_COPY_SETTINGS } from "./NetworkCopySet
|
|
|
10
10
|
import { NetworkHeaderBadges, NetworkClearButton, NetworkDetailPinActions, NetworkHeaderCopyButton, NetworkSavedButton } from "./NetworkHeaderLive";
|
|
11
11
|
import { NetworkListScreen } from "./NetworkListScreen";
|
|
12
12
|
import { NetworkSavedScreen } from "./NetworkSavedScreen";
|
|
13
|
+
import { NetworkDetailStepper } from "./NetworkDetailStepper";
|
|
13
14
|
import { useNetworkEventList } from "../hooks/useNetworkEventList";
|
|
14
15
|
import { useLiveNetworkEvent } from "../hooks/useLiveNetworkEvent";
|
|
15
16
|
import { FREE_TIER_SAVED_LIMIT, MAX_SAVED } from "../utils/networkSavedStore";
|
|
@@ -26,7 +27,14 @@ function NetworkDetailScreen({
|
|
|
26
27
|
eventId,
|
|
27
28
|
paused,
|
|
28
29
|
ignoredPatternValues,
|
|
29
|
-
onTogglePattern
|
|
30
|
+
onTogglePattern,
|
|
31
|
+
isPro,
|
|
32
|
+
filter,
|
|
33
|
+
ignoredPatterns,
|
|
34
|
+
fromSaved,
|
|
35
|
+
savedSearch,
|
|
36
|
+
onSelectEvent,
|
|
37
|
+
applySafeAreaInset
|
|
30
38
|
}) {
|
|
31
39
|
// Resolve the ID to the live event so a request opened while pending picks
|
|
32
40
|
// up its response/error in place instead of freezing on the snapshot taken
|
|
@@ -35,10 +43,26 @@ function NetworkDetailScreen({
|
|
|
35
43
|
paused: paused || !visible
|
|
36
44
|
});
|
|
37
45
|
if (!visible || !event) return null;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
// Column: the detail body scrolls, the stepper stays pinned under it. The
|
|
47
|
+
// body owns its scroll here (see `bodyOwnsScroll`) — inside JsModal's
|
|
48
|
+
// wrapper the footer would scroll away with the content.
|
|
49
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
50
|
+
style: styles.detailRoot,
|
|
51
|
+
children: [/*#__PURE__*/_jsx(NetworkEventDetailView, {
|
|
52
|
+
event: event,
|
|
53
|
+
ignoredPatterns: ignoredPatternValues,
|
|
54
|
+
onTogglePattern: onTogglePattern
|
|
55
|
+
}), /*#__PURE__*/_jsx(NetworkDetailStepper, {
|
|
56
|
+
eventId: event.id,
|
|
57
|
+
paused: paused,
|
|
58
|
+
filter: filter,
|
|
59
|
+
ignoredPatterns: ignoredPatterns,
|
|
60
|
+
isPro: isPro,
|
|
61
|
+
fromSaved: fromSaved,
|
|
62
|
+
savedSearch: savedSearch,
|
|
63
|
+
onSelect: onSelectEvent,
|
|
64
|
+
applySafeAreaInset: applySafeAreaInset
|
|
65
|
+
})]
|
|
42
66
|
});
|
|
43
67
|
}
|
|
44
68
|
function NetworkFilterScreen({
|
|
@@ -139,6 +163,10 @@ function NetworkModalInner({
|
|
|
139
163
|
const [activeTab, setActiveTab] = useState("filters");
|
|
140
164
|
const [searchText, setSearchText] = useState("");
|
|
141
165
|
const [isSearchActive, setIsSearchActive] = useState(false);
|
|
166
|
+
// The Saved screen's search box lives HERE, not in that screen, because the
|
|
167
|
+
// detail footer steps through the same list the user was just looking at —
|
|
168
|
+
// and the Saved screen is unmounted while a detail is open.
|
|
169
|
+
const [savedSearch, setSavedSearch] = useState("");
|
|
142
170
|
const searchInputRef = useRef(null);
|
|
143
171
|
// Ignored domains/URL patterns live in a shared, persisted singleton store
|
|
144
172
|
// (@buoy-gg/shared-ui) so the Network tool and the Events tool stay in sync.
|
|
@@ -223,8 +251,13 @@ function NetworkModalInner({
|
|
|
223
251
|
status: prev.status === status ? undefined : status
|
|
224
252
|
}));
|
|
225
253
|
};
|
|
226
|
-
|
|
227
|
-
|
|
254
|
+
|
|
255
|
+
// JsModal owns the mode; the only thing this modal needs it for is the
|
|
256
|
+
// detail footer's bottom inset — a bottom sheet sits on the home indicator,
|
|
257
|
+
// a floating window does not (same call StorageModalWithTabs makes).
|
|
258
|
+
const [modalMode, setModalMode] = useState("bottomSheet");
|
|
259
|
+
const handleModeChange = mode => {
|
|
260
|
+
setModalMode(mode);
|
|
228
261
|
};
|
|
229
262
|
useEffect(() => {
|
|
230
263
|
if (isSearchActive) {
|
|
@@ -381,8 +414,10 @@ function NetworkModalInner({
|
|
|
381
414
|
// it — inside JsModal's ScrollView wrapper every row mounts, which at
|
|
382
415
|
// the 500-event cap measured 17 JS FPS / 133% CPU / 1.4GB; see
|
|
383
416
|
// NetworkListScreen). The Saved screen is a FlatList too, so it takes the
|
|
384
|
-
// same deal.
|
|
385
|
-
|
|
417
|
+
// same deal. The DETAIL screen owns it as well, so its prev/next footer
|
|
418
|
+
// stays pinned instead of scrolling away with the body. Filter/copy still
|
|
419
|
+
// use the wrapper.
|
|
420
|
+
const bodyOwnsScroll = selectedEventId != null || !showFilterView;
|
|
386
421
|
const body = /*#__PURE__*/_jsxs(_Fragment, {
|
|
387
422
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
388
423
|
style: styles.container,
|
|
@@ -391,7 +426,19 @@ function NetworkModalInner({
|
|
|
391
426
|
eventId: selectedEventId,
|
|
392
427
|
paused: paused,
|
|
393
428
|
ignoredPatternValues: ignoredPatternValues,
|
|
394
|
-
onTogglePattern: toggleIgnoredPattern
|
|
429
|
+
onTogglePattern: toggleIgnoredPattern,
|
|
430
|
+
isPro: isPro,
|
|
431
|
+
filter: filter,
|
|
432
|
+
ignoredPatterns: ignoredPatterns
|
|
433
|
+
// `showSavedView` is what Back returns to, so it is also which list
|
|
434
|
+
// the user came from — and therefore which one to step through.
|
|
435
|
+
,
|
|
436
|
+
fromSaved: showSavedView,
|
|
437
|
+
savedSearch: savedSearch,
|
|
438
|
+
onSelectEvent: setSelectedEventId
|
|
439
|
+
// Inline (desktop panel) has no home indicator to clear.
|
|
440
|
+
,
|
|
441
|
+
applySafeAreaInset: !inline && modalMode === "bottomSheet"
|
|
395
442
|
}), /*#__PURE__*/_jsx(NetworkFilterScreen, {
|
|
396
443
|
visible: showFilterView && activeTab === "filters" && !selectedEventId,
|
|
397
444
|
paused: paused,
|
|
@@ -414,6 +461,8 @@ function NetworkModalInner({
|
|
|
414
461
|
visible: showSavedView && selectedEventId == null && !showFilterView,
|
|
415
462
|
isPro: isPro,
|
|
416
463
|
copySettings: copySettings,
|
|
464
|
+
search: savedSearch,
|
|
465
|
+
onSearchChange: setSavedSearch,
|
|
417
466
|
onEventPress: handleEventPress,
|
|
418
467
|
onUpgradePress: () => showUpgrade("saved")
|
|
419
468
|
}), /*#__PURE__*/_jsx(NetworkListScreen, {
|
|
@@ -459,7 +508,7 @@ function NetworkModalInner({
|
|
|
459
508
|
enablePersistence: true,
|
|
460
509
|
initialMode: "bottomSheet",
|
|
461
510
|
enableGlitchEffects: true,
|
|
462
|
-
disableScrollWrapper:
|
|
511
|
+
disableScrollWrapper: bodyOwnsScroll,
|
|
463
512
|
styles: {},
|
|
464
513
|
children: body
|
|
465
514
|
});
|
|
@@ -469,6 +518,12 @@ const styles = StyleSheet.create({
|
|
|
469
518
|
flex: 1,
|
|
470
519
|
backgroundColor: macOSColors.background.base
|
|
471
520
|
},
|
|
521
|
+
/** Detail = scrolling body + pinned stepper footer. `minHeight: 0` so the
|
|
522
|
+
* body's ScrollView scrolls instead of stretching the column. */
|
|
523
|
+
detailRoot: {
|
|
524
|
+
flex: 1,
|
|
525
|
+
minHeight: 0
|
|
526
|
+
},
|
|
472
527
|
/** Inline shell — fills the host panel; `minHeight: 0` so the list's own
|
|
473
528
|
* FlatList can scroll instead of stretching the column. */
|
|
474
529
|
inlineRoot: {
|
|
@@ -23,9 +23,9 @@ import { Bookmark, CopyButton, Search, macOSColors } from "@buoy-gg/shared-ui";
|
|
|
23
23
|
import { NetworkEventItemCompact } from "./NetworkEventItemCompact";
|
|
24
24
|
import { NetworkUpgradeBanner } from "./NetworkUpgradeBanner";
|
|
25
25
|
import { generateNetworkCopyText } from "../utils/generateNetworkCopyText";
|
|
26
|
-
import {
|
|
26
|
+
import { selectSavedEvents } from "../utils/selectSavedEvents";
|
|
27
27
|
import { useNetworkSaved } from "../hooks/useNetworkSaved";
|
|
28
|
-
import { FREE_TIER_SAVED_LIMIT
|
|
28
|
+
import { FREE_TIER_SAVED_LIMIT } from "../utils/networkSavedStore";
|
|
29
29
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
30
30
|
const keyExtractor = item => item.id;
|
|
31
31
|
function EmptyState() {
|
|
@@ -47,6 +47,8 @@ export function NetworkSavedScreen({
|
|
|
47
47
|
visible,
|
|
48
48
|
isPro,
|
|
49
49
|
copySettings,
|
|
50
|
+
search: searchProp,
|
|
51
|
+
onSearchChange,
|
|
50
52
|
onEventPress,
|
|
51
53
|
onUpgradePress
|
|
52
54
|
}) {
|
|
@@ -56,22 +58,17 @@ export function NetworkSavedScreen({
|
|
|
56
58
|
toggleSave,
|
|
57
59
|
clearSaved
|
|
58
60
|
} = useNetworkSaved();
|
|
59
|
-
const [
|
|
61
|
+
const [searchState, setSearchState] = useState("");
|
|
62
|
+
const controlled = searchProp != null && onSearchChange != null;
|
|
63
|
+
const search = controlled ? searchProp : searchState;
|
|
64
|
+
const setSearch = controlled ? onSearchChange : setSearchState;
|
|
60
65
|
if (!visible) return null;
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
*/
|
|
68
|
-
const limit = isPro ? MAX_SAVED : FREE_TIER_SAVED_LIMIT;
|
|
69
|
-
const unlocked = savedRecords.slice(0, limit);
|
|
70
|
-
const lockedCount = savedRecords.length - unlocked.length;
|
|
71
|
-
const events = unlocked.map(record => record.event);
|
|
72
|
-
const filtered = search ? filterNetworkEvents(events, {
|
|
73
|
-
searchText: search
|
|
74
|
-
}) : events;
|
|
67
|
+
// Shared with the detail footer, so "Next" can't disagree with the row below.
|
|
68
|
+
const {
|
|
69
|
+
events: filtered,
|
|
70
|
+
lockedCount
|
|
71
|
+
} = selectSavedEvents(savedRecords, isPro, search);
|
|
75
72
|
const handleLongPress = event => {
|
|
76
73
|
toggleSave(event);
|
|
77
74
|
};
|
|
@@ -31,6 +31,8 @@ interface NetworkDetailStepperProps {
|
|
|
31
31
|
/** The Saved screen's search box (lifted to the modal root so both agree). */
|
|
32
32
|
savedSearch: string;
|
|
33
33
|
onSelect: (eventId: string) => void;
|
|
34
|
+
/** Only a bottom sheet sits on the home indicator — see NetworkModal. */
|
|
35
|
+
applySafeAreaInset: boolean;
|
|
34
36
|
}
|
|
35
37
|
export declare const NetworkDetailStepper: import("react").NamedExoticComponent<NetworkDetailStepperProps>;
|
|
36
38
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkDetailStepper.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkDetailStepper.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,UAAU,CAAC;AAM5D,UAAU,yBAAyB;IACjC,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,eAAe,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,KAAK,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"NetworkDetailStepper.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkDetailStepper.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,UAAU,CAAC;AAM5D,UAAU,yBAAyB;IACjC,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,eAAe,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,KAAK,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,yEAAyE;IACzE,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,oBAAoB,iEAmE/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkModal.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NetworkModal.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkModal.tsx"],"names":[],"mappings":"AAkDA,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC;IACvC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAopBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,+BAMpD;AAED,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,GAAE,oBAAyB,+BAa/D"}
|
|
@@ -20,10 +20,21 @@ interface NetworkSavedScreenProps {
|
|
|
20
20
|
visible: boolean;
|
|
21
21
|
isPro: boolean;
|
|
22
22
|
copySettings: CopySettings;
|
|
23
|
+
/**
|
|
24
|
+
* Controlled search box — pass both halves or neither, same deal as
|
|
25
|
+
* NetworkModal's `paused`.
|
|
26
|
+
*
|
|
27
|
+
* NetworkModal controls it because the detail screen's prev/next footer
|
|
28
|
+
* steps through THIS list, and this screen is unmounted while a detail is
|
|
29
|
+
* open (see NetworkDetailStepper). A host rendering the screen on its own
|
|
30
|
+
* can omit both and keep the local state.
|
|
31
|
+
*/
|
|
32
|
+
search?: string;
|
|
33
|
+
onSearchChange?: (search: string) => void;
|
|
23
34
|
/** Row tap — the root's setSelectedEvent (inherently stable setter). */
|
|
24
35
|
onEventPress: (event: NetworkEvent) => void;
|
|
25
36
|
onUpgradePress: () => void;
|
|
26
37
|
}
|
|
27
|
-
export declare function NetworkSavedScreen({ visible, isPro, copySettings, onEventPress, onUpgradePress, }: NetworkSavedScreenProps): import("react").JSX.Element | null;
|
|
38
|
+
export declare function NetworkSavedScreen({ visible, isPro, copySettings, search: searchProp, onSearchChange, onEventPress, onUpgradePress, }: NetworkSavedScreenProps): import("react").JSX.Element | null;
|
|
28
39
|
export {};
|
|
29
40
|
//# sourceMappingURL=NetworkSavedScreen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkSavedScreen.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkSavedScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"NetworkSavedScreen.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkSavedScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAqB9D,UAAU,uBAAuB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;IAC3B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,wEAAwE;IACxE,YAAY,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC5C,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,KAAK,EACL,YAAY,EACZ,MAAM,EAAE,UAAU,EAClB,cAAc,EACd,YAAY,EACZ,cAAc,GACf,EAAE,uBAAuB,sCA2HzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/network",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.12",
|
|
4
4
|
"description": "In-app network inspector for React Native — requests, responses, timing & errors live, with GraphQL operation parsing. Part of Buoy devtools.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
],
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@buoy-gg/shared-ui": "^7.0.
|
|
29
|
+
"@buoy-gg/shared-ui": "^7.0.12"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"react": "*",
|