@yezack/dsh-remote-mobile 1.9.2 → 1.10.2
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/CHANGELOG.md +86 -12
- package/LICENSE +21 -21
- package/README.md +273 -56
- package/README_EN.md +281 -58
- package/lib/auth/crypto.js +3 -1
- package/lib/auth/gate.d.ts +39 -9
- package/lib/auth/gate.js +231 -33
- package/lib/auth/tailscale.d.ts +24 -2
- package/lib/auth/tailscale.js +38 -3
- package/lib/auth/token.d.ts +22 -0
- package/lib/auth/token.js +61 -2
- package/lib/bridge/compat.d.ts +22 -2
- package/lib/bridge/compat.js +319 -76
- package/lib/bridge/directory-picker.d.ts +118 -0
- package/lib/bridge/directory-picker.js +617 -0
- package/lib/client.js +1051 -166
- package/lib/gateway/detector.d.ts +40 -0
- package/lib/gateway/detector.js +75 -0
- package/lib/gateway/secret.d.ts +23 -0
- package/lib/gateway/secret.js +65 -0
- package/lib/gateway/server.d.ts +108 -0
- package/lib/gateway/server.js +568 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +201 -22
- package/lib/routes/api.d.ts +15 -12
- package/lib/routes/api.js +126 -11
- package/lib/routes/login-page.js +402 -399
- package/lib/routes/register.d.ts +9 -0
- package/lib/routes/register.js +53 -0
- package/lib/startup-hint.d.ts +5 -0
- package/lib/startup-hint.js +72 -0
- package/package.json +4 -4
package/lib/client.js
CHANGED
|
@@ -47,10 +47,10 @@ __export(index_exports, {
|
|
|
47
47
|
inject: () => inject
|
|
48
48
|
});
|
|
49
49
|
module.exports = __toCommonJS(index_exports);
|
|
50
|
-
var
|
|
50
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
51
51
|
|
|
52
52
|
// src/client/components/MainSection.jsx
|
|
53
|
-
var
|
|
53
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
54
54
|
|
|
55
55
|
// src/client/api.js
|
|
56
56
|
var RM_API_BASE = (function() {
|
|
@@ -103,6 +103,13 @@ function updateAdvancedSecurityOptions(payload) {
|
|
|
103
103
|
body: JSON.stringify(payload)
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
|
+
function updateProxyConfig(payload) {
|
|
107
|
+
return safeFetchJson(RM_API_BASE + "update-options", {
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: { "Content-Type": "application/json" },
|
|
110
|
+
body: JSON.stringify(payload)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
106
113
|
function updateSecret(secret) {
|
|
107
114
|
return safeFetchJson(RM_API_BASE + "set-secret", {
|
|
108
115
|
method: "POST",
|
|
@@ -172,6 +179,13 @@ function resetStylesApi() {
|
|
|
172
179
|
headers: { "Content-Type": "application/json" }
|
|
173
180
|
});
|
|
174
181
|
}
|
|
182
|
+
function toggleDirectoryPickerApi(enabled) {
|
|
183
|
+
return safeFetchJson(RM_API_BASE + "directory-picker", {
|
|
184
|
+
method: "POST",
|
|
185
|
+
headers: { "Content-Type": "application/json" },
|
|
186
|
+
body: JSON.stringify({ enabled: Boolean(enabled) })
|
|
187
|
+
});
|
|
188
|
+
}
|
|
175
189
|
|
|
176
190
|
// src/client/qrcode.js
|
|
177
191
|
var generateQrSvg = (function() {
|
|
@@ -687,6 +701,18 @@ var generateQrSvg = (function() {
|
|
|
687
701
|
};
|
|
688
702
|
})();
|
|
689
703
|
|
|
704
|
+
// src/client/utils/access.js
|
|
705
|
+
function resolveAccessPort(status) {
|
|
706
|
+
const port = Number(status?.proxy?.activePort);
|
|
707
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
708
|
+
return null;
|
|
709
|
+
}
|
|
710
|
+
return port;
|
|
711
|
+
}
|
|
712
|
+
function buildDirectLink(host, port, token) {
|
|
713
|
+
return `http://${host}:${port}/auth?token=${token || ""}`;
|
|
714
|
+
}
|
|
715
|
+
|
|
690
716
|
// src/client/components/NetworkCard.jsx
|
|
691
717
|
var import_react = __toESM(require("react"), 1);
|
|
692
718
|
|
|
@@ -798,6 +824,30 @@ var translations = {
|
|
|
798
824
|
saveConfigSuccessToast: "\u9AD8\u7EA7\u5B89\u5168\u53C2\u6570\u5DF2\u6210\u529F\u4FDD\u5B58\u5E76\u540C\u6B65\u5230 settings.json\uFF01",
|
|
799
825
|
restoreDefaultsSuccessToast: "\u5DF2\u6210\u529F\u6062\u590D\u9ED8\u8BA4\u5B89\u5168\u53C2\u6570\u5E76\u7ACB\u5373\u751F\u6548\uFF01",
|
|
800
826
|
saveConfigFailTip: "\u53C2\u6570\u5FC5\u987B\u4E3A\u5927\u4E8E 0 \u7684\u6709\u6548\u6574\u6570",
|
|
827
|
+
// 卡片 9: 接入代理配置
|
|
828
|
+
proxyConfigCardTitle: "\u63A5\u5165\u4EE3\u7406\u914D\u7F6E",
|
|
829
|
+
proxyConfigCardDesc: "\u63A7\u5236\u63A5\u5165\u6A21\u5F0F\u3001\u4EE3\u7406\u76D1\u542C\u5730\u5740\u4E0E\u53D7\u4FE1\u4EFB\u57DF\u540D\u3002\u4FDD\u5B58\u540E\u9700\u91CD\u542F DSH \u751F\u6548\u3002",
|
|
830
|
+
proxyModeLabel: "\u63A5\u5165\u6A21\u5F0F",
|
|
831
|
+
proxyModeHint: "proxy\uFF1A\u6838\u5FC3\u56DE\u73AF\uFF0C\u7531\u63D2\u4EF6\u8F6C\u53D1\uFF1Bdirect\uFF1A\u4E0D\u542F\u52A8\u4EE3\u7406\uFF0C\u76F4\u63A5\u8BBF\u95EE\u6838\u5FC3",
|
|
832
|
+
proxyModeProxy: "\u5B89\u5168\u63A5\u5165\u4EE3\u7406\uFF08proxy\uFF09",
|
|
833
|
+
proxyModeDirect: "\u76F4\u8FDE\u6838\u5FC3\uFF08direct\uFF09",
|
|
834
|
+
proxyPortLabel: "\u4EE3\u7406\u7AEF\u53E3",
|
|
835
|
+
proxyPortHint: "\u9ED8\u8BA4 3081\uFF1B\u7AEF\u53E3\u5360\u7528\u65F6\u4F1A\u81EA\u52A8\u9012\u589E",
|
|
836
|
+
proxyHostLabel: "\u4EE3\u7406\u76D1\u542C\u5730\u5740",
|
|
837
|
+
proxyHostHint: "0.0.0.0 \u8868\u793A\u6240\u6709\u7F51\u5361\uFF1B127.0.0.1 \u4EC5\u672C\u673A",
|
|
838
|
+
proxyTrustedHostsLabel: "\u53D7\u4FE1\u4EFB\u57DF\u540D",
|
|
839
|
+
proxyTrustedHostsHint: "\u6BCF\u884C\u4E00\u4E2A\uFF0C\u4F8B\u5982 xxx.tailnet.ts.net\uFF1B\u81EA\u5B9A\u4E49\u53CD\u4EE3\u57DF\u540D\u5FC5\u987B\u52A0\u5165",
|
|
840
|
+
proxyRestartNote: "\u4FDD\u5B58\u540E\u9700\u91CD\u542F DSH \u624D\u4F1A\u91CD\u65B0\u7ED1\u5B9A\u76D1\u542C\u5730\u5740/\u7AEF\u53E3\u3002",
|
|
841
|
+
proxySaveBtn: "\u{1F4BE} \u4FDD\u5B58\u63A5\u5165\u914D\u7F6E",
|
|
842
|
+
proxySavingBtn: "\u6B63\u5728\u4FDD\u5B58...",
|
|
843
|
+
proxyResetBtn: "\u{1F504} \u6062\u590D\u9ED8\u8BA4",
|
|
844
|
+
proxySaveConfirm: "\u786E\u5B9A\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u5417\uFF1F\u4FDD\u5B58\u540E\u9700\u91CD\u542F DSH \u751F\u6548\u3002",
|
|
845
|
+
proxyResetConfirm: "\u786E\u5B9A\u6062\u590D\u9ED8\u8BA4\u63A5\u5165\u914D\u7F6E\uFF08proxy\u30013081\u30010.0.0.0\u3001\u65E0\u53D7\u4FE1\u4EFB\u57DF\u540D\uFF09\u5417\uFF1F",
|
|
846
|
+
proxySavedToast: "\u63A5\u5165\u914D\u7F6E\u5DF2\u4FDD\u5B58\uFF1B\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
|
|
847
|
+
proxyResetToast: "\u5DF2\u6062\u590D\u9ED8\u8BA4\u63A5\u5165\u914D\u7F6E\uFF1B\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
|
|
848
|
+
proxySaveFailTip: "\u8BF7\u68C0\u67E5\u7AEF\u53E3\u3001\u76D1\u542C\u5730\u5740\u4E0E\u53D7\u4FE1\u4EFB\u57DF\u540D\u683C\u5F0F",
|
|
849
|
+
proxyCurrentRuntime: "\u5F53\u524D\u8FD0\u884C",
|
|
850
|
+
proxyNotReady: "\u5B89\u5168\u63A5\u5165\u4EE3\u7406\u672A\u5C31\u7EEA\uFF0C\u8BF7\u5148\u542F\u52A8\u4EE3\u7406",
|
|
801
851
|
// 卡片 8: 移动端样式片段(样式小插件)
|
|
802
852
|
tabAccess: "\u63A5\u5165",
|
|
803
853
|
tabDevices: "\u8BBE\u5907\u4E0E\u5B89\u5168",
|
|
@@ -841,6 +891,26 @@ var translations = {
|
|
|
841
891
|
conflictReportText: "[DSH \u63D2\u4EF6\u51B2\u7A81\u8BCA\u65AD\u62A5\u544A]\n\u73B0\u8C61\uFF1Adsh-remote-mobile \u8BBE\u7F6E\u9762\u677F\u63D0\u793A\u300C\u68C0\u6D4B\u5230\u5176\u4ED6\u8FDC\u7A0B\u63A5\u5165\u63D2\u4EF6\u300D\u3002\n\u539F\u56E0\uFF1A\u53E6\u4E00\u6B3E\u8FDC\u7A0B/Web \u63A5\u5165\u7C7B\u63D2\u4EF6\u5360\u7528\u4E86 Cordis \u5171\u4EAB\u670D\u52A1 remoteWebUiPairing\uFF0Cdsh-remote-mobile \u4E3A\u4FDD\u8BC1\u6B63\u5E38\u542F\u52A8\u5DF2\u81EA\u52A8\u8BA9\u51FA\u8BE5\u670D\u52A1\uFF0C\u5F53\u524D\u4E24\u5957\u8FDC\u7A0B\u63A5\u5165\u529F\u80FD\u5E76\u5B58\u3002\n\u5360\u7528\u65B9\u63D2\u4EF6\u5305\u540D\uFF1A{plugin}\n\u5360\u7528\u65B9 loader entry id\uFF1A{entryId}\n\u5904\u7406\u65B9\u6848\uFF08\u4E8C\u9009\u4E00\uFF09\uFF1A\n\u65B9\u6848 A\uFF08\u4FDD\u7559 dsh-remote-mobile\uFF0C\u7981\u7528\u5360\u7528\u65B9\uFF09\uFF1A\n1. \u6253\u5F00\u914D\u7F6E\u6587\u4EF6 ~/.dsh/profiles/web/cordis.patch.yml\n2. \u5728\u6587\u4EF6\u672B\u5C3E\u8FFD\u52A0\u4EE5\u4E0B\u4E24\u884C\uFF08\u6CE8\u610F YAML \u7F29\u8FDB\uFF0C\u7B2C\u4E8C\u884C\u524D\u6709\u4E24\u4E2A\u7A7A\u683C\uFF09\uFF1A\n- id: {entryId}\n disabled: true\n3. \u7ED3\u675F\u5F53\u524D\u6B63\u5728\u8FD0\u884C\u7684 dsh web \u8FDB\u7A0B\uFF0C\u91CD\u65B0\u6267\u884C dsh web --no-open\n\u65B9\u6848 B\uFF08\u4FDD\u7559\u5360\u7528\u65B9\uFF0C\u5378\u8F7D dsh-remote-mobile\uFF09\uFF1A\n\u6267\u884C\u547D\u4EE4 dsh plugin --profile web remove dsh-remote-mobile \u540E\u91CD\u542F dsh web",
|
|
842
892
|
conflictReportNoEntryIdText: "[DSH \u63D2\u4EF6\u51B2\u7A81\u8BCA\u65AD\u62A5\u544A]\n\u73B0\u8C61\uFF1Adsh-remote-mobile \u8BBE\u7F6E\u9762\u677F\u63D0\u793A\u300C\u68C0\u6D4B\u5230\u5176\u4ED6\u8FDC\u7A0B\u63A5\u5165\u63D2\u4EF6\u300D\u3002\n\u539F\u56E0\uFF1A\u53E6\u4E00\u6B3E\u8FDC\u7A0B/Web \u63A5\u5165\u7C7B\u63D2\u4EF6\u5360\u7528\u4E86 Cordis \u5171\u4EAB\u670D\u52A1 remoteWebUiPairing\uFF0Cdsh-remote-mobile \u4E3A\u4FDD\u8BC1\u6B63\u5E38\u542F\u52A8\u5DF2\u81EA\u52A8\u8BA9\u51FA\u8BE5\u670D\u52A1\uFF0C\u5F53\u524D\u4E24\u5957\u8FDC\u7A0B\u63A5\u5165\u529F\u80FD\u5E76\u5B58\u3002\n\u5360\u7528\u65B9\u63D2\u4EF6\u5305\u540D\uFF1A{plugin}\n\u5360\u7528\u65B9 loader entry id\uFF1A\u672A\u80FD\u81EA\u52A8\u8BC6\u522B\n\u5904\u7406\u65B9\u6848\uFF08\u4E8C\u9009\u4E00\uFF09\uFF1A\n\u65B9\u6848 A\uFF08\u4FDD\u7559 dsh-remote-mobile\uFF0C\u7981\u7528\u5360\u7528\u65B9\uFF09\uFF1A\n1. \u6267\u884C dsh --dump-config \u67E5\u770B\u5168\u90E8 loader entry\uFF0C\u627E\u5230\u5360\u7528\u65B9\u63D2\u4EF6\u5BF9\u5E94\u7684\u6761\u76EE id\n2. \u6253\u5F00\u914D\u7F6E\u6587\u4EF6 ~/.dsh/profiles/web/cordis.patch.yml\uFF0C\u5728\u6587\u4EF6\u672B\u5C3E\u8FFD\u52A0\uFF08\u6CE8\u610F YAML \u7F29\u8FDB\uFF09\uFF1A\n- id: <\u5360\u7528\u65B9\u6761\u76EEid>\n disabled: true\n3. \u7ED3\u675F\u5F53\u524D\u6B63\u5728\u8FD0\u884C\u7684 dsh web \u8FDB\u7A0B\uFF0C\u91CD\u65B0\u6267\u884C dsh web --no-open\n\u65B9\u6848 B\uFF08\u4FDD\u7559\u5360\u7528\u65B9\uFF0C\u5378\u8F7D dsh-remote-mobile\uFF09\uFF1A\n\u6267\u884C\u547D\u4EE4 dsh plugin --profile web remove dsh-remote-mobile \u540E\u91CD\u542F dsh web",
|
|
843
893
|
conflictBannerDismiss: "\u77E5\u9053\u4E86",
|
|
894
|
+
// 移动端目录选择器(添加工作区 / 选择文件夹)提醒与一键配置
|
|
895
|
+
dirPickerBannerTitle: "\u624B\u673A\u7AEF\u300C\u6DFB\u52A0\u5DE5\u4F5C\u533A / \u9009\u62E9\u6587\u4EF6\u5939\u300D\u53D7\u9650\u63D0\u9192",
|
|
896
|
+
dirPickerBannerBody: "\u5F53\u524D DSH \u6838\u5FC3\u7ED1\u5B9A\u5728\u672C\u5730\u56DE\u73AF\uFF08127.0.0.1\uFF09\uFF0C\u5B98\u65B9\u76EE\u5F55\u9009\u62E9\u5668\uFF08dsh-host-directory-picker-auto\uFF09\u4F1A\u5C06\u6765\u81EA 3081 \u4EE3\u7406\u7684\u624B\u673A\u8BF7\u6C42\u8BEF\u5224\u4E3A\u300C\u672C\u673A\u64CD\u4F5C\u300D\uFF0C\u4ECE\u800C\u628A\u6587\u4EF6\u5939\u9009\u62E9\u7A97\u53E3\u5F39\u5728\u7535\u8111\u5C4F\u5E55\u4E0A\uFF0C\u5BFC\u81F4\u624B\u673A\u7AEF\u4E00\u76F4\u7B49\u5F85\u3001\u65E0\u6CD5\u6DFB\u52A0\u5DE5\u4F5C\u533A\u3002\n\u53EF\u70B9\u51FB\u4E0B\u65B9\u6309\u94AE\u4E00\u952E\u5199\u5165\u7F51\u9875\u5185\u76EE\u5F55\u9009\u62E9\u5668\uFF08browse \u6A21\u5F0F\uFF0C\u5DF2\u5185\u7F6E\u9632\u91CD\u590D\u53BB\u91CD\uFF09\uFF0C\u5F00\u542F\u540E\u624B\u673A\u4E0E\u7535\u8111\u5747\u53EF\u76F4\u63A5\u5728\u7F51\u9875\u5185\u6D4F\u89C8\u5E76\u9009\u62E9\u6587\u4EF6\u5939\u3002",
|
|
897
|
+
dirPickerEnableBtn: "\u26A1 \u4E00\u952E\u5F00\u542F\u7F51\u9875\u76EE\u5F55\u9009\u62E9\u5668",
|
|
898
|
+
dirPickerEnablingBtn: "\u6B63\u5728\u5199\u5165\u914D\u7F6E...",
|
|
899
|
+
dirPickerCopyYamlBtn: "\u{1F4CB} \u590D\u5236 YAML \u914D\u7F6E",
|
|
900
|
+
dirPickerCopiedYamlTip: "\u5DF2\u590D\u5236\u76EE\u5F55\u9009\u62E9\u5668 YAML \u914D\u7F6E\uFF0C\u53EF\u7C98\u8D34\u5230 cordis.patch.yml",
|
|
901
|
+
dirPickerBannerDismiss: "\u6682\u4E0D\u5904\u7406",
|
|
902
|
+
dirPickerRestartBannerTitle: "\u7F51\u9875\u76EE\u5F55\u9009\u62E9\u5668\u914D\u7F6E\u5DF2\u5199\u5165\uFF08\u7B49\u5F85\u751F\u6548\uFF09",
|
|
903
|
+
dirPickerRestartBannerBody: "\u5DF2\u5C06\u7F51\u9875\u5185\u76EE\u5F55\u9009\u62E9\u5668\u914D\u7F6E\u5199\u5165 {path}\u3002\u82E5 DSH \u672A\u81EA\u52A8\u70ED\u91CD\u8F7D\uFF0C\u8BF7\u91CD\u542F dsh web \u5E76\u5237\u65B0\u624B\u673A\u9875\u9762\uFF0C\u5373\u53EF\u5728\u624B\u673A\u7AEF\u6B63\u5E38\u6DFB\u52A0\u5DE5\u4F5C\u533A\u3002",
|
|
904
|
+
dirPickerEnabledToast: "\u5DF2\u6210\u529F\u5199\u5165\u7F51\u9875\u76EE\u5F55\u9009\u62E9\u5668\u914D\u7F6E\uFF01\u82E5\u672A\u81EA\u52A8\u70ED\u91CD\u8F7D\uFF0C\u8BF7\u91CD\u542F dsh web \u751F\u6548\u3002",
|
|
905
|
+
dirPickerDisabledToast: "\u5DF2\u79FB\u9664\u7F51\u9875\u76EE\u5F55\u9009\u62E9\u5668\u914D\u7F6E\uFF08\u6062\u590D PC \u539F\u751F\u5F39\u7A97\uFF09\uFF0C\u91CD\u542F dsh web \u540E\u751F\u6548\u3002",
|
|
906
|
+
dirPickerDisableConfirm: "\u786E\u5B9A\u8981\u6062\u590D\u4E3A PC \u539F\u751F\u7CFB\u7EDF\u76EE\u5F55\u9009\u62E9\u5668\u5417\uFF1F\n\n\u6062\u590D\u540E\uFF0C\u7535\u8111\u7AEF\u5C06\u91CD\u65B0\u5F39\u51FA macOS / Windows \u539F\u751F\u6587\u4EF6\u5939\u7A97\u53E3\uFF0C\u4F46\u624B\u673A\u7AEF\u70B9\u51FB\u300C\u6DFB\u52A0\u5DE5\u4F5C\u533A / \u9009\u62E9\u6587\u4EF6\u5939\u300D\u65F6\u4F1A\u5F39\u5728\u7535\u8111\u684C\u9762\u4E0A\uFF0C\u5BFC\u81F4\u624B\u673A\u7AEF\u65E0\u6CD5\u72EC\u7ACB\u6DFB\u52A0\u5DE5\u4F5C\u533A\u3002",
|
|
907
|
+
dirPickerSectionTitle: "\u{1F4C1} \u79FB\u52A8\u7AEF\u6DFB\u52A0\u5DE5\u4F5C\u533A\uFF08\u76EE\u5F55\u9009\u62E9\u5668\u6A21\u5F0F\uFF09",
|
|
908
|
+
dirPickerSectionDesc: "\u63A7\u5236\u70B9\u51FB\u300C\u6DFB\u52A0\u5DE5\u4F5C\u533A / \u9009\u62E9\u6587\u4EF6\u5939\u300D\u65F6\u4F7F\u7528\u7F51\u9875\u5185\u76EE\u5F55\u6D4F\u89C8\u5668\uFF08\u624B\u673A+\u7535\u8111\u901A\u7528\uFF09\u8FD8\u662F\u7535\u8111\u7CFB\u7EDF\u539F\u751F\u5F39\u7A97\uFF08\u4EC5\u7535\u8111\u53EF\u7528\uFF09\u3002\u63D2\u4EF6\u5728\u5199\u5165 cordis.patch.yml \u65F6\u4F1A\u81EA\u52A8\u6267\u884C\u4E25\u683C\u5E42\u7B49\u53BB\u91CD\u3002",
|
|
909
|
+
dirPickerStatusActive: "\u{1F7E2} \u5DF2\u542F\u7528\u7F51\u9875\u5185\u76EE\u5F55\u9009\u62E9\u5668\uFF08\u624B\u673A\u7AEF\u53EF\u6B63\u5E38\u6DFB\u52A0\u5DE5\u4F5C\u533A\uFF09",
|
|
910
|
+
dirPickerStatusPendingRestart: "\u23F3 \u5DF2\u5199\u5165\u914D\u7F6E\uFF08\u91CD\u542F DSH \u6216\u70ED\u91CD\u8F7D\u540E\u751F\u6548\uFF09",
|
|
911
|
+
dirPickerStatusNativeWarn: "\u26A0\uFE0F \u5F53\u524D\u4E3A\u7CFB\u7EDF\u539F\u751F\u5F39\u7A97\uFF08\u624B\u673A\u7AEF\u65E0\u6CD5\u9009\u62E9\u6587\u4EF6\u5939\uFF09",
|
|
912
|
+
dirPickerRestoreNativeBtn: "\u{1F504} \u6062\u590D PC \u539F\u751F\u76EE\u5F55\u9009\u62E9\u5668",
|
|
913
|
+
dirPickerPatchFileLabel: "\u76EE\u6807\u914D\u7F6E\u6587\u4EF6\uFF1A",
|
|
844
914
|
// Toast 提示
|
|
845
915
|
toastDeviceConnected: "\u{1F389} \u65B0\u8BBE\u5907\u63A5\u5165\u6210\u529F\uFF1A{name} ({ip})",
|
|
846
916
|
toastDeviceOnline: "\u{1F4F6} \u8BBE\u5907\u91CD\u65B0\u4E0A\u7EBF\uFF1A{name} ({ip})",
|
|
@@ -952,6 +1022,30 @@ var translations = {
|
|
|
952
1022
|
saveConfigSuccessToast: "Security policy successfully saved and synced to settings.json!",
|
|
953
1023
|
restoreDefaultsSuccessToast: "Default security policies restored and applied immediately!",
|
|
954
1024
|
saveConfigFailTip: "Parameters must be valid integers greater than 0",
|
|
1025
|
+
// Card 9: Access Proxy Configuration
|
|
1026
|
+
proxyConfigCardTitle: "Access Proxy Configuration",
|
|
1027
|
+
proxyConfigCardDesc: "Configure the access mode, proxy listener, and trusted hosts. Restart DSH after saving.",
|
|
1028
|
+
proxyModeLabel: "Access mode",
|
|
1029
|
+
proxyModeHint: "proxy: core stays on loopback and the plugin forwards; direct: no proxy, access the core directly",
|
|
1030
|
+
proxyModeProxy: "Secure access proxy (proxy)",
|
|
1031
|
+
proxyModeDirect: "Direct core (direct)",
|
|
1032
|
+
proxyPortLabel: "Proxy port",
|
|
1033
|
+
proxyPortHint: "Default 3081; automatically increments if occupied",
|
|
1034
|
+
proxyHostLabel: "Proxy listen address",
|
|
1035
|
+
proxyHostHint: "0.0.0.0 means all interfaces; 127.0.0.1 means local only",
|
|
1036
|
+
proxyTrustedHostsLabel: "Trusted hosts",
|
|
1037
|
+
proxyTrustedHostsHint: "One per line, e.g. xxx.tailnet.ts.net; custom reverse-proxy domains must be listed",
|
|
1038
|
+
proxyRestartNote: "Restart DSH after saving to rebind the listen address/port.",
|
|
1039
|
+
proxySaveBtn: "\u{1F4BE} Save Access Config",
|
|
1040
|
+
proxySavingBtn: "Saving...",
|
|
1041
|
+
proxyResetBtn: "\u{1F504} Restore Defaults",
|
|
1042
|
+
proxySaveConfirm: "Save the access configuration? A DSH restart is required.",
|
|
1043
|
+
proxyResetConfirm: "Restore defaults (proxy, 3081, 0.0.0.0, no trusted hosts)?",
|
|
1044
|
+
proxySavedToast: "Access configuration saved; restart DSH to apply.",
|
|
1045
|
+
proxyResetToast: "Default access configuration restored; restart DSH to apply.",
|
|
1046
|
+
proxySaveFailTip: "Check the port, listen address, and trusted-host format",
|
|
1047
|
+
proxyCurrentRuntime: "Current runtime",
|
|
1048
|
+
proxyNotReady: "Secure access proxy is not ready. Start the proxy first.",
|
|
955
1049
|
// Card 8: Mobile Style Snippets (style mini-plugin)
|
|
956
1050
|
tabAccess: "Access",
|
|
957
1051
|
tabDevices: "Devices & Security",
|
|
@@ -995,6 +1089,26 @@ var translations = {
|
|
|
995
1089
|
conflictReportText: '[DSH plugin conflict diagnosis]\nSymptom: the dsh-remote-mobile settings panel shows "Another remote-access plugin detected".\nCause: another remote/Web access plugin registered the shared Cordis service remoteWebUiPairing first; dsh-remote-mobile yielded it to keep startup safe, so both remote features now run in parallel.\nConflicting plugin package: {plugin}\nConflicting loader entry id: {entryId}\nFix (choose ONE):\nOption A (keep dsh-remote-mobile, disable the other):\n1. Open ~/.dsh/profiles/web/cordis.patch.yml\n2. Append these two lines at the end (mind YAML indentation, two spaces before disabled):\n- id: {entryId}\n disabled: true\n3. Stop the running dsh web process, then run dsh web --no-open again\nOption B (keep the other, remove dsh-remote-mobile):\nRun dsh plugin --profile web remove dsh-remote-mobile and restart dsh web',
|
|
996
1090
|
conflictReportNoEntryIdText: '[DSH plugin conflict diagnosis]\nSymptom: the dsh-remote-mobile settings panel shows "Another remote-access plugin detected".\nCause: another remote/Web access plugin registered the shared Cordis service remoteWebUiPairing first; dsh-remote-mobile yielded it to keep startup safe, so both remote features now run in parallel.\nConflicting plugin package: {plugin}\nConflicting loader entry id: could not be detected automatically\nFix (choose ONE):\nOption A (keep dsh-remote-mobile, disable the other):\n1. Run dsh --dump-config to list all loader entries and find the entry id of the conflicting plugin\n2. Open ~/.dsh/profiles/web/cordis.patch.yml and append at the end (mind YAML indentation):\n- id: <the conflicting entry id>\n disabled: true\n3. Stop the running dsh web process, then run dsh web --no-open again\nOption B (keep the other, remove dsh-remote-mobile):\nRun dsh plugin --profile web remove dsh-remote-mobile and restart dsh web',
|
|
997
1091
|
conflictBannerDismiss: "Got it",
|
|
1092
|
+
// Mobile directory picker (Add Workspace / Select Folder) reminder & one-click patch
|
|
1093
|
+
dirPickerBannerTitle: 'Mobile "Add Workspace / Select Folder" Limitation',
|
|
1094
|
+
dirPickerBannerBody: "Because the DSH core stays on loopback (127.0.0.1), the official auto directory picker (dsh-host-directory-picker-auto) mistakes mobile requests via proxy 3081 for local desktop sessions and opens the native OS folder dialog on your PC screen \u2014 leaving your phone stuck waiting and unable to add workspaces.\nClick below to enable the in-app web directory browser (browse mode, with strict deduplication) so both mobile and PC can pick folders directly inside the web UI.",
|
|
1095
|
+
dirPickerEnableBtn: "\u26A1 Enable In-App Directory Browser",
|
|
1096
|
+
dirPickerEnablingBtn: "Applying patch...",
|
|
1097
|
+
dirPickerCopyYamlBtn: "\u{1F4CB} Copy YAML Snippet",
|
|
1098
|
+
dirPickerCopiedYamlTip: "YAML snippet copied! Paste it into cordis.patch.yml",
|
|
1099
|
+
dirPickerBannerDismiss: "Dismiss",
|
|
1100
|
+
dirPickerRestartBannerTitle: "In-App Directory Browser Configured (Pending Reload)",
|
|
1101
|
+
dirPickerRestartBannerBody: "Configuration has been written to {path}. If DSH does not hot-reload automatically, please restart dsh web and refresh your mobile browser to add workspaces on mobile.",
|
|
1102
|
+
dirPickerEnabledToast: "In-app directory browser enabled! Restart dsh web if HMR did not reload automatically.",
|
|
1103
|
+
dirPickerDisabledToast: "Restored PC native directory picker; restart dsh web to apply.",
|
|
1104
|
+
dirPickerDisableConfirm: "Restore the PC native OS folder dialog?\n\nOnce restored, PC will open the native macOS / Windows folder window again, but mobile devices will NOT be able to pick folders or add workspaces.",
|
|
1105
|
+
dirPickerSectionTitle: "\u{1F4C1} Mobile Workspace Directory Picker Mode",
|
|
1106
|
+
dirPickerSectionDesc: "Choose between the in-app web directory browser (works on both mobile and PC) and the native OS folder dialog (PC only). Writing to cordis.patch.yml automatically deduplicates entries.",
|
|
1107
|
+
dirPickerStatusActive: "\u{1F7E2} In-App Web Directory Browser Enabled (Mobile Ready)",
|
|
1108
|
+
dirPickerStatusPendingRestart: "\u23F3 Configured in patch file (Restart DSH or wait for HMR)",
|
|
1109
|
+
dirPickerStatusNativeWarn: "\u26A0\uFE0F Native OS Dialog Active (Mobile cannot add workspaces)",
|
|
1110
|
+
dirPickerRestoreNativeBtn: "\u{1F504} Restore PC Native Picker",
|
|
1111
|
+
dirPickerPatchFileLabel: "Target patch file: ",
|
|
998
1112
|
// Toast
|
|
999
1113
|
toastDeviceConnected: "\u{1F389} New device connected: {name} ({ip})",
|
|
1000
1114
|
toastDeviceOnline: "\u{1F4F6} Device reconnected: {name} ({ip})",
|
|
@@ -1065,7 +1179,10 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
1065
1179
|
function NetworkCard({ status, toggleTailscale, toggleLan, copyText, lang }) {
|
|
1066
1180
|
const tsHost = status.tailscaleIp || "100.x.y.z";
|
|
1067
1181
|
const lanHost = status.lanIp || "127.0.0.1";
|
|
1068
|
-
const port =
|
|
1182
|
+
const port = resolveAccessPort(status);
|
|
1183
|
+
const portReady = port !== null;
|
|
1184
|
+
const tailscaleAddress = portReady ? `http://${tsHost}:${port}` : null;
|
|
1185
|
+
const lanAddress = portReady ? `http://${lanHost}:${port}` : null;
|
|
1069
1186
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1070
1187
|
"div",
|
|
1071
1188
|
{
|
|
@@ -1099,6 +1216,29 @@ function NetworkCard({ status, toggleTailscale, toggleLan, copyText, lang }) {
|
|
|
1099
1216
|
children: t("netCardDesc", lang)
|
|
1100
1217
|
}
|
|
1101
1218
|
),
|
|
1219
|
+
status?.proxy?.mode === "proxy" && status.proxy.running === false ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1220
|
+
"div",
|
|
1221
|
+
{
|
|
1222
|
+
style: {
|
|
1223
|
+
background: "rgba(239, 68, 68, 0.12)",
|
|
1224
|
+
border: "1px solid rgba(239, 68, 68, 0.35)",
|
|
1225
|
+
borderRadius: "8px",
|
|
1226
|
+
padding: "10px 12px",
|
|
1227
|
+
marginBottom: "16px",
|
|
1228
|
+
fontSize: "12px",
|
|
1229
|
+
color: "var(--dsw-alias-label-error, #ef4444)",
|
|
1230
|
+
lineHeight: "1.5",
|
|
1231
|
+
textAlign: "left"
|
|
1232
|
+
},
|
|
1233
|
+
children: [
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("strong", { children: [
|
|
1235
|
+
"\u26A0\uFE0F ",
|
|
1236
|
+
lang === "en" ? "Secure Proxy Not Ready" : "\u5B89\u5168\u63A5\u5165\u4EE3\u7406\u672A\u5C31\u7EEA"
|
|
1237
|
+
] }),
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: status.proxy.error ? `${lang === "en" ? "Failure reason: " : "\u542F\u52A8\u5931\u8D25\uFF1A"}${status.proxy.error}` : lang === "en" ? "Secure proxy is initializing or failed to bind port. External devices cannot connect currently." : "\u5B89\u5168\u63A5\u5165\u4EE3\u7406\u6B63\u5728\u542F\u52A8\u6216\u7AEF\u53E3\u7ED1\u5B9A\u5931\u8D25\uFF0C\u5916\u90E8\u624B\u673A\u8BBE\u5907\u5F53\u524D\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u3002" })
|
|
1239
|
+
]
|
|
1240
|
+
}
|
|
1241
|
+
) : null,
|
|
1102
1242
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1103
1243
|
"div",
|
|
1104
1244
|
{
|
|
@@ -1237,7 +1377,7 @@ function NetworkCard({ status, toggleTailscale, toggleLan, copyText, lang }) {
|
|
|
1237
1377
|
style: {
|
|
1238
1378
|
fontSize: "13px",
|
|
1239
1379
|
fontFamily: "monospace",
|
|
1240
|
-
color: "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
1380
|
+
color: portReady ? "var(--dsw-alias-brand-primary, #3b82f6)" : "var(--dsw-alias-label-error, #ef4444)",
|
|
1241
1381
|
display: "flex",
|
|
1242
1382
|
alignItems: "center",
|
|
1243
1383
|
justifyContent: "space-between",
|
|
@@ -1258,22 +1398,24 @@ function NetworkCard({ status, toggleTailscale, toggleLan, copyText, lang }) {
|
|
|
1258
1398
|
flex: 1,
|
|
1259
1399
|
minWidth: 0
|
|
1260
1400
|
},
|
|
1261
|
-
children:
|
|
1401
|
+
children: tailscaleAddress || t("proxyNotReady", lang)
|
|
1262
1402
|
}
|
|
1263
1403
|
),
|
|
1264
1404
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1265
1405
|
"button",
|
|
1266
1406
|
{
|
|
1267
1407
|
type: "button",
|
|
1268
|
-
|
|
1408
|
+
disabled: !portReady,
|
|
1409
|
+
onClick: () => tailscaleAddress && copyText(tailscaleAddress, t("copiedTip", lang)),
|
|
1269
1410
|
style: {
|
|
1270
1411
|
padding: "3px 10px",
|
|
1271
1412
|
background: "var(--dsw-alias-bg-layer-3, rgba(255, 255, 255, 0.08))",
|
|
1272
1413
|
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
1273
1414
|
borderRadius: "4px",
|
|
1274
1415
|
fontSize: "11px",
|
|
1275
|
-
cursor: "pointer",
|
|
1416
|
+
cursor: portReady ? "pointer" : "not-allowed",
|
|
1276
1417
|
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
1418
|
+
opacity: portReady ? 1 : 0.4,
|
|
1277
1419
|
whiteSpace: "nowrap",
|
|
1278
1420
|
flexShrink: 0
|
|
1279
1421
|
},
|
|
@@ -1423,7 +1565,7 @@ function NetworkCard({ status, toggleTailscale, toggleLan, copyText, lang }) {
|
|
|
1423
1565
|
style: {
|
|
1424
1566
|
fontSize: "13px",
|
|
1425
1567
|
fontFamily: "monospace",
|
|
1426
|
-
color: "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
1568
|
+
color: portReady ? "var(--dsw-alias-brand-primary, #3b82f6)" : "var(--dsw-alias-label-error, #ef4444)",
|
|
1427
1569
|
display: "flex",
|
|
1428
1570
|
alignItems: "center",
|
|
1429
1571
|
justifyContent: "space-between",
|
|
@@ -1444,22 +1586,24 @@ function NetworkCard({ status, toggleTailscale, toggleLan, copyText, lang }) {
|
|
|
1444
1586
|
flex: 1,
|
|
1445
1587
|
minWidth: 0
|
|
1446
1588
|
},
|
|
1447
|
-
children:
|
|
1589
|
+
children: lanAddress || t("proxyNotReady", lang)
|
|
1448
1590
|
}
|
|
1449
1591
|
),
|
|
1450
1592
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1451
1593
|
"button",
|
|
1452
1594
|
{
|
|
1453
1595
|
type: "button",
|
|
1454
|
-
|
|
1596
|
+
disabled: !portReady,
|
|
1597
|
+
onClick: () => lanAddress && copyText(lanAddress, t("copiedTip", lang)),
|
|
1455
1598
|
style: {
|
|
1456
1599
|
padding: "3px 10px",
|
|
1457
1600
|
background: "var(--dsw-alias-bg-layer-3, rgba(255, 255, 255, 0.08))",
|
|
1458
1601
|
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
1459
1602
|
borderRadius: "4px",
|
|
1460
1603
|
fontSize: "11px",
|
|
1461
|
-
cursor: "pointer",
|
|
1604
|
+
cursor: portReady ? "pointer" : "not-allowed",
|
|
1462
1605
|
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
1606
|
+
opacity: portReady ? 1 : 0.4,
|
|
1463
1607
|
whiteSpace: "nowrap",
|
|
1464
1608
|
flexShrink: 0
|
|
1465
1609
|
},
|
|
@@ -1568,10 +1712,12 @@ function QrPairingCard({
|
|
|
1568
1712
|
copyDirectLink,
|
|
1569
1713
|
lang
|
|
1570
1714
|
}) {
|
|
1571
|
-
const port =
|
|
1715
|
+
const port = resolveAccessPort(status);
|
|
1716
|
+
const portReady = port !== null;
|
|
1717
|
+
const proxyUnavailable = status?.proxy?.mode === "proxy" && status.proxy.running === false;
|
|
1572
1718
|
const isExpired = timeLeft <= 0;
|
|
1573
1719
|
const currentHost = selectedTab === "lan" && status.lanIp ? status.lanIp : status.tailscaleIp || status.lanIp || typeof window !== "undefined" && window.location.hostname || "127.0.0.1";
|
|
1574
|
-
const directLink =
|
|
1720
|
+
const directLink = portReady ? buildDirectLink(currentHost, port, status.code || "") : "";
|
|
1575
1721
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1576
1722
|
"div",
|
|
1577
1723
|
{
|
|
@@ -1606,7 +1752,51 @@ function QrPairingCard({
|
|
|
1606
1752
|
children: t("pairingCardDesc", lang)
|
|
1607
1753
|
}
|
|
1608
1754
|
),
|
|
1609
|
-
|
|
1755
|
+
status?.proxy?.mode === "proxy" && status.proxy.running === false ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1756
|
+
"div",
|
|
1757
|
+
{
|
|
1758
|
+
style: {
|
|
1759
|
+
background: "rgba(239, 68, 68, 0.12)",
|
|
1760
|
+
border: "1px solid rgba(239, 68, 68, 0.35)",
|
|
1761
|
+
borderRadius: "8px",
|
|
1762
|
+
padding: "12px 14px",
|
|
1763
|
+
marginBottom: "14px",
|
|
1764
|
+
fontSize: "13px",
|
|
1765
|
+
color: "var(--dsw-alias-label-error, #ef4444)",
|
|
1766
|
+
lineHeight: "1.6",
|
|
1767
|
+
textAlign: "left"
|
|
1768
|
+
},
|
|
1769
|
+
children: [
|
|
1770
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
|
|
1771
|
+
"\u26A0\uFE0F ",
|
|
1772
|
+
lang === "en" ? "Secure Proxy Error" : "\u5B89\u5168\u63A5\u5165\u4EE3\u7406\u672A\u5C31\u7EEA"
|
|
1773
|
+
] }),
|
|
1774
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { marginTop: "4px", fontSize: "12px" }, children: status.proxy.error ? `${lang === "en" ? "Failure reason: " : "\u542F\u52A8\u5931\u8D25\uFF1A"}${status.proxy.error}` : lang === "en" ? "Secure proxy is initializing or port binding failed. External devices cannot connect currently." : "\u5B89\u5168\u63A5\u5165\u4EE3\u7406\u6B63\u5728\u542F\u52A8\u6216\u7AEF\u53E3\u7ED1\u5B9A\u5931\u8D25\uFF0C\u5916\u90E8\u624B\u673A\u8BBE\u5907\u6682\u65F6\u65E0\u6CD5\u626B\u7801\u8FDE\u63A5\u3002" }),
|
|
1775
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { marginTop: "4px", fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #888)" }, children: lang === "en" ? "Tip: Check whether the secure proxy port (default 3081) is in use or inspect background logs." : "\u6392\u67E5\u5EFA\u8BAE\uFF1A\u8BF7\u68C0\u67E5\u5B89\u5168\u63A5\u5165\u4EE3\u7406\u7AEF\u53E3\uFF08\u9ED8\u8BA4 3081\uFF09\u662F\u5426\u88AB\u5176\u4ED6\u8FDB\u7A0B\u5360\u7528\uFF0C\u6216\u68C0\u67E5\u540E\u53F0\u7EC8\u7AEF\u65E5\u5FD7\u3002" })
|
|
1776
|
+
]
|
|
1777
|
+
}
|
|
1778
|
+
) : null,
|
|
1779
|
+
!portReady && !status.loading && !proxyUnavailable ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1780
|
+
"div",
|
|
1781
|
+
{
|
|
1782
|
+
style: {
|
|
1783
|
+
background: "rgba(245, 158, 11, 0.12)",
|
|
1784
|
+
border: "1px solid rgba(245, 158, 11, 0.35)",
|
|
1785
|
+
borderRadius: "8px",
|
|
1786
|
+
padding: "12px 14px",
|
|
1787
|
+
marginBottom: "14px",
|
|
1788
|
+
fontSize: "13px",
|
|
1789
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
1790
|
+
lineHeight: "1.6",
|
|
1791
|
+
textAlign: "left"
|
|
1792
|
+
},
|
|
1793
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
|
|
1794
|
+
"\u26A0\uFE0F ",
|
|
1795
|
+
t("proxyNotReady", lang)
|
|
1796
|
+
] })
|
|
1797
|
+
}
|
|
1798
|
+
) : null,
|
|
1799
|
+
showQr && portReady && !proxyUnavailable ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1610
1800
|
"div",
|
|
1611
1801
|
{
|
|
1612
1802
|
style: {
|
|
@@ -1767,28 +1957,30 @@ function QrPairingCard({
|
|
|
1767
1957
|
fontSize: "32px",
|
|
1768
1958
|
fontWeight: "800",
|
|
1769
1959
|
letterSpacing: showCode ? "6px" : "4px",
|
|
1770
|
-
color: isExpired ? "var(--dsw-alias-label-error, #ef4444)" : "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
1960
|
+
color: status?.proxy?.mode === "proxy" && status.proxy.running === false || isExpired ? "var(--dsw-alias-label-error, #ef4444)" : "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
1771
1961
|
fontFamily: "monospace",
|
|
1772
1962
|
userSelect: "all"
|
|
1773
1963
|
},
|
|
1774
|
-
children: isExpired ? lang === "en" ? "EXPIRED" : "\u5DF2\u8FC7\u671F" : showCode ? status.code : "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
1964
|
+
children: status?.proxy?.mode === "proxy" && status.proxy.running === false ? lang === "en" ? "DISABLED" : "\u5DF2\u505C\u7528" : isExpired ? lang === "en" ? "EXPIRED" : "\u5DF2\u8FC7\u671F" : showCode ? status.code : "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
1775
1965
|
}
|
|
1776
1966
|
),
|
|
1777
1967
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1778
1968
|
"button",
|
|
1779
1969
|
{
|
|
1780
1970
|
type: "button",
|
|
1971
|
+
disabled: status?.proxy?.mode === "proxy" && status.proxy.running === false,
|
|
1781
1972
|
onClick: () => setShowCode(!showCode),
|
|
1782
1973
|
title: showCode ? t("clickToHide", lang) : t("clickToReveal", lang),
|
|
1783
1974
|
style: {
|
|
1784
1975
|
background: "transparent",
|
|
1785
1976
|
border: "none",
|
|
1786
1977
|
color: "var(--dsw-alias-label-secondary, #888)",
|
|
1787
|
-
cursor: "pointer",
|
|
1978
|
+
cursor: status?.proxy?.mode === "proxy" && status.proxy.running === false ? "not-allowed" : "pointer",
|
|
1788
1979
|
display: "flex",
|
|
1789
1980
|
alignItems: "center",
|
|
1790
1981
|
justifyContent: "center",
|
|
1791
|
-
padding: "4px"
|
|
1982
|
+
padding: "4px",
|
|
1983
|
+
opacity: status?.proxy?.mode === "proxy" && status.proxy.running === false ? 0.4 : 1
|
|
1792
1984
|
},
|
|
1793
1985
|
children: showCode ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { style: { width: "20px", height: "20px", fill: "currentColor" }, viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" }) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { style: { width: "20px", height: "20px", fill: "currentColor" }, viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z" }) })
|
|
1794
1986
|
}
|
|
@@ -1801,7 +1993,7 @@ function QrPairingCard({
|
|
|
1801
1993
|
{
|
|
1802
1994
|
style: {
|
|
1803
1995
|
fontSize: "12px",
|
|
1804
|
-
color: isExpired ? "var(--dsw-alias-label-error, #ef4444)" : "var(--dsw-alias-label-secondary, #888)",
|
|
1996
|
+
color: status?.proxy?.mode === "proxy" && status.proxy.running === false || isExpired ? "var(--dsw-alias-label-error, #ef4444)" : "var(--dsw-alias-label-secondary, #888)",
|
|
1805
1997
|
margin: "4px 0 16px 0",
|
|
1806
1998
|
display: "flex",
|
|
1807
1999
|
alignItems: "center",
|
|
@@ -1817,11 +2009,11 @@ function QrPairingCard({
|
|
|
1817
2009
|
width: "8px",
|
|
1818
2010
|
height: "8px",
|
|
1819
2011
|
borderRadius: "50%",
|
|
1820
|
-
background: isExpired ? "#ef4444" : "#10b981"
|
|
2012
|
+
background: status?.proxy?.mode === "proxy" && status.proxy.running === false || isExpired ? "#ef4444" : "#10b981"
|
|
1821
2013
|
}
|
|
1822
2014
|
}
|
|
1823
2015
|
),
|
|
1824
|
-
isExpired ? `\u26A0\uFE0F ${t("codeExpired", lang)}` : `${t("codeValidUntil", lang)}${formatCountdown(timeLeft, lang)}`
|
|
2016
|
+
status?.proxy?.mode === "proxy" && status.proxy.running === false ? `\u26A0\uFE0F ${lang === "en" ? "Proxy Service Error" : "\u5B89\u5168\u63A5\u5165\u4EE3\u7406\u670D\u52A1\u5F02\u5E38"}` : isExpired ? `\u26A0\uFE0F ${t("codeExpired", lang)}` : `${t("codeValidUntil", lang)}${formatCountdown(timeLeft, lang)}`
|
|
1825
2017
|
]
|
|
1826
2018
|
}
|
|
1827
2019
|
),
|
|
@@ -1839,6 +2031,7 @@ function QrPairingCard({
|
|
|
1839
2031
|
"button",
|
|
1840
2032
|
{
|
|
1841
2033
|
type: "button",
|
|
2034
|
+
disabled: proxyUnavailable || !portReady,
|
|
1842
2035
|
onClick: () => setShowQr(!showQr),
|
|
1843
2036
|
style: {
|
|
1844
2037
|
padding: "7px 16px",
|
|
@@ -1848,7 +2041,8 @@ function QrPairingCard({
|
|
|
1848
2041
|
borderRadius: "8px",
|
|
1849
2042
|
fontSize: "13px",
|
|
1850
2043
|
fontWeight: "600",
|
|
1851
|
-
cursor: "pointer",
|
|
2044
|
+
cursor: proxyUnavailable || !portReady ? "not-allowed" : "pointer",
|
|
2045
|
+
opacity: proxyUnavailable || !portReady ? 0.4 : 1,
|
|
1852
2046
|
whiteSpace: "nowrap",
|
|
1853
2047
|
flexShrink: 0
|
|
1854
2048
|
},
|
|
@@ -1859,6 +2053,7 @@ function QrPairingCard({
|
|
|
1859
2053
|
"button",
|
|
1860
2054
|
{
|
|
1861
2055
|
type: "button",
|
|
2056
|
+
disabled: status?.proxy?.mode === "proxy" && status.proxy.running === false,
|
|
1862
2057
|
onClick: refreshStatusAndCode,
|
|
1863
2058
|
style: {
|
|
1864
2059
|
padding: "7px 16px",
|
|
@@ -1868,7 +2063,8 @@ function QrPairingCard({
|
|
|
1868
2063
|
borderRadius: "8px",
|
|
1869
2064
|
fontSize: "13px",
|
|
1870
2065
|
fontWeight: "600",
|
|
1871
|
-
cursor: "pointer",
|
|
2066
|
+
cursor: status?.proxy?.mode === "proxy" && status.proxy.running === false ? "not-allowed" : "pointer",
|
|
2067
|
+
opacity: status?.proxy?.mode === "proxy" && status.proxy.running === false ? 0.4 : 1,
|
|
1872
2068
|
whiteSpace: "nowrap",
|
|
1873
2069
|
flexShrink: 0
|
|
1874
2070
|
},
|
|
@@ -3037,21 +3233,365 @@ function ConfigCard({
|
|
|
3037
3233
|
);
|
|
3038
3234
|
}
|
|
3039
3235
|
|
|
3040
|
-
// src/client/components/
|
|
3236
|
+
// src/client/components/ProxyConfigCard.jsx
|
|
3041
3237
|
var import_react8 = __toESM(require("react"), 1);
|
|
3042
3238
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3239
|
+
function ProxyConfigCard({
|
|
3240
|
+
status,
|
|
3241
|
+
modeInput,
|
|
3242
|
+
setModeInput,
|
|
3243
|
+
proxyPortInput,
|
|
3244
|
+
setProxyPortInput,
|
|
3245
|
+
proxyHostInput,
|
|
3246
|
+
setProxyHostInput,
|
|
3247
|
+
trustedHostsInput,
|
|
3248
|
+
setTrustedHostsInput,
|
|
3249
|
+
saveProxyConfig,
|
|
3250
|
+
resetProxyConfigDefaults,
|
|
3251
|
+
toggleDirectoryPicker,
|
|
3252
|
+
isPatchingDirPicker,
|
|
3253
|
+
copyText,
|
|
3254
|
+
isSaving,
|
|
3255
|
+
lang
|
|
3256
|
+
}) {
|
|
3257
|
+
const isDirect = modeInput === "direct";
|
|
3258
|
+
const dirPicker = status && status.directoryPicker || {};
|
|
3259
|
+
const isBrowseEnabled = Boolean(dirPicker.patchEnabled || dirPicker.runtimeActive);
|
|
3260
|
+
const fieldLabelStyle = {
|
|
3261
|
+
fontSize: "12px",
|
|
3262
|
+
fontWeight: "600",
|
|
3263
|
+
color: "var(--dsw-alias-label-primary, inherit)"
|
|
3264
|
+
};
|
|
3265
|
+
const fieldHintStyle = {
|
|
3266
|
+
fontSize: "11px",
|
|
3267
|
+
color: "var(--dsw-alias-label-tertiary, #888)",
|
|
3268
|
+
lineHeight: 1.5
|
|
3269
|
+
};
|
|
3270
|
+
const inputStyle = {
|
|
3271
|
+
height: "34px",
|
|
3272
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.15))",
|
|
3273
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
3274
|
+
borderRadius: "6px",
|
|
3275
|
+
padding: "0 10px",
|
|
3276
|
+
color: "inherit",
|
|
3277
|
+
fontSize: "13px",
|
|
3278
|
+
outline: "none",
|
|
3279
|
+
boxSizing: "border-box",
|
|
3280
|
+
width: "100%"
|
|
3281
|
+
};
|
|
3282
|
+
const fieldBoxStyle = {
|
|
3283
|
+
display: "flex",
|
|
3284
|
+
flexDirection: "column",
|
|
3285
|
+
gap: "6px",
|
|
3286
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(128,128,128,0.06))",
|
|
3287
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.12))",
|
|
3288
|
+
borderRadius: "8px",
|
|
3289
|
+
padding: "10px 12px"
|
|
3290
|
+
};
|
|
3291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3292
|
+
"div",
|
|
3293
|
+
{
|
|
3294
|
+
style: {
|
|
3295
|
+
background: "var(--dsw-alias-bg-layer-3, rgba(128,128,128,0.06))",
|
|
3296
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.15))",
|
|
3297
|
+
borderRadius: "12px",
|
|
3298
|
+
padding: "14px",
|
|
3299
|
+
display: "flex",
|
|
3300
|
+
flexDirection: "column",
|
|
3301
|
+
gap: "12px"
|
|
3302
|
+
},
|
|
3303
|
+
children: [
|
|
3304
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "8px 12px", flexWrap: "wrap" }, children: [
|
|
3305
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3306
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "16px" }, children: "\u{1F50C}" }),
|
|
3307
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "15px", fontWeight: "600", color: "var(--dsw-alias-label-primary, inherit)" }, children: t("proxyConfigCardTitle", lang) })
|
|
3308
|
+
] }),
|
|
3309
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3310
|
+
"span",
|
|
3311
|
+
{
|
|
3312
|
+
style: {
|
|
3313
|
+
fontSize: "11px",
|
|
3314
|
+
color: "var(--dsw-alias-label-tertiary, #888)",
|
|
3315
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(128,128,128,0.08))",
|
|
3316
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.15))",
|
|
3317
|
+
borderRadius: "999px",
|
|
3318
|
+
padding: "3px 8px",
|
|
3319
|
+
whiteSpace: "nowrap"
|
|
3320
|
+
},
|
|
3321
|
+
children: [
|
|
3322
|
+
t("proxyCurrentRuntime", lang),
|
|
3323
|
+
": ",
|
|
3324
|
+
status?.proxy?.mode || "-",
|
|
3325
|
+
" / ",
|
|
3326
|
+
status?.proxy?.activePort || "-"
|
|
3327
|
+
]
|
|
3328
|
+
}
|
|
3329
|
+
)
|
|
3330
|
+
] }),
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "12px", color: "var(--dsw-alias-label-tertiary, #888)", lineHeight: 1.5 }, children: t("proxyConfigCardDesc", lang) }),
|
|
3332
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))", gap: "12px" }, children: [
|
|
3333
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: fieldBoxStyle, children: [
|
|
3334
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { style: fieldLabelStyle, children: t("proxyModeLabel", lang) }),
|
|
3335
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3336
|
+
"select",
|
|
3337
|
+
{
|
|
3338
|
+
value: modeInput,
|
|
3339
|
+
onChange: (e) => setModeInput(e.target.value),
|
|
3340
|
+
style: { ...inputStyle, cursor: "pointer" },
|
|
3341
|
+
children: [
|
|
3342
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "proxy", children: t("proxyModeProxy", lang) }),
|
|
3343
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "direct", children: t("proxyModeDirect", lang) })
|
|
3344
|
+
]
|
|
3345
|
+
}
|
|
3346
|
+
),
|
|
3347
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: fieldHintStyle, children: t("proxyModeHint", lang) })
|
|
3348
|
+
] }),
|
|
3349
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: fieldBoxStyle, children: [
|
|
3350
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { style: fieldLabelStyle, children: t("proxyPortLabel", lang) }),
|
|
3351
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3352
|
+
"input",
|
|
3353
|
+
{
|
|
3354
|
+
type: "number",
|
|
3355
|
+
min: "1",
|
|
3356
|
+
max: "65535",
|
|
3357
|
+
value: proxyPortInput,
|
|
3358
|
+
onChange: (e) => setProxyPortInput(e.target.value),
|
|
3359
|
+
disabled: isDirect,
|
|
3360
|
+
style: { ...inputStyle, opacity: isDirect ? 0.55 : 1 }
|
|
3361
|
+
}
|
|
3362
|
+
),
|
|
3363
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: fieldHintStyle, children: t("proxyPortHint", lang) })
|
|
3364
|
+
] }),
|
|
3365
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: fieldBoxStyle, children: [
|
|
3366
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { style: fieldLabelStyle, children: t("proxyHostLabel", lang) }),
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3368
|
+
"input",
|
|
3369
|
+
{
|
|
3370
|
+
type: "text",
|
|
3371
|
+
value: proxyHostInput,
|
|
3372
|
+
onChange: (e) => setProxyHostInput(e.target.value),
|
|
3373
|
+
placeholder: "0.0.0.0",
|
|
3374
|
+
disabled: isDirect,
|
|
3375
|
+
style: { ...inputStyle, opacity: isDirect ? 0.55 : 1 }
|
|
3376
|
+
}
|
|
3377
|
+
),
|
|
3378
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: fieldHintStyle, children: t("proxyHostHint", lang) })
|
|
3379
|
+
] })
|
|
3380
|
+
] }),
|
|
3381
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: fieldBoxStyle, children: [
|
|
3382
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { style: fieldLabelStyle, children: t("proxyTrustedHostsLabel", lang) }),
|
|
3383
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3384
|
+
"textarea",
|
|
3385
|
+
{
|
|
3386
|
+
value: trustedHostsInput,
|
|
3387
|
+
onChange: (e) => setTrustedHostsInput(e.target.value),
|
|
3388
|
+
placeholder: "xxx.tailnet.ts.net\ndsh.example.com",
|
|
3389
|
+
rows: 3,
|
|
3390
|
+
spellCheck: false,
|
|
3391
|
+
style: {
|
|
3392
|
+
...inputStyle,
|
|
3393
|
+
height: "auto",
|
|
3394
|
+
minHeight: "70px",
|
|
3395
|
+
padding: "8px 10px",
|
|
3396
|
+
resize: "vertical",
|
|
3397
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace"
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
),
|
|
3401
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: fieldHintStyle, children: t("proxyTrustedHostsHint", lang) })
|
|
3402
|
+
] }),
|
|
3403
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { fontSize: "11px", color: "#f59e0b", lineHeight: 1.5 }, children: [
|
|
3404
|
+
"\u26A0\uFE0F ",
|
|
3405
|
+
t("proxyRestartNote", lang)
|
|
3406
|
+
] }),
|
|
3407
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "flex-end", gap: "10px", flexWrap: "wrap" }, children: [
|
|
3408
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3409
|
+
"button",
|
|
3410
|
+
{
|
|
3411
|
+
type: "button",
|
|
3412
|
+
onClick: resetProxyConfigDefaults,
|
|
3413
|
+
disabled: isSaving,
|
|
3414
|
+
style: {
|
|
3415
|
+
padding: "6px 14px",
|
|
3416
|
+
background: "transparent",
|
|
3417
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
3418
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
3419
|
+
borderRadius: "6px",
|
|
3420
|
+
fontSize: "12px",
|
|
3421
|
+
cursor: isSaving ? "not-allowed" : "pointer",
|
|
3422
|
+
opacity: isSaving ? 0.6 : 1,
|
|
3423
|
+
whiteSpace: "nowrap"
|
|
3424
|
+
},
|
|
3425
|
+
children: t("proxyResetBtn", lang)
|
|
3426
|
+
}
|
|
3427
|
+
),
|
|
3428
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3429
|
+
"button",
|
|
3430
|
+
{
|
|
3431
|
+
type: "button",
|
|
3432
|
+
onClick: saveProxyConfig,
|
|
3433
|
+
disabled: isSaving,
|
|
3434
|
+
style: {
|
|
3435
|
+
padding: "6px 18px",
|
|
3436
|
+
background: "#2563eb",
|
|
3437
|
+
border: "none",
|
|
3438
|
+
color: "#ffffff",
|
|
3439
|
+
borderRadius: "6px",
|
|
3440
|
+
fontSize: "12px",
|
|
3441
|
+
fontWeight: "600",
|
|
3442
|
+
cursor: isSaving ? "not-allowed" : "pointer",
|
|
3443
|
+
opacity: isSaving ? 0.7 : 1,
|
|
3444
|
+
whiteSpace: "nowrap",
|
|
3445
|
+
boxShadow: "0 2px 6px rgba(37, 99, 235, 0.3)"
|
|
3446
|
+
},
|
|
3447
|
+
children: isSaving ? t("proxySavingBtn", lang) : t("proxySaveBtn", lang)
|
|
3448
|
+
}
|
|
3449
|
+
)
|
|
3450
|
+
] }),
|
|
3451
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3452
|
+
"div",
|
|
3453
|
+
{
|
|
3454
|
+
style: {
|
|
3455
|
+
...fieldBoxStyle,
|
|
3456
|
+
marginTop: "4px",
|
|
3457
|
+
border: isBrowseEnabled ? "1px solid rgba(16, 185, 129, 0.3)" : "1px solid rgba(245, 158, 11, 0.35)",
|
|
3458
|
+
background: isBrowseEnabled ? "rgba(16, 185, 129, 0.06)" : "rgba(245, 158, 11, 0.08)"
|
|
3459
|
+
},
|
|
3460
|
+
children: [
|
|
3461
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3462
|
+
"div",
|
|
3463
|
+
{
|
|
3464
|
+
style: {
|
|
3465
|
+
display: "flex",
|
|
3466
|
+
alignItems: "center",
|
|
3467
|
+
justifyContent: "space-between",
|
|
3468
|
+
gap: "8px",
|
|
3469
|
+
flexWrap: "wrap"
|
|
3470
|
+
},
|
|
3471
|
+
children: [
|
|
3472
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: fieldLabelStyle, children: t("dirPickerSectionTitle", lang) }),
|
|
3473
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3474
|
+
"span",
|
|
3475
|
+
{
|
|
3476
|
+
style: {
|
|
3477
|
+
fontSize: "11px",
|
|
3478
|
+
fontWeight: "600",
|
|
3479
|
+
color: isBrowseEnabled ? "#10b981" : "#f59e0b"
|
|
3480
|
+
},
|
|
3481
|
+
children: dirPicker.restartRequired ? t("dirPickerStatusPendingRestart", lang) : isBrowseEnabled ? t("dirPickerStatusActive", lang) : t("dirPickerStatusNativeWarn", lang)
|
|
3482
|
+
}
|
|
3483
|
+
)
|
|
3484
|
+
]
|
|
3485
|
+
}
|
|
3486
|
+
),
|
|
3487
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: fieldHintStyle, children: t("dirPickerSectionDesc", lang) }),
|
|
3488
|
+
dirPicker.patchFilePath ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3489
|
+
"div",
|
|
3490
|
+
{
|
|
3491
|
+
style: {
|
|
3492
|
+
fontSize: "11px",
|
|
3493
|
+
color: "var(--dsw-alias-label-tertiary, #888)",
|
|
3494
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
3495
|
+
wordBreak: "break-all"
|
|
3496
|
+
},
|
|
3497
|
+
children: [
|
|
3498
|
+
t("dirPickerPatchFileLabel", lang),
|
|
3499
|
+
dirPicker.patchFilePath
|
|
3500
|
+
]
|
|
3501
|
+
}
|
|
3502
|
+
) : null,
|
|
3503
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3504
|
+
"div",
|
|
3505
|
+
{
|
|
3506
|
+
style: {
|
|
3507
|
+
display: "flex",
|
|
3508
|
+
alignItems: "center",
|
|
3509
|
+
gap: "8px",
|
|
3510
|
+
flexWrap: "wrap",
|
|
3511
|
+
marginTop: "4px"
|
|
3512
|
+
},
|
|
3513
|
+
children: [
|
|
3514
|
+
typeof toggleDirectoryPicker === "function" ? isBrowseEnabled ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3515
|
+
"button",
|
|
3516
|
+
{
|
|
3517
|
+
type: "button",
|
|
3518
|
+
disabled: isPatchingDirPicker,
|
|
3519
|
+
onClick: () => toggleDirectoryPicker(false),
|
|
3520
|
+
style: {
|
|
3521
|
+
padding: "5px 12px",
|
|
3522
|
+
background: "transparent",
|
|
3523
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.3))",
|
|
3524
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
3525
|
+
borderRadius: "6px",
|
|
3526
|
+
fontSize: "12px",
|
|
3527
|
+
cursor: isPatchingDirPicker ? "not-allowed" : "pointer",
|
|
3528
|
+
opacity: isPatchingDirPicker ? 0.6 : 1
|
|
3529
|
+
},
|
|
3530
|
+
children: t("dirPickerRestoreNativeBtn", lang)
|
|
3531
|
+
}
|
|
3532
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3533
|
+
"button",
|
|
3534
|
+
{
|
|
3535
|
+
type: "button",
|
|
3536
|
+
disabled: isPatchingDirPicker,
|
|
3537
|
+
onClick: () => toggleDirectoryPicker(true),
|
|
3538
|
+
style: {
|
|
3539
|
+
padding: "5px 12px",
|
|
3540
|
+
background: "#2563eb",
|
|
3541
|
+
border: "none",
|
|
3542
|
+
color: "#ffffff",
|
|
3543
|
+
borderRadius: "6px",
|
|
3544
|
+
fontSize: "12px",
|
|
3545
|
+
fontWeight: "600",
|
|
3546
|
+
cursor: isPatchingDirPicker ? "not-allowed" : "pointer",
|
|
3547
|
+
opacity: isPatchingDirPicker ? 0.7 : 1
|
|
3548
|
+
},
|
|
3549
|
+
children: isPatchingDirPicker ? t("dirPickerEnablingBtn", lang) : t("dirPickerEnableBtn", lang)
|
|
3550
|
+
}
|
|
3551
|
+
) : null,
|
|
3552
|
+
typeof copyText === "function" && dirPicker.yamlSnippet ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3553
|
+
"button",
|
|
3554
|
+
{
|
|
3555
|
+
type: "button",
|
|
3556
|
+
onClick: () => copyText(dirPicker.yamlSnippet, t("dirPickerCopiedYamlTip", lang)),
|
|
3557
|
+
style: {
|
|
3558
|
+
padding: "5px 10px",
|
|
3559
|
+
background: "transparent",
|
|
3560
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
3561
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
3562
|
+
borderRadius: "6px",
|
|
3563
|
+
fontSize: "12px",
|
|
3564
|
+
cursor: "pointer"
|
|
3565
|
+
},
|
|
3566
|
+
children: t("dirPickerCopyYamlBtn", lang)
|
|
3567
|
+
}
|
|
3568
|
+
) : null
|
|
3569
|
+
]
|
|
3570
|
+
}
|
|
3571
|
+
)
|
|
3572
|
+
]
|
|
3573
|
+
}
|
|
3574
|
+
)
|
|
3575
|
+
]
|
|
3576
|
+
}
|
|
3577
|
+
);
|
|
3578
|
+
}
|
|
3579
|
+
|
|
3580
|
+
// src/client/components/StylesCard.jsx
|
|
3581
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
3582
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
3043
3583
|
function StylesCard({ lang, showToast }) {
|
|
3044
|
-
const [snippets, setSnippets] = (0,
|
|
3045
|
-
const [loading, setLoading] = (0,
|
|
3046
|
-
const [editingId, setEditingId] = (0,
|
|
3047
|
-
const [showForm, setShowForm] = (0,
|
|
3048
|
-
const [name, setName] = (0,
|
|
3049
|
-
const [css, setCss] = (0,
|
|
3050
|
-
const [pcEnabled, setPcEnabled] = (0,
|
|
3051
|
-
const [mobileEnabled, setMobileEnabled] = (0,
|
|
3052
|
-
const [expanded, setExpanded] = (0,
|
|
3053
|
-
const [feedback, setFeedback] = (0,
|
|
3054
|
-
const showFeedback = (0,
|
|
3584
|
+
const [snippets, setSnippets] = (0, import_react9.useState)([]);
|
|
3585
|
+
const [loading, setLoading] = (0, import_react9.useState)(true);
|
|
3586
|
+
const [editingId, setEditingId] = (0, import_react9.useState)(null);
|
|
3587
|
+
const [showForm, setShowForm] = (0, import_react9.useState)(false);
|
|
3588
|
+
const [name, setName] = (0, import_react9.useState)("");
|
|
3589
|
+
const [css, setCss] = (0, import_react9.useState)("");
|
|
3590
|
+
const [pcEnabled, setPcEnabled] = (0, import_react9.useState)(false);
|
|
3591
|
+
const [mobileEnabled, setMobileEnabled] = (0, import_react9.useState)(true);
|
|
3592
|
+
const [expanded, setExpanded] = (0, import_react9.useState)({});
|
|
3593
|
+
const [feedback, setFeedback] = (0, import_react9.useState)("");
|
|
3594
|
+
const showFeedback = (0, import_react9.useCallback)((msg, type = "success") => {
|
|
3055
3595
|
if (typeof showToast === "function") {
|
|
3056
3596
|
showToast(msg, type);
|
|
3057
3597
|
} else {
|
|
@@ -3059,7 +3599,7 @@ function StylesCard({ lang, showToast }) {
|
|
|
3059
3599
|
setTimeout(() => setFeedback(""), 3500);
|
|
3060
3600
|
}
|
|
3061
3601
|
}, [showToast]);
|
|
3062
|
-
const load = (0,
|
|
3602
|
+
const load = (0, import_react9.useCallback)(() => {
|
|
3063
3603
|
fetchStyles().then((data) => {
|
|
3064
3604
|
setSnippets(data.snippets || []);
|
|
3065
3605
|
setLoading(false);
|
|
@@ -3068,7 +3608,7 @@ function StylesCard({ lang, showToast }) {
|
|
|
3068
3608
|
showFeedback(t("stylesLoadFail", lang), "danger");
|
|
3069
3609
|
});
|
|
3070
3610
|
}, [lang, showFeedback]);
|
|
3071
|
-
(0,
|
|
3611
|
+
(0, import_react9.useEffect)(() => {
|
|
3072
3612
|
load();
|
|
3073
3613
|
}, [load]);
|
|
3074
3614
|
const toggle = (id, scope, enabled) => {
|
|
@@ -3210,7 +3750,7 @@ function StylesCard({ lang, showToast }) {
|
|
|
3210
3750
|
color: "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
3211
3751
|
border: "1px solid rgba(59,130,246,0.3)"
|
|
3212
3752
|
};
|
|
3213
|
-
return /* @__PURE__ */ (0,
|
|
3753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3214
3754
|
"div",
|
|
3215
3755
|
{
|
|
3216
3756
|
style: {
|
|
@@ -3223,15 +3763,15 @@ function StylesCard({ lang, showToast }) {
|
|
|
3223
3763
|
gap: "14px"
|
|
3224
3764
|
},
|
|
3225
3765
|
children: [
|
|
3226
|
-
/* @__PURE__ */ (0,
|
|
3227
|
-
/* @__PURE__ */ (0,
|
|
3228
|
-
/* @__PURE__ */ (0,
|
|
3229
|
-
/* @__PURE__ */ (0,
|
|
3766
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "10px", flexWrap: "wrap" }, children: [
|
|
3767
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3768
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "16px" }, children: "\u{1F3A8}" }),
|
|
3769
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "15px", fontWeight: "600", color: "var(--dsw-alias-label-primary, inherit)" }, children: t("stylesCardTitle", lang) })
|
|
3230
3770
|
] }),
|
|
3231
|
-
/* @__PURE__ */ (0,
|
|
3771
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: resetAll, style: miniBtnStyle, children: t("stylesResetAll", lang) })
|
|
3232
3772
|
] }),
|
|
3233
|
-
/* @__PURE__ */ (0,
|
|
3234
|
-
feedback && typeof showToast !== "function" ? /* @__PURE__ */ (0,
|
|
3773
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "12px", color: "var(--dsw-alias-label-tertiary, #888)", lineHeight: "1.5" }, children: t("stylesCardDesc", lang) }),
|
|
3774
|
+
feedback && typeof showToast !== "function" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3235
3775
|
"div",
|
|
3236
3776
|
{
|
|
3237
3777
|
style: {
|
|
@@ -3245,15 +3785,15 @@ function StylesCard({ lang, showToast }) {
|
|
|
3245
3785
|
children: feedback
|
|
3246
3786
|
}
|
|
3247
3787
|
) : null,
|
|
3248
|
-
loading ? /* @__PURE__ */ (0,
|
|
3249
|
-
snippets.some((s) => s.builtin) ? /* @__PURE__ */ (0,
|
|
3250
|
-
/* @__PURE__ */ (0,
|
|
3251
|
-
/* @__PURE__ */ (0,
|
|
3252
|
-
/* @__PURE__ */ (0,
|
|
3253
|
-
/* @__PURE__ */ (0,
|
|
3254
|
-
/* @__PURE__ */ (0,
|
|
3255
|
-
/* @__PURE__ */ (0,
|
|
3256
|
-
/* @__PURE__ */ (0,
|
|
3788
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "12px", color: "var(--dsw-alias-label-tertiary, #888)" }, children: lang === "en" ? "Loading style snippets..." : "\u6B63\u5728\u52A0\u8F7D\u6837\u5F0F\u7247\u6BB5..." }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3789
|
+
snippets.some((s) => s.builtin) ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3790
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "13px", fontWeight: "600", color: "var(--dsw-alias-label-secondary, inherit)" }, children: t("stylesPresetsTitle", lang) }),
|
|
3791
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: snippets.filter((s) => s.builtin).map((s) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: rowStyle, children: [
|
|
3792
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3793
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: "1 1 180px", minWidth: 0, maxWidth: "100%" }, children: [
|
|
3794
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
|
|
3795
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "12px", fontWeight: "600", color: "var(--dsw-alias-label-primary, inherit)" }, children: s.name }),
|
|
3796
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3257
3797
|
"span",
|
|
3258
3798
|
{
|
|
3259
3799
|
style: {
|
|
@@ -3267,7 +3807,7 @@ function StylesCard({ lang, showToast }) {
|
|
|
3267
3807
|
children: "Preset"
|
|
3268
3808
|
}
|
|
3269
3809
|
),
|
|
3270
|
-
/* @__PURE__ */ (0,
|
|
3810
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3271
3811
|
"span",
|
|
3272
3812
|
{
|
|
3273
3813
|
style: {
|
|
@@ -3282,11 +3822,11 @@ function StylesCard({ lang, showToast }) {
|
|
|
3282
3822
|
}
|
|
3283
3823
|
)
|
|
3284
3824
|
] }),
|
|
3285
|
-
s.description ? /* @__PURE__ */ (0,
|
|
3825
|
+
s.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #888)", marginTop: "3px" }, children: s.description }) : null
|
|
3286
3826
|
] }),
|
|
3287
|
-
/* @__PURE__ */ (0,
|
|
3288
|
-
/* @__PURE__ */ (0,
|
|
3289
|
-
/* @__PURE__ */ (0,
|
|
3827
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px 8px", flexWrap: "wrap", maxWidth: "100%" }, children: [
|
|
3828
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
3829
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3290
3830
|
"input",
|
|
3291
3831
|
{
|
|
3292
3832
|
type: "checkbox",
|
|
@@ -3298,8 +3838,8 @@ function StylesCard({ lang, showToast }) {
|
|
|
3298
3838
|
"\u{1F5A5}\uFE0F ",
|
|
3299
3839
|
t("stylesPcShort", lang)
|
|
3300
3840
|
] }),
|
|
3301
|
-
/* @__PURE__ */ (0,
|
|
3302
|
-
/* @__PURE__ */ (0,
|
|
3841
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
3842
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3303
3843
|
"input",
|
|
3304
3844
|
{
|
|
3305
3845
|
type: "checkbox",
|
|
@@ -3311,13 +3851,13 @@ function StylesCard({ lang, showToast }) {
|
|
|
3311
3851
|
"\u{1F4F1} ",
|
|
3312
3852
|
t("stylesMobileShort", lang)
|
|
3313
3853
|
] }),
|
|
3314
|
-
/* @__PURE__ */ (0,
|
|
3315
|
-
/* @__PURE__ */ (0,
|
|
3316
|
-
/* @__PURE__ */ (0,
|
|
3854
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "inline-flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
|
|
3855
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: () => toggleExpand(s.id), style: miniBtnStyle, children: expanded[s.id] ? t("stylesHideCss", lang) : t("stylesViewCss", lang) }),
|
|
3856
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: () => copyCss(s.css), style: miniBtnStyle, children: t("stylesCopyCss", lang) })
|
|
3317
3857
|
] })
|
|
3318
3858
|
] })
|
|
3319
3859
|
] }),
|
|
3320
|
-
expanded[s.id] ? /* @__PURE__ */ (0,
|
|
3860
|
+
expanded[s.id] ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3321
3861
|
"pre",
|
|
3322
3862
|
{
|
|
3323
3863
|
style: {
|
|
@@ -3340,8 +3880,8 @@ function StylesCard({ lang, showToast }) {
|
|
|
3340
3880
|
) : null
|
|
3341
3881
|
] }, s.id)) })
|
|
3342
3882
|
] }) : null,
|
|
3343
|
-
/* @__PURE__ */ (0,
|
|
3344
|
-
!showForm ? /* @__PURE__ */ (0,
|
|
3883
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "13px", fontWeight: "600", color: "var(--dsw-alias-label-secondary, inherit)", marginTop: "4px" }, children: t("stylesCustomTitle", lang) }),
|
|
3884
|
+
!showForm ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3345
3885
|
"button",
|
|
3346
3886
|
{
|
|
3347
3887
|
type: "button",
|
|
@@ -3359,7 +3899,7 @@ function StylesCard({ lang, showToast }) {
|
|
|
3359
3899
|
},
|
|
3360
3900
|
children: t("stylesAddNew", lang)
|
|
3361
3901
|
}
|
|
3362
|
-
) : /* @__PURE__ */ (0,
|
|
3902
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3363
3903
|
"div",
|
|
3364
3904
|
{
|
|
3365
3905
|
style: {
|
|
@@ -3372,8 +3912,8 @@ function StylesCard({ lang, showToast }) {
|
|
|
3372
3912
|
padding: "12px"
|
|
3373
3913
|
},
|
|
3374
3914
|
children: [
|
|
3375
|
-
/* @__PURE__ */ (0,
|
|
3376
|
-
/* @__PURE__ */ (0,
|
|
3915
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3916
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3377
3917
|
"input",
|
|
3378
3918
|
{
|
|
3379
3919
|
type: "text",
|
|
@@ -3393,8 +3933,8 @@ function StylesCard({ lang, showToast }) {
|
|
|
3393
3933
|
}
|
|
3394
3934
|
}
|
|
3395
3935
|
),
|
|
3396
|
-
/* @__PURE__ */ (0,
|
|
3397
|
-
/* @__PURE__ */ (0,
|
|
3936
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
3937
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3398
3938
|
"input",
|
|
3399
3939
|
{
|
|
3400
3940
|
type: "checkbox",
|
|
@@ -3406,8 +3946,8 @@ function StylesCard({ lang, showToast }) {
|
|
|
3406
3946
|
"\u{1F5A5}\uFE0F ",
|
|
3407
3947
|
t("stylesPcShort", lang)
|
|
3408
3948
|
] }),
|
|
3409
|
-
/* @__PURE__ */ (0,
|
|
3410
|
-
/* @__PURE__ */ (0,
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
3950
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3411
3951
|
"input",
|
|
3412
3952
|
{
|
|
3413
3953
|
type: "checkbox",
|
|
@@ -3420,7 +3960,7 @@ function StylesCard({ lang, showToast }) {
|
|
|
3420
3960
|
t("stylesMobileShort", lang)
|
|
3421
3961
|
] })
|
|
3422
3962
|
] }),
|
|
3423
|
-
/* @__PURE__ */ (0,
|
|
3963
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3424
3964
|
"textarea",
|
|
3425
3965
|
{
|
|
3426
3966
|
value: css,
|
|
@@ -3443,20 +3983,20 @@ function StylesCard({ lang, showToast }) {
|
|
|
3443
3983
|
}
|
|
3444
3984
|
}
|
|
3445
3985
|
),
|
|
3446
|
-
/* @__PURE__ */ (0,
|
|
3447
|
-
/* @__PURE__ */ (0,
|
|
3448
|
-
editingId !== null ? /* @__PURE__ */ (0,
|
|
3449
|
-
showForm && !editingId ? /* @__PURE__ */ (0,
|
|
3986
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3987
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: save, style: primaryBtnStyle, children: t("stylesSave", lang) }),
|
|
3988
|
+
editingId !== null ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: cancelEdit, style: miniBtnStyle, children: t("stylesCancelEdit", lang) }) : null,
|
|
3989
|
+
showForm && !editingId ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: cancelEdit, style: miniBtnStyle, children: t("stylesCancelEdit", lang) }) : null
|
|
3450
3990
|
] })
|
|
3451
3991
|
]
|
|
3452
3992
|
}
|
|
3453
3993
|
),
|
|
3454
|
-
snippets.filter((s) => !s.builtin).length === 0 ? /* @__PURE__ */ (0,
|
|
3455
|
-
/* @__PURE__ */ (0,
|
|
3456
|
-
/* @__PURE__ */ (0,
|
|
3457
|
-
/* @__PURE__ */ (0,
|
|
3458
|
-
/* @__PURE__ */ (0,
|
|
3459
|
-
/* @__PURE__ */ (0,
|
|
3994
|
+
snippets.filter((s) => !s.builtin).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "12px", color: "var(--dsw-alias-label-tertiary, #888)" }, children: t("stylesEmptyCustom", lang) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: snippets.filter((s) => !s.builtin).map((s) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: rowStyle, children: [
|
|
3995
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3996
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: "1 1 180px", minWidth: 0, maxWidth: "100%" }, children: [
|
|
3997
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
|
|
3998
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "12px", fontWeight: "600", color: "var(--dsw-alias-label-primary, inherit)" }, children: s.name }),
|
|
3999
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3460
4000
|
"span",
|
|
3461
4001
|
{
|
|
3462
4002
|
style: {
|
|
@@ -3471,11 +4011,11 @@ function StylesCard({ lang, showToast }) {
|
|
|
3471
4011
|
}
|
|
3472
4012
|
)
|
|
3473
4013
|
] }),
|
|
3474
|
-
s.description ? /* @__PURE__ */ (0,
|
|
4014
|
+
s.description ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #888)", marginTop: "3px" }, children: s.description }) : null
|
|
3475
4015
|
] }),
|
|
3476
|
-
/* @__PURE__ */ (0,
|
|
3477
|
-
/* @__PURE__ */ (0,
|
|
3478
|
-
/* @__PURE__ */ (0,
|
|
4016
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px 8px", flexWrap: "wrap", maxWidth: "100%" }, children: [
|
|
4017
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
4018
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3479
4019
|
"input",
|
|
3480
4020
|
{
|
|
3481
4021
|
type: "checkbox",
|
|
@@ -3487,8 +4027,8 @@ function StylesCard({ lang, showToast }) {
|
|
|
3487
4027
|
"\u{1F5A5}\uFE0F ",
|
|
3488
4028
|
t("stylesPcShort", lang)
|
|
3489
4029
|
] }),
|
|
3490
|
-
/* @__PURE__ */ (0,
|
|
3491
|
-
/* @__PURE__ */ (0,
|
|
4030
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
4031
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3492
4032
|
"input",
|
|
3493
4033
|
{
|
|
3494
4034
|
type: "checkbox",
|
|
@@ -3500,15 +4040,15 @@ function StylesCard({ lang, showToast }) {
|
|
|
3500
4040
|
"\u{1F4F1} ",
|
|
3501
4041
|
t("stylesMobileShort", lang)
|
|
3502
4042
|
] }),
|
|
3503
|
-
/* @__PURE__ */ (0,
|
|
3504
|
-
/* @__PURE__ */ (0,
|
|
3505
|
-
/* @__PURE__ */ (0,
|
|
3506
|
-
/* @__PURE__ */ (0,
|
|
3507
|
-
/* @__PURE__ */ (0,
|
|
4043
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "inline-flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
|
|
4044
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: () => startEdit(s), style: miniBtnStyle, children: t("stylesEditBtn", lang) }),
|
|
4045
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: () => remove(s), style: { ...miniBtnStyle, color: "#ef4444" }, children: t("stylesDeleteBtn", lang) }),
|
|
4046
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: () => toggleExpand(s.id), style: miniBtnStyle, children: expanded[s.id] ? t("stylesHideCss", lang) : t("stylesViewCss", lang) }),
|
|
4047
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: () => copyCss(s.css), style: miniBtnStyle, children: t("stylesCopyCss", lang) })
|
|
3508
4048
|
] })
|
|
3509
4049
|
] })
|
|
3510
4050
|
] }),
|
|
3511
|
-
expanded[s.id] ? /* @__PURE__ */ (0,
|
|
4051
|
+
expanded[s.id] ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3512
4052
|
"pre",
|
|
3513
4053
|
{
|
|
3514
4054
|
style: {
|
|
@@ -3530,7 +4070,7 @@ function StylesCard({ lang, showToast }) {
|
|
|
3530
4070
|
}
|
|
3531
4071
|
) : null
|
|
3532
4072
|
] }, s.id)) }),
|
|
3533
|
-
/* @__PURE__ */ (0,
|
|
4073
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #888)", lineHeight: "1.6" }, children: t("stylesHint", lang) })
|
|
3534
4074
|
] })
|
|
3535
4075
|
]
|
|
3536
4076
|
}
|
|
@@ -3538,14 +4078,14 @@ function StylesCard({ lang, showToast }) {
|
|
|
3538
4078
|
}
|
|
3539
4079
|
|
|
3540
4080
|
// src/client/version.js
|
|
3541
|
-
var PLUGIN_VERSION = "v1.
|
|
3542
|
-
var BUILD_TIME = "2026-
|
|
4081
|
+
var PLUGIN_VERSION = "v1.10.2";
|
|
4082
|
+
var BUILD_TIME = "2026-11-02 23:13:58";
|
|
3543
4083
|
|
|
3544
4084
|
// src/client/components/MainSection.jsx
|
|
3545
|
-
var
|
|
4085
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
3546
4086
|
function TailscaleMobileSection(props) {
|
|
3547
4087
|
const ctx = props && props.ctx || typeof window !== "undefined" && window.__DSH_CLIENT_CTX__ || null;
|
|
3548
|
-
const [status, setStatus] = (0,
|
|
4088
|
+
const [status, setStatus] = (0, import_react10.useState)({
|
|
3549
4089
|
tailscaleIp: "",
|
|
3550
4090
|
lanIp: "",
|
|
3551
4091
|
code: "",
|
|
@@ -3567,36 +4107,53 @@ function TailscaleMobileSection(props) {
|
|
|
3567
4107
|
locale: "zh",
|
|
3568
4108
|
pairingBridgeMode: "pending",
|
|
3569
4109
|
pairingBridgeConflict: "",
|
|
3570
|
-
pairingBridgeConflictId: ""
|
|
4110
|
+
pairingBridgeConflictId: "",
|
|
4111
|
+
directoryPicker: {
|
|
4112
|
+
patchEnabled: false,
|
|
4113
|
+
patchPartial: false,
|
|
4114
|
+
runtimeActive: false,
|
|
4115
|
+
restartRequired: false,
|
|
4116
|
+
needsWarning: false,
|
|
4117
|
+
patchFilePath: "",
|
|
4118
|
+
yamlSnippet: ""
|
|
4119
|
+
},
|
|
4120
|
+
proxy: null
|
|
3571
4121
|
});
|
|
3572
|
-
const [secretInput, setSecretInput] = (0,
|
|
3573
|
-
const [showSecret, setShowSecret] = (0,
|
|
3574
|
-
const [showCode, setShowCode] = (0,
|
|
3575
|
-
const [showQr, setShowQr] = (0,
|
|
3576
|
-
const [selectedTab, setSelectedTab] = (0,
|
|
3577
|
-
const [timeLeft, setTimeLeft] = (0,
|
|
3578
|
-
const [toast, setToast] = (0,
|
|
3579
|
-
const [maxVisitsInput, setMaxVisitsInput] = (0,
|
|
3580
|
-
const [maxFailedInput, setMaxFailedInput] = (0,
|
|
3581
|
-
const [lockDurationMinsInput, setLockDurationMinsInput] = (0,
|
|
3582
|
-
const [
|
|
3583
|
-
const [
|
|
3584
|
-
const [
|
|
3585
|
-
const [
|
|
3586
|
-
const
|
|
3587
|
-
const [
|
|
3588
|
-
const
|
|
3589
|
-
const
|
|
3590
|
-
const
|
|
4122
|
+
const [secretInput, setSecretInput] = (0, import_react10.useState)("");
|
|
4123
|
+
const [showSecret, setShowSecret] = (0, import_react10.useState)(false);
|
|
4124
|
+
const [showCode, setShowCode] = (0, import_react10.useState)(false);
|
|
4125
|
+
const [showQr, setShowQr] = (0, import_react10.useState)(false);
|
|
4126
|
+
const [selectedTab, setSelectedTab] = (0, import_react10.useState)("lan");
|
|
4127
|
+
const [timeLeft, setTimeLeft] = (0, import_react10.useState)(300);
|
|
4128
|
+
const [toast, setToast] = (0, import_react10.useState)(null);
|
|
4129
|
+
const [maxVisitsInput, setMaxVisitsInput] = (0, import_react10.useState)("60");
|
|
4130
|
+
const [maxFailedInput, setMaxFailedInput] = (0, import_react10.useState)("5");
|
|
4131
|
+
const [lockDurationMinsInput, setLockDurationMinsInput] = (0, import_react10.useState)("15");
|
|
4132
|
+
const [modeInput, setModeInput] = (0, import_react10.useState)("proxy");
|
|
4133
|
+
const [proxyPortInput, setProxyPortInput] = (0, import_react10.useState)("3081");
|
|
4134
|
+
const [proxyHostInput, setProxyHostInput] = (0, import_react10.useState)("0.0.0.0");
|
|
4135
|
+
const [trustedHostsInput, setTrustedHostsInput] = (0, import_react10.useState)("");
|
|
4136
|
+
const proxyConfigLoadedRef = (0, import_react10.useRef)(false);
|
|
4137
|
+
const [isSaving, setIsSaving] = (0, import_react10.useState)(false);
|
|
4138
|
+
const [showVersionTip, setShowVersionTip] = (0, import_react10.useState)(false);
|
|
4139
|
+
const [currentLang, setCurrentLang] = (0, import_react10.useState)(resolveLocale(ctx, status));
|
|
4140
|
+
const [npmLatestVersion, setNpmLatestVersion] = (0, import_react10.useState)("");
|
|
4141
|
+
const [hasUpdate, setHasUpdate] = (0, import_react10.useState)(false);
|
|
4142
|
+
const [conflictBannerDismissed, setConflictBannerDismissed] = (0, import_react10.useState)(false);
|
|
4143
|
+
const [dirPickerBannerDismissed, setDirPickerBannerDismissed] = (0, import_react10.useState)(false);
|
|
4144
|
+
const [isPatchingDirPicker, setIsPatchingDirPicker] = (0, import_react10.useState)(false);
|
|
4145
|
+
const qrTabTouchedRef = (0, import_react10.useRef)(false);
|
|
4146
|
+
const toastTimerRef = (0, import_react10.useRef)(null);
|
|
4147
|
+
const showToast = (0, import_react10.useCallback)((message, type = "success", duration = 2500) => {
|
|
3591
4148
|
if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
|
|
3592
4149
|
setToast({ message, type });
|
|
3593
4150
|
toastTimerRef.current = setTimeout(() => setToast(null), duration);
|
|
3594
4151
|
}, []);
|
|
3595
|
-
const updateQrTab = (0,
|
|
4152
|
+
const updateQrTab = (0, import_react10.useCallback)((tab) => {
|
|
3596
4153
|
qrTabTouchedRef.current = true;
|
|
3597
4154
|
setSelectedTab(tab);
|
|
3598
4155
|
}, []);
|
|
3599
|
-
const [activeTab, setActiveTab] = (0,
|
|
4156
|
+
const [activeTab, setActiveTab] = (0, import_react10.useState)(() => {
|
|
3600
4157
|
try {
|
|
3601
4158
|
const saved = localStorage.getItem("dsh-rm-settings-tab");
|
|
3602
4159
|
if (saved === "access" || saved === "devices" || saved === "style" || saved === "storage") return saved;
|
|
@@ -3611,7 +4168,7 @@ function TailscaleMobileSection(props) {
|
|
|
3611
4168
|
} catch (e) {
|
|
3612
4169
|
}
|
|
3613
4170
|
};
|
|
3614
|
-
const refreshStatusOnly = (0,
|
|
4171
|
+
const refreshStatusOnly = (0, import_react10.useCallback)(() => {
|
|
3615
4172
|
fetchStatus().then((data) => {
|
|
3616
4173
|
if (data.tailscaleIp && !qrTabTouchedRef.current) {
|
|
3617
4174
|
setSelectedTab("tailscale");
|
|
@@ -3623,6 +4180,14 @@ function TailscaleMobileSection(props) {
|
|
|
3623
4180
|
if (data.locale) {
|
|
3624
4181
|
setCurrentLang(resolveLocale(ctx, data));
|
|
3625
4182
|
}
|
|
4183
|
+
if (!proxyConfigLoadedRef.current && data.proxy) {
|
|
4184
|
+
setModeInput(data.proxy.configuredMode === "direct" ? "direct" : "proxy");
|
|
4185
|
+
setProxyPortInput(String(data.proxy.proxyPort || 3081));
|
|
4186
|
+
setProxyHostInput(data.proxy.proxyHost || "0.0.0.0");
|
|
4187
|
+
setTrustedHostsInput(Array.isArray(data.proxy.trustedHosts) ? data.proxy.trustedHosts.join("\n") : "");
|
|
4188
|
+
proxyConfigLoadedRef.current = true;
|
|
4189
|
+
}
|
|
4190
|
+
const dp = data.directoryPicker || {};
|
|
3626
4191
|
setStatus((prev) => ({
|
|
3627
4192
|
...prev,
|
|
3628
4193
|
tailscaleIp: data.tailscaleIp || "",
|
|
@@ -3643,12 +4208,22 @@ function TailscaleMobileSection(props) {
|
|
|
3643
4208
|
pairingBridgeMode: data.pairingBridgeMode || "pending",
|
|
3644
4209
|
pairingBridgeConflict: data.pairingBridgeConflict || "",
|
|
3645
4210
|
pairingBridgeConflictId: data.pairingBridgeConflictId || "",
|
|
4211
|
+
directoryPicker: {
|
|
4212
|
+
patchEnabled: Boolean(dp.patchEnabled),
|
|
4213
|
+
patchPartial: Boolean(dp.patchPartial),
|
|
4214
|
+
runtimeActive: Boolean(dp.runtimeActive),
|
|
4215
|
+
restartRequired: Boolean(dp.restartRequired),
|
|
4216
|
+
needsWarning: Boolean(dp.needsWarning),
|
|
4217
|
+
patchFilePath: dp.patchFilePath || "",
|
|
4218
|
+
yamlSnippet: dp.yamlSnippet || ""
|
|
4219
|
+
},
|
|
4220
|
+
proxy: data.proxy || null,
|
|
3646
4221
|
loading: false
|
|
3647
4222
|
}));
|
|
3648
4223
|
}).catch(() => {
|
|
3649
4224
|
});
|
|
3650
4225
|
}, [ctx]);
|
|
3651
|
-
const refreshStatusAndCode = (0,
|
|
4226
|
+
const refreshStatusAndCode = (0, import_react10.useCallback)(() => {
|
|
3652
4227
|
refreshStatusOnly();
|
|
3653
4228
|
generatePairCode().then((data) => {
|
|
3654
4229
|
if (data.success) {
|
|
@@ -3663,7 +4238,7 @@ function TailscaleMobileSection(props) {
|
|
|
3663
4238
|
}).catch(() => {
|
|
3664
4239
|
});
|
|
3665
4240
|
}, [refreshStatusOnly]);
|
|
3666
|
-
(0,
|
|
4241
|
+
(0, import_react10.useEffect)(() => {
|
|
3667
4242
|
let cancelled = false;
|
|
3668
4243
|
fetch("https://registry.npmjs.org/dsh-remote-mobile/latest", { cache: "no-store" }).then((res) => res.ok ? res.json() : Promise.reject(new Error("npm registry error"))).then((data) => {
|
|
3669
4244
|
if (cancelled) return;
|
|
@@ -3691,7 +4266,7 @@ function TailscaleMobileSection(props) {
|
|
|
3691
4266
|
}
|
|
3692
4267
|
return 0;
|
|
3693
4268
|
};
|
|
3694
|
-
(0,
|
|
4269
|
+
(0, import_react10.useEffect)(() => {
|
|
3695
4270
|
refreshStatusAndCode();
|
|
3696
4271
|
const localeUnsubs = [];
|
|
3697
4272
|
try {
|
|
@@ -3759,7 +4334,7 @@ function TailscaleMobileSection(props) {
|
|
|
3759
4334
|
}
|
|
3760
4335
|
};
|
|
3761
4336
|
}, [refreshStatusAndCode, refreshStatusOnly, currentLang, ctx]);
|
|
3762
|
-
(0,
|
|
4337
|
+
(0, import_react10.useEffect)(() => {
|
|
3763
4338
|
if (timeLeft <= 0) return;
|
|
3764
4339
|
const timer = setInterval(() => {
|
|
3765
4340
|
setTimeLeft((prev) => {
|
|
@@ -3945,14 +4520,118 @@ function TailscaleMobileSection(props) {
|
|
|
3945
4520
|
showToast((currentLang === "en" ? "Reset failed: " : "\u91CD\u7F6E\u5931\u8D25\uFF1A") + (err?.message || err), "danger", 3500);
|
|
3946
4521
|
});
|
|
3947
4522
|
};
|
|
4523
|
+
const persistProxyConfig = (mode, port, host, hosts) => {
|
|
4524
|
+
setIsSaving(true);
|
|
4525
|
+
updateProxyConfig({
|
|
4526
|
+
mode,
|
|
4527
|
+
proxyPort: port,
|
|
4528
|
+
proxyHost: host,
|
|
4529
|
+
trustedHosts: hosts
|
|
4530
|
+
}).then((data) => {
|
|
4531
|
+
setIsSaving(false);
|
|
4532
|
+
if (data.success) {
|
|
4533
|
+
setStatus((prev) => ({
|
|
4534
|
+
...prev,
|
|
4535
|
+
proxy: prev.proxy ? {
|
|
4536
|
+
...prev.proxy,
|
|
4537
|
+
configuredMode: data.mode,
|
|
4538
|
+
proxyPort: data.proxyPort,
|
|
4539
|
+
proxyHost: data.proxyHost,
|
|
4540
|
+
trustedHosts: data.trustedHosts || [],
|
|
4541
|
+
mode: data.activeMode || prev.proxy.mode,
|
|
4542
|
+
activePort: data.activePort || prev.proxy.activePort
|
|
4543
|
+
} : prev.proxy
|
|
4544
|
+
}));
|
|
4545
|
+
refreshStatusOnly();
|
|
4546
|
+
showToast(t("proxySavedToast", currentLang), "success", 5e3);
|
|
4547
|
+
} else {
|
|
4548
|
+
showToast((currentLang === "en" ? "Save failed: " : "\u4FDD\u5B58\u5931\u8D25\uFF1A") + (data.reason || ""), "danger", 3500);
|
|
4549
|
+
}
|
|
4550
|
+
}).catch((err) => {
|
|
4551
|
+
setIsSaving(false);
|
|
4552
|
+
showToast((currentLang === "en" ? "Save failed: " : "\u4FDD\u5B58\u5931\u8D25\uFF1A") + (err?.message || err), "danger", 3500);
|
|
4553
|
+
});
|
|
4554
|
+
};
|
|
4555
|
+
const saveProxyConfig = () => {
|
|
4556
|
+
const port = parseInt(proxyPortInput, 10);
|
|
4557
|
+
const host = proxyHostInput.trim();
|
|
4558
|
+
const hosts = trustedHostsInput.split(/\r?\n/).map((h) => h.trim()).filter(Boolean);
|
|
4559
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535 || !host) {
|
|
4560
|
+
alert(t("proxySaveFailTip", currentLang));
|
|
4561
|
+
return;
|
|
4562
|
+
}
|
|
4563
|
+
if (!confirm(t("proxySaveConfirm", currentLang))) {
|
|
4564
|
+
return;
|
|
4565
|
+
}
|
|
4566
|
+
persistProxyConfig(modeInput === "direct" ? "direct" : "proxy", port, host, hosts);
|
|
4567
|
+
};
|
|
4568
|
+
const resetProxyConfigDefaults = () => {
|
|
4569
|
+
if (!confirm(t("proxyResetConfirm", currentLang))) {
|
|
4570
|
+
return;
|
|
4571
|
+
}
|
|
4572
|
+
setModeInput("proxy");
|
|
4573
|
+
setProxyPortInput("3081");
|
|
4574
|
+
setProxyHostInput("0.0.0.0");
|
|
4575
|
+
setTrustedHostsInput("");
|
|
4576
|
+
persistProxyConfig("proxy", 3081, "0.0.0.0", []);
|
|
4577
|
+
};
|
|
4578
|
+
const toggleDirectoryPicker = (enable) => {
|
|
4579
|
+
if (!enable) {
|
|
4580
|
+
if (!confirm(t("dirPickerDisableConfirm", currentLang))) {
|
|
4581
|
+
return;
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
setIsPatchingDirPicker(true);
|
|
4585
|
+
toggleDirectoryPickerApi(enable).then((res) => {
|
|
4586
|
+
setIsPatchingDirPicker(false);
|
|
4587
|
+
if (res && res.success) {
|
|
4588
|
+
const dp = res.directoryPicker || {};
|
|
4589
|
+
setStatus((prev) => ({
|
|
4590
|
+
...prev,
|
|
4591
|
+
directoryPicker: {
|
|
4592
|
+
patchEnabled: Boolean(dp.patchEnabled),
|
|
4593
|
+
patchPartial: Boolean(dp.patchPartial),
|
|
4594
|
+
runtimeActive: Boolean(dp.runtimeActive),
|
|
4595
|
+
restartRequired: Boolean(dp.restartRequired),
|
|
4596
|
+
needsWarning: Boolean(dp.needsWarning),
|
|
4597
|
+
patchFilePath: dp.patchFilePath || "",
|
|
4598
|
+
yamlSnippet: dp.yamlSnippet || ""
|
|
4599
|
+
}
|
|
4600
|
+
}));
|
|
4601
|
+
refreshStatusOnly();
|
|
4602
|
+
showToast(
|
|
4603
|
+
t(enable ? "dirPickerEnabledToast" : "dirPickerDisabledToast", currentLang),
|
|
4604
|
+
"success",
|
|
4605
|
+
4500
|
|
4606
|
+
);
|
|
4607
|
+
} else {
|
|
4608
|
+
showToast(
|
|
4609
|
+
(currentLang === "en" ? "Operation failed: " : "\u64CD\u4F5C\u5931\u8D25\uFF1A") + (res && res.reason || ""),
|
|
4610
|
+
"danger",
|
|
4611
|
+
3500
|
|
4612
|
+
);
|
|
4613
|
+
}
|
|
4614
|
+
}).catch((err) => {
|
|
4615
|
+
setIsPatchingDirPicker(false);
|
|
4616
|
+
showToast(
|
|
4617
|
+
(currentLang === "en" ? "Operation failed: " : "\u64CD\u4F5C\u5931\u8D25\uFF1A") + (err?.message || err),
|
|
4618
|
+
"danger",
|
|
4619
|
+
3500
|
|
4620
|
+
);
|
|
4621
|
+
});
|
|
4622
|
+
};
|
|
3948
4623
|
const copyDirectLink = () => {
|
|
3949
4624
|
if (timeLeft <= 0) {
|
|
3950
4625
|
alert(t("codeExpired", currentLang));
|
|
3951
4626
|
return;
|
|
3952
4627
|
}
|
|
3953
4628
|
const effectiveQrIp = selectedTab === "tailscale" && status.tailscaleIp ? status.tailscaleIp : status.lanIp || "127.0.0.1";
|
|
3954
|
-
const port =
|
|
3955
|
-
|
|
4629
|
+
const port = resolveAccessPort(status);
|
|
4630
|
+
if (port === null) {
|
|
4631
|
+
showToast(t("proxyNotReady", currentLang), "danger", 3e3);
|
|
4632
|
+
return;
|
|
4633
|
+
}
|
|
4634
|
+
const directLink = buildDirectLink(effectiveQrIp, port, status.code || "");
|
|
3956
4635
|
copyText(directLink, t("copiedTip", currentLang));
|
|
3957
4636
|
setStatus((prev) => ({ ...prev, copied: true }));
|
|
3958
4637
|
setTimeout(() => {
|
|
@@ -3997,7 +4676,7 @@ function TailscaleMobileSection(props) {
|
|
|
3997
4676
|
}
|
|
3998
4677
|
}
|
|
3999
4678
|
};
|
|
4000
|
-
return /* @__PURE__ */ (0,
|
|
4679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4001
4680
|
"div",
|
|
4002
4681
|
{
|
|
4003
4682
|
style: {
|
|
@@ -4009,7 +4688,7 @@ function TailscaleMobileSection(props) {
|
|
|
4009
4688
|
position: "relative"
|
|
4010
4689
|
},
|
|
4011
4690
|
children: [
|
|
4012
|
-
toast ? /* @__PURE__ */ (0,
|
|
4691
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4013
4692
|
"div",
|
|
4014
4693
|
{
|
|
4015
4694
|
style: {
|
|
@@ -4034,12 +4713,12 @@ function TailscaleMobileSection(props) {
|
|
|
4034
4713
|
pointerEvents: "none"
|
|
4035
4714
|
},
|
|
4036
4715
|
children: [
|
|
4037
|
-
/* @__PURE__ */ (0,
|
|
4038
|
-
/* @__PURE__ */ (0,
|
|
4716
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: toast.type === "danger" ? "\u{1F6A8}" : toast.type === "success" ? "\u2705" : "\u2139\uFE0F" }),
|
|
4717
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: toast.message })
|
|
4039
4718
|
]
|
|
4040
4719
|
}
|
|
4041
4720
|
) : null,
|
|
4042
|
-
/* @__PURE__ */ (0,
|
|
4721
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4043
4722
|
"div",
|
|
4044
4723
|
{
|
|
4045
4724
|
style: {
|
|
@@ -4051,8 +4730,8 @@ function TailscaleMobileSection(props) {
|
|
|
4051
4730
|
marginBottom: "4px"
|
|
4052
4731
|
},
|
|
4053
4732
|
children: [
|
|
4054
|
-
/* @__PURE__ */ (0,
|
|
4055
|
-
/* @__PURE__ */ (0,
|
|
4733
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { minWidth: "220px", flex: 1 }, children: [
|
|
4734
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4056
4735
|
"div",
|
|
4057
4736
|
{
|
|
4058
4737
|
style: {
|
|
@@ -4063,7 +4742,7 @@ function TailscaleMobileSection(props) {
|
|
|
4063
4742
|
margin: "0 0 6px 0"
|
|
4064
4743
|
},
|
|
4065
4744
|
children: [
|
|
4066
|
-
/* @__PURE__ */ (0,
|
|
4745
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4067
4746
|
"h3",
|
|
4068
4747
|
{
|
|
4069
4748
|
style: {
|
|
@@ -4075,7 +4754,7 @@ function TailscaleMobileSection(props) {
|
|
|
4075
4754
|
children: t("title", currentLang)
|
|
4076
4755
|
}
|
|
4077
4756
|
),
|
|
4078
|
-
/* @__PURE__ */ (0,
|
|
4757
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4079
4758
|
"div",
|
|
4080
4759
|
{
|
|
4081
4760
|
style: { position: "relative", display: "inline-flex", alignItems: "center" },
|
|
@@ -4089,7 +4768,7 @@ function TailscaleMobileSection(props) {
|
|
|
4089
4768
|
);
|
|
4090
4769
|
},
|
|
4091
4770
|
children: [
|
|
4092
|
-
/* @__PURE__ */ (0,
|
|
4771
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4093
4772
|
"span",
|
|
4094
4773
|
{
|
|
4095
4774
|
style: {
|
|
@@ -4106,7 +4785,7 @@ function TailscaleMobileSection(props) {
|
|
|
4106
4785
|
children: PLUGIN_VERSION
|
|
4107
4786
|
}
|
|
4108
4787
|
),
|
|
4109
|
-
showVersionTip ? /* @__PURE__ */ (0,
|
|
4788
|
+
showVersionTip ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4110
4789
|
"div",
|
|
4111
4790
|
{
|
|
4112
4791
|
style: {
|
|
@@ -4134,7 +4813,7 @@ function TailscaleMobileSection(props) {
|
|
|
4134
4813
|
]
|
|
4135
4814
|
}
|
|
4136
4815
|
),
|
|
4137
|
-
hasUpdate && npmLatestVersion ? /* @__PURE__ */ (0,
|
|
4816
|
+
hasUpdate && npmLatestVersion ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4138
4817
|
"a",
|
|
4139
4818
|
{
|
|
4140
4819
|
href: `https://www.npmjs.com/package/dsh-remote-mobile/v/${npmLatestVersion}`,
|
|
@@ -4164,7 +4843,7 @@ function TailscaleMobileSection(props) {
|
|
|
4164
4843
|
]
|
|
4165
4844
|
}
|
|
4166
4845
|
),
|
|
4167
|
-
/* @__PURE__ */ (0,
|
|
4846
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4168
4847
|
"div",
|
|
4169
4848
|
{
|
|
4170
4849
|
style: {
|
|
@@ -4175,7 +4854,7 @@ function TailscaleMobileSection(props) {
|
|
|
4175
4854
|
}
|
|
4176
4855
|
)
|
|
4177
4856
|
] }),
|
|
4178
|
-
/* @__PURE__ */ (0,
|
|
4857
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4179
4858
|
"a",
|
|
4180
4859
|
{
|
|
4181
4860
|
href: "https://github.com/IceApriler/dsh-remote-mobile",
|
|
@@ -4197,15 +4876,15 @@ function TailscaleMobileSection(props) {
|
|
|
4197
4876
|
cursor: "pointer"
|
|
4198
4877
|
},
|
|
4199
4878
|
children: [
|
|
4200
|
-
/* @__PURE__ */ (0,
|
|
4201
|
-
/* @__PURE__ */ (0,
|
|
4879
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { style: { width: "16px", height: "16px", fill: "currentColor" }, viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z" }) }),
|
|
4880
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "dsh-remote-mobile" })
|
|
4202
4881
|
]
|
|
4203
4882
|
}
|
|
4204
4883
|
)
|
|
4205
4884
|
]
|
|
4206
4885
|
}
|
|
4207
4886
|
),
|
|
4208
|
-
status.pairingBridgeConflict && !conflictBannerDismissed ? /* @__PURE__ */ (0,
|
|
4887
|
+
status.pairingBridgeConflict && !conflictBannerDismissed ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4209
4888
|
"div",
|
|
4210
4889
|
{
|
|
4211
4890
|
style: {
|
|
@@ -4218,9 +4897,9 @@ function TailscaleMobileSection(props) {
|
|
|
4218
4897
|
background: "rgba(245, 158, 11, 0.12)"
|
|
4219
4898
|
},
|
|
4220
4899
|
children: [
|
|
4221
|
-
/* @__PURE__ */ (0,
|
|
4222
|
-
/* @__PURE__ */ (0,
|
|
4223
|
-
/* @__PURE__ */ (0,
|
|
4900
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { fontSize: "16px", lineHeight: "20px" }, children: "\u26A0\uFE0F" }),
|
|
4901
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
4902
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4224
4903
|
"div",
|
|
4225
4904
|
{
|
|
4226
4905
|
style: {
|
|
@@ -4232,7 +4911,7 @@ function TailscaleMobileSection(props) {
|
|
|
4232
4911
|
children: t("conflictBannerTitle", currentLang)
|
|
4233
4912
|
}
|
|
4234
4913
|
),
|
|
4235
|
-
/* @__PURE__ */ (0,
|
|
4914
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4236
4915
|
"div",
|
|
4237
4916
|
{
|
|
4238
4917
|
style: {
|
|
@@ -4246,7 +4925,7 @@ function TailscaleMobileSection(props) {
|
|
|
4246
4925
|
})
|
|
4247
4926
|
}
|
|
4248
4927
|
),
|
|
4249
|
-
/* @__PURE__ */ (0,
|
|
4928
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4250
4929
|
"button",
|
|
4251
4930
|
{
|
|
4252
4931
|
type: "button",
|
|
@@ -4278,7 +4957,7 @@ function TailscaleMobileSection(props) {
|
|
|
4278
4957
|
}
|
|
4279
4958
|
)
|
|
4280
4959
|
] }),
|
|
4281
|
-
/* @__PURE__ */ (0,
|
|
4960
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4282
4961
|
"button",
|
|
4283
4962
|
{
|
|
4284
4963
|
type: "button",
|
|
@@ -4304,7 +4983,192 @@ function TailscaleMobileSection(props) {
|
|
|
4304
4983
|
]
|
|
4305
4984
|
}
|
|
4306
4985
|
) : null,
|
|
4307
|
-
/* @__PURE__ */ (0,
|
|
4986
|
+
!status.loading && status.directoryPicker.needsWarning && !dirPickerBannerDismissed ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4987
|
+
"div",
|
|
4988
|
+
{
|
|
4989
|
+
style: {
|
|
4990
|
+
display: "flex",
|
|
4991
|
+
alignItems: "flex-start",
|
|
4992
|
+
gap: "10px",
|
|
4993
|
+
padding: "12px 14px",
|
|
4994
|
+
borderRadius: "10px",
|
|
4995
|
+
border: "1px solid rgba(245, 158, 11, 0.45)",
|
|
4996
|
+
background: "rgba(245, 158, 11, 0.12)"
|
|
4997
|
+
},
|
|
4998
|
+
children: [
|
|
4999
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { fontSize: "16px", lineHeight: "20px" }, children: "\u{1F4C1}" }),
|
|
5000
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
5001
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5002
|
+
"div",
|
|
5003
|
+
{
|
|
5004
|
+
style: {
|
|
5005
|
+
fontSize: "13px",
|
|
5006
|
+
fontWeight: "700",
|
|
5007
|
+
marginBottom: "4px",
|
|
5008
|
+
color: "var(--dsw-alias-label-primary, inherit)"
|
|
5009
|
+
},
|
|
5010
|
+
children: t("dirPickerBannerTitle", currentLang)
|
|
5011
|
+
}
|
|
5012
|
+
),
|
|
5013
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5014
|
+
"div",
|
|
5015
|
+
{
|
|
5016
|
+
style: {
|
|
5017
|
+
fontSize: "12px",
|
|
5018
|
+
lineHeight: 1.6,
|
|
5019
|
+
whiteSpace: "pre-line",
|
|
5020
|
+
color: "var(--dsw-alias-label-secondary, inherit)"
|
|
5021
|
+
},
|
|
5022
|
+
children: t("dirPickerBannerBody", currentLang)
|
|
5023
|
+
}
|
|
5024
|
+
),
|
|
5025
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { marginTop: "10px", display: "flex", alignItems: "center", gap: "8px", flexWrap: "wrap" }, children: [
|
|
5026
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5027
|
+
"button",
|
|
5028
|
+
{
|
|
5029
|
+
type: "button",
|
|
5030
|
+
disabled: isPatchingDirPicker,
|
|
5031
|
+
onClick: () => toggleDirectoryPicker(true),
|
|
5032
|
+
style: {
|
|
5033
|
+
display: "inline-flex",
|
|
5034
|
+
alignItems: "center",
|
|
5035
|
+
gap: "6px",
|
|
5036
|
+
padding: "6px 12px",
|
|
5037
|
+
fontSize: "12px",
|
|
5038
|
+
fontWeight: "600",
|
|
5039
|
+
borderRadius: "7px",
|
|
5040
|
+
cursor: isPatchingDirPicker ? "not-allowed" : "pointer",
|
|
5041
|
+
opacity: isPatchingDirPicker ? 0.7 : 1,
|
|
5042
|
+
border: "none",
|
|
5043
|
+
background: "#2563eb",
|
|
5044
|
+
color: "#ffffff",
|
|
5045
|
+
boxShadow: "0 2px 6px rgba(37, 99, 235, 0.3)"
|
|
5046
|
+
},
|
|
5047
|
+
children: isPatchingDirPicker ? t("dirPickerEnablingBtn", currentLang) : t("dirPickerEnableBtn", currentLang)
|
|
5048
|
+
}
|
|
5049
|
+
),
|
|
5050
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5051
|
+
"button",
|
|
5052
|
+
{
|
|
5053
|
+
type: "button",
|
|
5054
|
+
onClick: () => {
|
|
5055
|
+
const yaml = status.directoryPicker.yamlSnippet || "";
|
|
5056
|
+
if (yaml) {
|
|
5057
|
+
copyText(yaml, t("dirPickerCopiedYamlTip", currentLang));
|
|
5058
|
+
}
|
|
5059
|
+
},
|
|
5060
|
+
style: {
|
|
5061
|
+
display: "inline-flex",
|
|
5062
|
+
alignItems: "center",
|
|
5063
|
+
gap: "6px",
|
|
5064
|
+
padding: "5px 10px",
|
|
5065
|
+
fontSize: "12px",
|
|
5066
|
+
fontWeight: "600",
|
|
5067
|
+
borderRadius: "7px",
|
|
5068
|
+
cursor: "pointer",
|
|
5069
|
+
border: "1px solid rgba(245, 158, 11, 0.55)",
|
|
5070
|
+
background: "rgba(245, 158, 11, 0.18)",
|
|
5071
|
+
color: "var(--dsw-alias-label-primary, inherit)"
|
|
5072
|
+
},
|
|
5073
|
+
children: t("dirPickerCopyYamlBtn", currentLang)
|
|
5074
|
+
}
|
|
5075
|
+
)
|
|
5076
|
+
] })
|
|
5077
|
+
] }),
|
|
5078
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5079
|
+
"button",
|
|
5080
|
+
{
|
|
5081
|
+
type: "button",
|
|
5082
|
+
onClick: () => setDirPickerBannerDismissed(true),
|
|
5083
|
+
title: t("dirPickerBannerDismiss", currentLang),
|
|
5084
|
+
style: {
|
|
5085
|
+
flexShrink: 0,
|
|
5086
|
+
width: "24px",
|
|
5087
|
+
height: "24px",
|
|
5088
|
+
display: "inline-flex",
|
|
5089
|
+
alignItems: "center",
|
|
5090
|
+
justifyContent: "center",
|
|
5091
|
+
border: "none",
|
|
5092
|
+
borderRadius: "6px",
|
|
5093
|
+
cursor: "pointer",
|
|
5094
|
+
fontSize: "12px",
|
|
5095
|
+
background: "rgba(128, 128, 128, 0.15)",
|
|
5096
|
+
color: "var(--dsw-alias-label-secondary, inherit)"
|
|
5097
|
+
},
|
|
5098
|
+
children: "\u2715"
|
|
5099
|
+
}
|
|
5100
|
+
)
|
|
5101
|
+
]
|
|
5102
|
+
}
|
|
5103
|
+
) : null,
|
|
5104
|
+
!status.loading && status.directoryPicker.patchEnabled && status.directoryPicker.restartRequired && !dirPickerBannerDismissed ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
5105
|
+
"div",
|
|
5106
|
+
{
|
|
5107
|
+
style: {
|
|
5108
|
+
display: "flex",
|
|
5109
|
+
alignItems: "flex-start",
|
|
5110
|
+
gap: "10px",
|
|
5111
|
+
padding: "12px 14px",
|
|
5112
|
+
borderRadius: "10px",
|
|
5113
|
+
border: "1px solid rgba(59, 130, 246, 0.45)",
|
|
5114
|
+
background: "rgba(59, 130, 246, 0.1)"
|
|
5115
|
+
},
|
|
5116
|
+
children: [
|
|
5117
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { fontSize: "16px", lineHeight: "20px" }, children: "\u2705" }),
|
|
5118
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
5119
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5120
|
+
"div",
|
|
5121
|
+
{
|
|
5122
|
+
style: {
|
|
5123
|
+
fontSize: "13px",
|
|
5124
|
+
fontWeight: "700",
|
|
5125
|
+
marginBottom: "4px",
|
|
5126
|
+
color: "var(--dsw-alias-label-primary, inherit)"
|
|
5127
|
+
},
|
|
5128
|
+
children: t("dirPickerRestartBannerTitle", currentLang)
|
|
5129
|
+
}
|
|
5130
|
+
),
|
|
5131
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5132
|
+
"div",
|
|
5133
|
+
{
|
|
5134
|
+
style: {
|
|
5135
|
+
fontSize: "12px",
|
|
5136
|
+
lineHeight: 1.6,
|
|
5137
|
+
color: "var(--dsw-alias-label-secondary, inherit)"
|
|
5138
|
+
},
|
|
5139
|
+
children: t("dirPickerRestartBannerBody", currentLang, {
|
|
5140
|
+
path: status.directoryPicker.patchFilePath || "~/.dsh/profiles/web/cordis.patch.yml"
|
|
5141
|
+
})
|
|
5142
|
+
}
|
|
5143
|
+
)
|
|
5144
|
+
] }),
|
|
5145
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5146
|
+
"button",
|
|
5147
|
+
{
|
|
5148
|
+
type: "button",
|
|
5149
|
+
onClick: () => setDirPickerBannerDismissed(true),
|
|
5150
|
+
title: t("dirPickerBannerDismiss", currentLang),
|
|
5151
|
+
style: {
|
|
5152
|
+
flexShrink: 0,
|
|
5153
|
+
width: "24px",
|
|
5154
|
+
height: "24px",
|
|
5155
|
+
display: "inline-flex",
|
|
5156
|
+
alignItems: "center",
|
|
5157
|
+
justifyContent: "center",
|
|
5158
|
+
border: "none",
|
|
5159
|
+
borderRadius: "6px",
|
|
5160
|
+
cursor: "pointer",
|
|
5161
|
+
fontSize: "12px",
|
|
5162
|
+
background: "rgba(128, 128, 128, 0.15)",
|
|
5163
|
+
color: "var(--dsw-alias-label-secondary, inherit)"
|
|
5164
|
+
},
|
|
5165
|
+
children: "\u2715"
|
|
5166
|
+
}
|
|
5167
|
+
)
|
|
5168
|
+
]
|
|
5169
|
+
}
|
|
5170
|
+
) : null,
|
|
5171
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4308
5172
|
"div",
|
|
4309
5173
|
{
|
|
4310
5174
|
style: {
|
|
@@ -4325,7 +5189,7 @@ function TailscaleMobileSection(props) {
|
|
|
4325
5189
|
{ id: "storage", label: t("tabStorage", currentLang) }
|
|
4326
5190
|
].map((item) => {
|
|
4327
5191
|
const isActive = activeTab === item.id;
|
|
4328
|
-
return /* @__PURE__ */ (0,
|
|
5192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4329
5193
|
"button",
|
|
4330
5194
|
{
|
|
4331
5195
|
type: "button",
|
|
@@ -4352,8 +5216,8 @@ function TailscaleMobileSection(props) {
|
|
|
4352
5216
|
})
|
|
4353
5217
|
}
|
|
4354
5218
|
),
|
|
4355
|
-
/* @__PURE__ */ (0,
|
|
4356
|
-
/* @__PURE__ */ (0,
|
|
5219
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: activeTab === "access" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: [
|
|
5220
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4357
5221
|
NetworkCard,
|
|
4358
5222
|
{
|
|
4359
5223
|
status,
|
|
@@ -4363,7 +5227,28 @@ function TailscaleMobileSection(props) {
|
|
|
4363
5227
|
lang: currentLang
|
|
4364
5228
|
}
|
|
4365
5229
|
),
|
|
4366
|
-
/* @__PURE__ */ (0,
|
|
5230
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5231
|
+
ProxyConfigCard,
|
|
5232
|
+
{
|
|
5233
|
+
status,
|
|
5234
|
+
modeInput,
|
|
5235
|
+
setModeInput,
|
|
5236
|
+
proxyPortInput,
|
|
5237
|
+
setProxyPortInput,
|
|
5238
|
+
proxyHostInput,
|
|
5239
|
+
setProxyHostInput,
|
|
5240
|
+
trustedHostsInput,
|
|
5241
|
+
setTrustedHostsInput,
|
|
5242
|
+
saveProxyConfig,
|
|
5243
|
+
resetProxyConfigDefaults,
|
|
5244
|
+
toggleDirectoryPicker,
|
|
5245
|
+
isPatchingDirPicker,
|
|
5246
|
+
copyText,
|
|
5247
|
+
isSaving,
|
|
5248
|
+
lang: currentLang
|
|
5249
|
+
}
|
|
5250
|
+
),
|
|
5251
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4367
5252
|
QrPairingCard,
|
|
4368
5253
|
{
|
|
4369
5254
|
status,
|
|
@@ -4380,7 +5265,7 @@ function TailscaleMobileSection(props) {
|
|
|
4380
5265
|
lang: currentLang
|
|
4381
5266
|
}
|
|
4382
5267
|
),
|
|
4383
|
-
/* @__PURE__ */ (0,
|
|
5268
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4384
5269
|
SecretCard,
|
|
4385
5270
|
{
|
|
4386
5271
|
status,
|
|
@@ -4394,8 +5279,8 @@ function TailscaleMobileSection(props) {
|
|
|
4394
5279
|
}
|
|
4395
5280
|
)
|
|
4396
5281
|
] }),
|
|
4397
|
-
/* @__PURE__ */ (0,
|
|
4398
|
-
/* @__PURE__ */ (0,
|
|
5282
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: activeTab === "devices" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: [
|
|
5283
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4399
5284
|
DeviceListCard,
|
|
4400
5285
|
{
|
|
4401
5286
|
status,
|
|
@@ -4404,7 +5289,7 @@ function TailscaleMobileSection(props) {
|
|
|
4404
5289
|
lang: currentLang
|
|
4405
5290
|
}
|
|
4406
5291
|
),
|
|
4407
|
-
/* @__PURE__ */ (0,
|
|
5292
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4408
5293
|
SecurityCard,
|
|
4409
5294
|
{
|
|
4410
5295
|
status,
|
|
@@ -4413,7 +5298,7 @@ function TailscaleMobileSection(props) {
|
|
|
4413
5298
|
lang: currentLang
|
|
4414
5299
|
}
|
|
4415
5300
|
),
|
|
4416
|
-
/* @__PURE__ */ (0,
|
|
5301
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4417
5302
|
ConfigCard,
|
|
4418
5303
|
{
|
|
4419
5304
|
maxVisitsInput,
|
|
@@ -4430,8 +5315,8 @@ function TailscaleMobileSection(props) {
|
|
|
4430
5315
|
}
|
|
4431
5316
|
)
|
|
4432
5317
|
] }),
|
|
4433
|
-
/* @__PURE__ */ (0,
|
|
4434
|
-
/* @__PURE__ */ (0,
|
|
5318
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: activeTab === "style" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StylesCard, { lang: currentLang, showToast }) }),
|
|
5319
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: activeTab === "storage" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StorageCard, { status, lang: currentLang, copyText }) })
|
|
4435
5320
|
]
|
|
4436
5321
|
}
|
|
4437
5322
|
);
|