@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,1496 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* NetworkEventDetailView.web — DOM twin of NetworkEventDetailView.tsx.
|
|
5
|
+
*
|
|
6
|
+
* The request DETAIL inspector: method/status/duration header row, URL
|
|
7
|
+
* breakdown (with collapsible query parameters), error box, timing card
|
|
8
|
+
* (Started + Sent/Received + the two real timing-phase bars), collapsible
|
|
9
|
+
* Request/Response Headers, Request/Response Body (JSON trees, response
|
|
10
|
+
* expanded on arrival), and the Filter Options section — same section order,
|
|
11
|
+
* labels, defaults and styling as native. The data layer is REUSED, not
|
|
12
|
+
* forked: `useNetworkBodyResolver` (plain React context), `formatGraphQLDisplay`
|
|
13
|
+
* and the `NetworkEvent`/`NetworkTimings` types are the same modules native
|
|
14
|
+
* uses; `showBodies` carries the same settle-window contract (see the native
|
|
15
|
+
* file's prop doc) with the same fixed-height `BodyDeferred` stand-in.
|
|
16
|
+
*
|
|
17
|
+
* shared-ui RN chrome is replicated as DOM with provenance (web consumers
|
|
18
|
+
* resolve `@buoy-gg/shared-ui` to a minimal shim):
|
|
19
|
+
* - `macOSColors` — inlined verbatim subset from
|
|
20
|
+
* shared/src/ui/gameUI/constants/macOSDesignSystemColors.ts.
|
|
21
|
+
* - Icons — inline lucide SVGs (shared-ui's icons are lucide re-exports).
|
|
22
|
+
* - `formatBytes` / `formatDuration` — copied verbatim from
|
|
23
|
+
* shared/src/utils/formatting/dataFormatting.ts (not in the web shim).
|
|
24
|
+
* - `formatHttpStatus` — copied verbatim from
|
|
25
|
+
* shared/src/utils/formatting/httpFormatting.ts; its `gameUIColors` are the
|
|
26
|
+
* macOS theme, so the color table below carries the same resolved values.
|
|
27
|
+
* - `formatRelativeTime` — copied verbatim from
|
|
28
|
+
* shared/src/utils/time/formatRelativeTime.ts.
|
|
29
|
+
* - `DataViewer` / `InlineCopyButton` — DOM twins in ./DataViewer.web.
|
|
30
|
+
*
|
|
31
|
+
* Intentional deviations (all logged):
|
|
32
|
+
* - License gating isn't part of the web port: the view renders the Pro path
|
|
33
|
+
* (`isPro = true` everywhere native branches) — copy buttons are real
|
|
34
|
+
* clipboard copies, never upgrade prompts — and shared-ui's `UpgradeModal`
|
|
35
|
+
* is therefore not mounted (`useFeatureGate` lives behind @buoy-gg/license,
|
|
36
|
+
* outside the web port).
|
|
37
|
+
* - Copy affordances use `navigator.clipboard` via the CopyButton twin; the
|
|
38
|
+
* full-request copy keeps native's LAZY function value so no markdown is
|
|
39
|
+
* built per render.
|
|
40
|
+
* - Relative time ("12s ago") refreshes on re-render only — native mounts a
|
|
41
|
+
* `TickProvider` at the modal root; the web port's live-event subscription
|
|
42
|
+
* re-renders an open detail on every store update, which covers it in
|
|
43
|
+
* practice for in-flight requests.
|
|
44
|
+
*
|
|
45
|
+
* @platform React DOM Web
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
import { memo, useEffect, useMemo, useState } from "react";
|
|
49
|
+
import { formatGraphQLDisplay } from "../utils/formatGraphQLVariables";
|
|
50
|
+
import { useNetworkBodyResolver } from "../sync/networkBodyResolver";
|
|
51
|
+
import { DataViewer, InlineCopyButton } from "./DataViewer.web";
|
|
52
|
+
|
|
53
|
+
// =============================
|
|
54
|
+
// Native palettes (provenance)
|
|
55
|
+
// =============================
|
|
56
|
+
|
|
57
|
+
/** macOSColors subset — shared/src/ui/gameUI/constants/macOSDesignSystemColors.ts, verbatim. */
|
|
58
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
59
|
+
const macOSColors = {
|
|
60
|
+
background: {
|
|
61
|
+
base: "#0A0A0C",
|
|
62
|
+
card: "#1A1A1C",
|
|
63
|
+
hover: "#1D1D1F",
|
|
64
|
+
input: "#26262A"
|
|
65
|
+
},
|
|
66
|
+
border: {
|
|
67
|
+
default: "#2D2D2F"
|
|
68
|
+
},
|
|
69
|
+
text: {
|
|
70
|
+
primary: "#F5F5F7",
|
|
71
|
+
secondary: "#A1A1A6",
|
|
72
|
+
muted: "#8E8E93"
|
|
73
|
+
},
|
|
74
|
+
semantic: {
|
|
75
|
+
success: "#34C759",
|
|
76
|
+
error: "#FF453A",
|
|
77
|
+
errorBackground: "rgba(255, 69, 58, 0.15)",
|
|
78
|
+
warning: "#FFEB3B",
|
|
79
|
+
warningBackground: "rgba(255, 235, 59, 0.15)",
|
|
80
|
+
info: "#00B8E6",
|
|
81
|
+
infoBackground: "rgba(0, 184, 230, 0.1)"
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Colour for the icons that merely LABEL a section (Sent/Received, the JSON
|
|
87
|
+
* body glyphs) — same rationale as native.
|
|
88
|
+
*/
|
|
89
|
+
const NEUTRAL_ICON = macOSColors.semantic.success;
|
|
90
|
+
|
|
91
|
+
// =============================
|
|
92
|
+
// Formatting utils (provenance: shared/src/utils — not in the web shim)
|
|
93
|
+
// =============================
|
|
94
|
+
|
|
95
|
+
/** shared/src/utils/formatting/dataFormatting.ts `formatBytes`, verbatim. */
|
|
96
|
+
function formatBytes(bytes) {
|
|
97
|
+
if (bytes === undefined || bytes === null) return "N/A";
|
|
98
|
+
if (bytes === 0) return "0 B";
|
|
99
|
+
const k = 1024;
|
|
100
|
+
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
101
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
102
|
+
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** shared/src/utils/formatting/dataFormatting.ts `formatDuration`, verbatim. */
|
|
106
|
+
function formatDuration(ms) {
|
|
107
|
+
if (ms === undefined || ms === null) return "N/A";
|
|
108
|
+
if (ms < 1000) return `${ms}ms`;
|
|
109
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
|
|
110
|
+
if (ms < 3600000) {
|
|
111
|
+
const minutes = Math.floor(ms / 60000);
|
|
112
|
+
const seconds = Math.floor(ms % 60000 / 1000);
|
|
113
|
+
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
114
|
+
}
|
|
115
|
+
const hours = Math.floor(ms / 3600000);
|
|
116
|
+
const minutes = Math.floor(ms % 3600000 / 60000);
|
|
117
|
+
return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** shared/src/utils/time/formatRelativeTime.ts, verbatim. */
|
|
121
|
+
function formatRelativeTime(timestamp, currentTime = Date.now()) {
|
|
122
|
+
const timestampMs = timestamp instanceof Date ? timestamp.getTime() : timestamp;
|
|
123
|
+
const seconds = Math.floor((currentTime - timestampMs) / 1000);
|
|
124
|
+
if (seconds < 0) return "just now";
|
|
125
|
+
if (seconds < 60) return seconds === 0 ? "just now" : `${seconds}s ago`;
|
|
126
|
+
const minutes = Math.floor(seconds / 60);
|
|
127
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
128
|
+
const hours = Math.floor(minutes / 60);
|
|
129
|
+
if (hours < 24) return `${hours}h ago`;
|
|
130
|
+
const days = Math.floor(hours / 24);
|
|
131
|
+
return `${days}d ago`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* shared/src/utils/formatting/httpFormatting.ts `formatHttpStatus`, verbatim —
|
|
136
|
+
* its `gameUIColors` resolve to the macOS theme's semantic values (the same
|
|
137
|
+
* `macOSColors.semantic` palette inlined above; muted = text.muted).
|
|
138
|
+
*/
|
|
139
|
+
function formatHttpStatus(status) {
|
|
140
|
+
if (status >= 100 && status < 200) {
|
|
141
|
+
return {
|
|
142
|
+
text: String(status),
|
|
143
|
+
color: macOSColors.semantic.info,
|
|
144
|
+
meaning: "Informational"
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (status >= 200 && status < 300) {
|
|
148
|
+
const meanings = {
|
|
149
|
+
200: "OK",
|
|
150
|
+
201: "Created",
|
|
151
|
+
202: "Accepted",
|
|
152
|
+
204: "No Content",
|
|
153
|
+
206: "Partial Content"
|
|
154
|
+
};
|
|
155
|
+
return {
|
|
156
|
+
text: String(status),
|
|
157
|
+
color: macOSColors.semantic.success,
|
|
158
|
+
meaning: meanings[status] || "Success"
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (status >= 300 && status < 400) {
|
|
162
|
+
const meanings = {
|
|
163
|
+
301: "Moved Permanently",
|
|
164
|
+
302: "Found",
|
|
165
|
+
303: "See Other",
|
|
166
|
+
304: "Not Modified",
|
|
167
|
+
307: "Temporary Redirect",
|
|
168
|
+
308: "Permanent Redirect"
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
text: String(status),
|
|
172
|
+
color: macOSColors.semantic.warning,
|
|
173
|
+
meaning: meanings[status] || "Redirect"
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (status >= 400 && status < 500) {
|
|
177
|
+
const meanings = {
|
|
178
|
+
400: "Bad Request",
|
|
179
|
+
401: "Unauthorized",
|
|
180
|
+
402: "Payment Required",
|
|
181
|
+
403: "Forbidden",
|
|
182
|
+
404: "Not Found",
|
|
183
|
+
405: "Method Not Allowed",
|
|
184
|
+
408: "Request Timeout",
|
|
185
|
+
409: "Conflict",
|
|
186
|
+
410: "Gone",
|
|
187
|
+
422: "Unprocessable Entity",
|
|
188
|
+
429: "Too Many Requests"
|
|
189
|
+
};
|
|
190
|
+
return {
|
|
191
|
+
text: String(status),
|
|
192
|
+
color: macOSColors.semantic.error,
|
|
193
|
+
meaning: meanings[status] || "Client Error"
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
if (status >= 500) {
|
|
197
|
+
const meanings = {
|
|
198
|
+
500: "Internal Server Error",
|
|
199
|
+
501: "Not Implemented",
|
|
200
|
+
502: "Bad Gateway",
|
|
201
|
+
503: "Service Unavailable",
|
|
202
|
+
504: "Gateway Timeout",
|
|
203
|
+
505: "HTTP Version Not Supported"
|
|
204
|
+
};
|
|
205
|
+
return {
|
|
206
|
+
text: String(status),
|
|
207
|
+
color: macOSColors.semantic.error,
|
|
208
|
+
meaning: meanings[status] || "Server Error"
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
text: String(status),
|
|
213
|
+
color: macOSColors.text.muted,
|
|
214
|
+
meaning: "Unknown"
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// =============================
|
|
219
|
+
// Inline lucide icons (shared-ui icons are lucide re-exports)
|
|
220
|
+
// =============================
|
|
221
|
+
|
|
222
|
+
function Svg({
|
|
223
|
+
size = 14,
|
|
224
|
+
color = "currentColor",
|
|
225
|
+
children
|
|
226
|
+
}) {
|
|
227
|
+
return /*#__PURE__*/_jsx("svg", {
|
|
228
|
+
width: size,
|
|
229
|
+
height: size,
|
|
230
|
+
viewBox: "0 0 24 24",
|
|
231
|
+
fill: "none",
|
|
232
|
+
stroke: color,
|
|
233
|
+
strokeWidth: 2,
|
|
234
|
+
strokeLinecap: "round",
|
|
235
|
+
strokeLinejoin: "round",
|
|
236
|
+
style: {
|
|
237
|
+
flexShrink: 0,
|
|
238
|
+
display: "block"
|
|
239
|
+
},
|
|
240
|
+
children: children
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
const Clock = p => /*#__PURE__*/_jsxs(Svg, {
|
|
244
|
+
...p,
|
|
245
|
+
children: [/*#__PURE__*/_jsx("circle", {
|
|
246
|
+
cx: "12",
|
|
247
|
+
cy: "12",
|
|
248
|
+
r: "10"
|
|
249
|
+
}), /*#__PURE__*/_jsx("polyline", {
|
|
250
|
+
points: "12 6 12 12 16 14"
|
|
251
|
+
})]
|
|
252
|
+
});
|
|
253
|
+
const Upload = p => /*#__PURE__*/_jsxs(Svg, {
|
|
254
|
+
...p,
|
|
255
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
256
|
+
d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
|
|
257
|
+
}), /*#__PURE__*/_jsx("polyline", {
|
|
258
|
+
points: "17 8 12 3 7 8"
|
|
259
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
260
|
+
x1: "12",
|
|
261
|
+
x2: "12",
|
|
262
|
+
y1: "3",
|
|
263
|
+
y2: "15"
|
|
264
|
+
})]
|
|
265
|
+
});
|
|
266
|
+
const Download = p => /*#__PURE__*/_jsxs(Svg, {
|
|
267
|
+
...p,
|
|
268
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
269
|
+
d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
|
|
270
|
+
}), /*#__PURE__*/_jsx("polyline", {
|
|
271
|
+
points: "7 10 12 15 17 10"
|
|
272
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
273
|
+
x1: "12",
|
|
274
|
+
x2: "12",
|
|
275
|
+
y1: "15",
|
|
276
|
+
y2: "3"
|
|
277
|
+
})]
|
|
278
|
+
});
|
|
279
|
+
const AlertCircle = p => /*#__PURE__*/_jsxs(Svg, {
|
|
280
|
+
...p,
|
|
281
|
+
children: [/*#__PURE__*/_jsx("circle", {
|
|
282
|
+
cx: "12",
|
|
283
|
+
cy: "12",
|
|
284
|
+
r: "10"
|
|
285
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
286
|
+
x1: "12",
|
|
287
|
+
x2: "12",
|
|
288
|
+
y1: "8",
|
|
289
|
+
y2: "12"
|
|
290
|
+
}), /*#__PURE__*/_jsx("line", {
|
|
291
|
+
x1: "12",
|
|
292
|
+
x2: "12.01",
|
|
293
|
+
y1: "16",
|
|
294
|
+
y2: "16"
|
|
295
|
+
})]
|
|
296
|
+
});
|
|
297
|
+
const ChevronDown = p => /*#__PURE__*/_jsx(Svg, {
|
|
298
|
+
...p,
|
|
299
|
+
children: /*#__PURE__*/_jsx("path", {
|
|
300
|
+
d: "m6 9 6 6 6-6"
|
|
301
|
+
})
|
|
302
|
+
});
|
|
303
|
+
const ChevronUp = p => /*#__PURE__*/_jsx(Svg, {
|
|
304
|
+
...p,
|
|
305
|
+
children: /*#__PURE__*/_jsx("path", {
|
|
306
|
+
d: "m18 15-6-6-6 6"
|
|
307
|
+
})
|
|
308
|
+
});
|
|
309
|
+
const Lock = p => /*#__PURE__*/_jsxs(Svg, {
|
|
310
|
+
...p,
|
|
311
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
312
|
+
width: "18",
|
|
313
|
+
height: "11",
|
|
314
|
+
x: "3",
|
|
315
|
+
y: "11",
|
|
316
|
+
rx: "2",
|
|
317
|
+
ry: "2"
|
|
318
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
319
|
+
d: "M7 11V7a5 5 0 0 1 10 0v4"
|
|
320
|
+
})]
|
|
321
|
+
});
|
|
322
|
+
const Unlock = p => /*#__PURE__*/_jsxs(Svg, {
|
|
323
|
+
...p,
|
|
324
|
+
children: [/*#__PURE__*/_jsx("rect", {
|
|
325
|
+
width: "18",
|
|
326
|
+
height: "11",
|
|
327
|
+
x: "3",
|
|
328
|
+
y: "11",
|
|
329
|
+
rx: "2",
|
|
330
|
+
ry: "2"
|
|
331
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
332
|
+
d: "M7 11V7a5 5 0 0 1 9.9-1"
|
|
333
|
+
})]
|
|
334
|
+
});
|
|
335
|
+
const FileJson = p => /*#__PURE__*/_jsxs(Svg, {
|
|
336
|
+
...p,
|
|
337
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
338
|
+
d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
|
|
339
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
340
|
+
d: "M14 2v4a2 2 0 0 0 2 2h4"
|
|
341
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
342
|
+
d: "M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1"
|
|
343
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
344
|
+
d: "M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1"
|
|
345
|
+
})]
|
|
346
|
+
});
|
|
347
|
+
const Filter = p => /*#__PURE__*/_jsx(Svg, {
|
|
348
|
+
...p,
|
|
349
|
+
children: /*#__PURE__*/_jsx("polygon", {
|
|
350
|
+
points: "22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"
|
|
351
|
+
})
|
|
352
|
+
});
|
|
353
|
+
const Globe = p => /*#__PURE__*/_jsxs(Svg, {
|
|
354
|
+
...p,
|
|
355
|
+
children: [/*#__PURE__*/_jsx("circle", {
|
|
356
|
+
cx: "12",
|
|
357
|
+
cy: "12",
|
|
358
|
+
r: "10"
|
|
359
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
360
|
+
d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"
|
|
361
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
362
|
+
d: "M2 12h20"
|
|
363
|
+
})]
|
|
364
|
+
});
|
|
365
|
+
const Link = p => /*#__PURE__*/_jsxs(Svg, {
|
|
366
|
+
...p,
|
|
367
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
368
|
+
d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
|
|
369
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
370
|
+
d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
|
|
371
|
+
})]
|
|
372
|
+
});
|
|
373
|
+
const FlaskConical = p => /*#__PURE__*/_jsxs(Svg, {
|
|
374
|
+
...p,
|
|
375
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
376
|
+
d: "M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2"
|
|
377
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
378
|
+
d: "M8.5 2h7"
|
|
379
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
380
|
+
d: "M7 16h10"
|
|
381
|
+
})]
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// =============================
|
|
385
|
+
// View (structure mirrors the native file 1:1)
|
|
386
|
+
// =============================
|
|
387
|
+
|
|
388
|
+
/** Hoisted so the defaults don't mint a new Set/function per render (native). */
|
|
389
|
+
const EMPTY_PATTERNS = new Set();
|
|
390
|
+
const noop = () => {};
|
|
391
|
+
/**
|
|
392
|
+
* The measurable slice of a request's lifetime, as proportional bars.
|
|
393
|
+
* Renders NOTHING when the interceptor couldn't measure it — same "absent,
|
|
394
|
+
* not zeroed" rule as native. Only two phases, on purpose (see native).
|
|
395
|
+
*/
|
|
396
|
+
const TimingPhases = ({
|
|
397
|
+
timings,
|
|
398
|
+
total
|
|
399
|
+
}) => {
|
|
400
|
+
// Guard the divisor: a sub-millisecond request would otherwise divide by 0.
|
|
401
|
+
const span = Math.max(1, total);
|
|
402
|
+
const phases = [{
|
|
403
|
+
label: "Waiting (TTFB)",
|
|
404
|
+
hint: "incl. queue, DNS, TLS",
|
|
405
|
+
value: timings.ttfb,
|
|
406
|
+
color: macOSColors.semantic.warning
|
|
407
|
+
}, {
|
|
408
|
+
label: "Content download",
|
|
409
|
+
hint: undefined,
|
|
410
|
+
value: timings.download,
|
|
411
|
+
color: macOSColors.semantic.success
|
|
412
|
+
}];
|
|
413
|
+
return /*#__PURE__*/_jsx("div", {
|
|
414
|
+
style: styles.phaseList,
|
|
415
|
+
children: phases.map(phase => /*#__PURE__*/_jsxs("div", {
|
|
416
|
+
style: styles.phaseRow,
|
|
417
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
418
|
+
style: styles.phaseLabelGroup,
|
|
419
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
420
|
+
style: styles.phaseLabel,
|
|
421
|
+
children: phase.label
|
|
422
|
+
}), phase.hint ? /*#__PURE__*/_jsx("div", {
|
|
423
|
+
style: styles.phaseHint,
|
|
424
|
+
children: phase.hint
|
|
425
|
+
}) : null]
|
|
426
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
427
|
+
style: styles.phaseTrack,
|
|
428
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
429
|
+
style: {
|
|
430
|
+
...styles.phaseBar,
|
|
431
|
+
backgroundColor: phase.color,
|
|
432
|
+
// Floor so a 1ms phase is a visible tick; ceiling because ttfb
|
|
433
|
+
// can exceed event.duration (measured at different points).
|
|
434
|
+
width: `${Math.min(100, Math.max(1, phase.value / span * 100))}%`
|
|
435
|
+
}
|
|
436
|
+
})
|
|
437
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
438
|
+
style: styles.phaseValue,
|
|
439
|
+
children: formatDuration(phase.value)
|
|
440
|
+
})]
|
|
441
|
+
}, phase.label))
|
|
442
|
+
});
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Stand-in for a body tree while the prev/next cursor is still moving.
|
|
447
|
+
* Fixed-height nothing — must cost ~0 and must not resize the scroll view as
|
|
448
|
+
* the real tree swaps in (native rationale).
|
|
449
|
+
*/
|
|
450
|
+
const BodyDeferred = () => /*#__PURE__*/_jsx("div", {
|
|
451
|
+
style: styles.bodyDeferred
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Component for collapsible sections matching Sentry style
|
|
455
|
+
const CollapsibleSection = ({
|
|
456
|
+
title,
|
|
457
|
+
icon,
|
|
458
|
+
children,
|
|
459
|
+
defaultOpen = false,
|
|
460
|
+
count
|
|
461
|
+
}) => {
|
|
462
|
+
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
463
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
464
|
+
style: styles.collapsibleSection,
|
|
465
|
+
children: [/*#__PURE__*/_jsxs("button", {
|
|
466
|
+
type: "button",
|
|
467
|
+
style: styles.collapsibleHeader,
|
|
468
|
+
onClick: () => setIsOpen(!isOpen),
|
|
469
|
+
"aria-expanded": isOpen,
|
|
470
|
+
children: [/*#__PURE__*/_jsxs("span", {
|
|
471
|
+
style: styles.collapsibleTitle,
|
|
472
|
+
children: [icon, /*#__PURE__*/_jsx("span", {
|
|
473
|
+
style: styles.collapsibleTitleText,
|
|
474
|
+
children: title
|
|
475
|
+
}), count !== undefined ? /*#__PURE__*/_jsx("span", {
|
|
476
|
+
style: styles.collapsibleCount,
|
|
477
|
+
children: count
|
|
478
|
+
}) : null]
|
|
479
|
+
}), isOpen ? /*#__PURE__*/_jsx(ChevronUp, {
|
|
480
|
+
size: 16,
|
|
481
|
+
color: macOSColors.text.secondary
|
|
482
|
+
}) : /*#__PURE__*/_jsx(ChevronDown, {
|
|
483
|
+
size: 16,
|
|
484
|
+
color: macOSColors.text.secondary
|
|
485
|
+
})]
|
|
486
|
+
}), isOpen ? /*#__PURE__*/_jsx("div", {
|
|
487
|
+
style: styles.collapsibleContent,
|
|
488
|
+
children: children
|
|
489
|
+
}) : null]
|
|
490
|
+
});
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
// URL breakdown component matching Sentry style
|
|
494
|
+
const UrlBreakdown = ({
|
|
495
|
+
url,
|
|
496
|
+
operationName,
|
|
497
|
+
graphqlVariables,
|
|
498
|
+
requestClient
|
|
499
|
+
}) => {
|
|
500
|
+
const parseUrl = urlString => {
|
|
501
|
+
try {
|
|
502
|
+
const urlObj = new URL(urlString);
|
|
503
|
+
const protocol = String(urlObj.protocol || "");
|
|
504
|
+
const host = String(urlObj.host || "");
|
|
505
|
+
const isSecure = protocol === "https:";
|
|
506
|
+
let pathname = String(urlObj.pathname || "");
|
|
507
|
+
|
|
508
|
+
// GraphQL requests format with arrow notation, matching React Query's
|
|
509
|
+
// key display: "GetPokemon › Sandshrew" (same pure util as native).
|
|
510
|
+
if (requestClient === "graphql" && operationName) {
|
|
511
|
+
const graphqlDisplay = formatGraphQLDisplay(operationName, graphqlVariables);
|
|
512
|
+
pathname = `${pathname} (${graphqlDisplay})`;
|
|
513
|
+
} else if (operationName) {
|
|
514
|
+
// Non-GraphQL requests with operation names (e.g., gRPC)
|
|
515
|
+
pathname = `${pathname} (${operationName})`;
|
|
516
|
+
}
|
|
517
|
+
const params = {};
|
|
518
|
+
const searchParams = urlObj.searchParams;
|
|
519
|
+
if (searchParams && typeof searchParams.forEach === "function") {
|
|
520
|
+
searchParams.forEach((value, key) => {
|
|
521
|
+
params[key] = value;
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
return {
|
|
525
|
+
protocol: protocol.replace(":", ""),
|
|
526
|
+
host,
|
|
527
|
+
pathname,
|
|
528
|
+
params: Object.keys(params).length > 0 ? params : null,
|
|
529
|
+
isSecure
|
|
530
|
+
};
|
|
531
|
+
} catch {
|
|
532
|
+
return {
|
|
533
|
+
protocol: "",
|
|
534
|
+
host: url,
|
|
535
|
+
pathname: "",
|
|
536
|
+
params: null,
|
|
537
|
+
isSecure: false
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* MUST be memoized — `params` is handed to DataViewer as its `data` prop,
|
|
544
|
+
* which the tree keys on by IDENTITY (same trap the native file documents).
|
|
545
|
+
*/
|
|
546
|
+
const urlParts = useMemo(() => parseUrl(url),
|
|
547
|
+
// parseUrl closes over the graphql/operation props, which are what change
|
|
548
|
+
// the derived pathname.
|
|
549
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
550
|
+
[url, requestClient, operationName, graphqlVariables]);
|
|
551
|
+
const [showParams, setShowParams] = useState(false);
|
|
552
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
553
|
+
style: styles.urlBreakdown,
|
|
554
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
555
|
+
style: styles.urlRow,
|
|
556
|
+
children: [urlParts.isSecure ? /*#__PURE__*/_jsx(Lock, {
|
|
557
|
+
size: 12,
|
|
558
|
+
color: macOSColors.semantic.success
|
|
559
|
+
}) : /*#__PURE__*/_jsx(Unlock, {
|
|
560
|
+
size: 12,
|
|
561
|
+
color: macOSColors.semantic.warning
|
|
562
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
563
|
+
style: styles.urlDomain,
|
|
564
|
+
children: urlParts.host
|
|
565
|
+
}), /*#__PURE__*/_jsxs("span", {
|
|
566
|
+
style: styles.urlProtocol,
|
|
567
|
+
children: ["(", urlParts.protocol.toUpperCase(), ")"]
|
|
568
|
+
}), /*#__PURE__*/_jsx(InlineCopyButton, {
|
|
569
|
+
value: url,
|
|
570
|
+
buttonStyle: styles.copyButton
|
|
571
|
+
})]
|
|
572
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
573
|
+
style: styles.urlPathRow,
|
|
574
|
+
children: /*#__PURE__*/_jsxs("span", {
|
|
575
|
+
style: styles.urlPath,
|
|
576
|
+
children: [urlParts.pathname, urlParts.params ? /*#__PURE__*/_jsxs("span", {
|
|
577
|
+
style: styles.urlQueryString,
|
|
578
|
+
children: ["?", new URLSearchParams(urlParts.params).toString()]
|
|
579
|
+
}) : null]
|
|
580
|
+
})
|
|
581
|
+
}), urlParts.params ? /*#__PURE__*/_jsxs("div", {
|
|
582
|
+
style: styles.queryParamsCollapsible,
|
|
583
|
+
children: [/*#__PURE__*/_jsxs("button", {
|
|
584
|
+
type: "button",
|
|
585
|
+
style: styles.queryParamsToggle,
|
|
586
|
+
onClick: () => setShowParams(!showParams),
|
|
587
|
+
"aria-expanded": showParams,
|
|
588
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
589
|
+
style: styles.queryParamsToggleText,
|
|
590
|
+
children: "Query Parameters"
|
|
591
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
592
|
+
style: {
|
|
593
|
+
...styles.collapsibleCount,
|
|
594
|
+
flex: 1,
|
|
595
|
+
textAlign: "left"
|
|
596
|
+
},
|
|
597
|
+
children: Object.keys(urlParts.params).length
|
|
598
|
+
}), showParams ? /*#__PURE__*/_jsx(ChevronUp, {
|
|
599
|
+
size: 14,
|
|
600
|
+
color: macOSColors.text.secondary
|
|
601
|
+
}) : /*#__PURE__*/_jsx(ChevronDown, {
|
|
602
|
+
size: 14,
|
|
603
|
+
color: macOSColors.text.secondary
|
|
604
|
+
})]
|
|
605
|
+
}), showParams ? /*#__PURE__*/_jsx(DataViewer, {
|
|
606
|
+
title: "",
|
|
607
|
+
data: urlParts.params,
|
|
608
|
+
showTypeFilter: true,
|
|
609
|
+
rawMode: true,
|
|
610
|
+
initialExpanded: true
|
|
611
|
+
}) : null]
|
|
612
|
+
}) : null]
|
|
613
|
+
});
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Detailed inspector for a single network event — Sentry-style layout with
|
|
618
|
+
* collapsible sections and quick copy affordances.
|
|
619
|
+
*
|
|
620
|
+
* MEMOIZED for the same two render paths as native: `useLiveNetworkEvent`
|
|
621
|
+
* replays the same event object on re-subscribe, and host-root state changes
|
|
622
|
+
* re-render the shell with the detail body unchanged.
|
|
623
|
+
*/
|
|
624
|
+
export const NetworkEventDetailView = /*#__PURE__*/memo(function NetworkEventDetailView({
|
|
625
|
+
event,
|
|
626
|
+
ignoredPatterns = EMPTY_PATTERNS,
|
|
627
|
+
onTogglePattern = noop,
|
|
628
|
+
showBodies = true
|
|
629
|
+
}) {
|
|
630
|
+
const status = event.status ? formatHttpStatus(event.status) : null;
|
|
631
|
+
const isPending = !event.status && !event.error;
|
|
632
|
+
|
|
633
|
+
// Large bodies are omitted from synced snapshots and fetched on demand
|
|
634
|
+
// through the resolver (plain React context — reused, not forked). In a
|
|
635
|
+
// webview port there is normally no resolver and bodies are always inline,
|
|
636
|
+
// so this is a no-op there — exactly like on the device.
|
|
637
|
+
const resolveBody = useNetworkBodyResolver();
|
|
638
|
+
const requestBodyOmitted = event.requestData === undefined && (event.requestSize ?? 0) > 0;
|
|
639
|
+
const responseBodyOmitted = event.responseData === undefined && (event.responseSize ?? 0) > 0;
|
|
640
|
+
const [resolvedBody, setResolvedBody] = useState(null);
|
|
641
|
+
const [isLoadingBody, setIsLoadingBody] = useState(false);
|
|
642
|
+
useEffect(() => {
|
|
643
|
+
setResolvedBody(null);
|
|
644
|
+
if (!resolveBody || !requestBodyOmitted && !responseBodyOmitted) {
|
|
645
|
+
setIsLoadingBody(false);
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
let cancelled = false;
|
|
649
|
+
setIsLoadingBody(true);
|
|
650
|
+
resolveBody(event.id).then(body => {
|
|
651
|
+
if (!cancelled) setResolvedBody(body);
|
|
652
|
+
}).catch(() => {}).finally(() => {
|
|
653
|
+
if (!cancelled) setIsLoadingBody(false);
|
|
654
|
+
});
|
|
655
|
+
return () => {
|
|
656
|
+
cancelled = true;
|
|
657
|
+
};
|
|
658
|
+
}, [event.id, resolveBody, requestBodyOmitted, responseBodyOmitted]);
|
|
659
|
+
|
|
660
|
+
// Effective bodies: inline data when present, otherwise the lazily resolved
|
|
661
|
+
// body. `null`/`undefined` both collapse to undefined ("no body").
|
|
662
|
+
const requestData = event.requestData ?? resolvedBody?.requestData ?? undefined;
|
|
663
|
+
const responseData = event.responseData ?? resolvedBody?.responseData ?? undefined;
|
|
664
|
+
|
|
665
|
+
// Generate full request details for copying (resolved LAZILY at press time —
|
|
666
|
+
// see the copy button below).
|
|
667
|
+
const getFullRequestDetails = () => {
|
|
668
|
+
const requestDetails = {
|
|
669
|
+
method: event.method,
|
|
670
|
+
url: event.url,
|
|
671
|
+
status: event.status,
|
|
672
|
+
statusText: event.statusText,
|
|
673
|
+
timestamp: new Date(event.timestamp).toISOString(),
|
|
674
|
+
duration: event.duration ? `${event.duration}ms` : "N/A",
|
|
675
|
+
requestHeaders: event.requestHeaders,
|
|
676
|
+
requestData,
|
|
677
|
+
responseHeaders: event.responseHeaders,
|
|
678
|
+
responseData,
|
|
679
|
+
requestSize: event.requestSize ? formatBytes(event.requestSize) : "N/A",
|
|
680
|
+
responseSize: event.responseSize ? formatBytes(event.responseSize) : "N/A",
|
|
681
|
+
error: event.error,
|
|
682
|
+
client: event.requestClient
|
|
683
|
+
};
|
|
684
|
+
return `# Network Request Details
|
|
685
|
+
|
|
686
|
+
## Request
|
|
687
|
+
- **Method:** ${requestDetails.method}
|
|
688
|
+
- **URL:** ${requestDetails.url}
|
|
689
|
+
- **Client:** ${requestDetails.client || "N/A"}
|
|
690
|
+
- **Timestamp:** ${requestDetails.timestamp}
|
|
691
|
+
|
|
692
|
+
## Response
|
|
693
|
+
- **Status:** ${requestDetails.status || "Pending"}${requestDetails.statusText ? ` (${requestDetails.statusText})` : ""}
|
|
694
|
+
- **Duration:** ${requestDetails.duration}
|
|
695
|
+
- **Request Size:** ${requestDetails.requestSize}
|
|
696
|
+
- **Response Size:** ${requestDetails.responseSize}
|
|
697
|
+
${requestDetails.error ? `- **Error:** ${requestDetails.error}` : ""}
|
|
698
|
+
|
|
699
|
+
## Request Headers
|
|
700
|
+
\`\`\`json
|
|
701
|
+
${JSON.stringify(requestDetails.requestHeaders, null, 2)}
|
|
702
|
+
\`\`\`
|
|
703
|
+
|
|
704
|
+
## Request Data
|
|
705
|
+
\`\`\`json
|
|
706
|
+
${JSON.stringify(requestDetails.requestData, null, 2)}
|
|
707
|
+
\`\`\`
|
|
708
|
+
|
|
709
|
+
## Response Headers
|
|
710
|
+
\`\`\`json
|
|
711
|
+
${JSON.stringify(requestDetails.responseHeaders, null, 2)}
|
|
712
|
+
\`\`\`
|
|
713
|
+
|
|
714
|
+
## Response Data
|
|
715
|
+
\`\`\`json
|
|
716
|
+
${JSON.stringify(requestDetails.responseData, null, 2)}
|
|
717
|
+
\`\`\`
|
|
718
|
+
`;
|
|
719
|
+
};
|
|
720
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
721
|
+
style: styles.container,
|
|
722
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
723
|
+
style: styles.requestDetailsSection,
|
|
724
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
725
|
+
style: styles.httpHeader,
|
|
726
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
727
|
+
style: styles.httpMethodBadge,
|
|
728
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
729
|
+
style: styles.httpMethod,
|
|
730
|
+
children: event.method
|
|
731
|
+
})
|
|
732
|
+
}), event.status ? /*#__PURE__*/_jsx("span", {
|
|
733
|
+
style: {
|
|
734
|
+
...styles.httpStatusBadge,
|
|
735
|
+
backgroundColor: `${status?.color}20`
|
|
736
|
+
},
|
|
737
|
+
children: /*#__PURE__*/_jsxs("span", {
|
|
738
|
+
style: {
|
|
739
|
+
...styles.httpStatusText,
|
|
740
|
+
color: status?.color
|
|
741
|
+
},
|
|
742
|
+
children: [status?.text, " ", status?.meaning]
|
|
743
|
+
})
|
|
744
|
+
}) : isPending ? /*#__PURE__*/_jsxs("span", {
|
|
745
|
+
style: styles.pendingBadge,
|
|
746
|
+
children: [/*#__PURE__*/_jsx(Clock, {
|
|
747
|
+
size: 10,
|
|
748
|
+
color: macOSColors.semantic.warning
|
|
749
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
750
|
+
style: styles.pendingBadgeText,
|
|
751
|
+
children: "Pending"
|
|
752
|
+
})]
|
|
753
|
+
}) : null, event.duration ? /*#__PURE__*/_jsxs("span", {
|
|
754
|
+
style: styles.httpDuration,
|
|
755
|
+
children: [/*#__PURE__*/_jsx(Clock, {
|
|
756
|
+
size: 10,
|
|
757
|
+
color: macOSColors.text.muted
|
|
758
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
759
|
+
style: styles.httpDurationText,
|
|
760
|
+
children: formatDuration(event.duration)
|
|
761
|
+
})]
|
|
762
|
+
}) : null, event.override ? /*#__PURE__*/_jsxs("span", {
|
|
763
|
+
style: styles.overrideBadge,
|
|
764
|
+
children: [/*#__PURE__*/_jsx(FlaskConical, {
|
|
765
|
+
size: 10,
|
|
766
|
+
color: macOSColors.semantic.warning
|
|
767
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
768
|
+
style: styles.overrideBadgeText,
|
|
769
|
+
children: event.override.ruleName || "Overridden"
|
|
770
|
+
})]
|
|
771
|
+
}) : null, /*#__PURE__*/_jsx(InlineCopyButton, {
|
|
772
|
+
value: getFullRequestDetails,
|
|
773
|
+
buttonStyle: styles.copyFullButton
|
|
774
|
+
})]
|
|
775
|
+
}), /*#__PURE__*/_jsx(UrlBreakdown, {
|
|
776
|
+
url: event.url,
|
|
777
|
+
requestData: requestData,
|
|
778
|
+
operationName: event.operationName,
|
|
779
|
+
graphqlVariables: event.graphqlVariables,
|
|
780
|
+
requestClient: event.requestClient
|
|
781
|
+
}), event.error ? /*#__PURE__*/_jsxs("div", {
|
|
782
|
+
style: styles.errorBox,
|
|
783
|
+
children: [/*#__PURE__*/_jsx(AlertCircle, {
|
|
784
|
+
size: 12,
|
|
785
|
+
color: macOSColors.semantic.error
|
|
786
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
787
|
+
style: styles.errorText,
|
|
788
|
+
children: event.error
|
|
789
|
+
})]
|
|
790
|
+
}) : null]
|
|
791
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
792
|
+
style: styles.timingSection,
|
|
793
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
794
|
+
style: styles.timingRow,
|
|
795
|
+
children: [/*#__PURE__*/_jsx(Clock, {
|
|
796
|
+
size: 12,
|
|
797
|
+
color: macOSColors.text.secondary
|
|
798
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
799
|
+
style: styles.timingLabel,
|
|
800
|
+
children: "Started:"
|
|
801
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
802
|
+
style: styles.timingValue,
|
|
803
|
+
children: formatRelativeTime(event.timestamp)
|
|
804
|
+
}), /*#__PURE__*/_jsxs("span", {
|
|
805
|
+
style: styles.timingExact,
|
|
806
|
+
children: ["(", new Date(event.timestamp).toLocaleTimeString(), ")"]
|
|
807
|
+
}), event.requestSize || event.responseSize ? /*#__PURE__*/_jsxs("span", {
|
|
808
|
+
style: styles.sizeRow,
|
|
809
|
+
children: [event.requestSize !== undefined ? /*#__PURE__*/_jsxs("span", {
|
|
810
|
+
style: styles.sizeItem,
|
|
811
|
+
children: [/*#__PURE__*/_jsx(Upload, {
|
|
812
|
+
size: 10,
|
|
813
|
+
color: macOSColors.semantic.info
|
|
814
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
815
|
+
style: styles.sizeLabel,
|
|
816
|
+
children: "Sent:"
|
|
817
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
818
|
+
style: styles.sizeValue,
|
|
819
|
+
children: formatBytes(event.requestSize)
|
|
820
|
+
})]
|
|
821
|
+
}) : null, event.responseSize !== undefined ? /*#__PURE__*/_jsxs("span", {
|
|
822
|
+
style: styles.sizeItem,
|
|
823
|
+
children: [/*#__PURE__*/_jsx(Download, {
|
|
824
|
+
size: 10,
|
|
825
|
+
color: NEUTRAL_ICON
|
|
826
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
827
|
+
style: styles.sizeLabel,
|
|
828
|
+
children: "Received:"
|
|
829
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
830
|
+
style: styles.sizeValue,
|
|
831
|
+
children: formatBytes(event.responseSize)
|
|
832
|
+
})]
|
|
833
|
+
}) : null]
|
|
834
|
+
}) : null]
|
|
835
|
+
}), event.timings ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
836
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
837
|
+
style: styles.phaseDivider
|
|
838
|
+
}), /*#__PURE__*/_jsx(TimingPhases, {
|
|
839
|
+
timings: event.timings,
|
|
840
|
+
total: event.duration ?? event.timings.ttfb + event.timings.download
|
|
841
|
+
})]
|
|
842
|
+
}) : null]
|
|
843
|
+
}), /*#__PURE__*/_jsx(CollapsibleSection, {
|
|
844
|
+
title: "Request Headers",
|
|
845
|
+
icon: /*#__PURE__*/_jsx(Upload, {
|
|
846
|
+
size: 14,
|
|
847
|
+
color: macOSColors.semantic.info
|
|
848
|
+
}),
|
|
849
|
+
defaultOpen: false,
|
|
850
|
+
count: Object.keys(event.requestHeaders).length,
|
|
851
|
+
children: Object.keys(event.requestHeaders).length > 0 ? /*#__PURE__*/_jsx("div", {
|
|
852
|
+
style: styles.dataViewerContainer,
|
|
853
|
+
children: /*#__PURE__*/_jsx(DataViewer, {
|
|
854
|
+
title: "",
|
|
855
|
+
data: event.requestHeaders,
|
|
856
|
+
showTypeFilter: true,
|
|
857
|
+
rawMode: true,
|
|
858
|
+
initialExpanded: true
|
|
859
|
+
})
|
|
860
|
+
}) : /*#__PURE__*/_jsx("div", {
|
|
861
|
+
style: styles.emptyText,
|
|
862
|
+
children: "No request headers"
|
|
863
|
+
})
|
|
864
|
+
}), /*#__PURE__*/_jsx(CollapsibleSection, {
|
|
865
|
+
title: "Response Headers",
|
|
866
|
+
icon: /*#__PURE__*/_jsx(Download, {
|
|
867
|
+
size: 14,
|
|
868
|
+
color: NEUTRAL_ICON
|
|
869
|
+
}),
|
|
870
|
+
defaultOpen: false,
|
|
871
|
+
count: Object.keys(event.responseHeaders).length,
|
|
872
|
+
children: Object.keys(event.responseHeaders).length > 0 ? /*#__PURE__*/_jsx("div", {
|
|
873
|
+
style: styles.dataViewerContainer,
|
|
874
|
+
children: /*#__PURE__*/_jsx(DataViewer, {
|
|
875
|
+
title: "",
|
|
876
|
+
data: event.responseHeaders,
|
|
877
|
+
showTypeFilter: true,
|
|
878
|
+
rawMode: true,
|
|
879
|
+
initialExpanded: true
|
|
880
|
+
})
|
|
881
|
+
}) : /*#__PURE__*/_jsx("div", {
|
|
882
|
+
style: styles.emptyText,
|
|
883
|
+
children: "No response headers yet"
|
|
884
|
+
})
|
|
885
|
+
}), requestData !== undefined ? /*#__PURE__*/_jsx(CollapsibleSection, {
|
|
886
|
+
title: "Request Body",
|
|
887
|
+
icon: /*#__PURE__*/_jsx(FileJson, {
|
|
888
|
+
size: 14,
|
|
889
|
+
color: macOSColors.semantic.info
|
|
890
|
+
}),
|
|
891
|
+
defaultOpen: false,
|
|
892
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
893
|
+
style: styles.dataViewerContainer,
|
|
894
|
+
children: showBodies ? /*#__PURE__*/_jsx(DataViewer, {
|
|
895
|
+
title: "",
|
|
896
|
+
data: requestData,
|
|
897
|
+
showTypeFilter: true,
|
|
898
|
+
rawMode: true,
|
|
899
|
+
initialExpanded: true
|
|
900
|
+
}) : /*#__PURE__*/_jsx(BodyDeferred, {})
|
|
901
|
+
})
|
|
902
|
+
}) : requestBodyOmitted ? /*#__PURE__*/_jsx(CollapsibleSection, {
|
|
903
|
+
title: "Request Body",
|
|
904
|
+
icon: /*#__PURE__*/_jsx(FileJson, {
|
|
905
|
+
size: 14,
|
|
906
|
+
color: macOSColors.semantic.info
|
|
907
|
+
}),
|
|
908
|
+
defaultOpen: true,
|
|
909
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
910
|
+
style: styles.emptyText,
|
|
911
|
+
children: isLoadingBody ? `Loading request body (${formatBytes(event.requestSize ?? 0)})…` : "Request body unavailable"
|
|
912
|
+
})
|
|
913
|
+
}) : null, responseData !== undefined ? /*#__PURE__*/_jsx(CollapsibleSection, {
|
|
914
|
+
title: "Response Body",
|
|
915
|
+
icon: /*#__PURE__*/_jsx(FileJson, {
|
|
916
|
+
size: 14,
|
|
917
|
+
color: NEUTRAL_ICON
|
|
918
|
+
})
|
|
919
|
+
// The body is what you opened the row FOR — expanded on arrival,
|
|
920
|
+
// everything else closed (native).
|
|
921
|
+
,
|
|
922
|
+
defaultOpen: true,
|
|
923
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
924
|
+
style: styles.dataViewerContainer,
|
|
925
|
+
children: showBodies ? /*#__PURE__*/_jsx(DataViewer, {
|
|
926
|
+
title: "",
|
|
927
|
+
data: responseData,
|
|
928
|
+
showTypeFilter: true,
|
|
929
|
+
rawMode: true,
|
|
930
|
+
initialExpanded: true
|
|
931
|
+
}) : /*#__PURE__*/_jsx(BodyDeferred, {})
|
|
932
|
+
})
|
|
933
|
+
}) : responseBodyOmitted ? /*#__PURE__*/_jsx(CollapsibleSection, {
|
|
934
|
+
title: "Response Body",
|
|
935
|
+
icon: /*#__PURE__*/_jsx(FileJson, {
|
|
936
|
+
size: 14,
|
|
937
|
+
color: NEUTRAL_ICON
|
|
938
|
+
}),
|
|
939
|
+
defaultOpen: true,
|
|
940
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
941
|
+
style: styles.emptyText,
|
|
942
|
+
children: isLoadingBody ? `Loading response body (${formatBytes(event.responseSize ?? 0)})…` : "Response body unavailable"
|
|
943
|
+
})
|
|
944
|
+
}) : null, /*#__PURE__*/_jsx(CollapsibleSection, {
|
|
945
|
+
title: "Filter Options",
|
|
946
|
+
icon: /*#__PURE__*/_jsx(Filter, {
|
|
947
|
+
size: 14,
|
|
948
|
+
color: macOSColors.semantic.warning
|
|
949
|
+
}),
|
|
950
|
+
defaultOpen: false,
|
|
951
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
952
|
+
style: styles.filterOptionsContainer,
|
|
953
|
+
children: (() => {
|
|
954
|
+
let domain = "";
|
|
955
|
+
let urlPath = "";
|
|
956
|
+
try {
|
|
957
|
+
const url = new URL(event.url);
|
|
958
|
+
domain = url.hostname;
|
|
959
|
+
urlPath = url.pathname;
|
|
960
|
+
} catch {
|
|
961
|
+
urlPath = event.url;
|
|
962
|
+
}
|
|
963
|
+
const isDomainIgnored = ignoredPatterns.has(domain);
|
|
964
|
+
const isUrlIgnored = ignoredPatterns.has(urlPath);
|
|
965
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
966
|
+
children: [/*#__PURE__*/_jsxs("button", {
|
|
967
|
+
type: "button",
|
|
968
|
+
style: {
|
|
969
|
+
...styles.filterOption,
|
|
970
|
+
...(isDomainIgnored ? styles.filterOptionActive : null)
|
|
971
|
+
},
|
|
972
|
+
onClick: () => domain && onTogglePattern(domain),
|
|
973
|
+
children: [/*#__PURE__*/_jsxs("span", {
|
|
974
|
+
style: styles.filterOptionLeft,
|
|
975
|
+
children: [/*#__PURE__*/_jsx(Globe, {
|
|
976
|
+
size: 16,
|
|
977
|
+
color: isDomainIgnored ? macOSColors.semantic.warning : macOSColors.text.muted
|
|
978
|
+
}), /*#__PURE__*/_jsxs("span", {
|
|
979
|
+
style: styles.filterOptionContent,
|
|
980
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
981
|
+
style: styles.filterOptionLabel,
|
|
982
|
+
children: "Ignore Domain"
|
|
983
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
984
|
+
style: styles.filterOptionValue,
|
|
985
|
+
children: domain || "N/A"
|
|
986
|
+
})]
|
|
987
|
+
})]
|
|
988
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
989
|
+
style: {
|
|
990
|
+
...styles.filterToggle,
|
|
991
|
+
...(isDomainIgnored ? styles.filterToggleActive : null)
|
|
992
|
+
},
|
|
993
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
994
|
+
style: {
|
|
995
|
+
...styles.filterToggleText,
|
|
996
|
+
...(isDomainIgnored ? styles.filterToggleTextActive : null)
|
|
997
|
+
},
|
|
998
|
+
children: isDomainIgnored ? "IGNORED" : "IGNORE"
|
|
999
|
+
})
|
|
1000
|
+
})]
|
|
1001
|
+
}), /*#__PURE__*/_jsxs("button", {
|
|
1002
|
+
type: "button",
|
|
1003
|
+
style: {
|
|
1004
|
+
...styles.filterOption,
|
|
1005
|
+
...(isUrlIgnored ? styles.filterOptionActive : null)
|
|
1006
|
+
},
|
|
1007
|
+
onClick: () => urlPath && onTogglePattern(urlPath),
|
|
1008
|
+
children: [/*#__PURE__*/_jsxs("span", {
|
|
1009
|
+
style: styles.filterOptionLeft,
|
|
1010
|
+
children: [/*#__PURE__*/_jsx(Link, {
|
|
1011
|
+
size: 16,
|
|
1012
|
+
color: isUrlIgnored ? macOSColors.semantic.warning : macOSColors.text.muted
|
|
1013
|
+
}), /*#__PURE__*/_jsxs("span", {
|
|
1014
|
+
style: styles.filterOptionContent,
|
|
1015
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
1016
|
+
style: styles.filterOptionLabel,
|
|
1017
|
+
children: "Ignore URL Pattern"
|
|
1018
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
1019
|
+
style: {
|
|
1020
|
+
...styles.filterOptionValue,
|
|
1021
|
+
...styles.singleLine
|
|
1022
|
+
},
|
|
1023
|
+
children: urlPath || "N/A"
|
|
1024
|
+
})]
|
|
1025
|
+
})]
|
|
1026
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
1027
|
+
style: {
|
|
1028
|
+
...styles.filterToggle,
|
|
1029
|
+
...(isUrlIgnored ? styles.filterToggleActive : null)
|
|
1030
|
+
},
|
|
1031
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
1032
|
+
style: {
|
|
1033
|
+
...styles.filterToggleText,
|
|
1034
|
+
...(isUrlIgnored ? styles.filterToggleTextActive : null)
|
|
1035
|
+
},
|
|
1036
|
+
children: isUrlIgnored ? "IGNORED" : "IGNORE"
|
|
1037
|
+
})
|
|
1038
|
+
})]
|
|
1039
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
1040
|
+
style: styles.filterInfoBox,
|
|
1041
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
1042
|
+
style: styles.filterInfoText,
|
|
1043
|
+
children: "Ignored requests will be hidden from the network list. You can manage filters in the Filters tab."
|
|
1044
|
+
})
|
|
1045
|
+
})]
|
|
1046
|
+
});
|
|
1047
|
+
})()
|
|
1048
|
+
})
|
|
1049
|
+
})]
|
|
1050
|
+
});
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
// Values mirror the native StyleSheet block 1:1.
|
|
1054
|
+
const styles = {
|
|
1055
|
+
// Native: ScrollView flex 1 on background.base — the detail body OWNS its
|
|
1056
|
+
// scrolling so the stepper footer stays pinned under it.
|
|
1057
|
+
container: {
|
|
1058
|
+
flex: 1,
|
|
1059
|
+
minHeight: 0,
|
|
1060
|
+
overflowY: "auto",
|
|
1061
|
+
backgroundColor: macOSColors.background.base
|
|
1062
|
+
},
|
|
1063
|
+
requestDetailsSection: {
|
|
1064
|
+
margin: "12px 12px 0",
|
|
1065
|
+
backgroundColor: macOSColors.background.card,
|
|
1066
|
+
borderRadius: 8,
|
|
1067
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
1068
|
+
padding: 12
|
|
1069
|
+
},
|
|
1070
|
+
httpHeader: {
|
|
1071
|
+
display: "flex",
|
|
1072
|
+
flexDirection: "row",
|
|
1073
|
+
alignItems: "center",
|
|
1074
|
+
gap: 8,
|
|
1075
|
+
marginBottom: 12,
|
|
1076
|
+
flexWrap: "nowrap"
|
|
1077
|
+
},
|
|
1078
|
+
httpMethodBadge: {
|
|
1079
|
+
display: "inline-flex",
|
|
1080
|
+
backgroundColor: macOSColors.semantic.infoBackground,
|
|
1081
|
+
padding: "4px 8px",
|
|
1082
|
+
borderRadius: 4
|
|
1083
|
+
},
|
|
1084
|
+
httpMethod: {
|
|
1085
|
+
color: macOSColors.semantic.info,
|
|
1086
|
+
fontSize: 11,
|
|
1087
|
+
fontWeight: 700,
|
|
1088
|
+
letterSpacing: 0.5
|
|
1089
|
+
},
|
|
1090
|
+
httpStatusBadge: {
|
|
1091
|
+
display: "inline-flex",
|
|
1092
|
+
padding: "4px 8px",
|
|
1093
|
+
borderRadius: 4,
|
|
1094
|
+
whiteSpace: "nowrap"
|
|
1095
|
+
},
|
|
1096
|
+
httpStatusText: {
|
|
1097
|
+
fontSize: 11,
|
|
1098
|
+
fontWeight: 600
|
|
1099
|
+
},
|
|
1100
|
+
pendingBadge: {
|
|
1101
|
+
display: "inline-flex",
|
|
1102
|
+
flexDirection: "row",
|
|
1103
|
+
alignItems: "center",
|
|
1104
|
+
gap: 4,
|
|
1105
|
+
backgroundColor: macOSColors.semantic.warningBackground,
|
|
1106
|
+
padding: "4px 8px",
|
|
1107
|
+
borderRadius: 4
|
|
1108
|
+
},
|
|
1109
|
+
pendingBadgeText: {
|
|
1110
|
+
color: macOSColors.semantic.warning,
|
|
1111
|
+
fontSize: 11,
|
|
1112
|
+
fontWeight: 600
|
|
1113
|
+
},
|
|
1114
|
+
httpDuration: {
|
|
1115
|
+
display: "inline-flex",
|
|
1116
|
+
flexDirection: "row",
|
|
1117
|
+
alignItems: "center",
|
|
1118
|
+
gap: 4
|
|
1119
|
+
},
|
|
1120
|
+
httpDurationText: {
|
|
1121
|
+
color: macOSColors.text.secondary,
|
|
1122
|
+
fontSize: 11
|
|
1123
|
+
},
|
|
1124
|
+
overrideBadge: {
|
|
1125
|
+
display: "inline-flex",
|
|
1126
|
+
flexDirection: "row",
|
|
1127
|
+
alignItems: "center",
|
|
1128
|
+
gap: 4,
|
|
1129
|
+
padding: "3px 6px",
|
|
1130
|
+
borderRadius: 4,
|
|
1131
|
+
backgroundColor: macOSColors.semantic.warningBackground
|
|
1132
|
+
},
|
|
1133
|
+
overrideBadgeText: {
|
|
1134
|
+
color: macOSColors.semantic.warning,
|
|
1135
|
+
fontSize: 10,
|
|
1136
|
+
fontWeight: 700
|
|
1137
|
+
},
|
|
1138
|
+
copyFullButton: {
|
|
1139
|
+
marginLeft: "auto",
|
|
1140
|
+
flexShrink: 0,
|
|
1141
|
+
padding: 4
|
|
1142
|
+
},
|
|
1143
|
+
// URL breakdown styles
|
|
1144
|
+
urlBreakdown: {
|
|
1145
|
+
backgroundColor: macOSColors.background.input,
|
|
1146
|
+
borderRadius: 4,
|
|
1147
|
+
padding: 8
|
|
1148
|
+
},
|
|
1149
|
+
urlRow: {
|
|
1150
|
+
display: "flex",
|
|
1151
|
+
flexDirection: "row",
|
|
1152
|
+
alignItems: "center",
|
|
1153
|
+
gap: 6,
|
|
1154
|
+
marginBottom: 4
|
|
1155
|
+
},
|
|
1156
|
+
urlDomain: {
|
|
1157
|
+
color: macOSColors.text.primary,
|
|
1158
|
+
fontSize: 12,
|
|
1159
|
+
fontWeight: 600,
|
|
1160
|
+
flex: 1,
|
|
1161
|
+
minWidth: 0,
|
|
1162
|
+
overflowWrap: "anywhere"
|
|
1163
|
+
},
|
|
1164
|
+
urlProtocol: {
|
|
1165
|
+
color: macOSColors.text.muted,
|
|
1166
|
+
fontSize: 10
|
|
1167
|
+
},
|
|
1168
|
+
copyButton: {
|
|
1169
|
+
padding: 4
|
|
1170
|
+
},
|
|
1171
|
+
urlPathRow: {
|
|
1172
|
+
paddingLeft: 18
|
|
1173
|
+
},
|
|
1174
|
+
urlPath: {
|
|
1175
|
+
color: macOSColors.text.secondary,
|
|
1176
|
+
fontSize: 11,
|
|
1177
|
+
fontFamily: "ui-monospace, Menlo, monospace",
|
|
1178
|
+
// Native numberOfLines={2}
|
|
1179
|
+
display: "-webkit-box",
|
|
1180
|
+
WebkitLineClamp: 2,
|
|
1181
|
+
WebkitBoxOrient: "vertical",
|
|
1182
|
+
overflow: "hidden",
|
|
1183
|
+
overflowWrap: "anywhere"
|
|
1184
|
+
},
|
|
1185
|
+
urlQueryString: {
|
|
1186
|
+
color: macOSColors.semantic.info,
|
|
1187
|
+
fontSize: 11,
|
|
1188
|
+
fontFamily: "ui-monospace, Menlo, monospace"
|
|
1189
|
+
},
|
|
1190
|
+
// Query Parameters - Collapsible section
|
|
1191
|
+
queryParamsCollapsible: {
|
|
1192
|
+
marginTop: 8
|
|
1193
|
+
},
|
|
1194
|
+
queryParamsToggle: {
|
|
1195
|
+
display: "flex",
|
|
1196
|
+
width: "100%",
|
|
1197
|
+
boxSizing: "border-box",
|
|
1198
|
+
flexDirection: "row",
|
|
1199
|
+
alignItems: "center",
|
|
1200
|
+
justifyContent: "space-between",
|
|
1201
|
+
gap: 8,
|
|
1202
|
+
padding: "10px 12px",
|
|
1203
|
+
backgroundColor: macOSColors.background.hover,
|
|
1204
|
+
borderRadius: 8,
|
|
1205
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
1206
|
+
marginBottom: 8,
|
|
1207
|
+
cursor: "pointer",
|
|
1208
|
+
margin: "0 0 8px",
|
|
1209
|
+
font: "inherit"
|
|
1210
|
+
},
|
|
1211
|
+
queryParamsToggleText: {
|
|
1212
|
+
flexGrow: 0,
|
|
1213
|
+
color: macOSColors.text.primary,
|
|
1214
|
+
fontSize: 12,
|
|
1215
|
+
fontWeight: 600,
|
|
1216
|
+
letterSpacing: 0.3,
|
|
1217
|
+
whiteSpace: "nowrap"
|
|
1218
|
+
},
|
|
1219
|
+
// Timing section - always visible
|
|
1220
|
+
timingSection: {
|
|
1221
|
+
margin: "8px 12px 0",
|
|
1222
|
+
backgroundColor: macOSColors.background.card,
|
|
1223
|
+
borderRadius: 8,
|
|
1224
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
1225
|
+
padding: 12
|
|
1226
|
+
},
|
|
1227
|
+
timingRow: {
|
|
1228
|
+
display: "flex",
|
|
1229
|
+
flexDirection: "row",
|
|
1230
|
+
alignItems: "center",
|
|
1231
|
+
gap: 6,
|
|
1232
|
+
// Wraps rather than squashing when the card is narrow — the sizes drop to
|
|
1233
|
+
// their own line there (native).
|
|
1234
|
+
flexWrap: "wrap"
|
|
1235
|
+
},
|
|
1236
|
+
timingLabel: {
|
|
1237
|
+
color: macOSColors.text.secondary,
|
|
1238
|
+
fontSize: 11
|
|
1239
|
+
},
|
|
1240
|
+
timingValue: {
|
|
1241
|
+
color: macOSColors.text.primary,
|
|
1242
|
+
fontSize: 11,
|
|
1243
|
+
fontWeight: 600
|
|
1244
|
+
},
|
|
1245
|
+
timingExact: {
|
|
1246
|
+
color: macOSColors.text.muted,
|
|
1247
|
+
fontSize: 10,
|
|
1248
|
+
marginLeft: 4
|
|
1249
|
+
},
|
|
1250
|
+
sizeRow: {
|
|
1251
|
+
display: "inline-flex",
|
|
1252
|
+
flexDirection: "row",
|
|
1253
|
+
alignItems: "center",
|
|
1254
|
+
gap: 16,
|
|
1255
|
+
// Pushed to the far end of the Started row (native).
|
|
1256
|
+
marginLeft: "auto"
|
|
1257
|
+
},
|
|
1258
|
+
sizeItem: {
|
|
1259
|
+
display: "inline-flex",
|
|
1260
|
+
flexDirection: "row",
|
|
1261
|
+
alignItems: "center",
|
|
1262
|
+
gap: 4
|
|
1263
|
+
},
|
|
1264
|
+
sizeLabel: {
|
|
1265
|
+
color: macOSColors.text.muted,
|
|
1266
|
+
fontSize: 10
|
|
1267
|
+
},
|
|
1268
|
+
sizeValue: {
|
|
1269
|
+
color: macOSColors.semantic.info,
|
|
1270
|
+
fontSize: 10,
|
|
1271
|
+
fontFamily: "ui-monospace, Menlo, monospace",
|
|
1272
|
+
fontWeight: 600
|
|
1273
|
+
},
|
|
1274
|
+
/* ---- Timing phases ---- */
|
|
1275
|
+
phaseDivider: {
|
|
1276
|
+
height: 1,
|
|
1277
|
+
backgroundColor: macOSColors.border.default,
|
|
1278
|
+
marginTop: 12,
|
|
1279
|
+
marginBottom: 12
|
|
1280
|
+
},
|
|
1281
|
+
phaseList: {
|
|
1282
|
+
display: "flex",
|
|
1283
|
+
flexDirection: "column",
|
|
1284
|
+
gap: 8
|
|
1285
|
+
},
|
|
1286
|
+
phaseRow: {
|
|
1287
|
+
display: "flex",
|
|
1288
|
+
flexDirection: "row",
|
|
1289
|
+
alignItems: "center",
|
|
1290
|
+
gap: 14
|
|
1291
|
+
},
|
|
1292
|
+
phaseLabelGroup: {
|
|
1293
|
+
width: 150,
|
|
1294
|
+
flexShrink: 0
|
|
1295
|
+
},
|
|
1296
|
+
phaseLabel: {
|
|
1297
|
+
fontSize: 12,
|
|
1298
|
+
color: macOSColors.text.secondary
|
|
1299
|
+
},
|
|
1300
|
+
phaseHint: {
|
|
1301
|
+
fontSize: 10,
|
|
1302
|
+
color: macOSColors.text.muted
|
|
1303
|
+
},
|
|
1304
|
+
phaseTrack: {
|
|
1305
|
+
flex: 1,
|
|
1306
|
+
minWidth: 0,
|
|
1307
|
+
height: 7,
|
|
1308
|
+
borderRadius: 4,
|
|
1309
|
+
backgroundColor: macOSColors.background.hover,
|
|
1310
|
+
display: "flex",
|
|
1311
|
+
justifyContent: "center",
|
|
1312
|
+
flexDirection: "column",
|
|
1313
|
+
overflow: "hidden"
|
|
1314
|
+
},
|
|
1315
|
+
phaseBar: {
|
|
1316
|
+
height: 7,
|
|
1317
|
+
borderRadius: 4
|
|
1318
|
+
},
|
|
1319
|
+
phaseValue: {
|
|
1320
|
+
width: 72,
|
|
1321
|
+
flexShrink: 0,
|
|
1322
|
+
textAlign: "right",
|
|
1323
|
+
fontSize: 12,
|
|
1324
|
+
fontFamily: "ui-monospace, Menlo, monospace",
|
|
1325
|
+
color: macOSColors.text.primary
|
|
1326
|
+
},
|
|
1327
|
+
// Collapsible section styles
|
|
1328
|
+
collapsibleSection: {
|
|
1329
|
+
margin: "8px 12px 0",
|
|
1330
|
+
backgroundColor: macOSColors.background.card,
|
|
1331
|
+
borderRadius: 8,
|
|
1332
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
1333
|
+
overflow: "hidden"
|
|
1334
|
+
},
|
|
1335
|
+
collapsibleHeader: {
|
|
1336
|
+
display: "flex",
|
|
1337
|
+
width: "100%",
|
|
1338
|
+
boxSizing: "border-box",
|
|
1339
|
+
flexDirection: "row",
|
|
1340
|
+
alignItems: "center",
|
|
1341
|
+
justifyContent: "space-between",
|
|
1342
|
+
padding: 12,
|
|
1343
|
+
// Near-white strip, not the selection grey (native rationale).
|
|
1344
|
+
backgroundColor: macOSColors.background.hover,
|
|
1345
|
+
border: "none",
|
|
1346
|
+
cursor: "pointer",
|
|
1347
|
+
margin: 0,
|
|
1348
|
+
font: "inherit",
|
|
1349
|
+
textAlign: "left"
|
|
1350
|
+
},
|
|
1351
|
+
collapsibleTitle: {
|
|
1352
|
+
display: "inline-flex",
|
|
1353
|
+
flexDirection: "row",
|
|
1354
|
+
alignItems: "center",
|
|
1355
|
+
gap: 8
|
|
1356
|
+
},
|
|
1357
|
+
collapsibleTitleText: {
|
|
1358
|
+
color: macOSColors.text.primary,
|
|
1359
|
+
fontSize: 13,
|
|
1360
|
+
fontWeight: 600
|
|
1361
|
+
},
|
|
1362
|
+
/** The "how much is in here" number beside a section title. */
|
|
1363
|
+
collapsibleCount: {
|
|
1364
|
+
color: macOSColors.text.muted,
|
|
1365
|
+
fontSize: 11.5,
|
|
1366
|
+
fontFamily: "ui-monospace, Menlo, monospace"
|
|
1367
|
+
},
|
|
1368
|
+
collapsibleContent: {
|
|
1369
|
+
padding: 12
|
|
1370
|
+
},
|
|
1371
|
+
// Data viewer container — pulls the tree flush against the section edges.
|
|
1372
|
+
dataViewerContainer: {
|
|
1373
|
+
margin: -12
|
|
1374
|
+
},
|
|
1375
|
+
/** Placeholder for a not-yet-mounted body tree. See BodyDeferred. */
|
|
1376
|
+
bodyDeferred: {
|
|
1377
|
+
height: 120
|
|
1378
|
+
},
|
|
1379
|
+
// Error box
|
|
1380
|
+
errorBox: {
|
|
1381
|
+
display: "flex",
|
|
1382
|
+
flexDirection: "row",
|
|
1383
|
+
alignItems: "center",
|
|
1384
|
+
gap: 6,
|
|
1385
|
+
backgroundColor: macOSColors.semantic.errorBackground,
|
|
1386
|
+
padding: 8,
|
|
1387
|
+
borderRadius: 4,
|
|
1388
|
+
marginTop: 8
|
|
1389
|
+
},
|
|
1390
|
+
errorText: {
|
|
1391
|
+
color: macOSColors.semantic.error,
|
|
1392
|
+
fontSize: 11,
|
|
1393
|
+
flex: 1,
|
|
1394
|
+
minWidth: 0,
|
|
1395
|
+
overflowWrap: "anywhere"
|
|
1396
|
+
},
|
|
1397
|
+
// Empty state
|
|
1398
|
+
emptyText: {
|
|
1399
|
+
color: macOSColors.text.muted,
|
|
1400
|
+
fontSize: 12,
|
|
1401
|
+
fontStyle: "italic",
|
|
1402
|
+
textAlign: "center"
|
|
1403
|
+
},
|
|
1404
|
+
// Filter options styles
|
|
1405
|
+
filterOptionsContainer: {
|
|
1406
|
+
display: "flex",
|
|
1407
|
+
flexDirection: "column",
|
|
1408
|
+
gap: 12
|
|
1409
|
+
},
|
|
1410
|
+
filterOption: {
|
|
1411
|
+
display: "flex",
|
|
1412
|
+
width: "100%",
|
|
1413
|
+
boxSizing: "border-box",
|
|
1414
|
+
flexDirection: "row",
|
|
1415
|
+
alignItems: "center",
|
|
1416
|
+
justifyContent: "space-between",
|
|
1417
|
+
backgroundColor: macOSColors.background.hover,
|
|
1418
|
+
borderRadius: 8,
|
|
1419
|
+
padding: 12,
|
|
1420
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
1421
|
+
cursor: "pointer",
|
|
1422
|
+
margin: 0,
|
|
1423
|
+
font: "inherit",
|
|
1424
|
+
textAlign: "left"
|
|
1425
|
+
},
|
|
1426
|
+
filterOptionActive: {
|
|
1427
|
+
backgroundColor: macOSColors.semantic.warningBackground,
|
|
1428
|
+
border: `1px solid ${macOSColors.semantic.warning}33`
|
|
1429
|
+
},
|
|
1430
|
+
filterOptionLeft: {
|
|
1431
|
+
display: "inline-flex",
|
|
1432
|
+
flexDirection: "row",
|
|
1433
|
+
alignItems: "center",
|
|
1434
|
+
gap: 12,
|
|
1435
|
+
flex: 1,
|
|
1436
|
+
minWidth: 0
|
|
1437
|
+
},
|
|
1438
|
+
filterOptionContent: {
|
|
1439
|
+
display: "inline-flex",
|
|
1440
|
+
flexDirection: "column",
|
|
1441
|
+
flex: 1,
|
|
1442
|
+
minWidth: 0
|
|
1443
|
+
},
|
|
1444
|
+
filterOptionLabel: {
|
|
1445
|
+
color: macOSColors.text.secondary,
|
|
1446
|
+
fontSize: 11,
|
|
1447
|
+
marginBottom: 2,
|
|
1448
|
+
textTransform: "uppercase",
|
|
1449
|
+
letterSpacing: 0.5
|
|
1450
|
+
},
|
|
1451
|
+
filterOptionValue: {
|
|
1452
|
+
color: macOSColors.text.primary,
|
|
1453
|
+
fontSize: 13,
|
|
1454
|
+
fontFamily: "ui-monospace, Menlo, monospace",
|
|
1455
|
+
overflowWrap: "anywhere"
|
|
1456
|
+
},
|
|
1457
|
+
/** Native numberOfLines={1}. */
|
|
1458
|
+
singleLine: {
|
|
1459
|
+
whiteSpace: "nowrap",
|
|
1460
|
+
overflow: "hidden",
|
|
1461
|
+
textOverflow: "ellipsis",
|
|
1462
|
+
display: "block"
|
|
1463
|
+
},
|
|
1464
|
+
filterToggle: {
|
|
1465
|
+
display: "inline-flex",
|
|
1466
|
+
padding: "6px 10px",
|
|
1467
|
+
borderRadius: 4,
|
|
1468
|
+
backgroundColor: macOSColors.background.input,
|
|
1469
|
+
border: `1px solid ${macOSColors.border.default}`,
|
|
1470
|
+
flexShrink: 0
|
|
1471
|
+
},
|
|
1472
|
+
filterToggleActive: {
|
|
1473
|
+
backgroundColor: `${macOSColors.semantic.warning}26`,
|
|
1474
|
+
border: `1px solid ${macOSColors.semantic.warning}4D`
|
|
1475
|
+
},
|
|
1476
|
+
filterToggleText: {
|
|
1477
|
+
fontSize: 10,
|
|
1478
|
+
fontWeight: 600,
|
|
1479
|
+
color: macOSColors.text.muted,
|
|
1480
|
+
letterSpacing: 0.5
|
|
1481
|
+
},
|
|
1482
|
+
filterToggleTextActive: {
|
|
1483
|
+
color: macOSColors.semantic.warning
|
|
1484
|
+
},
|
|
1485
|
+
filterInfoBox: {
|
|
1486
|
+
backgroundColor: macOSColors.semantic.infoBackground,
|
|
1487
|
+
borderRadius: 6,
|
|
1488
|
+
padding: 10,
|
|
1489
|
+
border: `1px solid ${macOSColors.semantic.info}33`
|
|
1490
|
+
},
|
|
1491
|
+
filterInfoText: {
|
|
1492
|
+
color: macOSColors.text.secondary,
|
|
1493
|
+
fontSize: 11,
|
|
1494
|
+
lineHeight: "16px"
|
|
1495
|
+
}
|
|
1496
|
+
};
|