@buoy-gg/network 7.0.15 → 7.0.17
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.web.js +395 -0
- package/lib/commonjs/network/components/DataViewer.web.js +879 -0
- package/lib/commonjs/network/components/NetworkCopyScreen.web.js +48 -0
- package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +1242 -0
- package/lib/commonjs/network/components/NetworkDetailScreen.web.js +101 -0
- package/lib/commonjs/network/components/NetworkDetailStepper.web.js +296 -0
- package/lib/commonjs/network/components/NetworkEventDetailView.web.js +1498 -0
- package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +802 -0
- package/lib/commonjs/network/components/NetworkFilterScreen.web.js +55 -0
- package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1310 -0
- package/lib/commonjs/network/components/NetworkHeaderLive.web.js +604 -0
- package/lib/commonjs/network/components/NetworkListScreen.js +2 -1
- package/lib/commonjs/network/components/NetworkListScreen.web.js +607 -0
- package/lib/commonjs/network/components/NetworkModal.js +12 -3
- package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +232 -0
- package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +942 -0
- package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +133 -0
- package/lib/commonjs/network/components/NetworkOverridesButton.web.js +143 -0
- package/lib/commonjs/network/components/NetworkOverridesScreen.js +160 -126
- package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +830 -0
- package/lib/commonjs/network/components/NetworkSavedScreen.web.js +459 -0
- package/lib/commonjs/network/components/response-editor/Explorer.web.js +1136 -0
- package/lib/commonjs/network/hooks/useNetworkEventList.js +12 -2
- package/lib/commonjs/network/overrides/applyToXhr.js +276 -15
- package/lib/commonjs/network/utils/generateNetworkCopyText.js +32 -5
- package/lib/commonjs/network/utils/networkEventStore.js +12 -4
- package/lib/commonjs/network/utils/networkListener.js +1 -16
- package/lib/module/index.web.js +81 -0
- package/lib/module/network/components/DataViewer.web.js +875 -0
- package/lib/module/network/components/NetworkCopyScreen.web.js +44 -0
- package/lib/module/network/components/NetworkCopySettingsView.web.js +1237 -0
- package/lib/module/network/components/NetworkDetailScreen.web.js +97 -0
- package/lib/module/network/components/NetworkDetailStepper.web.js +294 -0
- package/lib/module/network/components/NetworkEventDetailView.web.js +1496 -0
- package/lib/module/network/components/NetworkEventItemCompact.web.js +800 -0
- package/lib/module/network/components/NetworkFilterScreen.web.js +51 -0
- package/lib/module/network/components/NetworkFilterViewV3.web.js +1306 -0
- package/lib/module/network/components/NetworkHeaderLive.web.js +598 -0
- package/lib/module/network/components/NetworkListScreen.js +2 -1
- package/lib/module/network/components/NetworkListScreen.web.js +605 -0
- package/lib/module/network/components/NetworkModal.js +12 -3
- package/lib/module/network/components/NetworkNumberPrompt.web.js +230 -0
- package/lib/module/network/components/NetworkOverrideEditor.web.js +939 -0
- package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +131 -0
- package/lib/module/network/components/NetworkOverridesButton.web.js +141 -0
- package/lib/module/network/components/NetworkOverridesScreen.js +161 -127
- package/lib/module/network/components/NetworkOverridesScreen.web.js +826 -0
- package/lib/module/network/components/NetworkSavedScreen.web.js +457 -0
- package/lib/module/network/components/response-editor/Explorer.web.js +1133 -0
- package/lib/module/network/hooks/useNetworkEventList.js +12 -2
- package/lib/module/network/overrides/applyToXhr.js +275 -15
- package/lib/module/network/utils/generateNetworkCopyText.js +28 -1
- package/lib/module/network/utils/networkEventStore.js +12 -4
- package/lib/module/network/utils/networkListener.js +1 -16
- package/lib/typescript/index.web.d.ts +56 -0
- package/lib/typescript/index.web.d.ts.map +1 -0
- package/lib/typescript/network/components/DataViewer.web.d.ts +78 -0
- package/lib/typescript/network/components/DataViewer.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts +27 -0
- package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts +68 -0
- package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts +45 -0
- package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts +40 -0
- package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts +67 -0
- package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts +58 -0
- package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts +28 -0
- package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts +74 -0
- package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts +112 -0
- package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkListScreen.web.d.ts +63 -0
- package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts +38 -0
- package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts +43 -0
- package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts +32 -0
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts +26 -0
- package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts +9 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts +69 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts +67 -0
- package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/response-editor/Explorer.web.d.ts +56 -0
- package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +1 -0
- package/lib/typescript/network/hooks/useNetworkEventList.d.ts +10 -0
- package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +1 -1
- package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts.map +1 -1
- package/lib/typescript/network/overrides/applyToXhr.d.ts +40 -14
- package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -1
- package/lib/typescript/network/utils/generateNetworkCopyText.d.ts +34 -1
- package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkListener.d.ts +0 -1
- package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NetworkHeaderLive.web — DOM twin of NetworkHeaderLive.tsx.
|
|
5
|
+
*
|
|
6
|
+
* The header pieces that consume LIVE event data, each its own narrow store
|
|
7
|
+
* subscriber (same decomposition + hooks as native — `useNetworkBadgeCounts`,
|
|
8
|
+
* `useNetworkHasEvents`, `useNetworkSaved` are platform-free and reused, not
|
|
9
|
+
* forked):
|
|
10
|
+
*
|
|
11
|
+
* - `NetworkHeaderBadges` — success/error/pending count chips (tap toggles
|
|
12
|
+
* the status filter)
|
|
13
|
+
* - `NetworkClearButton` — trash button, enabled while the store has events
|
|
14
|
+
* - `NetworkSavedButton` — Saved-screen entry point with its live count
|
|
15
|
+
* - `NetworkDetailPinActions` — pin + save toggles for the request-DETAIL
|
|
16
|
+
* header (ported with the F3 detail-view feature; same flagsForEventId /
|
|
17
|
+
* cap logic and press-time event resolution as native)
|
|
18
|
+
* - `NetworkHeaderCopyButton` — copy-all button / labelled ⋯-menu row
|
|
19
|
+
* (ported with the F5 saved+copy feature; the copy text is the SAME
|
|
20
|
+
* platform-free `generateNetworkCopyText`, resolved lazily at press time
|
|
21
|
+
* from a live store read, exactly like native)
|
|
22
|
+
*
|
|
23
|
+
* shared-ui RN chrome is replicated as DOM with provenance (web consumers
|
|
24
|
+
* resolve `@buoy-gg/shared-ui` to a minimal shim):
|
|
25
|
+
* - `macOSColors` — inlined verbatim subset from
|
|
26
|
+
* shared/src/ui/gameUI/constants/macOSDesignSystemColors.ts.
|
|
27
|
+
* - Icons — inline lucide SVGs (shared-ui's icons are lucide re-exports).
|
|
28
|
+
* - The active chip's native shadow (shadowOffset 0/1, opacity 0.08,
|
|
29
|
+
* radius 2) → an equivalent CSS box-shadow.
|
|
30
|
+
* - shared-ui `CopyButton` (the Pro branch of the copy button) — inlined
|
|
31
|
+
* labelled DOM twin below: same idle/success/error icon set, 1500ms
|
|
32
|
+
* feedback, lazy function value, and label-follows-labelStyle behavior.
|
|
33
|
+
*
|
|
34
|
+
* Intentional deviations (all logged):
|
|
35
|
+
* - shared-ui CopyButton's ClipboardHintBanner and internal
|
|
36
|
+
* @buoy-gg/license Pro modal are not ported — license gating isn't part
|
|
37
|
+
* of the web port; the explicit `isPro` prop branch (native's own outer
|
|
38
|
+
* gate) still routes free users to `onUpgradePress`.
|
|
39
|
+
* - `CopySettings` is imported from the platform-free
|
|
40
|
+
* `generateNetworkCopyText` module (the native file imports it from
|
|
41
|
+
* NetworkCopySettingsView.tsx, which would drag react-native in).
|
|
42
|
+
*
|
|
43
|
+
* @platform React DOM Web
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
import { useEffect, useRef, useState } from "react";
|
|
47
|
+
import { networkEventStore } from "../utils/networkEventStore";
|
|
48
|
+
import { flagsForEventId, networkSavedStore, FREE_TIER_SAVED_LIMIT, MAX_PINNED, MAX_SAVED } from "../utils/networkSavedStore";
|
|
49
|
+
import { useNetworkSaved } from "../hooks/useNetworkSaved";
|
|
50
|
+
import { useSelectedNetworkEventId } from "../hooks/useNetworkSelection";
|
|
51
|
+
import { useNetworkBadgeCounts } from "../hooks/useNetworkBadgeCounts";
|
|
52
|
+
import { useNetworkHasEvents, useNetworkHasMatches } from "../hooks/useNetworkHasMatches";
|
|
53
|
+
import { generateNetworkCopyText } from "../utils/generateNetworkCopyText";
|
|
54
|
+
import { applyIgnoredPatterns, filterNetworkEvents } from "../utils/filterNetworkEvents";
|
|
55
|
+
|
|
56
|
+
// =============================
|
|
57
|
+
// Native palette (provenance)
|
|
58
|
+
// =============================
|
|
59
|
+
|
|
60
|
+
/** macOSColors subset — shared/src/ui/gameUI/constants/macOSDesignSystemColors.ts, verbatim. */
|
|
61
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
62
|
+
const macOSColors = {
|
|
63
|
+
background: {
|
|
64
|
+
hover: "#1D1D1F"
|
|
65
|
+
},
|
|
66
|
+
border: {
|
|
67
|
+
default: "#2D2D2F"
|
|
68
|
+
},
|
|
69
|
+
text: {
|
|
70
|
+
primary: "#F5F5F7",
|
|
71
|
+
secondary: "#A1A1A6",
|
|
72
|
+
muted: "#8E8E93",
|
|
73
|
+
disabled: "#9E9EA0"
|
|
74
|
+
},
|
|
75
|
+
semantic: {
|
|
76
|
+
success: "#34C759",
|
|
77
|
+
error: "#FF453A",
|
|
78
|
+
warning: "#FFEB3B",
|
|
79
|
+
info: "#00B8E6",
|
|
80
|
+
infoBackground: "rgba(0, 184, 230, 0.1)",
|
|
81
|
+
debug: "#BF5AF2"
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// =============================
|
|
86
|
+
// Inline lucide icons (shared-ui icons are lucide re-exports)
|
|
87
|
+
// =============================
|
|
88
|
+
|
|
89
|
+
function Svg({
|
|
90
|
+
size = 14,
|
|
91
|
+
color = "currentColor",
|
|
92
|
+
children
|
|
93
|
+
}) {
|
|
94
|
+
return /*#__PURE__*/_jsx("svg", {
|
|
95
|
+
width: size,
|
|
96
|
+
height: size,
|
|
97
|
+
viewBox: "0 0 24 24",
|
|
98
|
+
fill: "none",
|
|
99
|
+
stroke: color,
|
|
100
|
+
strokeWidth: 2,
|
|
101
|
+
strokeLinecap: "round",
|
|
102
|
+
strokeLinejoin: "round",
|
|
103
|
+
style: {
|
|
104
|
+
flexShrink: 0,
|
|
105
|
+
display: "block"
|
|
106
|
+
},
|
|
107
|
+
children: children
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const CheckCircle = p => /*#__PURE__*/_jsxs(Svg, {
|
|
111
|
+
...p,
|
|
112
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
113
|
+
d: "M21.801 10A10 10 0 1 1 17 3.335"
|
|
114
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
115
|
+
d: "m9 11 3 3L22 4"
|
|
116
|
+
})]
|
|
117
|
+
});
|
|
118
|
+
const XCircle = p => /*#__PURE__*/_jsxs(Svg, {
|
|
119
|
+
...p,
|
|
120
|
+
children: [/*#__PURE__*/_jsx("circle", {
|
|
121
|
+
cx: "12",
|
|
122
|
+
cy: "12",
|
|
123
|
+
r: "10"
|
|
124
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
125
|
+
d: "m15 9-6 6"
|
|
126
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
127
|
+
d: "m9 9 6 6"
|
|
128
|
+
})]
|
|
129
|
+
});
|
|
130
|
+
const Clock = p => /*#__PURE__*/_jsxs(Svg, {
|
|
131
|
+
...p,
|
|
132
|
+
children: [/*#__PURE__*/_jsx("circle", {
|
|
133
|
+
cx: "12",
|
|
134
|
+
cy: "12",
|
|
135
|
+
r: "10"
|
|
136
|
+
}), /*#__PURE__*/_jsx("polyline", {
|
|
137
|
+
points: "12 6 12 12 16 14"
|
|
138
|
+
})]
|
|
139
|
+
});
|
|
140
|
+
const Trash2 = p => /*#__PURE__*/_jsxs(Svg, {
|
|
141
|
+
...p,
|
|
142
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
143
|
+
d: "M3 6h18"
|
|
144
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
145
|
+
d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"
|
|
146
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
147
|
+
d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
|
|
148
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
149
|
+
x1: "10",
|
|
150
|
+
x2: "10",
|
|
151
|
+
y1: "11",
|
|
152
|
+
y2: "17"
|
|
153
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
154
|
+
x1: "14",
|
|
155
|
+
x2: "14",
|
|
156
|
+
y1: "11",
|
|
157
|
+
y2: "17"
|
|
158
|
+
})]
|
|
159
|
+
});
|
|
160
|
+
const Bookmark = p => /*#__PURE__*/_jsx(Svg, {
|
|
161
|
+
...p,
|
|
162
|
+
children: /*#__PURE__*/_jsx("path", {
|
|
163
|
+
d: "m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"
|
|
164
|
+
})
|
|
165
|
+
});
|
|
166
|
+
const Pin = p => /*#__PURE__*/_jsxs(Svg, {
|
|
167
|
+
...p,
|
|
168
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
169
|
+
d: "M12 17v5"
|
|
170
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
171
|
+
d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4h1z"
|
|
172
|
+
})]
|
|
173
|
+
});
|
|
174
|
+
const Copy = p => /*#__PURE__*/_jsxs(Svg, {
|
|
175
|
+
...p,
|
|
176
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
177
|
+
width: "14",
|
|
178
|
+
height: "14",
|
|
179
|
+
x: "8",
|
|
180
|
+
y: "8",
|
|
181
|
+
rx: "2",
|
|
182
|
+
ry: "2"
|
|
183
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
184
|
+
d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
|
|
185
|
+
})]
|
|
186
|
+
});
|
|
187
|
+
const CheckCircle2 = p => /*#__PURE__*/_jsxs(Svg, {
|
|
188
|
+
...p,
|
|
189
|
+
children: [/*#__PURE__*/_jsx("circle", {
|
|
190
|
+
cx: "12",
|
|
191
|
+
cy: "12",
|
|
192
|
+
r: "10"
|
|
193
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
194
|
+
d: "m9 12 2 2 4-4"
|
|
195
|
+
})]
|
|
196
|
+
});
|
|
197
|
+
const AlertTriangle = p => /*#__PURE__*/_jsxs(Svg, {
|
|
198
|
+
...p,
|
|
199
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
200
|
+
d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"
|
|
201
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
202
|
+
d: "M12 9v4"
|
|
203
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
204
|
+
d: "M12 17h.01"
|
|
205
|
+
})]
|
|
206
|
+
});
|
|
207
|
+
/** Success / error / pending chips — tap to toggle the status filter. */
|
|
208
|
+
export function NetworkHeaderBadges({
|
|
209
|
+
activeStatus,
|
|
210
|
+
onToggleStatus,
|
|
211
|
+
ignoredPatterns,
|
|
212
|
+
paused
|
|
213
|
+
}) {
|
|
214
|
+
const counts = useNetworkBadgeCounts({
|
|
215
|
+
ignoredPatterns,
|
|
216
|
+
paused
|
|
217
|
+
});
|
|
218
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
219
|
+
style: styles.headerChipRow,
|
|
220
|
+
children: [/*#__PURE__*/_jsxs("button", {
|
|
221
|
+
type: "button",
|
|
222
|
+
style: {
|
|
223
|
+
...styles.headerChip,
|
|
224
|
+
...(activeStatus === "success" ? styles.headerChipActive : null)
|
|
225
|
+
},
|
|
226
|
+
onClick: () => onToggleStatus("success"),
|
|
227
|
+
children: [/*#__PURE__*/_jsx(CheckCircle, {
|
|
228
|
+
size: 12,
|
|
229
|
+
color: macOSColors.semantic.success
|
|
230
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
231
|
+
style: {
|
|
232
|
+
...styles.headerChipValue,
|
|
233
|
+
color: macOSColors.semantic.success
|
|
234
|
+
},
|
|
235
|
+
children: counts.successful
|
|
236
|
+
})]
|
|
237
|
+
}), /*#__PURE__*/_jsxs("button", {
|
|
238
|
+
type: "button",
|
|
239
|
+
style: {
|
|
240
|
+
...styles.headerChip,
|
|
241
|
+
...(activeStatus === "error" ? styles.headerChipActive : null)
|
|
242
|
+
},
|
|
243
|
+
onClick: () => onToggleStatus("error"),
|
|
244
|
+
children: [/*#__PURE__*/_jsx(XCircle, {
|
|
245
|
+
size: 12,
|
|
246
|
+
color: macOSColors.semantic.error
|
|
247
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
248
|
+
style: {
|
|
249
|
+
...styles.headerChipValue,
|
|
250
|
+
color: macOSColors.semantic.error
|
|
251
|
+
},
|
|
252
|
+
children: counts.failed
|
|
253
|
+
})]
|
|
254
|
+
}), /*#__PURE__*/_jsxs("button", {
|
|
255
|
+
type: "button",
|
|
256
|
+
style: {
|
|
257
|
+
...styles.headerChip,
|
|
258
|
+
...(activeStatus === "pending" ? styles.headerChipActive : null)
|
|
259
|
+
},
|
|
260
|
+
onClick: () => onToggleStatus("pending"),
|
|
261
|
+
children: [/*#__PURE__*/_jsx(Clock, {
|
|
262
|
+
size: 12,
|
|
263
|
+
color: macOSColors.semantic.warning
|
|
264
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
265
|
+
style: {
|
|
266
|
+
...styles.headerChipValue,
|
|
267
|
+
color: macOSColors.semantic.warning
|
|
268
|
+
},
|
|
269
|
+
children: counts.pending
|
|
270
|
+
})]
|
|
271
|
+
})]
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/** Trash button — handler co-located; enabled while the store has events.
|
|
275
|
+
* Subscribes to a flip-guarded boolean, so it renders when the store goes
|
|
276
|
+
* empty↔non-empty, not on every count change. */
|
|
277
|
+
export function NetworkClearButton({
|
|
278
|
+
paused
|
|
279
|
+
}) {
|
|
280
|
+
const hasEvents = useNetworkHasEvents({
|
|
281
|
+
paused
|
|
282
|
+
});
|
|
283
|
+
return /*#__PURE__*/_jsx("button", {
|
|
284
|
+
type: "button",
|
|
285
|
+
"aria-label": "Clear events",
|
|
286
|
+
onClick: () => networkEventStore.clearEvents(),
|
|
287
|
+
style: {
|
|
288
|
+
...styles.headerActionButton,
|
|
289
|
+
...(!hasEvents ? styles.headerActionButtonDisabled : null)
|
|
290
|
+
},
|
|
291
|
+
disabled: !hasEvents,
|
|
292
|
+
children: /*#__PURE__*/_jsx(Trash2, {
|
|
293
|
+
size: 14,
|
|
294
|
+
color: hasEvents ? macOSColors.text.muted : macOSColors.text.disabled
|
|
295
|
+
})
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Entry point to the Saved screen, with its count. A self-subscribing leaf so
|
|
300
|
+
* the badge tracks the store without the modal header re-rendering.
|
|
301
|
+
*/
|
|
302
|
+
export function NetworkSavedButton({
|
|
303
|
+
onPress
|
|
304
|
+
}) {
|
|
305
|
+
const {
|
|
306
|
+
savedRecords
|
|
307
|
+
} = useNetworkSaved();
|
|
308
|
+
const count = savedRecords.length;
|
|
309
|
+
return /*#__PURE__*/_jsxs("button", {
|
|
310
|
+
type: "button",
|
|
311
|
+
onClick: onPress,
|
|
312
|
+
"aria-label": "Saved requests",
|
|
313
|
+
style: styles.headerActionButton,
|
|
314
|
+
children: [/*#__PURE__*/_jsx(Bookmark, {
|
|
315
|
+
size: 14,
|
|
316
|
+
color: count > 0 ? macOSColors.semantic.debug : macOSColors.text.muted
|
|
317
|
+
}), count > 0 ? /*#__PURE__*/_jsx("span", {
|
|
318
|
+
style: styles.savedBadge,
|
|
319
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
320
|
+
style: styles.savedBadgeText,
|
|
321
|
+
children: count > 99 ? "99+" : count
|
|
322
|
+
})
|
|
323
|
+
}) : null]
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Pin + Save toggles for the request-detail header — same self-subscribing
|
|
328
|
+
* leaf as native, for the same two reasons: the host root stays free of
|
|
329
|
+
* subscriptions, and these buttons deliberately do NOT live inside
|
|
330
|
+
* `NetworkEventDetailView` (the Events tool renders that same detail view
|
|
331
|
+
* with no saved store behind it).
|
|
332
|
+
*
|
|
333
|
+
* The event object is resolved at PRESS time (live store first, then the
|
|
334
|
+
* saved snapshot), and the selected id is SUBSCRIBED here rather than passed
|
|
335
|
+
* down, so stepping through requests doesn't rebuild the host header.
|
|
336
|
+
*/
|
|
337
|
+
export function NetworkDetailPinActions({
|
|
338
|
+
isPro,
|
|
339
|
+
onUpgradePress
|
|
340
|
+
}) {
|
|
341
|
+
const eventId = useSelectedNetworkEventId();
|
|
342
|
+
const state = useNetworkSaved();
|
|
343
|
+
const {
|
|
344
|
+
pinned,
|
|
345
|
+
saved
|
|
346
|
+
} = flagsForEventId(state, eventId);
|
|
347
|
+
const savedLimit = isPro ? MAX_SAVED : FREE_TIER_SAVED_LIMIT;
|
|
348
|
+
const atPinCap = !pinned && state.pinnedEvents.length >= MAX_PINNED;
|
|
349
|
+
const atSavedCap = !saved && state.savedRecords.length >= savedLimit;
|
|
350
|
+
const resolveEvent = () => {
|
|
351
|
+
if (!eventId) return null;
|
|
352
|
+
return networkEventStore.getEvents().find(event => event.id === eventId) ?? networkSavedStore.getEventById(eventId);
|
|
353
|
+
};
|
|
354
|
+
const handlePin = () => {
|
|
355
|
+
const event = resolveEvent();
|
|
356
|
+
if (event) state.togglePin(event);
|
|
357
|
+
};
|
|
358
|
+
const handleSave = () => {
|
|
359
|
+
// Hitting the free ceiling is an upgrade moment, not a dead button.
|
|
360
|
+
if (atSavedCap && !isPro) {
|
|
361
|
+
onUpgradePress();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const event = resolveEvent();
|
|
365
|
+
if (event) state.toggleSave(event);
|
|
366
|
+
};
|
|
367
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
368
|
+
children: [/*#__PURE__*/_jsx("button", {
|
|
369
|
+
type: "button",
|
|
370
|
+
onClick: handlePin,
|
|
371
|
+
disabled: atPinCap,
|
|
372
|
+
"aria-label": pinned ? "Unpin request" : "Pin request",
|
|
373
|
+
title: atPinCap ? `Pin limit reached (${MAX_PINNED})` : undefined,
|
|
374
|
+
style: {
|
|
375
|
+
...styles.headerActionButton,
|
|
376
|
+
...(pinned ? styles.headerActionButtonActive : null),
|
|
377
|
+
...(atPinCap ? styles.headerActionButtonDisabled : null)
|
|
378
|
+
},
|
|
379
|
+
children: /*#__PURE__*/_jsx(Pin, {
|
|
380
|
+
size: 14,
|
|
381
|
+
color: pinned ? macOSColors.semantic.info : atPinCap ? macOSColors.text.disabled : macOSColors.text.secondary
|
|
382
|
+
})
|
|
383
|
+
}), /*#__PURE__*/_jsx("button", {
|
|
384
|
+
type: "button",
|
|
385
|
+
onClick: handleSave,
|
|
386
|
+
disabled: atSavedCap && isPro,
|
|
387
|
+
"aria-label": saved ? "Remove from saved" : "Save request",
|
|
388
|
+
title: atSavedCap && isPro ? `Saved limit reached (${MAX_SAVED})` : undefined,
|
|
389
|
+
style: {
|
|
390
|
+
...styles.headerActionButton,
|
|
391
|
+
...(saved ? styles.headerActionButtonSaved : null),
|
|
392
|
+
...(atSavedCap && isPro ? styles.headerActionButtonDisabled : null)
|
|
393
|
+
},
|
|
394
|
+
children: /*#__PURE__*/_jsx(Bookmark, {
|
|
395
|
+
size: 14,
|
|
396
|
+
color: saved ? macOSColors.semantic.debug : atSavedCap && isPro ? macOSColors.text.disabled : macOSColors.text.secondary
|
|
397
|
+
})
|
|
398
|
+
})]
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Copy-all-requests button. Subscribes to a flip-guarded boolean (its
|
|
403
|
+
* enabled state); the copy text is generated at PRESS time from a live
|
|
404
|
+
* store read, so there's no per-event work and no stale closure.
|
|
405
|
+
*
|
|
406
|
+
* The Pro branch inlines shared-ui CopyButton's copy/feedback loop (same
|
|
407
|
+
* icon set, 1500ms feedback, label keeps its own color while the icon
|
|
408
|
+
* follows the state — native's `labelStyle` wins over the state color).
|
|
409
|
+
*/
|
|
410
|
+
export function NetworkHeaderCopyButton({
|
|
411
|
+
isPro,
|
|
412
|
+
filter,
|
|
413
|
+
ignoredPatterns,
|
|
414
|
+
copySettings,
|
|
415
|
+
paused,
|
|
416
|
+
onUpgradePress,
|
|
417
|
+
label
|
|
418
|
+
}) {
|
|
419
|
+
const hasEvents = useNetworkHasMatches({
|
|
420
|
+
filter,
|
|
421
|
+
ignoredPatterns,
|
|
422
|
+
paused
|
|
423
|
+
});
|
|
424
|
+
const [copyState, setCopyState] = useState("idle");
|
|
425
|
+
const timeoutRef = useRef(null);
|
|
426
|
+
useEffect(() => () => {
|
|
427
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
428
|
+
}, []);
|
|
429
|
+
if (!isPro) {
|
|
430
|
+
return /*#__PURE__*/_jsxs("button", {
|
|
431
|
+
type: "button",
|
|
432
|
+
onClick: onUpgradePress,
|
|
433
|
+
style: {
|
|
434
|
+
...(label ? styles.copyMenuRow : styles.headerActionButton),
|
|
435
|
+
...(!hasEvents ? styles.headerActionButtonDisabled : null)
|
|
436
|
+
},
|
|
437
|
+
disabled: !hasEvents,
|
|
438
|
+
"aria-label": label ?? "Copy requests",
|
|
439
|
+
children: [/*#__PURE__*/_jsx(Copy, {
|
|
440
|
+
size: 14,
|
|
441
|
+
color: hasEvents ? macOSColors.text.secondary : macOSColors.text.disabled
|
|
442
|
+
}), label ? /*#__PURE__*/_jsx("span", {
|
|
443
|
+
style: styles.copyMenuLabel,
|
|
444
|
+
children: label
|
|
445
|
+
}) : null]
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
const settle = state => {
|
|
449
|
+
setCopyState(state);
|
|
450
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
451
|
+
// 1500ms — shared-ui CopyButton's `feedbackDuration` default.
|
|
452
|
+
timeoutRef.current = setTimeout(() => {
|
|
453
|
+
setCopyState("idle");
|
|
454
|
+
timeoutRef.current = null;
|
|
455
|
+
}, 1500);
|
|
456
|
+
};
|
|
457
|
+
const handleCopy = async () => {
|
|
458
|
+
try {
|
|
459
|
+
// Lazy value: resolved at copy time from the LIVE store — no per-event
|
|
460
|
+
// work, no staleness (native's CopyButton function-value contract).
|
|
461
|
+
const text = generateNetworkCopyText(filterNetworkEvents(applyIgnoredPatterns(networkEventStore.getEvents(), ignoredPatterns), filter), copySettings);
|
|
462
|
+
await navigator.clipboard.writeText(text);
|
|
463
|
+
settle("success");
|
|
464
|
+
} catch {
|
|
465
|
+
settle("error");
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
const iconColor = copyState === "success" ? macOSColors.semantic.success : copyState === "error" ? macOSColors.semantic.error : hasEvents ? macOSColors.text.secondary : macOSColors.text.disabled;
|
|
469
|
+
return /*#__PURE__*/_jsxs("button", {
|
|
470
|
+
type: "button",
|
|
471
|
+
onClick: copyState === "idle" ? handleCopy : undefined,
|
|
472
|
+
style: {
|
|
473
|
+
...(label ? styles.copyMenuRow : styles.headerActionButton),
|
|
474
|
+
...(!hasEvents ? styles.headerActionButtonDisabled : null)
|
|
475
|
+
},
|
|
476
|
+
disabled: !hasEvents,
|
|
477
|
+
"aria-label": copyState === "idle" ? label ?? "Copy to clipboard" : copyState === "success" ? "Copied to clipboard" : "Failed to copy",
|
|
478
|
+
children: [copyState === "success" ? /*#__PURE__*/_jsx(CheckCircle2, {
|
|
479
|
+
size: 14,
|
|
480
|
+
color: iconColor
|
|
481
|
+
}) : copyState === "error" ? /*#__PURE__*/_jsx(AlertTriangle, {
|
|
482
|
+
size: 14,
|
|
483
|
+
color: iconColor
|
|
484
|
+
}) : /*#__PURE__*/_jsx(Copy, {
|
|
485
|
+
size: 14,
|
|
486
|
+
color: iconColor
|
|
487
|
+
}), label ? /*#__PURE__*/_jsx("span", {
|
|
488
|
+
style: styles.copyMenuLabel,
|
|
489
|
+
children: label
|
|
490
|
+
}) : null]
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Values mirror the native StyleSheet block 1:1.
|
|
495
|
+
const styles = {
|
|
496
|
+
/** The overflow-menu variant: a full-width row, matching the other items. */
|
|
497
|
+
copyMenuRow: {
|
|
498
|
+
display: "flex",
|
|
499
|
+
width: "100%",
|
|
500
|
+
boxSizing: "border-box",
|
|
501
|
+
flexDirection: "row",
|
|
502
|
+
alignItems: "center",
|
|
503
|
+
gap: 10,
|
|
504
|
+
padding: "11px 6px",
|
|
505
|
+
justifyContent: "flex-start",
|
|
506
|
+
background: "none",
|
|
507
|
+
border: "none",
|
|
508
|
+
cursor: "pointer",
|
|
509
|
+
margin: 0,
|
|
510
|
+
fontFamily: "inherit",
|
|
511
|
+
textAlign: "left"
|
|
512
|
+
},
|
|
513
|
+
copyMenuLabel: {
|
|
514
|
+
fontSize: 13,
|
|
515
|
+
fontWeight: 600,
|
|
516
|
+
color: macOSColors.text.primary
|
|
517
|
+
},
|
|
518
|
+
headerChipRow: {
|
|
519
|
+
display: "flex",
|
|
520
|
+
flexDirection: "row",
|
|
521
|
+
alignItems: "center",
|
|
522
|
+
gap: 8
|
|
523
|
+
},
|
|
524
|
+
/**
|
|
525
|
+
* Counter chips and toolbar buttons carry a permanent outline; the fill
|
|
526
|
+
* marks the active filter.
|
|
527
|
+
*/
|
|
528
|
+
headerChip: {
|
|
529
|
+
display: "inline-flex",
|
|
530
|
+
flexDirection: "row",
|
|
531
|
+
alignItems: "center",
|
|
532
|
+
gap: 4,
|
|
533
|
+
backgroundColor: macOSColors.background.hover,
|
|
534
|
+
padding: "5px 10px",
|
|
535
|
+
borderRadius: 12,
|
|
536
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
537
|
+
cursor: "pointer",
|
|
538
|
+
margin: 0
|
|
539
|
+
},
|
|
540
|
+
headerChipActive: {
|
|
541
|
+
backgroundColor: macOSColors.semantic.infoBackground,
|
|
542
|
+
border: `1px solid ${macOSColors.semantic.info}50`,
|
|
543
|
+
// Native: shadowColor info, offset 0/1, opacity 0.08, radius 2.
|
|
544
|
+
boxShadow: "0 1px 2px rgba(0, 184, 230, 0.08)"
|
|
545
|
+
},
|
|
546
|
+
headerChipValue: {
|
|
547
|
+
fontSize: 12,
|
|
548
|
+
fontWeight: 600,
|
|
549
|
+
fontFamily: "ui-monospace, Menlo, monospace"
|
|
550
|
+
},
|
|
551
|
+
headerActionButton: {
|
|
552
|
+
position: "relative",
|
|
553
|
+
display: "inline-flex",
|
|
554
|
+
width: 32,
|
|
555
|
+
height: 32,
|
|
556
|
+
boxSizing: "border-box",
|
|
557
|
+
borderRadius: 8,
|
|
558
|
+
backgroundColor: macOSColors.background.hover,
|
|
559
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
560
|
+
alignItems: "center",
|
|
561
|
+
justifyContent: "center",
|
|
562
|
+
cursor: "pointer",
|
|
563
|
+
padding: 0,
|
|
564
|
+
margin: 0
|
|
565
|
+
},
|
|
566
|
+
headerActionButtonDisabled: {
|
|
567
|
+
opacity: 0.55,
|
|
568
|
+
cursor: "default"
|
|
569
|
+
},
|
|
570
|
+
headerActionButtonActive: {
|
|
571
|
+
backgroundColor: macOSColors.semantic.infoBackground,
|
|
572
|
+
border: `1px solid ${macOSColors.semantic.info}50`
|
|
573
|
+
},
|
|
574
|
+
headerActionButtonSaved: {
|
|
575
|
+
backgroundColor: `${macOSColors.semantic.debug}1A`,
|
|
576
|
+
border: `1px solid ${macOSColors.semantic.debug}50`
|
|
577
|
+
},
|
|
578
|
+
savedBadge: {
|
|
579
|
+
position: "absolute",
|
|
580
|
+
top: -3,
|
|
581
|
+
right: -3,
|
|
582
|
+
minWidth: 14,
|
|
583
|
+
height: 14,
|
|
584
|
+
boxSizing: "border-box",
|
|
585
|
+
padding: "0 3px",
|
|
586
|
+
borderRadius: 7,
|
|
587
|
+
backgroundColor: macOSColors.semantic.debug,
|
|
588
|
+
display: "inline-flex",
|
|
589
|
+
alignItems: "center",
|
|
590
|
+
justifyContent: "center"
|
|
591
|
+
},
|
|
592
|
+
savedBadgeText: {
|
|
593
|
+
color: "#FFFFFF",
|
|
594
|
+
fontSize: 9,
|
|
595
|
+
fontWeight: 700,
|
|
596
|
+
fontFamily: "ui-monospace, Menlo, monospace"
|
|
597
|
+
}
|
|
598
|
+
};
|