dsh-mishu 0.5.4 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -33,7 +33,7 @@ __export(index_exports, {
33
33
  module.exports = __toCommonJS(index_exports);
34
34
 
35
35
  // src/client/Board.tsx
36
- var import_react3 = require("react");
36
+ var import_react4 = require("react");
37
37
 
38
38
  // src/client/api.ts
39
39
  async function post(path, body) {
@@ -70,6 +70,9 @@ var settingsApi = {
70
70
  testGithub: (lang) => post("/github/test", { lang }),
71
71
  saveToken: (lang, token) => post("/github/token/save", { lang, token }),
72
72
  deleteToken: (lang) => post("/github/token/delete", { lang }),
73
+ deviceStart: (lang) => post("/github/device/start", { lang }),
74
+ deviceStatus: (lang) => post("/github/device/status", { lang }),
75
+ deviceCancel: (lang) => post("/github/device/cancel", { lang }),
73
76
  saveMail: (lang, account, password) => post("/mail/save", { lang, account, password }),
74
77
  testMail: (lang, account, password) => post("/mail/test", { lang, account, password }),
75
78
  deleteMail: (lang, id) => post("/mail/delete", { lang, id }),
@@ -142,6 +145,9 @@ var zh = {
142
145
  restartTip: "\u91CD\u88C5\u6216\u5347\u7EA7\u63D2\u4EF6\u540E\uFF0C\u53EF\u4EE5\u7528\u8FD9\u4E2A\u6309\u952E\u91CD\u542F\u672C DSH",
143
146
  restartConfirm: "\u91CD\u542F DSH\uFF1F\u5B89\u88C5\u63D2\u4EF6\u6216\u8005\u63D2\u4EF6\u66F4\u65B0\u540E\u9700\u8981\u91CD\u542F DSH\u3002",
144
147
  restarting: "\u6B63\u5728\u91CD\u542F\u2026\u7A97\u53E3\u4F1A\u5173\u6389\u518D\u81EA\u52A8\u6253\u5F00",
148
+ restartingWeb: "\u6B63\u5728\u91CD\u542F\u2026\u9875\u9762\u4F1A\u65AD\u5F00\u4E00\u4F1A\u513F\uFF0C\u8FDE\u4E0A\u540E\u81EA\u52A8\u5237\u65B0",
149
+ restartReloading: "\u5DF2\u7ECF\u91CD\u542F\u597D\u4E86\uFF0C\u6B63\u5728\u5237\u65B0\u9875\u9762\u2026",
150
+ restartSlow: "\u4E24\u5206\u949F\u4E86\u8FD8\u6CA1\u8FDE\u4E0A\uFF0C\u8BF7\u624B\u52A8\u5237\u65B0\u9875\u9762\u770B\u770B\u3002",
145
151
  all: "\u5168\u90E8",
146
152
  sourceGithub: "GitHub",
147
153
  sourceMail: "\u90AE\u4EF6",
@@ -159,6 +165,19 @@ var zh = {
159
165
  sTokenGh: "\u7528 GitHub CLI\uFF08gh\uFF09\u767B\u5F55\u7684\u8D26\u53F7\uFF0Ctoken \u5728\u7CFB\u7EDF\u94A5\u5319\u4E32\u91CC",
160
166
  sTokenKeychain: "\u4F60\u5728\u8FD9\u91CC\u586B\u7684 token\uFF0C\u5B58\u5728\u7CFB\u7EDF\u94A5\u5319\u4E32\u91CC",
161
167
  sTokenPaste: "\u586B\u4E00\u4E2A GitHub token",
168
+ gLogin: "\u7528 GitHub \u767B\u5F55",
169
+ gPasteInstead: "\u6216\u8005\u7C98\u8D34\u4E00\u4E2A token",
170
+ gStarting: "\u6B63\u5728\u5411 GitHub \u8981\u767B\u5F55\u7801\u2026",
171
+ gStep1: "1. \u590D\u5236\u8FD9\u4E2A\u767B\u5F55\u7801",
172
+ gCopy: "\u590D\u5236",
173
+ gCopied: "\u5DF2\u590D\u5236",
174
+ gStep2: "2. \u6253\u5F00 GitHub\uFF0C\u7C98\u8D34\u767B\u5F55\u7801\uFF0C\u70B9 Authorize\u3002\u7528\u624B\u673A\u6216\u522B\u7684\u7535\u8111\u6253\u5F00\u4E5F\u884C\u3002",
175
+ gOpen: "\u6253\u5F00 GitHub",
176
+ gWaiting: "\u7B49\u4F60\u5728 GitHub \u4E0A\u6388\u6743\u2026",
177
+ gScopes: "\u4F1A\u8BF7\u6C42\u4E24\u9879\u6743\u9650\uFF1A\u8BFB\u901A\u77E5\uFF08notifications\uFF09\u548C\u4ED3\u5E93\uFF08repo\uFF0C\u67E5\u79C1\u6709\u4ED3\u5E93\u7684 CI\u3001PR \u8981\u7528\uFF1BGitHub \u6CA1\u6709\u53EA\u8BFB\u7684\u7248\u672C\uFF0C\u5C0F\u79D8\u4E66\u53EA\u8BFB\u4E0D\u5199\uFF09\u3002\u62FF\u5230\u7684 token \u53EA\u5B58\u5728\u8FD9\u53F0\u7535\u8111\u4E0A\u3002",
178
+ gDone: (login) => `\u767B\u5F55\u597D\u4E86\uFF0C\u8D26\u53F7 ${login}`,
179
+ gRetry: "\u518D\u8BD5\u4E00\u6B21",
180
+ gClose: "\u5173\u95ED",
162
181
  sTokenHow: "\u7528 classic token\uFF0C\u52FE\u9009 notifications\uFF1B\u8981\u770B\u79C1\u6709\u4ED3\u5E93\u518D\u52FE repo\u3002GitHub \u7684\u901A\u77E5\u63A5\u53E3\u4E0D\u8BA4 fine-grained token\u3002token \u53EA\u5B58\u8FDB\u7CFB\u7EDF\u94A5\u5319\u4E32\uFF0C\u4E0D\u5199\u8FDB\u4EFB\u4F55\u6587\u4EF6\u3002",
163
182
  sTokenNew: "\u53BB GitHub \u751F\u6210\uFF08\u6743\u9650\u5DF2\u52FE\u597D\uFF09",
164
183
  sTokenSave: "\u68C0\u67E5\u5E76\u4FDD\u5B58",
@@ -180,6 +199,7 @@ var zh = {
180
199
  sMail: "\u90AE\u7BB1",
181
200
  sMailPrivacy: "\u53EA\u8BFB\uFF1A\u5C0F\u79D8\u4E66\u7528\u53EA\u8BFB\u65B9\u5F0F\u6253\u5F00\u6536\u4EF6\u7BB1\uFF0C\u53EA\u770B\u53D1\u4EF6\u4EBA\u3001\u6536\u4EF6\u4EBA\u3001\u6807\u9898\u548C\u51E0\u4E2A\u90AE\u4EF6\u5934\uFF0C\u4E0D\u8BFB\u6B63\u6587\uFF0C\u4E5F\u4E0D\u4F1A\u628A\u90AE\u4EF6\u6807\u6210\u5DF2\u8BFB\u3002",
182
201
  sSecretsAt: (kind) => `\u5BC6\u7801\u4FDD\u5B58\u5728\uFF1A${kind}\uFF08\u52A0\u5BC6\u4FDD\u5B58\uFF0C\u4E0D\u5199\u8FDB\u4EFB\u4F55\u6587\u4EF6\uFF09`,
202
+ sSecretsFile: (path, why) => `\u8FD9\u53F0\u7535\u8111\u6CA1\u6709\u53EF\u7528\u7684\u7CFB\u7EDF\u94A5\u5319\u4E32\uFF08${why}\uFF09\uFF0C\u6240\u4EE5\u5BC6\u7801\u548C token \u5B58\u5728 ${path}\u3002\u8FD9\u4E2A\u6587\u4EF6\u53EA\u6709\u4F60\u7684\u7CFB\u7EDF\u8D26\u53F7\u80FD\u8BFB\uFF08\u6743\u9650 600\uFF09\uFF0C\u4F46\u6CA1\u6709\u52A0\u5BC6\uFF1A\u80FD\u767B\u5F55\u4F60\u8FD9\u4E2A\u8D26\u53F7\u7684\u4EBA\u90FD\u80FD\u770B\u5230\u3002`,
183
203
  sSecretsNone: (why) => `\u8FD9\u53F0\u7535\u8111\u4E0A\u6CA1\u6709\u53EF\u7528\u7684\u7CFB\u7EDF\u94A5\u5319\u4E32\uFF1A${why}\u3002\u5BC6\u7801\u4E0D\u4F1A\u88AB\u4FDD\u5B58\uFF1B\u8D26\u6237\u7167\u6837\u80FD\u4FDD\u5B58\uFF0C\u5BC6\u7801\u7528\u73AF\u5883\u53D8\u91CF\u63D0\u4F9B\uFF0C\u53D8\u91CF\u540D\u5199\u5728\u6BCF\u4E2A\u8D26\u6237\u4E0B\u9762\u3002`,
184
204
  sPasswordTestOnly: "\u6CA1\u6709\u94A5\u5319\u4E32\uFF1A\u8FD9\u91CC\u586B\u7684\u53EA\u7528\u6765\u6D4B\u8BD5\u8FDE\u63A5\uFF0C\u4E0D\u4F1A\u4FDD\u5B58",
185
205
  secretKinds: { macos: "macOS \u94A5\u5319\u4E32", windows: "Windows \u51ED\u636E\u7BA1\u7406\u5668", linux: "Linux \u5BC6\u94A5\u73AF\uFF08Secret Service\uFF09", memory: "\u5185\u5B58\uFF08\u6D4B\u8BD5\u7528\uFF09" },
@@ -203,6 +223,15 @@ var zh = {
203
223
  sMailOk: (n) => `\u8FDE\u4E0A\u4E86\uFF0C\u6700\u8FD1\u6709 ${n} \u5C01\u672A\u8BFB\u90AE\u4EF6`,
204
224
  sEnvHint: (name) => `\u6CA1\u6709\u627E\u5230\u5BC6\u7801\u3002\u70B9\u300C\u7F16\u8F91\u300D\u91CD\u65B0\u586B\u4E00\u6B21\uFF1B\u8FD9\u53F0\u7535\u8111\u6CA1\u6709\u94A5\u5319\u4E32\u7684\u8BDD\uFF0C\u5728\u542F\u52A8 DSH \u7684\u73AF\u5883\u91CC\u8BBE\u7F6E ${name}=\u6388\u6743\u7801\uFF0C\u518D\u91CD\u542F DSH\u3002`,
205
225
  sNeverChecked: "\u8FD8\u6CA1\u6536\u8FC7",
226
+ sNoPassword: "\u8FD8\u6CA1\u6709\u8FD9\u4E2A\u90AE\u7BB1\u7684\u5BC6\u7801\uFF08\u6388\u6743\u7801\uFF09\u3002\u70B9\u300C\u7F16\u8F91\u300D\u586B\u4E00\u6B21\u3002",
227
+ mTitleAdd: "\u6DFB\u52A0\u90AE\u7BB1",
228
+ mTitleEdit: "\u7F16\u8F91\u90AE\u7BB1",
229
+ mStepsHelp: "\u7167\u7740\u505A\u8FD8\u662F\u5361\u4F4F\u4E86\uFF1F",
230
+ mTestSave: "\u6D4B\u8BD5\u5E76\u4FDD\u5B58",
231
+ mSaveAnyway: "\u4E0D\u6D4B\u8BD5\uFF0C\u76F4\u63A5\u4FDD\u5B58",
232
+ mMore: "\u66F4\u591A\u8BBE\u7F6E",
233
+ mLength: (label, want, got) => `${label}${/[A-Za-z]$/.test(label) ? " " : ""}\u7684\u6388\u6743\u7801\uFF08\u5E94\u7528\u4E13\u7528\u5BC6\u7801\uFF09\u662F ${want} \u4F4D\uFF0C\u4F60\u586B\u7684\u662F ${got} \u4F4D\uFF0C\u53EF\u80FD\u586B\u6210\u4E86\u767B\u5F55\u5BC6\u7801\u3002`,
234
+ mSavedUnread: (n) => `\u5DF2\u4FDD\u5B58\u3002\u8FDE\u4E0A\u4E86\uFF0C\u6700\u8FD1\u6709 ${n} \u5C01\u672A\u8BFB\u90AE\u4EF6\u3002`,
206
235
  sFeishu: "\u98DE\u4E66",
207
236
  sComing: "\u5373\u5C06\u63A5\u5165",
208
237
  ai: "+AI",
@@ -270,6 +299,9 @@ var en = {
270
299
  restartTip: "After reinstalling or upgrading plugins, use this to restart DSH",
271
300
  restartConfirm: "Restart DSH? DSH needs a restart after you install or update plugins.",
272
301
  restarting: "Restarting\u2026 the window closes and opens again",
302
+ restartingWeb: "Restarting\u2026 the page loses its connection for a moment and reloads once DSH is back",
303
+ restartReloading: "DSH is back; reloading the page\u2026",
304
+ restartSlow: "Still not back after two minutes; reload the page yourself.",
273
305
  all: "All",
274
306
  sourceGithub: "GitHub",
275
307
  sourceMail: "Mail",
@@ -287,6 +319,19 @@ var en = {
287
319
  sTokenGh: "The account the GitHub CLI (gh) is signed in to; the token stays in the system keychain",
288
320
  sTokenKeychain: "The token you pasted here, kept in the system keychain",
289
321
  sTokenPaste: "Paste a GitHub token",
322
+ gLogin: "Sign in with GitHub",
323
+ gPasteInstead: "Or paste a token",
324
+ gStarting: "Asking GitHub for a sign-in code\u2026",
325
+ gStep1: "1. Copy this code",
326
+ gCopy: "Copy",
327
+ gCopied: "Copied",
328
+ gStep2: "2. Open GitHub, paste the code and click Authorize. A phone or another computer works too.",
329
+ gOpen: "Open GitHub",
330
+ gWaiting: "Waiting for you to authorize on GitHub\u2026",
331
+ gScopes: "It asks for two permissions: notifications, and repo (needed for CI runs and pull requests of private repositories; GitHub has no read-only version, and the secretary only reads). The token stays on this computer.",
332
+ gDone: (login) => `Signed in as ${login}`,
333
+ gRetry: "Try again",
334
+ gClose: "Close",
290
335
  sTokenHow: "Use a classic token with the notifications scope, plus repo for private repositories. GitHub's notifications API does not take fine-grained tokens. The token goes to the system keychain only, never to a file.",
291
336
  sTokenNew: "Create one on GitHub (scopes pre-ticked)",
292
337
  sTokenSave: "Check and save",
@@ -308,6 +353,7 @@ var en = {
308
353
  sMail: "Mail",
309
354
  sMailPrivacy: "Read-only: the secretary opens your inbox read-only and looks at sender, recipients, subject and a few headers only. It never reads bodies and never marks mail read.",
310
355
  sSecretsAt: (kind) => `Passwords are kept in: ${kind} (encrypted, never written to a file)`,
356
+ sSecretsFile: (path, why) => `No usable system keychain on this computer (${why}), so passwords and tokens are kept in ${path}. Only your system account can read that file (mode 600), but it is not encrypted: anyone who can sign in as you can read it.`,
311
357
  sSecretsNone: (why) => `No usable system keychain on this computer: ${why}. Passwords are not saved; you can still save accounts and give each password through the environment variable shown under it.`,
312
358
  sPasswordTestOnly: "No keychain: used only to test the connection, not saved",
313
359
  secretKinds: { macos: "the macOS Keychain", windows: "Windows Credential Manager", linux: "the Linux keyring (Secret Service)", memory: "memory (tests)" },
@@ -331,6 +377,15 @@ var en = {
331
377
  sMailOk: (n) => `Connected; ${n} unread messages recently`,
332
378
  sEnvHint: (name) => `No password found. Click Edit and enter it again; if this computer has no keychain, set ${name}=<app password> in the environment DSH starts from, then restart DSH.`,
333
379
  sNeverChecked: "Not checked yet",
380
+ sNoPassword: "No password (app password) for this account yet. Click Edit and enter it.",
381
+ mTitleAdd: "Add a mail account",
382
+ mTitleEdit: "Edit mail account",
383
+ mStepsHelp: "Stuck on a step?",
384
+ mTestSave: "Test and save",
385
+ mSaveAnyway: "Save without testing",
386
+ mMore: "More settings",
387
+ mLength: (label, want, got) => `A ${label} app password is ${want} characters; this one is ${got}. It may be your sign-in password instead.`,
388
+ mSavedUnread: (n) => `Saved. Connected; ${n} unread messages recently.`,
334
389
  sFeishu: "Feishu / Lark",
335
390
  sComing: "Coming soon",
336
391
  ai: "+AI",
@@ -391,19 +446,47 @@ function AskAI({ topic, lang, locale, openChat: openChat2, compact = false }) {
391
446
  }
392
447
 
393
448
  // src/client/Settings.tsx
449
+ var import_react3 = require("react");
450
+
451
+ // src/client/Modal.tsx
394
452
  var import_react2 = require("react");
453
+ var import_react_dom = require("react-dom");
395
454
  var import_jsx_runtime2 = require("react/jsx-runtime");
455
+ function Modal({ title, onClose, children }) {
456
+ (0, import_react2.useEffect)(() => {
457
+ const key = (event) => {
458
+ if (event.key === "Escape") onClose();
459
+ };
460
+ window.addEventListener("keydown", key);
461
+ return () => window.removeEventListener("keydown", key);
462
+ }, [onClose]);
463
+ return (0, import_react_dom.createPortal)(
464
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-modal-backdrop", onMouseDown: (event) => {
465
+ if (event.target === event.currentTarget) onClose();
466
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-modal", role: "dialog", "aria-modal": "true", "aria-label": title, children: [
467
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-modal-head", children: [
468
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: title }),
469
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", "aria-label": "\xD7", onClick: onClose, children: "\xD7" })
470
+ ] }),
471
+ children
472
+ ] }) }),
473
+ document.body
474
+ );
475
+ }
476
+
477
+ // src/client/Settings.tsx
478
+ var import_jsx_runtime3 = require("react/jsx-runtime");
396
479
  var CATEGORIES = ["document", "bill", "birthday", "renewal", "other"];
397
480
  function MishuSettings({ lang, locale, openChat: openChat2 }) {
398
481
  const t = TEXT[lang];
399
- const [view, setView] = (0, import_react2.useState)();
400
- const [error, setError] = (0, import_react2.useState)();
401
- const [note, setNote] = (0, import_react2.useState)();
402
- const [lead, setLead] = (0, import_react2.useState)({});
403
- const [githubTest, setGithubTest] = (0, import_react2.useState)();
404
- const [confirmOn, setConfirmOn] = (0, import_react2.useState)(false);
405
- const [pasting, setPasting] = (0, import_react2.useState)(false);
406
- const [editing, setEditing] = (0, import_react2.useState)();
482
+ const [view, setView] = (0, import_react3.useState)();
483
+ const [error, setError] = (0, import_react3.useState)();
484
+ const [note, setNote] = (0, import_react3.useState)();
485
+ const [lead, setLead] = (0, import_react3.useState)({});
486
+ const [githubTest, setGithubTest] = (0, import_react3.useState)();
487
+ const [confirmOn, setConfirmOn] = (0, import_react3.useState)(false);
488
+ const [pasting, setPasting] = (0, import_react3.useState)(false);
489
+ const [editing, setEditing] = (0, import_react3.useState)();
407
490
  const take = (result, saved) => {
408
491
  if (result.ok) {
409
492
  setView(result.view);
@@ -414,11 +497,11 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
414
497
  setError(result.message);
415
498
  }
416
499
  };
417
- (0, import_react2.useEffect)(() => {
500
+ (0, import_react3.useEffect)(() => {
418
501
  void settingsApi.load(locale()).then((r) => take(r));
419
502
  }, [locale]);
420
503
  if (view === void 0) {
421
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-settings", children: error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-error", children: [
504
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-settings", children: error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-error", children: [
422
505
  t.failed,
423
506
  error
424
507
  ] }) });
@@ -426,95 +509,96 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
426
509
  const save = async (settings) => take(await settingsApi.save(locale(), settings), t.sSaved);
427
510
  const token = view.github.token;
428
511
  const secretKind = t.secretKinds[view.secrets.kind] ?? view.secrets.kind;
429
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-settings", children: [
430
- error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-error", children: [
512
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-settings", children: [
513
+ error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-error", children: [
431
514
  t.failed,
432
515
  error
433
516
  ] }),
434
- note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-ok", children: note }),
435
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
436
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sGeneral }),
437
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
517
+ note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-ok", children: note }),
518
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "mishu-panel", children: [
519
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: t.sGeneral }),
520
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
438
521
  t.sLanguage,
439
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("select", { value: view.settings.language, onChange: (e) => {
522
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: view.settings.language, onChange: (e) => {
440
523
  void save({ language: e.target.value });
441
524
  }, children: [
442
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "auto", children: t.sLanguageAuto }),
443
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }),
444
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "en", children: "English" })
525
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "auto", children: t.sLanguageAuto }),
526
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }),
527
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "en", children: "English" })
445
528
  ] })
446
529
  ] }),
447
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-field", children: t.sLead }),
448
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-grid5", children: CATEGORIES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
530
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-field", children: t.sLead }),
531
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-grid5", children: CATEGORIES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
449
532
  t.categories[c],
450
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", min: 0, max: 366, value: lead[c] ?? 0, onChange: (e) => setLead({ ...lead, [c]: Number(e.target.value) }) })
533
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "number", min: 0, max: 366, value: lead[c] ?? 0, onChange: (e) => setLead({ ...lead, [c]: Number(e.target.value) }) })
451
534
  ] }, c)) }),
452
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
535
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
453
536
  void save({ leadDays: lead });
454
537
  }, children: t.sSave })
455
538
  ] }),
456
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
457
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sGithub }),
458
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-check", children: [
459
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: view.settings.githubEnabled, onChange: (e) => {
539
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "mishu-panel", children: [
540
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: t.sGithub }),
541
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-check", children: [
542
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: view.settings.githubEnabled, onChange: (e) => {
460
543
  void save({ githubEnabled: e.target.checked });
461
544
  } }),
462
545
  t.sGithubOn
463
546
  ] }),
464
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row-explain", children: [
465
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mishu-row-label", children: t.sToken }),
466
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: token.found ? "" : "mishu-danger", children: token.found ? token.from === "env" ? t.sTokenEnv(view.github.tokenEnv) : token.from === "keychain" ? t.sTokenKeychain : t.sTokenGh : token.text })
547
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row-explain", children: [
548
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-row-label", children: t.sToken }),
549
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: token.found ? "" : "mishu-danger", children: token.found ? token.from === "env" ? t.sTokenEnv(view.github.tokenEnv) : token.from === "keychain" ? t.sTokenKeychain : t.sTokenGh : token.text })
467
550
  ] }),
468
- token.found ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
469
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
551
+ token.found ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
552
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
470
553
  setGithubTest(t.sTesting);
471
554
  void settingsApi.testGithub(locale()).then((r) => setGithubTest(r.ok ? t.sGithubOk(r.login) : `${t.failed}${r.message}`));
472
555
  }, children: t.sTest }),
473
- token.from === "env" || pasting ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setPasting(true), children: t.sTokenReplace }),
474
- token.from === "keychain" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
556
+ token.from === "env" || pasting ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setPasting(true), children: t.sTokenReplace }),
557
+ token.from === "keychain" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
475
558
  if (window.confirm(t.sTokenRemoveConfirm)) void settingsApi.deleteToken(locale()).then((r) => {
476
559
  setGithubTest(void 0);
477
560
  take(r);
478
561
  });
479
562
  }, children: t.sTokenRemove }) : null,
480
- githubTest === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mishu-hint", children: githubTest })
563
+ githubTest === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-hint", children: githubTest })
481
564
  ] }) : null,
482
- !token.found || pasting ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TokenForm, { view, lang, locale, onSaved: (next, login) => {
565
+ !token.found || pasting ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GithubConnect, { view, lang, locale, onSaved: (next, login) => {
483
566
  setPasting(false);
484
567
  setGithubTest(t.sTokenSaved(login));
485
568
  take({ ok: true, view: next });
486
569
  }, onCancel: token.found ? () => setPasting(false) : void 0 }) : null,
487
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
570
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
488
571
  t.sMarkRead,
489
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("select", { value: view.settings.markRead, onChange: (e) => {
572
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: view.settings.markRead, onChange: (e) => {
490
573
  const value = e.target.value;
491
574
  if (value === "on") setConfirmOn(true);
492
575
  else void save({ markRead: value });
493
576
  }, children: [
494
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "off", children: t.sMarkOff }),
495
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "shadow", children: t.sMarkShadow }),
496
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "on", children: t.sMarkOn })
577
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "off", children: t.sMarkOff }),
578
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "shadow", children: t.sMarkShadow }),
579
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "on", children: t.sMarkOn })
497
580
  ] })
498
581
  ] }),
499
- confirmOn ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-banner", children: [
500
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: t.sMarkConfirm }),
501
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
502
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
582
+ confirmOn ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-banner", children: [
583
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: t.sMarkConfirm }),
584
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
585
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
503
586
  setConfirmOn(false);
504
587
  void save({ markRead: "on" });
505
588
  }, children: t.sConfirm }),
506
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setConfirmOn(false), children: t.sCancel })
589
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setConfirmOn(false), children: t.sCancel })
507
590
  ] })
508
591
  ] }) : null
509
592
  ] }),
510
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
511
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sMail }),
512
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-hint", children: t.sMailPrivacy }),
513
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: view.secrets.available ? "mishu-hint" : "mishu-hint mishu-warn", children: view.secrets.available ? t.sSecretsAt(secretKind) : t.sSecretsNone(view.secrets.why ?? secretKind) }),
514
- view.accounts.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-empty", children: t.sNoAccounts }) : view.accounts.map((account) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
593
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "mishu-panel", children: [
594
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: t.sMail }),
595
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.sMailPrivacy }),
596
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: view.secrets.available && view.secrets.file === void 0 ? "mishu-hint" : "mishu-hint mishu-warn", children: !view.secrets.available ? t.sSecretsNone(view.secrets.why ?? secretKind) : view.secrets.file !== void 0 ? t.sSecretsFile(view.secrets.file.path, view.secrets.file.why) : t.sSecretsAt(secretKind) }),
597
+ view.accounts.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-empty", children: t.sNoAccounts }) : view.accounts.map((account) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
515
598
  AccountRow,
516
599
  {
517
600
  account,
601
+ secretsOk: view.secrets.available,
518
602
  lang,
519
603
  locale,
520
604
  openChat: openChat2,
@@ -523,24 +607,133 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
523
607
  },
524
608
  account.id
525
609
  )),
526
- editing === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setEditing({ preset: "qq", sinceDays: 14, enabled: true }), children: t.sAddAccount }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AccountForm, { draft: editing, view, lang, locale, openChat: openChat2, onDone: (next) => {
527
- setEditing(void 0);
528
- if (next !== void 0) take({ ok: true, view: next }, t.sSaved);
529
- } })
610
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setEditing({ preset: "custom", sinceDays: 14, enabled: true }), children: t.sAddAccount }),
611
+ editing === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
612
+ MailDialog,
613
+ {
614
+ draft: editing,
615
+ view,
616
+ lang,
617
+ locale,
618
+ openChat: openChat2,
619
+ onDone: (next, note2) => {
620
+ setEditing(void 0);
621
+ if (next !== void 0) take({ ok: true, view: next }, note2 ?? t.sSaved);
622
+ }
623
+ }
624
+ )
530
625
  ] }),
531
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
532
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sFeishu }),
533
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-hint", children: t.sComing })
626
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "mishu-panel", children: [
627
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: t.sFeishu }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.sComing })
534
629
  ] })
535
630
  ] });
536
631
  }
632
+ function GithubConnect({ view, lang, locale, onSaved, onCancel }) {
633
+ const t = TEXT[lang];
634
+ const [signingIn, setSigningIn] = (0, import_react3.useState)(false);
635
+ const [paste, setPaste] = (0, import_react3.useState)(!view.github.deviceLogin);
636
+ if (!view.github.deviceLogin) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TokenForm, { view, lang, locale, onSaved, onCancel });
637
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
638
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
639
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => setSigningIn(true), children: t.gLogin }),
640
+ paste ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => setPaste(true), children: t.gPasteInstead }),
641
+ onCancel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: onCancel, children: t.sCancel })
642
+ ] }),
643
+ paste ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TokenForm, { view, lang, locale, onSaved, onCancel: void 0 }) : null,
644
+ signingIn ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GithubLoginDialog, { lang, locale, onClose: () => setSigningIn(false), onSaved: (next, login) => {
645
+ setSigningIn(false);
646
+ onSaved(next, login);
647
+ } }) : null
648
+ ] });
649
+ }
650
+ function GithubLoginDialog({ lang, locale, onClose, onSaved }) {
651
+ const t = TEXT[lang];
652
+ const [login, setLogin] = (0, import_react3.useState)();
653
+ const [error, setError] = (0, import_react3.useState)();
654
+ const [copied, setCopied] = (0, import_react3.useState)(false);
655
+ const [attempt, setAttempt] = (0, import_react3.useState)(0);
656
+ const saved = (0, import_react3.useRef)(void 0);
657
+ (0, import_react3.useEffect)(() => {
658
+ let alive = true;
659
+ let timer;
660
+ setLogin(void 0);
661
+ setError(void 0);
662
+ const poll = async () => {
663
+ const r = await settingsApi.deviceStatus(locale());
664
+ if (!alive) return;
665
+ if (!r.ok) {
666
+ setError(r.message);
667
+ return;
668
+ }
669
+ setLogin(r.login);
670
+ if (r.login.state === "done" && r.view !== void 0) saved.current = { view: r.view, login: r.login.login };
671
+ else if (r.login.state === "waiting") timer = setTimeout(() => {
672
+ void poll();
673
+ }, 2e3);
674
+ };
675
+ void settingsApi.deviceStart(locale()).then((r) => {
676
+ if (!alive) return;
677
+ if (!r.ok) {
678
+ setError(r.message);
679
+ return;
680
+ }
681
+ setLogin(r.login);
682
+ timer = setTimeout(() => {
683
+ void poll();
684
+ }, 2e3);
685
+ });
686
+ return () => {
687
+ alive = false;
688
+ if (timer !== void 0) clearTimeout(timer);
689
+ };
690
+ }, [attempt, locale]);
691
+ const close = () => {
692
+ if (saved.current !== void 0) onSaved(saved.current.view, saved.current.login);
693
+ else {
694
+ void settingsApi.deviceCancel(locale());
695
+ onClose();
696
+ }
697
+ };
698
+ const copy2 = (code) => {
699
+ void navigator.clipboard?.writeText(code).then(() => setCopied(true), () => setCopied(false));
700
+ };
701
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Modal, { title: t.gLogin, onClose: close, children: error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
702
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-preview mishu-danger", children: error }),
703
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-actions", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: close, children: t.gClose }) })
704
+ ] }) : login === void 0 || login.state === "idle" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.gStarting }) : login.state === "waiting" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
705
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-field", children: t.gStep1 }),
706
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-code-row", children: [
707
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { className: "mishu-code", children: login.userCode }),
708
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => copy2(login.userCode), children: copied ? t.gCopied : t.gCopy })
709
+ ] }),
710
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-field", children: t.gStep2 }),
711
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
712
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => window.open(login.verificationUri, "_blank", "noopener"), children: t.gOpen }),
713
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-hint", children: t.gWaiting })
714
+ ] }),
715
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.gScopes })
716
+ ] }) : login.state === "done" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
717
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-ok", children: t.gDone(login.login) }),
718
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-actions", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: close, children: t.gClose }) })
719
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
720
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-preview mishu-danger", children: login.message }),
721
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
722
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
723
+ setCopied(false);
724
+ setAttempt(attempt + 1);
725
+ }, children: t.gRetry }),
726
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: close, children: t.gClose })
727
+ ] })
728
+ ] }) });
729
+ }
537
730
  function TokenForm({ view, lang, locale, onSaved, onCancel }) {
538
731
  const t = TEXT[lang];
539
- const [token, setToken] = (0, import_react2.useState)("");
540
- const [busy, setBusy] = (0, import_react2.useState)(false);
541
- const [message, setMessage] = (0, import_react2.useState)();
732
+ const [token, setToken] = (0, import_react3.useState)("");
733
+ const [busy, setBusy] = (0, import_react3.useState)(false);
734
+ const [message, setMessage] = (0, import_react3.useState)();
542
735
  if (!view.secrets.available) {
543
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sTokenNoKeychain(view.github.tokenEnv, view.secrets.why ?? "") });
736
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sTokenNoKeychain(view.github.tokenEnv, view.secrets.why ?? "") });
544
737
  }
545
738
  const save = async () => {
546
739
  setBusy(true);
@@ -554,162 +747,191 @@ function TokenForm({ view, lang, locale, onSaved, onCancel }) {
554
747
  setMessage(r.message);
555
748
  }
556
749
  };
557
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-add", children: [
558
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
750
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-add", children: [
751
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
559
752
  t.sTokenPaste,
560
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "password", value: token, autoComplete: "off", spellCheck: false, placeholder: "ghp_\u2026", onChange: (e) => {
753
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "password", value: token, autoComplete: "off", spellCheck: false, placeholder: "ghp_\u2026", onChange: (e) => {
561
754
  setToken(e.target.value);
562
755
  setMessage(void 0);
563
756
  } })
564
757
  ] }),
565
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-hint", children: t.sTokenHow }),
566
- message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-preview mishu-danger", children: message }),
567
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
568
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => window.open(view.github.newTokenUrl, "_blank", "noopener"), children: t.sTokenNew }),
569
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || token.trim() === "", onClick: () => {
758
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.sTokenHow }),
759
+ message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-preview mishu-danger", children: message }),
760
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
761
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => window.open(view.github.newTokenUrl, "_blank", "noopener"), children: t.sTokenNew }),
762
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || token.trim() === "", onClick: () => {
570
763
  void save();
571
764
  }, children: busy ? t.sTesting : t.sTokenSave }),
572
- onCancel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: onCancel, children: t.sCancel })
765
+ onCancel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: onCancel, children: t.sCancel })
573
766
  ] })
574
767
  ] });
575
768
  }
576
- function AccountRow({ account, lang, locale, openChat: openChat2, onEdit, onView }) {
769
+ function AccountRow({ account, secretsOk, lang, locale, openChat: openChat2, onEdit, onView }) {
577
770
  const t = TEXT[lang];
578
- const [busy, setBusy] = (0, import_react2.useState)(false);
771
+ const [busy, setBusy] = (0, import_react3.useState)(false);
579
772
  const report = account.report;
580
- const status = report === null ? t.sNeverChecked : report.error !== void 0 ? report.error[lang] : lang === "zh" ? `${new Date(report.at).toLocaleString()} \u6536\u4FE1\uFF0C${report.messages} \u5C01\u672A\u8BFB` : `checked ${new Date(report.at).toLocaleString()}, ${report.messages} unread`;
581
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-card", children: [
582
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-card-title", children: [
773
+ const status = !account.hasPassword ? secretsOk ? t.sNoPassword : t.sEnvHint(account.envName) : report === null ? t.sNeverChecked : report.error !== void 0 ? report.error[lang] : lang === "zh" ? `${new Date(report.at).toLocaleString()} \u6536\u4FE1\uFF0C${report.messages} \u5C01\u672A\u8BFB` : `checked ${new Date(report.at).toLocaleString()}, ${report.messages} unread`;
774
+ const failed = !account.hasPassword || report?.error !== void 0;
775
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-card", children: [
776
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-card-title", children: [
583
777
  account.label,
584
778
  account.enabled ? "" : ` (${lang === "zh" ? "\u5DF2\u505C\u7528" : "disabled"})`
585
779
  ] }),
586
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-card-meta", children: [
780
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-card-meta", children: [
587
781
  account.address,
588
782
  " \xB7 ",
589
783
  account.host,
590
784
  ":",
591
785
  account.port
592
786
  ] }),
593
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `mishu-card-note ${report?.error === void 0 ? "" : "mishu-danger"}`, children: [
787
+ account.mismatch === null ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-card-note mishu-warn", children: account.mismatch }),
788
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `mishu-card-note ${failed ? "mishu-danger" : ""}`, children: [
594
789
  status,
595
- report?.error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AskAI, { topic: { kind: "mail-error", accountId: account.id }, lang, locale, openChat: openChat2, compact: true })
790
+ account.hasPassword && report?.error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "mail-error", accountId: account.id }, lang, locale, openChat: openChat2, compact: true }) : null
596
791
  ] }),
597
- account.hasPassword ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-card-note mishu-warn", children: t.sEnvHint(account.envName) }),
598
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
599
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy, onClick: () => {
792
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
793
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy || !account.hasPassword, onClick: () => {
600
794
  setBusy(true);
601
795
  void settingsApi.syncMail(locale(), account.id).then((r) => {
602
796
  setBusy(false);
603
797
  onView(r);
604
798
  });
605
799
  }, children: busy ? t.sTesting : t.sCheckNow }),
606
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: onEdit, children: t.sEdit }),
607
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
800
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: account.hasPassword && account.mismatch === null ? "mishu-btn" : "mishu-btn primary", onClick: onEdit, children: t.sEdit }),
801
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
608
802
  if (window.confirm(t.sDeleteConfirm)) void settingsApi.deleteMail(locale(), account.id).then(onView);
609
803
  }, children: t.sDelete })
610
804
  ] })
611
805
  ] });
612
806
  }
613
- function AccountForm({ draft, view, lang, locale, openChat: openChat2, onDone }) {
807
+ function MailDialog({ draft, view, lang, locale, openChat: openChat2, onDone }) {
614
808
  const t = TEXT[lang];
615
- const [account, setAccount] = (0, import_react2.useState)(draft);
616
- const [password, setPassword] = (0, import_react2.useState)("");
617
- const [message, setMessage] = (0, import_react2.useState)();
618
- const [busy, setBusy] = (0, import_react2.useState)(false);
809
+ const existing = draft.id !== void 0;
810
+ const [account, setAccount] = (0, import_react3.useState)(draft);
811
+ const [picked, setPicked] = (0, import_react3.useState)(existing);
812
+ const [password, setPassword] = (0, import_react3.useState)("");
813
+ const [message, setMessage] = (0, import_react3.useState)();
814
+ const [failedTest, setFailedTest] = (0, import_react3.useState)(false);
815
+ const [busy, setBusy] = (0, import_react3.useState)(false);
619
816
  const preset = view.presets.find((p) => p.id === account.preset) ?? view.presets[view.presets.length - 1];
620
817
  const custom = preset.id === "custom";
621
- const existing = draft.id !== void 0;
622
818
  const set = (patch) => {
623
819
  setAccount({ ...account, ...patch });
624
820
  setMessage(void 0);
821
+ setFailedTest(false);
625
822
  };
626
- const test = async () => {
627
- setBusy(true);
628
- setMessage({ ok: true, text: t.sTesting });
629
- const r = await settingsApi.testMail(locale(), account, password);
630
- setBusy(false);
631
- setMessage(r.ok ? { ok: true, text: t.sMailOk(r.unread) } : { ok: false, text: r.message });
823
+ const setAddress = (address) => {
824
+ const domain = address.trim().toLowerCase().split("@")[1] ?? "";
825
+ const known = view.presets.find((p) => p.domains.includes(domain));
826
+ set({ address, ...picked ? {} : known !== void 0 ? { preset: known.id } : domain.includes(".") ? { preset: "custom" } : {} });
632
827
  };
633
- const save = async () => {
634
- setBusy(true);
828
+ const typed = password.replace(/\s+/g, "");
829
+ const lengthOff = preset.passwordLength !== null && typed !== "" && typed.length !== preset.passwordLength;
830
+ const save = async (unread) => {
635
831
  const r = await settingsApi.saveMail(locale(), account, password);
636
832
  setBusy(false);
833
+ if (r.ok) onDone(r.view, unread === void 0 ? void 0 : t.mSavedUnread(unread));
834
+ else setMessage({ ok: false, text: r.message });
835
+ };
836
+ const testAndSave = async () => {
837
+ setBusy(true);
838
+ setMessage({ ok: true, text: t.sTesting });
839
+ const r = await settingsApi.testMail(locale(), account, password);
637
840
  if (r.ok) {
638
- setPassword("");
639
- onDone(r.view);
841
+ await save(r.unread);
640
842
  } else {
843
+ setBusy(false);
844
+ setFailedTest(true);
641
845
  setMessage({ ok: false, text: r.message });
642
846
  }
643
847
  };
644
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-add", children: [
645
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
646
- t.sProvider,
647
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("select", { value: account.preset, onChange: (e) => set({ preset: e.target.value }), children: view.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: p.id, children: p.label }, p.id)) })
648
- ] }),
649
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: preset.supported ? "mishu-hint" : "mishu-hint mishu-danger", children: [
650
- preset.howTo,
651
- preset.supported ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id }, lang, locale, openChat: openChat2, compact: true }) : null
652
- ] }),
653
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
848
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Modal, { title: existing ? t.mTitleEdit : t.mTitleAdd, onClose: () => onDone(), children: [
849
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
654
850
  t.sAddress,
655
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "email", value: account.address ?? "", autoComplete: "off", onChange: (e) => set({ address: e.target.value }) })
851
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "email", value: account.address ?? "", autoComplete: "off", autoFocus: !existing, onChange: (e) => setAddress(e.target.value) })
656
852
  ] }),
657
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row", children: [
658
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
659
- t.sLabel,
660
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: account.label ?? "", onChange: (e) => set({ label: e.target.value }) })
661
- ] }),
662
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
663
- t.sUser,
664
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: account.user ?? "", placeholder: account.address ?? "", autoComplete: "off", onChange: (e) => set({ user: e.target.value }) })
665
- ] })
853
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
854
+ t.sProvider,
855
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("select", { value: account.preset, onChange: (e) => {
856
+ setPicked(true);
857
+ set({ preset: e.target.value });
858
+ }, children: view.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: p.id, children: p.label }, p.id)) })
666
859
  ] }),
667
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
860
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `mishu-steps${preset.supported ? "" : " mishu-danger"}${failedTest ? " attention" : ""}`, children: [
861
+ preset.steps.length === 0 ? preset.howTo : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ol", { children: preset.steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
862
+ step.text,
863
+ step.link === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
864
+ " ",
865
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => window.open(step.link.url, "_blank", "noopener"), children: step.link.label })
866
+ ] })
867
+ ] }, i)) }),
868
+ preset.supported ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-steps-help", children: [
869
+ t.mStepsHelp,
870
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id }, lang, locale, openChat: openChat2, compact: true })
871
+ ] }) : null
872
+ ] }),
873
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
668
874
  t.sPassword,
669
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "password", value: password, autoComplete: "new-password", placeholder: existing && view.secrets.available ? t.sPasswordKeep : "", onChange: (e) => {
875
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "password", value: password, autoComplete: "new-password", placeholder: existing && view.secrets.available ? t.sPasswordKeep : "", onChange: (e) => {
670
876
  setPassword(e.target.value);
671
877
  setMessage(void 0);
878
+ setFailedTest(false);
672
879
  } })
673
880
  ] }),
674
- view.secrets.available ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sPasswordTestOnly }),
675
- custom ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row", children: [
676
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
881
+ lengthOff ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint mishu-warn", children: t.mLength(preset.label, preset.passwordLength, typed.length) }) : null,
882
+ view.secrets.available ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sPasswordTestOnly }),
883
+ custom ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row", children: [
884
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
677
885
  t.sHost,
678
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: account.host ?? "", onChange: (e) => set({ host: e.target.value }) })
886
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: account.host ?? "", placeholder: "imap.example.com", onChange: (e) => set({ host: e.target.value }) })
679
887
  ] }),
680
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
888
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
681
889
  t.sPort,
682
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", value: account.port ?? 993, onChange: (e) => set({ port: Number(e.target.value) }) })
890
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "number", value: account.port ?? 993, onChange: (e) => set({ port: Number(e.target.value) }) })
683
891
  ] })
684
892
  ] }) : null,
685
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row", children: [
686
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
687
- t.sSince,
688
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", min: 1, max: 90, value: account.sinceDays ?? 14, onChange: (e) => set({ sinceDays: Number(e.target.value) }) })
893
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("details", { className: "mishu-more", children: [
894
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("summary", { children: t.mMore }),
895
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row", children: [
896
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
897
+ t.sLabel,
898
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: account.label ?? "", placeholder: account.address ?? "", onChange: (e) => set({ label: e.target.value }) })
899
+ ] }),
900
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
901
+ t.sUser,
902
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: account.user ?? "", placeholder: account.address ?? "", autoComplete: "off", onChange: (e) => set({ user: e.target.value }) })
903
+ ] })
689
904
  ] }),
690
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-check", children: [
691
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: account.enabled !== false, onChange: (e) => set({ enabled: e.target.checked }) }),
692
- t.sEnabled
905
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row", children: [
906
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
907
+ t.sSince,
908
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "number", min: 1, max: 90, value: account.sinceDays ?? 14, onChange: (e) => set({ sinceDays: Number(e.target.value) }) })
909
+ ] }),
910
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-check", children: [
911
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: account.enabled !== false, onChange: (e) => set({ enabled: e.target.checked }) }),
912
+ t.sEnabled
913
+ ] })
693
914
  ] })
694
915
  ] }),
695
- message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `mishu-preview ${message.ok ? "" : "mishu-danger"}`, children: [
916
+ message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `mishu-preview ${message.ok ? "" : "mishu-danger"}`, children: [
696
917
  message.text,
697
- message.ok || !preset.supported ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id, error: message.text }, lang, locale, openChat: openChat2, compact: true })
918
+ message.ok || !preset.supported ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id, error: message.text }, lang, locale, openChat: openChat2, compact: true })
698
919
  ] }),
699
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
700
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy || !preset.supported, onClick: () => {
701
- void test();
702
- }, children: t.sTest }),
703
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || !preset.supported, onClick: () => {
920
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
921
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || !preset.supported || (account.address ?? "") === "", onClick: () => {
922
+ void testAndSave();
923
+ }, children: busy ? t.sTesting : t.mTestSave }),
924
+ failedTest ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", disabled: busy, onClick: () => {
925
+ setBusy(true);
704
926
  void save();
705
- }, children: t.sSave }),
706
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
927
+ }, children: t.mSaveAnyway }) : null,
928
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
707
929
  ] })
708
930
  ] });
709
931
  }
710
932
 
711
933
  // src/client/Board.tsx
712
- var import_jsx_runtime3 = require("react/jsx-runtime");
934
+ var import_jsx_runtime4 = require("react/jsx-runtime");
713
935
  var SOURCE_KEY = "dsh-mishu.source";
714
936
  function loadSource() {
715
937
  try {
@@ -745,14 +967,14 @@ function saveWidths(widths) {
745
967
  }
746
968
  }
747
969
  function MishuBoard({ locale, openChat: openChat2 }) {
748
- const [board, setBoard] = (0, import_react3.useState)();
749
- const [error, setError] = (0, import_react3.useState)();
750
- const [busy, setBusy] = (0, import_react3.useState)(false);
751
- const [syncing, setSyncing] = (0, import_react3.useState)(false);
752
- const [dropOn, setDropOn] = (0, import_react3.useState)();
753
- const [widths, setWidths] = (0, import_react3.useState)(loadWidths);
754
- const [tab, setTab] = (0, import_react3.useState)("board");
755
- const [source, setSourceState] = (0, import_react3.useState)(loadSource);
970
+ const [board, setBoard] = (0, import_react4.useState)();
971
+ const [error, setError] = (0, import_react4.useState)();
972
+ const [busy, setBusy] = (0, import_react4.useState)(false);
973
+ const [syncing, setSyncing] = (0, import_react4.useState)(false);
974
+ const [dropOn, setDropOn] = (0, import_react4.useState)();
975
+ const [widths, setWidths] = (0, import_react4.useState)(loadWidths);
976
+ const [tab, setTab] = (0, import_react4.useState)("board");
977
+ const [source, setSourceState] = (0, import_react4.useState)(loadSource);
756
978
  const setSource = (next) => {
757
979
  setSourceState(next);
758
980
  try {
@@ -760,11 +982,11 @@ function MishuBoard({ locale, openChat: openChat2 }) {
760
982
  } catch {
761
983
  }
762
984
  };
763
- const dragged = (0, import_react3.useRef)(void 0);
764
- const columnsRef = (0, import_react3.useRef)(null);
985
+ const dragged = (0, import_react4.useRef)(void 0);
986
+ const columnsRef = (0, import_react4.useRef)(null);
765
987
  const lang = board?.lang ?? uiLang(locale());
766
988
  const t = TEXT[lang];
767
- const take = (0, import_react3.useCallback)((result) => {
989
+ const take = (0, import_react4.useCallback)((result) => {
768
990
  if (result.ok) {
769
991
  setBoard(result.board);
770
992
  setError(void 0);
@@ -772,8 +994,8 @@ function MishuBoard({ locale, openChat: openChat2 }) {
772
994
  setError(result.message);
773
995
  }
774
996
  }, []);
775
- const load = (0, import_react3.useCallback)(() => mishuApi.board(locale()).then(take), [locale, take]);
776
- (0, import_react3.useEffect)(() => {
997
+ const load = (0, import_react4.useCallback)(() => mishuApi.board(locale()).then(take), [locale, take]);
998
+ (0, import_react4.useEffect)(() => {
777
999
  void load();
778
1000
  const timer = setInterval(() => {
779
1001
  void load();
@@ -863,7 +1085,7 @@ function MishuBoard({ locale, openChat: openChat2 }) {
863
1085
  reopen: t.reopen,
864
1086
  stop: t.stop
865
1087
  };
866
- const card = (item, column) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1088
+ const card = (item, column) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
867
1089
  Card,
868
1090
  {
869
1091
  item,
@@ -887,12 +1109,12 @@ function MishuBoard({ locale, openChat: openChat2 }) {
887
1109
  `${item.target}-${item.id}`
888
1110
  );
889
1111
  if (board === void 0) {
890
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-page", children: [
891
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-head", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-title", children: [
892
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: t.title }),
893
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RestartButton, { lang, locale })
1112
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-page", children: [
1113
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-head", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-title", children: [
1114
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { children: t.title }),
1115
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RestartButton, { lang, locale })
894
1116
  ] }) }),
895
- error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-error", children: [
1117
+ error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-error", children: [
896
1118
  t.failed,
897
1119
  error
898
1120
  ] })
@@ -917,7 +1139,7 @@ function MishuBoard({ locale, openChat: openChat2 }) {
917
1139
  { id: "manual", label: t.sourceManual }
918
1140
  ];
919
1141
  const template = `minmax(0, ${widths[0]}fr) 10px minmax(0, ${widths[1]}fr) 10px minmax(0, ${widths[2]}fr)`;
920
- const divider = (index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1142
+ const divider = (index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
921
1143
  "div",
922
1144
  {
923
1145
  className: "mishu-divider",
@@ -928,107 +1150,107 @@ function MishuBoard({ locale, openChat: openChat2 }) {
928
1150
  onDoubleClick: resetWidths
929
1151
  }
930
1152
  );
931
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-page", "data-mishu-board": "", children: [
932
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-head", children: [
933
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-title", children: [
934
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: t.title }),
935
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-tabs", role: "tablist", children: [
936
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "board", className: tab === "board" ? "active" : "", onClick: () => setTab("board"), children: t.tabBoard }),
937
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "settings", className: tab === "settings" ? "active" : "", onClick: () => setTab("settings"), children: t.tabSettings })
1153
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-page", "data-mishu-board": "", children: [
1154
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-head", children: [
1155
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-title", children: [
1156
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { children: t.title }),
1157
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-tabs", role: "tablist", children: [
1158
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "board", className: tab === "board" ? "active" : "", onClick: () => setTab("board"), children: t.tabBoard }),
1159
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "settings", className: tab === "settings" ? "active" : "", onClick: () => setTab("settings"), children: t.tabSettings })
938
1160
  ] }),
939
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RestartButton, { lang, locale })
1161
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RestartButton, { lang, locale })
940
1162
  ] }),
941
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-sources", children: [
942
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
943
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: `mishu-dot ${board.sources.github.state}` }),
1163
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-sources", children: [
1164
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
1165
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("i", { className: `mishu-dot ${board.sources.github.state}` }),
944
1166
  board.sources.github.text,
945
- board.sources.github.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "github-error" }, lang, locale, openChat: openChat2, compact: true }) : null
1167
+ board.sources.github.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: { kind: "github-error" }, lang, locale, openChat: openChat2, compact: true }) : null
946
1168
  ] }),
947
- board.sources.mail.map((m) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
948
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: `mishu-dot ${m.state}` }),
1169
+ board.sources.mail.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
1170
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("i", { className: `mishu-dot ${m.state}` }),
949
1171
  m.text,
950
- m.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "mail-error", accountId: m.id }, lang, locale, openChat: openChat2, compact: true }) : null
1172
+ m.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: { kind: "mail-error", accountId: m.id }, lang, locale, openChat: openChat2, compact: true }) : null
951
1173
  ] }, m.id)),
952
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", disabled: syncing, onClick: () => {
1174
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", disabled: syncing, onClick: () => {
953
1175
  void sync();
954
1176
  }, children: syncing ? t.syncing : t.sync })
955
1177
  ] })
956
1178
  ] }),
957
- tab === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MishuSettings, { lang, locale, openChat: openChat2 }) : null,
958
- tab === "settings" ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
959
- error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-error", children: [
1179
+ tab === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MishuSettings, { lang, locale, openChat: openChat2 }) : null,
1180
+ tab === "settings" ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1181
+ error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-error", children: [
960
1182
  t.failed,
961
1183
  error
962
1184
  ] }),
963
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "mishu-summary", children: [
1185
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mishu-summary", children: [
964
1186
  board.summary,
965
1187
  " ",
966
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "summary" }, lang, locale, openChat: openChat2, compact: true })
1188
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: { kind: "summary" }, lang, locale, openChat: openChat2, compact: true })
967
1189
  ] }),
968
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metrics", children: [
969
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
970
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricHandle }),
971
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric-value", children: [
1190
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-metrics", children: [
1191
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-metric", children: [
1192
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-metric-label", children: t.metricHandle }),
1193
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-metric-value", children: [
972
1194
  metrics.handle,
973
- metrics.overdue > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("small", { className: "mishu-danger", children: [
1195
+ metrics.overdue > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { className: "mishu-danger", children: [
974
1196
  metrics.overdue,
975
1197
  " ",
976
1198
  t.metricOverdue
977
1199
  ] }) : null
978
1200
  ] })
979
1201
  ] }),
980
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
981
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricSoon }),
982
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-value", children: metrics.dueSoon })
1202
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-metric", children: [
1203
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-metric-label", children: t.metricSoon }),
1204
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-metric-value", children: metrics.dueSoon })
983
1205
  ] }),
984
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
985
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricClosed }),
986
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-value", children: metrics.closedToday })
1206
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-metric", children: [
1207
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-metric-label", children: t.metricClosed }),
1208
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-metric-value", children: metrics.closedToday })
987
1209
  ] }),
988
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
989
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricShadow }),
990
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric-value", children: [
1210
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-metric", children: [
1211
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-metric-label", children: t.metricShadow }),
1212
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-metric-value", children: [
991
1213
  metrics.shadow,
992
- board.markRead === "shadow" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { className: "mishu-warn", children: t.shadowTag }) : null
1214
+ board.markRead === "shadow" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { className: "mishu-warn", children: t.shadowTag }) : null
993
1215
  ] })
994
1216
  ] })
995
1217
  ] }),
996
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-filters", role: "group", children: sources.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", "aria-pressed": source === s.id, className: `mishu-chip ${source === s.id ? "active" : ""}`, onClick: () => setSource(s.id), children: [
1218
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-filters", role: "group", children: sources.map((s) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", "aria-pressed": source === s.id, className: `mishu-chip ${source === s.id ? "active" : ""}`, onClick: () => setSource(s.id), children: [
997
1219
  s.label,
998
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: count(s.id) })
1220
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: count(s.id) })
999
1221
  ] }, s.id)) }),
1000
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-columns", ref: columnsRef, style: { ["--mishu-cols"]: template }, children: [
1001
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: `mishu-col ${dropOn === "handle" ? "drop" : ""}`, ...dropProps("handle"), "aria-label": t.handle, children: [
1002
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-col-head", children: [
1222
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-columns", ref: columnsRef, style: { ["--mishu-cols"]: template }, children: [
1223
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: `mishu-col ${dropOn === "handle" ? "drop" : ""}`, ...dropProps("handle"), "aria-label": t.handle, children: [
1224
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-col-head", children: [
1003
1225
  t.handle,
1004
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: columns.handle.length })
1226
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: columns.handle.length })
1005
1227
  ] }),
1006
- columns.handle.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.emptyHandle }) : columns.handle.map((item) => card(item, "handle"))
1228
+ columns.handle.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-empty", children: t.emptyHandle }) : columns.handle.map((item) => card(item, "handle"))
1007
1229
  ] }),
1008
1230
  divider(0),
1009
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: `mishu-col ${dropOn === "remember" ? "drop" : ""}`, ...dropProps("remember"), "aria-label": t.remember, title: t.dropRemember, children: [
1010
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-col-head", children: [
1231
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: `mishu-col ${dropOn === "remember" ? "drop" : ""}`, ...dropProps("remember"), "aria-label": t.remember, title: t.dropRemember, children: [
1232
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-col-head", children: [
1011
1233
  t.remember,
1012
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: columns.remember.length })
1234
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: columns.remember.length })
1013
1235
  ] }),
1014
- columns.remember.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.emptyRemember }) : columns.remember.map((item) => card(item, "remember")),
1015
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AddForm, { lang, locale, onAdded: (next) => setBoard(next) })
1236
+ columns.remember.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-empty", children: t.emptyRemember }) : columns.remember.map((item) => card(item, "remember")),
1237
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AddForm, { lang, locale, onAdded: (next) => setBoard(next) })
1016
1238
  ] }),
1017
1239
  divider(1),
1018
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: `mishu-col ${dropOn === "done" ? "drop" : ""}`, ...dropProps("done"), "aria-label": t.done, title: t.dropDone, children: [
1019
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-col-head", children: [
1240
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: `mishu-col ${dropOn === "done" ? "drop" : ""}`, ...dropProps("done"), "aria-label": t.done, title: t.dropDone, children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-col-head", children: [
1020
1242
  t.done,
1021
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: columns.done.total })
1243
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: columns.done.total })
1022
1244
  ] }),
1023
- columns.done.groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.emptyDone }) : columns.done.groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("details", { className: "mishu-group", children: [
1024
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("summary", { children: [
1245
+ columns.done.groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-empty", children: t.emptyDone }) : columns.done.groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("details", { className: "mishu-group", children: [
1246
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("summary", { children: [
1025
1247
  group.label,
1026
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: group.items.length })
1248
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: group.items.length })
1027
1249
  ] }),
1028
1250
  group.items.map((item) => card(item, "done"))
1029
1251
  ] }, group.reason)),
1030
- columns.done.total > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.doneHint }) : null,
1031
- metrics.shadow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-banner", children: t.shadow(metrics.shadow) }) : null
1252
+ columns.done.total > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.doneHint }) : null,
1253
+ metrics.shadow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-banner", children: t.shadow(metrics.shadow) }) : null
1032
1254
  ] })
1033
1255
  ] })
1034
1256
  ] })
@@ -1036,8 +1258,8 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1036
1258
  }
1037
1259
  function Card({ item, column, lang, locale, busy, label, openChat: openChat2, onAct, onDragStart, onDragEnd }) {
1038
1260
  const t = TEXT[lang];
1039
- const [open, setOpen] = (0, import_react3.useState)(false);
1040
- const [detail, setDetail] = (0, import_react3.useState)();
1261
+ const [open, setOpen] = (0, import_react4.useState)(false);
1262
+ const [detail, setDetail] = (0, import_react4.useState)();
1041
1263
  const explain = item.explain;
1042
1264
  const compact = column === "done";
1043
1265
  const toggle = () => {
@@ -1047,11 +1269,11 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
1047
1269
  void mishuApi.detail(locale(), item.id).then((r) => setDetail(r.ok ? r.detail : { error: r.message }));
1048
1270
  }
1049
1271
  };
1050
- const row = (name, text, className = "") => text === null || text === void 0 || text === "" ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `mishu-row-explain ${className}`, children: [
1051
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-row-label", children: name }),
1052
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: text })
1272
+ const row = (name, text, className = "") => text === null || text === void 0 || text === "" ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `mishu-row-explain ${className}`, children: [
1273
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mishu-row-label", children: name }),
1274
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: text })
1053
1275
  ] });
1054
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1276
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1055
1277
  "div",
1056
1278
  {
1057
1279
  className: `mishu-card ${item.tone === "normal" ? "" : item.tone}`,
@@ -1062,35 +1284,35 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
1062
1284
  },
1063
1285
  onDragEnd,
1064
1286
  children: [
1065
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-card-title", children: item.title }),
1066
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-card-meta", children: item.meta }),
1067
- !compact && explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-explain", children: [
1287
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-card-title", children: item.title }),
1288
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-card-meta", children: item.meta }),
1289
+ !compact && explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-explain", children: [
1068
1290
  row(t.what, explain.what),
1069
1291
  row(column === "remember" ? t.whyKeep : t.why, explain.why),
1070
1292
  row(t.fix, explain.fix, "mishu-fix")
1071
1293
  ] }) : null,
1072
- !compact && explain === null && item.note !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-card-note", children: item.note }) : null,
1073
- open ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-detail", children: detail === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.loading }) : "error" in detail ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-danger", children: detail.error }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1074
- compact && detail.explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1294
+ !compact && explain === null && item.note !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-card-note", children: item.note }) : null,
1295
+ open ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-detail", children: detail === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-empty", children: t.loading }) : "error" in detail ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-danger", children: detail.error }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1296
+ compact && detail.explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1075
1297
  row(t.what, detail.explain.what),
1076
1298
  row(t.whyDone, detail.explain.why)
1077
1299
  ] }) : null,
1078
- detail.did.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row-explain", children: [
1079
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-row-label", children: t.did }),
1080
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: detail.did.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: line }, i)) })
1300
+ detail.did.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-row-explain", children: [
1301
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mishu-row-label", children: t.did }),
1302
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: detail.did.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: line }, i)) })
1081
1303
  ] }) : null,
1082
- detail.messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-messages", children: [
1083
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-row-label", children: t.messages(detail.messages.length) }),
1084
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { children: detail.messages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
1085
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: m.at }),
1304
+ detail.messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-messages", children: [
1305
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-row-label", children: t.messages(detail.messages.length) }),
1306
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { children: detail.messages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { children: [
1307
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: m.at }),
1086
1308
  " ",
1087
1309
  m.title
1088
1310
  ] }, i)) })
1089
1311
  ] }) : null
1090
1312
  ] }) }) : null,
1091
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
1092
- column === "handle" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2 }) : null,
1093
- item.actions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1313
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
1314
+ column === "handle" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2 }) : null,
1315
+ item.actions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1094
1316
  "button",
1095
1317
  {
1096
1318
  type: "button",
@@ -1101,8 +1323,8 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
1101
1323
  },
1102
1324
  action
1103
1325
  )),
1104
- item.target === "matter" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", "aria-expanded": open, onClick: toggle, children: open ? t.hide : compact ? t.explainDone : t.detail }) : null,
1105
- column === "handle" ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2, compact: true })
1326
+ item.target === "matter" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", "aria-expanded": open, onClick: toggle, children: open ? t.hide : compact ? t.explainDone : t.detail }) : null,
1327
+ column === "handle" ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2, compact: true })
1106
1328
  ] })
1107
1329
  ]
1108
1330
  }
@@ -1111,11 +1333,11 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
1111
1333
  var EMPTY = { title: "", due: "", repeat: "none", category: "other", note: "" };
1112
1334
  function AddForm({ lang, locale, onAdded }) {
1113
1335
  const t = TEXT[lang];
1114
- const [open, setOpen] = (0, import_react3.useState)(false);
1115
- const [item, setItem] = (0, import_react3.useState)(EMPTY);
1116
- const [preview, setPreview] = (0, import_react3.useState)();
1117
- const [saving, setSaving] = (0, import_react3.useState)(false);
1118
- (0, import_react3.useEffect)(() => {
1336
+ const [open, setOpen] = (0, import_react4.useState)(false);
1337
+ const [item, setItem] = (0, import_react4.useState)(EMPTY);
1338
+ const [preview, setPreview] = (0, import_react4.useState)();
1339
+ const [saving, setSaving] = (0, import_react4.useState)(false);
1340
+ (0, import_react4.useEffect)(() => {
1119
1341
  if (!open || item.title.trim() === "" || item.due === "") {
1120
1342
  setPreview(void 0);
1121
1343
  return;
@@ -1126,7 +1348,7 @@ function AddForm({ lang, locale, onAdded }) {
1126
1348
  return () => clearTimeout(timer);
1127
1349
  }, [open, item, locale]);
1128
1350
  if (!open) {
1129
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setOpen(true), children: [
1351
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setOpen(true), children: [
1130
1352
  "+ ",
1131
1353
  t.add
1132
1354
  ] });
@@ -1144,49 +1366,49 @@ function AddForm({ lang, locale, onAdded }) {
1144
1366
  setPreview({ ok: false, text: result.message });
1145
1367
  }
1146
1368
  };
1147
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-add", children: [
1148
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
1369
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-add", children: [
1370
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1149
1371
  t.addTitle,
1150
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: item.title, placeholder: t.addTitlePlaceholder, onChange: set("title") })
1372
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: item.title, placeholder: t.addTitlePlaceholder, onChange: set("title") })
1151
1373
  ] }),
1152
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row", children: [
1153
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
1374
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-row", children: [
1375
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1154
1376
  t.addDue,
1155
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "date", value: item.due, onChange: set("due") })
1377
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "date", value: item.due, onChange: set("due") })
1156
1378
  ] }),
1157
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1158
1380
  t.addRepeat,
1159
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("select", { value: item.repeat, onChange: set("repeat"), children: Object.entries(t.repeats).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value, children: text }, value)) })
1381
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { value: item.repeat, onChange: set("repeat"), children: Object.entries(t.repeats).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value, children: text }, value)) })
1160
1382
  ] })
1161
1383
  ] }),
1162
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row", children: [
1163
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
1384
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-row", children: [
1385
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1164
1386
  t.addCategory,
1165
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("select", { value: item.category, onChange: set("category"), children: Object.entries(t.categories).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value, children: text }, value)) })
1387
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { value: item.category, onChange: set("category"), children: Object.entries(t.categories).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value, children: text }, value)) })
1166
1388
  ] }),
1167
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
1389
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1168
1390
  t.addNote,
1169
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: item.note, onChange: set("note") })
1391
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: item.note, onChange: set("note") })
1170
1392
  ] })
1171
1393
  ] }),
1172
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `mishu-preview ${preview?.ok === false ? "mishu-danger" : ""}`, children: preview?.text ?? t.previewHint }),
1173
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
1174
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: saving || preview?.ok !== true, onClick: () => {
1394
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `mishu-preview ${preview?.ok === false ? "mishu-danger" : ""}`, children: preview?.text ?? t.previewHint }),
1395
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
1396
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: saving || preview?.ok !== true, onClick: () => {
1175
1397
  void save();
1176
1398
  }, children: t.save }),
1177
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
1399
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
1178
1400
  setOpen(false);
1179
1401
  setItem(EMPTY);
1180
1402
  }, children: t.cancel })
1181
1403
  ] }),
1182
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.chatHint })
1404
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.chatHint })
1183
1405
  ] });
1184
1406
  }
1185
1407
  function RestartButton({ lang, locale }) {
1186
1408
  const t = TEXT[lang];
1187
- const [why, setWhy] = (0, import_react3.useState)();
1188
- const [status, setStatus] = (0, import_react3.useState)();
1189
- (0, import_react3.useEffect)(() => {
1409
+ const [why, setWhy] = (0, import_react4.useState)();
1410
+ const [status, setStatus] = (0, import_react4.useState)();
1411
+ (0, import_react4.useEffect)(() => {
1190
1412
  void restartApi.info(locale()).then((r) => {
1191
1413
  if (r.ok && !r.supported) setWhy(r.why);
1192
1414
  });
@@ -1199,16 +1421,35 @@ function RestartButton({ lang, locale }) {
1199
1421
  if (!window.confirm(t.restartConfirm)) return;
1200
1422
  setStatus({ ok: true, text: t.restarting });
1201
1423
  const r = await restartApi.restart(locale());
1202
- if (!r.ok) setStatus({ ok: false, text: r.message });
1424
+ if (!r.ok) {
1425
+ setStatus({ ok: false, text: r.message });
1426
+ } else if (r.reconnect === true) {
1427
+ setStatus({ ok: true, text: t.restartingWeb });
1428
+ setStatus({ ok: true, text: await reconnect(locale) ? t.restartReloading : t.restartSlow });
1429
+ }
1203
1430
  };
1204
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1205
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", title: why === void 0 ? t.restartTip : `${t.restartTip}
1431
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1432
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", title: why === void 0 ? t.restartTip : `${t.restartTip}
1206
1433
  ${why}`, disabled: status?.ok === true, onClick: () => {
1207
1434
  void restart();
1208
1435
  }, children: t.restart }),
1209
- status === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: status.ok ? "mishu-hint" : "mishu-hint mishu-warn", children: status.text })
1436
+ status === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: status.ok ? "mishu-hint" : "mishu-hint mishu-warn", children: status.text })
1210
1437
  ] });
1211
1438
  }
1439
+ async function reconnect(locale) {
1440
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1441
+ let wentDown = false;
1442
+ for (const until = Date.now() + 12e4; Date.now() < until; ) {
1443
+ await sleep(1500);
1444
+ const r = await restartApi.info(locale());
1445
+ if (!r.ok) wentDown = true;
1446
+ else if (wentDown) {
1447
+ window.location.reload();
1448
+ return true;
1449
+ }
1450
+ }
1451
+ return false;
1452
+ }
1212
1453
 
1213
1454
  // src/client/styles.ts
1214
1455
  var v = (name, fallback) => `var(--dsw-alias-${name}, ${fallback})`;
@@ -1224,6 +1465,7 @@ var DANGER = v("state-error-primary", "#d14343");
1224
1465
  var WARN = v("state-warn-primary", "#b7791f");
1225
1466
  var OK = v("state-success-primary", "#2f855a");
1226
1467
  var ACCENT = v("brand-primary", "#4d6bfe");
1468
+ var SURFACE = v("bg-layer-0", v("bg-base", "Canvas"));
1227
1469
  var STYLES = `
1228
1470
  .mishu-page{box-sizing:border-box;height:100%;overflow:auto;padding:20px 24px 32px;color:${TEXT2};font-size:13px;line-height:1.5}
1229
1471
  .mishu-page *{box-sizing:border-box}
@@ -1284,6 +1526,22 @@ var STYLES = `
1284
1526
  .mishu-row{display:grid;grid-template-columns:1fr 1fr;gap:6px}
1285
1527
  .mishu-preview{white-space:pre-wrap;font-size:12px;background:${LAYER2};border-radius:6px;padding:6px 8px;margin:4px 0 6px;color:${TEXT2}}
1286
1528
  .mishu-preview.mishu-danger{color:${DANGER}}
1529
+ .mishu-modal-backdrop{position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;padding:16px}
1530
+ .mishu-modal{background:${SURFACE};color:${TEXT2};border:1px solid ${LINE_STRONG};border-radius:12px;box-shadow:0 12px 40px rgba(0,0,0,.35);width:min(480px,100%);max-height:calc(100vh - 32px);overflow:auto;padding:14px 16px 16px;font-size:13px;line-height:1.5}
1531
+ .mishu-modal *{box-sizing:border-box}
1532
+ .mishu-modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
1533
+ .mishu-modal-head h2{font-size:15px;font-weight:600;margin:0}
1534
+ .mishu-steps{font-size:12px;color:${MUTED};background:${LAYER1};border-radius:8px;padding:8px 10px;margin:2px 0 10px;line-height:1.6}
1535
+ .mishu-steps ol{margin:0;padding-left:20px}
1536
+ .mishu-steps li{margin:2px 0 6px}
1537
+ .mishu-steps li .mishu-btn{margin-left:4px;vertical-align:baseline}
1538
+ .mishu-steps.attention{outline:2px solid ${ACCENT};outline-offset:1px;color:${TEXT2}}
1539
+ .mishu-steps-help{display:flex;align-items:center;gap:6px;margin-top:4px}
1540
+ .mishu-steps.mishu-danger{color:${DANGER}}
1541
+ .mishu-more{margin:4px 0 8px;font-size:12px;color:${MUTED}}
1542
+ .mishu-more summary{cursor:pointer;margin-bottom:6px}
1543
+ .mishu-code-row{display:flex;align-items:center;gap:10px;margin:2px 0 10px}
1544
+ .mishu-code{font:600 26px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:3px;user-select:all;padding:4px 10px;border-radius:8px;background:${LAYER2}}
1287
1545
  .mishu-add>.mishu-hint{margin-bottom:8px}
1288
1546
  .mishu-title{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
1289
1547
  .mishu-tabs{display:flex;gap:2px;background:${LAYER1};border-radius:8px;padding:2px}
@@ -1312,18 +1570,18 @@ var STYLES = `
1312
1570
  `;
1313
1571
 
1314
1572
  // src/client/index.tsx
1315
- var import_jsx_runtime4 = require("react/jsx-runtime");
1573
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1316
1574
  var PACKAGE_NAME = "dsh-mishu";
1317
1575
  var inject = ["slots", "locale"];
1318
1576
  var PANEL_ID = "dsh-mishu";
1319
1577
  var NS = "dsh-mishu";
1320
1578
  var openChat;
1321
1579
  function MishuIcon({ size }) {
1322
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
1323
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "5", y: "4", width: "14", height: "17", rx: "2" }),
1324
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 4h6v3H9z" }),
1325
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 12l2 2 4-4" }),
1326
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 17h6" })
1580
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
1581
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "5", y: "4", width: "14", height: "17", rx: "2" }),
1582
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M9 4h6v3H9z" }),
1583
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M9 12l2 2 4-4" }),
1584
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M9 17h6" })
1327
1585
  ] });
1328
1586
  }
1329
1587
  function apply(ctx) {