dsh-provider-proxy 0.6.1 → 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 +16 -3
- package/lib/client.js +551 -111
- package/lib/client.js.map +3 -3
- 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;
|
|
@@ -357,7 +357,7 @@ async function fetchCatalog() {
|
|
|
357
357
|
};
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
|
-
return { rows, hits, problems, lastUse };
|
|
360
|
+
return { rows, publishedRows: rows, hits, problems, lastUse };
|
|
361
361
|
}
|
|
362
362
|
var CATALOG_REFRESH_MS = 1e4;
|
|
363
363
|
var catalogPoll;
|
|
@@ -540,6 +540,29 @@ var S = {
|
|
|
540
540
|
fontSize: "12px",
|
|
541
541
|
cursor: "pointer"
|
|
542
542
|
},
|
|
543
|
+
/** The reveal/hide control sits inside the password field's right edge. */
|
|
544
|
+
passwordControl: {
|
|
545
|
+
position: "relative",
|
|
546
|
+
minWidth: "0"
|
|
547
|
+
},
|
|
548
|
+
passwordToggle: {
|
|
549
|
+
position: "absolute",
|
|
550
|
+
top: "50%",
|
|
551
|
+
right: "4px",
|
|
552
|
+
display: "flex",
|
|
553
|
+
alignItems: "center",
|
|
554
|
+
justifyContent: "center",
|
|
555
|
+
width: "26px",
|
|
556
|
+
height: "26px",
|
|
557
|
+
padding: "0",
|
|
558
|
+
border: "0",
|
|
559
|
+
borderRadius: "6px",
|
|
560
|
+
background: "transparent",
|
|
561
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
562
|
+
lineHeight: "1",
|
|
563
|
+
transform: "translateY(-50%)",
|
|
564
|
+
cursor: "pointer"
|
|
565
|
+
},
|
|
543
566
|
testResult: {
|
|
544
567
|
// A flex row so the target can drop onto its own line: the container was a
|
|
545
568
|
// plain span, where `flexBasis: 100%` does nothing and the target ran into
|
|
@@ -566,6 +589,10 @@ var S = {
|
|
|
566
589
|
diagProblem: {
|
|
567
590
|
color: "var(--dsw-alias-state-error-primary, #f85149)"
|
|
568
591
|
},
|
|
592
|
+
/** Informational catalogue mismatch: not a rejected route, so no error red. */
|
|
593
|
+
diagNote: {
|
|
594
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
595
|
+
},
|
|
569
596
|
advanced: {
|
|
570
597
|
marginTop: "4px",
|
|
571
598
|
fontSize: "12px"
|
|
@@ -639,10 +666,11 @@ var S = {
|
|
|
639
666
|
},
|
|
640
667
|
field: {
|
|
641
668
|
display: "grid",
|
|
642
|
-
gridTemplateColumns: "
|
|
669
|
+
gridTemplateColumns: "76px 1fr",
|
|
643
670
|
alignItems: "center",
|
|
644
|
-
gap: "
|
|
645
|
-
fontSize: "12px"
|
|
671
|
+
gap: "8px",
|
|
672
|
+
fontSize: "12px",
|
|
673
|
+
minWidth: "0"
|
|
646
674
|
},
|
|
647
675
|
label: { color: "var(--dsw-alias-label-secondary)" },
|
|
648
676
|
input: {
|
|
@@ -667,9 +695,83 @@ var S = {
|
|
|
667
695
|
color: "var(--dsw-alias-label-secondary)"
|
|
668
696
|
},
|
|
669
697
|
hint: {
|
|
670
|
-
gridColumn: "
|
|
698
|
+
gridColumn: "1 / -1",
|
|
671
699
|
fontSize: "11px",
|
|
672
|
-
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"
|
|
673
775
|
}
|
|
674
776
|
};
|
|
675
777
|
function renderPage(ctx) {
|
|
@@ -693,6 +795,7 @@ function renderPage(ctx) {
|
|
|
693
795
|
void fetchCatalog().then((catalog) => catalogueSetter?.(catalog)).catch((error) => {
|
|
694
796
|
catalogueSetter?.({
|
|
695
797
|
rows: [],
|
|
798
|
+
publishedRows: [],
|
|
696
799
|
hits: {},
|
|
697
800
|
problems: {},
|
|
698
801
|
lastUse: {},
|
|
@@ -701,6 +804,7 @@ function renderPage(ctx) {
|
|
|
701
804
|
});
|
|
702
805
|
return {
|
|
703
806
|
rows: void 0,
|
|
807
|
+
publishedRows: void 0,
|
|
704
808
|
hits: {},
|
|
705
809
|
problems: {},
|
|
706
810
|
lastUse: {},
|
|
@@ -710,6 +814,7 @@ function renderPage(ctx) {
|
|
|
710
814
|
});
|
|
711
815
|
catalogueSetter = (catalog) => setState({
|
|
712
816
|
rows: catalog.rows,
|
|
817
|
+
publishedRows: catalog.publishedRows,
|
|
713
818
|
hits: catalog.hits,
|
|
714
819
|
problems: catalog.problems,
|
|
715
820
|
lastUse: catalog.lastUse,
|
|
@@ -718,6 +823,7 @@ function renderPage(ctx) {
|
|
|
718
823
|
});
|
|
719
824
|
touchCatalogPolling();
|
|
720
825
|
const published = state.rows ?? [];
|
|
826
|
+
const publishedRows = state.publishedRows ?? [];
|
|
721
827
|
const hits = state.hits ?? {};
|
|
722
828
|
const lastUse = state.lastUse ?? {};
|
|
723
829
|
const lastUseText = (id) => {
|
|
@@ -731,7 +837,14 @@ function renderPage(ctx) {
|
|
|
731
837
|
const problemLines = Object.entries(problems).map(
|
|
732
838
|
([id, message]) => h("li", { key: `p:${id}`, style: S.diagProblem }, `${id}\uFF1A${message}`)
|
|
733
839
|
);
|
|
734
|
-
const
|
|
840
|
+
const publishedIds = new Set(publishedRows.map((row) => row.id));
|
|
841
|
+
const missingFromCatalog = state.pending === true || state.error !== void 0 ? [] : Object.keys(configured).filter((id) => !publishedIds.has(id)).sort();
|
|
842
|
+
const catalogueMismatchLine = missingFromCatalog.length === 0 ? void 0 : h(
|
|
843
|
+
"li",
|
|
844
|
+
{ key: "catalogue-mismatch", style: S.diagNote },
|
|
845
|
+
`${t.catalogueMismatch}${missingFromCatalog.join("\u3001")}${t.catalogueMismatchSuffix}`
|
|
846
|
+
);
|
|
847
|
+
const problemCount = problemLines.length + (catalogueMismatchLine === void 0 ? 0 : 1);
|
|
735
848
|
note(
|
|
736
849
|
`provider \u5217\u8868\uFF1A\u6765\u81EA Host \u5171 ${published.length} \u4E2A\uFF08${published.map((r) => r.id).join("\u3001") || "\u65E0"}\uFF09`
|
|
737
850
|
);
|
|
@@ -741,6 +854,45 @@ function renderPage(ctx) {
|
|
|
741
854
|
const [defaultDraft, setDefaultDraft] = (React.useState ?? ((v) => [v, () => {
|
|
742
855
|
}]))({});
|
|
743
856
|
const editDefault = (field2, value) => setDefaultDraft((current) => ({ ...current, [field2]: value }));
|
|
857
|
+
const [passwordVisible, setPasswordVisible] = (React.useState ?? ((v) => [v, () => {
|
|
858
|
+
}]))({});
|
|
859
|
+
const [defaultPasswordVisible, setDefaultPasswordVisible] = (React.useState ?? ((v) => [v, () => {
|
|
860
|
+
}]))(false);
|
|
861
|
+
const togglePassword = (id) => setPasswordVisible((current) => ({ ...current, [id]: current[id] !== true }));
|
|
862
|
+
const toggleDefaultPassword = () => setDefaultPasswordVisible((current) => current !== true);
|
|
863
|
+
const passwordToggle = (visible, onToggle) => h(
|
|
864
|
+
"button",
|
|
865
|
+
{
|
|
866
|
+
className: import_client.default.passwordToggle,
|
|
867
|
+
style: S.passwordToggle,
|
|
868
|
+
type: "button",
|
|
869
|
+
"aria-label": visible ? t.hidePassword : t.showPassword,
|
|
870
|
+
"aria-pressed": visible,
|
|
871
|
+
title: visible ? t.hidePassword : t.showPassword,
|
|
872
|
+
onClick: onToggle
|
|
873
|
+
},
|
|
874
|
+
h(
|
|
875
|
+
"svg",
|
|
876
|
+
{
|
|
877
|
+
width: 16,
|
|
878
|
+
height: 16,
|
|
879
|
+
viewBox: "0 0 24 24",
|
|
880
|
+
fill: "none",
|
|
881
|
+
stroke: "currentColor",
|
|
882
|
+
strokeWidth: 2,
|
|
883
|
+
strokeLinecap: "round",
|
|
884
|
+
strokeLinejoin: "round",
|
|
885
|
+
"aria-hidden": "true",
|
|
886
|
+
focusable: "false"
|
|
887
|
+
},
|
|
888
|
+
h("path", {
|
|
889
|
+
key: "eye",
|
|
890
|
+
d: "M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z"
|
|
891
|
+
}),
|
|
892
|
+
h("circle", { key: "pupil", cx: 12, cy: 12, r: 3 }),
|
|
893
|
+
visible ? h("path", { key: "slash", d: "m3 3 18 18" }) : null
|
|
894
|
+
)
|
|
895
|
+
);
|
|
744
896
|
const [globalDraft, setGlobalDraft] = (React.useState ?? ((v) => [v, () => {
|
|
745
897
|
}]))({});
|
|
746
898
|
const editGlobal = (field2, value) => setGlobalDraft((current) => ({ ...current, [field2]: value }));
|
|
@@ -768,11 +920,77 @@ function renderPage(ctx) {
|
|
|
768
920
|
};
|
|
769
921
|
const [filter, setFilter] = (React.useState ?? ((v) => [v, () => {
|
|
770
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
|
+
);
|
|
771
989
|
const runTest = (id) => {
|
|
772
990
|
const generation = (testGeneration.get(id) ?? 0) + 1;
|
|
773
991
|
testGeneration.set(id, generation);
|
|
774
992
|
setTests((current) => ({ ...current, [id]: { pending: true } }));
|
|
775
|
-
|
|
993
|
+
return (async () => {
|
|
776
994
|
try {
|
|
777
995
|
for (const [key, entry] of [...pendingWrites]) {
|
|
778
996
|
if (key.startsWith(`${id}\0`) || key.startsWith("\0default\0") || key.startsWith("\0global\0")) {
|
|
@@ -798,6 +1016,28 @@ function renderPage(ctx) {
|
|
|
798
1016
|
}
|
|
799
1017
|
})();
|
|
800
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
|
+
};
|
|
801
1041
|
const rows = knownProviders({ ...configured, ...draft }, published);
|
|
802
1042
|
const inheritingIds = () => rows.filter((row) => view({ ...configured[row.id], ...draft[row.id] }).useDefault === true).map((row) => row.id);
|
|
803
1043
|
const save = (key, path, label, value, onRefused) => {
|
|
@@ -924,6 +1164,9 @@ function renderPage(ctx) {
|
|
|
924
1164
|
);
|
|
925
1165
|
};
|
|
926
1166
|
const promoteToDefault = (id) => {
|
|
1167
|
+
if (defaultComplete && inheritingIds().length > 0 && globalThis.window?.confirm?.(t.confirmPromoteToDefault) !== true) {
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
927
1170
|
const route = view({ ...configured[id], ...draft[id] });
|
|
928
1171
|
applyDefaultUrl({
|
|
929
1172
|
protocol: route.protocol,
|
|
@@ -945,7 +1188,7 @@ function renderPage(ctx) {
|
|
|
945
1188
|
saveMany(
|
|
946
1189
|
"\0default\0applyAll",
|
|
947
1190
|
ids.map((id) => ({ op: "set", path: ["providers", id, "useDefault"], value: true })),
|
|
948
|
-
|
|
1191
|
+
`\u6240\u6709 provider \u7684 useDefault\uFF08${ids.length} \u4E2A\uFF09`,
|
|
949
1192
|
() => setDraft((current) => {
|
|
950
1193
|
const next = { ...current };
|
|
951
1194
|
for (const id of ids) {
|
|
@@ -968,9 +1211,16 @@ function renderPage(ctx) {
|
|
|
968
1211
|
event.preventDefault?.();
|
|
969
1212
|
apply2(parts);
|
|
970
1213
|
};
|
|
971
|
-
const field = (label, control, hint, hintError) => h(
|
|
1214
|
+
const field = (label, control, hint, hintError, fullWidth) => h(
|
|
972
1215
|
"label",
|
|
973
|
-
{
|
|
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
|
+
},
|
|
974
1224
|
h("span", { className: import_client.default.label, style: S.label }, label),
|
|
975
1225
|
control,
|
|
976
1226
|
hint === void 0 ? null : h(
|
|
@@ -978,8 +1228,8 @@ function renderPage(ctx) {
|
|
|
978
1228
|
{
|
|
979
1229
|
className: import_client.default.hint,
|
|
980
1230
|
style: {
|
|
981
|
-
|
|
982
|
-
|
|
1231
|
+
...S.hint,
|
|
1232
|
+
marginTop: "2px",
|
|
983
1233
|
// A warning that a value can never work is an answer, not
|
|
984
1234
|
// decoration — same rule as the failed self-check text.
|
|
985
1235
|
...hintError === true ? { color: "var(--dsw-alias-state-error-primary, #f85149)" } : {}
|
|
@@ -1015,73 +1265,84 @@ function renderPage(ctx) {
|
|
|
1015
1265
|
)
|
|
1016
1266
|
),
|
|
1017
1267
|
h("p", { className: import_client.default.defaultLead, style: S.defaultLead }, t.defaultLead),
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
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", {
|
|
1023
1289
|
className: import_client.default.input,
|
|
1024
1290
|
style: S.input,
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
)
|
|
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,
|
|
1318
|
+
h("input", {
|
|
1319
|
+
className: import_client.default.input,
|
|
1320
|
+
style: S.input,
|
|
1321
|
+
autoComplete: "off",
|
|
1322
|
+
value: defaultView.username,
|
|
1323
|
+
onChange: (event) => bindDefault("username")(event.target.value)
|
|
1324
|
+
})
|
|
1325
|
+
),
|
|
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
|
|
1031
1344
|
)
|
|
1032
1345
|
),
|
|
1033
|
-
field(
|
|
1034
|
-
t.host,
|
|
1035
|
-
h("input", {
|
|
1036
|
-
className: import_client.default.input,
|
|
1037
|
-
style: S.input,
|
|
1038
|
-
placeholder: "127.0.0.1",
|
|
1039
|
-
value: defaultView.host,
|
|
1040
|
-
onChange: (event) => bindDefault("host")(event.target.value),
|
|
1041
|
-
// Same convenience as the cards: a full URL fills the whole block.
|
|
1042
|
-
onPaste: onProxyUrlPaste(applyDefaultUrl)
|
|
1043
|
-
}),
|
|
1044
|
-
defaultHostWhy ?? t.hostHint,
|
|
1045
|
-
defaultHostWhy !== void 0
|
|
1046
|
-
),
|
|
1047
|
-
field(
|
|
1048
|
-
t.port,
|
|
1049
|
-
h("input", {
|
|
1050
|
-
className: import_client.default.input,
|
|
1051
|
-
style: S.input,
|
|
1052
|
-
type: "number",
|
|
1053
|
-
min: 1,
|
|
1054
|
-
max: 65535,
|
|
1055
|
-
placeholder: "7890",
|
|
1056
|
-
value: defaultView.port === 0 ? "" : String(defaultView.port),
|
|
1057
|
-
onChange: (event) => {
|
|
1058
|
-
const parsed = Number.parseInt(event.target.value, 10);
|
|
1059
|
-
bindDefault("port")(Number.isNaN(parsed) ? 0 : parsed);
|
|
1060
|
-
}
|
|
1061
|
-
})
|
|
1062
|
-
),
|
|
1063
|
-
field(
|
|
1064
|
-
t.username,
|
|
1065
|
-
h("input", {
|
|
1066
|
-
className: import_client.default.input,
|
|
1067
|
-
style: S.input,
|
|
1068
|
-
autocomplete: "off",
|
|
1069
|
-
value: defaultView.username,
|
|
1070
|
-
onChange: (event) => bindDefault("username")(event.target.value)
|
|
1071
|
-
})
|
|
1072
|
-
),
|
|
1073
|
-
field(
|
|
1074
|
-
t.password,
|
|
1075
|
-
h("input", {
|
|
1076
|
-
className: import_client.default.input,
|
|
1077
|
-
style: S.input,
|
|
1078
|
-
type: "password",
|
|
1079
|
-
autocomplete: "off",
|
|
1080
|
-
value: defaultView.password,
|
|
1081
|
-
onChange: (event) => bindDefault("password")(event.target.value)
|
|
1082
|
-
}),
|
|
1083
|
-
t.passwordHintProxy
|
|
1084
|
-
),
|
|
1085
1346
|
// Bulk opt-in, in ONE write: a per-card walk would rebuild the table N times.
|
|
1086
1347
|
// Disabled while the default configuration is incomplete, because pointing every card at an
|
|
1087
1348
|
// empty endpoint would just refuse them all.
|
|
@@ -1097,7 +1358,7 @@ function renderPage(ctx) {
|
|
|
1097
1358
|
disabled: !defaultComplete || rows.length === 0,
|
|
1098
1359
|
onClick: applyDefaultToAll
|
|
1099
1360
|
},
|
|
1100
|
-
t.applyDefaultAll
|
|
1361
|
+
`${t.applyDefaultAll}\uFF08${rows.length}\uFF09`
|
|
1101
1362
|
)
|
|
1102
1363
|
)
|
|
1103
1364
|
);
|
|
@@ -1128,7 +1389,7 @@ function renderPage(ctx) {
|
|
|
1128
1389
|
value: globalTestUrl,
|
|
1129
1390
|
onChange: (event) => bindGlobal("testUrl")(event.target.value)
|
|
1130
1391
|
}),
|
|
1131
|
-
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(
|
|
1132
1393
|
"span",
|
|
1133
1394
|
{
|
|
1134
1395
|
className: import_client.default.hint,
|
|
@@ -1166,21 +1427,87 @@ function renderPage(ctx) {
|
|
|
1166
1427
|
),
|
|
1167
1428
|
h(
|
|
1168
1429
|
"p",
|
|
1169
|
-
{ style: S.hint },
|
|
1430
|
+
{ className: import_client.default.hint, style: { ...S.hint, margin: "2px 0 0" } },
|
|
1170
1431
|
globalLocalDirect ? t.localDirectOnHint : t.localDirectOffHint
|
|
1171
1432
|
)
|
|
1172
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
|
+
};
|
|
1173
1443
|
const query = filter.trim().toLowerCase();
|
|
1174
|
-
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
|
+
);
|
|
1175
1477
|
const filterRow = rows.length === 0 ? null : field(
|
|
1176
1478
|
t.filterLabel,
|
|
1177
|
-
h(
|
|
1178
|
-
|
|
1179
|
-
style:
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
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
|
+
)
|
|
1184
1511
|
);
|
|
1185
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;
|
|
1186
1513
|
const catalogueNotice = state.error !== void 0 && rows.length > 0 ? h(
|
|
@@ -1274,7 +1601,7 @@ function renderPage(ctx) {
|
|
|
1274
1601
|
h("input", {
|
|
1275
1602
|
className: import_client.default.input,
|
|
1276
1603
|
style: S.input,
|
|
1277
|
-
|
|
1604
|
+
autoComplete: "off",
|
|
1278
1605
|
value: route.username,
|
|
1279
1606
|
onChange: (event) => bind(row.id, "username")(event.target.value)
|
|
1280
1607
|
})
|
|
@@ -1286,19 +1613,26 @@ function renderPage(ctx) {
|
|
|
1286
1613
|
// config; the diagnostics only ever surface a credential-free origin.
|
|
1287
1614
|
field(
|
|
1288
1615
|
t.password,
|
|
1289
|
-
h(
|
|
1290
|
-
|
|
1291
|
-
style: S.
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1616
|
+
h(
|
|
1617
|
+
"div",
|
|
1618
|
+
{ style: S.passwordControl },
|
|
1619
|
+
h("input", {
|
|
1620
|
+
className: import_client.default.input,
|
|
1621
|
+
style: { ...S.input, paddingRight: "36px" },
|
|
1622
|
+
type: passwordVisible[row.id] === true ? "text" : "password",
|
|
1623
|
+
autoComplete: "off",
|
|
1624
|
+
value: route.password,
|
|
1625
|
+
onChange: (event) => bind(row.id, "password")(event.target.value)
|
|
1626
|
+
}),
|
|
1627
|
+
passwordToggle(passwordVisible[row.id] === true, () => togglePassword(row.id))
|
|
1628
|
+
),
|
|
1629
|
+
route.protocol === "socks5" ? t.passwordHint : t.passwordHintProxy,
|
|
1630
|
+
false,
|
|
1631
|
+
true
|
|
1298
1632
|
)
|
|
1299
1633
|
];
|
|
1300
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 };
|
|
1301
|
-
|
|
1635
|
+
const cardSection = h(
|
|
1302
1636
|
"section",
|
|
1303
1637
|
{
|
|
1304
1638
|
className: rejected ? import_client.default.cardRejected : route.enabled ? import_client.default.cardActive : import_client.default.card,
|
|
@@ -1364,7 +1698,7 @@ function renderPage(ctx) {
|
|
|
1364
1698
|
{ key: `${row.id}:inherit`, style: S.inheritNote },
|
|
1365
1699
|
`${t.inheritingDefault}${defaultOrigin}`
|
|
1366
1700
|
) : null,
|
|
1367
|
-
...useDefault ? [] : endpointFields,
|
|
1701
|
+
...useDefault ? [] : [h("div", { className: import_client.default.formGrid, style: S.formGrid, key: `${row.id}:form-grid` }, ...endpointFields)],
|
|
1368
1702
|
// The self-check is offered whenever there is something to check: an
|
|
1369
1703
|
// enabled route (the Host's table carries it, and a rejected one still
|
|
1370
1704
|
// reports WHY), or a disabled one whose endpoint is already complete —
|
|
@@ -1405,7 +1739,12 @@ function renderPage(ctx) {
|
|
|
1405
1739
|
{ key: "status" },
|
|
1406
1740
|
`HTTP ${result.status}`
|
|
1407
1741
|
) : null,
|
|
1408
|
-
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
|
+
),
|
|
1409
1748
|
result.direct === true ? h("span", { key: "direct" }, t.directLabel) : null,
|
|
1410
1749
|
result.cached === true ? h("span", { key: "cached" }, t.cachedLabel) : null,
|
|
1411
1750
|
result.target === void 0 ? null : h(
|
|
@@ -1416,13 +1755,22 @@ function renderPage(ctx) {
|
|
|
1416
1755
|
flexBasis: "100%",
|
|
1417
1756
|
fontSize: "11px",
|
|
1418
1757
|
color: "var(--dsw-alias-label-secondary)",
|
|
1419
|
-
wordBreak: "break-all"
|
|
1758
|
+
wordBreak: "break-all",
|
|
1759
|
+
display: "inline-flex",
|
|
1760
|
+
alignItems: "center",
|
|
1761
|
+
gap: "3px"
|
|
1420
1762
|
}
|
|
1421
1763
|
},
|
|
1422
|
-
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}
|
|
1764
|
+
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,
|
|
1765
|
+
copyButton(`${row.id}:target`, result.target, t.copy)
|
|
1423
1766
|
)
|
|
1424
1767
|
] : [
|
|
1425
|
-
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
|
+
),
|
|
1426
1774
|
typeof result.status === "number" ? h("span", { key: "status" }, `HTTP ${result.status}`) : null,
|
|
1427
1775
|
result.target === void 0 ? null : h(
|
|
1428
1776
|
"span",
|
|
@@ -1432,10 +1780,14 @@ function renderPage(ctx) {
|
|
|
1432
1780
|
flexBasis: "100%",
|
|
1433
1781
|
fontSize: "11px",
|
|
1434
1782
|
color: "var(--dsw-alias-label-secondary)",
|
|
1435
|
-
wordBreak: "break-all"
|
|
1783
|
+
wordBreak: "break-all",
|
|
1784
|
+
display: "inline-flex",
|
|
1785
|
+
alignItems: "center",
|
|
1786
|
+
gap: "3px"
|
|
1436
1787
|
}
|
|
1437
1788
|
},
|
|
1438
|
-
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}
|
|
1789
|
+
`${t.testTargetLabel}${result.target}${targetSourceSuffix(result, t)}`,
|
|
1790
|
+
copyButton(`${row.id}:target`, result.target, t.copy)
|
|
1439
1791
|
)
|
|
1440
1792
|
]
|
|
1441
1793
|
) : null,
|
|
@@ -1498,6 +1850,58 @@ function renderPage(ctx) {
|
|
|
1498
1850
|
)
|
|
1499
1851
|
)
|
|
1500
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;
|
|
1501
1905
|
});
|
|
1502
1906
|
return h(
|
|
1503
1907
|
"div",
|
|
@@ -1538,6 +1942,7 @@ function renderPage(ctx) {
|
|
|
1538
1942
|
defaultBlock,
|
|
1539
1943
|
globalBlock,
|
|
1540
1944
|
catalogueNotice,
|
|
1945
|
+
chipRow,
|
|
1541
1946
|
filterRow,
|
|
1542
1947
|
...body,
|
|
1543
1948
|
h(
|
|
@@ -1567,6 +1972,7 @@ function renderPage(ctx) {
|
|
|
1567
1972
|
{ className: import_client.default.diagList, style: { margin: "6px 0 0", paddingLeft: "18px" } },
|
|
1568
1973
|
...problemCount === 0 && diagnostics.length === 0 && savedNote === void 0 ? [h("li", { key: "none" }, t.diagPending)] : [
|
|
1569
1974
|
...problemLines,
|
|
1975
|
+
...catalogueMismatchLine === void 0 ? [] : [catalogueMismatchLine],
|
|
1570
1976
|
...savedNote === void 0 ? [] : [h("li", { key: "saved" }, savedNote)],
|
|
1571
1977
|
...diagnostics.map((line, index) => h("li", { key: `d${index}` }, line))
|
|
1572
1978
|
]
|
|
@@ -1588,6 +1994,10 @@ var EN = {
|
|
|
1588
1994
|
defaultMissing: "The default proxy configuration is incomplete, so this provider is not proxied: ",
|
|
1589
1995
|
filterLabel: "Filter",
|
|
1590
1996
|
filterPlaceholder: "Filter by name or id\u2026",
|
|
1997
|
+
filterStatusAll: "All",
|
|
1998
|
+
filterStatusProxied: "Proxied",
|
|
1999
|
+
filterStatusDirect: "Direct",
|
|
2000
|
+
filterStatusRejected: "Rejected",
|
|
1591
2001
|
noMatch: "No provider matches the filter.",
|
|
1592
2002
|
setAsDefault: "Set as the default proxy",
|
|
1593
2003
|
applyDefaultAll: "Use the default proxy for all providers",
|
|
@@ -1596,7 +2006,10 @@ var EN = {
|
|
|
1596
2006
|
port: "Port",
|
|
1597
2007
|
username: "Username",
|
|
1598
2008
|
password: "Password",
|
|
1599
|
-
|
|
2009
|
+
showPassword: "Show",
|
|
2010
|
+
hidePassword: "Hide",
|
|
2011
|
+
confirmPromoteToDefault: "The default proxy is already in use by one or more providers. Replace it with this card's endpoint?",
|
|
2012
|
+
hostHint: "IP or domain only; paste full URL supported",
|
|
1600
2013
|
passwordHint: "Sent to the SOCKS5 proxy for authentication; stored with this setting.",
|
|
1601
2014
|
passwordHintProxy: "Sent to the proxy as an authentication password; stored with this setting.",
|
|
1602
2015
|
hitCountPrefix: "",
|
|
@@ -1609,6 +2022,12 @@ var EN = {
|
|
|
1609
2022
|
minutesAgo: " min ago",
|
|
1610
2023
|
hoursAgo: " h ago",
|
|
1611
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",
|
|
1612
2031
|
testButton: "Test",
|
|
1613
2032
|
testRunning: "Testing\u2026",
|
|
1614
2033
|
testDisabledNote: "Not enabled \u2014 test only: ",
|
|
@@ -1647,8 +2066,12 @@ var EN = {
|
|
|
1647
2066
|
notConfigured: "not configured",
|
|
1648
2067
|
diagnostics: "Connection diagnostics",
|
|
1649
2068
|
diagPending: "(collecting\u2026)",
|
|
2069
|
+
catalogueMismatch: "Saved but not listed by the Host catalogue: ",
|
|
2070
|
+
catalogueMismatchSuffix: ". Their proxy settings are kept.",
|
|
1650
2071
|
saveFailedPrefix: "Save failed: ",
|
|
1651
|
-
close: "Close"
|
|
2072
|
+
close: "Close",
|
|
2073
|
+
copy: "Copy",
|
|
2074
|
+
copied: "Copied"
|
|
1652
2075
|
};
|
|
1653
2076
|
var ZH = {
|
|
1654
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",
|
|
@@ -1664,6 +2087,10 @@ var ZH = {
|
|
|
1664
2087
|
defaultMissing: "\u9876\u5C42\u9ED8\u8BA4\u4EE3\u7406\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u8BE5 provider \u4E0D\u4F1A\u8D70\u4EE3\u7406\uFF1A",
|
|
1665
2088
|
filterLabel: "\u8FC7\u6EE4",
|
|
1666
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",
|
|
1667
2094
|
noMatch: "\u6CA1\u6709\u5339\u914D\u7684 provider\u3002",
|
|
1668
2095
|
setAsDefault: "\u8BBE\u4E3A\u9ED8\u8BA4\u4EE3\u7406",
|
|
1669
2096
|
applyDefaultAll: "\u6240\u6709 provider \u4F7F\u7528\u9ED8\u8BA4\u4EE3\u7406",
|
|
@@ -1672,7 +2099,10 @@ var ZH = {
|
|
|
1672
2099
|
port: "\u7AEF\u53E3",
|
|
1673
2100
|
username: "\u7528\u6237\u540D",
|
|
1674
2101
|
password: "\u5BC6\u7801",
|
|
1675
|
-
|
|
2102
|
+
showPassword: "\u663E\u793A",
|
|
2103
|
+
hidePassword: "\u9690\u85CF",
|
|
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",
|
|
2105
|
+
hostHint: "\u4EC5\u9650 IP \u6216\u57DF\u540D\uFF0C\u652F\u6301\u7C98\u8D34\u5B8C\u6574\u4EE3\u7406 URL",
|
|
1676
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",
|
|
1677
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",
|
|
1678
2108
|
hitCountPrefix: "\u5DF2\u4EE3\u7406 ",
|
|
@@ -1685,6 +2115,12 @@ var ZH = {
|
|
|
1685
2115
|
minutesAgo: " \u5206\u949F\u524D",
|
|
1686
2116
|
hoursAgo: " \u5C0F\u65F6\u524D",
|
|
1687
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",
|
|
1688
2124
|
testButton: "\u6D4B\u8BD5",
|
|
1689
2125
|
testRunning: "\u6D4B\u8BD5\u4E2D\u2026",
|
|
1690
2126
|
testDisabledNote: "\u672A\u542F\u7528\uFF0C\u4EC5\u6D4B\u8BD5\uFF1A",
|
|
@@ -1723,8 +2159,12 @@ var ZH = {
|
|
|
1723
2159
|
notConfigured: "\u672A\u914D\u7F6E",
|
|
1724
2160
|
diagnostics: "\u8FDE\u63A5\u8BCA\u65AD",
|
|
1725
2161
|
diagPending: "\uFF08\u6B63\u5728\u6536\u96C6\u2026\uFF09",
|
|
2162
|
+
catalogueMismatch: "\u5DF2\u4FDD\u5B58\u4F46\u672A\u51FA\u73B0\u5728 Host \u76EE\u5F55\u4E2D\u7684 provider\uFF1A",
|
|
2163
|
+
catalogueMismatchSuffix: "\u3002\u4EE3\u7406\u914D\u7F6E\u4ECD\u4F1A\u4FDD\u7559\u3002",
|
|
1726
2164
|
saveFailedPrefix: "\u4FDD\u5B58\u5931\u8D25\uFF1A",
|
|
1727
|
-
close: "\u5173\u95ED"
|
|
2165
|
+
close: "\u5173\u95ED",
|
|
2166
|
+
copy: "\u590D\u5236",
|
|
2167
|
+
copied: "\u5DF2\u590D\u5236"
|
|
1728
2168
|
};
|
|
1729
2169
|
function stringsFor(ctx) {
|
|
1730
2170
|
const language = localeOf(ctx);
|