dsh-deeppilot 0.9.11 → 0.9.13
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/COMPATIBILITY.md +69 -8
- package/README.md +14 -6
- package/README.zh-CN.md +9 -5
- package/bin/SHA256SUMS +6 -6
- package/bin/darwin-amd64/dsh-deeppilot-tunnel +0 -0
- package/bin/darwin-arm64/dsh-deeppilot-tunnel +0 -0
- package/bin/linux-amd64/dsh-deeppilot-tunnel +0 -0
- package/bin/linux-arm64/dsh-deeppilot-tunnel +0 -0
- package/bin/windows-amd64/dsh-deeppilot-tunnel.exe +0 -0
- package/bin/windows-arm64/dsh-deeppilot-tunnel.exe +0 -0
- package/docs/DSH_022_FEATURES.md +43 -0
- package/docs/DSH_RELEASE_MEMORY.md +288 -11
- package/docs/NPM_PUBLISHING.md +20 -0
- package/lib/client.js +436 -250
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +76 -2
- package/lib/index.js +1147 -30
- package/lib/index.js.map +1 -1
- package/package.json +18 -14
package/lib/client.js
CHANGED
|
@@ -46,6 +46,30 @@ window.__ModuleLoader__.load({
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
//#endregion
|
|
49
|
+
//#region src/tailscale-version.ts
|
|
50
|
+
/**
|
|
51
|
+
* 内嵌 helper 上报的 tailscale.com 模块版本。
|
|
52
|
+
*
|
|
53
|
+
* 版本的唯一来源是 helper 启动事件(`helper/main.go` 读 Go 构建信息里的
|
|
54
|
+
* `tailscale.com` 依赖版本),不是 go.mod、也不是插件常量:用户可能通过
|
|
55
|
+
* `remote.helperPath` 换成自己编译的 helper,界面必须显示实际在跑的那一个。
|
|
56
|
+
*
|
|
57
|
+
* 两条边界都要守卫:
|
|
58
|
+
* - 宿主侧 `parseHelperEvent` 把 helper 的 stdout 当成不可信输入,格式不对
|
|
59
|
+
* 就丢弃,避免把任意文本渲染进设置页;
|
|
60
|
+
* - 设置页侧 `reportSchema` 同样校验 Host RPC 返回值,旧 Host 不带该字段
|
|
61
|
+
* 时保持 undefined(页面显示「未获取」),不当作错误。
|
|
62
|
+
*
|
|
63
|
+
* 接受 Go 模块版本形态:`v1.104.2`、`v1.104.2-pre.1`、
|
|
64
|
+
* `v0.0.0-20260101000000-abcdef123456`。长度上限防止异常输入撑爆界面。
|
|
65
|
+
*/
|
|
66
|
+
const TAILSCALE_VERSION_PATTERN = /^v?\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]{1,64})?$/;
|
|
67
|
+
const MAX_TAILSCALE_VERSION_LENGTH = 80;
|
|
68
|
+
/** 判断外部输入是否是合法的 Tailscale 模块版本字符串。 */
|
|
69
|
+
function isTailscaleVersion(value) {
|
|
70
|
+
return typeof value === "string" && value.length <= MAX_TAILSCALE_VERSION_LENGTH && TAILSCALE_VERSION_PATTERN.test(value);
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
49
73
|
//#region src/device-auth.ts
|
|
50
74
|
const DEVICE_SCOPES = [
|
|
51
75
|
"sessions.read",
|
|
@@ -144,15 +168,18 @@ window.__ModuleLoader__.load({
|
|
|
144
168
|
const publicURL = s.publicURL;
|
|
145
169
|
const authURL = s.authURL;
|
|
146
170
|
const message = s.message;
|
|
171
|
+
const tailscaleVersion = s.tailscaleVersion;
|
|
147
172
|
if (publicURL !== void 0 && typeof publicURL !== "string") reject("remote.publicURL");
|
|
148
173
|
if (authURL !== void 0 && typeof authURL !== "string") reject("remote.authURL");
|
|
149
174
|
if (message !== void 0 && typeof message !== "string") reject("remote.message");
|
|
175
|
+
if (tailscaleVersion !== void 0 && !isTailscaleVersion(tailscaleVersion)) reject("remote.tailscaleVersion");
|
|
150
176
|
return {
|
|
151
177
|
provider,
|
|
152
178
|
phase,
|
|
153
179
|
...typeof publicURL === "string" ? { publicURL } : {},
|
|
154
180
|
...typeof authURL === "string" ? { authURL } : {},
|
|
155
181
|
...typeof message === "string" ? { message } : {},
|
|
182
|
+
...typeof tailscaleVersion === "string" ? { tailscaleVersion } : {},
|
|
156
183
|
updatedAt: int(s, "updatedAt", "remote.updatedAt")
|
|
157
184
|
};
|
|
158
185
|
}
|
|
@@ -555,6 +582,13 @@ window.__ModuleLoader__.load({
|
|
|
555
582
|
"phase.unavailable": "远程 helper 不可用",
|
|
556
583
|
"phase.stopped": "已停止",
|
|
557
584
|
"phase.unknown": "状态未知",
|
|
585
|
+
"channel.state.disabled": "未启用",
|
|
586
|
+
"channel.state.starting": "正在启动",
|
|
587
|
+
"channel.state.login_required": "待授权",
|
|
588
|
+
"channel.state.online": "已就绪",
|
|
589
|
+
"channel.state.error": "失败",
|
|
590
|
+
"channel.state.unavailable": "不可用",
|
|
591
|
+
"channel.state.stopped": "已停止",
|
|
558
592
|
"panel.activeConnections": "当前连接",
|
|
559
593
|
"panel.identity": "设备身份认证",
|
|
560
594
|
"panel.identityReady": "v2 已就绪",
|
|
@@ -582,6 +616,7 @@ window.__ModuleLoader__.load({
|
|
|
582
616
|
"pair.kind.lan": "内网",
|
|
583
617
|
"pair.noAddress": "没有可用地址",
|
|
584
618
|
"pair.noAddressHelp": "没有可用的局域网或远程入口。请确认局域网连接已启动,或启用远程连接。",
|
|
619
|
+
"pair.disabledHelp": "DeepPilot 连接已关闭。先在上方开启连接,再添加手机。",
|
|
585
620
|
"pair.qrAlt": "DeepPilot 配对二维码",
|
|
586
621
|
"pair.qrShow": "显示二维码",
|
|
587
622
|
"pair.qrHide": "隐藏二维码",
|
|
@@ -596,6 +631,8 @@ window.__ModuleLoader__.load({
|
|
|
596
631
|
"advanced.summary": "高级信息",
|
|
597
632
|
"advanced.protocolVersion": "协议版本",
|
|
598
633
|
"advanced.serverVersion": "服务器版本",
|
|
634
|
+
"advanced.tailscaleVersion": "Tailscale 版本",
|
|
635
|
+
"advanced.tailscaleVersionUnknown": "未获取",
|
|
599
636
|
"advanced.tokenPath": "Token 路径",
|
|
600
637
|
"advanced.identityPath": "设备注册表路径",
|
|
601
638
|
"advanced.bufferMax": "重放缓冲上限",
|
|
@@ -798,6 +835,13 @@ window.__ModuleLoader__.load({
|
|
|
798
835
|
"phase.unavailable": "Remote helper unavailable",
|
|
799
836
|
"phase.stopped": "Stopped",
|
|
800
837
|
"phase.unknown": "Status unknown",
|
|
838
|
+
"channel.state.disabled": "Off",
|
|
839
|
+
"channel.state.starting": "Starting",
|
|
840
|
+
"channel.state.login_required": "Needs sign-in",
|
|
841
|
+
"channel.state.online": "Ready",
|
|
842
|
+
"channel.state.error": "Failed",
|
|
843
|
+
"channel.state.unavailable": "Unavailable",
|
|
844
|
+
"channel.state.stopped": "Stopped",
|
|
801
845
|
"panel.activeConnections": "Active connections",
|
|
802
846
|
"panel.identity": "Device authentication",
|
|
803
847
|
"panel.identityReady": "v2 ready",
|
|
@@ -825,6 +869,7 @@ window.__ModuleLoader__.load({
|
|
|
825
869
|
"pair.kind.lan": "LAN",
|
|
826
870
|
"pair.noAddress": "No address available",
|
|
827
871
|
"pair.noAddressHelp": "No LAN or remote endpoint is available. Make sure LAN is running or enable remote access.",
|
|
872
|
+
"pair.disabledHelp": "DeepPilot is turned off. Turn the connection on above before adding a phone.",
|
|
828
873
|
"pair.qrAlt": "DeepPilot pairing QR code",
|
|
829
874
|
"pair.qrShow": "Show QR code",
|
|
830
875
|
"pair.qrHide": "Hide QR code",
|
|
@@ -839,6 +884,8 @@ window.__ModuleLoader__.load({
|
|
|
839
884
|
"advanced.summary": "Advanced info",
|
|
840
885
|
"advanced.protocolVersion": "Protocol version",
|
|
841
886
|
"advanced.serverVersion": "Server version",
|
|
887
|
+
"advanced.tailscaleVersion": "Tailscale version",
|
|
888
|
+
"advanced.tailscaleVersionUnknown": "Not reported",
|
|
842
889
|
"advanced.tokenPath": "Token path",
|
|
843
890
|
"advanced.identityPath": "Device registry path",
|
|
844
891
|
"advanced.bufferMax": "Replay buffer cap",
|
|
@@ -1021,155 +1068,169 @@ window.__ModuleLoader__.load({
|
|
|
1021
1068
|
}
|
|
1022
1069
|
//#endregion
|
|
1023
1070
|
//#region src/client/styles.ts
|
|
1071
|
+
const EASE = "cubic-bezier(0.22,1,0.36,1)";
|
|
1024
1072
|
const CSS = [
|
|
1025
|
-
".pbb-section{max-width:760px;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:
|
|
1073
|
+
".pbb-section{container:pbb/inline-size;max-width:760px;color:var(--dsw-alias-label-primary);font-size:14px;line-height:1.5;display:flex;flex-direction:column;gap:16px}",
|
|
1074
|
+
".pbb-section>*{animation:pbb-cardIn 160ms " + EASE + " backwards}",
|
|
1075
|
+
".pbb-section>*:nth-child(2){animation-delay:24ms}",
|
|
1076
|
+
".pbb-section>*:nth-child(3){animation-delay:48ms}",
|
|
1077
|
+
".pbb-section>*:nth-child(4){animation-delay:72ms}",
|
|
1078
|
+
".pbb-section>*:nth-child(5){animation-delay:96ms}",
|
|
1079
|
+
".pbb-section>*:nth-child(6){animation-delay:120ms}",
|
|
1080
|
+
".pbb-section>*:nth-child(7){animation-delay:144ms}",
|
|
1081
|
+
".pbb-section>*:nth-child(n+8){animation-delay:144ms}",
|
|
1082
|
+
"@keyframes pbb-cardIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}",
|
|
1026
1083
|
".pbb-pageHeader{display:flex;align-items:flex-start;gap:16px;padding:2px 2px 4px}",
|
|
1027
1084
|
".pbb-title{margin:0;font-size:18px;font-weight:600;letter-spacing:-.01em}",
|
|
1028
|
-
".pbb-intro{color:var(--dsw-alias-label-
|
|
1029
|
-
".pbb-refresh{font:inherit;font-size:12px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:none;border:none;padding:3px 0;margin-left:auto;white-space:nowrap}",
|
|
1030
|
-
".pbb-refresh:
|
|
1085
|
+
".pbb-intro{color:var(--dsw-alias-label-secondary);font-size:14px;line-height:1.5;margin:4px 0 0;max-width:600px}",
|
|
1086
|
+
".pbb-refresh{font:inherit;font-size:12px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:none;border:none;padding:3px 0;margin-left:auto;white-space:nowrap;transition:transform 160ms " + EASE + ",color 160ms " + EASE + "}",
|
|
1087
|
+
".pbb-refresh:active{transform:scale(0.97)}",
|
|
1031
1088
|
".pbb-refresh:disabled{cursor:default;opacity:.5}",
|
|
1032
|
-
".pbb-
|
|
1089
|
+
".pbb-statusStrip{display:grid;grid-template-columns:repeat(4,1fr);background:var(--dsw-alias-settings-card-fill,var(--dsw-alias-bg-layer-2));border:.5px solid var(--dsw-alias-settings-card-stroke,var(--dsw-alias-border-l4));border-radius:var(--dsw-radius-xl,20px);overflow:hidden}",
|
|
1090
|
+
".pbb-statusCell{padding:14px 16px;min-width:0}",
|
|
1091
|
+
".pbb-statusCell+.pbb-statusCell{border-left:1px solid var(--dsw-alias-border-l2)}",
|
|
1092
|
+
".pbb-statusLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}",
|
|
1093
|
+
".pbb-statusValue{margin-top:2px;font-size:16px;font-weight:600;line-height:22px;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}",
|
|
1094
|
+
".pbb-statusValue .pbb-dot{margin-right:6px}",
|
|
1095
|
+
".pbb-statusSub{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}",
|
|
1096
|
+
".pbb-card{border:.5px solid var(--dsw-alias-settings-card-stroke,var(--dsw-alias-border-l4));background:var(--dsw-alias-settings-card-fill,var(--dsw-alias-bg-layer-2));border-radius:var(--dsw-radius-xl,20px);overflow:hidden}",
|
|
1033
1097
|
".pbb-cardHeader{display:flex;align-items:flex-start;gap:16px;padding:15px 18px 13px}",
|
|
1034
1098
|
".pbb-cardHeader>div:first-child{min-width:0;flex:1}",
|
|
1035
|
-
".pbb-cardTitle{margin:0;font-size:
|
|
1036
|
-
".pbb-cardDescription{margin:3px 0 0;color:var(--dsw-alias-label-tertiary);font-size:
|
|
1037
|
-
".pbb-
|
|
1099
|
+
".pbb-cardTitle{margin:0;font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary)}",
|
|
1100
|
+
".pbb-cardDescription{margin:3px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}",
|
|
1101
|
+
".pbb-cardHead{display:flex;align-items:center;gap:10px;width:100%;min-height:52px;padding:0 18px;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer;transition:background-color 160ms " + EASE + "}",
|
|
1102
|
+
".pbb-cardHead:active{background:var(--dsw-alias-bg-module-platform)}",
|
|
1103
|
+
".pbb-cardSummary{flex:1;min-width:0;text-align:right;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}",
|
|
1104
|
+
".pbb-chev{flex:none;display:inline-flex;align-items:center;color:var(--dsw-alias-label-tertiary);transition:transform 160ms " + EASE + "}",
|
|
1105
|
+
".pbb-chevIcon{display:block}",
|
|
1106
|
+
".pbb-cardHead[aria-expanded=\"true\"] .pbb-chev,.pbb-expand[aria-expanded=\"true\"] .pbb-chev{transform:rotate(90deg)}",
|
|
1107
|
+
".pbb-cardBody{display:flex;flex-direction:column;gap:12px;padding:4px 18px 16px}",
|
|
1108
|
+
".pbb-pairingBody{display:flex;flex-direction:column;gap:10px;padding:0 18px 15px}",
|
|
1038
1109
|
".pbb-sectionIntro{padding-bottom:2px}",
|
|
1110
|
+
".pbb-fold{display:grid;grid-template-rows:1fr;transition:grid-template-rows 240ms " + EASE + ",opacity 200ms " + EASE + ";opacity:1}",
|
|
1111
|
+
".pbb-foldClosed{grid-template-rows:0fr;opacity:0}",
|
|
1112
|
+
".pbb-fold>div{overflow:hidden;min-height:0}",
|
|
1039
1113
|
".pbb-row{display:flex;align-items:center;gap:8px}",
|
|
1040
1114
|
".pbb-label{flex:1;font-size:12px;font-weight:500;color:var(--dsw-alias-label-primary);min-width:0}",
|
|
1041
1115
|
".pbb-value{font-size:12px;color:var(--dsw-alias-label-secondary);word-break:break-all;text-align:right}",
|
|
1042
|
-
".pbb-badge,.pbb-countBadge{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:2px 8px;font-size:
|
|
1116
|
+
".pbb-badge,.pbb-countBadge{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:2px 8px;font-size:12px;font-weight:500;white-space:nowrap}",
|
|
1117
|
+
".pbb-badgeOk{background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#22a06b) 12%,transparent);color:var(--dsw-alias-state-success-primary,#22a06b)}",
|
|
1118
|
+
".pbb-badgeWarn{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 14%,transparent);color:var(--dsw-alias-state-warn-primary,#f59e0b)}",
|
|
1043
1119
|
".pbb-countBadge{min-width:24px;text-align:center}",
|
|
1044
|
-
".pbb-statusBadge{display:inline-flex;align-items:center;gap:6px;flex:none;padding:3px 8px;border-radius:999px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);font-size:
|
|
1120
|
+
".pbb-statusBadge{display:inline-flex;align-items:center;gap:6px;flex:none;padding:3px 8px;border-radius:999px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;white-space:nowrap}",
|
|
1045
1121
|
".pbb-ok{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-label-secondary));font-weight:500}",
|
|
1046
|
-
".pbb-bad{color:var(--dsw-alias-
|
|
1047
|
-
".pbb-diag{font-size:
|
|
1048
|
-
".pbb-diagBad{color:var(--dsw-alias-
|
|
1049
|
-
".pbb-empty{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.55;margin:0;padding:12px;border:1px dashed var(--dsw-alias-border-
|
|
1050
|
-
".pbb-
|
|
1051
|
-
".pbb-
|
|
1052
|
-
".pbb-
|
|
1053
|
-
".pbb-action{font:inherit;font-size:12px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:none;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:5px 9px;line-height:1.2;white-space:nowrap}",
|
|
1054
|
-
".pbb-action:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}",
|
|
1122
|
+
".pbb-bad{color:var(--dsw-alias-state-error-primary);font-weight:500}",
|
|
1123
|
+
".pbb-diag{font-size:12px;color:var(--dsw-alias-label-tertiary);margin:0;line-height:1.5;overflow-wrap:anywhere}",
|
|
1124
|
+
".pbb-diagBad{color:var(--dsw-alias-state-error-primary)}",
|
|
1125
|
+
".pbb-empty{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.55;margin:0;padding:12px;border:1px dashed var(--dsw-alias-border-l3);border-radius:8px}",
|
|
1126
|
+
".pbb-token{max-width:100%;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--dsw-alias-label-secondary);word-break:break-all}",
|
|
1127
|
+
".pbb-action{font:inherit;font-size:12px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:none;border:1px solid var(--dsw-alias-border-l3);border-radius:7px;padding:5px 9px;line-height:1.2;white-space:nowrap;transition:transform 160ms " + EASE + ",color 160ms " + EASE + ",background-color 160ms " + EASE + ",border-color 160ms " + EASE + "}",
|
|
1128
|
+
".pbb-action:active{transform:scale(0.97)}",
|
|
1055
1129
|
".pbb-action:disabled{cursor:default;opacity:.5}",
|
|
1056
|
-
".pbb-buttonPrimary{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-
|
|
1057
|
-
".pbb-
|
|
1058
|
-
".pbb-
|
|
1059
|
-
".pbb-actionDangerGhost{color:#dc2626;border-color:rgba(220,38,38,.38);background:transparent;line-height:1.35;padding:4px 9px;transition:color .15s ease,background-color .15s ease,border-color .15s ease,transform .1s ease}",
|
|
1060
|
-
".pbb-actionDangerGhost:hover:not(:disabled){color:#b91c1c;background:rgba(220,38,38,.09);border-color:rgba(185,28,28,.5)}",
|
|
1061
|
-
".pbb-actionDangerGhost:active:not(:disabled){transform:translateY(1px)}",
|
|
1062
|
-
".pbb-actionDangerGhost:focus-visible{outline:2px solid rgba(220,38,38,.32);outline-offset:1px}",
|
|
1130
|
+
".pbb-buttonPrimary{font-size:13px;padding:6px 12px;color:var(--dsw-alias-label-primary-foreground);border-color:transparent;background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-brand-primary))}",
|
|
1131
|
+
".pbb-actionDangerGhost{color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 38%,transparent);background:transparent;line-height:1.35;padding:4px 9px}",
|
|
1132
|
+
".pbb-actionDangerGhost:active{transform:scale(0.97)}",
|
|
1063
1133
|
".pbb-actionDangerGhost:disabled{cursor:default;opacity:.62}",
|
|
1064
1134
|
".pbb-actionIcon{flex:none;display:inline-block;vertical-align:-2px;margin-right:5px;pointer-events:none}",
|
|
1065
1135
|
".pbb-actionBusy{display:inline-flex;align-items:center;gap:6px}",
|
|
1066
|
-
".pbb-actionBusy::before{content:\"\";width:9px;height:9px;border-radius:50%;border:1.5px solid
|
|
1136
|
+
".pbb-actionBusy::before{content:\"\";width:9px;height:9px;border-radius:50%;border:1.5px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 35%,transparent);border-top-color:currentColor;animation:pbb-spin .7s linear infinite}",
|
|
1067
1137
|
"@keyframes pbb-spin{to{transform:rotate(360deg)}}",
|
|
1068
|
-
".pbb-masterRow{display:flex;align-items:center;gap:14px
|
|
1138
|
+
".pbb-masterRow{display:flex;align-items:center;gap:14px}",
|
|
1069
1139
|
".pbb-switchText{display:flex;flex-direction:column;gap:3px;flex:1;min-width:0}",
|
|
1070
|
-
".pbb-switchTitle{font-size:
|
|
1071
|
-
".pbb-switchDesc{font-size:
|
|
1072
|
-
".pbb-switch{appearance:none;-webkit-appearance:none;width:
|
|
1073
|
-
".pbb-switch::after{content:\"\";position:absolute;top:2px;left:2px;width:
|
|
1074
|
-
".pbb-switchOn{background:var(--dsw-alias-
|
|
1075
|
-
".pbb-switchOn::after{transform:translateX(
|
|
1140
|
+
".pbb-switchTitle{font-size:14px;font-weight:500;color:var(--dsw-alias-label-primary)}",
|
|
1141
|
+
".pbb-switchDesc{font-size:12px;color:var(--dsw-alias-label-tertiary);line-height:1.45}",
|
|
1142
|
+
".pbb-switch{appearance:none;-webkit-appearance:none;width:40px;height:24px;border-radius:999px;background:color-mix(in srgb,var(--dsw-alias-label-primary) 20%,transparent);border:1px solid transparent;position:relative;cursor:pointer;padding:0;flex:none;transition:background-color 160ms " + EASE + ",border-color 160ms " + EASE + ",transform 160ms " + EASE + "}",
|
|
1143
|
+
".pbb-switch::after{content:\"\";position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.24);transition:transform 160ms " + EASE + ",background-color 160ms " + EASE + "}",
|
|
1144
|
+
".pbb-switchOn{background:var(--dsw-alias-brand-primary)}",
|
|
1145
|
+
".pbb-switchOn::after{transform:translateX(16px);background:var(--dsw-alias-label-primary-foreground)}",
|
|
1146
|
+
".pbb-switch:active{transform:scale(0.97)}",
|
|
1076
1147
|
".pbb-switch:disabled{opacity:.5;cursor:default}",
|
|
1077
|
-
".pbb-switch:focus-visible,.pbb-action:focus-visible,.pbb-targetButton:focus-visible{outline:2px solid color
|
|
1078
|
-
".pbb-
|
|
1079
|
-
".pbb-connectionTile{min-width:0;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-module-platform);padding:11px 12px;display:flex;flex-direction:column;gap:5px}",
|
|
1080
|
-
".pbb-connectionTileHeader{display:flex;align-items:center;gap:10px}",
|
|
1081
|
-
".pbb-dotRow{display:flex;align-items:center;gap:7px;flex:1;min-width:0}",
|
|
1082
|
-
".pbb-dot{width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-label-tertiary);flex:none}",
|
|
1148
|
+
".pbb-switch:focus-visible,.pbb-action:focus-visible,.pbb-targetButton:focus-visible,.pbb-cardHead:focus-visible,.pbb-expand:focus-visible,.pbb-refresh:focus-visible,.pbb-numberInput:focus-visible,.pbb-deviceNameInput:focus-visible,.pbb-disclosure>summary:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}",
|
|
1149
|
+
".pbb-dot{display:inline-block;vertical-align:1px;width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-label-tertiary);flex:none}",
|
|
1083
1150
|
".pbb-dotOk{background:var(--dsw-alias-state-success-primary,#22a06b)}",
|
|
1084
|
-
".pbb-dotWarn{background:var(--dsw-alias-state-
|
|
1085
|
-
".pbb-dotBad{background:var(--dsw-alias-
|
|
1086
|
-
".pbb-
|
|
1087
|
-
".pbb-
|
|
1088
|
-
".pbb-
|
|
1089
|
-
".pbb-
|
|
1090
|
-
".pbb-
|
|
1091
|
-
".pbb-statLabel{font-size:11px;color:var(--dsw-alias-label-tertiary);flex:1}",
|
|
1092
|
-
".pbb-statValue{font-size:12px;color:var(--dsw-alias-label-primary);font-weight:600}",
|
|
1093
|
-
".pbb-inlineDetails,.pbb-help{border-top:1px solid var(--dsw-alias-border-l2)}",
|
|
1094
|
-
".pbb-inlineDetails>summary,.pbb-help>summary{cursor:pointer;color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500;user-select:none;list-style:none;display:flex;align-items:center;padding:12px 18px}",
|
|
1095
|
-
".pbb-inlineDetails>summary::-webkit-details-marker,.pbb-help>summary::-webkit-details-marker{display:none}",
|
|
1096
|
-
".pbb-inlineDetails>summary::after,.pbb-help>summary::after{content:\"›\";margin-left:auto;color:var(--dsw-alias-label-tertiary);font-size:16px;line-height:1;transform:rotate(90deg);transition:transform .15s ease}",
|
|
1097
|
-
".pbb-inlineDetails[open]>summary::after,.pbb-help[open]>summary::after{transform:rotate(-90deg)}",
|
|
1098
|
-
".pbb-inlineDetails[open]>summary,.pbb-help[open]>summary{color:var(--dsw-alias-label-secondary)}",
|
|
1099
|
-
".pbb-helpBody{display:flex;flex-direction:column;gap:14px;padding:2px 18px 15px}",
|
|
1100
|
-
".pbb-helpSection{display:flex;flex-direction:column;gap:6px}",
|
|
1101
|
-
".pbb-helpHeading{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary)}",
|
|
1102
|
-
".pbb-helpList{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:1.6}",
|
|
1103
|
-
".pbb-helpList li+li{margin-top:4px}",
|
|
1104
|
-
".pbb-helpText{margin:0;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:1.6}",
|
|
1105
|
-
".pbb-helpCode{display:block;margin:2px 0 0;padding:10px;overflow:auto;white-space:pre-wrap;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:11px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace}",
|
|
1106
|
-
".pbb-helpLink{color:var(--dsw-alias-label-secondary);text-decoration:underline;text-underline-offset:2px}",
|
|
1151
|
+
".pbb-dotWarn{background:var(--dsw-alias-state-warn-primary,#f59e0b)}",
|
|
1152
|
+
".pbb-dotBad{background:var(--dsw-alias-state-error-primary)}",
|
|
1153
|
+
".pbb-switchTitle .pbb-dot{margin-right:6px;vertical-align:1px}",
|
|
1154
|
+
".pbb-channel{border-top:1px solid var(--dsw-alias-border-l2);padding-top:12px;display:flex;flex-direction:column;gap:10px}",
|
|
1155
|
+
".pbb-expand{border:0;background:none;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;cursor:pointer;padding:0;display:flex;align-items:center;gap:6px;align-self:flex-start;transition:color 160ms " + EASE + ",transform 160ms " + EASE + "}",
|
|
1156
|
+
".pbb-expand:active{transform:scale(0.97)}",
|
|
1157
|
+
".pbb-channelBody{display:flex;flex-direction:column;gap:12px;padding:2px 0 0 14px}",
|
|
1107
1158
|
".pbb-limitRow{display:flex;align-items:center;gap:12px;padding:10px 0;border-top:1px solid var(--dsw-alias-border-l2)}",
|
|
1108
1159
|
".pbb-limitRow:first-child{border-top:0;padding-top:2px}",
|
|
1109
1160
|
".pbb-limitControl{display:flex;align-items:center;gap:8px;flex:none}",
|
|
1110
|
-
".pbb-numberInput{width:72px;box-sizing:border-box;border
|
|
1111
|
-
".pbb-numberInput:focus{outline:2px solid var(--dsw-alias-state-
|
|
1161
|
+
".pbb-numberInput{width:72px;box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:7px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;padding:6px 8px}",
|
|
1162
|
+
".pbb-numberInput:focus{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}",
|
|
1112
1163
|
".pbb-numberInput:disabled{opacity:.5}",
|
|
1113
|
-
".pbb-targetList{display:flex;flex-wrap:wrap;gap:
|
|
1114
|
-
".pbb-targetButton{font:inherit;font-size:
|
|
1115
|
-
".pbb-targetButton:
|
|
1164
|
+
".pbb-targetList{display:inline-flex;flex-wrap:wrap;gap:2px;background:var(--dsw-alias-bg-module-platform);border-radius:999px;padding:2px;align-self:flex-start}",
|
|
1165
|
+
".pbb-targetButton{font:inherit;font-size:12px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:none;border:0;border-radius:999px;padding:6px 9px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:transform 160ms " + EASE + ",color 160ms " + EASE + ",background-color 160ms " + EASE + ",box-shadow 160ms " + EASE + "}",
|
|
1166
|
+
".pbb-targetButton:active{transform:scale(0.97)}",
|
|
1116
1167
|
".pbb-targetButton:disabled{cursor:default;opacity:.5}",
|
|
1117
|
-
".pbb-targetSelected{color:var(--dsw-alias-label-primary);
|
|
1118
|
-
".pbb-qrPanel{display:
|
|
1119
|
-
".pbb-qrImage{width:224px;height:224px;max-width:100%;background:#fff;border-radius:
|
|
1120
|
-
".pbb-
|
|
1121
|
-
".pbb-
|
|
1122
|
-
".pbb-
|
|
1123
|
-
".pbb-
|
|
1124
|
-
".pbb-
|
|
1125
|
-
".pbb-
|
|
1126
|
-
".pbb-
|
|
1127
|
-
".pbb-
|
|
1128
|
-
".pbb-
|
|
1129
|
-
".pbb-
|
|
1130
|
-
".pbb-
|
|
1131
|
-
".pbb-
|
|
1132
|
-
".pbb-
|
|
1133
|
-
".pbb-
|
|
1134
|
-
".pbb-
|
|
1168
|
+
".pbb-targetSelected{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);box-shadow:0 1px 3px color-mix(in srgb,var(--dsw-alias-label-primary) 14%,transparent);font-weight:500}",
|
|
1169
|
+
".pbb-qrPanel{display:grid;grid-template-columns:224px 1fr;gap:20px;align-items:start;padding:14px 0 4px;border-top:1px solid var(--dsw-alias-border-l2)}",
|
|
1170
|
+
".pbb-qrImage{width:224px;height:224px;max-width:100%;background:#fff;border-radius:12px;padding:8px;box-sizing:border-box}",
|
|
1171
|
+
".pbb-countdown{margin-top:10px;display:flex;flex-direction:column;gap:6px}",
|
|
1172
|
+
".pbb-countdownBar{height:4px;border-radius:999px;background:var(--dsw-alias-bg-module-platform);overflow:hidden}",
|
|
1173
|
+
".pbb-countdownBar i{display:block;width:100%;height:100%;transform-origin:left center;background:var(--dsw-alias-state-business-primary,var(--dsw-alias-state-success-primary,#22a06b));border-radius:999px;transition:transform 1s linear}",
|
|
1174
|
+
".pbb-countdownText{font-size:12px;color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums}",
|
|
1175
|
+
".pbb-pairInfo{display:flex;flex-direction:column;gap:10px;min-width:0}",
|
|
1176
|
+
".pbb-pairCodeBlock{width:100%;display:flex;flex-direction:column;gap:6px}",
|
|
1177
|
+
".pbb-pairCodeLabel{font-size:12px;color:var(--dsw-alias-label-tertiary)}",
|
|
1178
|
+
".pbb-pairCodeRow{display:flex;align-items:center;gap:8px;flex-wrap:wrap}",
|
|
1179
|
+
".pbb-pairCode{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;line-height:1.4;letter-spacing:.03em;color:var(--dsw-alias-label-primary);word-break:break-all;user-select:all}",
|
|
1180
|
+
".pbb-qrHint{font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary);margin:0}",
|
|
1181
|
+
".pbb-rowAction{display:flex;gap:8px;margin-top:4px}",
|
|
1182
|
+
".pbb-resultRow{display:flex;align-items:flex-start;gap:6px}",
|
|
1183
|
+
".pbb-resultIcon{flex:none;display:inline-flex;margin-top:2px;color:var(--dsw-alias-state-success-primary)}",
|
|
1184
|
+
".pbb-resultIconBad{color:var(--dsw-alias-state-error-primary)}",
|
|
1185
|
+
".pbb-deviceList{display:flex;flex-direction:column}",
|
|
1186
|
+
".pbb-deviceRow{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:12px;row-gap:8px;padding:10px 0;border-top:1px solid var(--dsw-alias-border-l2)}",
|
|
1187
|
+
".pbb-deviceRow:first-child{border-top:0;padding-top:2px}",
|
|
1188
|
+
".pbb-deviceRow:last-child{padding-bottom:0}",
|
|
1189
|
+
".pbb-deviceRow>.pbb-deviceRenameForm,.pbb-deviceRow>.pbb-deviceConfirm{grid-column:1/-1}",
|
|
1190
|
+
".pbb-deviceMain{min-width:0;display:flex;flex-direction:column;gap:2px}",
|
|
1135
1191
|
".pbb-deviceNameRow{display:flex;align-items:center;gap:6px;min-width:0}",
|
|
1136
|
-
".pbb-deviceName{display:block;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
1137
|
-
".pbb-deviceMeta{display:flex;
|
|
1138
|
-
".pbb-deviceMeta
|
|
1139
|
-
".pbb-
|
|
1140
|
-
".pbb-
|
|
1141
|
-
".pbb-
|
|
1142
|
-
".pbb-
|
|
1143
|
-
".pbb-deviceNameInput
|
|
1192
|
+
".pbb-deviceName{display:block;font-size:14px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
1193
|
+
".pbb-deviceMeta{display:flex;flex-wrap:wrap;column-gap:6px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;min-width:0}",
|
|
1194
|
+
".pbb-deviceMeta>*+*::before{content:\"\\00B7\";margin-right:6px}",
|
|
1195
|
+
".pbb-deviceMeta code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
1196
|
+
".pbb-deviceActions{grid-row:1;grid-column:2;display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}",
|
|
1197
|
+
".pbb-deviceConfirm{display:flex;flex-direction:column;gap:8px}",
|
|
1198
|
+
".pbb-deviceRenameForm{display:flex;gap:8px;flex-wrap:wrap;min-width:0}",
|
|
1199
|
+
".pbb-deviceNameInput{flex:1;min-width:0;box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:7px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;padding:6px 8px}",
|
|
1200
|
+
".pbb-deviceNameInput:focus{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}",
|
|
1144
1201
|
".pbb-deviceNameInput:disabled{opacity:.5}",
|
|
1145
1202
|
".pbb-deviceRenameActions{display:flex;align-items:center;gap:5px;flex:none}",
|
|
1146
|
-
".pbb-
|
|
1147
|
-
".pbb-
|
|
1148
|
-
".pbb-
|
|
1149
|
-
".pbb-
|
|
1150
|
-
".pbb-
|
|
1151
|
-
".pbb-
|
|
1152
|
-
".pbb-
|
|
1153
|
-
".pbb-
|
|
1154
|
-
".pbb-disclosure{padding:0}",
|
|
1155
|
-
".pbb-disclosure>summary{list-style:none;display:flex;align-items:center;gap:12px;padding:13px 18px;cursor:pointer;color:var(--dsw-alias-label-primary)}",
|
|
1156
|
-
".pbb-disclosure>summary::-webkit-details-marker{display:none}",
|
|
1157
|
-
".pbb-disclosure>summary::after{content:\"›\";color:var(--dsw-alias-label-tertiary);font-size:17px;line-height:1;transform:rotate(90deg);transition:transform .15s ease}",
|
|
1158
|
-
".pbb-disclosure[open]>summary::after{transform:rotate(-90deg)}",
|
|
1159
|
-
".pbb-disclosureTitle{font-size:12px;font-weight:500;flex:1}",
|
|
1160
|
-
".pbb-disclosureMeta{font-size:11px;color:var(--dsw-alias-label-tertiary);max-width:46%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
1161
|
-
".pbb-disclosureBody{display:flex;flex-direction:column;gap:12px;padding:2px 18px 16px}",
|
|
1203
|
+
".pbb-helpBody{display:flex;flex-direction:column;gap:14px}",
|
|
1204
|
+
".pbb-helpSection{display:flex;flex-direction:column;gap:6px}",
|
|
1205
|
+
".pbb-helpHeading{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary)}",
|
|
1206
|
+
".pbb-helpList{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6}",
|
|
1207
|
+
".pbb-helpList li+li{margin-top:4px}",
|
|
1208
|
+
".pbb-helpText{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6}",
|
|
1209
|
+
".pbb-helpCode{display:block;margin:2px 0 0;padding:10px;overflow:auto;white-space:pre-wrap;border:1px solid var(--dsw-alias-border-l3);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:12px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace}",
|
|
1210
|
+
".pbb-helpLink{color:var(--dsw-alias-label-secondary);text-decoration:underline;text-underline-offset:2px}",
|
|
1162
1211
|
".pbb-testGrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}",
|
|
1163
|
-
".pbb-testItem
|
|
1164
|
-
".pbb-
|
|
1165
|
-
".pbb-
|
|
1166
|
-
".pbb-
|
|
1212
|
+
".pbb-testItem:last-child:nth-child(odd){grid-column:1/-1}",
|
|
1213
|
+
".pbb-testItem{display:flex;align-items:center;gap:12px;padding:11px;border:1px solid var(--dsw-alias-border-l3);border-radius:8px;background:var(--dsw-alias-bg-module-platform)}",
|
|
1214
|
+
".pbb-testTitle{font-size:13px;font-weight:500;color:var(--dsw-alias-label-primary)}",
|
|
1215
|
+
".pbb-testDescription{font-size:12px;color:var(--dsw-alias-label-tertiary);line-height:1.5}",
|
|
1216
|
+
".pbb-runtimeList{display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l3);border-radius:8px;overflow:hidden}",
|
|
1167
1217
|
".pbb-runtimeList>.pbb-runtimeRow,.pbb-runtimeRow{display:flex;align-items:center;gap:10px;padding:9px 10px;border-top:1px solid var(--dsw-alias-border-l2)}",
|
|
1168
1218
|
".pbb-runtimeList>.pbb-runtimeRow:first-child{border-top:0}",
|
|
1169
1219
|
".pbb-runtimeList>.pbb-runtimeRow>.pbb-row{flex:1;min-width:0}",
|
|
1170
|
-
".pbb-updateRow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-
|
|
1220
|
+
".pbb-updateRow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-business-primary,#4176e6) 35%,var(--dsw-alias-border-l3));border-radius:8px;color:var(--dsw-alias-label-primary);font-size:13px;text-decoration:none;cursor:pointer;transition:background-color 160ms " + EASE + "}",
|
|
1221
|
+
".pbb-disclosure{padding:0}",
|
|
1222
|
+
".pbb-disclosure>summary{list-style:none;display:flex;align-items:center;gap:10px;padding:13px 18px;cursor:pointer;color:var(--dsw-alias-label-primary)}",
|
|
1223
|
+
".pbb-disclosure>summary::-webkit-details-marker{display:none}",
|
|
1224
|
+
".pbb-disclosure[open]>summary .pbb-chev{transform:rotate(90deg)}",
|
|
1225
|
+
".pbb-disclosureTitle{font-size:13px;font-weight:500;flex:1}",
|
|
1226
|
+
".pbb-disclosureMeta{font-size:12px;color:var(--dsw-alias-label-tertiary);max-width:46%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
1227
|
+
".pbb-disclosureBody{display:flex;flex-direction:column;gap:12px;padding:2px 18px 16px}",
|
|
1171
1228
|
".pbb-diagnostics>summary{color:var(--dsw-alias-label-secondary)}",
|
|
1172
|
-
"@media (
|
|
1229
|
+
"@media (hover:hover) and (pointer:fine){.pbb-refresh:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.pbb-cardHead:hover{background:var(--dsw-alias-bg-module-platform)}.pbb-action:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}.pbb-buttonPrimary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover,var(--dsw-alias-interactive-bg-hover-solid))}.pbb-actionDangerGhost:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 9%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 55%,transparent)}.pbb-expand:hover{color:var(--dsw-alias-label-primary)}.pbb-updateRow:hover{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4176e6) 8%,transparent)}}",
|
|
1230
|
+
"@media (prefers-reduced-motion:reduce){.pbb-section *{animation-duration:.01ms!important;animation-delay:0s!important;transition-duration:.01ms!important;transition-delay:0s!important}}",
|
|
1231
|
+
"@container pbb (max-width:640px){.pbb-statusStrip{grid-template-columns:repeat(2,1fr)}.pbb-statusCell:nth-child(3){border-left:0}.pbb-statusCell:nth-child(n+3){border-top:1px solid var(--dsw-alias-border-l2)}.pbb-cardSummary{display:none}}",
|
|
1232
|
+
"@container pbb (max-width:480px){.pbb-testGrid{grid-template-columns:1fr}.pbb-testItem:last-child:nth-child(odd){grid-column:auto}.pbb-qrPanel{grid-template-columns:1fr}.pbb-limitRow{align-items:flex-start;flex-direction:column}.pbb-limitControl{align-self:flex-end}.pbb-deviceRow{grid-template-columns:minmax(0,1fr)}.pbb-deviceActions{grid-row:auto;grid-column:auto;justify-content:flex-start}}",
|
|
1233
|
+
"@media (pointer:coarse){.pbb-action{min-height:32px;padding:7px 10px;font-size:13px}.pbb-buttonPrimary{font-size:14px}.pbb-cardHead{min-height:56px}.pbb-expand{padding:5px 0}.pbb-refresh{padding:5px 0}}"
|
|
1173
1234
|
].join("\n");
|
|
1174
1235
|
/**
|
|
1175
1236
|
* Client bundle id, identical to the `window.__ModuleLoader__.load({ id })`
|
|
@@ -4032,26 +4093,6 @@ window.__ModuleLoader__.load({
|
|
|
4032
4093
|
function deviceLabel(device) {
|
|
4033
4094
|
return (device.customName ?? device.deviceName).trim();
|
|
4034
4095
|
}
|
|
4035
|
-
/** 渲染一块连接磁贴。纯数据函数:九参进,元素树出。 */
|
|
4036
|
-
function renderConnectionTile(key, title, description, checked, ready, dot, statusLabel, onToggle, extra = null) {
|
|
4037
|
-
return (0, react.createElement)("div", {
|
|
4038
|
-
className: "pbb-connectionTile",
|
|
4039
|
-
key
|
|
4040
|
-
}, (0, react.createElement)("div", { className: "pbb-connectionTileHeader" }, (0, react.createElement)("span", { className: "pbb-switchTitle pbb-dotRow" }, (0, react.createElement)("span", {
|
|
4041
|
-
className: "pbb-dot" + dot,
|
|
4042
|
-
role: "img",
|
|
4043
|
-
"aria-label": statusLabel,
|
|
4044
|
-
title: statusLabel
|
|
4045
|
-
}), title), (0, react.createElement)("button", {
|
|
4046
|
-
type: "button",
|
|
4047
|
-
role: "switch",
|
|
4048
|
-
"aria-checked": checked,
|
|
4049
|
-
"aria-label": title,
|
|
4050
|
-
disabled: !ready,
|
|
4051
|
-
className: "pbb-switch" + (checked ? " pbb-switchOn" : ""),
|
|
4052
|
-
onClick: onToggle
|
|
4053
|
-
})), (0, react.createElement)("span", { className: "pbb-connectionState" }, statusLabel), (0, react.createElement)("p", { className: "pbb-connectionDescription" }, description), extra);
|
|
4054
|
-
}
|
|
4055
4096
|
//#endregion
|
|
4056
4097
|
//#region src/client/settings-page.ts
|
|
4057
4098
|
/** phase 语义标签 → i18n key。措辞归页面,view model 只认语义。 */
|
|
@@ -4071,6 +4112,16 @@ window.__ModuleLoader__.load({
|
|
|
4071
4112
|
error: "local.phaseError",
|
|
4072
4113
|
stopped: "local.phaseStopped"
|
|
4073
4114
|
};
|
|
4115
|
+
/** 状态条用的短状态:列标签已经写明是哪条通道,值只说状态,免得在窄格里被截断。 */
|
|
4116
|
+
const CHANNEL_STATE_KEY = {
|
|
4117
|
+
disabled: "channel.state.disabled",
|
|
4118
|
+
starting: "channel.state.starting",
|
|
4119
|
+
login_required: "channel.state.login_required",
|
|
4120
|
+
online: "channel.state.online",
|
|
4121
|
+
error: "channel.state.error",
|
|
4122
|
+
unavailable: "channel.state.unavailable",
|
|
4123
|
+
stopped: "channel.state.stopped"
|
|
4124
|
+
};
|
|
4074
4125
|
/** 服务状态 → i18n key。 */
|
|
4075
4126
|
const SERVICE_STATUS_KEY = {
|
|
4076
4127
|
loading: "status.loading",
|
|
@@ -4093,29 +4144,59 @@ window.__ModuleLoader__.load({
|
|
|
4093
4144
|
strokeLinejoin: "round",
|
|
4094
4145
|
"aria-hidden": true
|
|
4095
4146
|
}, (0, react.createElement)("path", { d: "M2.5 4.5h11" }), (0, react.createElement)("path", { d: "M6.5 2.5h3" }), (0, react.createElement)("path", { d: "M4 4.5l.6 8.2a1 1 0 0 0 1 .9h4.8a1 1 0 0 0 1-.9l.6-8.2" }), (0, react.createElement)("path", { d: "M6.6 7v4.2" }), (0, react.createElement)("path", { d: "M9.4 7v4.2" }));
|
|
4147
|
+
/** Chevron icon (linear, currentColor). CSS rotates it 90° while its owner is
|
|
4148
|
+
* expanded, so collapsed always means "points right, more content behind". */
|
|
4149
|
+
const ChevronIcon = () => (0, react.createElement)("svg", {
|
|
4150
|
+
className: "pbb-chevIcon",
|
|
4151
|
+
viewBox: "0 0 16 16",
|
|
4152
|
+
width: 12,
|
|
4153
|
+
height: 12,
|
|
4154
|
+
fill: "none",
|
|
4155
|
+
stroke: "currentColor",
|
|
4156
|
+
strokeWidth: 1.5,
|
|
4157
|
+
strokeLinecap: "round",
|
|
4158
|
+
strokeLinejoin: "round",
|
|
4159
|
+
"aria-hidden": true
|
|
4160
|
+
}, (0, react.createElement)("path", { d: "M6 3.5 10.5 8 6 12.5" }));
|
|
4161
|
+
/** Check/cross marks for the relay and push result lines. They used to be the
|
|
4162
|
+
* dingbats '✓'/'✗', which the repo's visual rules reject as character icons. */
|
|
4096
4163
|
const CheckIcon = () => (0, react.createElement)("svg", {
|
|
4097
|
-
className: "pbb-controlIcon",
|
|
4098
4164
|
viewBox: "0 0 16 16",
|
|
4099
|
-
width:
|
|
4100
|
-
height:
|
|
4165
|
+
width: 12,
|
|
4166
|
+
height: 12,
|
|
4101
4167
|
fill: "none",
|
|
4102
4168
|
stroke: "currentColor",
|
|
4103
|
-
strokeWidth: 1.
|
|
4169
|
+
strokeWidth: 1.6,
|
|
4104
4170
|
strokeLinecap: "round",
|
|
4105
4171
|
strokeLinejoin: "round",
|
|
4106
4172
|
"aria-hidden": true
|
|
4107
|
-
}, (0, react.createElement)("path", { d: "
|
|
4108
|
-
const
|
|
4109
|
-
className: "pbb-controlIcon",
|
|
4173
|
+
}, (0, react.createElement)("path", { d: "M3.5 8.5 6.5 11.5 12.5 4.5" }));
|
|
4174
|
+
const CrossIcon = () => (0, react.createElement)("svg", {
|
|
4110
4175
|
viewBox: "0 0 16 16",
|
|
4111
|
-
width:
|
|
4112
|
-
height:
|
|
4176
|
+
width: 12,
|
|
4177
|
+
height: 12,
|
|
4113
4178
|
fill: "none",
|
|
4114
4179
|
stroke: "currentColor",
|
|
4115
4180
|
strokeWidth: 1.6,
|
|
4116
4181
|
strokeLinecap: "round",
|
|
4182
|
+
strokeLinejoin: "round",
|
|
4117
4183
|
"aria-hidden": true
|
|
4118
|
-
}, (0, react.createElement)("path", { d: "
|
|
4184
|
+
}, (0, react.createElement)("path", { d: "M4.5 4.5 11.5 11.5" }), (0, react.createElement)("path", { d: "M11.5 4.5 4.5 11.5" }));
|
|
4185
|
+
/** One result line: SVG mark + text; the mark carries the pass/fail state. */
|
|
4186
|
+
const resultRow = (ok, text, key) => (0, react.createElement)("p", {
|
|
4187
|
+
className: "pbb-diag pbb-resultRow",
|
|
4188
|
+
key
|
|
4189
|
+
}, (0, react.createElement)("span", { className: "pbb-resultIcon" + (ok ? "" : " pbb-resultIconBad") }, ok ? CheckIcon() : CrossIcon()), (0, react.createElement)("span", null, text));
|
|
4190
|
+
/** 最近在线只细化到分钟:秒和年份对判断设备是否还连着没有意义。 */
|
|
4191
|
+
function formatLastSeen(ts) {
|
|
4192
|
+
if (ts === void 0 || !Number.isFinite(ts) || ts <= 0) return "—";
|
|
4193
|
+
return new Date(ts).toLocaleString(void 0, {
|
|
4194
|
+
month: "numeric",
|
|
4195
|
+
day: "numeric",
|
|
4196
|
+
hour: "2-digit",
|
|
4197
|
+
minute: "2-digit"
|
|
4198
|
+
});
|
|
4199
|
+
}
|
|
4119
4200
|
async function writeClipboard(t, value) {
|
|
4120
4201
|
try {
|
|
4121
4202
|
await navigator.clipboard.writeText(value);
|
|
@@ -4164,6 +4245,11 @@ window.__ModuleLoader__.load({
|
|
|
4164
4245
|
message: "",
|
|
4165
4246
|
failed: false
|
|
4166
4247
|
});
|
|
4248
|
+
const [localOptionsOpen, setLocalOptionsOpen] = (0, react.useState)(false);
|
|
4249
|
+
const [remoteOptionsOpen, setRemoteOptionsOpen] = (0, react.useState)(false);
|
|
4250
|
+
const [systemOpen, setSystemOpen] = (0, react.useState)(false);
|
|
4251
|
+
const [armedRevokeDeviceId, setArmedRevokeDeviceId] = (0, react.useState)(null);
|
|
4252
|
+
const [nowMs, setNowMs] = (0, react.useState)(() => Date.now());
|
|
4167
4253
|
(0, react.useEffect)(() => {
|
|
4168
4254
|
if (!can("refresh")) return;
|
|
4169
4255
|
const refresh = props.refresh;
|
|
@@ -4423,37 +4509,22 @@ window.__ModuleLoader__.load({
|
|
|
4423
4509
|
});
|
|
4424
4510
|
});
|
|
4425
4511
|
};
|
|
4426
|
-
const primaryRows = [];
|
|
4427
4512
|
const advancedRows = [];
|
|
4428
|
-
if (report !== null) {
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
key: "proto"
|
|
4443
|
-
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.protocolVersion")), (0, react.createElement)("span", { className: "pbb-value" }, "v" + String(report.protocolVersion)))), (0, react.createElement)("div", {
|
|
4444
|
-
className: "pbb-runtimeRow",
|
|
4445
|
-
key: "server"
|
|
4446
|
-
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.serverVersion")), (0, react.createElement)("span", { className: "pbb-value" }, report.serverVersion))), (0, react.createElement)("div", {
|
|
4447
|
-
className: "pbb-runtimeRow",
|
|
4448
|
-
key: "path"
|
|
4449
|
-
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.identityPath")), (0, react.createElement)("span", { className: "pbb-value" }, report.identityPath))), (0, react.createElement)("div", {
|
|
4450
|
-
className: "pbb-runtimeRow",
|
|
4451
|
-
key: "buffer"
|
|
4452
|
-
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.bufferMax")), (0, react.createElement)("span", { className: "pbb-value" }, String(report.historyBufferMax) + translateWith(props.t, "advanced.frames")))));
|
|
4453
|
-
}
|
|
4454
|
-
const revokeDevice = (deviceId, name) => {
|
|
4513
|
+
if (report !== null) advancedRows.push((0, react.createElement)("div", {
|
|
4514
|
+
className: "pbb-runtimeRow",
|
|
4515
|
+
key: "proto"
|
|
4516
|
+
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.protocolVersion")), (0, react.createElement)("span", { className: "pbb-value" }, "v" + String(report.protocolVersion)))), (0, react.createElement)("div", {
|
|
4517
|
+
className: "pbb-runtimeRow",
|
|
4518
|
+
key: "server"
|
|
4519
|
+
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.serverVersion")), (0, react.createElement)("span", { className: "pbb-value" }, report.serverVersion))), (0, react.createElement)("div", {
|
|
4520
|
+
className: "pbb-runtimeRow",
|
|
4521
|
+
key: "path"
|
|
4522
|
+
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.identityPath")), (0, react.createElement)("span", { className: "pbb-value" }, report.identityPath))), (0, react.createElement)("div", {
|
|
4523
|
+
className: "pbb-runtimeRow",
|
|
4524
|
+
key: "buffer"
|
|
4525
|
+
}, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.bufferMax")), (0, react.createElement)("span", { className: "pbb-value" }, String(report.historyBufferMax) + translateWith(props.t, "advanced.frames")))));
|
|
4526
|
+
const revokeDevice = (deviceId, _name) => {
|
|
4455
4527
|
if (!can("revokeDevice")) return;
|
|
4456
|
-
if (typeof window !== "undefined" && !window.confirm(translateWith(props.t, "devices.revokeConfirm", { name }))) return;
|
|
4457
4528
|
setDeviceBusy(deviceId);
|
|
4458
4529
|
setDeviceBusyAction("revoke");
|
|
4459
4530
|
setDeviceMessage("");
|
|
@@ -4468,6 +4539,7 @@ window.__ModuleLoader__.load({
|
|
|
4468
4539
|
};
|
|
4469
4540
|
const deviceLabel$1 = (device) => deviceLabel(device) || translateWith(props.t, "devices.unnamed");
|
|
4470
4541
|
const beginDeviceRename = (device) => {
|
|
4542
|
+
setArmedRevokeDeviceId(null);
|
|
4471
4543
|
setEditingDeviceId(device.deviceId);
|
|
4472
4544
|
setDeviceNameDraft(device.customName ?? device.deviceName);
|
|
4473
4545
|
setDeviceMessage("");
|
|
@@ -4499,20 +4571,28 @@ window.__ModuleLoader__.load({
|
|
|
4499
4571
|
});
|
|
4500
4572
|
};
|
|
4501
4573
|
const visibleDevices$1 = visibleDevices(report);
|
|
4502
|
-
const
|
|
4574
|
+
const deviceRows = visibleDevices$1.length > 0 ? (0, react.createElement)("div", { className: "pbb-deviceList" }, visibleDevices$1.map((d) => {
|
|
4503
4575
|
const editing = editingDeviceId === d.deviceId;
|
|
4504
4576
|
const busy = deviceBusy === d.deviceId;
|
|
4505
4577
|
const label = deviceLabel$1(d);
|
|
4506
|
-
|
|
4578
|
+
const fingerprint = d.fingerprint ?? "";
|
|
4579
|
+
const armed = armedRevokeDeviceId === d.deviceId;
|
|
4580
|
+
return (0, react.createElement)("div", {
|
|
4581
|
+
className: "pbb-deviceRow",
|
|
4507
4582
|
key: d.deviceId,
|
|
4508
|
-
"
|
|
4509
|
-
|
|
4583
|
+
"data-armed": armed || void 0,
|
|
4584
|
+
"aria-busy": busy,
|
|
4585
|
+
"aria-label": translateWith(props.t, "devices.col.name") + ": " + label
|
|
4586
|
+
}, (0, react.createElement)("div", { className: "pbb-deviceMain" }, (0, react.createElement)("div", { className: "pbb-deviceNameRow" }, (0, react.createElement)("span", {
|
|
4587
|
+
className: "pbb-deviceName",
|
|
4588
|
+
title: label
|
|
4589
|
+
}, label), d.customName ? (0, react.createElement)("span", { className: "pbb-badge" }, translateWith(props.t, "devices.customBadge")) : null), (0, react.createElement)("div", { className: "pbb-deviceMeta" }, (0, react.createElement)("span", null, d.appVersion), (0, react.createElement)("code", { title: fingerprint }, fingerprint.slice(0, 12)), (0, react.createElement)("span", null, translateWith(props.t, "devices.col.lastSeen") + ": " + formatLastSeen(d.lastSeenTs)))), editing ? (0, react.createElement)("form", {
|
|
4510
4590
|
className: "pbb-deviceRenameForm",
|
|
4511
4591
|
onSubmit: (event) => {
|
|
4512
4592
|
event.preventDefault();
|
|
4513
4593
|
saveDeviceName(d.deviceId);
|
|
4514
4594
|
}
|
|
4515
|
-
}, (0, react.createElement)("
|
|
4595
|
+
}, (0, react.createElement)("input", {
|
|
4516
4596
|
className: "pbb-deviceNameInput",
|
|
4517
4597
|
type: "text",
|
|
4518
4598
|
value: deviceNameDraft,
|
|
@@ -4533,21 +4613,21 @@ window.__ModuleLoader__.load({
|
|
|
4533
4613
|
}
|
|
4534
4614
|
}), (0, react.createElement)("div", { className: "pbb-deviceRenameActions" }, (0, react.createElement)("button", {
|
|
4535
4615
|
type: "submit",
|
|
4536
|
-
className: "pbb-action pbb-
|
|
4616
|
+
className: "pbb-action pbb-buttonPrimary",
|
|
4537
4617
|
disabled: busy || deviceNameDraft.length > 64,
|
|
4538
4618
|
title: busy ? translateWith(props.t, "devices.nameSaving") : translateWith(props.t, "devices.nameSave"),
|
|
4539
4619
|
"aria-label": busy ? translateWith(props.t, "devices.nameSaving") : translateWith(props.t, "devices.nameSave")
|
|
4540
|
-
}, busy ? (0, react.createElement)("
|
|
4541
|
-
className: "pbb-inlineSpinner",
|
|
4542
|
-
"aria-hidden": true
|
|
4543
|
-
}) : CheckIcon()), (0, react.createElement)("button", {
|
|
4620
|
+
}, busy ? translateWith(props.t, "devices.nameSaving") : translateWith(props.t, "devices.nameSave")), (0, react.createElement)("button", {
|
|
4544
4621
|
type: "button",
|
|
4545
|
-
className: "pbb-action
|
|
4622
|
+
className: "pbb-action",
|
|
4546
4623
|
disabled: busy,
|
|
4547
4624
|
title: translateWith(props.t, "devices.nameCancel"),
|
|
4548
4625
|
"aria-label": translateWith(props.t, "devices.nameCancel"),
|
|
4549
4626
|
onClick: cancelDeviceRename
|
|
4550
|
-
},
|
|
4627
|
+
}, translateWith(props.t, "devices.nameCancel"))), deviceNameDraft.length > 64 ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, translateWith(props.t, "devices.nameInvalid")) : null) : null, armed ? null : (0, react.createElement)("div", {
|
|
4628
|
+
className: "pbb-deviceActions",
|
|
4629
|
+
"aria-label": translateWith(props.t, "devices.col.actions")
|
|
4630
|
+
}, !editing ? (0, react.createElement)("button", {
|
|
4551
4631
|
type: "button",
|
|
4552
4632
|
className: "pbb-action",
|
|
4553
4633
|
disabled: busy || editingDeviceId !== null || !can("setDeviceName"),
|
|
@@ -4558,9 +4638,27 @@ window.__ModuleLoader__.load({
|
|
|
4558
4638
|
className: "pbb-action pbb-actionDangerGhost",
|
|
4559
4639
|
disabled: busy,
|
|
4560
4640
|
"aria-label": busy && deviceBusyAction === "revoke" ? translateWith(props.t, "devices.deleting", { name: label }) : translateWith(props.t, "devices.revokeAria", { name: label }),
|
|
4561
|
-
onClick: () =>
|
|
4562
|
-
|
|
4563
|
-
|
|
4641
|
+
onClick: () => {
|
|
4642
|
+
cancelDeviceRename();
|
|
4643
|
+
setArmedRevokeDeviceId(d.deviceId);
|
|
4644
|
+
}
|
|
4645
|
+
}, busy && deviceBusyAction === "revoke" ? null : TrashIcon(), busy && deviceBusyAction === "revoke" ? (0, react.createElement)("span", { className: "pbb-actionBusy" }, translateWith(props.t, "devices.deleting")) : translateWith(props.t, "devices.revoke"))), armed && !busy ? (0, react.createElement)("div", { className: "pbb-deviceConfirm" }, (0, react.createElement)("p", {
|
|
4646
|
+
className: "pbb-diag pbb-diagBad",
|
|
4647
|
+
role: "alert"
|
|
4648
|
+
}, translateWith(props.t, "devices.revokeConfirm", { name: label })), (0, react.createElement)("div", { className: "pbb-rowAction" }, (0, react.createElement)("button", {
|
|
4649
|
+
type: "button",
|
|
4650
|
+
className: "pbb-action pbb-actionDangerGhost",
|
|
4651
|
+
"aria-label": translateWith(props.t, "devices.revokeAria", { name: label }),
|
|
4652
|
+
onClick: () => {
|
|
4653
|
+
setArmedRevokeDeviceId(null);
|
|
4654
|
+
revokeDevice(d.deviceId, label);
|
|
4655
|
+
}
|
|
4656
|
+
}, translateWith(props.t, "devices.revoke")), (0, react.createElement)("button", {
|
|
4657
|
+
type: "button",
|
|
4658
|
+
className: "pbb-action",
|
|
4659
|
+
onClick: () => setArmedRevokeDeviceId(null)
|
|
4660
|
+
}, translateWith(props.t, "devices.nameCancel")))) : null);
|
|
4661
|
+
})) : (0, react.createElement)("p", { className: "pbb-empty" }, translateWith(props.t, "devices.empty"));
|
|
4564
4662
|
const switchTitle = translateWith(props.t, "master.title");
|
|
4565
4663
|
const switchDesc = switchReady ? enabled ? translateWith(props.t, "master.on") : translateWith(props.t, "master.off") : translateWith(props.t, "master.loading");
|
|
4566
4664
|
const localMeta = report === null ? null : LOCAL_PHASE_META[report.local.phase];
|
|
@@ -4573,6 +4671,10 @@ window.__ModuleLoader__.load({
|
|
|
4573
4671
|
});
|
|
4574
4672
|
const serviceStatusText = translateWith(props.t, SERVICE_STATUS_KEY[service.kind]);
|
|
4575
4673
|
const serviceDot = service.dot;
|
|
4674
|
+
const localPhaseText = localMeta === null ? translateWith(props.t, "phase.unknown") : translateWith(props.t, LOCAL_LABEL_KEY[localMeta.label]);
|
|
4675
|
+
const remotePhaseText = remoteMeta === null ? translateWith(props.t, "phase.unknown") : translateWith(props.t, REMOTE_LABEL_KEY[remoteMeta.label]);
|
|
4676
|
+
const localStateText = localMeta === null ? translateWith(props.t, "phase.unknown") : translateWith(props.t, CHANNEL_STATE_KEY[localMeta.label]);
|
|
4677
|
+
const remoteStateText = remoteMeta === null ? translateWith(props.t, "phase.unknown") : translateWith(props.t, CHANNEL_STATE_KEY[remoteMeta.label]);
|
|
4576
4678
|
/** 一条失败事件的单行文本:时间 · 类型 · 分因,附带可选排查字段。 */
|
|
4577
4679
|
const diagnosticLine = (failure) => {
|
|
4578
4680
|
const base = translateWith(props.t, "diagnostics.item", {
|
|
@@ -4625,17 +4727,98 @@ window.__ModuleLoader__.load({
|
|
|
4625
4727
|
className: "pbb-action",
|
|
4626
4728
|
onClick: copyDiagnostics,
|
|
4627
4729
|
"data-testid": "diagnosticsCopy"
|
|
4628
|
-
}, translateWith(props.t, "diagnostics.copy"))), diagnosticsCopy.message ? (0, react.createElement)("p", {
|
|
4730
|
+
}, translateWith(props.t, "diagnostics.copy"))), diagnosticsCopy.message ? (0, react.createElement)("p", {
|
|
4731
|
+
className: "pbb-diag" + (diagnosticsCopy.failed ? " pbb-diagBad" : ""),
|
|
4732
|
+
role: "status"
|
|
4733
|
+
}, diagnosticsCopy.message) : null, report.diagnostics === void 0 ? (0, react.createElement)("p", { className: "pbb-diag" }, translateWith(props.t, "diagnostics.staleHost")) : report.diagnostics.recentFailures.length === 0 ? (0, react.createElement)("p", { className: "pbb-diag" }, translateWith(props.t, "diagnostics.empty")) : (0, react.createElement)("div", null, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "diagnostics.recent")), report.diagnostics.recentFailures.slice(-5).reverse().map((failure, index) => (0, react.createElement)("p", {
|
|
4629
4734
|
className: "pbb-diag",
|
|
4630
4735
|
key: String(index)
|
|
4631
4736
|
}, diagnosticLine(failure)))));
|
|
4737
|
+
/** 状态总览的一格:标签 / 点位 + 值 / 次行;整格 title 兜住被裁掉的全文。
|
|
4738
|
+
* dot 为 null 表示这一格是计数而非状态,不画点位(灰点会被读成「未启用」)。 */
|
|
4739
|
+
const statusCell = (label, dot, value, sub) => (0, react.createElement)("div", {
|
|
4740
|
+
className: "pbb-statusCell",
|
|
4741
|
+
title: label + " · " + value + (sub === "" ? "" : " · " + sub)
|
|
4742
|
+
}, (0, react.createElement)("div", { className: "pbb-statusLabel" }, label), (0, react.createElement)("div", { className: "pbb-statusValue" }, dot === null ? null : (0, react.createElement)("span", { className: "pbb-dot" + dot }), value), (0, react.createElement)("div", { className: "pbb-statusSub" }, sub));
|
|
4743
|
+
/** 折叠区:grid-rows 0fr→1fr 平滑开合(mockup 的做法),不用 <details> 的瞬时跳变。 */
|
|
4744
|
+
const fold = (open, body) => (0, react.createElement)("div", { className: "pbb-fold" + (open ? "" : " pbb-foldClosed") }, (0, react.createElement)("div", null, body));
|
|
4745
|
+
/** 配对倒计时:仅在 QR 面板打开且 grant 在场时每秒刷新一次。 */
|
|
4746
|
+
(0, react.useEffect)(() => {
|
|
4747
|
+
if (!panel.open || pairingPanel.grant === null) return;
|
|
4748
|
+
const timer = globalThis.setInterval(() => setNowMs(Date.now()), 1e3);
|
|
4749
|
+
return () => globalThis.clearInterval(timer);
|
|
4750
|
+
}, [panel.open, pairingPanel.grant]);
|
|
4751
|
+
const grantRemainingMs = pairingPanel.grant === null ? 0 : Math.max(0, pairingPanel.grant.expiresAt - nowMs);
|
|
4752
|
+
const grantRemainingText = String(Math.floor(grantRemainingMs / 6e4)) + ":" + String(Math.floor(grantRemainingMs / 1e3) % 60).padStart(2, "0");
|
|
4753
|
+
const grantRemainingPct = Math.min(100, grantRemainingMs / 3e5 * 100);
|
|
4754
|
+
const localDesc = localSwitchReady ? localEnabled ? translateWith(props.t, "local.on", { port: localPort }) : translateWith(props.t, "local.off") : translateWith(props.t, "master.loading");
|
|
4755
|
+
const remoteDesc = remoteSwitchReady ? remoteEnabled ? translateWith(props.t, "remote.on") : translateWith(props.t, "remote.off") : translateWith(props.t, "master.loading");
|
|
4756
|
+
/** 端点 → 状态条副行只暴露 host[:port],去掉协议前缀让一行能放下。 */
|
|
4757
|
+
const endpointHost = (value) => {
|
|
4758
|
+
if (value === void 0 || value === "") return void 0;
|
|
4759
|
+
try {
|
|
4760
|
+
return new URL(value).host;
|
|
4761
|
+
} catch {
|
|
4762
|
+
return value;
|
|
4763
|
+
}
|
|
4764
|
+
};
|
|
4765
|
+
const localStatusSub = !localSwitchReady ? translateWith(props.t, "master.loading") : report !== null && report.local.phase === "online" ? endpointHost(report.local.endpoints[0]) ?? localDesc : report !== null && report.local.phase === "error" ? report.local.message !== void 0 && report.local.message !== "" ? report.local.message : localDesc : report !== null && (report.local.phase === "disabled" || report.local.phase === "stopped") ? translateWith(props.t, "local.off") : localDesc;
|
|
4766
|
+
const remoteStatusSub = !remoteSwitchReady ? translateWith(props.t, "master.loading") : report !== null && report.remote.phase === "online" ? endpointHost(report.remote.publicURL) ?? remoteDesc : report !== null && report.remote.phase === "error" ? report.remote.message !== void 0 && report.remote.message !== "" ? report.remote.message : remoteDesc : report !== null && report.remote.phase === "disabled" ? translateWith(props.t, "remote.off") : remoteDesc;
|
|
4767
|
+
const isOffPhase = (phase) => phase === "disabled" || phase === "stopped";
|
|
4768
|
+
const localSettled = report === null || (localEnabled ? report.local.phase === "online" : isOffPhase(report.local.phase));
|
|
4769
|
+
const remoteSettled = report === null || (remoteEnabled ? report.remote.phase === "online" : isOffPhase(report.remote.phase));
|
|
4770
|
+
const localChannelDesc = localSettled ? localDesc : localPhaseText + " · " + localDesc;
|
|
4771
|
+
const remoteChannelDesc = remoteSettled ? remoteDesc : remotePhaseText + " · " + remoteDesc;
|
|
4772
|
+
const recentFailures = report?.diagnostics?.recentFailures ?? [];
|
|
4773
|
+
const troubleGood = relayTestResult !== null ? relayTestResult.overall === "ok" : pushTestResult !== null ? pushTestResult.overall === "sent" : false;
|
|
4774
|
+
const troubleBad = relayTestResult !== null ? relayTestResult.overall !== "ok" : pushTestResult !== null ? pushTestResult.overall !== "sent" : recentFailures.length > 0;
|
|
4775
|
+
const troubleConclusion = relayTestResult !== null ? relayTestResult.overall === "ok" ? translateWith(props.t, "push.relayOk") : translateWith(props.t, "push.relayBad") : pushTestResult !== null ? pushTestResult.overall === "sent" ? translateWith(props.t, "push.pushSent") : translateWith(props.t, "push.pushFailed") : recentFailures.length > 0 ? translateWith(props.t, "diagnostics.recent") + " " + String(recentFailures.length) : translateWith(props.t, "troubleshooting.title");
|
|
4632
4776
|
return (0, react.createElement)("div", { className: "pbb-section" }, (0, react.createElement)("header", { className: "pbb-pageHeader" }, (0, react.createElement)("div", null, (0, react.createElement)("h2", { className: "pbb-title" }, "DeepPilot"), (0, react.createElement)("p", { className: "pbb-intro" }, translateWith(props.t, "meta.intro"))), (0, react.createElement)("button", {
|
|
4633
4777
|
type: "button",
|
|
4634
4778
|
className: "pbb-refresh",
|
|
4635
4779
|
onClick: () => {
|
|
4636
4780
|
if (can("refresh")) props.refresh();
|
|
4637
4781
|
}
|
|
4638
|
-
}, translateWith(props.t, "meta.refresh"))), (0, react.createElement)("
|
|
4782
|
+
}, translateWith(props.t, "meta.refresh"))), (0, react.createElement)("section", { className: "pbb-statusStrip" }, statusCell(translateWith(props.t, "master.title"), serviceDot, serviceStatusText, switchDesc), statusCell(translateWith(props.t, "local.title"), localMeta?.dot ?? "", localStateText, localStatusSub), statusCell(translateWith(props.t, "remote.title"), remoteMeta?.dot ?? "", remoteStateText, remoteStatusSub), statusCell(translateWith(props.t, "panel.activeConnections"), null, report === null ? translateWith(props.t, "status.loading") : String(report.activeConnections), translateWith(props.t, "panel.identity") + " · " + (report !== null && report.pairingReady ? translateWith(props.t, "panel.identityReady") : translateWith(props.t, "panel.identityNotReady")))), report === null ? null : (0, react.createElement)("div", { className: "pbb-card" }, (0, react.createElement)("div", { className: "pbb-cardHeader" }, (0, react.createElement)("div", null, (0, react.createElement)("h3", { className: "pbb-cardTitle" }, translateWith(props.t, "pair.qrPanelTitle")), (0, react.createElement)("p", { className: "pbb-cardDescription" }, translateWith(props.t, "pair.description"))), pairingTarget === null ? (0, react.createElement)("span", { className: "pbb-statusBadge" + (enabled ? " pbb-bad" : "") }, enabled ? translateWith(props.t, "pair.noAddress") : translateWith(props.t, "status.off")) : (0, react.createElement)("button", {
|
|
4783
|
+
type: "button",
|
|
4784
|
+
className: "pbb-action pbb-buttonPrimary",
|
|
4785
|
+
disabled: panel.busy || report !== null && !report.pairingReady,
|
|
4786
|
+
onClick: () => {
|
|
4787
|
+
if (pairingTarget === null) return;
|
|
4788
|
+
if (panel.open) hidePairingQR();
|
|
4789
|
+
else showPairingQR(pairingTarget);
|
|
4790
|
+
}
|
|
4791
|
+
}, translateWith(props.t, panel.action))), (0, react.createElement)("div", { className: "pbb-pairingBody" }, pairingTarget === null ? (0, react.createElement)("p", { className: "pbb-diag" }, enabled ? translateWith(props.t, "pair.noAddressHelp") : translateWith(props.t, "pair.disabledHelp")) : null, pairingTargets.length < 2 ? null : (0, react.createElement)("div", { className: "pbb-targetList" }, pairingTargets.map((target) => (0, react.createElement)("button", {
|
|
4792
|
+
type: "button",
|
|
4793
|
+
key: target.host,
|
|
4794
|
+
className: "pbb-targetButton" + (target.host === pairingTarget?.host ? " pbb-targetSelected" : ""),
|
|
4795
|
+
disabled: panel.busy,
|
|
4796
|
+
onClick: () => {
|
|
4797
|
+
setSelectedPairingHost(target.host);
|
|
4798
|
+
if (panel.open) showPairingQR(target);
|
|
4799
|
+
else hidePairingQR();
|
|
4800
|
+
}
|
|
4801
|
+
}, (target.kind === "public" ? translateWith(props.t, "pair.kind.public") : translateWith(props.t, "pair.kind.lan")) + " · " + target.host))), panel.message ? (0, react.createElement)("p", {
|
|
4802
|
+
className: "pbb-diag pbb-diagBad",
|
|
4803
|
+
role: "alert"
|
|
4804
|
+
}, panel.message) : null, panel.notice ? (0, react.createElement)("p", {
|
|
4805
|
+
className: "pbb-diag",
|
|
4806
|
+
role: "status"
|
|
4807
|
+
}, panel.notice) : null, panel.failed && pairingTarget !== null ? (0, react.createElement)("div", { className: "pbb-rowAction" }, (0, react.createElement)("button", {
|
|
4808
|
+
type: "button",
|
|
4809
|
+
className: "pbb-action",
|
|
4810
|
+
disabled: panel.busy || report !== null && !report.pairingReady,
|
|
4811
|
+
onClick: () => showPairingQR(pairingTarget)
|
|
4812
|
+
}, translateWith(props.t, "pair.qrRetry"))) : null, panel.open && !panel.failed ? (0, react.createElement)("div", { className: "pbb-qrPanel" }, (0, react.createElement)("div", null, panel.qrDataURL === null ? (0, react.createElement)("p", { className: "pbb-diag" }, translateWith(props.t, "pair.qrGenerating")) : (0, react.createElement)("img", {
|
|
4813
|
+
className: "pbb-qrImage",
|
|
4814
|
+
src: panel.qrDataURL,
|
|
4815
|
+
alt: translateWith(props.t, "pair.qrAlt")
|
|
4816
|
+
}), pairingPanel.grant === null ? null : (0, react.createElement)("div", { className: "pbb-countdown" }, (0, react.createElement)("div", { className: "pbb-countdownBar" }, (0, react.createElement)("i", { style: { transform: "scaleX(" + String(grantRemainingPct / 100) + ")" } })), (0, react.createElement)("span", { className: "pbb-countdownText" }, grantRemainingText))), (0, react.createElement)("div", { className: "pbb-pairInfo" }, panel.link === null ? null : (0, react.createElement)("div", { className: "pbb-pairCodeBlock" }, (0, react.createElement)("span", { className: "pbb-pairCodeLabel" }, translateWith(props.t, "pair.infoLabel")), (0, react.createElement)("div", { className: "pbb-pairCodeRow" }, (0, react.createElement)("code", { className: "pbb-pairCode" }, panel.link), (0, react.createElement)("button", {
|
|
4817
|
+
type: "button",
|
|
4818
|
+
className: "pbb-action pbb-buttonPrimary",
|
|
4819
|
+
onClick: copyPairingInfo,
|
|
4820
|
+
"data-testid": "pairingInfoCopy"
|
|
4821
|
+
}, translateWith(props.t, "panel.tokenAction.copy")))), (0, react.createElement)("p", { className: "pbb-qrHint" }, translateWith(props.t, "pair.qrHint", { kind: panel.target?.kind === "public" ? translateWith(props.t, "pair.kind.public") : translateWith(props.t, "pair.kind.lan") })))) : null)), (0, react.createElement)("div", { className: "pbb-card" }, (0, react.createElement)("div", { className: "pbb-cardHeader" }, (0, react.createElement)("div", null, (0, react.createElement)("h3", { className: "pbb-cardTitle" }, translateWith(props.t, "connection.title")), (0, react.createElement)("p", { className: "pbb-cardDescription" }, translateWith(props.t, "connection.description")))), (0, react.createElement)("div", { className: "pbb-cardBody" }, (0, react.createElement)("div", { className: "pbb-masterRow" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("span", { className: "pbb-switchTitle" }, switchTitle), (0, react.createElement)("span", { className: "pbb-switchDesc" }, switchDesc)), (0, react.createElement)("button", {
|
|
4639
4822
|
type: "button",
|
|
4640
4823
|
role: "switch",
|
|
4641
4824
|
"aria-checked": enabled,
|
|
@@ -4645,16 +4828,22 @@ window.__ModuleLoader__.load({
|
|
|
4645
4828
|
onClick: () => {
|
|
4646
4829
|
if (can("setEnabled")) props.setDeepPilotEnabled(!enabled);
|
|
4647
4830
|
}
|
|
4648
|
-
})), (0, react.createElement)("div", { className: "pbb-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4831
|
+
})), (0, react.createElement)("div", { className: "pbb-channel" }, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("span", { className: "pbb-switchTitle" }, (0, react.createElement)("span", { className: "pbb-dot" + (localMeta?.dot ?? "") }), " ", translateWith(props.t, "local.title")), (0, react.createElement)("span", { className: "pbb-switchDesc" }, localChannelDesc)), (0, react.createElement)("button", {
|
|
4832
|
+
type: "button",
|
|
4833
|
+
role: "switch",
|
|
4834
|
+
"aria-checked": localEnabled,
|
|
4835
|
+
"aria-label": translateWith(props.t, "local.title"),
|
|
4836
|
+
disabled: !localSwitchReady,
|
|
4837
|
+
className: "pbb-switch" + (localEnabled ? " pbb-switchOn" : ""),
|
|
4838
|
+
onClick: () => {
|
|
4839
|
+
if (can("setLocalEnabled")) props.setDeepPilotLocalEnabled(!localEnabled);
|
|
4840
|
+
}
|
|
4841
|
+
})), report !== null && report.local.message && report.local.phase === "error" ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, report.local.message) : null, report !== null && report.local.tlsIdentityRegenerated === true ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, translateWith(props.t, "local.tlsRegenerated")) : null, (0, react.createElement)("button", {
|
|
4842
|
+
type: "button",
|
|
4843
|
+
className: "pbb-expand",
|
|
4844
|
+
"aria-expanded": localOptionsOpen,
|
|
4845
|
+
onClick: () => setLocalOptionsOpen(!localOptionsOpen)
|
|
4846
|
+
}, translateWith(props.t, "connection.optionsSummary"), " ", (0, react.createElement)("span", { className: "pbb-chev" }, ChevronIcon())), fold(localOptionsOpen, (0, react.createElement)("div", { className: "pbb-channelBody" }, (0, react.createElement)("div", { className: "pbb-limitRow" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("label", {
|
|
4658
4847
|
className: "pbb-switchTitle",
|
|
4659
4848
|
htmlFor: "deeppilot-local-port"
|
|
4660
4849
|
}, translateWith(props.t, "local.portTitle")), (0, react.createElement)("span", { className: "pbb-switchDesc" }, translateWith(props.t, "local.portDescription")), !localPortView.valid ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, translateWith(props.t, "local.portInvalid")) : localPortDraft.message ? (0, react.createElement)("p", { className: "pbb-diag" + (localPortDraft.failed ? " pbb-diagBad" : "") }, localPortDraft.message) : null), (0, react.createElement)("div", { className: "pbb-limitControl" }, (0, react.createElement)("input", {
|
|
@@ -4683,7 +4872,27 @@ window.__ModuleLoader__.load({
|
|
|
4683
4872
|
className: "pbb-action",
|
|
4684
4873
|
disabled: !localPortReady || !localPortView.valid || localPortView.unchanged,
|
|
4685
4874
|
onClick: applyLocalPort
|
|
4686
|
-
}, translateWith(props.t, "remote.limitApply")))), (0, react.createElement)("div", { className: "pbb-limitRow pbb-
|
|
4875
|
+
}, translateWith(props.t, "remote.limitApply")))), report !== null && report.local.phase === "online" && report.local.tlsFingerprint ? (0, react.createElement)("div", { className: "pbb-limitRow" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("span", { className: "pbb-switchTitle" }, translateWith(props.t, "local.tlsFingerprint")), (0, react.createElement)("code", { className: "pbb-token" }, report.local.tlsFingerprint))) : null))), (0, react.createElement)("div", { className: "pbb-channel" }, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("span", { className: "pbb-switchTitle" }, (0, react.createElement)("span", { className: "pbb-dot" + (remoteMeta?.dot ?? "") }), " ", translateWith(props.t, "remote.title")), (0, react.createElement)("span", { className: "pbb-switchDesc" }, remoteChannelDesc)), (0, react.createElement)("button", {
|
|
4876
|
+
type: "button",
|
|
4877
|
+
role: "switch",
|
|
4878
|
+
"aria-checked": remoteEnabled,
|
|
4879
|
+
"aria-label": translateWith(props.t, "remote.title"),
|
|
4880
|
+
disabled: !remoteSwitchReady,
|
|
4881
|
+
className: "pbb-switch" + (remoteEnabled ? " pbb-switchOn" : ""),
|
|
4882
|
+
onClick: () => {
|
|
4883
|
+
if (can("setRemoteEnabled")) props.setDeepPilotRemoteEnabled(!remoteEnabled);
|
|
4884
|
+
}
|
|
4885
|
+
})), report !== null && report.remote.phase === "login_required" && typeof report.remote.authURL === "string" && report.remote.authURL.startsWith("https://") ? (0, react.createElement)("div", { className: "pbb-rowAction" }, (0, react.createElement)("a", {
|
|
4886
|
+
className: "pbb-action pbb-buttonPrimary",
|
|
4887
|
+
href: report.remote.authURL,
|
|
4888
|
+
target: "_blank",
|
|
4889
|
+
rel: "noreferrer"
|
|
4890
|
+
}, translateWith(props.t, "remote.openAuth"))) : null, report !== null && report.remote.message && (report.remote.phase === "error" || report.remote.phase === "unavailable") ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, report.remote.message) : null, (0, react.createElement)("button", {
|
|
4891
|
+
type: "button",
|
|
4892
|
+
className: "pbb-expand",
|
|
4893
|
+
"aria-expanded": remoteOptionsOpen,
|
|
4894
|
+
onClick: () => setRemoteOptionsOpen(!remoteOptionsOpen)
|
|
4895
|
+
}, translateWith(props.t, "connection.optionsSummary"), " ", (0, react.createElement)("span", { className: "pbb-chev" }, ChevronIcon())), fold(remoteOptionsOpen, (0, react.createElement)("div", { className: "pbb-channelBody" }, (0, react.createElement)("div", { className: "pbb-limitRow" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("label", {
|
|
4687
4896
|
className: "pbb-switchTitle",
|
|
4688
4897
|
htmlFor: "deeppilot-funnel-source-limit"
|
|
4689
4898
|
}, translateWith(props.t, "remote.limitTitle")), (0, react.createElement)("span", { className: "pbb-switchDesc" }, translateWith(props.t, "remote.limitDescription")), !remoteLimitView.valid ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, translateWith(props.t, "remote.limitInvalid")) : remoteLimitDraft.message ? (0, react.createElement)("p", { className: "pbb-diag" + (remoteLimitDraft.failed ? " pbb-diagBad" : "") }, remoteLimitDraft.message) : null), (0, react.createElement)("div", { className: "pbb-limitControl" }, (0, react.createElement)("input", {
|
|
@@ -4712,48 +4921,20 @@ window.__ModuleLoader__.load({
|
|
|
4712
4921
|
className: "pbb-action",
|
|
4713
4922
|
disabled: !remoteConnectionLimitReady || !remoteLimitView.valid || remoteLimitView.unchanged,
|
|
4714
4923
|
onClick: applyRemoteLimit
|
|
4715
|
-
}, translateWith(props.t, "remote.limitApply"))))
|
|
4924
|
+
}, translateWith(props.t, "remote.limitApply")))), (0, react.createElement)("div", { className: "pbb-helpBody" }, (0, react.createElement)("div", { className: "pbb-helpSection" }, (0, react.createElement)("div", { className: "pbb-helpHeading" }, translateWith(props.t, "help.remoteTitle")), (0, react.createElement)("div", { className: "pbb-helpHeading" }, translateWith(props.t, "help.recommended")), (0, react.createElement)("ol", { className: "pbb-helpList" }, (0, react.createElement)("li", null, translateWith(props.t, "help.step1")), (0, react.createElement)("li", null, translateWith(props.t, "help.step2")), (0, react.createElement)("li", null, translateWith(props.t, "help.step3")), (0, react.createElement)("li", null, translateWith(props.t, "help.step4"))), (0, react.createElement)("p", { className: "pbb-helpText" }, translateWith(props.t, "help.funnelHint"))), (0, react.createElement)("div", { className: "pbb-helpSection" }, (0, react.createElement)("div", { className: "pbb-helpHeading" }, translateWith(props.t, "help.httpsTitle")), (0, react.createElement)("ol", { className: "pbb-helpList" }, (0, react.createElement)("li", null, translateWith(props.t, "help.httpsStep1")), (0, react.createElement)("li", null, translateWith(props.t, "help.httpsStep2")), (0, react.createElement)("li", null, translateWith(props.t, "help.httpsStep3"))), (0, react.createElement)("p", { className: "pbb-helpText" }, translateWith(props.t, "help.httpsHint"))), (0, react.createElement)("div", { className: "pbb-helpSection" }, (0, react.createElement)("div", { className: "pbb-helpHeading" }, translateWith(props.t, "help.allowTitle")), (0, react.createElement)("p", { className: "pbb-helpText" }, translateWith(props.t, "help.allowBody")), (0, react.createElement)("code", { className: "pbb-helpCode" }, "\"nodeAttrs\": [\n {\n \"target\": [\"autogroup:member\"],\n \"attr\": [\"funnel\"],\n },\n],"), (0, react.createElement)("p", { className: "pbb-helpText" }, translateWith(props.t, "help.allowHint"))), (0, react.createElement)("div", { className: "pbb-helpSection" }, (0, react.createElement)("div", { className: "pbb-helpHeading" }, translateWith(props.t, "help.faqTitle")), (0, react.createElement)("ul", { className: "pbb-helpList" }, (0, react.createElement)("li", null, translateWith(props.t, "help.faq1")), (0, react.createElement)("li", null, translateWith(props.t, "help.faq2")), (0, react.createElement)("li", null, translateWith(props.t, "help.faq3")), (0, react.createElement)("li", null, translateWith(props.t, "help.faq4")))), (0, react.createElement)("div", { className: "pbb-helpSection" }, (0, react.createElement)("div", { className: "pbb-helpHeading" }, translateWith(props.t, "help.securityTitle")), (0, react.createElement)("ul", { className: "pbb-helpList" }, (0, react.createElement)("li", null, translateWith(props.t, "help.security1")), (0, react.createElement)("li", null, translateWith(props.t, "help.security2")), (0, react.createElement)("li", null, translateWith(props.t, "help.security3")), (0, react.createElement)("li", null, translateWith(props.t, "help.security4")), (0, react.createElement)("li", null, translateWith(props.t, "help.security5"))), (0, react.createElement)("p", { className: "pbb-helpText" }, translateWith(props.t, "help.docsPrefix"), (0, react.createElement)("a", {
|
|
4716
4925
|
className: "pbb-helpLink",
|
|
4717
4926
|
href: "https://tailscale.com/docs/features/tailscale-funnel",
|
|
4718
4927
|
target: "_blank",
|
|
4719
4928
|
rel: "noreferrer"
|
|
4720
|
-
}, translateWith(props.t, "help.funnelDocs"))))))),
|
|
4929
|
+
}, translateWith(props.t, "help.funnelDocs")))))))))), (0, react.createElement)("div", { className: "pbb-card" }, (0, react.createElement)("div", { className: "pbb-cardHeader" }, (0, react.createElement)("div", null, (0, react.createElement)("h3", { className: "pbb-cardTitle" }, translateWith(props.t, "devices.title")), (0, react.createElement)("p", { className: "pbb-cardDescription" }, translateWith(props.t, "devices.description"))), (0, react.createElement)("span", { className: "pbb-countBadge" }, String(visibleDevices$1.length))), (0, react.createElement)("div", { className: "pbb-cardBody" }, deviceMessage ? (0, react.createElement)("p", {
|
|
4930
|
+
className: "pbb-diag" + (deviceMessage.startsWith(translateWith(props.t, "devices.renameFailed")) || deviceMessage.startsWith(translateWith(props.t, "devices.revokeFailed")) ? " pbb-diagBad" : ""),
|
|
4931
|
+
role: "status"
|
|
4932
|
+
}, deviceMessage) : null, deviceRows)), (0, react.createElement)("div", { className: "pbb-card" }, (0, react.createElement)("button", {
|
|
4721
4933
|
type: "button",
|
|
4722
|
-
className: "pbb-
|
|
4723
|
-
|
|
4724
|
-
onClick: () =>
|
|
4725
|
-
|
|
4726
|
-
else showPairingQR(pairingTarget);
|
|
4727
|
-
}
|
|
4728
|
-
}, translateWith(props.t, panel.action))), (0, react.createElement)("div", { className: "pbb-pairingBody" }, pairingTarget === null ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, translateWith(props.t, "pair.noAddressHelp")) : null, pairingTargets.length < 2 ? null : (0, react.createElement)("div", { className: "pbb-targetList" }, pairingTargets.map((target) => (0, react.createElement)("button", {
|
|
4729
|
-
type: "button",
|
|
4730
|
-
key: target.host,
|
|
4731
|
-
className: "pbb-targetButton" + (target.host === pairingTarget?.host ? " pbb-targetSelected" : ""),
|
|
4732
|
-
disabled: panel.busy,
|
|
4733
|
-
onClick: () => {
|
|
4734
|
-
setSelectedPairingHost(target.host);
|
|
4735
|
-
if (panel.open) showPairingQR(target);
|
|
4736
|
-
else hidePairingQR();
|
|
4737
|
-
}
|
|
4738
|
-
}, (target.kind === "public" ? translateWith(props.t, "pair.kind.public") : translateWith(props.t, "pair.kind.lan")) + " · " + target.host))), panel.message ? (0, react.createElement)("p", { className: "pbb-diag pbb-diagBad" }, panel.message) : null, panel.notice ? (0, react.createElement)("p", { className: "pbb-diag" }, panel.notice) : null, panel.failed && pairingTarget !== null ? (0, react.createElement)("div", { className: "pbb-rowAction" }, (0, react.createElement)("button", {
|
|
4739
|
-
type: "button",
|
|
4740
|
-
className: "pbb-action",
|
|
4741
|
-
disabled: panel.busy || !report.pairingReady,
|
|
4742
|
-
onClick: () => showPairingQR(pairingTarget)
|
|
4743
|
-
}, translateWith(props.t, "pair.qrRetry"))) : null, panel.open ? (0, react.createElement)("div", { className: "pbb-qrPanel" }, panel.qrDataURL === null ? (0, react.createElement)("p", { className: "pbb-diag" }, translateWith(props.t, "pair.qrGenerating")) : (0, react.createElement)("img", {
|
|
4744
|
-
className: "pbb-qrImage",
|
|
4745
|
-
src: panel.qrDataURL,
|
|
4746
|
-
alt: translateWith(props.t, "pair.qrAlt")
|
|
4747
|
-
}), panel.link === null ? null : (0, react.createElement)("div", { className: "pbb-pairCodeBlock" }, (0, react.createElement)("span", { className: "pbb-pairCodeLabel" }, translateWith(props.t, "pair.infoLabel")), (0, react.createElement)("div", { className: "pbb-pairCodeRow" }, (0, react.createElement)("code", { className: "pbb-pairCode" }, panel.link), (0, react.createElement)("button", {
|
|
4748
|
-
type: "button",
|
|
4749
|
-
className: "pbb-action pbb-buttonPrimary",
|
|
4750
|
-
onClick: copyPairingInfo,
|
|
4751
|
-
"data-testid": "pairingInfoCopy"
|
|
4752
|
-
}, translateWith(props.t, "panel.tokenAction.copy")))), (0, react.createElement)("p", { className: "pbb-qrHint" }, translateWith(props.t, "pair.qrHint", { kind: panel.target?.kind === "public" ? translateWith(props.t, "pair.kind.public") : translateWith(props.t, "pair.kind.lan") }))) : null)), (0, react.createElement)("div", { className: "pbb-card" }, (0, react.createElement)("div", { className: "pbb-cardHeader" }, (0, react.createElement)("div", null, (0, react.createElement)("h3", { className: "pbb-cardTitle" }, translateWith(props.t, "devices.title")), (0, react.createElement)("p", { className: "pbb-cardDescription" }, translateWith(props.t, "devices.description"))), (0, react.createElement)("span", { className: "pbb-countBadge" }, String(visibleDevices$1.length))), (0, react.createElement)("div", { className: "pbb-cardBody" }, deviceMessage ? (0, react.createElement)("p", { className: "pbb-diag" + (deviceMessage.startsWith(translateWith(props.t, "devices.renameFailed")) || deviceMessage.startsWith(translateWith(props.t, "devices.revokeFailed")) ? " pbb-diagBad" : "") }, deviceMessage) : null, deviceTable)), (0, react.createElement)("details", {
|
|
4753
|
-
className: "pbb-card pbb-disclosure",
|
|
4754
|
-
open: troubleshootingOpen,
|
|
4755
|
-
onToggle: (event) => setTroubleshootingOpen(event.currentTarget.open)
|
|
4756
|
-
}, (0, react.createElement)("summary", null, (0, react.createElement)("span", { className: "pbb-disclosureTitle" }, translateWith(props.t, "troubleshooting.summary")), (0, react.createElement)("span", { className: "pbb-disclosureMeta" }, relayTestResult !== null ? relayTestResult.overall === "ok" ? translateWith(props.t, "push.relayOk") : translateWith(props.t, "push.relayBad") : pushTestResult !== null ? pushTestResult.overall === "sent" ? translateWith(props.t, "push.pushSent") : translateWith(props.t, "push.pushFailed") : translateWith(props.t, "troubleshooting.title"))), (0, react.createElement)("div", { className: "pbb-disclosureBody" }, (0, react.createElement)("div", { className: "pbb-sectionIntro" }, (0, react.createElement)("h3", { className: "pbb-cardTitle" }, translateWith(props.t, "troubleshooting.title")), (0, react.createElement)("p", { className: "pbb-cardDescription" }, translateWith(props.t, "troubleshooting.description"))), (0, react.createElement)("div", { className: "pbb-testGrid" }, (0, react.createElement)("div", { className: "pbb-testItem" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("span", { className: "pbb-testTitle" }, translateWith(props.t, "push.relayTitle")), (0, react.createElement)("span", { className: "pbb-testDescription" }, translateWith(props.t, "push.relayDefault"))), (0, react.createElement)("button", {
|
|
4934
|
+
className: "pbb-cardHead",
|
|
4935
|
+
"aria-expanded": troubleshootingOpen,
|
|
4936
|
+
onClick: () => setTroubleshootingOpen(!troubleshootingOpen)
|
|
4937
|
+
}, (0, react.createElement)("span", { className: "pbb-chev" }, ChevronIcon()), (0, react.createElement)("span", { className: "pbb-cardTitle" }, translateWith(props.t, "troubleshooting.summary")), (0, react.createElement)("span", { className: "pbb-cardSummary" }, translateWith(props.t, "troubleshooting.description")), (0, react.createElement)("span", { className: "pbb-badge" + (troubleGood ? " pbb-badgeOk" : troubleBad ? " pbb-badgeWarn" : "") }, troubleConclusion)), fold(troubleshootingOpen, (0, react.createElement)("div", { className: "pbb-cardBody" }, (0, react.createElement)("div", { className: "pbb-testGrid" }, (0, react.createElement)("div", { className: "pbb-testItem" }, (0, react.createElement)("div", { className: "pbb-switchText" }, (0, react.createElement)("span", { className: "pbb-testTitle" }, translateWith(props.t, "push.relayTitle")), (0, react.createElement)("span", { className: "pbb-testDescription" }, translateWith(props.t, "push.relayDefault"))), (0, react.createElement)("button", {
|
|
4757
4938
|
type: "button",
|
|
4758
4939
|
className: "pbb-action",
|
|
4759
4940
|
disabled: relayTestBusy,
|
|
@@ -4773,21 +4954,26 @@ window.__ModuleLoader__.load({
|
|
|
4773
4954
|
onClick: () => {
|
|
4774
4955
|
if (can("setDebug")) props.setDeepPilotDebug(!debugEnabled);
|
|
4775
4956
|
}
|
|
4776
|
-
}))), relayTestError ? (0, react.createElement)("p", {
|
|
4777
|
-
className: "pbb-diag",
|
|
4778
|
-
|
|
4779
|
-
},
|
|
4780
|
-
className: "pbb-diag",
|
|
4781
|
-
|
|
4782
|
-
},
|
|
4783
|
-
|
|
4957
|
+
}))), relayTestError ? (0, react.createElement)("p", {
|
|
4958
|
+
className: "pbb-diag pbb-diagBad",
|
|
4959
|
+
role: "alert"
|
|
4960
|
+
}, relayTestError) : null, relayTestResult === null ? null : (0, react.createElement)("div", { className: "pbb-helpBody" }, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("span", { className: "pbb-label" }, relayTestResult.url || translateWith(props.t, "push.relayUrlEmpty")), (0, react.createElement)("code", { className: "pbb-token " + (relayTestResult.overall === "ok" ? "pbb-ok" : "pbb-bad") }, relayTestResult.overall === "ok" ? translateWith(props.t, "push.relayOk") : translateWith(props.t, "push.relayBad"))), relayTestResult.steps.map((step, index) => resultRow(step.ok, (step.id === "health" ? translateWith(props.t, "push.relayStep.health") : translateWith(props.t, "push.relayStep.enroll")) + (step.latencyMs !== void 0 ? ` (${String(step.latencyMs)}ms)` : "") + " — " + step.message, String(index)))), pushTestError ? (0, react.createElement)("p", {
|
|
4961
|
+
className: "pbb-diag pbb-diagBad",
|
|
4962
|
+
role: "alert"
|
|
4963
|
+
}, pushTestError) : null, pushTestResult === null ? null : (0, react.createElement)("div", { className: "pbb-helpBody" }, (0, react.createElement)("div", { className: "pbb-row" }, (0, react.createElement)("code", { className: "pbb-token " + (pushTestResult.overall === "sent" ? "pbb-ok" : pushTestResult.overall === "failed" ? "pbb-bad" : "") }, pushTestResult.overall === "sent" ? translateWith(props.t, "push.pushSent") : pushTestResult.overall === "failed" ? translateWith(props.t, "push.pushFailed") : pushTestResult.overall === "no-targets" ? translateWith(props.t, "push.pushNoTargets") : translateWith(props.t, "push.pushNotEnabled"))), pushTestResult.message ? (0, react.createElement)("p", { className: "pbb-diag" }, pushTestResult.message) : null, pushTestResult.results.map((r, index) => resultRow(r.outcome === "sent", r.name + " [" + r.environment + "] — " + r.outcome + (r.reason ? "(" + r.reason + ")" : "") + (r.tokenFingerprint ? " token:" + r.tokenFingerprint + "…" : ""), String(index)))), diagnosticsSection))), report === null ? null : (0, react.createElement)("div", { className: "pbb-card" }, (0, react.createElement)("button", {
|
|
4964
|
+
type: "button",
|
|
4965
|
+
className: "pbb-cardHead",
|
|
4966
|
+
"aria-expanded": systemOpen,
|
|
4967
|
+
onClick: () => setSystemOpen(!systemOpen)
|
|
4968
|
+
}, (0, react.createElement)("span", { className: "pbb-chev" }, ChevronIcon()), (0, react.createElement)("span", { className: "pbb-cardTitle" }, translateWith(props.t, "system.summary")), (0, react.createElement)("span", { className: "pbb-cardSummary" }, translateWith(props.t, "system.description")), (0, react.createElement)("span", { className: "pbb-badge" + (report.updateAvailable === true ? " pbb-badgeOk" : "") }, "v" + report.pluginVersion + (report.updateAvailable === true ? " · " + translateWith(props.t, "update.badge") : ""))), fold(systemOpen, (0, react.createElement)("div", { className: "pbb-cardBody" }, (0, react.createElement)("div", { className: "pbb-sectionIntro" }, (0, react.createElement)("h3", { className: "pbb-cardTitle" }, translateWith(props.t, "system.title"))), (0, react.createElement)("div", { className: "pbb-runtimeList" }, (0, react.createElement)("div", { className: "pbb-runtimeRow" }, (0, react.createElement)("span", { className: "pbb-label" }, "DeepPilot"), (0, react.createElement)("span", { className: "pbb-value" }, "v" + report.pluginVersion)), (0, react.createElement)("div", { className: "pbb-runtimeRow" }, (0, react.createElement)("span", { className: "pbb-label" }, translateWith(props.t, "advanced.tailscaleVersion")), (0, react.createElement)("span", { className: "pbb-value" }, report.remote.tailscaleVersion ?? translateWith(props.t, "advanced.tailscaleVersionUnknown"))), advancedRows, report.updateAvailable === true ? (0, react.createElement)("a", {
|
|
4969
|
+
className: "pbb-updateRow",
|
|
4784
4970
|
href: typeof report.releaseUrl === "string" && /^https:\/\//.test(report.releaseUrl) ? report.releaseUrl : "https://github.com/Mars-Sea/dsh-deeppilot/releases",
|
|
4785
4971
|
target: "_blank",
|
|
4786
4972
|
rel: "noreferrer"
|
|
4787
|
-
}, translateWith(props.t, "update.badge"))) : null))), diag.length > 0 ? (0, react.createElement)("details", {
|
|
4973
|
+
}, (0, react.createElement)("span", null, translateWith(props.t, "update.badge")), (0, react.createElement)("span", { className: "pbb-chev" }, ChevronIcon())) : null)))), diag.length > 0 ? (0, react.createElement)("details", {
|
|
4788
4974
|
className: "pbb-card pbb-disclosure pbb-diagnostics",
|
|
4789
4975
|
open: failed
|
|
4790
|
-
}, (0, react.createElement)("summary", null, translateWith(props.t, "diag.summary")), (0, react.createElement)("div", { className: "pbb-disclosureBody" }, (0, react.createElement)("p", { className: "pbb-diag" + (failed ? " pbb-diagBad" : "") }, translateWith(props.t, "diag.prefix") + diag.join(" | ")))) : null);
|
|
4976
|
+
}, (0, react.createElement)("summary", null, (0, react.createElement)("span", { className: "pbb-chev" }, ChevronIcon()), (0, react.createElement)("span", { className: "pbb-disclosureTitle" }, translateWith(props.t, "diag.summary"))), (0, react.createElement)("div", { className: "pbb-disclosureBody" }, (0, react.createElement)("p", { className: "pbb-diag" + (failed ? " pbb-diagBad" : "") }, translateWith(props.t, "diag.prefix") + diag.join(" | ")))) : null);
|
|
4791
4977
|
}
|
|
4792
4978
|
//#endregion
|
|
4793
4979
|
//#region src/client/config-form.ts
|