dsh-pocket 2.6.2 → 2.7.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/client/client.js CHANGED
@@ -37,7 +37,7 @@ __export(index_exports, {
37
37
  redactStatus: () => redactStatus
38
38
  });
39
39
  module.exports = __toCommonJS(index_exports);
40
- var import_react3 = require("react");
40
+ var import_react2 = require("react");
41
41
 
42
42
  // client/api.js
43
43
  var POCKET_RPC_CHANNEL = "/dsh-pocket";
@@ -54,10 +54,7 @@ var POCKET_ENDPOINTS = Object.freeze({
54
54
  lanSetOverride: "lan.setOverride",
55
55
  lanSetEnabled: "lan.setEnabled",
56
56
  pinSetCustom: "pin.setCustom",
57
- pocketReset: "pocket.reset",
58
- tempPinCreate: "tempPin.create",
59
- tempPinList: "tempPin.list",
60
- tempPinRevoke: "tempPin.revoke"
57
+ pocketReset: "pocket.reset"
61
58
  });
62
59
  function compareVersions(a, b) {
63
60
  const pa = String(a).replace(/^[vV]/, "").split(".");
@@ -340,57 +337,85 @@ function MobileDrawerFooter({ useSessions, downloadSessionLog, toggleSidebar, t
340
337
  ));
341
338
  }
342
339
 
343
- // client/mobile/MobileComposerFullscreen.tsx
344
- var import_react2 = require("react");
345
- var FULLSCREEN_ATTR = "data-dsh-pocket-composer-fullscreen";
346
- function isFullscreen() {
347
- return typeof document !== "undefined" && document.body?.getAttribute(FULLSCREEN_ATTR) === "1";
340
+ // client/mobile/fileCopy.ts
341
+ var BUTTON_ATTR = "data-mobile-nav";
342
+ var BUTTON_VALUE = "copy-file";
343
+ var MARKER = "data-mobile-nav-copy";
344
+ async function copyText(text) {
345
+ try {
346
+ if (navigator.clipboard && window.isSecureContext) {
347
+ await navigator.clipboard.writeText(text);
348
+ return true;
349
+ }
350
+ } catch {
351
+ }
352
+ try {
353
+ const ta = document.createElement("textarea");
354
+ ta.value = text;
355
+ ta.setAttribute("readonly", "");
356
+ ta.style.position = "fixed";
357
+ ta.style.top = "0";
358
+ ta.style.left = "0";
359
+ ta.style.opacity = "0";
360
+ document.body.appendChild(ta);
361
+ ta.select();
362
+ const ok = document.execCommand("copy");
363
+ ta.remove();
364
+ return ok;
365
+ } catch {
366
+ return false;
367
+ }
348
368
  }
349
- function setFullscreen(on) {
350
- if (typeof document === "undefined") return;
351
- if (on) document.body.setAttribute(FULLSCREEN_ATTR, "1");
352
- else document.body.removeAttribute(FULLSCREEN_ATTR);
369
+ function createCopyButton() {
370
+ const btn = document.createElement("button");
371
+ btn.type = "button";
372
+ btn.setAttribute(BUTTON_ATTR, BUTTON_VALUE);
373
+ btn.textContent = "\u590D\u5236";
374
+ btn.setAttribute("aria-label", "\u590D\u5236\u6587\u4EF6\u5185\u5BB9");
375
+ btn.addEventListener("click", async (event) => {
376
+ event.preventDefault();
377
+ event.stopPropagation();
378
+ const card = btn.parentElement;
379
+ const block = card?.querySelector("pre") ?? null;
380
+ const text = block?.textContent ?? "";
381
+ const ok = await copyText(text);
382
+ const prev = btn.textContent;
383
+ btn.textContent = ok ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5931\u8D25";
384
+ btn.setAttribute("data-copied", ok ? "1" : "0");
385
+ window.setTimeout(() => {
386
+ btn.textContent = prev;
387
+ btn.removeAttribute("data-copied");
388
+ }, 1500);
389
+ });
390
+ return btn;
353
391
  }
354
- function MobileComposerFullscreen() {
355
- const [on, setOn] = (0, import_react2.useState)(isFullscreen);
356
- (0, import_react2.useEffect)(() => {
357
- const update = () => setOn(isFullscreen());
358
- const observer = new MutationObserver(update);
359
- observer.observe(document.body, { attributes: true, attributeFilter: [FULLSCREEN_ATTR] });
360
- return () => observer.disconnect();
361
- }, []);
362
- return (0, import_react2.createElement)("button", {
363
- type: "button",
364
- "aria-label": on ? "\u6536\u8D77\u8F93\u5165" : "\u653E\u5927\u8F93\u5165",
365
- "aria-pressed": on,
366
- title: on ? "\u6536\u8D77\u8F93\u5165" : "\u653E\u5927\u8F93\u5165",
367
- "data-mobile-nav": "composer-fullscreen",
368
- "data-mobile-nav-keep": "1",
369
- // 自己的按钮不该被 #23 的 slot 通用隐藏规则误伤
370
- onClick: () => {
371
- const next = !isFullscreen();
372
- setFullscreen(next);
373
- setOn(next);
374
- },
375
- style: {
376
- appearance: "none",
377
- WebkitAppearance: "none",
378
- border: "none",
379
- background: "transparent",
380
- color: "inherit",
381
- cursor: "pointer",
382
- padding: "0 8px",
383
- height: 32,
384
- minWidth: 32,
385
- borderRadius: 6,
386
- display: "inline-flex",
387
- alignItems: "center",
388
- justifyContent: "center",
389
- font: "inherit",
390
- fontSize: 16,
391
- lineHeight: 1
392
- }
393
- }, on ? "\u2921" : "\u2922");
392
+ function injectInto(card) {
393
+ if (card.hasAttribute(MARKER)) return;
394
+ card.setAttribute(MARKER, "1");
395
+ if (getComputedStyle(card).position === "static") card.style.position = "relative";
396
+ card.appendChild(createCopyButton());
397
+ }
398
+ function collectCodeBlocks(root) {
399
+ const out = [];
400
+ for (const pre of Array.from(root.querySelectorAll("pre"))) {
401
+ const card = pre.parentElement;
402
+ if (card === null) continue;
403
+ if (card.hasAttribute(MARKER)) continue;
404
+ if ((pre.textContent ?? "").trim().length < 1) continue;
405
+ out.push(card);
406
+ }
407
+ return out;
408
+ }
409
+ function startFileCopyInjection() {
410
+ const scan = () => {
411
+ for (const card of collectCodeBlocks(document)) injectInto(card);
412
+ };
413
+ const observer = new MutationObserver(scan);
414
+ observer.observe(document.body, { childList: true, subtree: true });
415
+ scan();
416
+ return () => {
417
+ observer.disconnect();
418
+ };
394
419
  }
395
420
 
396
421
  // client/mobile/mobile.css.ts
@@ -1253,6 +1278,42 @@ var MOBILE_CSS = `
1253
1278
  [data-phase="hero"] [class$="_stack"] {
1254
1279
  gap: 0 !important;
1255
1280
  }
1281
+
1282
+ /* ---------- \u590D\u5236\u6587\u4EF6\u5185\u5BB9\u6309\u94AE\uFF08issue #17\uFF09 ----------
1283
+ \u6302\u5728\u4EE3\u7801/\u6587\u4EF6\u5757\u5BB9\u5668\u53F3\u4E0A\u89D2\uFF08position:relative \u7531 JS \u5728\u6CE8\u5165\u65F6\u8865\u4E0A\uFF09\u3002
1284
+ \u53EA\u5C4F\u5185\u53EF\u89C1\uFF1A\u684C\u9762\u7AEF DSH \u81EA\u5E26\u590D\u5236\uFF0C\u4E14\u672C effect \u53EA\u5728 narrow \u4E0B\u6302\u8F7D\uFF0C\u6309\u94AE
1285
+ \u6839\u672C\u4E0D\u4F1A\u6CE8\u5165\uFF1B\u8FD9\u91CC\u518D\u515C\u5E95\u4E00\u5C42\uFF0C\u907F\u514D\u4EFB\u4F55\u9057\u6F0F\u3002 */
1286
+ [data-mobile-nav="copy-file"] {
1287
+ position: absolute !important;
1288
+ top: 6px !important;
1289
+ right: 6px !important;
1290
+ z-index: 6 !important;
1291
+ display: inline-flex !important;
1292
+ align-items: center !important;
1293
+ justify-content: center !important;
1294
+ height: 26px !important;
1295
+ padding: 0 10px !important;
1296
+ border: 1px solid var(--dsw-alias-border-l1, rgba(0, 0, 0, .12)) !important;
1297
+ border-radius: 8px !important;
1298
+ background: var(--dsw-alias-bg-base, #ffffff) !important;
1299
+ color: var(--dsw-alias-label-primary, inherit) !important;
1300
+ font-family: inherit !important;
1301
+ font-size: 12px !important;
1302
+ line-height: 1 !important;
1303
+ cursor: pointer !important;
1304
+ -webkit-tap-highlight-color: transparent !important;
1305
+ box-shadow: 0 1px 4px rgba(0, 0, 0, .14) !important;
1306
+ }
1307
+ [data-mobile-nav="copy-file"]:active {
1308
+ background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, .06)) !important;
1309
+ }
1310
+ [data-mobile-nav="copy-file"][data-copied="1"] {
1311
+ color: var(--dsw-alias-state-success-primary, #1a9d54) !important;
1312
+ border-color: var(--dsw-alias-state-success-primary, #1a9d54) !important;
1313
+ }
1314
+ [data-mobile-nav="copy-file"][data-copied="0"] {
1315
+ color: var(--dsw-alias-state-danger-primary, #e5484d) !important;
1316
+ }
1256
1317
  }
1257
1318
 
1258
1319
  /* ---------- desktop: the mobile controls must never appear ---------- */
@@ -1267,52 +1328,8 @@ var MOBILE_CSS = `
1267
1328
  [data-mobile-nav="drawer-actions"] {
1268
1329
  display: none !important;
1269
1330
  }
1270
- /* \u684C\u9762\u7AEF\u6C38\u8FDC\u4E0D\u9700\u8981\u300C\u26F6 \u653E\u5927\u8F93\u5165\u300D\u6309\u94AE\uFF08composer \u5DF2\u7ECF\u6709\u5B8C\u6574\u5DE5\u5177\u884C\uFF09 */
1271
- [data-mobile-nav="composer-fullscreen"] {
1272
- display: none !important;
1273
- }
1274
1331
  }
1275
1332
 
1276
- /* ---------- \u653E\u5927\u8F93\u5165\uFF08issue #23\uFF09 ----------
1277
- \u7A84\u5C4F\u9ED8\u8BA4\u9690\u85CF\u63D2\u4EF6\u6CE8\u518C\u5230 conversation.input.* slot \u7684 UI\uFF08\u4EC5\u7559\u5B98\u65B9 resident
1278
- chrome\uFF09\uFF0C\u70B9\u300C\u26F6\u300D\u6309\u94AE\u628A composer \u5361\u7247\u56FA\u5B9A\u5230\u5168\u5C4F\u540E\u6240\u6709\u63D2\u4EF6 UI \u6062\u590D\u663E\u793A\u2014\u2014
1279
- \u65B0\u63D2\u4EF6\u96F6\u9002\u914D\u3002
1280
- \u5B9E\u73B0\u8BF4\u660E\uFF1A\u5F53\u524D dsh 0.1.1 \u6CA1\u628A input slot \u6E32\u67D3\u6210 [data-slot] \u5305\u88C5\uFF080.1.2+ \u624D\u6709\uFF09\uFF0C
1281
- \u6240\u4EE5\u8FD9\u91CC\u7528\u300C\u767D\u540D\u5355\u300D\u53CD\u9009\uFF1AmobileApply \u6CE8\u518C\u7684 mobile \u81EA\u8EAB\u8282\u70B9\u52A0
1282
- data-mobile-nav="composer-fullscreen" \u4E0D\u88AB\u9690\u85CF\uFF1B\u5176\u5B83\u63D2\u4EF6 UI \u9690\u85CF\u3002 */
1283
- @media (max-width: 1023px) {
1284
- /* \u9ED8\u8BA4\uFF08\u975E\u5168\u5C4F\uFF09\uFF1A\u9690\u85CF input slot \u5BB9\u5668\u4E0B\u7684\u6240\u6709\u76F4\u63A5\u5B50\u5143\u7D20\uFF08\u5305\u542B\u63D2\u4EF6\u548C\u5B98\u65B9\uFF09
1285
- \u2014\u2014\u5B98\u65B9\u81EA\u5DF1\u5982\u679C\u60F3\u5728\u7A84\u5C4F\u4E5F\u9732\u51FA\uFF0C\u6CE8 input slot \u65F6\u52A0 data-mobile-nav-keep="1" */
1286
- [data-dsh-pocket-composer-fullscreen]:not([data-dsh-pocket-composer-fullscreen="1"])
1287
- [class$="_card"]:has(textarea) [data-slot^="conversation.input."] > :not([data-mobile-nav-keep]),
1288
- [data-dsh-pocket-composer-fullscreen]:not([data-dsh-pocket-composer-fullscreen="1"])
1289
- [class$="_card"]:has(textarea) [data-slot^="conversation.input."]:empty {
1290
- display: none !important;
1291
- }
1292
- /* \u653E\u5927\u6309\u94AE\uFF1A\u5E38\u9A7B\u5728 conversation.input.right slot \u65C1\uFF0C\u684C\u9762\u7AEF\u5DF2\u88AB\u4E0A\u9762\u89C4\u5219\u9690\u85CF */
1293
- [data-mobile-nav="composer-fullscreen"] {
1294
- display: inline-flex;
1295
- }
1296
- /* \u5168\u5C4F\u6A21\u5F0F\uFF1Acomposer \u5361\u7247\u56FA\u5B9A\u5230\u89C6\u53E3\uFF0Ctextarea \u62C9\u9AD8\uFF0C\u5DE5\u5177\u884C\u53EF\u6362\u884C */
1297
- [data-dsh-pocket-composer-fullscreen="1"] [class$="_card"]:has(textarea) {
1298
- position: fixed !important;
1299
- inset: 0 !important;
1300
- z-index: 9999 !important;
1301
- border-radius: 0 !important;
1302
- margin: 0 !important;
1303
- height: 100dvh !important;
1304
- display: flex !important;
1305
- flex-direction: column !important;
1306
- }
1307
- [data-dsh-pocket-composer-fullscreen="1"] [class$="_card"]:has(textarea) textarea {
1308
- flex: 1 1 auto !important;
1309
- min-height: 50dvh !important;
1310
- max-height: none !important;
1311
- }
1312
- [data-dsh-pocket-composer-fullscreen="1"] [class$="_card"]:has(textarea) [data-slot^="conversation.input."] {
1313
- flex-wrap: wrap !important;
1314
- }
1315
- }
1316
1333
  `;
1317
1334
 
1318
1335
  // client/mobile/locales.ts
@@ -1528,6 +1545,11 @@ function mobileApply(ctx) {
1528
1545
  observer.disconnect();
1529
1546
  };
1530
1547
  }, "dsh-mobile-nav: sheet rise animation replay");
1548
+ ctx.effect(() => {
1549
+ if (!narrow.matches) return () => {
1550
+ };
1551
+ return startFileCopyInjection();
1552
+ }, "dsh-mobile-nav: file copy button (issue #17)");
1531
1553
  ctx.slots.inject("conversation.session.header.actions", () => ctx.slots.register({
1532
1554
  name: "conversation.session.header.actions",
1533
1555
  id: "mobile-nav-toggle",
@@ -1537,12 +1559,6 @@ function mobileApply(ctx) {
1537
1559
  toggleSidebar: () => ctx.layout.toggleSidebar()
1538
1560
  })
1539
1561
  }, MobileNavToggle));
1540
- ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
1541
- name: "conversation.input.right",
1542
- id: "mobile-composer-fullscreen",
1543
- order: 100,
1544
- locale: NS
1545
- }, MobileComposerFullscreen));
1546
1562
  ctx.slots.inject("shell.overlay", () => ctx.slots.register({
1547
1563
  name: "shell.overlay",
1548
1564
  id: "mobile-nav-overlay",
@@ -1659,26 +1675,7 @@ var zh2 = {
1659
1675
  "slowHint": " \u2014 \u6709\u70B9\u4E45\uFF1F\u68C0\u67E5\u662F\u5426\u5F00\u7740\u4EE3\u7406/VPN\uFF08Clash TUN \u7B49\uFF09",
1660
1676
  "error": "\u274C \u5F00\u542F\u5931\u8D25\uFF1A{detail}\uFF08\u53EF\u91CD\u8BD5\uFF1B\u82E5\u662F\u4EE3\u7406/VPN \u95EE\u9898\u89C1 README \u6392\u969C\uFF09",
1661
1677
  "unknownError": "\u672A\u77E5\u9519\u8BEF",
1662
- "feedback": "\u6709\u95EE\u9898\uFF1F\u6B22\u8FCE\u5230 GitHub Issues \u53CD\u9988 \u{1F64F}",
1663
- // 临时 PIN(issue #69)
1664
- "tempPinTitle": "\u4E34\u65F6\u8BBF\u95EE PIN\uFF08\u5E26\u8D85\u65F6\uFF09",
1665
- "tempPinSubtitle": "\u7ED9\u8BBF\u5BA2\u5F00\u4E00\u4E2A\u6709\u5BFF\u547D\u7684 8 \u4F4D PIN\uFF0C\u8FC7\u671F\u81EA\u52A8\u4F5C\u5E9F\uFF1B\u4E0E\u4E3B PIN \u5171\u7528\u901F\u7387\u9650\u5236\u3002",
1666
- "tempPinKindPublic": "\u516C\u7F51",
1667
- "tempPinKindLan": "\u5C40\u57DF\u7F51",
1668
- "tempPinDuration": "\u6709\u6548\u65F6\u957F",
1669
- "tempPinDuration1h": "1 \u5C0F\u65F6",
1670
- "tempPinDuration24h": "24 \u5C0F\u65F6",
1671
- "tempPinDuration7d": "7 \u5929",
1672
- "tempPinLabel": "\u5907\u6CE8\uFF08\u53EF\u9009\uFF0C\u7ED9\u8C01\u7528\uFF09",
1673
- "tempPinLabelPh": "\u670B\u53CB\u5C0F\u738B",
1674
- "tempPinCreate": "\u751F\u6210",
1675
- "tempPinCreated": "\u5DF2\u751F\u6210\uFF08\u4EC5\u663E\u793A\u4E00\u6B21\uFF09",
1676
- "tempPinCopied": "\u5DF2\u590D\u5236",
1677
- "tempPinCopy": "\u590D\u5236",
1678
- "tempPinEmpty": "\u6682\u65E0\u4E34\u65F6 PIN",
1679
- "tempPinExpiresIn": "\u8FC7\u671F",
1680
- "tempPinRevoke": "\u64A4\u9500",
1681
- "tempPinRevoked": "\u5DF2\u64A4\u9500"
1678
+ "feedback": "\u6709\u95EE\u9898\uFF1F\u6B22\u8FCE\u5230 GitHub Issues \u53CD\u9988 \u{1F64F}"
1682
1679
  };
1683
1680
  var en2 = {
1684
1681
  "section": "Phone access",
@@ -1773,26 +1770,7 @@ var en2 = {
1773
1770
  "slowHint": " \u2014 taking long? Check for a proxy/VPN (e.g., Clash TUN)",
1774
1771
  "error": "\u274C Failed to enable: {detail} (you can retry; for proxy/VPN issues see the README)",
1775
1772
  "unknownError": "unknown error",
1776
- "feedback": "\u{1F64F} Questions? Open an issue on GitHub",
1777
- // Temp PIN (issue #69)
1778
- "tempPinTitle": "Temporary access PINs (auto-expire)",
1779
- "tempPinSubtitle": "Issue a time-limited 8-char PIN to a guest; expires automatically. Shares the main PIN rate limit.",
1780
- "tempPinKindPublic": "Public",
1781
- "tempPinKindLan": "LAN",
1782
- "tempPinDuration": "Valid for",
1783
- "tempPinDuration1h": "1 hour",
1784
- "tempPinDuration24h": "24 hours",
1785
- "tempPinDuration7d": "7 days",
1786
- "tempPinLabel": "Note (optional, who is this for)",
1787
- "tempPinLabelPh": "Friend Alice",
1788
- "tempPinCreate": "Create",
1789
- "tempPinCreated": "Created (shown once)",
1790
- "tempPinCopied": "Copied",
1791
- "tempPinCopy": "Copy",
1792
- "tempPinEmpty": "No temporary PINs yet",
1793
- "tempPinExpiresIn": "expires",
1794
- "tempPinRevoke": "Revoke",
1795
- "tempPinRevoked": "Revoked"
1773
+ "feedback": "\u{1F64F} Questions? Open an issue on GitHub"
1796
1774
  };
1797
1775
 
1798
1776
  // client/index.jsx
@@ -1820,15 +1798,15 @@ var styles = {
1820
1798
  warn: { color: "var(--dsw-alias-state-warn-primary,#b45309)", fontSize: 12, lineHeight: 1.5 }
1821
1799
  };
1822
1800
  function PocketSettingsTab({ rpcCall, t }) {
1823
- const [status, setStatus] = (0, import_react3.useState)(null);
1824
- const [busy, setBusy] = (0, import_react3.useState)(false);
1825
- const [error, setError] = (0, import_react3.useState)(null);
1826
- const [tunnelState, setTunnelState] = (0, import_react3.useState)(null);
1827
- const [restartNotice, setRestartNotice] = (0, import_react3.useState)(false);
1828
- const [updateInfo, setUpdateInfo] = (0, import_react3.useState)(null);
1829
- const [isDesktop, setIsDesktop] = (0, import_react3.useState)(false);
1830
- const [now, setNow] = (0, import_react3.useState)(Date.now());
1831
- (0, import_react3.useEffect)(() => {
1801
+ const [status, setStatus] = (0, import_react2.useState)(null);
1802
+ const [busy, setBusy] = (0, import_react2.useState)(false);
1803
+ const [error, setError] = (0, import_react2.useState)(null);
1804
+ const [tunnelState, setTunnelState] = (0, import_react2.useState)(null);
1805
+ const [restartNotice, setRestartNotice] = (0, import_react2.useState)(false);
1806
+ const [updateInfo, setUpdateInfo] = (0, import_react2.useState)(null);
1807
+ const [isDesktop, setIsDesktop] = (0, import_react2.useState)(false);
1808
+ const [now, setNow] = (0, import_react2.useState)(Date.now());
1809
+ (0, import_react2.useEffect)(() => {
1832
1810
  const t2 = setInterval(() => setNow(Date.now()), 1e3);
1833
1811
  return () => clearInterval(t2);
1834
1812
  }, []);
@@ -1860,18 +1838,18 @@ function PocketSettingsTab({ rpcCall, t }) {
1860
1838
  } catch {
1861
1839
  }
1862
1840
  };
1863
- (0, import_react3.useEffect)(() => {
1841
+ (0, import_react2.useEffect)(() => {
1864
1842
  load();
1865
1843
  const t2 = setInterval(load, 3e3);
1866
1844
  return () => clearInterval(t2);
1867
1845
  }, []);
1868
- (0, import_react3.useEffect)(() => {
1846
+ (0, import_react2.useEffect)(() => {
1869
1847
  try {
1870
1848
  sessionStorage.removeItem("dshp-auto-reloaded");
1871
1849
  } catch {
1872
1850
  }
1873
1851
  }, []);
1874
- (0, import_react3.useEffect)(() => {
1852
+ (0, import_react2.useEffect)(() => {
1875
1853
  if (isDesktop) return;
1876
1854
  let alive = true;
1877
1855
  const check = async () => {
@@ -1927,75 +1905,8 @@ function PocketSettingsTab({ rpcCall, t }) {
1927
1905
  setUpdateInfo((u) => ({ ...u, updating: false, result: "fail", output: err.message }));
1928
1906
  }
1929
1907
  };
1930
- const [tempPinForm, setTempPinForm] = (0, import_react3.useState)({ kind: "lan", expiresInSec: 86400, label: "" });
1931
- const [tempPinsList, setTempPinsList] = (0, import_react3.useState)([]);
1932
- const [tempPinLast, setTempPinLast] = (0, import_react3.useState)(null);
1933
- const [tempPinBusy, setTempPinBusy] = (0, import_react3.useState)(false);
1934
- const [tempPinError, setTempPinError] = (0, import_react3.useState)(null);
1935
- const loadTempPins = async () => {
1936
- try {
1937
- const r = await call(POCKET_ENDPOINTS.tempPinList, {});
1938
- setTempPinsList(Array.isArray(r?.tempPins) ? r.tempPins : []);
1939
- } catch {
1940
- }
1941
- };
1942
- (0, import_react3.useEffect)(() => {
1943
- loadTempPins();
1944
- }, []);
1945
- (0, import_react3.useEffect)(() => {
1946
- if (tempPinsList.length === 0 && !tempPinLast) return;
1947
- const t2 = setInterval(() => {
1948
- loadTempPins();
1949
- }, 3e4);
1950
- return () => clearInterval(t2);
1951
- }, [tempPinsList.length, tempPinLast]);
1952
- const createTempPinNow = async () => {
1953
- setTempPinBusy(true);
1954
- setTempPinError(null);
1955
- try {
1956
- const r = await call(POCKET_ENDPOINTS.tempPinCreate, { kind: tempPinForm.kind, expiresInSec: tempPinForm.expiresInSec, label: tempPinForm.label });
1957
- setTempPinLast(r);
1958
- setTempPinForm((f) => ({ ...f, label: "" }));
1959
- await loadTempPins();
1960
- } catch (err) {
1961
- setTempPinError(err.message);
1962
- } finally {
1963
- setTempPinBusy(false);
1964
- }
1965
- };
1966
- const revokeTempPinNow = async (p) => {
1967
- try {
1968
- await call(POCKET_ENDPOINTS.tempPinRevoke, { value: p.value, kind: p.kind });
1969
- showToast(t("tempPinRevoked"));
1970
- if (tempPinLast?.value === p.value) setTempPinLast(null);
1971
- await loadTempPins();
1972
- } catch (err) {
1973
- setError(err.message);
1974
- }
1975
- };
1976
- const copyTempPin = async (value) => {
1977
- try {
1978
- if (navigator.clipboard?.writeText) {
1979
- await navigator.clipboard.writeText(value);
1980
- showToast(t("tempPinCopied"));
1981
- }
1982
- } catch {
1983
- }
1984
- };
1985
- const formatRemaining = (expiresAt) => {
1986
- const ms = expiresAt - Date.now();
1987
- if (ms <= 0) return "0s";
1988
- const s = Math.floor(ms / 1e3);
1989
- if (s < 60) return `${s}s`;
1990
- const m = Math.floor(s / 60);
1991
- if (m < 60) return `${m}m`;
1992
- const h3 = Math.floor(m / 60);
1993
- if (h3 < 24) return `${h3}h`;
1994
- const d = Math.floor(h3 / 24);
1995
- return `${d}d`;
1996
- };
1997
- const [disclaimerOpen, setDisclaimerOpen] = (0, import_react3.useState)(false);
1998
- const [disclaimerChecked, setDisclaimerChecked] = (0, import_react3.useState)(false);
1908
+ const [disclaimerOpen, setDisclaimerOpen] = (0, import_react2.useState)(false);
1909
+ const [disclaimerChecked, setDisclaimerChecked] = (0, import_react2.useState)(false);
1999
1910
  const doStartTunnel = async () => {
2000
1911
  const cfg = status?.tunnelConfig;
2001
1912
  if (cfg?.mode === "named" && (!cfg.hostname || !cfg.tokenSet)) {
@@ -2028,7 +1939,7 @@ function PocketSettingsTab({ rpcCall, t }) {
2028
1939
  } catch {
2029
1940
  }
2030
1941
  };
2031
- const [tunnelCfg, setTunnelCfg] = (0, import_react3.useState)(null);
1942
+ const [tunnelCfg, setTunnelCfg] = (0, import_react2.useState)(null);
2032
1943
  const switchToQuick = async () => {
2033
1944
  try {
2034
1945
  setStatus(await call(POCKET_ENDPOINTS.tunnelSetConfig, { mode: "quick" }));
@@ -2049,7 +1960,7 @@ function PocketSettingsTab({ rpcCall, t }) {
2049
1960
  setTunnelCfg((c) => ({ ...c, err: err.message }));
2050
1961
  }
2051
1962
  };
2052
- const [resetOpen, setResetOpen] = (0, import_react3.useState)(false);
1963
+ const [resetOpen, setResetOpen] = (0, import_react2.useState)(false);
2053
1964
  const doFactoryReset = async () => {
2054
1965
  setResetOpen(false);
2055
1966
  setBusy(true);
@@ -2081,7 +1992,7 @@ function PocketSettingsTab({ rpcCall, t }) {
2081
1992
  } catch {
2082
1993
  }
2083
1994
  };
2084
- const [lanToggleOpen, setLanToggleOpen] = (0, import_react3.useState)(null);
1995
+ const [lanToggleOpen, setLanToggleOpen] = (0, import_react2.useState)(null);
2085
1996
  const requestLanToggle = (on) => setLanToggleOpen(on);
2086
1997
  const confirmLanToggle = async () => {
2087
1998
  const on = lanToggleOpen;
@@ -2101,7 +2012,7 @@ function PocketSettingsTab({ rpcCall, t }) {
2101
2012
  setError(err.message);
2102
2013
  }
2103
2014
  };
2104
- const [customPin, setCustomPin] = (0, import_react3.useState)(null);
2015
+ const [customPin, setCustomPin] = (0, import_react2.useState)(null);
2105
2016
  const saveCustomPin = async (which) => {
2106
2017
  try {
2107
2018
  const r = await call(POCKET_ENDPOINTS.pinSetCustom, { which, value: customPin?.value ?? "" });
@@ -2117,11 +2028,11 @@ function PocketSettingsTab({ rpcCall, t }) {
2117
2028
  setCustomPin((c) => ({ ...c, err: err.message }));
2118
2029
  }
2119
2030
  };
2120
- const customPinRow = (which) => (0, import_react3.createElement)(
2031
+ const customPinRow = (which) => (0, import_react2.createElement)(
2121
2032
  "div",
2122
2033
  { style: { marginTop: 6, fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)", lineHeight: 1.5 } },
2123
2034
  t("customizing"),
2124
- (0, import_react3.createElement)("input", {
2035
+ (0, import_react2.createElement)("input", {
2125
2036
  style: { width: 130, margin: "0 6px", padding: "4px 8px", fontSize: 14, letterSpacing: 1, textAlign: "center", border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", borderRadius: 6, outline: "none" },
2126
2037
  type: "password",
2127
2038
  maxLength: 8,
@@ -2133,11 +2044,11 @@ function PocketSettingsTab({ rpcCall, t }) {
2133
2044
  if (e.key === "Escape") setCustomPin(null);
2134
2045
  }
2135
2046
  }),
2136
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12, marginLeft: 2 }, onClick: () => saveCustomPin(which) }, t("save")),
2137
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: () => setCustomPin(null) }, t("cancel")),
2138
- customPin?.err ? (0, import_react3.createElement)("div", { style: { color: "var(--dsw-alias-state-error-primary,#dc2626)", marginTop: 4 } }, errText(customPin.err)) : null
2047
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12, marginLeft: 2 }, onClick: () => saveCustomPin(which) }, t("save")),
2048
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: () => setCustomPin(null) }, t("cancel")),
2049
+ customPin?.err ? (0, import_react2.createElement)("div", { style: { color: "var(--dsw-alias-state-error-primary,#dc2626)", marginTop: 4 } }, errText(customPin.err)) : null
2139
2050
  );
2140
- const customBtn = (which) => (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12, marginLeft: 8 }, onClick: () => setCustomPin({ which, value: "", err: null }) }, t("customize"));
2051
+ const customBtn = (which) => (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12, marginLeft: 8 }, onClick: () => setCustomPin({ which, value: "", err: null }) }, t("customize"));
2141
2052
  const lanUrl = status?.lanUrl;
2142
2053
  const tunnelUrl = status?.tunnelUrl;
2143
2054
  const tunnelPhase = tunnelState?.phase ?? "idle";
@@ -2153,14 +2064,14 @@ function PocketSettingsTab({ rpcCall, t }) {
2153
2064
  if (i < 0) return s;
2154
2065
  return (t("ok") === zh2.ok ? s.slice(0, i) : s.slice(i + 3)).trim();
2155
2066
  };
2156
- const [toast, setToast] = (0, import_react3.useState)(null);
2157
- const toastTimer = (0, import_react3.useRef)(null);
2067
+ const [toast, setToast] = (0, import_react2.useState)(null);
2068
+ const toastTimer = (0, import_react2.useRef)(null);
2158
2069
  const showToast = (text) => {
2159
2070
  setToast(text);
2160
2071
  clearTimeout(toastTimer.current);
2161
2072
  toastTimer.current = setTimeout(() => setToast(null), 2600);
2162
2073
  };
2163
- (0, import_react3.useEffect)(() => () => clearTimeout(toastTimer.current), []);
2074
+ (0, import_react2.useEffect)(() => () => clearTimeout(toastTimer.current), []);
2164
2075
  const modeBtnStyle = (active) => ({
2165
2076
  ...styles.btn,
2166
2077
  height: 28,
@@ -2170,49 +2081,49 @@ function PocketSettingsTab({ rpcCall, t }) {
2170
2081
  background: active ? "var(--dsw-alias-button-primary-fill, var(--dsw-alias-brand-primary,#4f6ef7))" : "var(--dsw-alias-bg-layer-1,#fff)",
2171
2082
  color: active ? "var(--dsw-alias-label-primary-foreground, #fff)" : "var(--dsw-alias-label-primary,inherit)"
2172
2083
  });
2173
- const Switch = (on, onClick) => (0, import_react3.createElement)("button", {
2084
+ const Switch = (on, onClick) => (0, import_react2.createElement)("button", {
2174
2085
  role: "switch",
2175
2086
  "aria-checked": !!on,
2176
2087
  style: { flexShrink: 0, width: 40, height: 22, borderRadius: 11, border: "none", padding: 0, position: "relative", cursor: "pointer", font: "inherit", background: on ? "var(--dsw-alias-button-primary-fill, var(--dsw-alias-brand-primary,#4f6ef7))" : "var(--dsw-alias-border-l2,#d1d5db)" },
2177
2088
  onClick
2178
- }, (0, import_react3.createElement)("span", { style: { position: "absolute", top: 2, left: on ? 20 : 2, width: 18, height: 18, borderRadius: "50%", background: "#fff" } }));
2179
- const qrArea = (src, url, hint) => (0, import_react3.createElement)(
2089
+ }, (0, import_react2.createElement)("span", { style: { position: "absolute", top: 2, left: on ? 20 : 2, width: 18, height: 18, borderRadius: "50%", background: "#fff" } }));
2090
+ const qrArea = (src, url, hint) => (0, import_react2.createElement)(
2180
2091
  "div",
2181
2092
  { style: { background: "var(--dsw-alias-bg-layer-2,#f3f4f6)", borderRadius: 10, padding: "10px 12px", textAlign: "center", margin: "10px 0" } },
2182
- (0, import_react3.createElement)("img", { src, alt: "QR", style: styles.qr }),
2183
- (0, import_react3.createElement)("div", { style: styles.code }, url),
2184
- (0, import_react3.createElement)("div", { style: styles.muted }, hint)
2093
+ (0, import_react2.createElement)("img", { src, alt: "QR", style: styles.qr }),
2094
+ (0, import_react2.createElement)("div", { style: styles.code }, url),
2095
+ (0, import_react2.createElement)("div", { style: styles.muted }, hint)
2185
2096
  );
2186
- const row = (label, control, extra) => (0, import_react3.createElement)(
2097
+ const row = (label, control, extra) => (0, import_react2.createElement)(
2187
2098
  "div",
2188
2099
  { style: { borderTop: "1px solid var(--dsw-alias-border-l2,#e5e7eb)", paddingTop: 9, marginTop: 9 } },
2189
- (0, import_react3.createElement)(
2100
+ (0, import_react2.createElement)(
2190
2101
  "div",
2191
2102
  { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } },
2192
- (0, import_react3.createElement)("span", { style: { fontSize: 13 } }, label),
2103
+ (0, import_react2.createElement)("span", { style: { fontSize: 13 } }, label),
2193
2104
  control
2194
2105
  ),
2195
2106
  extra ?? null
2196
2107
  );
2197
- const [advOpen, setAdvOpen] = (0, import_react3.useState)(false);
2198
- return (0, import_react3.createElement)(
2108
+ const [advOpen, setAdvOpen] = (0, import_react2.useState)(false);
2109
+ return (0, import_react2.createElement)(
2199
2110
  "div",
2200
2111
  { style: styles.card },
2201
- (0, import_react3.createElement)(
2112
+ (0, import_react2.createElement)(
2202
2113
  "div",
2203
2114
  { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } },
2204
- (0, import_react3.createElement)(
2115
+ (0, import_react2.createElement)(
2205
2116
  "div",
2206
2117
  null,
2207
- (0, import_react3.createElement)("strong", null, t("title")),
2208
- (0, import_react3.createElement)("div", { style: styles.muted }, t("subtitle"))
2118
+ (0, import_react2.createElement)("strong", null, t("title")),
2119
+ (0, import_react2.createElement)("div", { style: styles.muted }, t("subtitle"))
2209
2120
  ),
2210
- (0, import_react3.createElement)(
2121
+ (0, import_react2.createElement)(
2211
2122
  "div",
2212
2123
  { style: { fontSize: 12, color: "var(--dsw-alias-label-tertiary,#8b93a1)", textAlign: "right" } },
2213
- (0, import_react3.createElement)("div", { style: { whiteSpace: "nowrap" } }, t("developer")),
2214
- (0, import_react3.createElement)("div", { style: { whiteSpace: "nowrap" } }, t("starAsk")),
2215
- (0, import_react3.createElement)(
2124
+ (0, import_react2.createElement)("div", { style: { whiteSpace: "nowrap" } }, t("developer")),
2125
+ (0, import_react2.createElement)("div", { style: { whiteSpace: "nowrap" } }, t("starAsk")),
2126
+ (0, import_react2.createElement)(
2216
2127
  "a",
2217
2128
  { href: "https://github.com/shaobeichen/dsh-pocket", target: "_blank", rel: "noreferrer", style: { color: "var(--dsw-alias-brand-primary,#4f6ef7)", fontSize: 12, lineHeight: 1.6, textDecoration: "underline" } },
2218
2129
  t("starCta")
@@ -2221,49 +2132,49 @@ function PocketSettingsTab({ rpcCall, t }) {
2221
2132
  ),
2222
2133
  // 桌面端不显示更新/重启横幅(更新由 DSH Desktop 管理),也不需要额外提示
2223
2134
  // 重启后提示(进程在后台运行,停止方法)——左侧蓝色色条(桌面端不会触发本插件的自重启)
2224
- !isDesktop && restartNotice ? (0, import_react3.createElement)(
2135
+ !isDesktop && restartNotice ? (0, import_react2.createElement)(
2225
2136
  "div",
2226
2137
  { style: { ...styles.block, borderLeft: "4px solid var(--dsw-alias-brand-primary,#4f6ef7)", borderRadius: 8, background: "var(--dsw-alias-bg-layer-2,#f3f4f6)", padding: "10px 12px" } },
2227
- (0, import_react3.createElement)(
2138
+ (0, import_react2.createElement)(
2228
2139
  "div",
2229
2140
  { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } },
2230
- (0, import_react3.createElement)("div", { style: { fontWeight: 600, fontSize: 13 } }, t("restarted")),
2231
- (0, import_react3.createElement)("button", { style: styles.btn, onClick: () => setRestartNotice(false) }, t("ok"))
2141
+ (0, import_react2.createElement)("div", { style: { fontWeight: 600, fontSize: 13 } }, t("restarted")),
2142
+ (0, import_react2.createElement)("button", { style: styles.btn, onClick: () => setRestartNotice(false) }, t("ok"))
2232
2143
  ),
2233
- (0, import_react3.createElement)("div", { style: styles.muted, marginTop: 4, wordBreak: "break-all" }, fmt(t, "bgHint", { cmd: status?.killHint ?? `lsof -ti :${status?.dshPort ?? 3080} | xargs kill -9` }))
2144
+ (0, import_react2.createElement)("div", { style: styles.muted, marginTop: 4, wordBreak: "break-all" }, fmt(t, "bgHint", { cmd: status?.killHint ?? `lsof -ti :${status?.dshPort ?? 3080} | xargs kill -9` }))
2234
2145
  ) : null,
2235
2146
  // 更新提示——左侧黄色色条(提示有新版本);单状态:有更新/更新中/已更新自动重启,不并存
2236
2147
  // 桌面端不渲染(更新由 DSH Desktop 管理)
2237
- !isDesktop && updateInfo ? (0, import_react3.createElement)(
2148
+ !isDesktop && updateInfo ? (0, import_react2.createElement)(
2238
2149
  "div",
2239
2150
  { style: { ...styles.block, borderLeft: "4px solid var(--dsw-alias-state-warn-primary,#b45309)", borderRadius: 8, background: "var(--dsw-alias-bg-layer-2,#f3f4f6)", padding: "10px 12px" } },
2240
- (0, import_react3.createElement)(
2151
+ (0, import_react2.createElement)(
2241
2152
  "div",
2242
2153
  { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } },
2243
- (0, import_react3.createElement)(
2154
+ (0, import_react2.createElement)(
2244
2155
  "div",
2245
2156
  { style: { fontWeight: 600, fontSize: 13 } },
2246
2157
  updateInfo.updated ? fmt(t, "updatedRestart", { ver: updateInfo.current }) : updateInfo.result === "ok" ? updateInfo.autoRestart ? fmt(t, "updateAutoRestarting", { ver: updateInfo.latest }) : fmt(t, "updatedOk", { ver: updateInfo.latest }) : fmt(t, "updateAvailable", { ver: updateInfo.latest })
2247
2158
  ),
2248
- updateInfo.result !== "ok" ? (0, import_react3.createElement)("button", { style: styles.primary, onClick: runUpdate, disabled: updateInfo.updating }, updateInfo.updating ? t("updating") : fmt(t, "updateTo", { ver: updateInfo.latest })) : updateInfo.autoRestart ? (0, import_react3.createElement)("button", { style: styles.btn, disabled: true }, t("restartingNow")) : (0, import_react3.createElement)("button", { style: styles.primary, onClick: restartPocket, disabled: updateInfo.restarting }, updateInfo.restarting ? t("restarting") : t("restartNow"))
2159
+ updateInfo.result !== "ok" ? (0, import_react2.createElement)("button", { style: styles.primary, onClick: runUpdate, disabled: updateInfo.updating }, updateInfo.updating ? t("updating") : fmt(t, "updateTo", { ver: updateInfo.latest })) : updateInfo.autoRestart ? (0, import_react2.createElement)("button", { style: styles.btn, disabled: true }, t("restartingNow")) : (0, import_react2.createElement)("button", { style: styles.primary, onClick: restartPocket, disabled: updateInfo.restarting }, updateInfo.restarting ? t("restarting") : t("restartNow"))
2249
2160
  ),
2250
- (0, import_react3.createElement)(
2161
+ (0, import_react2.createElement)(
2251
2162
  "div",
2252
2163
  { style: styles.muted, marginTop: 4 },
2253
2164
  updateInfo.updating ? fmt(t, "updatingDetail", { s: elapsed(updateInfo.startedAt) }) : updateInfo.restarting ? fmt(t, "restartingDetail", { s: elapsed(updateInfo.startedAt) }) : updateInfo.result === "ok" ? updateInfo.autoRestart ? t("updatedAutoDetail") : t("updatedRestartDetail") : updateInfo.result === "fail" ? fmt(t, "updateFailed", { err: errText(updateInfo.output) || t("unknownError") }) : fmt(t, "versionRange", { cur: updateInfo.current, latest: updateInfo.latest })
2254
2165
  )
2255
2166
  ) : null,
2256
2167
  // 局域网:标题行自带总开关 → 二维码+地址 → 设置行(访问密码 / 高级·手动选地址)
2257
- (0, import_react3.createElement)(
2168
+ (0, import_react2.createElement)(
2258
2169
  "div",
2259
2170
  { style: styles.block },
2260
- (0, import_react3.createElement)(
2171
+ (0, import_react2.createElement)(
2261
2172
  "div",
2262
2173
  { style: { display: "flex", alignItems: "center", justifyContent: "space-between" } },
2263
- (0, import_react3.createElement)("span", { style: { fontWeight: 600, fontSize: 13 } }, t("lanAccess")),
2174
+ (0, import_react2.createElement)("span", { style: { fontWeight: 600, fontSize: 13 } }, t("lanAccess")),
2264
2175
  Switch(status?.lanEnabled !== false, () => requestLanToggle(status?.lanEnabled === false))
2265
2176
  ),
2266
- status?.lanEnabled === false ? (0, import_react3.createElement)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsw-alias-state-warn-primary,#b45309)", lineHeight: 1.5 } }, t("lanDisabledHint")) : lanUrl ? (0, import_react3.createElement)(
2177
+ status?.lanEnabled === false ? (0, import_react2.createElement)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsw-alias-state-warn-primary,#b45309)", lineHeight: 1.5 } }, t("lanDisabledHint")) : lanUrl ? (0, import_react2.createElement)(
2267
2178
  "div",
2268
2179
  null,
2269
2180
  qrArea(status.lanQr, lanUrl, t("lanHint")),
@@ -2271,100 +2182,100 @@ function PocketSettingsTab({ rpcCall, t }) {
2271
2182
  row(
2272
2183
  t("lanPin"),
2273
2184
  Switch(status?.lanAuthEnabled !== false, () => setLanAuth(status?.lanAuthEnabled === false)),
2274
- status?.lanAuthEnabled === false ? (0, import_react3.createElement)("div", { style: { ...styles.muted, marginTop: 6 } }, t("lanPinOff")) : customPin?.which === "lan" ? customPinRow("lan") : (0, import_react3.createElement)(
2185
+ status?.lanAuthEnabled === false ? (0, import_react2.createElement)("div", { style: { ...styles.muted, marginTop: 6 } }, t("lanPinOff")) : customPin?.which === "lan" ? customPinRow("lan") : (0, import_react2.createElement)(
2275
2186
  "div",
2276
2187
  { style: { marginTop: 6, display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" } },
2277
- (0, import_react3.createElement)("span", { style: { fontFamily: "ui-monospace,Menlo,monospace", fontSize: 13, letterSpacing: 1 } }, status.lanToken),
2278
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: refreshLanPin }, t("refresh")),
2188
+ (0, import_react2.createElement)("span", { style: { fontFamily: "ui-monospace,Menlo,monospace", fontSize: 13, letterSpacing: 1 } }, status.lanToken),
2189
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: refreshLanPin }, t("refresh")),
2279
2190
  customBtn("lan"),
2280
- status?.lanPinCustom ? (0, import_react3.createElement)("span", { style: { fontSize: 11, color: "var(--dsw-alias-state-warn-primary,#b45309)" } }, t("pinCustomHint")) : null
2191
+ status?.lanPinCustom ? (0, import_react2.createElement)("span", { style: { fontSize: 11, color: "var(--dsw-alias-state-warn-primary,#b45309)" } }, t("pinCustomHint")) : null
2281
2192
  )
2282
2193
  ),
2283
2194
  // 高级:手动选地址(默认收起)
2284
2195
  row(
2285
2196
  t("advAddress"),
2286
- (0, import_react3.createElement)(
2197
+ (0, import_react2.createElement)(
2287
2198
  "button",
2288
2199
  { style: { border: "none", background: "none", font: "inherit", cursor: "pointer", fontSize: 12, color: "var(--dsw-alias-label-tertiary,#8b93a1)", padding: 0 }, onClick: () => setAdvOpen((v) => !v) },
2289
2200
  (status?.lanIpOverride || t("lanAddressAuto")) + " \u203A"
2290
2201
  ),
2291
- advOpen ? (0, import_react3.createElement)(
2202
+ advOpen ? (0, import_react2.createElement)(
2292
2203
  "div",
2293
2204
  { style: { marginTop: 8 } },
2294
- (0, import_react3.createElement)(
2205
+ (0, import_react2.createElement)(
2295
2206
  "label",
2296
2207
  { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)" } },
2297
2208
  t("lanAddress"),
2298
- (0, import_react3.createElement)(
2209
+ (0, import_react2.createElement)(
2299
2210
  "select",
2300
2211
  {
2301
2212
  value: status?.lanIpOverride || "",
2302
2213
  onChange: (e) => setLanAddress(e.target.value),
2303
2214
  style: { font: "inherit", height: 30, padding: "0 8px", borderRadius: 8, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", background: "var(--dsw-alias-bg-layer-1,#fff)", color: "var(--dsw-alias-label-primary,inherit)" }
2304
2215
  },
2305
- (0, import_react3.createElement)("option", { value: "" }, t("lanAddressAuto")),
2306
- (status?.lanCandidates || []).map((ip) => (0, import_react3.createElement)("option", { key: ip, value: ip }, ip))
2216
+ (0, import_react2.createElement)("option", { value: "" }, t("lanAddressAuto")),
2217
+ (status?.lanCandidates || []).map((ip) => (0, import_react2.createElement)("option", { key: ip, value: ip }, ip))
2307
2218
  )
2308
2219
  )
2309
2220
  ) : null
2310
2221
  )
2311
- ) : (0, import_react3.createElement)("div", { style: styles.muted }, t("lanStarting"))
2222
+ ) : (0, import_react2.createElement)("div", { style: styles.muted }, t("lanStarting"))
2312
2223
  ),
2313
2224
  // 公网:标题行自带 开启/关闭 → 开启后:二维码+地址、地址模式行、访问密码行
2314
- (0, import_react3.createElement)(
2225
+ (0, import_react2.createElement)(
2315
2226
  "div",
2316
2227
  { style: styles.block },
2317
- (0, import_react3.createElement)(
2228
+ (0, import_react2.createElement)(
2318
2229
  "div",
2319
2230
  { style: { display: "flex", alignItems: "center", justifyContent: "space-between" } },
2320
- (0, import_react3.createElement)("span", { style: { fontWeight: 600, fontSize: 13 } }, t("wanAccess")),
2321
- tunnelUrl ? (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 28, padding: "0 12px", fontSize: 12, color: "var(--dsw-alias-state-error-primary,#dc2626)" }, onClick: stopTunnel }, t("stopTunnel")) : (0, import_react3.createElement)("button", { style: { ...styles.primary, height: 28, padding: "0 14px", fontSize: 12 }, onClick: startTunnel, disabled: busy || tunnelStarting }, busy || tunnelStarting ? t("opening") : t("enable"))
2231
+ (0, import_react2.createElement)("span", { style: { fontWeight: 600, fontSize: 13 } }, t("wanAccess")),
2232
+ tunnelUrl ? (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 28, padding: "0 12px", fontSize: 12, color: "var(--dsw-alias-state-error-primary,#dc2626)" }, onClick: stopTunnel }, t("stopTunnel")) : (0, import_react2.createElement)("button", { style: { ...styles.primary, height: 28, padding: "0 14px", fontSize: 12 }, onClick: startTunnel, disabled: busy || tunnelStarting }, busy || tunnelStarting ? t("opening") : t("enable"))
2322
2233
  ),
2323
- tunnelStarting ? (0, import_react3.createElement)(
2234
+ tunnelStarting ? (0, import_react2.createElement)(
2324
2235
  "div",
2325
2236
  { style: { marginTop: 8, fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)" } },
2326
2237
  tunnelPhase === "downloading" ? fmt(t, "downloading", { s: elapsed(tunnelStateStarted) }) : fmt(t, "connecting", { s: elapsed(tunnelStateStarted), suffix: elapsed(tunnelStateStarted) > 30 ? t("slowHint") : "" })
2327
- ) : tunnelPhase === "error" ? (0, import_react3.createElement)(
2238
+ ) : tunnelPhase === "error" ? (0, import_react2.createElement)(
2328
2239
  "div",
2329
2240
  { style: { marginTop: 8, fontSize: 12, color: "var(--dsw-alias-state-error-primary,#dc2626)" } },
2330
2241
  fmt(t, "error", { detail: errText(tunnelStateDetail) || t("unknownError") })
2331
- ) : !tunnelUrl && !isDesktop ? (0, import_react3.createElement)("div", { style: { ...styles.muted, marginTop: 8 } }, t("wanOffHint")) : null,
2332
- tunnelUrl ? (0, import_react3.createElement)(
2242
+ ) : !tunnelUrl && !isDesktop ? (0, import_react2.createElement)("div", { style: { ...styles.muted, marginTop: 8 } }, t("wanOffHint")) : null,
2243
+ tunnelUrl ? (0, import_react2.createElement)(
2333
2244
  "div",
2334
2245
  null,
2335
2246
  qrArea(status.tunnelQr, tunnelUrl, namedMode ? t("namedRunningHint") : t("wanHint")),
2336
2247
  // 地址模式行(随机/固定;固定域名选中或编辑时高亮)
2337
2248
  row(
2338
2249
  t("modeLabel"),
2339
- (0, import_react3.createElement)(
2250
+ (0, import_react2.createElement)(
2340
2251
  "span",
2341
2252
  { style: { display: "inline-flex", gap: 6 } },
2342
- (0, import_react3.createElement)("button", { style: modeBtnStyle(!namedActive), onClick: namedMode ? switchToQuick : tunnelCfg ? () => setTunnelCfg(null) : void 0 }, t("modeQuick")),
2343
- (0, import_react3.createElement)("button", { style: modeBtnStyle(namedActive), onClick: () => setTunnelCfg(tunnelCfg ? null : { hostname: tunnelModeView.hostname ?? "", token: "", err: null }) }, t("modeNamed"))
2253
+ (0, import_react2.createElement)("button", { style: modeBtnStyle(!namedActive), onClick: namedMode ? switchToQuick : tunnelCfg ? () => setTunnelCfg(null) : void 0 }, t("modeQuick")),
2254
+ (0, import_react2.createElement)("button", { style: modeBtnStyle(namedActive), onClick: () => setTunnelCfg(tunnelCfg ? null : { hostname: tunnelModeView.hostname ?? "", token: "", err: null }) }, t("modeNamed"))
2344
2255
  ),
2345
- (0, import_react3.createElement)(
2256
+ (0, import_react2.createElement)(
2346
2257
  "div",
2347
2258
  { style: { marginTop: 6 } },
2348
2259
  // 刚保存固定域名但当前连接仍是随机域名:需关闭后重新开启才生效
2349
- namedMode && /trycloudflare\.com/i.test(tunnelUrl ?? "") ? (0, import_react3.createElement)("div", { style: { ...styles.warn } }, t("namedTakeEffect")) : null,
2260
+ namedMode && /trycloudflare\.com/i.test(tunnelUrl ?? "") ? (0, import_react2.createElement)("div", { style: { ...styles.warn } }, t("namedTakeEffect")) : null,
2350
2261
  // 固定域名:已保存摘要 + 修改入口(非编辑态)
2351
- namedMode && !tunnelCfg ? (0, import_react3.createElement)(
2262
+ namedMode && !tunnelCfg ? (0, import_react2.createElement)(
2352
2263
  "div",
2353
2264
  { style: { ...styles.muted } },
2354
2265
  fmt(t, "namedSummary", { host: tunnelModeView.hostname || "\u2014", token: tunnelModeView.tokenSet ? t("namedTokenSet") : t("namedTokenMissing") }),
2355
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12, marginLeft: 8 }, onClick: () => setTunnelCfg({ hostname: tunnelModeView.hostname ?? "", token: "", err: null }) }, t("namedEdit")),
2356
- (0, import_react3.createElement)("div", { style: { ...styles.muted, marginTop: 4 } }, t("namedHow")),
2357
- !tunnelModeView.tokenSet || !tunnelModeView.hostname ? (0, import_react3.createElement)("div", { style: { marginTop: 2, color: "var(--dsw-alias-state-error-primary,#dc2626)" } }, t("namedNeedCfg")) : null
2266
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12, marginLeft: 8 }, onClick: () => setTunnelCfg({ hostname: tunnelModeView.hostname ?? "", token: "", err: null }) }, t("namedEdit")),
2267
+ (0, import_react2.createElement)("div", { style: { ...styles.muted, marginTop: 4 } }, t("namedHow")),
2268
+ !tunnelModeView.tokenSet || !tunnelModeView.hostname ? (0, import_react2.createElement)("div", { style: { marginTop: 2, color: "var(--dsw-alias-state-error-primary,#dc2626)" } }, t("namedNeedCfg")) : null
2358
2269
  ) : null,
2359
2270
  // 固定域名:编辑表单(域名 + Tunnel Token,Token 留空保持不变)
2360
- tunnelCfg ? (0, import_react3.createElement)(
2271
+ tunnelCfg ? (0, import_react2.createElement)(
2361
2272
  "div",
2362
2273
  { style: { marginTop: 6, fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)", lineHeight: 1.6 } },
2363
- (0, import_react3.createElement)(
2274
+ (0, import_react2.createElement)(
2364
2275
  "div",
2365
2276
  null,
2366
2277
  t("namedHostnameLabel"),
2367
- (0, import_react3.createElement)("input", {
2278
+ (0, import_react2.createElement)("input", {
2368
2279
  style: { margin: "4px 0 0 6px", padding: "4px 8px", fontSize: 13, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", borderRadius: 6, outline: "none", width: 200 },
2369
2280
  placeholder: "pocket.example.com",
2370
2281
  value: tunnelCfg.hostname ?? "",
@@ -2376,11 +2287,11 @@ function PocketSettingsTab({ rpcCall, t }) {
2376
2287
  }
2377
2288
  })
2378
2289
  ),
2379
- (0, import_react3.createElement)(
2290
+ (0, import_react2.createElement)(
2380
2291
  "div",
2381
2292
  { style: { marginTop: 6 } },
2382
2293
  t("namedTokenLabel"),
2383
- (0, import_react3.createElement)("input", {
2294
+ (0, import_react2.createElement)("input", {
2384
2295
  style: { margin: "4px 0 0 6px", padding: "4px 8px", fontSize: 13, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", borderRadius: 6, outline: "none", width: 240, fontFamily: "ui-monospace,Menlo,monospace" },
2385
2296
  type: "password",
2386
2297
  value: tunnelCfg.token ?? "",
@@ -2391,192 +2302,121 @@ function PocketSettingsTab({ rpcCall, t }) {
2391
2302
  }
2392
2303
  })
2393
2304
  ),
2394
- (0, import_react3.createElement)(
2305
+ (0, import_react2.createElement)(
2395
2306
  "div",
2396
2307
  { style: { marginTop: 6, display: "flex", gap: 8 } },
2397
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: saveNamedTunnel }, t("save")),
2398
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: () => setTunnelCfg(null) }, t("cancel"))
2308
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: saveNamedTunnel }, t("save")),
2309
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 26, padding: "0 10px", fontSize: 12 }, onClick: () => setTunnelCfg(null) }, t("cancel"))
2399
2310
  ),
2400
- (0, import_react3.createElement)("div", { style: { ...styles.muted, marginTop: 6 } }, t("namedHow")),
2401
- (0, import_react3.createElement)("div", { style: { marginTop: 2, fontSize: 11, color: "var(--dsw-alias-state-warn-primary,#b45309)", lineHeight: 1.5 } }, t("namedSecurity")),
2402
- tunnelCfg.err ? (0, import_react3.createElement)("div", { style: { color: "var(--dsw-alias-state-error-primary,#dc2626)", marginTop: 4 } }, errText(tunnelCfg.err)) : null
2311
+ (0, import_react2.createElement)("div", { style: { ...styles.muted, marginTop: 6 } }, t("namedHow")),
2312
+ (0, import_react2.createElement)("div", { style: { marginTop: 2, fontSize: 11, color: "var(--dsw-alias-state-warn-primary,#b45309)", lineHeight: 1.5 } }, t("namedSecurity")),
2313
+ tunnelCfg.err ? (0, import_react2.createElement)("div", { style: { color: "var(--dsw-alias-state-error-primary,#dc2626)", marginTop: 4 } }, errText(tunnelCfg.err)) : null
2403
2314
  ) : null
2404
2315
  )
2405
2316
  ),
2406
2317
  // 访问密码行:值 + 自定义(自定义输入态整体替换)
2407
2318
  status.accessToken ? row(
2408
2319
  t("pinLabel"),
2409
- customPin?.which === "public" ? null : (0, import_react3.createElement)(
2320
+ customPin?.which === "public" ? null : (0, import_react2.createElement)(
2410
2321
  "span",
2411
2322
  { style: { display: "inline-flex", alignItems: "center", gap: 8 } },
2412
- (0, import_react3.createElement)("span", { style: { fontFamily: "ui-monospace,Menlo,monospace", fontSize: 13, letterSpacing: 1 } }, status.accessToken),
2323
+ (0, import_react2.createElement)("span", { style: { fontFamily: "ui-monospace,Menlo,monospace", fontSize: 13, letterSpacing: 1 } }, status.accessToken),
2413
2324
  customBtn("public")
2414
2325
  ),
2415
- (0, import_react3.createElement)(
2326
+ (0, import_react2.createElement)(
2416
2327
  "div",
2417
2328
  { style: { marginTop: 6 } },
2418
2329
  customPin?.which === "public" ? customPinRow("public") : null,
2419
- status?.publicPinCustom ? (0, import_react3.createElement)("div", { style: { ...styles.warn } }, t("pinCustomHint")) : null,
2420
- namedMode ? (0, import_react3.createElement)("div", { style: { ...styles.warn } }, t("namedSecurity")) : null
2330
+ status?.publicPinCustom ? (0, import_react2.createElement)("div", { style: { ...styles.warn } }, t("pinCustomHint")) : null,
2331
+ namedMode ? (0, import_react2.createElement)("div", { style: { ...styles.warn } }, t("namedSecurity")) : null
2421
2332
  )
2422
2333
  ) : null
2423
2334
  ) : null
2424
2335
  ),
2425
- error ? (0, import_react3.createElement)("div", { style: { color: "var(--dsw-alias-state-error-primary,#dc2626)", fontSize: 12, marginTop: 8 } }, `\u274C ${errText(error)}`) : null,
2426
- // 临时 PIN(issue #69):带过期的访问密码,给访客用
2427
- (0, import_react3.createElement)(
2428
- "div",
2429
- { style: styles.block },
2430
- (0, import_react3.createElement)("div", { style: { fontWeight: 600, fontSize: 13, marginBottom: 4 } }, t("tempPinTitle")),
2431
- (0, import_react3.createElement)("div", { style: { ...styles.muted, marginBottom: 10 } }, t("tempPinSubtitle")),
2432
- // 生成表单:分类 + 时长 + 备注 + 生成
2433
- (0, import_react3.createElement)(
2434
- "div",
2435
- { style: { display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center" } },
2436
- (0, import_react3.createElement)(
2437
- "select",
2438
- {
2439
- value: tempPinForm.kind,
2440
- onChange: (e) => setTempPinForm((f) => ({ ...f, kind: e.target.value })),
2441
- style: { font: "inherit", height: 30, padding: "0 8px", borderRadius: 8, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", background: "var(--dsw-alias-bg-layer-1,#fff)", color: "var(--dsw-alias-label-primary,inherit)" }
2442
- },
2443
- (0, import_react3.createElement)("option", { value: "public" }, t("tempPinKindPublic")),
2444
- (0, import_react3.createElement)("option", { value: "lan" }, t("tempPinKindLan"))
2445
- ),
2446
- (0, import_react3.createElement)(
2447
- "select",
2448
- {
2449
- value: String(tempPinForm.expiresInSec),
2450
- onChange: (e) => setTempPinForm((f) => ({ ...f, expiresInSec: Number(e.target.value) })),
2451
- style: { font: "inherit", height: 30, padding: "0 8px", borderRadius: 8, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", background: "var(--dsw-alias-bg-layer-1,#fff)", color: "var(--dsw-alias-label-primary,inherit)" }
2452
- },
2453
- (0, import_react3.createElement)("option", { value: "3600" }, t("tempPinDuration1h")),
2454
- (0, import_react3.createElement)("option", { value: "86400" }, t("tempPinDuration24h")),
2455
- (0, import_react3.createElement)("option", { value: "604800" }, t("tempPinDuration7d"))
2456
- ),
2457
- (0, import_react3.createElement)("input", {
2458
- style: { flex: 1, minWidth: 120, height: 30, padding: "0 10px", borderRadius: 8, border: "1px solid var(--dsw-alias-border-l2,#d1d5db)", fontSize: 13, outline: "none" },
2459
- placeholder: t("tempPinLabelPh"),
2460
- value: tempPinForm.label,
2461
- onChange: (e) => setTempPinForm((f) => ({ ...f, label: e.target.value })),
2462
- onKeyDown: (e) => {
2463
- if (e.key === "Enter") createTempPinNow();
2464
- }
2465
- }),
2466
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 30 }, onClick: createTempPinNow, disabled: tempPinBusy }, t("tempPinCreate"))
2467
- ),
2468
- // 错误展示
2469
- tempPinError ? (0, import_react3.createElement)("div", { style: { color: "var(--dsw-alias-state-error-primary,#dc2626)", fontSize: 12, marginTop: 6 } }, errText(tempPinError)) : null,
2470
- // 刚生成的那一个(高亮,下一秒会消失提示用户立刻复制)
2471
- tempPinLast ? (0, import_react3.createElement)(
2472
- "div",
2473
- { style: { marginTop: 10, padding: "8px 10px", borderRadius: 8, background: "var(--dsw-alias-bg-layer-2,#f3f4f6)", display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" } },
2474
- (0, import_react3.createElement)(
2475
- "div",
2476
- null,
2477
- (0, import_react3.createElement)("div", { style: { fontSize: 11, color: "var(--dsw-alias-state-success-primary,#16a34a)", fontWeight: 600, marginBottom: 2 } }, `${t("tempPinCreated")} \xB7 ${tempPinLast.kind === "public" ? t("tempPinKindPublic") : t("tempPinKindLan")} \xB7 ${formatRemaining(tempPinLast.expiresAt)}`),
2478
- (0, import_react3.createElement)("span", { style: { fontFamily: "ui-monospace,Menlo,monospace", fontSize: 16, letterSpacing: 2, fontWeight: 600 } }, tempPinLast.value)
2479
- ),
2480
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 28, padding: "0 12px", fontSize: 12 }, onClick: () => copyTempPin(tempPinLast.value) }, t("tempPinCopy"))
2481
- ) : null,
2482
- // 列表
2483
- (0, import_react3.createElement)(
2484
- "div",
2485
- { style: { marginTop: 12, borderTop: "1px solid var(--dsw-alias-border-l2,#e5e7eb)", paddingTop: 8 } },
2486
- tempPinsList.length === 0 ? (0, import_react3.createElement)("div", { style: { ...styles.muted, padding: "6px 0" } }, t("tempPinEmpty")) : tempPinsList.map((p) => (0, import_react3.createElement)(
2487
- "div",
2488
- { key: p.value, style: { display: "flex", alignItems: "center", gap: 8, padding: "6px 0", borderBottom: "1px solid var(--dsw-alias-border-l2,#e5e7eb)" } },
2489
- (0, import_react3.createElement)("span", { style: { fontSize: 11, color: "var(--dsw-alias-label-tertiary,#8b93a1)", minWidth: 50 } }, p.kind === "public" ? t("tempPinKindPublic") : t("tempPinKindLan")),
2490
- (0, import_react3.createElement)("span", { style: { fontFamily: "ui-monospace,Menlo,monospace", fontSize: 13, letterSpacing: 1, flexShrink: 0 } }, p.value),
2491
- (0, import_react3.createElement)("span", { style: { ...styles.muted, flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, p.label || "\u2014"),
2492
- (0, import_react3.createElement)("span", { style: { fontSize: 11, color: "var(--dsw-alias-label-tertiary,#8b93a1)" } }, `${t("tempPinExpiresIn")} ${formatRemaining(p.expiresAt)}`),
2493
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 24, padding: "0 10px", fontSize: 11 }, onClick: () => revokeTempPinNow(p) }, t("tempPinRevoke"))
2494
- ))
2495
- )
2496
- ),
2336
+ error ? (0, import_react2.createElement)("div", { style: { color: "var(--dsw-alias-state-error-primary,#dc2626)", fontSize: 12, marginTop: 8 } }, `\u274C ${errText(error)}`) : null,
2497
2337
  // 恢复出厂设置:设置出问题时的临时兜底(最底部,避免误触)
2498
- (0, import_react3.createElement)(
2338
+ (0, import_react2.createElement)(
2499
2339
  "div",
2500
2340
  { style: styles.block },
2501
- (0, import_react3.createElement)(
2341
+ (0, import_react2.createElement)(
2502
2342
  "div",
2503
2343
  { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } },
2504
- (0, import_react3.createElement)("span", { style: { fontWeight: 600, fontSize: 13 } }, t("resetFactory")),
2505
- (0, import_react3.createElement)("button", { style: { ...styles.btn, height: 28, padding: "0 12px", fontSize: 12, color: "var(--dsw-alias-state-error-primary,#dc2626)" }, onClick: () => setResetOpen(true) }, t("resetGo"))
2344
+ (0, import_react2.createElement)("span", { style: { fontWeight: 600, fontSize: 13 } }, t("resetFactory")),
2345
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, height: 28, padding: "0 12px", fontSize: 12, color: "var(--dsw-alias-state-error-primary,#dc2626)" }, onClick: () => setResetOpen(true) }, t("resetGo"))
2506
2346
  ),
2507
- (0, import_react3.createElement)("div", { style: { ...styles.muted, marginTop: 6 } }, t("resetIntro"))
2347
+ (0, import_react2.createElement)("div", { style: { ...styles.muted, marginTop: 6 } }, t("resetIntro"))
2508
2348
  ),
2509
2349
  // 恢复出厂设置确认弹框
2510
- resetOpen ? (0, import_react3.createElement)(
2350
+ resetOpen ? (0, import_react2.createElement)(
2511
2351
  "div",
2512
2352
  { style: { position: "fixed", inset: 0, zIndex: 1e4, background: "rgba(0,0,0,.5)", display: "flex", alignItems: "center", justifyContent: "center", padding: 20 } },
2513
- (0, import_react3.createElement)(
2353
+ (0, import_react2.createElement)(
2514
2354
  "div",
2515
2355
  { style: { background: "var(--dsw-alias-bg-layer-1,#fff)", borderRadius: 12, maxWidth: 440, width: "100%", padding: "20px 22px", boxShadow: "0 8px 32px rgba(0,0,0,.18)" } },
2516
- (0, import_react3.createElement)("div", { style: { fontWeight: 600, fontSize: 15, color: "var(--dsw-alias-state-warn-primary,#b45309)", marginBottom: 10 } }, t("resetTitle")),
2517
- (0, import_react3.createElement)("div", { style: { fontSize: 13, lineHeight: 1.7, color: "var(--dsw-alias-label-primary,inherit)", whiteSpace: "pre-line" } }, t("resetBody")),
2518
- (0, import_react3.createElement)(
2356
+ (0, import_react2.createElement)("div", { style: { fontWeight: 600, fontSize: 15, color: "var(--dsw-alias-state-warn-primary,#b45309)", marginBottom: 10 } }, t("resetTitle")),
2357
+ (0, import_react2.createElement)("div", { style: { fontSize: 13, lineHeight: 1.7, color: "var(--dsw-alias-label-primary,inherit)", whiteSpace: "pre-line" } }, t("resetBody")),
2358
+ (0, import_react2.createElement)(
2519
2359
  "div",
2520
2360
  { style: { display: "flex", gap: 8, marginTop: 16 } },
2521
- (0, import_react3.createElement)("button", { style: { ...styles.btn, flex: 1 }, onClick: () => setResetOpen(false) }, t("cancel")),
2522
- (0, import_react3.createElement)("button", { style: { ...styles.primary, flex: 1, background: "var(--dsw-alias-state-error-primary,#dc2626)" }, onClick: doFactoryReset }, t("resetConfirm"))
2361
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, flex: 1 }, onClick: () => setResetOpen(false) }, t("cancel")),
2362
+ (0, import_react2.createElement)("button", { style: { ...styles.primary, flex: 1, background: "var(--dsw-alias-state-error-primary,#dc2626)" }, onClick: doFactoryReset }, t("resetConfirm"))
2523
2363
  )
2524
2364
  )
2525
2365
  ) : null,
2526
2366
  // Toast:重置等操作的即时反馈(固定屏幕正中央,2.6s 自动消失)
2527
- toast ? (0, import_react3.createElement)("div", {
2367
+ toast ? (0, import_react2.createElement)("div", {
2528
2368
  style: { position: "fixed", left: "50%", top: "50%", transform: "translate(-50%, -50%)", zIndex: 10001, width: "auto", maxWidth: 280, background: "rgba(17,24,39,.92)", color: "#fff", border: "none", borderRadius: 10, padding: "10px 16px", fontSize: 13, lineHeight: 1.5, textAlign: "center", boxShadow: "0 8px 24px rgba(0,0,0,.22)" }
2529
2369
  }, toast) : null,
2530
2370
  // 局域网访问开关确认弹框(关闭/打开时弹窗提醒)
2531
- lanToggleOpen !== null ? (0, import_react3.createElement)(
2371
+ lanToggleOpen !== null ? (0, import_react2.createElement)(
2532
2372
  "div",
2533
2373
  { style: { position: "fixed", inset: 0, zIndex: 1e4, background: "rgba(0,0,0,.5)", display: "flex", alignItems: "center", justifyContent: "center", padding: 20 } },
2534
- (0, import_react3.createElement)(
2374
+ (0, import_react2.createElement)(
2535
2375
  "div",
2536
2376
  { style: { background: "var(--dsw-alias-bg-layer-1,#fff)", borderRadius: 12, maxWidth: 420, width: "100%", padding: "20px 22px", boxShadow: "0 8px 32px rgba(0,0,0,.18)" } },
2537
- (0, import_react3.createElement)("div", { style: { fontWeight: 600, fontSize: 15, color: lanToggleOpen ? "var(--dsw-alias-brand-primary,#4f6ef7)" : "var(--dsw-alias-state-warn-primary,#b45309)", marginBottom: 10 } }, t(lanToggleOpen ? "lanToggleTitleOn" : "lanToggleTitleOff")),
2538
- (0, import_react3.createElement)("div", { style: { fontSize: 13, lineHeight: 1.7, color: "var(--dsw-alias-label-primary,inherit)" } }, t(lanToggleOpen ? "lanToggleBodyOn" : "lanToggleBodyOff")),
2539
- (0, import_react3.createElement)(
2377
+ (0, import_react2.createElement)("div", { style: { fontWeight: 600, fontSize: 15, color: lanToggleOpen ? "var(--dsw-alias-brand-primary,#4f6ef7)" : "var(--dsw-alias-state-warn-primary,#b45309)", marginBottom: 10 } }, t(lanToggleOpen ? "lanToggleTitleOn" : "lanToggleTitleOff")),
2378
+ (0, import_react2.createElement)("div", { style: { fontSize: 13, lineHeight: 1.7, color: "var(--dsw-alias-label-primary,inherit)" } }, t(lanToggleOpen ? "lanToggleBodyOn" : "lanToggleBodyOff")),
2379
+ (0, import_react2.createElement)(
2540
2380
  "div",
2541
2381
  { style: { display: "flex", gap: 8, marginTop: 16 } },
2542
- (0, import_react3.createElement)("button", { style: { ...styles.btn, flex: 1 }, onClick: () => setLanToggleOpen(null) }, t("cancel")),
2543
- (0, import_react3.createElement)("button", { style: { ...styles.primary, flex: 1 }, onClick: confirmLanToggle }, t("confirm"))
2382
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, flex: 1 }, onClick: () => setLanToggleOpen(null) }, t("cancel")),
2383
+ (0, import_react2.createElement)("button", { style: { ...styles.primary, flex: 1 }, onClick: confirmLanToggle }, t("confirm"))
2544
2384
  )
2545
2385
  )
2546
2386
  ) : null,
2547
2387
  // 安全免责声明弹框(issue #31):每次开启公网访问前确认
2548
- disclaimerOpen ? (0, import_react3.createElement)(
2388
+ disclaimerOpen ? (0, import_react2.createElement)(
2549
2389
  "div",
2550
2390
  { style: { position: "fixed", inset: 0, zIndex: 1e4, background: "rgba(0,0,0,.5)", display: "flex", alignItems: "center", justifyContent: "center", padding: 20 } },
2551
- (0, import_react3.createElement)(
2391
+ (0, import_react2.createElement)(
2552
2392
  "div",
2553
2393
  { style: { background: "var(--dsw-alias-bg-layer-1,#fff)", borderRadius: 12, maxWidth: 420, width: "100%", padding: "20px 22px", boxShadow: "0 8px 32px rgba(0,0,0,.18)" } },
2554
- (0, import_react3.createElement)("div", { style: { fontWeight: 600, fontSize: 15, color: "var(--dsw-alias-state-warn-primary,#b45309)", marginBottom: 10 } }, t("disclaimerTitle")),
2555
- (0, import_react3.createElement)("div", { style: { fontSize: 13, lineHeight: 1.7, color: "var(--dsw-alias-label-primary,inherit)" } }, t("disclaimerBody")),
2556
- (0, import_react3.createElement)(
2394
+ (0, import_react2.createElement)("div", { style: { fontWeight: 600, fontSize: 15, color: "var(--dsw-alias-state-warn-primary,#b45309)", marginBottom: 10 } }, t("disclaimerTitle")),
2395
+ (0, import_react2.createElement)("div", { style: { fontSize: 13, lineHeight: 1.7, color: "var(--dsw-alias-label-primary,inherit)" } }, t("disclaimerBody")),
2396
+ (0, import_react2.createElement)(
2557
2397
  "label",
2558
2398
  { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 14, fontSize: 13, cursor: "pointer" } },
2559
- (0, import_react3.createElement)("input", { type: "checkbox", checked: disclaimerChecked, onChange: (e) => setDisclaimerChecked(e.target.checked), style: { width: 16, height: 16 } }),
2399
+ (0, import_react2.createElement)("input", { type: "checkbox", checked: disclaimerChecked, onChange: (e) => setDisclaimerChecked(e.target.checked), style: { width: 16, height: 16 } }),
2560
2400
  t("disclaimerAgree")
2561
2401
  ),
2562
- (0, import_react3.createElement)(
2402
+ (0, import_react2.createElement)(
2563
2403
  "div",
2564
2404
  { style: { display: "flex", gap: 8, marginTop: 16 } },
2565
- (0, import_react3.createElement)("button", { style: { ...styles.btn, flex: 1 }, onClick: () => setDisclaimerOpen(false) }, t("cancel")),
2566
- (0, import_react3.createElement)("button", {
2405
+ (0, import_react2.createElement)("button", { style: { ...styles.btn, flex: 1 }, onClick: () => setDisclaimerOpen(false) }, t("cancel")),
2406
+ (0, import_react2.createElement)("button", {
2567
2407
  style: { ...styles.primary, flex: 1, opacity: disclaimerChecked ? 1 : 0.5 },
2568
2408
  disabled: !disclaimerChecked,
2569
2409
  onClick: confirmDisclaimer
2570
2410
  }, t("disclaimerAgree"))
2571
2411
  ),
2572
- !disclaimerChecked ? (0, import_react3.createElement)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsw-alias-state-error-primary,#dc2626)" } }, t("disclaimerHint")) : null
2412
+ !disclaimerChecked ? (0, import_react2.createElement)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsw-alias-state-error-primary,#dc2626)" } }, t("disclaimerHint")) : null
2573
2413
  )
2574
2414
  ) : null,
2575
2415
  // 页面最底部:反馈入口
2576
- (0, import_react3.createElement)(
2416
+ (0, import_react2.createElement)(
2577
2417
  "div",
2578
2418
  { style: { ...styles.block, textAlign: "center" } },
2579
- (0, import_react3.createElement)(
2419
+ (0, import_react2.createElement)(
2580
2420
  "a",
2581
2421
  { href: "https://github.com/shaobeichen/dsh-pocket/issues", target: "_blank", rel: "noreferrer", style: { fontSize: 12, color: "var(--dsw-alias-label-secondary,#6b7280)", textDecoration: "none" } },
2582
2422
  t("feedback")