dsh-remote-mobile 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/README.md +93 -12
- package/README_EN.md +92 -12
- package/lib/auth/crypto.js +2 -2
- package/lib/auth/gate.d.ts +15 -0
- package/lib/auth/gate.js +49 -0
- package/lib/auth/token.js +9 -4
- package/lib/bridge/compat.d.ts +58 -9
- package/lib/bridge/compat.js +416 -50
- package/lib/client.js +1093 -303
- package/lib/index.d.ts +1 -0
- package/lib/index.js +9 -6
- package/lib/routes/api.d.ts +6 -1
- package/lib/routes/api.js +85 -2
- package/lib/styles/style-snippets.d.ts +133 -0
- package/lib/styles/style-snippets.js +786 -0
- package/package.json +2 -2
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_react10 = __toESM(require("react"), 1);
|
|
51
51
|
|
|
52
52
|
// src/client/components/MainSection.jsx
|
|
53
|
-
var
|
|
53
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
54
54
|
|
|
55
55
|
// src/client/api.js
|
|
56
56
|
function fetchStatus() {
|
|
@@ -132,6 +132,46 @@ function clearIpStatsApi() {
|
|
|
132
132
|
return res.json();
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
|
+
function fetchStyles() {
|
|
136
|
+
return fetch("/api/remote-mobile/styles?_t=" + Date.now()).then(function(res) {
|
|
137
|
+
return res.json();
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function saveStyleSnippet(payload) {
|
|
141
|
+
return fetch("/api/remote-mobile/styles", {
|
|
142
|
+
method: "POST",
|
|
143
|
+
headers: { "Content-Type": "application/json" },
|
|
144
|
+
body: JSON.stringify(payload)
|
|
145
|
+
}).then(function(res) {
|
|
146
|
+
return res.json();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function toggleStyleApi(id, scope, enabled) {
|
|
150
|
+
return fetch("/api/remote-mobile/styles/toggle", {
|
|
151
|
+
method: "POST",
|
|
152
|
+
headers: { "Content-Type": "application/json" },
|
|
153
|
+
body: JSON.stringify({ id, scope, enabled })
|
|
154
|
+
}).then(function(res) {
|
|
155
|
+
return res.json();
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function deleteStyleSnippetApi(id) {
|
|
159
|
+
return fetch("/api/remote-mobile/styles/delete", {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: { "Content-Type": "application/json" },
|
|
162
|
+
body: JSON.stringify({ id })
|
|
163
|
+
}).then(function(res) {
|
|
164
|
+
return res.json();
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function resetStylesApi() {
|
|
168
|
+
return fetch("/api/remote-mobile/styles/reset", {
|
|
169
|
+
method: "POST",
|
|
170
|
+
headers: { "Content-Type": "application/json" }
|
|
171
|
+
}).then(function(res) {
|
|
172
|
+
return res.json();
|
|
173
|
+
});
|
|
174
|
+
}
|
|
135
175
|
|
|
136
176
|
// src/client/qrcode.js
|
|
137
177
|
var generateQrSvg = (function() {
|
|
@@ -739,7 +779,7 @@ var translations = {
|
|
|
739
779
|
storageCardDesc: "\u6240\u6709\u654F\u611F\u51ED\u8BC1\u5747\u5728\u672C\u5730\u7ECF\u8FC7\u52A0\u76D0\u54C8\u5E0C\u6216\u975E\u5BF9\u79F0\u52A0\u5BC6\u4FDD\u62A4\uFF0C\u4E0D\u4F9D\u8D56\u4EFB\u4F55\u7B2C\u4E09\u65B9\u4E91\u7AEF\u9274\u6743\u4E2D\u5FC3\u3002",
|
|
740
780
|
storageDeviceFile: "\u5DF2\u6388\u6743\u8BBE\u5907\u4E0E\u4F1A\u8BDD\u7F13\u5B58\u6587\u4EF6\uFF1A",
|
|
741
781
|
storageRsaFile: "\u670D\u52A1\u7AEF RSA \u79C1\u94A5\u6587\u4EF6 (0o600 \u6743\u9650\u4FDD\u62A4)\uFF1A",
|
|
742
|
-
|
|
782
|
+
storageStylesFile: "\u79FB\u52A8\u7AEF\u6837\u5F0F\u7247\u6BB5\u6587\u4EF6 (\u53EF\u72EC\u7ACB\u542F\u505C\u7684 CSS \u5C0F\u63D2\u4EF6)\uFF1A",
|
|
743
783
|
// 卡片 7: 全局高级配置
|
|
744
784
|
configCardTitle: "\u5168\u5C40\u9AD8\u7EA7\u5B89\u5168\u53C2\u6570\u914D\u7F6E",
|
|
745
785
|
configCardDesc: "\u8C03\u6574\u5355 IP \u8BBF\u95EE\u9891\u7387\u9650\u5236\u3001\u8F93\u9519\u5C01\u7981\u9608\u503C\u4E0E\u9501\u5B9A\u6301\u7EED\u65F6\u95F4\u3002\u70B9\u51FB\u4FDD\u5B58\u5C06\u7ACB\u5373\u751F\u6548\u5E76\u81EA\u52A8\u540C\u6B65\u5199\u56DE ~/.dsh/settings.yaml \u914D\u7F6E\u6587\u4EF6\u3002",
|
|
@@ -758,6 +798,47 @@ var translations = {
|
|
|
758
798
|
saveConfigSuccessToast: "\u9AD8\u7EA7\u5B89\u5168\u53C2\u6570\u5DF2\u6210\u529F\u4FDD\u5B58\u5E76\u540C\u6B65\u5230 settings.yaml\uFF01",
|
|
759
799
|
restoreDefaultsSuccessToast: "\u5DF2\u6210\u529F\u6062\u590D\u9ED8\u8BA4\u5B89\u5168\u53C2\u6570\u5E76\u7ACB\u5373\u751F\u6548\uFF01",
|
|
760
800
|
saveConfigFailTip: "\u53C2\u6570\u5FC5\u987B\u4E3A\u5927\u4E8E 0 \u7684\u6709\u6548\u6574\u6570",
|
|
801
|
+
// 卡片 8: 移动端样式片段(样式小插件)
|
|
802
|
+
tabAccess: "\u63A5\u5165",
|
|
803
|
+
tabDevices: "\u8BBE\u5907\u4E0E\u5B89\u5168",
|
|
804
|
+
tabStyle: "\u6837\u5F0F\u8986\u5199",
|
|
805
|
+
tabStorage: "\u672C\u5730\u6570\u636E",
|
|
806
|
+
stylesCardTitle: "\u79FB\u52A8\u7AEF\u6837\u5F0F\u7247\u6BB5\uFF08\u6837\u5F0F\u5C0F\u63D2\u4EF6\uFF09",
|
|
807
|
+
stylesCardDesc: "\u4EE5\u53EF\u72EC\u7ACB\u542F\u505C\u7684 CSS \u7247\u6BB5\u65B9\u5F0F\u9002\u914D DSH Web \u754C\u9762\u3002\u5185\u7F6E\u9884\u8BBE\u6309\u754C\u9762\u533A\u57DF\u5206\u4E3A\u4FA7\u8FB9\u680F\u3001\u8BBE\u7F6E\u9762\u677F\u4E0E\u6B63\u6587\u4E09\u6BB5\uFF0C\u6BCF\u6BB5\u5747\u53EF\u5206\u522B\u8BBE\u7F6E PC / \u79FB\u52A8\u7AEF\u662F\u5426\u542F\u7528\uFF1B\u4F60\u4E5F\u53EF\u4EE5\u7C98\u8D34\u81EA\u5DF1\u7684 CSS \u5C0F\u63D2\u4EF6\uFF0C\u4FDD\u5B58\u540E\u4E0B\u4E00\u6B21\u9875\u9762\u52A0\u8F7D\u7ACB\u5373\u751F\u6548\uFF0C\u65E0\u9700\u91CD\u542F\u3002",
|
|
808
|
+
stylesPresetsTitle: "\u{1F9E9} \u5185\u7F6E\u9884\u8BBE\u7247\u6BB5",
|
|
809
|
+
stylesCustomTitle: "\u270D\uFE0F \u81EA\u5B9A\u4E49\u7247\u6BB5",
|
|
810
|
+
stylesPcShort: "PC",
|
|
811
|
+
stylesMobileShort: "\u79FB\u52A8\u7AEF",
|
|
812
|
+
stylesBothDevices: "PC + \u79FB\u52A8\u7AEF",
|
|
813
|
+
stylesMobileOnlyBadge: "\u4EC5\u79FB\u52A8\u7AEF",
|
|
814
|
+
stylesPcOnlyBadge: "\u4EC5 PC",
|
|
815
|
+
stylesDisabled: "\u5DF2\u505C\u7528",
|
|
816
|
+
stylesViewCss: "\u67E5\u770B CSS",
|
|
817
|
+
stylesHideCss: "\u6536\u8D77 CSS",
|
|
818
|
+
stylesNamePlaceholder: "\u7247\u6BB5\u540D\u79F0\uFF08\u5FC5\u586B\uFF09",
|
|
819
|
+
stylesCssPlaceholder: "\u7C98\u8D34\u6216\u7F16\u5199 CSS \u4EE3\u7801\u7247\u6BB5\u2026\uFF08\u79FB\u52A8\u7AEF\u53EF\u7528 html[data-dsh-mobile] \u4F5C\u4E3A\u4F5C\u7528\u57DF\u9009\u62E9\u5668\uFF09",
|
|
820
|
+
stylesAddNew: "\uFF0B \u65B0\u589E\u81EA\u5B9A\u4E49\u7247\u6BB5",
|
|
821
|
+
stylesSave: "\u{1F4BE} \u4FDD\u5B58\u7247\u6BB5",
|
|
822
|
+
stylesCancelEdit: "\u53D6\u6D88",
|
|
823
|
+
stylesEditBtn: "\u7F16\u8F91",
|
|
824
|
+
stylesDeleteBtn: "\u5220\u9664",
|
|
825
|
+
stylesResetAll: "\u{1F504} \u6062\u590D\u9ED8\u8BA4\u542F\u505C",
|
|
826
|
+
stylesEmptyCustom: "\u6682\u65E0\u81EA\u5B9A\u4E49\u7247\u6BB5\uFF0C\u70B9\u51FB\u300C\u65B0\u589E\u81EA\u5B9A\u4E49\u7247\u6BB5\u300D\u5F00\u59CB\u3002",
|
|
827
|
+
stylesLoadFail: "\u52A0\u8F7D\u6837\u5F0F\u7247\u6BB5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
|
|
828
|
+
stylesSaveSuccess: "\u6837\u5F0F\u7247\u6BB5\u5DF2\u4FDD\u5B58\uFF0C\u5237\u65B0\u9875\u9762\u5373\u53EF\u770B\u5230\u6548\u679C",
|
|
829
|
+
stylesDeleteConfirm: "\u786E\u5B9A\u8981\u5220\u9664\u8BE5\u81EA\u5B9A\u4E49\u6837\u5F0F\u7247\u6BB5\u5417\uFF1F",
|
|
830
|
+
stylesResetConfirm: "\u786E\u5B9A\u8981\u6062\u590D\u6240\u6709\u7247\u6BB5\u7684\u9ED8\u8BA4\u542F\u505C\u72B6\u6001\u5417\uFF1F\uFF08\u5185\u7F6E\u9884\u8BBE\uFF1APC \u5173\u95ED\u3001\u79FB\u52A8\u7AEF\u542F\u7528\uFF1B\u81EA\u5B9A\u4E49\u7247\u6BB5\uFF1APC \u5173\u95ED\u3001\u79FB\u52A8\u7AEF\u542F\u7528\uFF09",
|
|
831
|
+
stylesFieldsRequired: "\u8BF7\u586B\u5199\u7247\u6BB5\u540D\u79F0\u4E0E CSS \u5185\u5BB9",
|
|
832
|
+
stylesHint: "\u{1F4A1} \u63D0\u793A\uFF1A\u6BCF\u6BB5\u9884\u8BBE\u4E0E\u81EA\u5B9A\u4E49\u7247\u6BB5\u90FD\u652F\u6301 PC / \u79FB\u52A8\u7AEF\u5206\u522B\u542F\u7528\u3002\u79FB\u52A8\u7AEF\u8BF7\u6C42\u4F1A\u7ED9 <html> \u6253\u4E0A data-dsh-mobile \u6807\u8BB0\uFF1B\u5185\u7F6E\u9884\u8BBE\u9762\u5411\u79FB\u52A8\u7AEF\u4F18\u5316\uFF08\u9ED8\u8BA4 PC \u5173\u95ED\uFF09\uFF0C\u5728 PC \u4E0A\u542F\u7528\u65F6\u8BF7\u786E\u4FDD\u7247\u6BB5\u4E0D\u4F9D\u8D56 data-dsh-mobile \u4F5C\u7528\u57DF\u3002",
|
|
833
|
+
// 插件共存警示横幅
|
|
834
|
+
conflictBannerTitle: "\u68C0\u6D4B\u5230\u5176\u4ED6\u8FDC\u7A0B\u63A5\u5165\u63D2\u4EF6",
|
|
835
|
+
conflictUnknownPlugin: "\u53E6\u4E00\u6B3E\u8FDC\u7A0B\u63A5\u5165\u7C7B\u63D2\u4EF6",
|
|
836
|
+
conflictBannerBody: "\u68C0\u6D4B\u5230 {plugin} \u5DF2\u5360\u7528\u914D\u5BF9\u5171\u4EAB\u670D\u52A1\uFF08remoteWebUiPairing\uFF09\uFF0C\u672C\u63D2\u4EF6\u5DF2\u81EA\u52A8\u8BA9\u51FA\u4EE5\u4FDD\u8BC1\u6B63\u5E38\u542F\u52A8\u3002\u4E24\u5957\u8FDC\u7A0B\u63A5\u5165\u529F\u80FD\u5E76\u5B58\u53EF\u80FD\u51FA\u73B0\u91CD\u590D\u5165\u53E3\u4E0E\u72B6\u6001\u4E0D\u4E00\u81F4\uFF0C\u5EFA\u8BAE\u53EA\u4FDD\u7559\u5176\u4E00\u3002\u53EF\u590D\u5236\u4E0B\u65B9\u8BCA\u65AD\u4FE1\u606F\uFF0C\u7C98\u8D34\u7ED9 AI \u52A9\u624B\u6309\u6B65\u9AA4\u5904\u7406\u3002",
|
|
837
|
+
conflictCopyBtn: "\u{1F4CB} \u590D\u5236\u8BCA\u65AD\u4E0E\u4FEE\u590D\u4FE1\u606F",
|
|
838
|
+
conflictCopiedTip: "\u8BCA\u65AD\u4FE1\u606F\u5DF2\u590D\u5236\uFF0C\u53EF\u76F4\u63A5\u7C98\u8D34\u7ED9 AI \u52A9\u624B\u534F\u52A9\u5904\u7406",
|
|
839
|
+
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",
|
|
840
|
+
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",
|
|
841
|
+
conflictBannerDismiss: "\u77E5\u9053\u4E86",
|
|
761
842
|
// Toast 提示
|
|
762
843
|
toastDeviceConnected: "\u{1F389} \u65B0\u8BBE\u5907\u63A5\u5165\u6210\u529F\uFF1A{name} ({ip})",
|
|
763
844
|
toastDeviceOnline: "\u{1F4F6} \u8BBE\u5907\u91CD\u65B0\u4E0A\u7EBF\uFF1A{name} ({ip})",
|
|
@@ -850,7 +931,7 @@ var translations = {
|
|
|
850
931
|
storageCardDesc: "All sensitive credentials are protected locally via slow salt hashing and asymmetric RSA cryptography, without cloud dependencies.",
|
|
851
932
|
storageDeviceFile: "Authorized devices & session cache:",
|
|
852
933
|
storageRsaFile: "Server RSA private key (0o600 protected):",
|
|
853
|
-
|
|
934
|
+
storageStylesFile: "Mobile style snippets file (toggleable CSS mini-plugins):",
|
|
854
935
|
// Card 7: Advanced Security Config
|
|
855
936
|
configCardTitle: "Global Security Policy Configuration",
|
|
856
937
|
configCardDesc: "Configure per-IP rate limits, brute-force failure thresholds, and lockout durations. Changes take effect immediately and sync to ~/.dsh/settings.yaml.",
|
|
@@ -869,6 +950,47 @@ var translations = {
|
|
|
869
950
|
saveConfigSuccessToast: "Security policy successfully saved and synced to settings.yaml!",
|
|
870
951
|
restoreDefaultsSuccessToast: "Default security policies restored and applied immediately!",
|
|
871
952
|
saveConfigFailTip: "Parameters must be valid integers greater than 0",
|
|
953
|
+
// Card 8: Mobile Style Snippets (style mini-plugin)
|
|
954
|
+
tabAccess: "Access",
|
|
955
|
+
tabDevices: "Devices & Security",
|
|
956
|
+
tabStyle: "Style Overrides",
|
|
957
|
+
tabStorage: "Local Data",
|
|
958
|
+
stylesCardTitle: "Mobile Style Snippets",
|
|
959
|
+
stylesCardDesc: "Adapt the DSH web UI via toggleable CSS snippets. Built-in presets are split by UI area: sidebar, settings panel and conversation. Each can be enabled per device (PC / Mobile). You can also add your own CSS mini-plugins; changes take effect on the next page load without restart.",
|
|
960
|
+
stylesPresetsTitle: "\u{1F9E9} Built-in Presets",
|
|
961
|
+
stylesCustomTitle: "\u270D\uFE0F Custom Snippets",
|
|
962
|
+
stylesPcShort: "PC",
|
|
963
|
+
stylesMobileShort: "Mobile",
|
|
964
|
+
stylesBothDevices: "PC + Mobile",
|
|
965
|
+
stylesMobileOnlyBadge: "Mobile only",
|
|
966
|
+
stylesPcOnlyBadge: "PC only",
|
|
967
|
+
stylesDisabled: "Disabled",
|
|
968
|
+
stylesViewCss: "View CSS",
|
|
969
|
+
stylesHideCss: "Hide CSS",
|
|
970
|
+
stylesNamePlaceholder: "Snippet name (required)",
|
|
971
|
+
stylesCssPlaceholder: "Paste or write CSS here\u2026 (html[data-dsh-mobile] can be used as a mobile scope selector)",
|
|
972
|
+
stylesAddNew: "\uFF0B Add Custom Snippet",
|
|
973
|
+
stylesSave: "\u{1F4BE} Save Snippet",
|
|
974
|
+
stylesCancelEdit: "Cancel",
|
|
975
|
+
stylesEditBtn: "Edit",
|
|
976
|
+
stylesDeleteBtn: "Delete",
|
|
977
|
+
stylesResetAll: "\u{1F504} Reset Defaults",
|
|
978
|
+
stylesEmptyCustom: 'No custom snippets yet. Click "Add Custom Snippet" to start.',
|
|
979
|
+
stylesLoadFail: "Failed to load style snippets, please try again later",
|
|
980
|
+
stylesSaveSuccess: "Style snippet saved. Refresh to see the effect.",
|
|
981
|
+
stylesDeleteConfirm: "Are you sure you want to delete this custom style snippet?",
|
|
982
|
+
stylesResetConfirm: "Reset all snippets to default states? (Built-ins: PC off / Mobile on. Custom: PC off / Mobile on.)",
|
|
983
|
+
stylesFieldsRequired: "Please fill in both the snippet name and CSS content",
|
|
984
|
+
stylesHint: "\u{1F4A1} Tip: every preset and custom snippet has separate PC / Mobile toggles. Mobile requests add a data-dsh-mobile attribute to <html>. Built-ins target mobile (PC off by default); when enabling them on PC, make sure they do not depend on the data-dsh-mobile scope.",
|
|
985
|
+
// Plugin coexistence banner
|
|
986
|
+
conflictBannerTitle: "Another remote-access plugin detected",
|
|
987
|
+
conflictUnknownPlugin: "another remote-access plugin",
|
|
988
|
+
conflictBannerBody: "{plugin} has already registered the shared pairing service (remoteWebUiPairing); this plugin has automatically yielded it to keep startup safe. Running two remote-access features side by side may cause duplicated entries and inconsistent state \u2014 keeping only one is recommended. Copy the diagnosis below and paste it to an AI assistant for step-by-step help.",
|
|
989
|
+
conflictCopyBtn: "\u{1F4CB} Copy diagnosis & fix",
|
|
990
|
+
conflictCopiedTip: "Diagnosis copied! Paste it to your AI assistant",
|
|
991
|
+
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',
|
|
992
|
+
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',
|
|
993
|
+
conflictBannerDismiss: "Got it",
|
|
872
994
|
// Toast
|
|
873
995
|
toastDeviceConnected: "\u{1F389} New device connected: {name} ({ip})",
|
|
874
996
|
toastDeviceOnline: "\u{1F4F6} Device reconnected: {name} ({ip})",
|
|
@@ -2430,8 +2552,42 @@ function SecurityCard({ status, unlockIp, clearIpStats, lang }) {
|
|
|
2430
2552
|
// src/client/components/StorageCard.jsx
|
|
2431
2553
|
var import_react6 = __toESM(require("react"), 1);
|
|
2432
2554
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2433
|
-
function StorageCard({ status, lang }) {
|
|
2434
|
-
|
|
2555
|
+
function StorageCard({ status, lang, copyText }) {
|
|
2556
|
+
const handleCopy = (path, tip) => {
|
|
2557
|
+
if (!path) return;
|
|
2558
|
+
if (typeof copyText === "function") {
|
|
2559
|
+
copyText(path, tip);
|
|
2560
|
+
return;
|
|
2561
|
+
}
|
|
2562
|
+
if (typeof navigator !== "undefined" && navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
|
2563
|
+
navigator.clipboard.writeText(path).catch(() => {
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2567
|
+
const devicesPath = status.persistPath || "";
|
|
2568
|
+
const rsaPath = status.rsaKeyPath || "";
|
|
2569
|
+
const stylesPath = status.styleSnippetsPath || "";
|
|
2570
|
+
const items = [
|
|
2571
|
+
{
|
|
2572
|
+
icon: "\u{1F4C1}",
|
|
2573
|
+
title: t("storageDeviceFile", lang),
|
|
2574
|
+
path: devicesPath,
|
|
2575
|
+
tip: lang === "en" ? "Devices storage path copied!" : "\u5DF2\u6210\u529F\u590D\u5236\u8BBE\u5907\u5B58\u50A8\u6587\u4EF6\u8DEF\u5F84\uFF01"
|
|
2576
|
+
},
|
|
2577
|
+
{
|
|
2578
|
+
icon: "\u{1F511}",
|
|
2579
|
+
title: t("storageRsaFile", lang),
|
|
2580
|
+
path: rsaPath,
|
|
2581
|
+
tip: lang === "en" ? "RSA key path copied!" : "\u5DF2\u6210\u529F\u590D\u5236 RSA \u5BC6\u94A5\u6587\u4EF6\u8DEF\u5F84\uFF01"
|
|
2582
|
+
},
|
|
2583
|
+
{
|
|
2584
|
+
icon: "\u{1F3A8}",
|
|
2585
|
+
title: t("storageStylesFile", lang),
|
|
2586
|
+
path: stylesPath,
|
|
2587
|
+
tip: lang === "en" ? "Style snippets path copied!" : "\u5DF2\u6210\u529F\u590D\u5236\u6837\u5F0F\u7247\u6BB5\u6587\u4EF6\u8DEF\u5F84\uFF01"
|
|
2588
|
+
}
|
|
2589
|
+
];
|
|
2590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2435
2591
|
"div",
|
|
2436
2592
|
{
|
|
2437
2593
|
style: {
|
|
@@ -2443,138 +2599,69 @@ function StorageCard({ status, lang }) {
|
|
|
2443
2599
|
flexDirection: "column",
|
|
2444
2600
|
gap: "10px"
|
|
2445
2601
|
},
|
|
2446
|
-
children:
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
{
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
] })
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
}
|
|
2510
|
-
),
|
|
2511
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2512
|
-
"div",
|
|
2513
|
-
{
|
|
2514
|
-
style: {
|
|
2515
|
-
display: "flex",
|
|
2516
|
-
alignItems: "center",
|
|
2517
|
-
justifyContent: "space-between",
|
|
2518
|
-
gap: "12px",
|
|
2519
|
-
paddingTop: "8px",
|
|
2520
|
-
borderTop: "1px dashed var(--dsw-alias-border-l2, rgba(128,128,128,0.15))"
|
|
2521
|
-
},
|
|
2522
|
-
children: [
|
|
2523
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "10px", minWidth: 0 }, children: [
|
|
2524
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: "18px" }, children: "\u{1F511}" }),
|
|
2525
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "2px", minWidth: 0 }, children: [
|
|
2526
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2527
|
-
"div",
|
|
2528
|
-
{
|
|
2529
|
-
style: {
|
|
2530
|
-
fontSize: "12px",
|
|
2531
|
-
fontWeight: "600",
|
|
2532
|
-
color: "var(--dsw-alias-label-primary, inherit)"
|
|
2533
|
-
},
|
|
2534
|
-
children: t("storageRsaFile", lang)
|
|
2535
|
-
}
|
|
2536
|
-
),
|
|
2537
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2538
|
-
"code",
|
|
2539
|
-
{
|
|
2540
|
-
style: {
|
|
2541
|
-
fontSize: "11px",
|
|
2542
|
-
color: "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
2543
|
-
fontFamily: "monospace",
|
|
2544
|
-
wordBreak: "break-all"
|
|
2545
|
-
},
|
|
2546
|
-
children: status.rsaKeyPath || "~/.dsh/remote-mobile/rsa-keys.json"
|
|
2547
|
-
}
|
|
2548
|
-
)
|
|
2549
|
-
] })
|
|
2550
|
-
] }),
|
|
2551
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2552
|
-
"button",
|
|
2553
|
-
{
|
|
2554
|
-
type: "button",
|
|
2555
|
-
onClick: () => {
|
|
2556
|
-
const p = status.rsaKeyPath || "~/.dsh/remote-mobile/rsa-keys.json";
|
|
2557
|
-
navigator.clipboard.writeText(p).then(() => {
|
|
2558
|
-
alert((lang === "en" ? "Copied RSA path:\n" : "RSA \u5BC6\u94A5\u6587\u4EF6\u8DEF\u5F84\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\uFF01\n") + p);
|
|
2559
|
-
});
|
|
2560
|
-
},
|
|
2561
|
-
style: {
|
|
2562
|
-
padding: "4px 10px",
|
|
2563
|
-
background: "var(--dsw-alias-bg-layer-3, rgba(128,128,128,0.1))",
|
|
2564
|
-
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.2))",
|
|
2565
|
-
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
2566
|
-
borderRadius: "6px",
|
|
2567
|
-
fontSize: "11px",
|
|
2568
|
-
cursor: "pointer",
|
|
2569
|
-
whiteSpace: "nowrap"
|
|
2570
|
-
},
|
|
2571
|
-
children: t("copyUrlBtn", lang)
|
|
2572
|
-
}
|
|
2573
|
-
)
|
|
2574
|
-
]
|
|
2575
|
-
}
|
|
2576
|
-
)
|
|
2577
|
-
]
|
|
2602
|
+
children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2603
|
+
"div",
|
|
2604
|
+
{
|
|
2605
|
+
style: {
|
|
2606
|
+
display: "flex",
|
|
2607
|
+
alignItems: "center",
|
|
2608
|
+
justifyContent: "space-between",
|
|
2609
|
+
gap: "12px",
|
|
2610
|
+
paddingTop: index > 0 ? "8px" : "0",
|
|
2611
|
+
borderTop: index > 0 ? "1px dashed var(--dsw-alias-border-l2, rgba(128,128,128,0.15))" : "none"
|
|
2612
|
+
},
|
|
2613
|
+
children: [
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "10px", minWidth: 0, flex: 1 }, children: [
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: "18px", flexShrink: 0 }, children: item.icon }),
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "2px", minWidth: 0 }, children: [
|
|
2617
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2618
|
+
"div",
|
|
2619
|
+
{
|
|
2620
|
+
style: {
|
|
2621
|
+
fontSize: "12px",
|
|
2622
|
+
fontWeight: "600",
|
|
2623
|
+
color: "var(--dsw-alias-label-primary, inherit)"
|
|
2624
|
+
},
|
|
2625
|
+
children: item.title
|
|
2626
|
+
}
|
|
2627
|
+
),
|
|
2628
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2629
|
+
"code",
|
|
2630
|
+
{
|
|
2631
|
+
style: {
|
|
2632
|
+
fontSize: "11px",
|
|
2633
|
+
color: "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
2634
|
+
fontFamily: "monospace",
|
|
2635
|
+
wordBreak: "break-all"
|
|
2636
|
+
},
|
|
2637
|
+
children: item.path || "..."
|
|
2638
|
+
}
|
|
2639
|
+
)
|
|
2640
|
+
] })
|
|
2641
|
+
] }),
|
|
2642
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2643
|
+
"button",
|
|
2644
|
+
{
|
|
2645
|
+
type: "button",
|
|
2646
|
+
onClick: () => handleCopy(item.path, item.tip),
|
|
2647
|
+
style: {
|
|
2648
|
+
padding: "4px 10px",
|
|
2649
|
+
background: "var(--dsw-alias-bg-layer-3, rgba(128,128,128,0.1))",
|
|
2650
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.2))",
|
|
2651
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
2652
|
+
borderRadius: "6px",
|
|
2653
|
+
fontSize: "11px",
|
|
2654
|
+
cursor: "pointer",
|
|
2655
|
+
whiteSpace: "nowrap",
|
|
2656
|
+
flexShrink: 0
|
|
2657
|
+
},
|
|
2658
|
+
children: t("copyUrlBtn", lang)
|
|
2659
|
+
}
|
|
2660
|
+
)
|
|
2661
|
+
]
|
|
2662
|
+
},
|
|
2663
|
+
index
|
|
2664
|
+
))
|
|
2578
2665
|
}
|
|
2579
2666
|
);
|
|
2580
2667
|
}
|
|
@@ -2592,7 +2679,8 @@ function ConfigCard({
|
|
|
2592
2679
|
saveAdvancedConfig,
|
|
2593
2680
|
resetAdvancedConfigDefaults,
|
|
2594
2681
|
isSaving,
|
|
2595
|
-
lang
|
|
2682
|
+
lang,
|
|
2683
|
+
copyText
|
|
2596
2684
|
}) {
|
|
2597
2685
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2598
2686
|
"div",
|
|
@@ -2636,11 +2724,12 @@ function ConfigCard({
|
|
|
2636
2724
|
{
|
|
2637
2725
|
type: "button",
|
|
2638
2726
|
onClick: () => {
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2727
|
+
if (typeof copyText === "function") {
|
|
2728
|
+
copyText(
|
|
2729
|
+
"~/.dsh/settings.yaml",
|
|
2730
|
+
lang === "en" ? "Settings path copied (~/.dsh/settings.yaml)" : "\u5DF2\u590D\u5236\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08~/.dsh/settings.yaml\uFF09"
|
|
2642
2731
|
);
|
|
2643
|
-
}
|
|
2732
|
+
}
|
|
2644
2733
|
},
|
|
2645
2734
|
style: {
|
|
2646
2735
|
padding: "4px 10px",
|
|
@@ -2890,15 +2979,478 @@ function ConfigCard({
|
|
|
2890
2979
|
);
|
|
2891
2980
|
}
|
|
2892
2981
|
|
|
2982
|
+
// src/client/components/StylesCard.jsx
|
|
2983
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
2984
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2985
|
+
function StylesCard({ lang, showToast }) {
|
|
2986
|
+
const [snippets, setSnippets] = (0, import_react8.useState)([]);
|
|
2987
|
+
const [loading, setLoading] = (0, import_react8.useState)(true);
|
|
2988
|
+
const [editingId, setEditingId] = (0, import_react8.useState)(null);
|
|
2989
|
+
const [showForm, setShowForm] = (0, import_react8.useState)(false);
|
|
2990
|
+
const [name, setName] = (0, import_react8.useState)("");
|
|
2991
|
+
const [css, setCss] = (0, import_react8.useState)("");
|
|
2992
|
+
const [pcEnabled, setPcEnabled] = (0, import_react8.useState)(false);
|
|
2993
|
+
const [mobileEnabled, setMobileEnabled] = (0, import_react8.useState)(true);
|
|
2994
|
+
const [expanded, setExpanded] = (0, import_react8.useState)({});
|
|
2995
|
+
const [feedback, setFeedback] = (0, import_react8.useState)("");
|
|
2996
|
+
const showFeedback = (0, import_react8.useCallback)((msg, type = "success") => {
|
|
2997
|
+
if (typeof showToast === "function") {
|
|
2998
|
+
showToast(msg, type);
|
|
2999
|
+
} else {
|
|
3000
|
+
setFeedback(msg);
|
|
3001
|
+
setTimeout(() => setFeedback(""), 3500);
|
|
3002
|
+
}
|
|
3003
|
+
}, [showToast]);
|
|
3004
|
+
const load = (0, import_react8.useCallback)(() => {
|
|
3005
|
+
fetchStyles().then((data) => {
|
|
3006
|
+
setSnippets(data.snippets || []);
|
|
3007
|
+
setLoading(false);
|
|
3008
|
+
}).catch(() => {
|
|
3009
|
+
setLoading(false);
|
|
3010
|
+
showFeedback(t("stylesLoadFail", lang), "danger");
|
|
3011
|
+
});
|
|
3012
|
+
}, [lang, showFeedback]);
|
|
3013
|
+
(0, import_react8.useEffect)(() => {
|
|
3014
|
+
load();
|
|
3015
|
+
}, [load]);
|
|
3016
|
+
const toggle = (id, scope, enabled) => {
|
|
3017
|
+
toggleStyleApi(id, scope, enabled).then((data) => {
|
|
3018
|
+
if (data.success) {
|
|
3019
|
+
load();
|
|
3020
|
+
const scopeLabel = scope === "pc" ? lang === "en" ? "PC" : "PC \u7AEF" : lang === "en" ? "Mobile" : "\u79FB\u52A8\u7AEF";
|
|
3021
|
+
showFeedback(
|
|
3022
|
+
enabled ? lang === "en" ? scopeLabel + " enabled!" : scopeLabel + " \u5DF2\u542F\u7528\uFF01" : lang === "en" ? scopeLabel + " disabled!" : scopeLabel + " \u5DF2\u505C\u7528\uFF01",
|
|
3023
|
+
"success"
|
|
3024
|
+
);
|
|
3025
|
+
}
|
|
3026
|
+
});
|
|
3027
|
+
};
|
|
3028
|
+
const startEdit = (s) => {
|
|
3029
|
+
setEditingId(s.id);
|
|
3030
|
+
setShowForm(true);
|
|
3031
|
+
setName(s.name);
|
|
3032
|
+
setCss(s.css);
|
|
3033
|
+
setPcEnabled(s.pcEnabled !== false);
|
|
3034
|
+
setMobileEnabled(s.mobileEnabled !== false);
|
|
3035
|
+
setFeedback("");
|
|
3036
|
+
};
|
|
3037
|
+
const cancelEdit = () => {
|
|
3038
|
+
setEditingId(null);
|
|
3039
|
+
setShowForm(false);
|
|
3040
|
+
setName("");
|
|
3041
|
+
setCss("");
|
|
3042
|
+
setPcEnabled(false);
|
|
3043
|
+
setMobileEnabled(true);
|
|
3044
|
+
setFeedback("");
|
|
3045
|
+
};
|
|
3046
|
+
const save = () => {
|
|
3047
|
+
if (!name.trim() || !css.trim()) {
|
|
3048
|
+
alert(t("stylesFieldsRequired", lang));
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
3051
|
+
saveStyleSnippet({
|
|
3052
|
+
id: editingId || void 0,
|
|
3053
|
+
name: name.trim(),
|
|
3054
|
+
css,
|
|
3055
|
+
pcEnabled,
|
|
3056
|
+
mobileEnabled
|
|
3057
|
+
}).then((data) => {
|
|
3058
|
+
if (data.success) {
|
|
3059
|
+
load();
|
|
3060
|
+
cancelEdit();
|
|
3061
|
+
showFeedback(t("stylesSaveSuccess", lang));
|
|
3062
|
+
} else {
|
|
3063
|
+
alert((lang === "en" ? "Save failed: " : "\u4FDD\u5B58\u5931\u8D25\uFF1A") + (data.reason || ""));
|
|
3064
|
+
}
|
|
3065
|
+
}).catch(() => {
|
|
3066
|
+
alert(lang === "en" ? "Network request failed, please try again." : "\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
|
|
3067
|
+
});
|
|
3068
|
+
};
|
|
3069
|
+
const remove = (s) => {
|
|
3070
|
+
if (s.builtin) return;
|
|
3071
|
+
if (confirm(t("stylesDeleteConfirm", lang))) {
|
|
3072
|
+
deleteStyleSnippetApi(s.id).then((data) => {
|
|
3073
|
+
if (data.success) {
|
|
3074
|
+
if (editingId === s.id) cancelEdit();
|
|
3075
|
+
load();
|
|
3076
|
+
showFeedback(lang === "en" ? "Style snippet deleted!" : "\u81EA\u5B9A\u4E49\u6837\u5F0F\u7247\u6BB5\u5DF2\u5220\u9664\uFF01");
|
|
3077
|
+
}
|
|
3078
|
+
});
|
|
3079
|
+
}
|
|
3080
|
+
};
|
|
3081
|
+
const resetAll = () => {
|
|
3082
|
+
if (!confirm(t("stylesResetConfirm", lang))) return;
|
|
3083
|
+
resetStylesApi().then((data) => {
|
|
3084
|
+
if (data.success) {
|
|
3085
|
+
load();
|
|
3086
|
+
showFeedback(lang === "en" ? "Style snippets reset to defaults!" : "\u5DF2\u6062\u590D\u6240\u6709\u7247\u6BB5\u7684\u9ED8\u8BA4\u542F\u505C\u72B6\u6001\uFF01");
|
|
3087
|
+
}
|
|
3088
|
+
});
|
|
3089
|
+
};
|
|
3090
|
+
const toggleExpand = (id) => {
|
|
3091
|
+
setExpanded((prev) => ({ ...prev, [id]: !prev[id] }));
|
|
3092
|
+
};
|
|
3093
|
+
const scopeBadge = (s) => {
|
|
3094
|
+
if (s.pcEnabled && s.mobileEnabled) return t("stylesBothDevices", lang);
|
|
3095
|
+
if (s.mobileEnabled) return "\u{1F4F1} " + t("stylesMobileOnlyBadge", lang);
|
|
3096
|
+
if (s.pcEnabled) return "\u{1F5A5}\uFE0F " + t("stylesPcOnlyBadge", lang);
|
|
3097
|
+
return t("stylesDisabled", lang);
|
|
3098
|
+
};
|
|
3099
|
+
const rowStyle = {
|
|
3100
|
+
display: "flex",
|
|
3101
|
+
flexDirection: "column",
|
|
3102
|
+
gap: "8px",
|
|
3103
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(128,128,128,0.06))",
|
|
3104
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.12))",
|
|
3105
|
+
borderRadius: "8px",
|
|
3106
|
+
padding: "10px 12px"
|
|
3107
|
+
};
|
|
3108
|
+
const miniBtnStyle = {
|
|
3109
|
+
padding: "4px 10px",
|
|
3110
|
+
background: "var(--dsw-alias-bg-layer-3, rgba(128,128,128,0.1))",
|
|
3111
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.2))",
|
|
3112
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
3113
|
+
borderRadius: "6px",
|
|
3114
|
+
fontSize: "11px",
|
|
3115
|
+
cursor: "pointer",
|
|
3116
|
+
whiteSpace: "nowrap"
|
|
3117
|
+
};
|
|
3118
|
+
const primaryBtnStyle = {
|
|
3119
|
+
...miniBtnStyle,
|
|
3120
|
+
background: "rgba(59,130,246,0.15)",
|
|
3121
|
+
color: "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
3122
|
+
border: "1px solid rgba(59,130,246,0.3)"
|
|
3123
|
+
};
|
|
3124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3125
|
+
"div",
|
|
3126
|
+
{
|
|
3127
|
+
style: {
|
|
3128
|
+
background: "var(--dsw-alias-bg-layer-3, rgba(128,128,128,0.06))",
|
|
3129
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.15))",
|
|
3130
|
+
borderRadius: "12px",
|
|
3131
|
+
padding: "18px 20px",
|
|
3132
|
+
display: "flex",
|
|
3133
|
+
flexDirection: "column",
|
|
3134
|
+
gap: "14px"
|
|
3135
|
+
},
|
|
3136
|
+
children: [
|
|
3137
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "10px", flexWrap: "wrap" }, children: [
|
|
3138
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
3139
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "16px" }, children: "\u{1F3A8}" }),
|
|
3140
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "15px", fontWeight: "600", color: "var(--dsw-alias-label-primary, inherit)" }, children: t("stylesCardTitle", lang) })
|
|
3141
|
+
] }),
|
|
3142
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: resetAll, style: miniBtnStyle, children: t("stylesResetAll", lang) })
|
|
3143
|
+
] }),
|
|
3144
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "12px", color: "var(--dsw-alias-label-tertiary, #888)", lineHeight: "1.5" }, children: t("stylesCardDesc", lang) }),
|
|
3145
|
+
feedback && typeof showToast !== "function" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3146
|
+
"div",
|
|
3147
|
+
{
|
|
3148
|
+
style: {
|
|
3149
|
+
fontSize: "12px",
|
|
3150
|
+
padding: "8px 12px",
|
|
3151
|
+
borderRadius: "8px",
|
|
3152
|
+
background: "rgba(16,185,129,0.12)",
|
|
3153
|
+
color: "var(--dsw-alias-success, #10b981)",
|
|
3154
|
+
border: "1px solid rgba(16,185,129,0.25)"
|
|
3155
|
+
},
|
|
3156
|
+
children: feedback
|
|
3157
|
+
}
|
|
3158
|
+
) : null,
|
|
3159
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime8.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_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3160
|
+
snippets.some((s) => s.builtin) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3161
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "13px", fontWeight: "600", color: "var(--dsw-alias-label-secondary, inherit)" }, children: t("stylesPresetsTitle", lang) }),
|
|
3162
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: snippets.filter((s) => s.builtin).map((s) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: rowStyle, children: [
|
|
3163
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { flex: 1, minWidth: "180px" }, children: [
|
|
3165
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
|
|
3166
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "12px", fontWeight: "600", color: "var(--dsw-alias-label-primary, inherit)" }, children: s.name }),
|
|
3167
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3168
|
+
"span",
|
|
3169
|
+
{
|
|
3170
|
+
style: {
|
|
3171
|
+
fontSize: "10px",
|
|
3172
|
+
padding: "1px 6px",
|
|
3173
|
+
borderRadius: "8px",
|
|
3174
|
+
background: "rgba(139,92,246,0.15)",
|
|
3175
|
+
color: "#8b5cf6",
|
|
3176
|
+
fontWeight: "600"
|
|
3177
|
+
},
|
|
3178
|
+
children: "Preset"
|
|
3179
|
+
}
|
|
3180
|
+
),
|
|
3181
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3182
|
+
"span",
|
|
3183
|
+
{
|
|
3184
|
+
style: {
|
|
3185
|
+
fontSize: "10px",
|
|
3186
|
+
padding: "1px 6px",
|
|
3187
|
+
borderRadius: "8px",
|
|
3188
|
+
background: "rgba(59,130,246,0.12)",
|
|
3189
|
+
color: "#3b82f6",
|
|
3190
|
+
fontWeight: "600"
|
|
3191
|
+
},
|
|
3192
|
+
children: scopeBadge(s)
|
|
3193
|
+
}
|
|
3194
|
+
)
|
|
3195
|
+
] }),
|
|
3196
|
+
s.description ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #888)", marginTop: "3px" }, children: s.description }) : null
|
|
3197
|
+
] }),
|
|
3198
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px", flexShrink: 0, flexWrap: "wrap" }, children: [
|
|
3199
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer" }, children: [
|
|
3200
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3201
|
+
"input",
|
|
3202
|
+
{
|
|
3203
|
+
type: "checkbox",
|
|
3204
|
+
checked: s.pcEnabled,
|
|
3205
|
+
onChange: (e) => toggle(s.id, "pc", e.target.checked),
|
|
3206
|
+
style: { accentColor: "#3b82f6", width: "16px", height: "16px", cursor: "pointer" }
|
|
3207
|
+
}
|
|
3208
|
+
),
|
|
3209
|
+
"\u{1F5A5}\uFE0F ",
|
|
3210
|
+
t("stylesPcShort", lang)
|
|
3211
|
+
] }),
|
|
3212
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer" }, children: [
|
|
3213
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3214
|
+
"input",
|
|
3215
|
+
{
|
|
3216
|
+
type: "checkbox",
|
|
3217
|
+
checked: s.mobileEnabled,
|
|
3218
|
+
onChange: (e) => toggle(s.id, "mobile", e.target.checked),
|
|
3219
|
+
style: { accentColor: "#3b82f6", width: "16px", height: "16px", cursor: "pointer" }
|
|
3220
|
+
}
|
|
3221
|
+
),
|
|
3222
|
+
"\u{1F4F1} ",
|
|
3223
|
+
t("stylesMobileShort", lang)
|
|
3224
|
+
] }),
|
|
3225
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: () => toggleExpand(s.id), style: miniBtnStyle, children: expanded[s.id] ? t("stylesHideCss", lang) : t("stylesViewCss", lang) })
|
|
3226
|
+
] })
|
|
3227
|
+
] }),
|
|
3228
|
+
expanded[s.id] ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3229
|
+
"pre",
|
|
3230
|
+
{
|
|
3231
|
+
style: {
|
|
3232
|
+
maxHeight: "180px",
|
|
3233
|
+
overflow: "auto",
|
|
3234
|
+
fontSize: "11px",
|
|
3235
|
+
lineHeight: "1.5",
|
|
3236
|
+
margin: 0,
|
|
3237
|
+
padding: "8px 10px",
|
|
3238
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.25))",
|
|
3239
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.15))",
|
|
3240
|
+
borderRadius: "6px",
|
|
3241
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
3242
|
+
whiteSpace: "pre-wrap",
|
|
3243
|
+
wordBreak: "break-word",
|
|
3244
|
+
fontFamily: "var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, monospace)"
|
|
3245
|
+
},
|
|
3246
|
+
children: s.css
|
|
3247
|
+
}
|
|
3248
|
+
) : null
|
|
3249
|
+
] }, s.id)) })
|
|
3250
|
+
] }) : null,
|
|
3251
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "13px", fontWeight: "600", color: "var(--dsw-alias-label-secondary, inherit)", marginTop: "4px" }, children: t("stylesCustomTitle", lang) }),
|
|
3252
|
+
!showForm ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3253
|
+
"button",
|
|
3254
|
+
{
|
|
3255
|
+
type: "button",
|
|
3256
|
+
onClick: () => setShowForm(true),
|
|
3257
|
+
style: {
|
|
3258
|
+
width: "100%",
|
|
3259
|
+
padding: "12px",
|
|
3260
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(128,128,128,0.06))",
|
|
3261
|
+
border: "1px dashed var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
3262
|
+
borderRadius: "8px",
|
|
3263
|
+
color: "var(--dsw-alias-brand-primary, #3b82f6)",
|
|
3264
|
+
fontSize: "12px",
|
|
3265
|
+
fontWeight: "600",
|
|
3266
|
+
cursor: "pointer"
|
|
3267
|
+
},
|
|
3268
|
+
children: t("stylesAddNew", lang)
|
|
3269
|
+
}
|
|
3270
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3271
|
+
"div",
|
|
3272
|
+
{
|
|
3273
|
+
style: {
|
|
3274
|
+
display: "flex",
|
|
3275
|
+
flexDirection: "column",
|
|
3276
|
+
gap: "8px",
|
|
3277
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(128,128,128,0.06))",
|
|
3278
|
+
border: "1px dashed var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
3279
|
+
borderRadius: "8px",
|
|
3280
|
+
padding: "12px"
|
|
3281
|
+
},
|
|
3282
|
+
children: [
|
|
3283
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3284
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3285
|
+
"input",
|
|
3286
|
+
{
|
|
3287
|
+
type: "text",
|
|
3288
|
+
value: name,
|
|
3289
|
+
onChange: (e) => setName(e.target.value),
|
|
3290
|
+
placeholder: t("stylesNamePlaceholder", lang),
|
|
3291
|
+
style: {
|
|
3292
|
+
flex: 1,
|
|
3293
|
+
minWidth: "160px",
|
|
3294
|
+
padding: "8px 10px",
|
|
3295
|
+
fontSize: "12px",
|
|
3296
|
+
borderRadius: "6px",
|
|
3297
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
3298
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.2))",
|
|
3299
|
+
color: "var(--dsw-alias-label-primary, inherit)",
|
|
3300
|
+
outline: "none"
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
),
|
|
3304
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
3305
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3306
|
+
"input",
|
|
3307
|
+
{
|
|
3308
|
+
type: "checkbox",
|
|
3309
|
+
checked: pcEnabled,
|
|
3310
|
+
onChange: (e) => setPcEnabled(e.target.checked),
|
|
3311
|
+
style: { accentColor: "#3b82f6", width: "16px", height: "16px", cursor: "pointer" }
|
|
3312
|
+
}
|
|
3313
|
+
),
|
|
3314
|
+
"\u{1F5A5}\uFE0F ",
|
|
3315
|
+
t("stylesPcShort", lang)
|
|
3316
|
+
] }),
|
|
3317
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer", whiteSpace: "nowrap" }, children: [
|
|
3318
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3319
|
+
"input",
|
|
3320
|
+
{
|
|
3321
|
+
type: "checkbox",
|
|
3322
|
+
checked: mobileEnabled,
|
|
3323
|
+
onChange: (e) => setMobileEnabled(e.target.checked),
|
|
3324
|
+
style: { accentColor: "#3b82f6", width: "16px", height: "16px", cursor: "pointer" }
|
|
3325
|
+
}
|
|
3326
|
+
),
|
|
3327
|
+
"\u{1F4F1} ",
|
|
3328
|
+
t("stylesMobileShort", lang)
|
|
3329
|
+
] })
|
|
3330
|
+
] }),
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3332
|
+
"textarea",
|
|
3333
|
+
{
|
|
3334
|
+
value: css,
|
|
3335
|
+
onChange: (e) => setCss(e.target.value),
|
|
3336
|
+
placeholder: t("stylesCssPlaceholder", lang),
|
|
3337
|
+
rows: 5,
|
|
3338
|
+
style: {
|
|
3339
|
+
width: "100%",
|
|
3340
|
+
boxSizing: "border-box",
|
|
3341
|
+
padding: "8px 10px",
|
|
3342
|
+
fontSize: "12px",
|
|
3343
|
+
lineHeight: "1.5",
|
|
3344
|
+
borderRadius: "6px",
|
|
3345
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))",
|
|
3346
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.2))",
|
|
3347
|
+
color: "var(--dsw-alias-label-primary, inherit)",
|
|
3348
|
+
fontFamily: "var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, monospace)",
|
|
3349
|
+
outline: "none",
|
|
3350
|
+
resize: "vertical"
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
),
|
|
3354
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3355
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: save, style: primaryBtnStyle, children: t("stylesSave", lang) }),
|
|
3356
|
+
editingId !== null ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: cancelEdit, style: miniBtnStyle, children: t("stylesCancelEdit", lang) }) : null,
|
|
3357
|
+
showForm && !editingId ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: cancelEdit, style: miniBtnStyle, children: t("stylesCancelEdit", lang) }) : null
|
|
3358
|
+
] })
|
|
3359
|
+
]
|
|
3360
|
+
}
|
|
3361
|
+
),
|
|
3362
|
+
snippets.filter((s) => !s.builtin).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "12px", color: "var(--dsw-alias-label-tertiary, #888)" }, children: t("stylesEmptyCustom", lang) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: snippets.filter((s) => !s.builtin).map((s) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: rowStyle, children: [
|
|
3363
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3364
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { flex: 1, minWidth: "180px" }, children: [
|
|
3365
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
|
|
3366
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "12px", fontWeight: "600", color: "var(--dsw-alias-label-primary, inherit)" }, children: s.name }),
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3368
|
+
"span",
|
|
3369
|
+
{
|
|
3370
|
+
style: {
|
|
3371
|
+
fontSize: "10px",
|
|
3372
|
+
padding: "1px 6px",
|
|
3373
|
+
borderRadius: "8px",
|
|
3374
|
+
background: "rgba(59,130,246,0.12)",
|
|
3375
|
+
color: "#3b82f6",
|
|
3376
|
+
fontWeight: "600"
|
|
3377
|
+
},
|
|
3378
|
+
children: scopeBadge(s)
|
|
3379
|
+
}
|
|
3380
|
+
)
|
|
3381
|
+
] }),
|
|
3382
|
+
s.description ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #888)", marginTop: "3px" }, children: s.description }) : null
|
|
3383
|
+
] }),
|
|
3384
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px", flexShrink: 0, flexWrap: "wrap" }, children: [
|
|
3385
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer" }, children: [
|
|
3386
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3387
|
+
"input",
|
|
3388
|
+
{
|
|
3389
|
+
type: "checkbox",
|
|
3390
|
+
checked: s.pcEnabled,
|
|
3391
|
+
onChange: (e) => toggle(s.id, "pc", e.target.checked),
|
|
3392
|
+
style: { accentColor: "#3b82f6", width: "16px", height: "16px", cursor: "pointer" }
|
|
3393
|
+
}
|
|
3394
|
+
),
|
|
3395
|
+
"\u{1F5A5}\uFE0F ",
|
|
3396
|
+
t("stylesPcShort", lang)
|
|
3397
|
+
] }),
|
|
3398
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: "4px", fontSize: "11px", cursor: "pointer" }, children: [
|
|
3399
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3400
|
+
"input",
|
|
3401
|
+
{
|
|
3402
|
+
type: "checkbox",
|
|
3403
|
+
checked: s.mobileEnabled,
|
|
3404
|
+
onChange: (e) => toggle(s.id, "mobile", e.target.checked),
|
|
3405
|
+
style: { accentColor: "#3b82f6", width: "16px", height: "16px", cursor: "pointer" }
|
|
3406
|
+
}
|
|
3407
|
+
),
|
|
3408
|
+
"\u{1F4F1} ",
|
|
3409
|
+
t("stylesMobileShort", lang)
|
|
3410
|
+
] }),
|
|
3411
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: () => startEdit(s), style: miniBtnStyle, children: t("stylesEditBtn", lang) }),
|
|
3412
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: () => remove(s), style: { ...miniBtnStyle, color: "#ef4444" }, children: t("stylesDeleteBtn", lang) }),
|
|
3413
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: () => toggleExpand(s.id), style: miniBtnStyle, children: expanded[s.id] ? t("stylesHideCss", lang) : t("stylesViewCss", lang) })
|
|
3414
|
+
] })
|
|
3415
|
+
] }),
|
|
3416
|
+
expanded[s.id] ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3417
|
+
"pre",
|
|
3418
|
+
{
|
|
3419
|
+
style: {
|
|
3420
|
+
maxHeight: "180px",
|
|
3421
|
+
overflow: "auto",
|
|
3422
|
+
fontSize: "11px",
|
|
3423
|
+
lineHeight: "1.5",
|
|
3424
|
+
margin: 0,
|
|
3425
|
+
padding: "8px 10px",
|
|
3426
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.25))",
|
|
3427
|
+
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.15))",
|
|
3428
|
+
borderRadius: "6px",
|
|
3429
|
+
color: "var(--dsw-alias-label-secondary, inherit)",
|
|
3430
|
+
whiteSpace: "pre-wrap",
|
|
3431
|
+
wordBreak: "break-word",
|
|
3432
|
+
fontFamily: "var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, monospace)"
|
|
3433
|
+
},
|
|
3434
|
+
children: s.css
|
|
3435
|
+
}
|
|
3436
|
+
) : null
|
|
3437
|
+
] }, s.id)) }),
|
|
3438
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #888)", lineHeight: "1.6" }, children: t("stylesHint", lang) })
|
|
3439
|
+
] })
|
|
3440
|
+
]
|
|
3441
|
+
}
|
|
3442
|
+
);
|
|
3443
|
+
}
|
|
3444
|
+
|
|
2893
3445
|
// src/client/version.js
|
|
2894
|
-
var PLUGIN_VERSION = "v1.
|
|
2895
|
-
var BUILD_TIME = "2026-08-23
|
|
3446
|
+
var PLUGIN_VERSION = "v1.4.0";
|
|
3447
|
+
var BUILD_TIME = "2026-08-24 23:56:32";
|
|
2896
3448
|
|
|
2897
3449
|
// src/client/components/MainSection.jsx
|
|
2898
|
-
var
|
|
3450
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2899
3451
|
function TailscaleMobileSection(props) {
|
|
2900
3452
|
const ctx = props && props.ctx || typeof window !== "undefined" && window.__DSH_CLIENT_CTX__ || null;
|
|
2901
|
-
const [status, setStatus] = (0,
|
|
3453
|
+
const [status, setStatus] = (0, import_react9.useState)({
|
|
2902
3454
|
tailscaleIp: "",
|
|
2903
3455
|
lanIp: "",
|
|
2904
3456
|
code: "",
|
|
@@ -2915,24 +3467,50 @@ function TailscaleMobileSection(props) {
|
|
|
2915
3467
|
copied: false,
|
|
2916
3468
|
loading: true,
|
|
2917
3469
|
persistPath: "",
|
|
2918
|
-
|
|
3470
|
+
rsaKeyPath: "",
|
|
3471
|
+
styleSnippetsPath: "",
|
|
3472
|
+
locale: "zh",
|
|
3473
|
+
pairingBridgeMode: "pending",
|
|
3474
|
+
pairingBridgeConflict: "",
|
|
3475
|
+
pairingBridgeConflictId: ""
|
|
2919
3476
|
});
|
|
2920
|
-
const [secretInput, setSecretInput] = (0,
|
|
2921
|
-
const [showSecret, setShowSecret] = (0,
|
|
2922
|
-
const [showCode, setShowCode] = (0,
|
|
2923
|
-
const [showQr, setShowQr] = (0,
|
|
2924
|
-
const [selectedTab, setSelectedTab] = (0,
|
|
2925
|
-
const [timeLeft, setTimeLeft] = (0,
|
|
2926
|
-
const [toast, setToast] = (0,
|
|
2927
|
-
const [maxVisitsInput, setMaxVisitsInput] = (0,
|
|
2928
|
-
const [maxFailedInput, setMaxFailedInput] = (0,
|
|
2929
|
-
const [lockDurationMinsInput, setLockDurationMinsInput] = (0,
|
|
2930
|
-
const [isSaving, setIsSaving] = (0,
|
|
2931
|
-
const [showVersionTip, setShowVersionTip] = (0,
|
|
2932
|
-
const [currentLang, setCurrentLang] = (0,
|
|
2933
|
-
const
|
|
3477
|
+
const [secretInput, setSecretInput] = (0, import_react9.useState)("");
|
|
3478
|
+
const [showSecret, setShowSecret] = (0, import_react9.useState)(false);
|
|
3479
|
+
const [showCode, setShowCode] = (0, import_react9.useState)(false);
|
|
3480
|
+
const [showQr, setShowQr] = (0, import_react9.useState)(false);
|
|
3481
|
+
const [selectedTab, setSelectedTab] = (0, import_react9.useState)("lan");
|
|
3482
|
+
const [timeLeft, setTimeLeft] = (0, import_react9.useState)(300);
|
|
3483
|
+
const [toast, setToast] = (0, import_react9.useState)(null);
|
|
3484
|
+
const [maxVisitsInput, setMaxVisitsInput] = (0, import_react9.useState)("60");
|
|
3485
|
+
const [maxFailedInput, setMaxFailedInput] = (0, import_react9.useState)("5");
|
|
3486
|
+
const [lockDurationMinsInput, setLockDurationMinsInput] = (0, import_react9.useState)("15");
|
|
3487
|
+
const [isSaving, setIsSaving] = (0, import_react9.useState)(false);
|
|
3488
|
+
const [showVersionTip, setShowVersionTip] = (0, import_react9.useState)(false);
|
|
3489
|
+
const [currentLang, setCurrentLang] = (0, import_react9.useState)(resolveLocale(ctx, status));
|
|
3490
|
+
const [conflictBannerDismissed, setConflictBannerDismissed] = (0, import_react9.useState)(false);
|
|
3491
|
+
const qrTabTouchedRef = (0, import_react9.useRef)(false);
|
|
3492
|
+
const updateQrTab = (0, import_react9.useCallback)((tab) => {
|
|
3493
|
+
qrTabTouchedRef.current = true;
|
|
3494
|
+
setSelectedTab(tab);
|
|
3495
|
+
}, []);
|
|
3496
|
+
const [activeTab, setActiveTab] = (0, import_react9.useState)(() => {
|
|
3497
|
+
try {
|
|
3498
|
+
const saved = localStorage.getItem("dsh-rm-settings-tab");
|
|
3499
|
+
if (saved === "access" || saved === "devices" || saved === "style" || saved === "storage") return saved;
|
|
3500
|
+
} catch (e) {
|
|
3501
|
+
}
|
|
3502
|
+
return "access";
|
|
3503
|
+
});
|
|
3504
|
+
const switchTab = (tab) => {
|
|
3505
|
+
setActiveTab(tab);
|
|
3506
|
+
try {
|
|
3507
|
+
localStorage.setItem("dsh-rm-settings-tab", tab);
|
|
3508
|
+
} catch (e) {
|
|
3509
|
+
}
|
|
3510
|
+
};
|
|
3511
|
+
const refreshStatusOnly = (0, import_react9.useCallback)(() => {
|
|
2934
3512
|
fetchStatus().then((data) => {
|
|
2935
|
-
if (data.tailscaleIp) {
|
|
3513
|
+
if (data.tailscaleIp && !qrTabTouchedRef.current) {
|
|
2936
3514
|
setSelectedTab("tailscale");
|
|
2937
3515
|
}
|
|
2938
3516
|
if (data.maxVisitsPerMinute) setMaxVisitsInput(String(data.maxVisitsPerMinute));
|
|
@@ -2957,13 +3535,17 @@ function TailscaleMobileSection(props) {
|
|
|
2957
3535
|
ipSecurityStats: data.ipSecurityStats || [],
|
|
2958
3536
|
persistPath: data.persistPath || "",
|
|
2959
3537
|
rsaKeyPath: data.rsaKeyPath || "",
|
|
3538
|
+
styleSnippetsPath: data.styleSnippetsPath || "",
|
|
2960
3539
|
locale: data.locale || "zh",
|
|
3540
|
+
pairingBridgeMode: data.pairingBridgeMode || "pending",
|
|
3541
|
+
pairingBridgeConflict: data.pairingBridgeConflict || "",
|
|
3542
|
+
pairingBridgeConflictId: data.pairingBridgeConflictId || "",
|
|
2961
3543
|
loading: false
|
|
2962
3544
|
}));
|
|
2963
3545
|
}).catch(() => {
|
|
2964
3546
|
});
|
|
2965
3547
|
}, [ctx]);
|
|
2966
|
-
const refreshStatusAndCode = (0,
|
|
3548
|
+
const refreshStatusAndCode = (0, import_react9.useCallback)(() => {
|
|
2967
3549
|
refreshStatusOnly();
|
|
2968
3550
|
generatePairCode().then((data) => {
|
|
2969
3551
|
if (data.success) {
|
|
@@ -2978,7 +3560,7 @@ function TailscaleMobileSection(props) {
|
|
|
2978
3560
|
}).catch(() => {
|
|
2979
3561
|
});
|
|
2980
3562
|
}, [refreshStatusOnly]);
|
|
2981
|
-
(0,
|
|
3563
|
+
(0, import_react9.useEffect)(() => {
|
|
2982
3564
|
refreshStatusAndCode();
|
|
2983
3565
|
const localeUnsubs = [];
|
|
2984
3566
|
try {
|
|
@@ -3015,8 +3597,7 @@ function TailscaleMobileSection(props) {
|
|
|
3015
3597
|
name: dev.deviceName || "Device",
|
|
3016
3598
|
ip: dev.ip
|
|
3017
3599
|
});
|
|
3018
|
-
|
|
3019
|
-
setTimeout(() => setToast(null), 4e3);
|
|
3600
|
+
showToast(msg, "info", 4e3);
|
|
3020
3601
|
}
|
|
3021
3602
|
if (detail.type === "device-revoked") {
|
|
3022
3603
|
setStatus((prev) => {
|
|
@@ -3031,8 +3612,7 @@ function TailscaleMobileSection(props) {
|
|
|
3031
3612
|
}
|
|
3032
3613
|
if (detail.type === "ip-security-alert") {
|
|
3033
3614
|
const alertMsg = t("toastIpLocked", currentLang, { ip: detail.ip });
|
|
3034
|
-
|
|
3035
|
-
setTimeout(() => setToast(null), 5e3);
|
|
3615
|
+
showToast(alertMsg, "danger", 5e3);
|
|
3036
3616
|
}
|
|
3037
3617
|
refreshStatusOnly();
|
|
3038
3618
|
};
|
|
@@ -3048,7 +3628,7 @@ function TailscaleMobileSection(props) {
|
|
|
3048
3628
|
}
|
|
3049
3629
|
};
|
|
3050
3630
|
}, [refreshStatusAndCode, refreshStatusOnly, currentLang, ctx]);
|
|
3051
|
-
(0,
|
|
3631
|
+
(0, import_react9.useEffect)(() => {
|
|
3052
3632
|
if (timeLeft <= 0) return;
|
|
3053
3633
|
const timer = setInterval(() => {
|
|
3054
3634
|
setTimeLeft((prev) => {
|
|
@@ -3093,11 +3673,11 @@ function TailscaleMobileSection(props) {
|
|
|
3093
3673
|
if (data.success) {
|
|
3094
3674
|
setStatus((prev) => ({ ...prev, hasSecret: true }));
|
|
3095
3675
|
setSecretInput("");
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3676
|
+
showToast(
|
|
3677
|
+
currentLang === "en" ? "Persistent password saved!" : "\u957F\u671F\u8BBF\u95EE\u5BC6\u7801\u5DF2\u6210\u529F\u4FDD\u5B58\u5E76\u542F\u7528\uFF01",
|
|
3678
|
+
"success",
|
|
3679
|
+
3e3
|
|
3680
|
+
);
|
|
3101
3681
|
} else {
|
|
3102
3682
|
alert((currentLang === "en" ? "Save failed: " : "\u4FDD\u5B58\u5931\u8D25\uFF1A") + (data.reason || ""));
|
|
3103
3683
|
}
|
|
@@ -3108,11 +3688,11 @@ function TailscaleMobileSection(props) {
|
|
|
3108
3688
|
clearSecretApi().then(() => {
|
|
3109
3689
|
setStatus((prev) => ({ ...prev, hasSecret: false }));
|
|
3110
3690
|
setSecretInput("");
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3691
|
+
showToast(
|
|
3692
|
+
currentLang === "en" ? "Password cleared!" : "\u5DF2\u6210\u529F\u6E05\u9664\u957F\u671F\u8BBF\u95EE\u5BC6\u7801\uFF01",
|
|
3693
|
+
"info",
|
|
3694
|
+
3e3
|
|
3695
|
+
);
|
|
3116
3696
|
});
|
|
3117
3697
|
}
|
|
3118
3698
|
};
|
|
@@ -3120,11 +3700,11 @@ function TailscaleMobileSection(props) {
|
|
|
3120
3700
|
if (confirm(t("revokeDeviceConfirm", currentLang))) {
|
|
3121
3701
|
revokeDeviceApi(token).then(() => {
|
|
3122
3702
|
refreshStatusAndCode();
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3703
|
+
showToast(
|
|
3704
|
+
currentLang === "en" ? "Device disconnected!" : "\u5DF2\u6210\u529F\u8E22\u51FA\u8BE5\u8BBE\u5907\uFF01",
|
|
3705
|
+
"info",
|
|
3706
|
+
2500
|
|
3707
|
+
);
|
|
3128
3708
|
});
|
|
3129
3709
|
}
|
|
3130
3710
|
};
|
|
@@ -3132,11 +3712,11 @@ function TailscaleMobileSection(props) {
|
|
|
3132
3712
|
if (confirm(t("revokeAllConfirm", currentLang))) {
|
|
3133
3713
|
revokeAllDevicesApi().then(() => {
|
|
3134
3714
|
refreshStatusAndCode();
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3715
|
+
showToast(
|
|
3716
|
+
currentLang === "en" ? "All devices disconnected!" : "\u5DF2\u6210\u529F\u6CE8\u9500\u5E76\u8E22\u4E0B\u7EBF\u6240\u6709\u8BBE\u5907\uFF01",
|
|
3717
|
+
"info",
|
|
3718
|
+
2500
|
|
3719
|
+
);
|
|
3140
3720
|
});
|
|
3141
3721
|
}
|
|
3142
3722
|
};
|
|
@@ -3144,11 +3724,11 @@ function TailscaleMobileSection(props) {
|
|
|
3144
3724
|
if (confirm(t("unlockIpConfirm", currentLang, { ip }))) {
|
|
3145
3725
|
unlockIpApi(ip).then(() => {
|
|
3146
3726
|
refreshStatusAndCode();
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3727
|
+
showToast(
|
|
3728
|
+
currentLang === "en" ? `IP ${ip} unlocked!` : `\u5DF2\u6210\u529F\u4E3A IP ${ip} \u89E3\u9664\u9501\u5B9A\uFF01`,
|
|
3729
|
+
"success",
|
|
3730
|
+
3e3
|
|
3731
|
+
);
|
|
3152
3732
|
}).catch(() => {
|
|
3153
3733
|
});
|
|
3154
3734
|
}
|
|
@@ -3157,11 +3737,11 @@ function TailscaleMobileSection(props) {
|
|
|
3157
3737
|
if (confirm(t("clearSecurityLogConfirm", currentLang))) {
|
|
3158
3738
|
clearIpStatsApi().then(() => {
|
|
3159
3739
|
refreshStatusAndCode();
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3740
|
+
showToast(
|
|
3741
|
+
currentLang === "en" ? "Audit logs cleared!" : "\u5DF2\u6210\u529F\u6E05\u7A7A\u6240\u6709\u5B89\u5168\u5BA1\u8BA1\u65E5\u5FD7\uFF01",
|
|
3742
|
+
"success",
|
|
3743
|
+
2500
|
|
3744
|
+
);
|
|
3165
3745
|
}).catch(() => {
|
|
3166
3746
|
});
|
|
3167
3747
|
}
|
|
@@ -3186,8 +3766,7 @@ function TailscaleMobileSection(props) {
|
|
|
3186
3766
|
setIsSaving(false);
|
|
3187
3767
|
if (data.success) {
|
|
3188
3768
|
refreshStatusAndCode();
|
|
3189
|
-
|
|
3190
|
-
setTimeout(() => setToast(null), 3e3);
|
|
3769
|
+
showToast(t("saveConfigSuccessToast", currentLang), "success", 3e3);
|
|
3191
3770
|
} else {
|
|
3192
3771
|
alert((currentLang === "en" ? "Save failed: " : "\u4FDD\u5B58\u5931\u8D25\uFF1A") + (data.reason || ""));
|
|
3193
3772
|
}
|
|
@@ -3212,8 +3791,7 @@ function TailscaleMobileSection(props) {
|
|
|
3212
3791
|
setIsSaving(false);
|
|
3213
3792
|
if (data.success) {
|
|
3214
3793
|
refreshStatusAndCode();
|
|
3215
|
-
|
|
3216
|
-
setTimeout(() => setToast(null), 3e3);
|
|
3794
|
+
showToast(t("restoreDefaultsSuccessToast", currentLang), "success", 3e3);
|
|
3217
3795
|
} else {
|
|
3218
3796
|
alert((currentLang === "en" ? "Reset failed: " : "\u91CD\u7F6E\u5931\u8D25\uFF1A") + (data.reason || ""));
|
|
3219
3797
|
}
|
|
@@ -3230,23 +3808,57 @@ function TailscaleMobileSection(props) {
|
|
|
3230
3808
|
const effectiveQrIp = selectedTab === "tailscale" && status.tailscaleIp ? status.tailscaleIp : status.lanIp || "127.0.0.1";
|
|
3231
3809
|
const port = typeof window !== "undefined" && window.location.port || "3080";
|
|
3232
3810
|
const directLink = `http://${effectiveQrIp}:${port}/auth?token=${status.code || ""}`;
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
});
|
|
3811
|
+
copyText(directLink, t("copiedTip", currentLang));
|
|
3812
|
+
setStatus((prev) => ({ ...prev, copied: true }));
|
|
3813
|
+
setTimeout(() => {
|
|
3814
|
+
setStatus((prev) => ({ ...prev, copied: false }));
|
|
3815
|
+
}, 2e3);
|
|
3239
3816
|
};
|
|
3817
|
+
const toastTimerRef = (0, import_react9.useRef)(null);
|
|
3818
|
+
const showToast = (0, import_react9.useCallback)((message, type = "success", duration = 2500) => {
|
|
3819
|
+
if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
|
|
3820
|
+
setToast({ message, type });
|
|
3821
|
+
toastTimerRef.current = setTimeout(() => setToast(null), duration);
|
|
3822
|
+
}, []);
|
|
3240
3823
|
const copyText = (text, successTip) => {
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3824
|
+
const triggerToast = () => {
|
|
3825
|
+
showToast(
|
|
3826
|
+
successTip || (currentLang === "en" ? "Copied to clipboard!" : "\u5DF2\u6210\u529F\u590D\u5236\u5230\u526A\u8D34\u677F\uFF01"),
|
|
3827
|
+
"success",
|
|
3828
|
+
2500
|
|
3829
|
+
);
|
|
3830
|
+
};
|
|
3831
|
+
if (typeof navigator !== "undefined" && navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
|
3832
|
+
navigator.clipboard.writeText(text).then(triggerToast).catch(() => {
|
|
3833
|
+
try {
|
|
3834
|
+
const ta = document.createElement("textarea");
|
|
3835
|
+
ta.value = text;
|
|
3836
|
+
ta.style.position = "fixed";
|
|
3837
|
+
ta.style.opacity = "0";
|
|
3838
|
+
document.body.appendChild(ta);
|
|
3839
|
+
ta.select();
|
|
3840
|
+
document.execCommand("copy");
|
|
3841
|
+
document.body.removeChild(ta);
|
|
3842
|
+
triggerToast();
|
|
3843
|
+
} catch (e) {
|
|
3844
|
+
}
|
|
3245
3845
|
});
|
|
3246
|
-
|
|
3247
|
-
|
|
3846
|
+
} else {
|
|
3847
|
+
try {
|
|
3848
|
+
const ta = document.createElement("textarea");
|
|
3849
|
+
ta.value = text;
|
|
3850
|
+
ta.style.position = "fixed";
|
|
3851
|
+
ta.style.opacity = "0";
|
|
3852
|
+
document.body.appendChild(ta);
|
|
3853
|
+
ta.select();
|
|
3854
|
+
document.execCommand("copy");
|
|
3855
|
+
document.body.removeChild(ta);
|
|
3856
|
+
triggerToast();
|
|
3857
|
+
} catch (e) {
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3248
3860
|
};
|
|
3249
|
-
return /* @__PURE__ */ (0,
|
|
3861
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3250
3862
|
"div",
|
|
3251
3863
|
{
|
|
3252
3864
|
style: {
|
|
@@ -3254,10 +3866,41 @@ function TailscaleMobileSection(props) {
|
|
|
3254
3866
|
color: "var(--dsw-alias-label-primary, inherit)",
|
|
3255
3867
|
display: "flex",
|
|
3256
3868
|
flexDirection: "column",
|
|
3257
|
-
gap: "16px"
|
|
3869
|
+
gap: "16px",
|
|
3870
|
+
position: "relative"
|
|
3258
3871
|
},
|
|
3259
3872
|
children: [
|
|
3260
|
-
/* @__PURE__ */ (0,
|
|
3873
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3874
|
+
"div",
|
|
3875
|
+
{
|
|
3876
|
+
style: {
|
|
3877
|
+
position: "fixed",
|
|
3878
|
+
top: "24px",
|
|
3879
|
+
left: "50%",
|
|
3880
|
+
transform: "translateX(-50%)",
|
|
3881
|
+
zIndex: 100010,
|
|
3882
|
+
background: toast.type === "danger" ? "linear-gradient(135deg, rgba(239, 68, 68, 0.95), rgba(185, 28, 28, 0.95))" : toast.type === "success" ? "linear-gradient(135deg, rgba(16, 185, 129, 0.95), rgba(5, 150, 105, 0.95))" : "linear-gradient(135deg, rgba(59, 130, 246, 0.95), rgba(37, 99, 235, 0.95))",
|
|
3883
|
+
color: "#ffffff",
|
|
3884
|
+
borderRadius: "10px",
|
|
3885
|
+
padding: "10px 18px",
|
|
3886
|
+
fontSize: "13px",
|
|
3887
|
+
fontWeight: "600",
|
|
3888
|
+
boxShadow: "0 12px 30px rgba(0, 0, 0, 0.35)",
|
|
3889
|
+
backdropFilter: "blur(10px)",
|
|
3890
|
+
WebkitBackdropFilter: "blur(10px)",
|
|
3891
|
+
border: "1px solid rgba(255, 255, 255, 0.25)",
|
|
3892
|
+
display: "flex",
|
|
3893
|
+
alignItems: "center",
|
|
3894
|
+
gap: "8px",
|
|
3895
|
+
pointerEvents: "none"
|
|
3896
|
+
},
|
|
3897
|
+
children: [
|
|
3898
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: toast.type === "danger" ? "\u{1F6A8}" : toast.type === "success" ? "\u2705" : "\u2139\uFE0F" }),
|
|
3899
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: toast.message })
|
|
3900
|
+
]
|
|
3901
|
+
}
|
|
3902
|
+
) : null,
|
|
3903
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3261
3904
|
"div",
|
|
3262
3905
|
{
|
|
3263
3906
|
style: {
|
|
@@ -3269,8 +3912,8 @@ function TailscaleMobileSection(props) {
|
|
|
3269
3912
|
marginBottom: "4px"
|
|
3270
3913
|
},
|
|
3271
3914
|
children: [
|
|
3272
|
-
/* @__PURE__ */ (0,
|
|
3273
|
-
/* @__PURE__ */ (0,
|
|
3915
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { minWidth: "220px", flex: 1 }, children: [
|
|
3916
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3274
3917
|
"div",
|
|
3275
3918
|
{
|
|
3276
3919
|
style: {
|
|
@@ -3281,7 +3924,7 @@ function TailscaleMobileSection(props) {
|
|
|
3281
3924
|
margin: "0 0 6px 0"
|
|
3282
3925
|
},
|
|
3283
3926
|
children: [
|
|
3284
|
-
/* @__PURE__ */ (0,
|
|
3927
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3285
3928
|
"h3",
|
|
3286
3929
|
{
|
|
3287
3930
|
style: {
|
|
@@ -3293,21 +3936,21 @@ function TailscaleMobileSection(props) {
|
|
|
3293
3936
|
children: t("title", currentLang)
|
|
3294
3937
|
}
|
|
3295
3938
|
),
|
|
3296
|
-
/* @__PURE__ */ (0,
|
|
3939
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3297
3940
|
"div",
|
|
3298
3941
|
{
|
|
3299
3942
|
style: { position: "relative", display: "inline-flex", alignItems: "center" },
|
|
3300
3943
|
onMouseEnter: () => setShowVersionTip(true),
|
|
3301
3944
|
onMouseLeave: () => setShowVersionTip(false),
|
|
3302
3945
|
onClick: () => {
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3946
|
+
showToast(
|
|
3947
|
+
`\u{1F4E6} dsh-remote-mobile ${PLUGIN_VERSION} (${currentLang === "en" ? "Build: " : "\u6784\u5EFA\u65F6\u95F4: "}${BUILD_TIME})`,
|
|
3948
|
+
"info",
|
|
3949
|
+
3e3
|
|
3950
|
+
);
|
|
3308
3951
|
},
|
|
3309
3952
|
children: [
|
|
3310
|
-
/* @__PURE__ */ (0,
|
|
3953
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3311
3954
|
"span",
|
|
3312
3955
|
{
|
|
3313
3956
|
style: {
|
|
@@ -3324,7 +3967,7 @@ function TailscaleMobileSection(props) {
|
|
|
3324
3967
|
children: PLUGIN_VERSION
|
|
3325
3968
|
}
|
|
3326
3969
|
),
|
|
3327
|
-
showVersionTip ? /* @__PURE__ */ (0,
|
|
3970
|
+
showVersionTip ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3328
3971
|
"div",
|
|
3329
3972
|
{
|
|
3330
3973
|
style: {
|
|
@@ -3355,7 +3998,7 @@ function TailscaleMobileSection(props) {
|
|
|
3355
3998
|
]
|
|
3356
3999
|
}
|
|
3357
4000
|
),
|
|
3358
|
-
/* @__PURE__ */ (0,
|
|
4001
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3359
4002
|
"div",
|
|
3360
4003
|
{
|
|
3361
4004
|
style: {
|
|
@@ -3366,7 +4009,7 @@ function TailscaleMobileSection(props) {
|
|
|
3366
4009
|
}
|
|
3367
4010
|
)
|
|
3368
4011
|
] }),
|
|
3369
|
-
/* @__PURE__ */ (0,
|
|
4012
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3370
4013
|
"a",
|
|
3371
4014
|
{
|
|
3372
4015
|
href: "https://github.com/IceApriler/dsh-remote-mobile",
|
|
@@ -3388,88 +4031,235 @@ function TailscaleMobileSection(props) {
|
|
|
3388
4031
|
cursor: "pointer"
|
|
3389
4032
|
},
|
|
3390
4033
|
children: [
|
|
3391
|
-
/* @__PURE__ */ (0,
|
|
3392
|
-
/* @__PURE__ */ (0,
|
|
4034
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { style: { width: "16px", height: "16px", fill: "currentColor" }, viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime9.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" }) }),
|
|
4035
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "dsh-remote-mobile" })
|
|
3393
4036
|
]
|
|
3394
4037
|
}
|
|
3395
4038
|
)
|
|
3396
4039
|
]
|
|
3397
4040
|
}
|
|
3398
4041
|
),
|
|
3399
|
-
/* @__PURE__ */ (0,
|
|
3400
|
-
|
|
3401
|
-
{
|
|
3402
|
-
status,
|
|
3403
|
-
toggleTailscale,
|
|
3404
|
-
toggleLan,
|
|
3405
|
-
copyText,
|
|
3406
|
-
lang: currentLang
|
|
3407
|
-
}
|
|
3408
|
-
),
|
|
3409
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3410
|
-
QrPairingCard,
|
|
3411
|
-
{
|
|
3412
|
-
status,
|
|
3413
|
-
showCode,
|
|
3414
|
-
setShowCode,
|
|
3415
|
-
timeLeft,
|
|
3416
|
-
showQr,
|
|
3417
|
-
setShowQr,
|
|
3418
|
-
selectedTab,
|
|
3419
|
-
setSelectedTab,
|
|
3420
|
-
generateQrSvg,
|
|
3421
|
-
refreshStatusAndCode,
|
|
3422
|
-
copyDirectLink,
|
|
3423
|
-
lang: currentLang
|
|
3424
|
-
}
|
|
3425
|
-
),
|
|
3426
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3427
|
-
SecretCard,
|
|
3428
|
-
{
|
|
3429
|
-
status,
|
|
3430
|
-
secretInput,
|
|
3431
|
-
setSecretInput,
|
|
3432
|
-
showSecret,
|
|
3433
|
-
setShowSecret,
|
|
3434
|
-
saveSecret,
|
|
3435
|
-
clearSecret,
|
|
3436
|
-
lang: currentLang
|
|
3437
|
-
}
|
|
3438
|
-
),
|
|
3439
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3440
|
-
DeviceListCard,
|
|
4042
|
+
status.pairingBridgeConflict && !conflictBannerDismissed ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4043
|
+
"div",
|
|
3441
4044
|
{
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
4045
|
+
style: {
|
|
4046
|
+
display: "flex",
|
|
4047
|
+
alignItems: "flex-start",
|
|
4048
|
+
gap: "10px",
|
|
4049
|
+
padding: "12px 14px",
|
|
4050
|
+
borderRadius: "10px",
|
|
4051
|
+
border: "1px solid rgba(245, 158, 11, 0.45)",
|
|
4052
|
+
background: "rgba(245, 158, 11, 0.12)"
|
|
4053
|
+
},
|
|
4054
|
+
children: [
|
|
4055
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "16px", lineHeight: "20px" }, children: "\u26A0\uFE0F" }),
|
|
4056
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
4057
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4058
|
+
"div",
|
|
4059
|
+
{
|
|
4060
|
+
style: {
|
|
4061
|
+
fontSize: "13px",
|
|
4062
|
+
fontWeight: "700",
|
|
4063
|
+
marginBottom: "4px",
|
|
4064
|
+
color: "var(--dsw-alias-label-primary, inherit)"
|
|
4065
|
+
},
|
|
4066
|
+
children: t("conflictBannerTitle", currentLang)
|
|
4067
|
+
}
|
|
4068
|
+
),
|
|
4069
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4070
|
+
"div",
|
|
4071
|
+
{
|
|
4072
|
+
style: {
|
|
4073
|
+
fontSize: "12px",
|
|
4074
|
+
lineHeight: 1.6,
|
|
4075
|
+
whiteSpace: "pre-line",
|
|
4076
|
+
color: "var(--dsw-alias-label-secondary, inherit)"
|
|
4077
|
+
},
|
|
4078
|
+
children: t("conflictBannerBody", currentLang, {
|
|
4079
|
+
plugin: status.pairingBridgeConflict || t("conflictUnknownPlugin", currentLang)
|
|
4080
|
+
})
|
|
4081
|
+
}
|
|
4082
|
+
),
|
|
4083
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4084
|
+
"button",
|
|
4085
|
+
{
|
|
4086
|
+
type: "button",
|
|
4087
|
+
onClick: () => {
|
|
4088
|
+
const plugin = status.pairingBridgeConflict || t("conflictUnknownPlugin", currentLang);
|
|
4089
|
+
const entryId = status.pairingBridgeConflictId || "";
|
|
4090
|
+
const report = t(
|
|
4091
|
+
entryId ? "conflictReportText" : "conflictReportNoEntryIdText",
|
|
4092
|
+
currentLang,
|
|
4093
|
+
{ plugin, entryId }
|
|
4094
|
+
);
|
|
4095
|
+
copyText(report, t("conflictCopiedTip", currentLang));
|
|
4096
|
+
},
|
|
4097
|
+
style: {
|
|
4098
|
+
marginTop: "8px",
|
|
4099
|
+
display: "inline-flex",
|
|
4100
|
+
alignItems: "center",
|
|
4101
|
+
gap: "6px",
|
|
4102
|
+
padding: "5px 10px",
|
|
4103
|
+
fontSize: "12px",
|
|
4104
|
+
fontWeight: "600",
|
|
4105
|
+
borderRadius: "7px",
|
|
4106
|
+
cursor: "pointer",
|
|
4107
|
+
border: "1px solid rgba(245, 158, 11, 0.55)",
|
|
4108
|
+
background: "rgba(245, 158, 11, 0.18)",
|
|
4109
|
+
color: "var(--dsw-alias-label-primary, inherit)"
|
|
4110
|
+
},
|
|
4111
|
+
children: t("conflictCopyBtn", currentLang)
|
|
4112
|
+
}
|
|
4113
|
+
)
|
|
4114
|
+
] }),
|
|
4115
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4116
|
+
"button",
|
|
4117
|
+
{
|
|
4118
|
+
type: "button",
|
|
4119
|
+
onClick: () => setConflictBannerDismissed(true),
|
|
4120
|
+
title: t("conflictBannerDismiss", currentLang),
|
|
4121
|
+
style: {
|
|
4122
|
+
flexShrink: 0,
|
|
4123
|
+
width: "24px",
|
|
4124
|
+
height: "24px",
|
|
4125
|
+
display: "inline-flex",
|
|
4126
|
+
alignItems: "center",
|
|
4127
|
+
justifyContent: "center",
|
|
4128
|
+
border: "none",
|
|
4129
|
+
borderRadius: "6px",
|
|
4130
|
+
cursor: "pointer",
|
|
4131
|
+
fontSize: "12px",
|
|
4132
|
+
background: "rgba(128, 128, 128, 0.15)",
|
|
4133
|
+
color: "var(--dsw-alias-label-secondary, inherit)"
|
|
4134
|
+
},
|
|
4135
|
+
children: "\u2715"
|
|
4136
|
+
}
|
|
4137
|
+
)
|
|
4138
|
+
]
|
|
3446
4139
|
}
|
|
3447
|
-
),
|
|
3448
|
-
/* @__PURE__ */ (0,
|
|
3449
|
-
|
|
4140
|
+
) : null,
|
|
4141
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4142
|
+
"div",
|
|
3450
4143
|
{
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
4144
|
+
style: {
|
|
4145
|
+
display: "flex",
|
|
4146
|
+
gap: "24px",
|
|
4147
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2, rgba(128, 128, 128, 0.2))",
|
|
4148
|
+
paddingBottom: "0",
|
|
4149
|
+
marginBottom: "6px"
|
|
4150
|
+
},
|
|
4151
|
+
children: [
|
|
4152
|
+
{ id: "access", label: t("tabAccess", currentLang) },
|
|
4153
|
+
{ id: "devices", label: t("tabDevices", currentLang) },
|
|
4154
|
+
{ id: "style", label: t("tabStyle", currentLang) },
|
|
4155
|
+
{ id: "storage", label: t("tabStorage", currentLang) }
|
|
4156
|
+
].map((item) => {
|
|
4157
|
+
const isActive = activeTab === item.id;
|
|
4158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4159
|
+
"button",
|
|
4160
|
+
{
|
|
4161
|
+
type: "button",
|
|
4162
|
+
onClick: () => switchTab(item.id),
|
|
4163
|
+
style: {
|
|
4164
|
+
background: "transparent",
|
|
4165
|
+
border: "none",
|
|
4166
|
+
outline: "none",
|
|
4167
|
+
padding: "8px 2px 10px 2px",
|
|
4168
|
+
fontSize: "14px",
|
|
4169
|
+
fontWeight: isActive ? "600" : "400",
|
|
4170
|
+
cursor: "pointer",
|
|
4171
|
+
color: isActive ? "var(--dsw-alias-label-primary, #111827)" : "var(--dsw-alias-label-tertiary, #8c8c8c)",
|
|
4172
|
+
borderBottom: isActive ? "2px solid var(--dsw-alias-label-primary, #111827)" : "2px solid transparent",
|
|
4173
|
+
marginBottom: "-1px",
|
|
4174
|
+
transition: "all 0.2s ease"
|
|
4175
|
+
},
|
|
4176
|
+
children: item.label
|
|
4177
|
+
},
|
|
4178
|
+
item.id
|
|
4179
|
+
);
|
|
4180
|
+
})
|
|
3455
4181
|
}
|
|
3456
4182
|
),
|
|
3457
|
-
/* @__PURE__ */ (0,
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
4183
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: activeTab === "access" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: [
|
|
4184
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4185
|
+
NetworkCard,
|
|
4186
|
+
{
|
|
4187
|
+
status,
|
|
4188
|
+
toggleTailscale,
|
|
4189
|
+
toggleLan,
|
|
4190
|
+
copyText,
|
|
4191
|
+
lang: currentLang
|
|
4192
|
+
}
|
|
4193
|
+
),
|
|
4194
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4195
|
+
QrPairingCard,
|
|
4196
|
+
{
|
|
4197
|
+
status,
|
|
4198
|
+
showCode,
|
|
4199
|
+
setShowCode,
|
|
4200
|
+
timeLeft,
|
|
4201
|
+
showQr,
|
|
4202
|
+
setShowQr,
|
|
4203
|
+
selectedTab,
|
|
4204
|
+
setSelectedTab: updateQrTab,
|
|
4205
|
+
generateQrSvg,
|
|
4206
|
+
refreshStatusAndCode,
|
|
4207
|
+
copyDirectLink,
|
|
4208
|
+
lang: currentLang
|
|
4209
|
+
}
|
|
4210
|
+
),
|
|
4211
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4212
|
+
SecretCard,
|
|
4213
|
+
{
|
|
4214
|
+
status,
|
|
4215
|
+
secretInput,
|
|
4216
|
+
setSecretInput,
|
|
4217
|
+
showSecret,
|
|
4218
|
+
setShowSecret,
|
|
4219
|
+
saveSecret,
|
|
4220
|
+
clearSecret,
|
|
4221
|
+
lang: currentLang
|
|
4222
|
+
}
|
|
4223
|
+
)
|
|
4224
|
+
] }),
|
|
4225
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: activeTab === "devices" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: [
|
|
4226
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4227
|
+
DeviceListCard,
|
|
4228
|
+
{
|
|
4229
|
+
status,
|
|
4230
|
+
revokeDevice,
|
|
4231
|
+
revokeAll,
|
|
4232
|
+
lang: currentLang
|
|
4233
|
+
}
|
|
4234
|
+
),
|
|
4235
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4236
|
+
SecurityCard,
|
|
4237
|
+
{
|
|
4238
|
+
status,
|
|
4239
|
+
unlockIp,
|
|
4240
|
+
clearIpStats,
|
|
4241
|
+
lang: currentLang
|
|
4242
|
+
}
|
|
4243
|
+
),
|
|
4244
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4245
|
+
ConfigCard,
|
|
4246
|
+
{
|
|
4247
|
+
maxVisitsInput,
|
|
4248
|
+
setMaxVisitsInput,
|
|
4249
|
+
maxFailedInput,
|
|
4250
|
+
setMaxFailedInput,
|
|
4251
|
+
lockDurationMinsInput,
|
|
4252
|
+
setLockDurationMinsInput,
|
|
4253
|
+
saveAdvancedConfig,
|
|
4254
|
+
resetAdvancedConfigDefaults,
|
|
4255
|
+
isSaving,
|
|
4256
|
+
lang: currentLang,
|
|
4257
|
+
copyText
|
|
4258
|
+
}
|
|
4259
|
+
)
|
|
4260
|
+
] }),
|
|
4261
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: activeTab === "style" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StylesCard, { lang: currentLang, showToast }) }),
|
|
4262
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: activeTab === "storage" ? "flex" : "none", flexDirection: "column", gap: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StorageCard, { status, lang: currentLang, copyText }) })
|
|
3473
4263
|
]
|
|
3474
4264
|
}
|
|
3475
4265
|
);
|