@buoy-gg/network 7.0.14 → 7.0.16

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 (107) hide show
  1. package/lib/commonjs/index.web.js +395 -0
  2. package/lib/commonjs/network/components/DataViewer.web.js +879 -0
  3. package/lib/commonjs/network/components/NetworkCopyScreen.web.js +48 -0
  4. package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +1242 -0
  5. package/lib/commonjs/network/components/NetworkDetailScreen.web.js +101 -0
  6. package/lib/commonjs/network/components/NetworkDetailStepper.web.js +296 -0
  7. package/lib/commonjs/network/components/NetworkEventDetailView.web.js +1498 -0
  8. package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +802 -0
  9. package/lib/commonjs/network/components/NetworkFilterScreen.web.js +55 -0
  10. package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1310 -0
  11. package/lib/commonjs/network/components/NetworkHeaderLive.web.js +604 -0
  12. package/lib/commonjs/network/components/NetworkListScreen.js +2 -1
  13. package/lib/commonjs/network/components/NetworkListScreen.web.js +607 -0
  14. package/lib/commonjs/network/components/NetworkModal.js +12 -3
  15. package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +232 -0
  16. package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +942 -0
  17. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +133 -0
  18. package/lib/commonjs/network/components/NetworkOverridesButton.web.js +143 -0
  19. package/lib/commonjs/network/components/NetworkOverridesScreen.js +160 -126
  20. package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +830 -0
  21. package/lib/commonjs/network/components/NetworkSavedScreen.web.js +459 -0
  22. package/lib/commonjs/network/components/response-editor/Explorer.web.js +1136 -0
  23. package/lib/commonjs/network/hooks/useNetworkEventList.js +12 -2
  24. package/lib/commonjs/network/overrides/applyToXhr.js +276 -15
  25. package/lib/commonjs/network/utils/generateNetworkCopyText.js +32 -5
  26. package/lib/commonjs/network/utils/networkEventStore.js +12 -4
  27. package/lib/commonjs/network/utils/networkListener.js +1 -16
  28. package/lib/module/index.web.js +81 -0
  29. package/lib/module/network/components/DataViewer.web.js +875 -0
  30. package/lib/module/network/components/NetworkCopyScreen.web.js +44 -0
  31. package/lib/module/network/components/NetworkCopySettingsView.web.js +1237 -0
  32. package/lib/module/network/components/NetworkDetailScreen.web.js +97 -0
  33. package/lib/module/network/components/NetworkDetailStepper.web.js +294 -0
  34. package/lib/module/network/components/NetworkEventDetailView.web.js +1496 -0
  35. package/lib/module/network/components/NetworkEventItemCompact.web.js +800 -0
  36. package/lib/module/network/components/NetworkFilterScreen.web.js +51 -0
  37. package/lib/module/network/components/NetworkFilterViewV3.web.js +1306 -0
  38. package/lib/module/network/components/NetworkHeaderLive.web.js +598 -0
  39. package/lib/module/network/components/NetworkListScreen.js +2 -1
  40. package/lib/module/network/components/NetworkListScreen.web.js +605 -0
  41. package/lib/module/network/components/NetworkModal.js +12 -3
  42. package/lib/module/network/components/NetworkNumberPrompt.web.js +230 -0
  43. package/lib/module/network/components/NetworkOverrideEditor.web.js +939 -0
  44. package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +131 -0
  45. package/lib/module/network/components/NetworkOverridesButton.web.js +141 -0
  46. package/lib/module/network/components/NetworkOverridesScreen.js +161 -127
  47. package/lib/module/network/components/NetworkOverridesScreen.web.js +826 -0
  48. package/lib/module/network/components/NetworkSavedScreen.web.js +457 -0
  49. package/lib/module/network/components/response-editor/Explorer.web.js +1133 -0
  50. package/lib/module/network/hooks/useNetworkEventList.js +12 -2
  51. package/lib/module/network/overrides/applyToXhr.js +275 -15
  52. package/lib/module/network/utils/generateNetworkCopyText.js +28 -1
  53. package/lib/module/network/utils/networkEventStore.js +12 -4
  54. package/lib/module/network/utils/networkListener.js +1 -16
  55. package/lib/typescript/index.web.d.ts +56 -0
  56. package/lib/typescript/index.web.d.ts.map +1 -0
  57. package/lib/typescript/network/components/DataViewer.web.d.ts +78 -0
  58. package/lib/typescript/network/components/DataViewer.web.d.ts.map +1 -0
  59. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts +27 -0
  60. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +1 -0
  61. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts +68 -0
  62. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +1 -0
  63. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts +45 -0
  64. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +1 -0
  65. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts +40 -0
  66. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +1 -0
  67. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts +67 -0
  68. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +1 -0
  69. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts +58 -0
  70. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +1 -0
  71. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts +28 -0
  72. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +1 -0
  73. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts +74 -0
  74. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +1 -0
  75. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts +112 -0
  76. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +1 -0
  77. package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
  78. package/lib/typescript/network/components/NetworkListScreen.web.d.ts +63 -0
  79. package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +1 -0
  80. package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
  81. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts +38 -0
  82. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +1 -0
  83. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts +43 -0
  84. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +1 -0
  85. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts +32 -0
  86. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +1 -0
  87. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts +26 -0
  88. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +1 -0
  89. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts +9 -0
  90. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -1
  91. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts +69 -0
  92. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +1 -0
  93. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts +67 -0
  94. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +1 -0
  95. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts +56 -0
  96. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +1 -0
  97. package/lib/typescript/network/hooks/useNetworkEventList.d.ts +10 -0
  98. package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +1 -1
  99. package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts.map +1 -1
  100. package/lib/typescript/network/overrides/applyToXhr.d.ts +40 -14
  101. package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -1
  102. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts +34 -1
  103. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +1 -1
  104. package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
  105. package/lib/typescript/network/utils/networkListener.d.ts +0 -1
  106. package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
  107. package/package.json +2 -2
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.NetworkDetailScreen = NetworkDetailScreen;
7
+ var _react = require("react");
8
+ var _useLiveNetworkEvent = require("../hooks/useLiveNetworkEvent");
9
+ var _useNetworkSelection = require("../hooks/useNetworkSelection");
10
+ var _networkSelectionStore = require("../utils/networkSelectionStore");
11
+ var _NetworkEventDetailView = require("./NetworkEventDetailView.web");
12
+ var _NetworkDetailStepper = require("./NetworkDetailStepper.web");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ /**
15
+ * NetworkDetailScreen.web — DOM twin of the `NetworkDetailScreen` screen
16
+ * component inside NetworkModal.tsx (the native detail screen is private to
17
+ * the modal; web hosts compose their own shell, so the screen is exported
18
+ * here as the reusable piece).
19
+ *
20
+ * Same rule4 contract and the same two-cursor render strategy as native:
21
+ *
22
+ * - Hooks run unconditionally; the component returns null when not visible.
23
+ * - The detail chrome renders at the IMMEDIATE selection
24
+ * (`useSelectedNetworkEventId`) — every step, no delay — while the
25
+ * expensive JSON body trees wait for the settled cursor
26
+ * (`useNetworkBodyEventId`): `showBodies` is false exactly while the
27
+ * prev/next cursor is still moving, so a burst of taps renders the request
28
+ * you land on and none of the ones you flew past.
29
+ * - The ID resolves through `useLiveNetworkEvent` so a request opened while
30
+ * pending picks up its response/error in place.
31
+ * - `reportRendered` still fires after the trees commit — benchmark
32
+ * instrumentation, same gating as native.
33
+ *
34
+ * All hooks and the selection store are the platform-free modules native
35
+ * uses — REUSED, not forked. Layout: the detail body scrolls, the stepper
36
+ * stays pinned under it (the body owns its scroll — see the native comment);
37
+ * the spacer holds the footer down when the ID resolves to nothing.
38
+ *
39
+ * @platform React DOM Web
40
+ */
41
+
42
+ function NetworkDetailScreen({
43
+ visible,
44
+ paused,
45
+ ignoredPatternValues,
46
+ onTogglePattern,
47
+ isPro,
48
+ filter,
49
+ ignoredPatterns,
50
+ fromSaved,
51
+ savedSearch,
52
+ applySafeAreaInset
53
+ }) {
54
+ const eventId = (0, _useNetworkSelection.useSelectedNetworkEventId)();
55
+ const settledId = (0, _useNetworkSelection.useNetworkBodyEventId)();
56
+ const heavyReady = eventId != null && eventId === settledId;
57
+ // Resolve the ID to the live event so a request opened while pending picks
58
+ // up its response/error in place instead of freezing on the tap snapshot.
59
+ const event = (0, _useLiveNetworkEvent.useLiveNetworkEvent)(eventId, {
60
+ paused: paused || !visible
61
+ });
62
+
63
+ // Instrumentation for the benchmark harness — reports when the expensive
64
+ // TREES landed (gated on `heavyReady`, same rationale as native).
65
+ (0, _react.useEffect)(() => {
66
+ if (visible && event && heavyReady) {
67
+ _networkSelectionStore.networkSelectionStore.reportRendered(event.id);
68
+ }
69
+ }, [visible, event, heavyReady]);
70
+ if (!visible) return null;
71
+ // Column: the detail body scrolls, the stepper stays pinned under it.
72
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
73
+ style: {
74
+ display: "flex",
75
+ flexDirection: "column",
76
+ flex: 1,
77
+ minHeight: 0
78
+ },
79
+ children: [event ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_NetworkEventDetailView.NetworkEventDetailView, {
80
+ event: event,
81
+ ignoredPatterns: ignoredPatternValues,
82
+ onTogglePattern: onTogglePattern,
83
+ showBodies: heavyReady
84
+ }) :
85
+ /*#__PURE__*/
86
+ /* Holds the footer down when the selected ID resolves to no event. */
87
+ (0, _jsxRuntime.jsx)("div", {
88
+ style: {
89
+ flex: 1
90
+ }
91
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_NetworkDetailStepper.NetworkDetailStepper, {
92
+ paused: paused,
93
+ filter: filter,
94
+ ignoredPatterns: ignoredPatterns,
95
+ isPro: isPro,
96
+ fromSaved: fromSaved,
97
+ savedSearch: savedSearch,
98
+ applySafeAreaInset: applySafeAreaInset
99
+ })]
100
+ });
101
+ }
@@ -0,0 +1,296 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.NetworkDetailStepper = void 0;
7
+ var _react = require("react");
8
+ var _useNetworkEventList = require("../hooks/useNetworkEventList");
9
+ var _useNetworkSaved = require("../hooks/useNetworkSaved");
10
+ var _useNetworkSelection = require("../hooks/useNetworkSelection");
11
+ var _networkSelectionStore = require("../utils/networkSelectionStore");
12
+ var _withPinnedFirst = require("../utils/withPinnedFirst");
13
+ var _selectSavedEvents = require("../utils/selectSavedEvents");
14
+ var _jsxRuntime = require("react/jsx-runtime");
15
+ /**
16
+ * NetworkDetailStepper.web — DOM twin of NetworkDetailStepper.tsx.
17
+ *
18
+ * Previous/Next footer for the request DETAIL screen. The data layer is
19
+ * REUSED, not forked — `useNetworkEventList`, `useNetworkSaved`,
20
+ * `useNetworkCursor`, `networkSelectionStore`, `splitPinned` and
21
+ * `selectSavedEvents` are all platform-free — so the navigable order is
22
+ * EXACTLY what the list screen renders (`[...pinned, ...rest]`), re-scoped in
23
+ * place by the live filter, and detail opened from the Saved screen steps
24
+ * through the saved list instead. It is its own leaf for the same reason as
25
+ * native: it is the only part of the detail screen that needs the event LIST,
26
+ * so a request arriving re-renders this footer and nothing else.
27
+ *
28
+ * shared-ui RN chrome is replicated as DOM with provenance:
29
+ * - `EventStepperFooter` — inlined DOM twin below, values from
30
+ * shared/src/ui/components/EventStepperFooter.tsx (macOSColors verbatim;
31
+ * the native -2px shadow → an equivalent CSS box-shadow).
32
+ * - `applySafeAreaInset` maps `useSafeAreaInsets().bottom` →
33
+ * `env(safe-area-inset-bottom)` (0 on desktop webviews, the real inset on
34
+ * phone webviews).
35
+ *
36
+ * @platform React DOM Web
37
+ */
38
+
39
+ // =============================
40
+ // Native palette (provenance)
41
+ // =============================
42
+
43
+ /** macOSColors subset — shared/src/ui/gameUI/constants/macOSDesignSystemColors.ts, verbatim. */const macOSColors = {
44
+ background: {
45
+ base: "#0A0A0C",
46
+ card: "#1A1A1C"
47
+ },
48
+ border: {
49
+ default: "#2D2D2F"
50
+ },
51
+ text: {
52
+ primary: "#F5F5F7",
53
+ secondary: "#A1A1A6",
54
+ muted: "#8E8E93"
55
+ }
56
+ };
57
+
58
+ // =============================
59
+ // Inline lucide icons (shared-ui icons are lucide re-exports)
60
+ // =============================
61
+
62
+ function Svg({
63
+ size = 14,
64
+ color = "currentColor",
65
+ children
66
+ }) {
67
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
68
+ width: size,
69
+ height: size,
70
+ viewBox: "0 0 24 24",
71
+ fill: "none",
72
+ stroke: color,
73
+ strokeWidth: 2,
74
+ strokeLinecap: "round",
75
+ strokeLinejoin: "round",
76
+ style: {
77
+ flexShrink: 0,
78
+ display: "block"
79
+ },
80
+ children: children
81
+ });
82
+ }
83
+ const ChevronLeft = p => /*#__PURE__*/(0, _jsxRuntime.jsx)(Svg, {
84
+ ...p,
85
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
86
+ d: "m15 18-6-6 6-6"
87
+ })
88
+ });
89
+ const ChevronRight = p => /*#__PURE__*/(0, _jsxRuntime.jsx)(Svg, {
90
+ ...p,
91
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
92
+ d: "m9 18 6-6-6-6"
93
+ })
94
+ });
95
+
96
+ // =============================
97
+ // EventStepperFooter DOM twin (shared/src/ui/components/EventStepperFooter.tsx)
98
+ // =============================
99
+
100
+ const EventStepperFooter = /*#__PURE__*/(0, _react.memo)(function EventStepperFooter({
101
+ currentIndex,
102
+ totalItems,
103
+ onPrevious,
104
+ onNext,
105
+ itemLabel = "Event",
106
+ subtitle,
107
+ applySafeAreaInset = true
108
+ }) {
109
+ // Don't render if there's only one or no items (native).
110
+ if (totalItems <= 1) return null;
111
+ const isFirstItem = currentIndex === 0;
112
+ const isLastItem = currentIndex === totalItems - 1;
113
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
114
+ style: {
115
+ ...footerStyles.footer,
116
+ paddingBottom: applySafeAreaInset ? "calc(12px + env(safe-area-inset-bottom, 0px))" : 12
117
+ },
118
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
119
+ type: "button",
120
+ onClick: onPrevious,
121
+ disabled: isFirstItem,
122
+ style: {
123
+ ...footerStyles.navButton,
124
+ ...(isFirstItem ? footerStyles.navButtonDisabled : null)
125
+ },
126
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(ChevronLeft, {
127
+ size: 20,
128
+ color: isFirstItem ? macOSColors.text.muted : macOSColors.text.primary
129
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
130
+ style: {
131
+ ...footerStyles.navButtonText,
132
+ ...(isFirstItem ? footerStyles.navButtonTextDisabled : null)
133
+ },
134
+ children: "Previous"
135
+ })]
136
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
137
+ style: footerStyles.counterContainer,
138
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
139
+ style: footerStyles.counterText,
140
+ children: [itemLabel, " ", currentIndex + 1, " of ", totalItems]
141
+ }), subtitle ? /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
142
+ style: footerStyles.subtitleText,
143
+ children: subtitle
144
+ }) : null]
145
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("button", {
146
+ type: "button",
147
+ onClick: onNext,
148
+ disabled: isLastItem,
149
+ style: {
150
+ ...footerStyles.navButton,
151
+ ...(isLastItem ? footerStyles.navButtonDisabled : null)
152
+ },
153
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
154
+ style: {
155
+ ...footerStyles.navButtonText,
156
+ ...(isLastItem ? footerStyles.navButtonTextDisabled : null)
157
+ },
158
+ children: "Next"
159
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(ChevronRight, {
160
+ size: 20,
161
+ color: isLastItem ? macOSColors.text.muted : macOSColors.text.primary
162
+ })]
163
+ })]
164
+ });
165
+ });
166
+
167
+ // Values mirror the native StyleSheet block 1:1.
168
+ const footerStyles = {
169
+ footer: {
170
+ display: "flex",
171
+ flexDirection: "row",
172
+ alignItems: "center",
173
+ justifyContent: "space-between",
174
+ padding: "12px 16px 12px",
175
+ backgroundColor: macOSColors.background.base,
176
+ borderTop: `1px solid ${macOSColors.border.default}`,
177
+ // Native: shadowOffset 0/-2, opacity 0.1, radius 4.
178
+ boxShadow: "0 -2px 4px rgba(0, 0, 0, 0.1)",
179
+ flexShrink: 0
180
+ },
181
+ navButton: {
182
+ display: "inline-flex",
183
+ flexDirection: "row",
184
+ alignItems: "center",
185
+ gap: 6,
186
+ padding: "8px 12px",
187
+ borderRadius: 6,
188
+ backgroundColor: macOSColors.background.card,
189
+ minWidth: 100,
190
+ boxSizing: "border-box",
191
+ justifyContent: "center",
192
+ border: "none",
193
+ cursor: "pointer",
194
+ margin: 0
195
+ },
196
+ navButtonDisabled: {
197
+ opacity: 0.3,
198
+ cursor: "default"
199
+ },
200
+ navButtonText: {
201
+ fontSize: 12,
202
+ fontWeight: 600,
203
+ color: macOSColors.text.primary,
204
+ fontFamily: "ui-monospace, Menlo, monospace",
205
+ textTransform: "uppercase"
206
+ },
207
+ navButtonTextDisabled: {
208
+ color: macOSColors.text.muted
209
+ },
210
+ counterContainer: {
211
+ display: "flex",
212
+ flexDirection: "column",
213
+ alignItems: "center"
214
+ },
215
+ counterText: {
216
+ fontSize: 14,
217
+ fontWeight: 700,
218
+ color: macOSColors.text.primary,
219
+ fontFamily: "ui-monospace, Menlo, monospace",
220
+ textTransform: "uppercase"
221
+ },
222
+ subtitleText: {
223
+ fontSize: 11,
224
+ color: macOSColors.text.secondary,
225
+ fontFamily: "ui-monospace, Menlo, monospace",
226
+ marginTop: 2
227
+ }
228
+ };
229
+
230
+ // =============================
231
+ // Stepper (logic mirrors the native file 1:1)
232
+ // =============================
233
+
234
+ /** Stable identities — the store is a singleton, so these never need to change. */
235
+ const stepPrevious = () => _networkSelectionStore.networkSelectionStore.step(-1);
236
+ const stepNext = () => _networkSelectionStore.networkSelectionStore.step(1);
237
+ const NetworkDetailStepper = exports.NetworkDetailStepper = /*#__PURE__*/(0, _react.memo)(function NetworkDetailStepper({
238
+ paused,
239
+ filter,
240
+ ignoredPatterns,
241
+ isPro,
242
+ fromSaved,
243
+ savedSearch,
244
+ applySafeAreaInset
245
+ }) {
246
+ const {
247
+ visibleEvents
248
+ } = (0, _useNetworkEventList.useNetworkEventList)({
249
+ filter,
250
+ ignoredPatterns,
251
+ paused,
252
+ isPro
253
+ });
254
+ const {
255
+ pinnedEvents,
256
+ pinnedLiveIds,
257
+ savedRecords
258
+ } = (0, _useNetworkSaved.useNetworkSaved)();
259
+ const ordered = (0, _react.useMemo)(() => {
260
+ if (fromSaved) {
261
+ return (0, _selectSavedEvents.selectSavedEvents)(savedRecords, isPro, savedSearch).events;
262
+ }
263
+ // Same split the list screen does — pins render above the list, so they
264
+ // come first here too.
265
+ const {
266
+ pinned,
267
+ rest
268
+ } = (0, _withPinnedFirst.splitPinned)(visibleEvents, pinnedEvents, pinnedLiveIds);
269
+ return pinned.length === 0 ? rest : [...pinned, ...rest];
270
+ }, [fromSaved, savedRecords, savedSearch, isPro, visibleEvents, pinnedEvents, pinnedLiveIds]);
271
+
272
+ // Publish the navigable order. `setIds` re-anchors the cursor BY ID and
273
+ // no-ops when the ids are unchanged, so this is safe to run every render.
274
+ (0, _react.useEffect)(() => {
275
+ _networkSelectionStore.networkSelectionStore.setIds((0, _networkSelectionStore.toSelectionIds)(ordered));
276
+ }, [ordered]);
277
+ const {
278
+ index,
279
+ total
280
+ } = (0, _useNetworkSelection.useNetworkCursor)();
281
+
282
+ // Not in the list at all (filter changed under it, aged past the cap, or a
283
+ // saved snapshot with no live twin) — no footer rather than a counter that
284
+ // lies.
285
+ if (index < 0) return null;
286
+
287
+ // Both lists are newest-first, so "Previous" walks toward the NEWER request.
288
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(EventStepperFooter, {
289
+ currentIndex: index,
290
+ totalItems: total,
291
+ itemLabel: "Request",
292
+ applySafeAreaInset: applySafeAreaInset,
293
+ onPrevious: stepPrevious,
294
+ onNext: stepNext
295
+ });
296
+ });