postboy-tui 1.3.9 → 1.4.1
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/dist/cli.js +692 -155
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -67534,7 +67534,7 @@ var useFocusManager = () => {
|
|
|
67534
67534
|
};
|
|
67535
67535
|
var use_focus_manager_default = useFocusManager;
|
|
67536
67536
|
// src/ui/app/ui.tsx
|
|
67537
|
-
var
|
|
67537
|
+
var import_react35 = __toESM(require_react(), 1);
|
|
67538
67538
|
|
|
67539
67539
|
// src/utils/history.ts
|
|
67540
67540
|
import { promises as fs2 } from "fs";
|
|
@@ -67626,7 +67626,7 @@ var historyManager = new HistoryManager;
|
|
|
67626
67626
|
import http from "http";
|
|
67627
67627
|
import https from "https";
|
|
67628
67628
|
import { URL as URL2 } from "url";
|
|
67629
|
-
function sendRequest({ method, url, headers = {}, body }) {
|
|
67629
|
+
function sendRequest({ method, url, headers = {}, body, onProgress }) {
|
|
67630
67630
|
return new Promise((resolve, reject) => {
|
|
67631
67631
|
const urlObj = new URL2(url);
|
|
67632
67632
|
const isHttps = urlObj.protocol === "https:";
|
|
@@ -67649,12 +67649,26 @@ function sendRequest({ method, url, headers = {}, body }) {
|
|
|
67649
67649
|
const req = reqModule.request(options, (res) => {
|
|
67650
67650
|
timings.ttfb = performance.now();
|
|
67651
67651
|
let data = "";
|
|
67652
|
+
let bytesReceived = 0;
|
|
67653
|
+
const totalBytes = parseInt(res.headers["content-length"] || "0", 10);
|
|
67654
|
+
const downloadStartTime = performance.now();
|
|
67652
67655
|
res.on("data", (chunk) => {
|
|
67653
67656
|
data += chunk;
|
|
67657
|
+
bytesReceived += Buffer.byteLength(chunk);
|
|
67658
|
+
if (onProgress) {
|
|
67659
|
+
const elapsed = (performance.now() - downloadStartTime) / 1000;
|
|
67660
|
+
const speed = elapsed > 0 ? bytesReceived / elapsed : 0;
|
|
67661
|
+
onProgress({
|
|
67662
|
+
bytesReceived,
|
|
67663
|
+
totalBytes,
|
|
67664
|
+
speed,
|
|
67665
|
+
elapsed
|
|
67666
|
+
});
|
|
67667
|
+
}
|
|
67654
67668
|
});
|
|
67655
67669
|
res.on("end", () => {
|
|
67656
67670
|
timings.end = performance.now();
|
|
67657
|
-
const contentLength =
|
|
67671
|
+
const contentLength = totalBytes || Buffer.byteLength(data, "utf8");
|
|
67658
67672
|
const metrics = {
|
|
67659
67673
|
dnsLookup: timings.dnsLookup - timings.start,
|
|
67660
67674
|
tcpConnection: timings.tcpConnection - timings.dnsLookup,
|
|
@@ -67859,7 +67873,7 @@ var Spinner = ({ theme }) => {
|
|
|
67859
67873
|
// src/ui/app/components/Formfield.tsx
|
|
67860
67874
|
var import_react24 = __toESM(require_react(), 1);
|
|
67861
67875
|
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
67862
|
-
var InputDialog = ({ label, value, onChange, onClose, theme, suggestions = [] }) => {
|
|
67876
|
+
var InputDialog = ({ label, value, onChange, onClose, theme, suggestions = [], isActive = true }) => {
|
|
67863
67877
|
const [localValue, setLocalValue] = import_react24.useState(value);
|
|
67864
67878
|
const [showSuggestions, setShowSuggestions] = import_react24.useState(false);
|
|
67865
67879
|
const [filteredSuggestions, setFilteredSuggestions] = import_react24.useState([]);
|
|
@@ -67908,7 +67922,7 @@ var InputDialog = ({ label, value, onChange, onClose, theme, suggestions = [] })
|
|
|
67908
67922
|
if (!key.upArrow && !key.downArrow && !key.leftArrow && !key.rightArrow && !key.return && !key.tab) {
|
|
67909
67923
|
setLocalValue((v) => v + input);
|
|
67910
67924
|
}
|
|
67911
|
-
});
|
|
67925
|
+
}, { isActive });
|
|
67912
67926
|
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
67913
67927
|
flexDirection: "column",
|
|
67914
67928
|
borderStyle: "double",
|
|
@@ -67970,8 +67984,8 @@ var FormField = ({ label, value, onChange, placeholder, theme, suggestions = [],
|
|
|
67970
67984
|
const { isFocused } = use_focus_default();
|
|
67971
67985
|
const [showDialog, setShowDialog] = import_react24.useState(false);
|
|
67972
67986
|
import_react24.useEffect(() => {
|
|
67973
|
-
onFocusChange?.(
|
|
67974
|
-
}, [
|
|
67987
|
+
onFocusChange?.(showDialog);
|
|
67988
|
+
}, [showDialog, onFocusChange]);
|
|
67975
67989
|
use_input_default((_, key) => {
|
|
67976
67990
|
if (isFocused && key.return && !showDialog) {
|
|
67977
67991
|
setShowDialog(true);
|
|
@@ -68034,7 +68048,7 @@ var FormField = ({ label, value, onChange, placeholder, theme, suggestions = [],
|
|
|
68034
68048
|
// src/ui/app/components/keyvaluefield.tsx
|
|
68035
68049
|
var import_react25 = __toESM(require_react(), 1);
|
|
68036
68050
|
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
68037
|
-
var KeyValueDialog = ({ label, pairs, onSave, onClose, theme }) => {
|
|
68051
|
+
var KeyValueDialog = ({ label, pairs, onSave, onClose, theme, isActive = true }) => {
|
|
68038
68052
|
const [localPairs, setLocalPairs] = import_react25.useState(pairs.length > 0 ? pairs : [{ key: "", value: "" }]);
|
|
68039
68053
|
const [activeField, setActiveField] = import_react25.useState("key");
|
|
68040
68054
|
const [activeRow, setActiveRow] = import_react25.useState(0);
|
|
@@ -68109,7 +68123,7 @@ var KeyValueDialog = ({ label, pairs, onSave, onClose, theme }) => {
|
|
|
68109
68123
|
return newPairs;
|
|
68110
68124
|
});
|
|
68111
68125
|
}
|
|
68112
|
-
});
|
|
68126
|
+
}, { isActive });
|
|
68113
68127
|
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
68114
68128
|
flexDirection: "column",
|
|
68115
68129
|
borderStyle: "double",
|
|
@@ -68200,8 +68214,8 @@ var KeyValueField = ({ label, value, onChange, placeholder, theme, onFocusChange
|
|
|
68200
68214
|
const { isFocused } = use_focus_default();
|
|
68201
68215
|
const [showDialog, setShowDialog] = import_react25.useState(false);
|
|
68202
68216
|
import_react25.useEffect(() => {
|
|
68203
|
-
onFocusChange?.(
|
|
68204
|
-
}, [
|
|
68217
|
+
onFocusChange?.(showDialog);
|
|
68218
|
+
}, [showDialog, onFocusChange]);
|
|
68205
68219
|
const parseJsonToPairs = (json) => {
|
|
68206
68220
|
try {
|
|
68207
68221
|
const obj = JSON.parse(json || "{}");
|
|
@@ -68285,7 +68299,7 @@ var TabItem = ({ name, label, isActive, onChange, theme }) => {
|
|
|
68285
68299
|
use_input_default((_, key) => {
|
|
68286
68300
|
if (isFocused && key.return)
|
|
68287
68301
|
onChange(name);
|
|
68288
|
-
});
|
|
68302
|
+
}, { isActive: isFocused });
|
|
68289
68303
|
return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
68290
68304
|
borderStyle: "round",
|
|
68291
68305
|
borderTopColor: "grey",
|
|
@@ -68983,7 +68997,7 @@ var HistoryListItem = ({ item, isSelected, theme }) => {
|
|
|
68983
68997
|
}, undefined, true, undefined, this)
|
|
68984
68998
|
}, undefined, false, undefined, this);
|
|
68985
68999
|
};
|
|
68986
|
-
var HistoryList = ({ history, onItemClick, theme }) => {
|
|
69000
|
+
var HistoryList = ({ history, onItemClick, theme, onSearchingChange, startSearching }) => {
|
|
68987
69001
|
const { stdout } = use_stdout_default();
|
|
68988
69002
|
const { isFocused } = use_focus_default();
|
|
68989
69003
|
const { focusNext } = use_focus_manager_default();
|
|
@@ -68992,29 +69006,45 @@ var HistoryList = ({ history, onItemClick, theme }) => {
|
|
|
68992
69006
|
const [searchQuery, setSearchQuery] = import_react27.useState("");
|
|
68993
69007
|
const [isSearching, setIsSearching] = import_react27.useState(false);
|
|
68994
69008
|
const listRef = import_react27.useRef(null);
|
|
69009
|
+
import_react27.useEffect(() => {
|
|
69010
|
+
if (startSearching && !isSearching) {
|
|
69011
|
+
setIsSearching(true);
|
|
69012
|
+
onSearchingChange?.(true);
|
|
69013
|
+
}
|
|
69014
|
+
}, [startSearching, isSearching, onSearchingChange]);
|
|
68995
69015
|
const filteredHistory = fuzzyFilter(history, searchQuery, (item) => `${item.method} ${item.url}`);
|
|
68996
69016
|
const maxHeight = stdout.rows - 10;
|
|
68997
69017
|
use_input_default((input, key) => {
|
|
68998
69018
|
if (input === "/" && !isSearching) {
|
|
68999
69019
|
setIsSearching(true);
|
|
69020
|
+
onSearchingChange?.(true);
|
|
69000
69021
|
return;
|
|
69001
69022
|
}
|
|
69002
69023
|
if (key.escape && isSearching) {
|
|
69003
69024
|
setIsSearching(false);
|
|
69004
69025
|
setSearchQuery("");
|
|
69026
|
+
onSearchingChange?.(false);
|
|
69005
69027
|
return;
|
|
69006
69028
|
}
|
|
69007
|
-
if (isSearching)
|
|
69008
|
-
return;
|
|
69009
69029
|
if (key.upArrow) {
|
|
69010
69030
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
69031
|
+
return;
|
|
69011
69032
|
}
|
|
69012
69033
|
if (key.downArrow) {
|
|
69013
69034
|
setSelectedIndex((prev) => Math.min(filteredHistory.length - 1, prev + 1));
|
|
69035
|
+
return;
|
|
69014
69036
|
}
|
|
69015
69037
|
if (key.return && filteredHistory[selectedIndex]) {
|
|
69016
69038
|
onItemClick(filteredHistory[selectedIndex]);
|
|
69039
|
+
if (isSearching) {
|
|
69040
|
+
setIsSearching(false);
|
|
69041
|
+
setSearchQuery("");
|
|
69042
|
+
onSearchingChange?.(false);
|
|
69043
|
+
}
|
|
69044
|
+
return;
|
|
69017
69045
|
}
|
|
69046
|
+
if (isSearching)
|
|
69047
|
+
return;
|
|
69018
69048
|
if (key.tab) {
|
|
69019
69049
|
focusNext();
|
|
69020
69050
|
}
|
|
@@ -69024,7 +69054,7 @@ var HistoryList = ({ history, onItemClick, theme }) => {
|
|
|
69024
69054
|
if (key.pageDown) {
|
|
69025
69055
|
setScrollPosition((prev) => Math.min(filteredHistory.length - maxHeight, prev + maxHeight));
|
|
69026
69056
|
}
|
|
69027
|
-
}, { isActive: isFocused });
|
|
69057
|
+
}, { isActive: isFocused || isSearching });
|
|
69028
69058
|
import_react27.useEffect(() => {
|
|
69029
69059
|
setSelectedIndex(0);
|
|
69030
69060
|
setScrollPosition(0);
|
|
@@ -69076,7 +69106,7 @@ var HistoryList = ({ history, onItemClick, theme }) => {
|
|
|
69076
69106
|
}, undefined, false, undefined, this)
|
|
69077
69107
|
}, undefined, false, undefined, this) : filteredHistory.slice(scrollPosition, scrollPosition + maxHeight).map((item, index) => /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(HistoryListItem, {
|
|
69078
69108
|
item,
|
|
69079
|
-
isSelected: isFocused && selectedIndex === scrollPosition + index,
|
|
69109
|
+
isSelected: (isFocused || isSearching) && selectedIndex === scrollPosition + index,
|
|
69080
69110
|
theme
|
|
69081
69111
|
}, item.timestamp, false, undefined, this))
|
|
69082
69112
|
}, undefined, false, undefined, this)
|
|
@@ -69101,7 +69131,7 @@ var Footer = import_react28.default.memo(({ theme }) => {
|
|
|
69101
69131
|
color: theme.primary,
|
|
69102
69132
|
children: "PostBoy"
|
|
69103
69133
|
}, undefined, false, undefined, this),
|
|
69104
|
-
" — [Q] Quit | [Ctrl+Enter] Send | [Ctrl+L/H] Switch Tabs | [T] Theme | [E] Export | [Tab] Navigate"
|
|
69134
|
+
" — [Q] Quit | [Ctrl+Enter] Send | [Ctrl+L/H] Switch Tabs | [T] Theme | [E] Export | [F] Find | [Tab] Navigate"
|
|
69105
69135
|
]
|
|
69106
69136
|
}, undefined, true, undefined, this)
|
|
69107
69137
|
}, undefined, false, undefined, this);
|
|
@@ -69148,7 +69178,7 @@ var getIndex = (theme) => {
|
|
|
69148
69178
|
}
|
|
69149
69179
|
return index;
|
|
69150
69180
|
};
|
|
69151
|
-
var ThemeSelector = ({ onThemeChange, theme }) => {
|
|
69181
|
+
var ThemeSelector = ({ onThemeChange, theme, isActive = true }) => {
|
|
69152
69182
|
const [selectedIndex, setSelectedIndex] = import_react29.useState(getIndex(theme.name));
|
|
69153
69183
|
const themeNames = Object.keys(themes);
|
|
69154
69184
|
import_react29.useEffect(() => {
|
|
@@ -69175,7 +69205,7 @@ var ThemeSelector = ({ onThemeChange, theme }) => {
|
|
|
69175
69205
|
onThemeChange(themeNames[newIndex]);
|
|
69176
69206
|
}
|
|
69177
69207
|
}
|
|
69178
|
-
}, { isActive
|
|
69208
|
+
}, { isActive });
|
|
69179
69209
|
return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
|
|
69180
69210
|
flexDirection: "column",
|
|
69181
69211
|
padding: 1,
|
|
@@ -69209,7 +69239,7 @@ var ThemeSelector = ({ onThemeChange, theme }) => {
|
|
|
69209
69239
|
// src/ui/app/components/scrollablebox.tsx
|
|
69210
69240
|
var import_react30 = __toESM(require_react(), 1);
|
|
69211
69241
|
var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
|
|
69212
|
-
var ScrollableBox = ({ children }) => {
|
|
69242
|
+
var ScrollableBox = ({ children, isActive = true }) => {
|
|
69213
69243
|
const { stdout } = use_stdout_default();
|
|
69214
69244
|
const [scrollPosition, setScrollPosition] = import_react30.useState(0);
|
|
69215
69245
|
const maxHeight = stdout.rows - 10;
|
|
@@ -69219,7 +69249,7 @@ var ScrollableBox = ({ children }) => {
|
|
|
69219
69249
|
setScrollPosition((prev) => Math.max(0, prev - maxHeight));
|
|
69220
69250
|
if (key.pageDown)
|
|
69221
69251
|
setScrollPosition((prev) => Math.min(contentHeight - maxHeight, prev + maxHeight));
|
|
69222
|
-
});
|
|
69252
|
+
}, { isActive });
|
|
69223
69253
|
import_react30.useEffect(() => {
|
|
69224
69254
|
const estimateHeight = (node) => {
|
|
69225
69255
|
if (!node)
|
|
@@ -69368,6 +69398,140 @@ var JsonSyntaxHighlight = import_react31.default.memo(({ jsonString, theme }) =>
|
|
|
69368
69398
|
// src/ui/app/components/responsepanel.tsx
|
|
69369
69399
|
var import_react32 = __toESM(require_react(), 1);
|
|
69370
69400
|
var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
|
|
69401
|
+
var StatusBadge = ({ status, statusText, theme }) => {
|
|
69402
|
+
const [glowFrame, setGlowFrame] = import_react32.useState(0);
|
|
69403
|
+
const statusNum = parseInt(status, 10);
|
|
69404
|
+
import_react32.useEffect(() => {
|
|
69405
|
+
const interval = setInterval(() => {
|
|
69406
|
+
setGlowFrame((prev) => (prev + 1) % 4);
|
|
69407
|
+
}, 300);
|
|
69408
|
+
return () => clearInterval(interval);
|
|
69409
|
+
}, []);
|
|
69410
|
+
const getStatusIcon = () => {
|
|
69411
|
+
if (statusNum >= 200 && statusNum < 300)
|
|
69412
|
+
return ["✓", "✔", "☑", "✓"][glowFrame];
|
|
69413
|
+
if (statusNum >= 300 && statusNum < 400)
|
|
69414
|
+
return ["↪", "→", "⇒", "↪"][glowFrame];
|
|
69415
|
+
if (statusNum >= 400 && statusNum < 500)
|
|
69416
|
+
return ["⚠", "⚡", "⚠", "⚡"][glowFrame];
|
|
69417
|
+
if (statusNum >= 500)
|
|
69418
|
+
return ["✗", "✘", "☒", "✗"][glowFrame];
|
|
69419
|
+
return "●";
|
|
69420
|
+
};
|
|
69421
|
+
const getBadgeStyle = () => {
|
|
69422
|
+
if (statusNum >= 200 && statusNum < 300)
|
|
69423
|
+
return { bg: theme.colors.success, icon: getStatusIcon(), label: "SUCCESS" };
|
|
69424
|
+
if (statusNum >= 300 && statusNum < 400)
|
|
69425
|
+
return { bg: theme.colors.accent, icon: getStatusIcon(), label: "REDIRECT" };
|
|
69426
|
+
if (statusNum >= 400 && statusNum < 500)
|
|
69427
|
+
return { bg: theme.colors.error, icon: getStatusIcon(), label: "CLIENT ERR" };
|
|
69428
|
+
if (statusNum >= 500)
|
|
69429
|
+
return { bg: theme.colors.error, icon: getStatusIcon(), label: "SERVER ERR" };
|
|
69430
|
+
return { bg: theme.colors.muted, icon: "●", label: "UNKNOWN" };
|
|
69431
|
+
};
|
|
69432
|
+
const style = getBadgeStyle();
|
|
69433
|
+
const glowChars = ["░", "▒", "▓", "▒"];
|
|
69434
|
+
if (!status || status === "Error") {
|
|
69435
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69436
|
+
children: [
|
|
69437
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69438
|
+
color: theme.colors.error,
|
|
69439
|
+
bold: true,
|
|
69440
|
+
children: "✗ "
|
|
69441
|
+
}, undefined, false, undefined, this),
|
|
69442
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69443
|
+
color: theme.colors.error,
|
|
69444
|
+
children: statusText || "Error"
|
|
69445
|
+
}, undefined, false, undefined, this)
|
|
69446
|
+
]
|
|
69447
|
+
}, undefined, true, undefined, this);
|
|
69448
|
+
}
|
|
69449
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69450
|
+
children: [
|
|
69451
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69452
|
+
color: style.bg,
|
|
69453
|
+
dimColor: true,
|
|
69454
|
+
children: glowChars[glowFrame]
|
|
69455
|
+
}, undefined, false, undefined, this),
|
|
69456
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69457
|
+
backgroundColor: style.bg,
|
|
69458
|
+
color: theme.colors.white,
|
|
69459
|
+
bold: true,
|
|
69460
|
+
children: [
|
|
69461
|
+
" ",
|
|
69462
|
+
style.icon,
|
|
69463
|
+
" ",
|
|
69464
|
+
status,
|
|
69465
|
+
" "
|
|
69466
|
+
]
|
|
69467
|
+
}, undefined, true, undefined, this),
|
|
69468
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69469
|
+
color: style.bg,
|
|
69470
|
+
dimColor: true,
|
|
69471
|
+
children: glowChars[glowFrame]
|
|
69472
|
+
}, undefined, false, undefined, this),
|
|
69473
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69474
|
+
color: theme.colors.muted,
|
|
69475
|
+
children: " │ "
|
|
69476
|
+
}, undefined, false, undefined, this),
|
|
69477
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69478
|
+
color: style.bg,
|
|
69479
|
+
bold: true,
|
|
69480
|
+
children: style.label
|
|
69481
|
+
}, undefined, false, undefined, this),
|
|
69482
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69483
|
+
color: theme.colors.muted,
|
|
69484
|
+
children: " │ "
|
|
69485
|
+
}, undefined, false, undefined, this),
|
|
69486
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69487
|
+
color: theme.colors.white,
|
|
69488
|
+
children: statusText
|
|
69489
|
+
}, undefined, false, undefined, this)
|
|
69490
|
+
]
|
|
69491
|
+
}, undefined, true, undefined, this);
|
|
69492
|
+
};
|
|
69493
|
+
var TypewriterText = ({ text, theme, speed = 2 }) => {
|
|
69494
|
+
const [displayedLength, setDisplayedLength] = import_react32.useState(0);
|
|
69495
|
+
const [cursorVisible, setCursorVisible] = import_react32.useState(true);
|
|
69496
|
+
const previousTextRef = import_react32.useRef("");
|
|
69497
|
+
import_react32.useEffect(() => {
|
|
69498
|
+
if (text !== previousTextRef.current) {
|
|
69499
|
+
setDisplayedLength(0);
|
|
69500
|
+
previousTextRef.current = text;
|
|
69501
|
+
}
|
|
69502
|
+
}, [text]);
|
|
69503
|
+
import_react32.useEffect(() => {
|
|
69504
|
+
if (displayedLength < text.length) {
|
|
69505
|
+
const charsToAdd = Math.min(speed, text.length - displayedLength);
|
|
69506
|
+
const timeout = setTimeout(() => {
|
|
69507
|
+
setDisplayedLength((prev) => Math.min(prev + charsToAdd, text.length));
|
|
69508
|
+
}, 5);
|
|
69509
|
+
return () => clearTimeout(timeout);
|
|
69510
|
+
}
|
|
69511
|
+
}, [displayedLength, text, speed]);
|
|
69512
|
+
import_react32.useEffect(() => {
|
|
69513
|
+
const interval = setInterval(() => {
|
|
69514
|
+
setCursorVisible((prev) => !prev);
|
|
69515
|
+
}, 400);
|
|
69516
|
+
return () => clearInterval(interval);
|
|
69517
|
+
}, []);
|
|
69518
|
+
const displayedText = text.slice(0, displayedLength);
|
|
69519
|
+
const isComplete = displayedLength >= text.length;
|
|
69520
|
+
const cursor = !isComplete && cursorVisible ? "█" : !isComplete ? " " : "";
|
|
69521
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69522
|
+
flexDirection: "column",
|
|
69523
|
+
children: [
|
|
69524
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(JsonSyntaxHighlight, {
|
|
69525
|
+
jsonString: displayedText,
|
|
69526
|
+
theme
|
|
69527
|
+
}, undefined, false, undefined, this),
|
|
69528
|
+
!isComplete && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69529
|
+
color: theme.colors.accent,
|
|
69530
|
+
children: cursor
|
|
69531
|
+
}, undefined, false, undefined, this)
|
|
69532
|
+
]
|
|
69533
|
+
}, undefined, true, undefined, this);
|
|
69534
|
+
};
|
|
69371
69535
|
var ResponsePanel = import_react32.default.memo(({ response, theme }) => {
|
|
69372
69536
|
const [activeTab, setActiveTab] = import_react32.useState("body");
|
|
69373
69537
|
const tabs = [{ name: "body", label: "Body" }, { name: "headers", label: "Headers" }];
|
|
@@ -69377,25 +69541,12 @@ var ResponsePanel = import_react32.default.memo(({ response, theme }) => {
|
|
|
69377
69541
|
children: [
|
|
69378
69542
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69379
69543
|
marginBottom: 1,
|
|
69380
|
-
children:
|
|
69381
|
-
|
|
69382
|
-
|
|
69383
|
-
|
|
69384
|
-
|
|
69385
|
-
|
|
69386
|
-
}, undefined, false, undefined, this)
|
|
69387
|
-
}, undefined, false, undefined, this),
|
|
69388
|
-
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
69389
|
-
color: getStatusColor(response.status, theme),
|
|
69390
|
-
bold: true,
|
|
69391
|
-
children: [
|
|
69392
|
-
response.status,
|
|
69393
|
-
" ",
|
|
69394
|
-
response.statustext
|
|
69395
|
-
]
|
|
69396
|
-
}, undefined, true, undefined, this)
|
|
69397
|
-
]
|
|
69398
|
-
}, undefined, true, undefined, this),
|
|
69544
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(StatusBadge, {
|
|
69545
|
+
status: response.status,
|
|
69546
|
+
statusText: response.statustext,
|
|
69547
|
+
theme
|
|
69548
|
+
}, undefined, false, undefined, this)
|
|
69549
|
+
}, undefined, false, undefined, this),
|
|
69399
69550
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Tabs, {
|
|
69400
69551
|
tabs,
|
|
69401
69552
|
activeTab,
|
|
@@ -69407,6 +69558,7 @@ var ResponsePanel = import_react32.default.memo(({ response, theme }) => {
|
|
|
69407
69558
|
flexGrow: 1,
|
|
69408
69559
|
children: [
|
|
69409
69560
|
activeTab === "headers" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ScrollableBox, {
|
|
69561
|
+
isActive: activeTab === "headers",
|
|
69410
69562
|
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69411
69563
|
flexDirection: "column",
|
|
69412
69564
|
children: Object.entries(JSON.parse(response.headers || "{}")).map(([key, value]) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
@@ -69428,12 +69580,14 @@ var ResponsePanel = import_react32.default.memo(({ response, theme }) => {
|
|
|
69428
69580
|
}, undefined, false, undefined, this)
|
|
69429
69581
|
}, undefined, false, undefined, this),
|
|
69430
69582
|
activeTab === "body" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ScrollableBox, {
|
|
69583
|
+
isActive: activeTab === "body",
|
|
69431
69584
|
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
69432
69585
|
flexDirection: "column",
|
|
69433
69586
|
flexGrow: 1,
|
|
69434
|
-
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(
|
|
69435
|
-
|
|
69436
|
-
theme
|
|
69587
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(TypewriterText, {
|
|
69588
|
+
text: response.body,
|
|
69589
|
+
theme,
|
|
69590
|
+
speed: 50
|
|
69437
69591
|
}, undefined, false, undefined, this)
|
|
69438
69592
|
}, undefined, false, undefined, this)
|
|
69439
69593
|
}, undefined, false, undefined, this)
|
|
@@ -69872,42 +70026,100 @@ class ThemeManager {
|
|
|
69872
70026
|
var themeManager = new ThemeManager;
|
|
69873
70027
|
|
|
69874
70028
|
// src/ui/app/components/metricspanel.tsx
|
|
70029
|
+
var import_react34 = __toESM(require_react(), 1);
|
|
69875
70030
|
var jsx_dev_runtime12 = __toESM(require_jsx_dev_runtime(), 1);
|
|
69876
|
-
var
|
|
69877
|
-
|
|
70031
|
+
var BAR_CHARS = ["▱", "▰"];
|
|
70032
|
+
var GLOW_FRAMES = ["◐", "◓", "◑", "◒"];
|
|
70033
|
+
var SPARK_CHARS = ["⚡", "✦", "✧", "⚡", "★", "☆"];
|
|
70034
|
+
var MetricBar = ({ label, value, maxValue, color, theme, delay }) => {
|
|
70035
|
+
const barWidth = 30;
|
|
69878
70036
|
const safeValue = Math.max(0, value);
|
|
69879
|
-
const
|
|
69880
|
-
const
|
|
69881
|
-
const
|
|
70037
|
+
const targetFilled = Math.max(0, Math.min(barWidth, maxValue > 0 ? Math.round(safeValue / maxValue * barWidth) : 0));
|
|
70038
|
+
const [animatedFilled, setAnimatedFilled] = import_react34.useState(0);
|
|
70039
|
+
const [glowFrame, setGlowFrame] = import_react34.useState(0);
|
|
70040
|
+
const [sparkle, setSparkle] = import_react34.useState(false);
|
|
70041
|
+
import_react34.useEffect(() => {
|
|
70042
|
+
const timeout = setTimeout(() => {
|
|
70043
|
+
if (animatedFilled < targetFilled) {
|
|
70044
|
+
const interval = setInterval(() => {
|
|
70045
|
+
setAnimatedFilled((prev) => {
|
|
70046
|
+
if (prev >= targetFilled) {
|
|
70047
|
+
clearInterval(interval);
|
|
70048
|
+
setSparkle(true);
|
|
70049
|
+
setTimeout(() => setSparkle(false), 300);
|
|
70050
|
+
return targetFilled;
|
|
70051
|
+
}
|
|
70052
|
+
return prev + 1;
|
|
70053
|
+
});
|
|
70054
|
+
}, 20);
|
|
70055
|
+
return () => clearInterval(interval);
|
|
70056
|
+
}
|
|
70057
|
+
}, delay);
|
|
70058
|
+
return () => clearTimeout(timeout);
|
|
70059
|
+
}, [targetFilled, delay]);
|
|
70060
|
+
import_react34.useEffect(() => {
|
|
70061
|
+
const interval = setInterval(() => {
|
|
70062
|
+
setGlowFrame((prev) => (prev + 1) % GLOW_FRAMES.length);
|
|
70063
|
+
}, 150);
|
|
70064
|
+
return () => clearInterval(interval);
|
|
70065
|
+
}, []);
|
|
70066
|
+
const filledBar = BAR_CHARS[1].repeat(animatedFilled);
|
|
70067
|
+
const emptyBar = BAR_CHARS[0].repeat(barWidth - animatedFilled);
|
|
70068
|
+
const indicator = animatedFilled > 0 && animatedFilled < targetFilled ? GLOW_FRAMES[glowFrame] : sparkle ? SPARK_CHARS[Math.floor(Math.random() * SPARK_CHARS.length)] : "";
|
|
69882
70069
|
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
69883
70070
|
marginY: 0,
|
|
69884
70071
|
children: [
|
|
69885
70072
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
69886
|
-
width:
|
|
70073
|
+
width: 16,
|
|
69887
70074
|
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
69888
|
-
color
|
|
70075
|
+
color,
|
|
70076
|
+
bold: true,
|
|
69889
70077
|
children: label
|
|
69890
70078
|
}, undefined, false, undefined, this)
|
|
69891
70079
|
}, undefined, false, undefined, this),
|
|
70080
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70081
|
+
color: theme.colors.muted,
|
|
70082
|
+
children: "│"
|
|
70083
|
+
}, undefined, false, undefined, this),
|
|
69892
70084
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
69893
|
-
width: barWidth +
|
|
69894
|
-
children:
|
|
69895
|
-
|
|
69896
|
-
|
|
69897
|
-
|
|
70085
|
+
width: barWidth + 3,
|
|
70086
|
+
children: [
|
|
70087
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70088
|
+
color,
|
|
70089
|
+
children: filledBar
|
|
70090
|
+
}, undefined, false, undefined, this),
|
|
70091
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70092
|
+
color,
|
|
70093
|
+
bold: true,
|
|
70094
|
+
children: indicator
|
|
70095
|
+
}, undefined, false, undefined, this),
|
|
70096
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70097
|
+
color: theme.colors.muted,
|
|
70098
|
+
dimColor: true,
|
|
70099
|
+
children: emptyBar
|
|
70100
|
+
}, undefined, false, undefined, this)
|
|
70101
|
+
]
|
|
70102
|
+
}, undefined, true, undefined, this),
|
|
70103
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70104
|
+
color: theme.colors.muted,
|
|
70105
|
+
children: "│"
|
|
69898
70106
|
}, undefined, false, undefined, this),
|
|
69899
70107
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
69900
|
-
width:
|
|
70108
|
+
width: 10,
|
|
69901
70109
|
justifyContent: "flex-end",
|
|
69902
|
-
children:
|
|
69903
|
-
|
|
69904
|
-
|
|
69905
|
-
|
|
69906
|
-
safeValue.toFixed(1)
|
|
69907
|
-
|
|
69908
|
-
|
|
69909
|
-
|
|
69910
|
-
|
|
70110
|
+
children: [
|
|
70111
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70112
|
+
color: theme.colors.white,
|
|
70113
|
+
bold: true,
|
|
70114
|
+
children: safeValue.toFixed(1)
|
|
70115
|
+
}, undefined, false, undefined, this),
|
|
70116
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70117
|
+
color: theme.colors.muted,
|
|
70118
|
+
dimColor: true,
|
|
70119
|
+
children: "ms"
|
|
70120
|
+
}, undefined, false, undefined, this)
|
|
70121
|
+
]
|
|
70122
|
+
}, undefined, true, undefined, this)
|
|
69911
70123
|
]
|
|
69912
70124
|
}, undefined, true, undefined, this);
|
|
69913
70125
|
};
|
|
@@ -69919,75 +70131,290 @@ var formatBytes = (bytes) => {
|
|
|
69919
70131
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
69920
70132
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
69921
70133
|
};
|
|
69922
|
-
var
|
|
69923
|
-
|
|
69924
|
-
|
|
69925
|
-
|
|
69926
|
-
|
|
69927
|
-
|
|
69928
|
-
|
|
69929
|
-
|
|
69930
|
-
|
|
69931
|
-
|
|
69932
|
-
|
|
69933
|
-
|
|
70134
|
+
var AnimatedValue = ({ value, suffix, color }) => {
|
|
70135
|
+
const [displayValue, setDisplayValue] = import_react34.useState(0);
|
|
70136
|
+
import_react34.useEffect(() => {
|
|
70137
|
+
const duration = 500;
|
|
70138
|
+
const steps = 20;
|
|
70139
|
+
const increment = value / steps;
|
|
70140
|
+
let current = 0;
|
|
70141
|
+
const interval = setInterval(() => {
|
|
70142
|
+
current += increment;
|
|
70143
|
+
if (current >= value) {
|
|
70144
|
+
setDisplayValue(value);
|
|
70145
|
+
clearInterval(interval);
|
|
70146
|
+
} else {
|
|
70147
|
+
setDisplayValue(current);
|
|
70148
|
+
}
|
|
70149
|
+
}, duration / steps);
|
|
70150
|
+
return () => clearInterval(interval);
|
|
70151
|
+
}, [value]);
|
|
70152
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70153
|
+
color,
|
|
70154
|
+
bold: true,
|
|
70155
|
+
children: [
|
|
70156
|
+
displayValue.toFixed(2),
|
|
70157
|
+
" ",
|
|
70158
|
+
suffix
|
|
70159
|
+
]
|
|
70160
|
+
}, undefined, true, undefined, this);
|
|
70161
|
+
};
|
|
70162
|
+
var PulsingDot = ({ color }) => {
|
|
70163
|
+
const [frame, setFrame] = import_react34.useState(0);
|
|
70164
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
70165
|
+
import_react34.useEffect(() => {
|
|
70166
|
+
const interval = setInterval(() => {
|
|
70167
|
+
setFrame((prev) => (prev + 1) % frames.length);
|
|
70168
|
+
}, 80);
|
|
70169
|
+
return () => clearInterval(interval);
|
|
70170
|
+
}, []);
|
|
70171
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70172
|
+
color,
|
|
70173
|
+
children: frames[frame]
|
|
70174
|
+
}, undefined, false, undefined, this);
|
|
70175
|
+
};
|
|
70176
|
+
var TimelineWaterfall = ({ metrics, theme }) => {
|
|
70177
|
+
const [animationProgress, setAnimationProgress] = import_react34.useState(0);
|
|
70178
|
+
const [pulseFrame, setPulseFrame] = import_react34.useState(0);
|
|
70179
|
+
const totalWidth = 50;
|
|
70180
|
+
const segments = [
|
|
70181
|
+
{ label: "DNS", value: Math.max(0, metrics.dnsLookup), color: theme.colors.cool, icon: "⚡" },
|
|
70182
|
+
{ label: "TCP", value: Math.max(0, metrics.tcpConnection), color: theme.colors.success, icon: "\uD83D\uDD0C" },
|
|
70183
|
+
...metrics.tlsHandshake > 0 ? [{ label: "TLS", value: Math.max(0, metrics.tlsHandshake), color: theme.colors.secondary, icon: "\uD83D\uDD10" }] : [],
|
|
70184
|
+
{ label: "TTFB", value: Math.max(0, metrics.ttfb), color: theme.colors.accent, icon: "⏱️" },
|
|
70185
|
+
{ label: "DL", value: Math.max(0, metrics.contentDownload), color: theme.colors.primary, icon: "\uD83D\uDCE5" }
|
|
70186
|
+
];
|
|
70187
|
+
const totalTime = segments.reduce((sum, s) => sum + s.value, 0);
|
|
70188
|
+
import_react34.useEffect(() => {
|
|
70189
|
+
setAnimationProgress(0);
|
|
70190
|
+
const interval = setInterval(() => {
|
|
70191
|
+
setAnimationProgress((prev) => {
|
|
70192
|
+
if (prev >= 100) {
|
|
70193
|
+
clearInterval(interval);
|
|
70194
|
+
return 100;
|
|
70195
|
+
}
|
|
70196
|
+
return prev + 2;
|
|
70197
|
+
});
|
|
70198
|
+
}, 15);
|
|
70199
|
+
return () => clearInterval(interval);
|
|
70200
|
+
}, [metrics]);
|
|
70201
|
+
import_react34.useEffect(() => {
|
|
70202
|
+
const interval = setInterval(() => {
|
|
70203
|
+
setPulseFrame((prev) => (prev + 1) % 4);
|
|
70204
|
+
}, 200);
|
|
70205
|
+
return () => clearInterval(interval);
|
|
70206
|
+
}, []);
|
|
70207
|
+
const pulseChars = ["▁", "▂", "▃", "▄"];
|
|
70208
|
+
const endCaps = ["◀", "▶"];
|
|
69934
70209
|
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
69935
70210
|
flexDirection: "column",
|
|
69936
|
-
|
|
70211
|
+
marginY: 1,
|
|
69937
70212
|
children: [
|
|
69938
70213
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
69939
70214
|
marginBottom: 1,
|
|
69940
|
-
flexDirection: "column",
|
|
69941
70215
|
children: [
|
|
69942
70216
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
69943
70217
|
color: theme.colors.accent,
|
|
69944
70218
|
bold: true,
|
|
69945
|
-
children: "
|
|
70219
|
+
children: "⏳ Request Timeline"
|
|
69946
70220
|
}, undefined, false, undefined, this),
|
|
69947
70221
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
69948
70222
|
color: theme.colors.muted,
|
|
69949
|
-
children:
|
|
70223
|
+
children: [
|
|
70224
|
+
" (",
|
|
70225
|
+
totalTime.toFixed(0),
|
|
70226
|
+
"ms total)"
|
|
70227
|
+
]
|
|
70228
|
+
}, undefined, true, undefined, this)
|
|
70229
|
+
]
|
|
70230
|
+
}, undefined, true, undefined, this),
|
|
70231
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70232
|
+
children: [
|
|
70233
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70234
|
+
color: theme.colors.muted,
|
|
70235
|
+
children: endCaps[0]
|
|
70236
|
+
}, undefined, false, undefined, this),
|
|
70237
|
+
segments.map((segment, idx) => {
|
|
70238
|
+
const segmentWidth = Math.max(1, Math.round(segment.value / totalTime * totalWidth));
|
|
70239
|
+
const animatedWidth = Math.round(animationProgress / 100 * segmentWidth);
|
|
70240
|
+
const filledPart = "█".repeat(Math.max(0, animatedWidth));
|
|
70241
|
+
const emptyPart = "░".repeat(Math.max(0, segmentWidth - animatedWidth));
|
|
70242
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70243
|
+
children: [
|
|
70244
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70245
|
+
color: segment.color,
|
|
70246
|
+
children: filledPart
|
|
70247
|
+
}, undefined, false, undefined, this),
|
|
70248
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70249
|
+
color: segment.color,
|
|
70250
|
+
dimColor: true,
|
|
70251
|
+
children: emptyPart
|
|
70252
|
+
}, undefined, false, undefined, this)
|
|
70253
|
+
]
|
|
70254
|
+
}, idx, true, undefined, this);
|
|
70255
|
+
}),
|
|
70256
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70257
|
+
color: theme.colors.muted,
|
|
70258
|
+
children: endCaps[1]
|
|
70259
|
+
}, undefined, false, undefined, this),
|
|
70260
|
+
animationProgress < 100 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70261
|
+
color: theme.colors.accent,
|
|
70262
|
+
children: [
|
|
70263
|
+
" ",
|
|
70264
|
+
pulseChars[pulseFrame]
|
|
70265
|
+
]
|
|
70266
|
+
}, undefined, true, undefined, this),
|
|
70267
|
+
animationProgress >= 100 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70268
|
+
color: theme.colors.success,
|
|
70269
|
+
children: " ✓"
|
|
69950
70270
|
}, undefined, false, undefined, this)
|
|
69951
70271
|
]
|
|
69952
70272
|
}, undefined, true, undefined, this),
|
|
70273
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70274
|
+
marginTop: 1,
|
|
70275
|
+
flexWrap: "wrap",
|
|
70276
|
+
children: segments.map((segment, idx) => /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70277
|
+
marginRight: 2,
|
|
70278
|
+
children: [
|
|
70279
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70280
|
+
color: segment.color,
|
|
70281
|
+
children: "■"
|
|
70282
|
+
}, undefined, false, undefined, this),
|
|
70283
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70284
|
+
color: theme.colors.muted,
|
|
70285
|
+
children: [
|
|
70286
|
+
" ",
|
|
70287
|
+
segment.label,
|
|
70288
|
+
" "
|
|
70289
|
+
]
|
|
70290
|
+
}, undefined, true, undefined, this),
|
|
70291
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70292
|
+
color: theme.colors.white,
|
|
70293
|
+
bold: true,
|
|
70294
|
+
children: segment.value.toFixed(0)
|
|
70295
|
+
}, undefined, false, undefined, this),
|
|
70296
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70297
|
+
color: theme.colors.muted,
|
|
70298
|
+
dimColor: true,
|
|
70299
|
+
children: "ms"
|
|
70300
|
+
}, undefined, false, undefined, this)
|
|
70301
|
+
]
|
|
70302
|
+
}, idx, true, undefined, this))
|
|
70303
|
+
}, undefined, false, undefined, this)
|
|
70304
|
+
]
|
|
70305
|
+
}, undefined, true, undefined, this);
|
|
70306
|
+
};
|
|
70307
|
+
var MetricsPanel = ({ metrics, theme }) => {
|
|
70308
|
+
const [showContent, setShowContent] = import_react34.useState(false);
|
|
70309
|
+
import_react34.useEffect(() => {
|
|
70310
|
+
if (metrics) {
|
|
70311
|
+
setShowContent(false);
|
|
70312
|
+
const timeout = setTimeout(() => setShowContent(true), 100);
|
|
70313
|
+
return () => clearTimeout(timeout);
|
|
70314
|
+
}
|
|
70315
|
+
}, [metrics]);
|
|
70316
|
+
if (!metrics) {
|
|
70317
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70318
|
+
flexDirection: "column",
|
|
70319
|
+
padding: 1,
|
|
70320
|
+
alignItems: "center",
|
|
70321
|
+
children: [
|
|
70322
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70323
|
+
marginBottom: 1,
|
|
70324
|
+
children: [
|
|
70325
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(PulsingDot, {
|
|
70326
|
+
color: theme.colors.muted
|
|
70327
|
+
}, undefined, false, undefined, this),
|
|
70328
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70329
|
+
color: theme.colors.muted,
|
|
70330
|
+
children: " Waiting for request..."
|
|
70331
|
+
}, undefined, false, undefined, this)
|
|
70332
|
+
]
|
|
70333
|
+
}, undefined, true, undefined, this),
|
|
70334
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70335
|
+
color: theme.colors.muted,
|
|
70336
|
+
dimColor: true,
|
|
70337
|
+
children: "Send a request to see metrics"
|
|
70338
|
+
}, undefined, false, undefined, this)
|
|
70339
|
+
]
|
|
70340
|
+
}, undefined, true, undefined, this);
|
|
70341
|
+
}
|
|
70342
|
+
const maxTime = Math.max(Math.max(0, metrics.dnsLookup), Math.max(0, metrics.tcpConnection), Math.max(0, metrics.tlsHandshake), Math.max(0, metrics.ttfb), Math.max(0, metrics.contentDownload), 1);
|
|
70343
|
+
if (!showContent) {
|
|
70344
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70345
|
+
flexDirection: "column",
|
|
70346
|
+
padding: 1,
|
|
70347
|
+
alignItems: "center",
|
|
70348
|
+
children: [
|
|
70349
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(PulsingDot, {
|
|
70350
|
+
color: theme.colors.accent
|
|
70351
|
+
}, undefined, false, undefined, this),
|
|
70352
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70353
|
+
color: theme.colors.accent,
|
|
70354
|
+
children: " Analyzing..."
|
|
70355
|
+
}, undefined, false, undefined, this)
|
|
70356
|
+
]
|
|
70357
|
+
}, undefined, true, undefined, this);
|
|
70358
|
+
}
|
|
70359
|
+
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70360
|
+
flexDirection: "column",
|
|
70361
|
+
paddingX: 1,
|
|
70362
|
+
children: [
|
|
70363
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(TimelineWaterfall, {
|
|
70364
|
+
metrics,
|
|
70365
|
+
theme
|
|
70366
|
+
}, undefined, false, undefined, this),
|
|
70367
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70368
|
+
marginTop: 1,
|
|
70369
|
+
flexDirection: "column",
|
|
70370
|
+
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70371
|
+
color: theme.colors.muted,
|
|
70372
|
+
children: "┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈"
|
|
70373
|
+
}, undefined, false, undefined, this)
|
|
70374
|
+
}, undefined, false, undefined, this),
|
|
69953
70375
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
69954
70376
|
flexDirection: "column",
|
|
69955
70377
|
gap: 0,
|
|
69956
70378
|
children: [
|
|
69957
70379
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
69958
|
-
label: "
|
|
70380
|
+
label: "⚡ DNS",
|
|
69959
70381
|
value: metrics.dnsLookup,
|
|
69960
70382
|
maxValue: maxTime,
|
|
69961
70383
|
color: theme.colors.cool,
|
|
69962
|
-
theme
|
|
70384
|
+
theme,
|
|
70385
|
+
delay: 0
|
|
69963
70386
|
}, undefined, false, undefined, this),
|
|
69964
70387
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
69965
|
-
label: "\uD83D\uDD0C TCP
|
|
70388
|
+
label: "\uD83D\uDD0C TCP",
|
|
69966
70389
|
value: metrics.tcpConnection,
|
|
69967
70390
|
maxValue: maxTime,
|
|
69968
70391
|
color: theme.colors.success,
|
|
69969
|
-
theme
|
|
70392
|
+
theme,
|
|
70393
|
+
delay: 100
|
|
69970
70394
|
}, undefined, false, undefined, this),
|
|
69971
70395
|
metrics.tlsHandshake > 0 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
69972
|
-
label: "\uD83D\uDD10 TLS
|
|
70396
|
+
label: "\uD83D\uDD10 TLS",
|
|
69973
70397
|
value: metrics.tlsHandshake,
|
|
69974
70398
|
maxValue: maxTime,
|
|
69975
70399
|
color: theme.colors.secondary,
|
|
69976
|
-
theme
|
|
70400
|
+
theme,
|
|
70401
|
+
delay: 200
|
|
69977
70402
|
}, undefined, false, undefined, this),
|
|
69978
70403
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
69979
70404
|
label: "⏱️ TTFB",
|
|
69980
70405
|
value: metrics.ttfb,
|
|
69981
70406
|
maxValue: maxTime,
|
|
69982
70407
|
color: theme.colors.accent,
|
|
69983
|
-
theme
|
|
70408
|
+
theme,
|
|
70409
|
+
delay: 300
|
|
69984
70410
|
}, undefined, false, undefined, this),
|
|
69985
70411
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(MetricBar, {
|
|
69986
70412
|
label: "\uD83D\uDCE5 Download",
|
|
69987
70413
|
value: metrics.contentDownload,
|
|
69988
70414
|
maxValue: maxTime,
|
|
69989
70415
|
color: theme.colors.primary,
|
|
69990
|
-
theme
|
|
70416
|
+
theme,
|
|
70417
|
+
delay: 400
|
|
69991
70418
|
}, undefined, false, undefined, this)
|
|
69992
70419
|
]
|
|
69993
70420
|
}, undefined, true, undefined, this),
|
|
@@ -69996,7 +70423,7 @@ var MetricsPanel = ({ metrics, theme }) => {
|
|
|
69996
70423
|
flexDirection: "column",
|
|
69997
70424
|
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
69998
70425
|
color: theme.colors.muted,
|
|
69999
|
-
children: "
|
|
70426
|
+
children: "┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈"
|
|
70000
70427
|
}, undefined, false, undefined, this)
|
|
70001
70428
|
}, undefined, false, undefined, this),
|
|
70002
70429
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
@@ -70007,30 +70434,25 @@ var MetricsPanel = ({ metrics, theme }) => {
|
|
|
70007
70434
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70008
70435
|
children: [
|
|
70009
70436
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70010
|
-
width:
|
|
70437
|
+
width: 12,
|
|
70011
70438
|
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70012
70439
|
color: theme.colors.accent,
|
|
70013
|
-
|
|
70014
|
-
children: "\uD83D\uDCCA Total Time"
|
|
70440
|
+
children: "⚡ Total"
|
|
70015
70441
|
}, undefined, false, undefined, this)
|
|
70016
70442
|
}, undefined, false, undefined, this),
|
|
70017
|
-
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(
|
|
70018
|
-
|
|
70019
|
-
|
|
70020
|
-
|
|
70021
|
-
|
|
70022
|
-
" ms"
|
|
70023
|
-
]
|
|
70024
|
-
}, undefined, true, undefined, this)
|
|
70443
|
+
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(AnimatedValue, {
|
|
70444
|
+
value: metrics.total,
|
|
70445
|
+
suffix: "ms",
|
|
70446
|
+
color: theme.colors.white
|
|
70447
|
+
}, undefined, false, undefined, this)
|
|
70025
70448
|
]
|
|
70026
70449
|
}, undefined, true, undefined, this),
|
|
70027
70450
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70028
70451
|
children: [
|
|
70029
70452
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70030
|
-
width:
|
|
70453
|
+
width: 12,
|
|
70031
70454
|
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70032
70455
|
color: theme.colors.accent,
|
|
70033
|
-
bold: true,
|
|
70034
70456
|
children: "\uD83D\uDCE6 Size"
|
|
70035
70457
|
}, undefined, false, undefined, this)
|
|
70036
70458
|
}, undefined, false, undefined, this),
|
|
@@ -70044,10 +70466,9 @@ var MetricsPanel = ({ metrics, theme }) => {
|
|
|
70044
70466
|
metrics.contentLength > 0 && metrics.contentDownload > 0 && /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70045
70467
|
children: [
|
|
70046
70468
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
70047
|
-
width:
|
|
70469
|
+
width: 12,
|
|
70048
70470
|
children: /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text, {
|
|
70049
70471
|
color: theme.colors.accent,
|
|
70050
|
-
bold: true,
|
|
70051
70472
|
children: "\uD83D\uDE80 Speed"
|
|
70052
70473
|
}, undefined, false, undefined, this)
|
|
70053
70474
|
}, undefined, false, undefined, this),
|
|
@@ -70062,31 +70483,135 @@ var MetricsPanel = ({ metrics, theme }) => {
|
|
|
70062
70483
|
]
|
|
70063
70484
|
}, undefined, true, undefined, this)
|
|
70064
70485
|
]
|
|
70065
|
-
}, undefined, true, undefined, this)
|
|
70066
|
-
|
|
70067
|
-
|
|
70068
|
-
|
|
70486
|
+
}, undefined, true, undefined, this)
|
|
70487
|
+
]
|
|
70488
|
+
}, undefined, true, undefined, this);
|
|
70489
|
+
};
|
|
70490
|
+
|
|
70491
|
+
// src/ui/app/ui.tsx
|
|
70492
|
+
var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
|
|
70493
|
+
var formatBytes2 = (bytes) => {
|
|
70494
|
+
if (bytes === 0)
|
|
70495
|
+
return "0 B";
|
|
70496
|
+
const k = 1024;
|
|
70497
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
70498
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
70499
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
70500
|
+
};
|
|
70501
|
+
var LiveByteCounter = ({ progress, theme }) => {
|
|
70502
|
+
const [pulseFrame, setPulseFrame] = import_react35.useState(0);
|
|
70503
|
+
const pulseChars = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
|
|
70504
|
+
const arrowFrames = ["↓", "⬇", "↓", "⇣"];
|
|
70505
|
+
import_react35.useEffect(() => {
|
|
70506
|
+
const interval = setInterval(() => {
|
|
70507
|
+
setPulseFrame((prev) => (prev + 1) % pulseChars.length);
|
|
70508
|
+
}, 100);
|
|
70509
|
+
return () => clearInterval(interval);
|
|
70510
|
+
}, []);
|
|
70511
|
+
if (!progress)
|
|
70512
|
+
return null;
|
|
70513
|
+
const { bytesReceived, totalBytes, speed } = progress;
|
|
70514
|
+
const percentage = totalBytes > 0 ? Math.round(bytesReceived / totalBytes * 100) : 0;
|
|
70515
|
+
const progressBarWidth = 20;
|
|
70516
|
+
const filledWidth = totalBytes > 0 ? Math.round(bytesReceived / totalBytes * progressBarWidth) : 0;
|
|
70517
|
+
const filledBar = "█".repeat(filledWidth);
|
|
70518
|
+
const emptyBar = "░".repeat(progressBarWidth - filledWidth);
|
|
70519
|
+
return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70520
|
+
flexDirection: "column",
|
|
70521
|
+
paddingX: 1,
|
|
70522
|
+
paddingY: 1,
|
|
70523
|
+
borderStyle: "round",
|
|
70524
|
+
borderColor: theme.accent,
|
|
70525
|
+
children: [
|
|
70526
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70527
|
+
marginBottom: 1,
|
|
70069
70528
|
children: [
|
|
70070
|
-
/* @__PURE__ */
|
|
70071
|
-
color: theme.
|
|
70072
|
-
|
|
70529
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70530
|
+
color: theme.accent,
|
|
70531
|
+
bold: true,
|
|
70532
|
+
children: [
|
|
70533
|
+
pulseChars[pulseFrame],
|
|
70534
|
+
" "
|
|
70535
|
+
]
|
|
70536
|
+
}, undefined, true, undefined, this),
|
|
70537
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70538
|
+
color: theme.primary,
|
|
70539
|
+
bold: true,
|
|
70540
|
+
children: "DOWNLOADING "
|
|
70073
70541
|
}, undefined, false, undefined, this),
|
|
70074
|
-
/* @__PURE__ */
|
|
70075
|
-
|
|
70076
|
-
children:
|
|
70077
|
-
color: theme.colors.muted,
|
|
70078
|
-
dimColor: true,
|
|
70079
|
-
children: "TTFB = Time To First Byte (DNS + TCP + TLS + Server Processing)"
|
|
70080
|
-
}, undefined, false, undefined, this)
|
|
70542
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70543
|
+
color: theme.accent,
|
|
70544
|
+
children: arrowFrames[pulseFrame % arrowFrames.length]
|
|
70081
70545
|
}, undefined, false, undefined, this)
|
|
70082
70546
|
]
|
|
70547
|
+
}, undefined, true, undefined, this),
|
|
70548
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70549
|
+
children: [
|
|
70550
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70551
|
+
color: theme.success,
|
|
70552
|
+
children: filledBar
|
|
70553
|
+
}, undefined, false, undefined, this),
|
|
70554
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70555
|
+
color: theme.muted,
|
|
70556
|
+
dimColor: true,
|
|
70557
|
+
children: emptyBar
|
|
70558
|
+
}, undefined, false, undefined, this),
|
|
70559
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70560
|
+
color: theme.white,
|
|
70561
|
+
bold: true,
|
|
70562
|
+
children: [
|
|
70563
|
+
" ",
|
|
70564
|
+
percentage,
|
|
70565
|
+
"%"
|
|
70566
|
+
]
|
|
70567
|
+
}, undefined, true, undefined, this)
|
|
70568
|
+
]
|
|
70569
|
+
}, undefined, true, undefined, this),
|
|
70570
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70571
|
+
marginTop: 1,
|
|
70572
|
+
children: [
|
|
70573
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70574
|
+
marginRight: 2,
|
|
70575
|
+
children: [
|
|
70576
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70577
|
+
color: theme.accent,
|
|
70578
|
+
children: "\uD83D\uDCE6 "
|
|
70579
|
+
}, undefined, false, undefined, this),
|
|
70580
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70581
|
+
color: theme.white,
|
|
70582
|
+
bold: true,
|
|
70583
|
+
children: formatBytes2(bytesReceived)
|
|
70584
|
+
}, undefined, false, undefined, this),
|
|
70585
|
+
totalBytes > 0 && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70586
|
+
color: theme.muted,
|
|
70587
|
+
children: [
|
|
70588
|
+
" / ",
|
|
70589
|
+
formatBytes2(totalBytes)
|
|
70590
|
+
]
|
|
70591
|
+
}, undefined, true, undefined, this)
|
|
70592
|
+
]
|
|
70593
|
+
}, undefined, true, undefined, this),
|
|
70594
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70595
|
+
children: [
|
|
70596
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70597
|
+
color: theme.success,
|
|
70598
|
+
children: "\uD83D\uDE80 "
|
|
70599
|
+
}, undefined, false, undefined, this),
|
|
70600
|
+
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Text, {
|
|
70601
|
+
color: theme.success,
|
|
70602
|
+
bold: true,
|
|
70603
|
+
children: [
|
|
70604
|
+
formatBytes2(speed),
|
|
70605
|
+
"/s"
|
|
70606
|
+
]
|
|
70607
|
+
}, undefined, true, undefined, this)
|
|
70608
|
+
]
|
|
70609
|
+
}, undefined, true, undefined, this)
|
|
70610
|
+
]
|
|
70083
70611
|
}, undefined, true, undefined, this)
|
|
70084
70612
|
]
|
|
70085
70613
|
}, undefined, true, undefined, this);
|
|
70086
70614
|
};
|
|
70087
|
-
|
|
70088
|
-
// src/ui/app/ui.tsx
|
|
70089
|
-
var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
|
|
70090
70615
|
var SendButton = ({ onPress, loading, theme }) => {
|
|
70091
70616
|
const { isFocused } = use_focus_default();
|
|
70092
70617
|
use_input_default((_, key) => {
|
|
@@ -70108,7 +70633,7 @@ var SendButton = ({ onPress, loading, theme }) => {
|
|
|
70108
70633
|
}, undefined, false, undefined, this);
|
|
70109
70634
|
};
|
|
70110
70635
|
var HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"];
|
|
70111
|
-
var RequestPanel =
|
|
70636
|
+
var RequestPanel = import_react35.default.memo(({ request, onMethodChange, onUrlChange, onHeadersChange, onBodyChange, onSend, loading, theme, historyUrls = [], onInputFocus }) => /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70112
70637
|
flexDirection: "column",
|
|
70113
70638
|
gap: 1,
|
|
70114
70639
|
flexGrow: 1,
|
|
@@ -70159,29 +70684,31 @@ var RequestPanel = import_react34.default.memo(({ request, onMethodChange, onUrl
|
|
|
70159
70684
|
]
|
|
70160
70685
|
}, undefined, true, undefined, this));
|
|
70161
70686
|
var UI = () => {
|
|
70162
|
-
const [theme, setTheme] =
|
|
70687
|
+
const [theme, setTheme] = import_react35.useState(themes.catppuccin);
|
|
70163
70688
|
const { exit } = use_app_default();
|
|
70164
|
-
const [activeTab, setActiveTab] =
|
|
70165
|
-
const [request, setRequest] =
|
|
70166
|
-
const [response, setResponse] =
|
|
70167
|
-
const [metrics, setMetrics] =
|
|
70168
|
-
const [history, setHistory] =
|
|
70169
|
-
const [loading, setLoading] =
|
|
70170
|
-
const
|
|
70689
|
+
const [activeTab, setActiveTab] = import_react35.useState("request");
|
|
70690
|
+
const [request, setRequest] = import_react35.useState({ method: "GET", url: "", headers: "", body: "" });
|
|
70691
|
+
const [response, setResponse] = import_react35.useState({ statustext: "", status: "", headers: "", body: "", error: "" });
|
|
70692
|
+
const [metrics, setMetrics] = import_react35.useState(null);
|
|
70693
|
+
const [history, setHistory] = import_react35.useState([]);
|
|
70694
|
+
const [loading, setLoading] = import_react35.useState(false);
|
|
70695
|
+
const [downloadProgress, setDownloadProgress] = import_react35.useState(null);
|
|
70696
|
+
const requestRef = import_react35.useRef(request);
|
|
70171
70697
|
requestRef.current = request;
|
|
70172
|
-
|
|
70698
|
+
import_react35.useEffect(() => {
|
|
70173
70699
|
const loadHistory = async () => setHistory((await historyManager.loadHistory()).entries);
|
|
70174
70700
|
loadHistory();
|
|
70175
70701
|
}, []);
|
|
70176
|
-
|
|
70702
|
+
import_react35.useEffect(() => {
|
|
70177
70703
|
const loadTheme = async () => {
|
|
70178
70704
|
const loadedTheme = await themeManager.loadCurrTheme();
|
|
70179
70705
|
setTheme(loadedTheme);
|
|
70180
70706
|
};
|
|
70181
70707
|
loadTheme();
|
|
70182
70708
|
}, []);
|
|
70183
|
-
const handleSend =
|
|
70709
|
+
const handleSend = import_react35.useCallback(async () => {
|
|
70184
70710
|
setLoading(true);
|
|
70711
|
+
setDownloadProgress(null);
|
|
70185
70712
|
const startTime = Date.now();
|
|
70186
70713
|
const currentRequest = requestRef.current;
|
|
70187
70714
|
try {
|
|
@@ -70203,7 +70730,8 @@ var UI = () => {
|
|
|
70203
70730
|
method: currentRequest.method,
|
|
70204
70731
|
url: currentRequest.url,
|
|
70205
70732
|
headers: parsedHeaders,
|
|
70206
|
-
body: reqBody
|
|
70733
|
+
body: reqBody,
|
|
70734
|
+
onProgress: (progress) => setDownloadProgress(progress)
|
|
70207
70735
|
});
|
|
70208
70736
|
const responseTime = Date.now() - startTime;
|
|
70209
70737
|
await historyManager.addEntry({ ...currentRequest }, res.status, responseTime);
|
|
@@ -70216,13 +70744,14 @@ var UI = () => {
|
|
|
70216
70744
|
setActiveTab("response");
|
|
70217
70745
|
} finally {
|
|
70218
70746
|
setLoading(false);
|
|
70747
|
+
setDownloadProgress(null);
|
|
70219
70748
|
}
|
|
70220
70749
|
}, []);
|
|
70221
70750
|
const handleThemeChange = (theme2) => {
|
|
70222
70751
|
themeManager.ChangeTheme(theme2);
|
|
70223
70752
|
setTheme(theme2);
|
|
70224
70753
|
};
|
|
70225
|
-
const handleHistoryClick =
|
|
70754
|
+
const handleHistoryClick = import_react35.useCallback((item) => {
|
|
70226
70755
|
setRequest({
|
|
70227
70756
|
method: item.method,
|
|
70228
70757
|
url: item.url,
|
|
@@ -70233,9 +70762,10 @@ var UI = () => {
|
|
|
70233
70762
|
}, []);
|
|
70234
70763
|
const tabs = [{ name: "request", label: "Request" }, { name: "response", label: "Response" }];
|
|
70235
70764
|
const activeIndex = tabs.findIndex((t) => t.name === activeTab);
|
|
70236
|
-
const [showThemeSelector, setShowThemeSelector] =
|
|
70237
|
-
const [showExportDialog, setShowExportDialog] =
|
|
70238
|
-
const [inputFocused, setInputFocused] =
|
|
70765
|
+
const [showThemeSelector, setShowThemeSelector] = import_react35.useState(false);
|
|
70766
|
+
const [showExportDialog, setShowExportDialog] = import_react35.useState(false);
|
|
70767
|
+
const [inputFocused, setInputFocused] = import_react35.useState(false);
|
|
70768
|
+
const [historySearching, setHistorySearching] = import_react35.useState(false);
|
|
70239
70769
|
use_input_default((input, key) => {
|
|
70240
70770
|
if (input === "q" && !showExportDialog)
|
|
70241
70771
|
exit();
|
|
@@ -70249,15 +70779,17 @@ var UI = () => {
|
|
|
70249
70779
|
setShowThemeSelector(false);
|
|
70250
70780
|
if (key.escape && showExportDialog)
|
|
70251
70781
|
setShowExportDialog(false);
|
|
70252
|
-
if ((input === "t" || input === "T") && !key.ctrl && !key.meta && !inputFocused && !showExportDialog)
|
|
70782
|
+
if ((input === "t" || input === "T") && !key.ctrl && !key.meta && !inputFocused && !historySearching && !showExportDialog)
|
|
70253
70783
|
setShowThemeSelector((prev) => !prev);
|
|
70254
|
-
if ((input === "e" || input === "E") && !key.ctrl && !key.meta && !inputFocused && !showThemeSelector)
|
|
70784
|
+
if ((input === "e" || input === "E") && !key.ctrl && !key.meta && !inputFocused && !historySearching && !showThemeSelector)
|
|
70255
70785
|
setShowExportDialog((prev) => !prev);
|
|
70786
|
+
if ((input === "f" || input === "F") && !key.ctrl && !key.meta && !inputFocused && !historySearching && !showThemeSelector && !showExportDialog)
|
|
70787
|
+
setHistorySearching(true);
|
|
70256
70788
|
}, { isActive: !showExportDialog });
|
|
70257
|
-
const onMethodChange =
|
|
70258
|
-
const onUrlChange =
|
|
70259
|
-
const onHeadersChange =
|
|
70260
|
-
const onBodyChange =
|
|
70789
|
+
const onMethodChange = import_react35.useCallback((method) => setRequest((r) => ({ ...r, method })), []);
|
|
70790
|
+
const onUrlChange = import_react35.useCallback((url) => setRequest((r) => ({ ...r, url })), []);
|
|
70791
|
+
const onHeadersChange = import_react35.useCallback((headers) => setRequest((r) => ({ ...r, headers })), []);
|
|
70792
|
+
const onBodyChange = import_react35.useCallback((body) => setRequest((r) => ({ ...r, body })), []);
|
|
70261
70793
|
const historyUrls = Array.from(new Set(history.map((h) => h.url))).filter(Boolean);
|
|
70262
70794
|
return /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70263
70795
|
padding: 1,
|
|
@@ -70272,7 +70804,8 @@ var UI = () => {
|
|
|
70272
70804
|
theme,
|
|
70273
70805
|
onThemeChange: (themeName) => {
|
|
70274
70806
|
handleThemeChange(themes[themeName]);
|
|
70275
|
-
}
|
|
70807
|
+
},
|
|
70808
|
+
isActive: showThemeSelector
|
|
70276
70809
|
}, undefined, false, undefined, this)
|
|
70277
70810
|
}, undefined, false, undefined, this),
|
|
70278
70811
|
showExportDialog && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
@@ -70359,7 +70892,9 @@ var UI = () => {
|
|
|
70359
70892
|
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(HistoryList, {
|
|
70360
70893
|
history,
|
|
70361
70894
|
onItemClick: handleHistoryClick,
|
|
70362
|
-
theme
|
|
70895
|
+
theme,
|
|
70896
|
+
onSearchingChange: setHistorySearching,
|
|
70897
|
+
startSearching: historySearching
|
|
70363
70898
|
}, undefined, false, undefined, this)
|
|
70364
70899
|
}, undefined, false, undefined, this),
|
|
70365
70900
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
@@ -70415,6 +70950,14 @@ var UI = () => {
|
|
|
70415
70950
|
onChange: setActiveTab,
|
|
70416
70951
|
theme
|
|
70417
70952
|
}, undefined, false, undefined, this),
|
|
70953
|
+
downloadProgress && /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70954
|
+
marginTop: 1,
|
|
70955
|
+
justifyContent: "center",
|
|
70956
|
+
children: /* @__PURE__ */ jsx_dev_runtime13.jsxDEV(LiveByteCounter, {
|
|
70957
|
+
progress: downloadProgress,
|
|
70958
|
+
theme: theme.colors
|
|
70959
|
+
}, undefined, false, undefined, this)
|
|
70960
|
+
}, undefined, false, undefined, this),
|
|
70418
70961
|
/* @__PURE__ */ jsx_dev_runtime13.jsxDEV(Box_default, {
|
|
70419
70962
|
marginTop: 1,
|
|
70420
70963
|
flexDirection: "column",
|
|
@@ -70477,12 +71020,6 @@ function App2() {
|
|
|
70477
71020
|
var import_chalk6 = __toESM(require_source(), 1);
|
|
70478
71021
|
var jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
|
|
70479
71022
|
var UIWrapper = () => {
|
|
70480
|
-
const { exit } = use_app_default();
|
|
70481
|
-
use_input_default((input) => {
|
|
70482
|
-
if (input === "q") {
|
|
70483
|
-
exit();
|
|
70484
|
-
}
|
|
70485
|
-
});
|
|
70486
71023
|
return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
|
|
70487
71024
|
flexDirection: "column",
|
|
70488
71025
|
children: [
|
|
@@ -70663,7 +71200,7 @@ async function mockApis() {
|
|
|
70663
71200
|
|
|
70664
71201
|
// src/index.ts
|
|
70665
71202
|
var program2 = new Command;
|
|
70666
|
-
program2.version("1.
|
|
71203
|
+
program2.version("1.4.1").description(import_chalk9.default.yellow("PostBoy CLI - Test your APIs with ease"));
|
|
70667
71204
|
program2.command("run").description("Run a test API request").action(testCommand);
|
|
70668
71205
|
program2.command("mock-list").description("List the mock API servers").action(mockApis);
|
|
70669
71206
|
program2.command("ui").description("UI for PostBoy").action(uiCommand);
|