dsh-provider-proxy 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/lib/client.js +439 -100
- package/lib/client.js.map +2 -2
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -39,13 +39,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
39
39
|
var require_client = __commonJS({
|
|
40
40
|
"src/client.css"(exports, module2) {
|
|
41
41
|
"use strict";
|
|
42
|
-
var __dshMap = { "root": "
|
|
42
|
+
var __dshMap = { "root": "1c0df77c_root", "lead": "5d248416_lead", "empty": "1710aef8_empty", "card": "b4a56347_card", "cardActive": "5d17f1d6_cardActive", "cardRejected": "0b12be1b_cardRejected", "defaultCard": "4dc8a19a_defaultCard", "defaultLead": "593693ac_defaultLead", "cardHead": "0c3d7976_cardHead", "cardTitles": "ba5490f7_cardTitles", "name": "fc223200_name", "id": "b54fcb50_id", "pillOn": "2d0e393c_pillOn", "pillLive": "ed98388d_pillLive", "pillOff": "07959fb6_pillOff", "pillRejected": "23916369_pillRejected", "toggle": "44052e5b_toggle", "field": "7826b254_field", "label": "fd3de42a_label", "hint": "9c1dd04c_hint", "input": "0cb12e78_input", "passwordToggle": "e7ed8e99_passwordToggle", "testButton": "3ea31502_testButton", "diag": "8093bbdb_diag", "diagSummary": "bb056060_diagSummary", "diagList": "643d5158_diagList", "chipRow": "cf7604fc_chipRow", "chip": "69584a20_chip", "chipActive": "9e9e3b3e_chipActive", "formGrid": "07283bc3_formGrid", "formGridFull": "31635992_formGridFull", "compactRow": "10f37453_compactRow", "compactRowActive": "b8d0ab91_compactRowActive", "compactRowRejected": "518f0c81_compactRowRejected", "copyButton": "4b86d627_copyButton" };
|
|
43
43
|
var __dshStyles = globalThis.__dshPluginStyles || (globalThis.__dshPluginStyles = /* @__PURE__ */ new Set());
|
|
44
44
|
if (!__dshStyles.has("dsh-provider-proxy/client.css")) {
|
|
45
45
|
__dshStyles.add("dsh-provider-proxy/client.css");
|
|
46
46
|
__dshStyle = document.createElement("style");
|
|
47
47
|
__dshStyle.setAttribute("data-plugin-css", "dsh-provider-proxy/client.css");
|
|
48
|
-
__dshStyle.textContent = '/* dsh-provider-proxy \u2014 provider proxy settings page.\n Tokens only: no literal colours, matching the shared --dsw-* system. */\n\n.
|
|
48
|
+
__dshStyle.textContent = '/* dsh-provider-proxy \u2014 provider proxy settings page.\r\n Tokens only: no literal colours, matching the shared --dsw-* system. */\r\n\r\n.1c0df77c_root {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n max-width: 640px;\r\n}\r\n\r\n.5d248416_lead {\r\n margin: 0 0 4px;\r\n font-size: 12px;\r\n line-height: 1.6;\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n.1710aef8_empty {\r\n margin: 0;\r\n padding: 16px;\r\n border: 1px dashed var(--dsw-alias-border-l1);\r\n border-radius: 8px;\r\n font-size: 12px;\r\n text-align: center;\r\n color: var(--dsw-alias-state-idle-primary);\r\n}\r\n\r\n/* ---- provider card ---- */\r\n\r\n.b4a56347_card,\r\n.5d17f1d6_cardActive,\r\n.0b12be1b_cardRejected {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n padding: 12px 14px;\r\n border: 1px solid var(--dsw-alias-border-l1);\r\n border-radius: 10px;\r\n background: var(--dsw-alias-bg-layer-1);\r\n}\r\n\r\n.5d17f1d6_cardActive {\r\n border-color: var(--dsw-alias-state-success-primary);\r\n background: var(--dsw-alias-bg-layer-2);\r\n}\r\n\r\n/* An enabled route the Host refused: never dress it as active. */\r\n.0b12be1b_cardRejected {\r\n border-color: var(--dsw-alias-state-error-primary, #f85149);\r\n background: var(--dsw-alias-bg-layer-2);\r\n}\r\n\r\n/* ---- shared default endpoint ---- */\r\n\r\n/* A distinct outer layer, so it reads as "one setting for the page" rather than\r\n as one more provider card. */\r\n.4dc8a19a_defaultCard {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 10px;\r\n padding: 14px 16px;\r\n border: 1px solid var(--dsw-alias-border-l2);\r\n border-radius: 10px;\r\n background: var(--dsw-alias-bg-layer-2);\r\n}\r\n\r\n.593693ac_defaultLead {\r\n margin: -2px 0 0;\r\n font-size: 11px;\r\n line-height: 1.5;\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n.0c3d7976_cardHead {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n}\r\n\r\n.ba5490f7_cardTitles {\r\n display: flex;\r\n align-items: baseline;\r\n gap: 8px;\r\n min-width: 0;\r\n}\r\n\r\n.fc223200_name {\r\n overflow: hidden;\r\n font-size: 13px;\r\n font-weight: 600;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n color: var(--dsw-alias-label-primary);\r\n}\r\n\r\n.b54fcb50_id {\r\n flex: none;\r\n padding: 1px 6px;\r\n border-radius: 4px;\r\n background: var(--dsw-alias-bg-layer-2);\r\n font-family: ui-monospace, monospace;\r\n font-size: 11px;\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n/* ---- status pill ---- */\r\n\r\n.2d0e393c_pillOn,\r\n.ed98388d_pillLive,\r\n.07959fb6_pillOff,\r\n.23916369_pillRejected {\r\n flex: none;\r\n padding: 2px 8px;\r\n border-radius: 999px;\r\n font-size: 11px;\r\n font-weight: 500;\r\n white-space: nowrap;\r\n}\r\n\r\n.2d0e393c_pillOn {\r\n background: var(--dsw-alias-state-success-primary);\r\n color: var(--dsw-alias-bg-base);\r\n}\r\n\r\n.ed98388d_pillLive {\r\n border: 1px solid var(--dsw-alias-border-l2);\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n.07959fb6_pillOff {\r\n color: var(--dsw-alias-state-idle-primary);\r\n}\r\n\r\n.23916369_pillRejected {\r\n border: 1px solid var(--dsw-alias-state-error-primary, #f85149);\r\n color: var(--dsw-alias-state-error-primary, #f85149);\r\n}\r\n\r\n/* ---- toggle ---- */\r\n\r\n.44052e5b_toggle {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding-top: 2px;\r\n font-size: 12px;\r\n color: var(--dsw-alias-label-primary);\r\n cursor: pointer;\r\n}\r\n\r\n.44052e5b_toggle input {\r\n accent-color: var(--dsw-alias-brand-primary);\r\n cursor: pointer;\r\n}\r\n\r\n/* ---- fields ---- */\r\n\r\n.7826b254_field {\r\n display: grid;\r\n grid-template-columns: 76px 1fr;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 12px;\r\n min-width: 0;\r\n}\r\n\r\n.fd3de42a_label {\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n.9c1dd04c_hint {\r\n grid-column: 1 / -1;\r\n margin-top: 2px;\r\n font-size: 11px;\r\n color: var(--dsw-alias-state-warn-primary, #d29922);\r\n}\r\n\r\n.0cb12e78_input {\r\n box-sizing: border-box;\r\n width: 100%;\r\n min-width: 0;\r\n padding: 5px 8px;\r\n border: 1px solid var(--dsw-alias-border-l1);\r\n border-radius: 6px;\r\n outline: none;\r\n background: var(--dsw-alias-bg-layer-1);\r\n color: var(--dsw-alias-label-primary);\r\n font: inherit;\r\n font-size: 12px;\r\n transition: border-color 120ms ease, background 120ms ease;\r\n}\r\n\r\n/* The base look of every input is INLINE too, so these three state rules only\r\n ever take effect as author-important declarations \u2014 same reason as the\r\n self-check button above. `cursor` has no inline base and needs none, and the\r\n hover border uses `l3` because `l1`\u2192`l2` is a 4%\u219210% black step nobody can\r\n see. */\r\n\r\n.0cb12e78_input:hover:not(:disabled) {\r\n border-color: var(--dsw-alias-border-l3) !important;\r\n}\r\n\r\n.0cb12e78_input:focus {\r\n border-color: var(--dsw-alias-brand-primary) !important;\r\n}\r\n\r\n.0cb12e78_input:disabled {\r\n color: var(--dsw-alias-state-idle-primary) !important;\r\n background: var(--dsw-alias-bg-layer-2) !important;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* The icon sits inside the input, so its hover/focus feedback must be local\r\n and must outrank the transparent inline base. */\r\n.e7ed8e99_passwordToggle {\r\n transition: background 120ms ease, color 120ms ease;\r\n}\r\n\r\n.e7ed8e99_passwordToggle:hover:not(:disabled) {\r\n background: var(--dsw-alias-interactive-bg-hover) !important;\r\n color: var(--dsw-alias-label-primary) !important;\r\n}\r\n\r\n.e7ed8e99_passwordToggle:focus-visible {\r\n outline: 2px solid var(--dsw-alias-brand-primary);\r\n outline-offset: 1px;\r\n}\r\n\r\n/* ---- self-check ---- */\r\n\r\n/* The hover state is the one thing an inline style cannot express, which is why\r\n this element carries a class at all. Layout stays inline.\r\n\r\n Two traps, both hit before this comment existed:\r\n - `!important` is load-bearing: the base border and background are INLINE, and\r\n the cascade sorts a style attribute after every author rule, so a plain\r\n declaration here would ship, match, and still lose.\r\n - the TOKENS must be visible ones. `bg-layer-1/2/3` all resolve to\r\n `neutral-bluish-00` in the light theme, so a layer swap is a no-op there, and\r\n `border-l1`\u2192`l2` is 4%\u219210% black on a 1px line. The app\'s own hovers use\r\n `interactive-bg-hover`; using it here is what makes the feedback exist. */\r\n.3ea31502_testButton {\r\n transition: border-color 120ms ease, background 120ms ease;\r\n}\r\n\r\n.3ea31502_testButton:hover:not(:disabled) {\r\n border-color: var(--dsw-alias-border-l3) !important;\r\n background: var(--dsw-alias-interactive-bg-hover) !important;\r\n}\r\n\r\n/* ---- diagnostics ---- */\r\n\r\n.8093bbdb_diag {\r\n margin-top: 2px;\r\n padding: 8px 10px;\r\n border: 1px solid var(--dsw-alias-border-l1);\r\n border-radius: 8px;\r\n font-size: 11px;\r\n color: var(--dsw-alias-label-secondary);\r\n}\r\n\r\n.bb056060_diagSummary {\r\n cursor: pointer;\r\n color: var(--dsw-alias-state-warn-primary);\r\n}\r\n\r\n.643d5158_diagList {\r\n margin: 6px 0 0;\r\n padding-left: 18px;\r\n font-family: ui-monospace, monospace;\r\n word-break: break-all;\r\n}\r\n\r\n/* ---- v0.8.0 N9 additions: status filter chips ---- */\r\n\r\n.cf7604fc_chipRow {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.69584a20_chip {\r\n transition: border-color 120ms ease, background 120ms ease, color 120ms ease;\r\n}\r\n\r\n.69584a20_chip:hover:not(:disabled) {\r\n border-color: var(--dsw-alias-border-l3) !important;\r\n background: var(--dsw-alias-interactive-bg-hover) !important;\r\n color: var(--dsw-alias-label-primary) !important;\r\n}\r\n\r\n.9e9e3b3e_chipActive {\r\n border-color: var(--dsw-alias-brand-primary) !important;\r\n background: var(--dsw-alias-interactive-bg-hover) !important;\r\n color: var(--dsw-alias-brand-primary) !important;\r\n}\r\n\r\n/* ---- v0.8.0 N11 additions: form grid ---- */\r\n\r\n.07283bc3_formGrid {\r\n display: grid;\r\n grid-template-columns: repeat(2, minmax(0, 1fr));\r\n align-items: start;\r\n gap: 10px 14px;\r\n}\r\n\r\n.31635992_formGridFull {\r\n grid-column: 1 / -1;\r\n}\r\n\r\n@media (max-width: 520px) {\r\n .07283bc3_formGrid {\r\n grid-template-columns: 1fr !important;\r\n }\r\n .31635992_formGridFull {\r\n grid-column: auto !important;\r\n }\r\n}\r\n\r\n/* ---- v0.8.0 N10 additions: compact view ---- */\r\n\r\n.10f37453_compactRow,\r\n.b8d0ab91_compactRowActive,\r\n.518f0c81_compactRowRejected {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 10px;\r\n padding: 10px 14px;\r\n border: 1px solid var(--dsw-alias-border-l1);\r\n border-radius: 8px;\r\n background: var(--dsw-alias-bg-layer-1);\r\n margin-bottom: 8px;\r\n}\r\n\r\n.b8d0ab91_compactRowActive {\r\n border-color: var(--dsw-alias-state-success-primary);\r\n background: var(--dsw-alias-bg-layer-2);\r\n}\r\n\r\n.518f0c81_compactRowRejected {\r\n border-color: var(--dsw-alias-state-error-primary, #f85149);\r\n background: var(--dsw-alias-bg-layer-2);\r\n}\r\n\r\n/* ---- v0.8.0 N13 additions: quick copy ---- */\r\n.4b86d627_copyButton {\r\n transition: background 120ms ease, color 120ms ease;\r\n}\r\n\r\n.4b86d627_copyButton:hover:not(:disabled) {\r\n background: var(--dsw-alias-interactive-bg-hover) !important;\r\n color: var(--dsw-alias-label-primary) !important;\r\n}\r\n';
|
|
49
49
|
document.head.appendChild(__dshStyle);
|
|
50
50
|
}
|
|
51
51
|
var __dshStyle;
|
|
@@ -666,10 +666,11 @@ var S = {
|
|
|
666
666
|
},
|
|
667
667
|
field: {
|
|
668
668
|
display: "grid",
|
|
669
|
-
gridTemplateColumns: "
|
|
669
|
+
gridTemplateColumns: "76px 1fr",
|
|
670
670
|
alignItems: "center",
|
|
671
|
-
gap: "
|
|
672
|
-
fontSize: "12px"
|
|
671
|
+
gap: "8px",
|
|
672
|
+
fontSize: "12px",
|
|
673
|
+
minWidth: "0"
|
|
673
674
|
},
|
|
674
675
|
label: { color: "var(--dsw-alias-label-secondary)" },
|
|
675
676
|
input: {
|
|
@@ -694,9 +695,83 @@ var S = {
|
|
|
694
695
|
color: "var(--dsw-alias-label-secondary)"
|
|
695
696
|
},
|
|
696
697
|
hint: {
|
|
697
|
-
gridColumn: "
|
|
698
|
+
gridColumn: "1 / -1",
|
|
698
699
|
fontSize: "11px",
|
|
699
|
-
color: "var(--dsw-alias-
|
|
700
|
+
color: "var(--dsw-alias-state-warn-primary, #d29922)"
|
|
701
|
+
},
|
|
702
|
+
chipRow: {
|
|
703
|
+
display: "flex",
|
|
704
|
+
alignItems: "center",
|
|
705
|
+
gap: "6px",
|
|
706
|
+
flexWrap: "wrap",
|
|
707
|
+
marginBottom: "2px"
|
|
708
|
+
},
|
|
709
|
+
chip: {
|
|
710
|
+
display: "inline-flex",
|
|
711
|
+
alignItems: "center",
|
|
712
|
+
padding: "3px 10px",
|
|
713
|
+
borderRadius: "999px",
|
|
714
|
+
border: "1px solid var(--dsw-alias-border-l1)",
|
|
715
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
716
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
717
|
+
fontSize: "11px",
|
|
718
|
+
fontWeight: "500",
|
|
719
|
+
cursor: "pointer",
|
|
720
|
+
userSelect: "none"
|
|
721
|
+
},
|
|
722
|
+
chipActive: {
|
|
723
|
+
borderColor: "var(--dsw-alias-brand-primary)",
|
|
724
|
+
background: "var(--dsw-alias-interactive-bg-hover)",
|
|
725
|
+
color: "var(--dsw-alias-brand-primary)",
|
|
726
|
+
fontWeight: "600"
|
|
727
|
+
},
|
|
728
|
+
compactRow: {
|
|
729
|
+
display: "flex",
|
|
730
|
+
alignItems: "center",
|
|
731
|
+
justifyContent: "space-between",
|
|
732
|
+
gap: "10px",
|
|
733
|
+
padding: "10px 14px",
|
|
734
|
+
border: "1px solid var(--dsw-alias-border-l1)",
|
|
735
|
+
borderRadius: "8px",
|
|
736
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
737
|
+
marginBottom: "8px"
|
|
738
|
+
},
|
|
739
|
+
compactRowActive: {
|
|
740
|
+
borderColor: "var(--dsw-alias-state-success-primary)",
|
|
741
|
+
background: "var(--dsw-alias-bg-layer-2)"
|
|
742
|
+
},
|
|
743
|
+
compactRowRejected: {
|
|
744
|
+
borderColor: "var(--dsw-alias-state-error-primary, #f85149)",
|
|
745
|
+
background: "var(--dsw-alias-bg-layer-2)"
|
|
746
|
+
},
|
|
747
|
+
compactEndpoint: {
|
|
748
|
+
fontSize: "11px",
|
|
749
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
750
|
+
overflow: "hidden",
|
|
751
|
+
textOverflow: "ellipsis",
|
|
752
|
+
whiteSpace: "nowrap",
|
|
753
|
+
maxWidth: "180px"
|
|
754
|
+
},
|
|
755
|
+
formGrid: {
|
|
756
|
+
display: "grid",
|
|
757
|
+
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
|
|
758
|
+
alignItems: "start",
|
|
759
|
+
gap: "10px 14px"
|
|
760
|
+
},
|
|
761
|
+
formGridFull: {
|
|
762
|
+
gridColumn: "1 / -1"
|
|
763
|
+
},
|
|
764
|
+
copyButton: {
|
|
765
|
+
display: "inline-flex",
|
|
766
|
+
alignItems: "center",
|
|
767
|
+
padding: "2px 4px",
|
|
768
|
+
border: "none",
|
|
769
|
+
borderRadius: "4px",
|
|
770
|
+
background: "transparent",
|
|
771
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
772
|
+
cursor: "pointer",
|
|
773
|
+
fontSize: "11px",
|
|
774
|
+
lineHeight: "1"
|
|
700
775
|
}
|
|
701
776
|
};
|
|
702
777
|
function renderPage(ctx) {
|
|
@@ -845,11 +920,77 @@ function renderPage(ctx) {
|
|
|
845
920
|
};
|
|
846
921
|
const [filter, setFilter] = (React.useState ?? ((v) => [v, () => {
|
|
847
922
|
}]))("");
|
|
923
|
+
const [statusFilter, setStatusFilter] = (React.useState ?? ((v) => [v, () => {
|
|
924
|
+
}]))("all");
|
|
925
|
+
const [viewMode, setViewMode] = (React.useState ?? ((v) => [v, () => {
|
|
926
|
+
}]))("card");
|
|
927
|
+
const [expandedCards, setExpandedCards] = (React.useState ?? ((v) => [v, () => {
|
|
928
|
+
}]))({});
|
|
929
|
+
const [batchProgress, setBatchProgress] = (React.useState ?? ((v) => [v, () => {
|
|
930
|
+
}]))(null);
|
|
931
|
+
const [copiedKey, setCopiedKey] = (React.useState ?? ((v) => [v, () => {
|
|
932
|
+
}]))(void 0);
|
|
933
|
+
const copyToClipboard = (key, text) => {
|
|
934
|
+
try {
|
|
935
|
+
if (typeof globalThis.navigator?.clipboard?.writeText === "function") {
|
|
936
|
+
void globalThis.navigator.clipboard.writeText(text).then(() => {
|
|
937
|
+
setCopiedKey(key);
|
|
938
|
+
setTimeout(() => setCopiedKey((prev) => prev === key ? void 0 : prev), 1500);
|
|
939
|
+
}).catch(() => void 0);
|
|
940
|
+
}
|
|
941
|
+
} catch {
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
const copyButton = (key, text, ariaLabel) => h(
|
|
945
|
+
"button",
|
|
946
|
+
{
|
|
947
|
+
className: import_client.default.copyButton,
|
|
948
|
+
style: S.copyButton,
|
|
949
|
+
type: "button",
|
|
950
|
+
"aria-label": ariaLabel,
|
|
951
|
+
title: copiedKey === key ? t.copied : ariaLabel,
|
|
952
|
+
onClick: (e) => {
|
|
953
|
+
e.stopPropagation?.();
|
|
954
|
+
copyToClipboard(key, text);
|
|
955
|
+
}
|
|
956
|
+
},
|
|
957
|
+
copiedKey === key ? h(
|
|
958
|
+
"svg",
|
|
959
|
+
{
|
|
960
|
+
width: 12,
|
|
961
|
+
height: 12,
|
|
962
|
+
viewBox: "0 0 24 24",
|
|
963
|
+
fill: "none",
|
|
964
|
+
stroke: "var(--dsw-alias-state-success-primary, #2ea043)",
|
|
965
|
+
strokeWidth: 2,
|
|
966
|
+
strokeLinecap: "round",
|
|
967
|
+
strokeLinejoin: "round",
|
|
968
|
+
"aria-hidden": "true"
|
|
969
|
+
},
|
|
970
|
+
h("path", { d: "M20 6 9 17l-5-5" })
|
|
971
|
+
) : h(
|
|
972
|
+
"svg",
|
|
973
|
+
{
|
|
974
|
+
width: 12,
|
|
975
|
+
height: 12,
|
|
976
|
+
viewBox: "0 0 24 24",
|
|
977
|
+
fill: "none",
|
|
978
|
+
stroke: "currentColor",
|
|
979
|
+
strokeWidth: 2,
|
|
980
|
+
strokeLinecap: "round",
|
|
981
|
+
strokeLinejoin: "round",
|
|
982
|
+
"aria-hidden": "true"
|
|
983
|
+
},
|
|
984
|
+
h("rect", { width: 14, height: 14, x: 8, y: 8, rx: 2, ry: 2 }),
|
|
985
|
+
h("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
|
|
986
|
+
),
|
|
987
|
+
copiedKey === key ? h("span", { style: { marginLeft: "3px", fontSize: "10px", color: "var(--dsw-alias-state-success-primary, #2ea043)" } }, t.copied) : null
|
|
988
|
+
);
|
|
848
989
|
const runTest = (id) => {
|
|
849
990
|
const generation = (testGeneration.get(id) ?? 0) + 1;
|
|
850
991
|
testGeneration.set(id, generation);
|
|
851
992
|
setTests((current) => ({ ...current, [id]: { pending: true } }));
|
|
852
|
-
|
|
993
|
+
return (async () => {
|
|
853
994
|
try {
|
|
854
995
|
for (const [key, entry] of [...pendingWrites]) {
|
|
855
996
|
if (key.startsWith(`${id}\0`) || key.startsWith("\0default\0") || key.startsWith("\0global\0")) {
|
|
@@ -875,6 +1016,28 @@ function renderPage(ctx) {
|
|
|
875
1016
|
}
|
|
876
1017
|
})();
|
|
877
1018
|
};
|
|
1019
|
+
const runBatchTest = () => {
|
|
1020
|
+
const activeIds = rows.filter((row) => view({ ...configured[row.id], ...draft[row.id] }).enabled).map((row) => row.id);
|
|
1021
|
+
if (activeIds.length === 0 || batchProgress !== null) return;
|
|
1022
|
+
setBatchProgress({ done: 0, total: activeIds.length });
|
|
1023
|
+
void (async () => {
|
|
1024
|
+
let index = 0;
|
|
1025
|
+
let completed = 0;
|
|
1026
|
+
const concurrency = Math.min(3, activeIds.length);
|
|
1027
|
+
const worker = async () => {
|
|
1028
|
+
while (index < activeIds.length) {
|
|
1029
|
+
const id = activeIds[index++];
|
|
1030
|
+
await runTest(id);
|
|
1031
|
+
completed++;
|
|
1032
|
+
setBatchProgress({ done: completed, total: activeIds.length });
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
await Promise.all(Array.from({ length: concurrency }, () => worker()));
|
|
1036
|
+
setTimeout(() => {
|
|
1037
|
+
setBatchProgress(null);
|
|
1038
|
+
}, 2e3);
|
|
1039
|
+
})();
|
|
1040
|
+
};
|
|
878
1041
|
const rows = knownProviders({ ...configured, ...draft }, published);
|
|
879
1042
|
const inheritingIds = () => rows.filter((row) => view({ ...configured[row.id], ...draft[row.id] }).useDefault === true).map((row) => row.id);
|
|
880
1043
|
const save = (key, path, label, value, onRefused) => {
|
|
@@ -1048,9 +1211,16 @@ function renderPage(ctx) {
|
|
|
1048
1211
|
event.preventDefault?.();
|
|
1049
1212
|
apply2(parts);
|
|
1050
1213
|
};
|
|
1051
|
-
const field = (label, control, hint, hintError) => h(
|
|
1214
|
+
const field = (label, control, hint, hintError, fullWidth) => h(
|
|
1052
1215
|
"label",
|
|
1053
|
-
{
|
|
1216
|
+
{
|
|
1217
|
+
className: `${import_client.default.field}${fullWidth ? ` ${import_client.default.formGridFull}` : ""}`,
|
|
1218
|
+
style: {
|
|
1219
|
+
...S.field,
|
|
1220
|
+
...fullWidth ? S.formGridFull : {}
|
|
1221
|
+
},
|
|
1222
|
+
key: label
|
|
1223
|
+
},
|
|
1054
1224
|
h("span", { className: import_client.default.label, style: S.label }, label),
|
|
1055
1225
|
control,
|
|
1056
1226
|
hint === void 0 ? null : h(
|
|
@@ -1058,8 +1228,8 @@ function renderPage(ctx) {
|
|
|
1058
1228
|
{
|
|
1059
1229
|
className: import_client.default.hint,
|
|
1060
1230
|
style: {
|
|
1061
|
-
|
|
1062
|
-
|
|
1231
|
+
...S.hint,
|
|
1232
|
+
marginTop: "2px",
|
|
1063
1233
|
// A warning that a value can never work is an answer, not
|
|
1064
1234
|
// decoration — same rule as the failed self-check text.
|
|
1065
1235
|
...hintError === true ? { color: "var(--dsw-alias-state-error-primary, #f85149)" } : {}
|
|
@@ -1095,77 +1265,83 @@ function renderPage(ctx) {
|
|
|
1095
1265
|
)
|
|
1096
1266
|
),
|
|
1097
1267
|
h("p", { className: import_client.default.defaultLead, style: S.defaultLead }, t.defaultLead),
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1268
|
+
h(
|
|
1269
|
+
"div",
|
|
1270
|
+
{ className: import_client.default.formGrid, style: S.formGrid, key: "default:form-grid" },
|
|
1271
|
+
field(
|
|
1272
|
+
t.protocol,
|
|
1273
|
+
h(
|
|
1274
|
+
"select",
|
|
1275
|
+
{
|
|
1276
|
+
className: import_client.default.input,
|
|
1277
|
+
style: S.input,
|
|
1278
|
+
value: defaultView.protocol,
|
|
1279
|
+
onChange: (event) => bindDefault("protocol")(event.target.value)
|
|
1280
|
+
},
|
|
1281
|
+
...PROTOCOLS.map(
|
|
1282
|
+
(protocol) => h("option", { key: protocol, value: protocol }, protocol.toUpperCase())
|
|
1283
|
+
)
|
|
1284
|
+
)
|
|
1285
|
+
),
|
|
1286
|
+
field(
|
|
1287
|
+
t.host,
|
|
1288
|
+
h("input", {
|
|
1103
1289
|
className: import_client.default.input,
|
|
1104
1290
|
style: S.input,
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
)
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
type: "number",
|
|
1133
|
-
min: 1,
|
|
1134
|
-
max: 65535,
|
|
1135
|
-
placeholder: "7890",
|
|
1136
|
-
value: defaultView.port === 0 ? "" : String(defaultView.port),
|
|
1137
|
-
onChange: (event) => {
|
|
1138
|
-
const parsed = Number.parseInt(event.target.value, 10);
|
|
1139
|
-
bindDefault("port")(Number.isNaN(parsed) ? 0 : parsed);
|
|
1140
|
-
}
|
|
1141
|
-
})
|
|
1142
|
-
),
|
|
1143
|
-
field(
|
|
1144
|
-
t.username,
|
|
1145
|
-
h("input", {
|
|
1146
|
-
className: import_client.default.input,
|
|
1147
|
-
style: S.input,
|
|
1148
|
-
autoComplete: "off",
|
|
1149
|
-
value: defaultView.username,
|
|
1150
|
-
onChange: (event) => bindDefault("username")(event.target.value)
|
|
1151
|
-
})
|
|
1152
|
-
),
|
|
1153
|
-
field(
|
|
1154
|
-
t.password,
|
|
1155
|
-
h(
|
|
1156
|
-
"div",
|
|
1157
|
-
{ style: S.passwordControl },
|
|
1291
|
+
placeholder: "127.0.0.1",
|
|
1292
|
+
value: defaultView.host,
|
|
1293
|
+
onChange: (event) => bindDefault("host")(event.target.value),
|
|
1294
|
+
// Same convenience as the cards: a full URL fills the whole block.
|
|
1295
|
+
onPaste: onProxyUrlPaste(applyDefaultUrl)
|
|
1296
|
+
}),
|
|
1297
|
+
defaultHostWhy ?? t.hostHint,
|
|
1298
|
+
defaultHostWhy !== void 0
|
|
1299
|
+
),
|
|
1300
|
+
field(
|
|
1301
|
+
t.port,
|
|
1302
|
+
h("input", {
|
|
1303
|
+
className: import_client.default.input,
|
|
1304
|
+
style: S.input,
|
|
1305
|
+
type: "number",
|
|
1306
|
+
min: 1,
|
|
1307
|
+
max: 65535,
|
|
1308
|
+
placeholder: "7890",
|
|
1309
|
+
value: defaultView.port === 0 ? "" : String(defaultView.port),
|
|
1310
|
+
onChange: (event) => {
|
|
1311
|
+
const parsed = Number.parseInt(event.target.value, 10);
|
|
1312
|
+
bindDefault("port")(Number.isNaN(parsed) ? 0 : parsed);
|
|
1313
|
+
}
|
|
1314
|
+
})
|
|
1315
|
+
),
|
|
1316
|
+
field(
|
|
1317
|
+
t.username,
|
|
1158
1318
|
h("input", {
|
|
1159
1319
|
className: import_client.default.input,
|
|
1160
|
-
style:
|
|
1161
|
-
type: defaultPasswordVisible === true ? "text" : "password",
|
|
1320
|
+
style: S.input,
|
|
1162
1321
|
autoComplete: "off",
|
|
1163
|
-
value: defaultView.
|
|
1164
|
-
onChange: (event) => bindDefault("
|
|
1165
|
-
})
|
|
1166
|
-
passwordToggle(defaultPasswordVisible === true, toggleDefaultPassword)
|
|
1322
|
+
value: defaultView.username,
|
|
1323
|
+
onChange: (event) => bindDefault("username")(event.target.value)
|
|
1324
|
+
})
|
|
1167
1325
|
),
|
|
1168
|
-
|
|
1326
|
+
field(
|
|
1327
|
+
t.password,
|
|
1328
|
+
h(
|
|
1329
|
+
"div",
|
|
1330
|
+
{ style: S.passwordControl },
|
|
1331
|
+
h("input", {
|
|
1332
|
+
className: import_client.default.input,
|
|
1333
|
+
style: { ...S.input, paddingRight: "36px" },
|
|
1334
|
+
type: defaultPasswordVisible === true ? "text" : "password",
|
|
1335
|
+
autoComplete: "off",
|
|
1336
|
+
value: defaultView.password,
|
|
1337
|
+
onChange: (event) => bindDefault("password")(event.target.value)
|
|
1338
|
+
}),
|
|
1339
|
+
passwordToggle(defaultPasswordVisible === true, toggleDefaultPassword)
|
|
1340
|
+
),
|
|
1341
|
+
t.passwordHintProxy,
|
|
1342
|
+
false,
|
|
1343
|
+
true
|
|
1344
|
+
)
|
|
1169
1345
|
),
|
|
1170
1346
|
// Bulk opt-in, in ONE write: a per-card walk would rebuild the table N times.
|
|
1171
1347
|
// Disabled while the default configuration is incomplete, because pointing every card at an
|
|
@@ -1213,7 +1389,7 @@ function renderPage(ctx) {
|
|
|
1213
1389
|
value: globalTestUrl,
|
|
1214
1390
|
onChange: (event) => bindGlobal("testUrl")(event.target.value)
|
|
1215
1391
|
}),
|
|
1216
|
-
globalTestUrlHint === void 0 ? h("span", { style: S.hint }, t.testUrlHint) : h(
|
|
1392
|
+
globalTestUrlHint === void 0 ? h("span", { className: import_client.default.hint, style: S.hint }, t.testUrlHint) : h(
|
|
1217
1393
|
"span",
|
|
1218
1394
|
{
|
|
1219
1395
|
className: import_client.default.hint,
|
|
@@ -1251,21 +1427,87 @@ function renderPage(ctx) {
|
|
|
1251
1427
|
),
|
|
1252
1428
|
h(
|
|
1253
1429
|
"p",
|
|
1254
|
-
{ style: S.hint },
|
|
1430
|
+
{ className: import_client.default.hint, style: { ...S.hint, margin: "2px 0 0" } },
|
|
1255
1431
|
globalLocalDirect ? t.localDirectOnHint : t.localDirectOffHint
|
|
1256
1432
|
)
|
|
1257
1433
|
);
|
|
1434
|
+
const routeStateOf = (row) => {
|
|
1435
|
+
const route = view({ ...configured[row.id], ...draft[row.id] });
|
|
1436
|
+
const recorded = problems[row.id];
|
|
1437
|
+
const useDefault = route.useDefault === true;
|
|
1438
|
+
const problemText = recorded !== void 0 ? recorded : useDefault ? defaultComplete ? void 0 : `${t.defaultMissing}${defaultWhy}` : route.enabled ? defaultProxyProblem(route) : void 0;
|
|
1439
|
+
if (route.enabled && problemText !== void 0) return "rejected";
|
|
1440
|
+
if (route.enabled) return "proxied";
|
|
1441
|
+
return "direct";
|
|
1442
|
+
};
|
|
1258
1443
|
const query = filter.trim().toLowerCase();
|
|
1259
|
-
const
|
|
1444
|
+
const matchedKeywordRows = query.length === 0 ? rows : rows.filter((row) => `${row.id} ${row.name}`.toLowerCase().includes(query));
|
|
1445
|
+
const countActive = matchedKeywordRows.filter((r) => routeStateOf(r) === "proxied").length;
|
|
1446
|
+
const countDirect = matchedKeywordRows.filter((r) => routeStateOf(r) === "direct").length;
|
|
1447
|
+
const countRejected = matchedKeywordRows.filter((r) => routeStateOf(r) === "rejected").length;
|
|
1448
|
+
const shown = matchedKeywordRows.filter((row) => {
|
|
1449
|
+
if (statusFilter === "all") return true;
|
|
1450
|
+
return routeStateOf(row) === statusFilter;
|
|
1451
|
+
});
|
|
1452
|
+
const chipRow = rows.length === 0 ? null : h(
|
|
1453
|
+
"div",
|
|
1454
|
+
{ className: import_client.default.chipRow, style: S.chipRow, key: "status-chips" },
|
|
1455
|
+
[
|
|
1456
|
+
{ id: "all", label: `${t.filterStatusAll} (${matchedKeywordRows.length})` },
|
|
1457
|
+
{ id: "proxied", label: `${t.filterStatusProxied} (${countActive})` },
|
|
1458
|
+
{ id: "direct", label: `${t.filterStatusDirect} (${countDirect})` },
|
|
1459
|
+
{ id: "rejected", label: `${t.filterStatusRejected} (${countRejected})` }
|
|
1460
|
+
].map(
|
|
1461
|
+
({ id, label }) => h(
|
|
1462
|
+
"button",
|
|
1463
|
+
{
|
|
1464
|
+
key: id,
|
|
1465
|
+
type: "button",
|
|
1466
|
+
className: statusFilter === id ? import_client.default.chipActive : import_client.default.chip,
|
|
1467
|
+
style: {
|
|
1468
|
+
...S.chip,
|
|
1469
|
+
...statusFilter === id ? S.chipActive : {}
|
|
1470
|
+
},
|
|
1471
|
+
onClick: () => setStatusFilter(id)
|
|
1472
|
+
},
|
|
1473
|
+
label
|
|
1474
|
+
)
|
|
1475
|
+
)
|
|
1476
|
+
);
|
|
1260
1477
|
const filterRow = rows.length === 0 ? null : field(
|
|
1261
1478
|
t.filterLabel,
|
|
1262
|
-
h(
|
|
1263
|
-
|
|
1264
|
-
style:
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1479
|
+
h(
|
|
1480
|
+
"div",
|
|
1481
|
+
{ style: { display: "flex", alignItems: "center", gap: "8px" } },
|
|
1482
|
+
h("input", {
|
|
1483
|
+
className: import_client.default.input,
|
|
1484
|
+
style: S.input,
|
|
1485
|
+
placeholder: t.filterPlaceholder,
|
|
1486
|
+
value: filter,
|
|
1487
|
+
onChange: (event) => setFilter(event.target.value)
|
|
1488
|
+
}),
|
|
1489
|
+
h(
|
|
1490
|
+
"button",
|
|
1491
|
+
{
|
|
1492
|
+
className: import_client.default.testButton,
|
|
1493
|
+
style: { ...S.testButton, flex: "none", whiteSpace: "nowrap" },
|
|
1494
|
+
type: "button",
|
|
1495
|
+
disabled: countActive === 0 || batchProgress !== null,
|
|
1496
|
+
onClick: runBatchTest
|
|
1497
|
+
},
|
|
1498
|
+
batchProgress !== null ? `${t.batchTesting} (${batchProgress.done}/${batchProgress.total})` : `${t.batchTest} (${countActive})`
|
|
1499
|
+
),
|
|
1500
|
+
h(
|
|
1501
|
+
"button",
|
|
1502
|
+
{
|
|
1503
|
+
className: import_client.default.testButton,
|
|
1504
|
+
style: { ...S.testButton, flex: "none", whiteSpace: "nowrap" },
|
|
1505
|
+
type: "button",
|
|
1506
|
+
onClick: () => setViewMode((m) => m === "card" ? "compact" : "card")
|
|
1507
|
+
},
|
|
1508
|
+
viewMode === "card" ? t.viewCompact : t.viewCard
|
|
1509
|
+
)
|
|
1510
|
+
)
|
|
1269
1511
|
);
|
|
1270
1512
|
const catalogueStatus = rows.length === 0 ? state.pending ? { text: t.catalogueLoading, error: false } : state.error !== void 0 ? { text: `${t.catalogueError}${state.error}`, error: true } : void 0 : void 0;
|
|
1271
1513
|
const catalogueNotice = state.error !== void 0 && rows.length > 0 ? h(
|
|
@@ -1384,11 +1626,13 @@ function renderPage(ctx) {
|
|
|
1384
1626
|
}),
|
|
1385
1627
|
passwordToggle(passwordVisible[row.id] === true, () => togglePassword(row.id))
|
|
1386
1628
|
),
|
|
1387
|
-
route.protocol === "socks5" ? t.passwordHint : t.passwordHintProxy
|
|
1629
|
+
route.protocol === "socks5" ? t.passwordHint : t.passwordHintProxy,
|
|
1630
|
+
false,
|
|
1631
|
+
true
|
|
1388
1632
|
)
|
|
1389
1633
|
];
|
|
1390
1634
|
const pill = rejected ? { className: import_client.default.pillRejected, style: { ...S.pill, ...S.pillRejected }, text: t.rejected } : route.enabled ? { className: import_client.default.pillOn, style: { ...S.pill, ...S.pillOn }, text: t.on } : { className: import_client.default.pillLive, style: { ...S.pill, ...S.pillLive }, text: t.off };
|
|
1391
|
-
|
|
1635
|
+
const cardSection = h(
|
|
1392
1636
|
"section",
|
|
1393
1637
|
{
|
|
1394
1638
|
className: rejected ? import_client.default.cardRejected : route.enabled ? import_client.default.cardActive : import_client.default.card,
|
|
@@ -1454,7 +1698,7 @@ function renderPage(ctx) {
|
|
|
1454
1698
|
{ key: `${row.id}:inherit`, style: S.inheritNote },
|
|
1455
1699
|
`${t.inheritingDefault}${defaultOrigin}`
|
|
1456
1700
|
) : null,
|
|
1457
|
-
...useDefault ? [] : endpointFields,
|
|
1701
|
+
...useDefault ? [] : [h("div", { className: import_client.default.formGrid, style: S.formGrid, key: `${row.id}:form-grid` }, ...endpointFields)],
|
|
1458
1702
|
// The self-check is offered whenever there is something to check: an
|
|
1459
1703
|
// enabled route (the Host's table carries it, and a rejected one still
|
|
1460
1704
|
// reports WHY), or a disabled one whose endpoint is already complete —
|
|
@@ -1495,7 +1739,12 @@ function renderPage(ctx) {
|
|
|
1495
1739
|
{ key: "status" },
|
|
1496
1740
|
`HTTP ${result.status}`
|
|
1497
1741
|
) : null,
|
|
1498
|
-
result.ip === void 0 ? null : h(
|
|
1742
|
+
result.ip === void 0 ? null : h(
|
|
1743
|
+
"span",
|
|
1744
|
+
{ key: "ip", style: { display: "inline-flex", alignItems: "center", gap: "3px" } },
|
|
1745
|
+
`${t.exitIpLabel}${result.ip}`,
|
|
1746
|
+
copyButton(`${row.id}:ip`, result.ip, t.copy)
|
|
1747
|
+
),
|
|
1499
1748
|
result.direct === true ? h("span", { key: "direct" }, t.directLabel) : null,
|
|
1500
1749
|
result.cached === true ? h("span", { key: "cached" }, t.cachedLabel) : null,
|
|
1501
1750
|
result.target === void 0 ? null : h(
|
|
@@ -1506,13 +1755,22 @@ function renderPage(ctx) {
|
|
|
1506
1755
|
flexBasis: "100%",
|
|
1507
1756
|
fontSize: "11px",
|
|
1508
1757
|
color: "var(--dsw-alias-label-secondary)",
|
|
1509
|
-
wordBreak: "break-all"
|
|
1758
|
+
wordBreak: "break-all",
|
|
1759
|
+
display: "inline-flex",
|
|
1760
|
+
alignItems: "center",
|
|
1761
|
+
gap: "3px"
|
|
1510
1762
|
}
|
|
1511
1763
|
},
|
|
1512
|
-
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}
|
|
1764
|
+
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,
|
|
1765
|
+
copyButton(`${row.id}:target`, result.target, t.copy)
|
|
1513
1766
|
)
|
|
1514
1767
|
] : [
|
|
1515
|
-
h(
|
|
1768
|
+
h(
|
|
1769
|
+
"span",
|
|
1770
|
+
{ key: "err", style: { ...S.testFailure, display: "inline-flex", alignItems: "center", gap: "3px" } },
|
|
1771
|
+
`\u2717 ${result.error}`,
|
|
1772
|
+
copyButton(`${row.id}:err`, String(result.error), t.copy)
|
|
1773
|
+
),
|
|
1516
1774
|
typeof result.status === "number" ? h("span", { key: "status" }, `HTTP ${result.status}`) : null,
|
|
1517
1775
|
result.target === void 0 ? null : h(
|
|
1518
1776
|
"span",
|
|
@@ -1522,10 +1780,14 @@ function renderPage(ctx) {
|
|
|
1522
1780
|
flexBasis: "100%",
|
|
1523
1781
|
fontSize: "11px",
|
|
1524
1782
|
color: "var(--dsw-alias-label-secondary)",
|
|
1525
|
-
wordBreak: "break-all"
|
|
1783
|
+
wordBreak: "break-all",
|
|
1784
|
+
display: "inline-flex",
|
|
1785
|
+
alignItems: "center",
|
|
1786
|
+
gap: "3px"
|
|
1526
1787
|
}
|
|
1527
1788
|
},
|
|
1528
|
-
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}
|
|
1789
|
+
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,
|
|
1790
|
+
copyButton(`${row.id}:target`, result.target, t.copy)
|
|
1529
1791
|
)
|
|
1530
1792
|
]
|
|
1531
1793
|
) : null,
|
|
@@ -1588,6 +1850,58 @@ function renderPage(ctx) {
|
|
|
1588
1850
|
)
|
|
1589
1851
|
)
|
|
1590
1852
|
);
|
|
1853
|
+
const isExpanded = expandedCards[row.id] === true;
|
|
1854
|
+
const compactRowElement = h(
|
|
1855
|
+
"section",
|
|
1856
|
+
{
|
|
1857
|
+
className: rejected ? import_client.default.compactRowRejected : route.enabled ? import_client.default.compactRowActive : import_client.default.compactRow,
|
|
1858
|
+
style: rejected ? { ...S.compactRow, ...S.compactRowRejected } : route.enabled ? { ...S.compactRow, ...S.compactRowActive } : S.compactRow,
|
|
1859
|
+
key: `compact:${row.id}`
|
|
1860
|
+
},
|
|
1861
|
+
h(
|
|
1862
|
+
"div",
|
|
1863
|
+
{ style: { display: "flex", alignItems: "center", gap: "8px", minWidth: "0" } },
|
|
1864
|
+
h("input", {
|
|
1865
|
+
type: "checkbox",
|
|
1866
|
+
checked: route.enabled,
|
|
1867
|
+
onChange: (event) => bind(row.id, "enabled")(event.target.checked === true)
|
|
1868
|
+
}),
|
|
1869
|
+
h("span", { className: import_client.default.name, style: { ...S.name, maxWidth: "140px" } }, row.name),
|
|
1870
|
+
h("span", { className: import_client.default.id, style: S.id }, row.id),
|
|
1871
|
+
useDefault ? h("span", { style: S.compactEndpoint }, `${t.useDefault}: ${defaultOrigin}`) : h("span", { style: S.compactEndpoint }, `${route.protocol.toUpperCase()}://${route.host || "\u2014"}:${route.port || "\u2014"}`)
|
|
1872
|
+
),
|
|
1873
|
+
h(
|
|
1874
|
+
"div",
|
|
1875
|
+
{ style: { display: "flex", alignItems: "center", gap: "8px", flex: "none" } },
|
|
1876
|
+
result?.pending === true ? h("span", { style: { fontSize: "11px", color: "var(--dsw-alias-label-secondary)" } }, t.testRunning) : result?.ok === true ? h("span", { style: { fontSize: "11px", color: latencyColor(result.ms), fontWeight: "500" } }, `\u2713 ${result.ms ?? "\u2014"} ms`) : result?.ok === false ? h("span", { style: { fontSize: "11px", color: "var(--dsw-alias-state-error-primary, #f85149)", fontWeight: "500" } }, `\u2717 ${result.error}`) : lastText !== void 0 ? h("span", { style: { fontSize: "11px", color: "var(--dsw-alias-label-secondary)" } }, lastText) : null,
|
|
1877
|
+
h("span", { className: pill.className, style: pill.style }, pill.text),
|
|
1878
|
+
showTest ? h(
|
|
1879
|
+
"button",
|
|
1880
|
+
{
|
|
1881
|
+
className: import_client.default.testButton,
|
|
1882
|
+
style: { ...S.testButton, padding: "3px 8px", fontSize: "11px" },
|
|
1883
|
+
type: "button",
|
|
1884
|
+
disabled: result?.pending === true,
|
|
1885
|
+
onClick: () => runTest(row.id)
|
|
1886
|
+
},
|
|
1887
|
+
result?.pending === true ? t.testRunning : t.testButton
|
|
1888
|
+
) : null,
|
|
1889
|
+
h(
|
|
1890
|
+
"button",
|
|
1891
|
+
{
|
|
1892
|
+
className: import_client.default.testButton,
|
|
1893
|
+
style: { ...S.testButton, padding: "3px 8px", fontSize: "11px" },
|
|
1894
|
+
type: "button",
|
|
1895
|
+
onClick: () => setExpandedCards((curr) => ({ ...curr, [row.id]: !curr[row.id] }))
|
|
1896
|
+
},
|
|
1897
|
+
isExpanded ? t.collapseDetails : t.expandDetails
|
|
1898
|
+
)
|
|
1899
|
+
)
|
|
1900
|
+
);
|
|
1901
|
+
if (viewMode === "compact") {
|
|
1902
|
+
return isExpanded ? h("div", { key: `compact-wrap:${row.id}` }, compactRowElement, cardSection) : compactRowElement;
|
|
1903
|
+
}
|
|
1904
|
+
return cardSection;
|
|
1591
1905
|
});
|
|
1592
1906
|
return h(
|
|
1593
1907
|
"div",
|
|
@@ -1628,6 +1942,7 @@ function renderPage(ctx) {
|
|
|
1628
1942
|
defaultBlock,
|
|
1629
1943
|
globalBlock,
|
|
1630
1944
|
catalogueNotice,
|
|
1945
|
+
chipRow,
|
|
1631
1946
|
filterRow,
|
|
1632
1947
|
...body,
|
|
1633
1948
|
h(
|
|
@@ -1679,6 +1994,10 @@ var EN = {
|
|
|
1679
1994
|
defaultMissing: "The default proxy configuration is incomplete, so this provider is not proxied: ",
|
|
1680
1995
|
filterLabel: "Filter",
|
|
1681
1996
|
filterPlaceholder: "Filter by name or id\u2026",
|
|
1997
|
+
filterStatusAll: "All",
|
|
1998
|
+
filterStatusProxied: "Proxied",
|
|
1999
|
+
filterStatusDirect: "Direct",
|
|
2000
|
+
filterStatusRejected: "Rejected",
|
|
1682
2001
|
noMatch: "No provider matches the filter.",
|
|
1683
2002
|
setAsDefault: "Set as the default proxy",
|
|
1684
2003
|
applyDefaultAll: "Use the default proxy for all providers",
|
|
@@ -1690,7 +2009,7 @@ var EN = {
|
|
|
1690
2009
|
showPassword: "Show",
|
|
1691
2010
|
hidePassword: "Hide",
|
|
1692
2011
|
confirmPromoteToDefault: "The default proxy is already in use by one or more providers. Replace it with this card's endpoint?",
|
|
1693
|
-
hostHint: "
|
|
2012
|
+
hostHint: "IP or domain only; paste full URL supported",
|
|
1694
2013
|
passwordHint: "Sent to the SOCKS5 proxy for authentication; stored with this setting.",
|
|
1695
2014
|
passwordHintProxy: "Sent to the proxy as an authentication password; stored with this setting.",
|
|
1696
2015
|
hitCountPrefix: "",
|
|
@@ -1703,6 +2022,12 @@ var EN = {
|
|
|
1703
2022
|
minutesAgo: " min ago",
|
|
1704
2023
|
hoursAgo: " h ago",
|
|
1705
2024
|
daysAgo: " d ago",
|
|
2025
|
+
viewCard: "Card view",
|
|
2026
|
+
viewCompact: "Compact view",
|
|
2027
|
+
expandDetails: "Edit",
|
|
2028
|
+
collapseDetails: "Collapse",
|
|
2029
|
+
batchTest: "Test active",
|
|
2030
|
+
batchTesting: "Testing",
|
|
1706
2031
|
testButton: "Test",
|
|
1707
2032
|
testRunning: "Testing\u2026",
|
|
1708
2033
|
testDisabledNote: "Not enabled \u2014 test only: ",
|
|
@@ -1744,7 +2069,9 @@ var EN = {
|
|
|
1744
2069
|
catalogueMismatch: "Saved but not listed by the Host catalogue: ",
|
|
1745
2070
|
catalogueMismatchSuffix: ". Their proxy settings are kept.",
|
|
1746
2071
|
saveFailedPrefix: "Save failed: ",
|
|
1747
|
-
close: "Close"
|
|
2072
|
+
close: "Close",
|
|
2073
|
+
copy: "Copy",
|
|
2074
|
+
copied: "Copied"
|
|
1748
2075
|
};
|
|
1749
2076
|
var ZH = {
|
|
1750
2077
|
lead: "\u8BA9\u6307\u5B9A\u7684 provider \u8D70\u4F60\u81EA\u5DF1\u7684\u6B63\u5411\u4EE3\u7406\uFF0C\u5176\u5B83 provider \u4FDD\u6301\u76F4\u8FDE\u3002\u6307\u5411\u672C\u673A\u6216\u5185\u7F51\u5730\u5740\uFF08localhost\u3001127.x\u3001\u79C1\u6709\u7F51\u6BB5\uFF09\u7684\u8BF7\u6C42\u9ED8\u8BA4\u76F4\u8FDE\uFF0C\u9876\u5C42 localDirect \u8BBE\u4E3A false \u65F6\u6062\u590D\u8D70\u4EE3\u7406\u2014\u2014\u6B63\u5411\u4EE3\u7406\u901A\u5E38\u591F\u4E0D\u5230\u4F60\u81EA\u5DF1\u7684\u673A\u5668\u3002",
|
|
@@ -1760,6 +2087,10 @@ var ZH = {
|
|
|
1760
2087
|
defaultMissing: "\u9876\u5C42\u9ED8\u8BA4\u4EE3\u7406\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u8BE5 provider \u4E0D\u4F1A\u8D70\u4EE3\u7406\uFF1A",
|
|
1761
2088
|
filterLabel: "\u8FC7\u6EE4",
|
|
1762
2089
|
filterPlaceholder: "\u6309\u540D\u79F0\u6216 id \u8FC7\u6EE4\u2026",
|
|
2090
|
+
filterStatusAll: "\u5168\u90E8",
|
|
2091
|
+
filterStatusProxied: "\u8D70\u4EE3\u7406",
|
|
2092
|
+
filterStatusDirect: "\u76F4\u8FDE",
|
|
2093
|
+
filterStatusRejected: "\u914D\u7F6E\u88AB\u62D2",
|
|
1763
2094
|
noMatch: "\u6CA1\u6709\u5339\u914D\u7684 provider\u3002",
|
|
1764
2095
|
setAsDefault: "\u8BBE\u4E3A\u9ED8\u8BA4\u4EE3\u7406",
|
|
1765
2096
|
applyDefaultAll: "\u6240\u6709 provider \u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406",
|
|
@@ -1771,7 +2102,7 @@ var ZH = {
|
|
|
1771
2102
|
showPassword: "\u663E\u793A",
|
|
1772
2103
|
hidePassword: "\u9690\u85CF",
|
|
1773
2104
|
confirmPromoteToDefault: "\u5DF2\u6709 provider \u6B63\u5728\u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406\u3002\u8981\u7528\u8FD9\u5F20\u5361\u7247\u7684\u7AEF\u70B9\u8986\u76D6\u5B83\u5417\uFF1F",
|
|
1774
|
-
hostHint: "\
|
|
2105
|
+
hostHint: "\u4EC5\u9650 IP \u6216\u57DF\u540D\uFF0C\u652F\u6301\u7C98\u8D34\u5B8C\u6574\u4EE3\u7406 URL",
|
|
1775
2106
|
passwordHint: "\u4EC5\u4F5C\u4E3A SOCKS5 \u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002",
|
|
1776
2107
|
passwordHintProxy: "\u4F5C\u4E3A\u4EE3\u7406\u8BA4\u8BC1\u53E3\u4EE4\u53D1\u9001\u7ED9\u4EE3\u7406\uFF1B\u968F\u8BE5\u8BBE\u7F6E\u4E00\u8D77\u4FDD\u5B58\u3002",
|
|
1777
2108
|
hitCountPrefix: "\u5DF2\u4EE3\u7406 ",
|
|
@@ -1784,6 +2115,12 @@ var ZH = {
|
|
|
1784
2115
|
minutesAgo: " \u5206\u949F\u524D",
|
|
1785
2116
|
hoursAgo: " \u5C0F\u65F6\u524D",
|
|
1786
2117
|
daysAgo: " \u5929\u524D",
|
|
2118
|
+
viewCard: "\u5361\u7247\u89C6\u56FE",
|
|
2119
|
+
viewCompact: "\u7D27\u51D1\u89C6\u56FE",
|
|
2120
|
+
expandDetails: "\u7F16\u8F91",
|
|
2121
|
+
collapseDetails: "\u6536\u8D77",
|
|
2122
|
+
batchTest: "\u6D4B\u8BD5\u5DF2\u542F\u7528",
|
|
2123
|
+
batchTesting: "\u6B63\u5728\u6D4B\u8BD5",
|
|
1787
2124
|
testButton: "\u6D4B\u8BD5",
|
|
1788
2125
|
testRunning: "\u6D4B\u8BD5\u4E2D\u2026",
|
|
1789
2126
|
testDisabledNote: "\u672A\u542F\u7528\uFF0C\u4EC5\u6D4B\u8BD5\uFF1A",
|
|
@@ -1825,7 +2162,9 @@ var ZH = {
|
|
|
1825
2162
|
catalogueMismatch: "\u5DF2\u4FDD\u5B58\u4F46\u672A\u51FA\u73B0\u5728 Host \u76EE\u5F55\u4E2D\u7684 provider\uFF1A",
|
|
1826
2163
|
catalogueMismatchSuffix: "\u3002\u4EE3\u7406\u914D\u7F6E\u4ECD\u4F1A\u4FDD\u7559\u3002",
|
|
1827
2164
|
saveFailedPrefix: "\u4FDD\u5B58\u5931\u8D25\uFF1A",
|
|
1828
|
-
close: "\u5173\u95ED"
|
|
2165
|
+
close: "\u5173\u95ED",
|
|
2166
|
+
copy: "\u590D\u5236",
|
|
2167
|
+
copied: "\u5DF2\u590D\u5236"
|
|
1829
2168
|
};
|
|
1830
2169
|
function stringsFor(ctx) {
|
|
1831
2170
|
const language = localeOf(ctx);
|