dsh-mishu 0.7.1 → 0.7.3

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_react5 = require("react");
36
+ var import_react6 = require("react");
37
37
 
38
38
  // src/client/api.ts
39
39
  async function post(path, body) {
@@ -80,7 +80,11 @@ var settingsApi = {
80
80
  saveMail: (lang, account, password) => post("/mail/save", { lang, account, password }),
81
81
  testMail: (lang, account, password) => post("/mail/test", { lang, account, password }),
82
82
  deleteMail: (lang, id) => post("/mail/delete", { lang, id }),
83
- syncMail: (lang, id) => post("/mail/sync", { lang, id })
83
+ syncMail: (lang, id) => post("/mail/sync", { lang, id }),
84
+ saveWatch: (lang, watch) => post("/watch/save", { lang, watch }),
85
+ testWatch: (lang, watch) => post("/watch/test", { lang, watch }),
86
+ deleteWatch: (lang, id) => post("/watch/delete", { lang, id }),
87
+ syncWatch: (lang, id) => post("/watch/sync", { lang, id })
84
88
  };
85
89
 
86
90
  // src/client/AskAI.tsx
@@ -156,6 +160,7 @@ var zh = {
156
160
  sourceGithub: "GitHub",
157
161
  sourceMail: "\u90AE\u4EF6",
158
162
  sourceManual: "\u4EA4\u4EE3",
163
+ sourceWatch: "\u5173\u6CE8",
159
164
  sGeneral: "\u901A\u7528",
160
165
  sLanguage: "\u8BED\u8A00",
161
166
  sLanguageAuto: "\u8DDF\u968F\u7CFB\u7EDF",
@@ -208,6 +213,34 @@ var zh = {
208
213
  sPasswordTestOnly: "\u6CA1\u6709\u94A5\u5319\u4E32\uFF1A\u8FD9\u91CC\u586B\u7684\u53EA\u7528\u6765\u6D4B\u8BD5\u8FDE\u63A5\uFF0C\u4E0D\u4F1A\u4FDD\u5B58",
209
214
  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" },
210
215
  sNoAccounts: "\u8FD8\u6CA1\u6709\u6DFB\u52A0\u90AE\u7BB1\u3002",
216
+ sWatch: "\u81EA\u5DF1\u5173\u6CE8\u7684",
217
+ sWatchHint: "\u9664\u4E86 GitHub \u548C\u90AE\u7BB1\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u8BA9\u5C0F\u79D8\u4E66\u76EF\u7740\u4EFB\u610F\u4E00\u4E2A\u7F51\u5740\uFF1A\u516C\u544A\u9875\u3001\u4EF7\u683C\u3001\u62DB\u8058\u9875\u3001\u8BA2\u9605\u6E90\u90FD\u884C\u3002\u5B83\u4F1A\u9694\u4E00\u4F1A\u513F\u770B\u4E00\u6B21\uFF0C\u6709\u53D8\u5316\u5C31\u653E\u5230\u770B\u677F\u4E0A\u3002",
218
+ sNoWatches: "\u8FD8\u6CA1\u6709\u5173\u6CE8\u4EFB\u4F55\u7F51\u5740\u3002",
219
+ sAddWatch: "+ \u5173\u6CE8\u4E00\u4E2A\u7F51\u5740",
220
+ wTitleAdd: "\u5173\u6CE8\u4E00\u4E2A\u7F51\u5740",
221
+ wTitleEdit: "\u4FEE\u6539\u5173\u6CE8",
222
+ wUrl: "\u7F51\u5740",
223
+ wUrlHint: "RSS \u8BA2\u9605\u3001JSON \u63A5\u53E3\u3001\u666E\u901A\u7F51\u9875\u90FD\u53EF\u4EE5\u3002\u8981\u767B\u5F55\u624D\u80FD\u770B\u7684\u9875\u9762\u8BFB\u4E0D\u5230\u3002",
224
+ wLabel: "\u540D\u79F0",
225
+ wKeywords: "\u5173\u6CE8\u54EA\u4E9B\u5B57\uFF08\u53EF\u9009\uFF0C\u7528\u9017\u53F7\u5206\u5F00\uFF09",
226
+ wKeywordsHint: "\u586B\u4E86\u5C31\u53EA\u5728\u51FA\u73B0\u8FD9\u4E9B\u5B57\u65F6\u63D0\u9192\u4F60\uFF1B\u4E0D\u586B\u5C31\u662F\u6709\u53D8\u5316\u5C31\u63D0\u9192\u3002",
227
+ wEvery: "\u591A\u4E45\u770B\u4E00\u6B21",
228
+ wEveryUnit: (n) => `${n} \u5206\u949F`,
229
+ wTest: "\u5148\u8BD5\u8BFB\u4E00\u4E0B",
230
+ wTesting: "\u6B63\u5728\u8BFB\u2026",
231
+ wTestOk: (n, title) => `\u8BFB\u5230\u4E86 ${n} \u6761\u5185\u5BB9\uFF0C\u7B2C\u4E00\u6761\u662F\u300C${title}\u300D\u3002`,
232
+ wTestNoHit: (word) => `\u8BFB\u5230\u4E86\uFF0C\u4F46\u7B2C\u4E00\u6761\u91CC\u6CA1\u6709\u300C${word}\u300D\u3002\u4FDD\u5B58\u540E\u8FD8\u4F1A\u7EE7\u7EED\u76EF\u7740\u3002`,
233
+ wTestHit: (word) => `\u8BFB\u5230\u4E86\uFF0C\u7B2C\u4E00\u6761\u91CC\u5C31\u6709\u300C${word}\u300D\u3002`,
234
+ wSave: "\u4FDD\u5B58",
235
+ wSaveAndCheck: "\u4FDD\u5B58\u5E76\u770B\u4E00\u6B21",
236
+ wCheckNow: "\u73B0\u5728\u770B\u4E00\u6B21",
237
+ wDeleteConfirm: "\u5220\u6389\u8FD9\u4E2A\u5173\u6CE8\uFF1F\u5B83\u8FD8\u6CA1\u5904\u7406\u7684\u4E8B\u9879\u4F1A\u88AB\u5173\u6389\u3002",
238
+ wNeverChecked: "\u8FD8\u6CA1\u770B\u8FC7",
239
+ wKeywordsNone: "\u6709\u4EFB\u4F55\u53D8\u5316\u5C31\u544A\u8BC9\u6211",
240
+ wKeywordsList: (words) => `\u63D0\u5230 ${words} \u65F6\u544A\u8BC9\u6211`,
241
+ wChecked: (at, n) => `${at} \u770B\u8FC7\uFF0C${n} \u6761\u5185\u5BB9`,
242
+ wDisabled: "\u5DF2\u505C\u7528",
243
+ wAskSetup: "\u4E0D\u77E5\u9053\u8BE5\u586B\u4EC0\u4E48\u7F51\u5740\uFF1F",
211
244
  sAddAccount: "+ \u6DFB\u52A0\u90AE\u7BB1",
212
245
  sEdit: "\u7F16\u8F91",
213
246
  sDelete: "\u5220\u9664",
@@ -343,6 +376,7 @@ var en = {
343
376
  sourceGithub: "GitHub",
344
377
  sourceMail: "Mail",
345
378
  sourceManual: "Noted",
379
+ sourceWatch: "Watching",
346
380
  sGeneral: "General",
347
381
  sLanguage: "Language",
348
382
  sLanguageAuto: "Follow the system",
@@ -395,6 +429,34 @@ var en = {
395
429
  sPasswordTestOnly: "No keychain: used only to test the connection, not saved",
396
430
  secretKinds: { macos: "the macOS Keychain", windows: "Windows Credential Manager", linux: "the Linux keyring (Secret Service)", memory: "memory (tests)" },
397
431
  sNoAccounts: "No mail account yet.",
432
+ sWatch: "Things you watch",
433
+ sWatchHint: "Beyond GitHub and mail, the secretary can keep an eye on any address you give it: an announcements page, a price, a job posting, a feed. It looks now and then and puts a card on the board when something changes.",
434
+ sNoWatches: "Not watching anything yet.",
435
+ sAddWatch: "+ Watch an address",
436
+ wTitleAdd: "Watch an address",
437
+ wTitleEdit: "Edit watch",
438
+ wUrl: "Address",
439
+ wUrlHint: "An RSS feed, a JSON endpoint or a plain page all work. Pages behind a login cannot be read.",
440
+ wLabel: "Name",
441
+ wKeywords: "Words to watch for (optional, comma separated)",
442
+ wKeywordsHint: "With words, it only tells you when they show up; without, any change is worth a card.",
443
+ wEvery: "Check every",
444
+ wEveryUnit: (n) => `${n} minutes`,
445
+ wTest: "Read it once",
446
+ wTesting: "Reading\u2026",
447
+ wTestOk: (n, title) => `Read ${n} entries; the first is "${title}".`,
448
+ wTestNoHit: (word) => `It loaded, but the first entry does not mention "${word}". It keeps watching after you save.`,
449
+ wTestHit: (word) => `It loaded, and the first entry mentions "${word}".`,
450
+ wSave: "Save",
451
+ wSaveAndCheck: "Save and look once",
452
+ wCheckNow: "Look now",
453
+ wDeleteConfirm: "Delete this watch? Anything it still has open is closed.",
454
+ wNeverChecked: "Not checked yet",
455
+ wKeywordsNone: "tell me about any change",
456
+ wKeywordsList: (words) => `tell me when it mentions ${words}`,
457
+ wChecked: (at, n) => `checked ${at}, ${n} entries`,
458
+ wDisabled: "disabled",
459
+ wAskSetup: "Not sure what address to use?",
398
460
  sAddAccount: "+ Add a mail account",
399
461
  sEdit: "Edit",
400
462
  sDelete: "Delete",
@@ -516,14 +578,52 @@ function AskAI({ topic, lang, locale, openChat: openChat2, compact = false }) {
516
578
  }
517
579
 
518
580
  // src/client/Settings.tsx
519
- var import_react4 = require("react");
581
+ var import_react5 = require("react");
520
582
 
521
- // src/client/Modal.tsx
583
+ // src/client/Fold.tsx
522
584
  var import_react2 = require("react");
523
- var import_react_dom = require("react-dom");
524
585
  var import_jsx_runtime2 = require("react/jsx-runtime");
586
+ var FoldCtx = (0, import_react2.createContext)({ open: void 0, toggle: () => {
587
+ } });
588
+ function FoldGroup({ children }) {
589
+ const [open, setOpen] = (0, import_react2.useState)();
590
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FoldCtx.Provider, { value: { open, toggle: (key) => setOpen((current) => current === key ? void 0 : key) }, children });
591
+ }
592
+ function Fold({ id, title, aside, className = "", children }) {
593
+ const parent = (0, import_react2.useContext)(FoldCtx);
594
+ const [inner, setInner] = (0, import_react2.useState)();
595
+ const open = parent.open === id;
596
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `mishu-card mishu-fold${open ? " open" : ""}${className === "" ? "" : ` ${className}`}`, children: [
597
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
598
+ "div",
599
+ {
600
+ className: "mishu-card-head",
601
+ role: "button",
602
+ tabIndex: 0,
603
+ "aria-expanded": open,
604
+ onClick: () => parent.toggle(id),
605
+ onKeyDown: (event) => {
606
+ if (event.key !== "Enter" && event.key !== " ") return;
607
+ event.preventDefault();
608
+ parent.toggle(id);
609
+ },
610
+ children: [
611
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mishu-caret", "aria-hidden": "true" }),
612
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mishu-card-title", children: title }),
613
+ aside === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mishu-card-aside", onClick: (event) => event.stopPropagation(), children: aside })
614
+ ]
615
+ }
616
+ ),
617
+ open ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-card-body", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FoldCtx.Provider, { value: { open: inner, toggle: (key) => setInner((current) => current === key ? void 0 : key) }, children }) }) : null
618
+ ] });
619
+ }
620
+
621
+ // src/client/Modal.tsx
622
+ var import_react3 = require("react");
623
+ var import_react_dom = require("react-dom");
624
+ var import_jsx_runtime3 = require("react/jsx-runtime");
525
625
  function Modal({ title, onClose, children }) {
526
- (0, import_react2.useEffect)(() => {
626
+ (0, import_react3.useEffect)(() => {
527
627
  const key = (event) => {
528
628
  if (event.key === "Escape") onClose();
529
629
  };
@@ -531,12 +631,12 @@ function Modal({ title, onClose, children }) {
531
631
  return () => window.removeEventListener("keydown", key);
532
632
  }, [onClose]);
533
633
  return (0, import_react_dom.createPortal)(
534
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-modal-backdrop", onMouseDown: (event) => {
634
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-modal-backdrop", onMouseDown: (event) => {
535
635
  if (event.target === event.currentTarget) onClose();
536
- }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-modal", role: "dialog", "aria-modal": "true", "aria-label": title, children: [
537
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-modal-head", children: [
538
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: title }),
539
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", "aria-label": "\xD7", onClick: onClose, children: "\xD7" })
636
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-modal", role: "dialog", "aria-modal": "true", "aria-label": title, children: [
637
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-modal-head", children: [
638
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: title }),
639
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", "aria-label": "\xD7", onClick: onClose, children: "\xD7" })
540
640
  ] }),
541
641
  children
542
642
  ] }) }),
@@ -545,8 +645,8 @@ function Modal({ title, onClose, children }) {
545
645
  }
546
646
 
547
647
  // src/client/Notify.tsx
548
- var import_react3 = require("react");
549
- var import_jsx_runtime3 = require("react/jsx-runtime");
648
+ var import_react4 = require("react");
649
+ var import_jsx_runtime4 = require("react/jsx-runtime");
550
650
  var browserZone = () => {
551
651
  try {
552
652
  return Intl.DateTimeFormat().resolvedOptions().timeZone ?? "";
@@ -557,10 +657,10 @@ var browserZone = () => {
557
657
  function NotifySection({ view, lang, locale, take }) {
558
658
  const t = TEXT[lang];
559
659
  const notify = view.notify.settings;
560
- const [tested, setTested] = (0, import_react3.useState)({});
561
- const [feishuOpen, setFeishuOpen] = (0, import_react3.useState)(false);
660
+ const [tested, setTested] = (0, import_react4.useState)({});
661
+ const [feishuOpen, setFeishuOpen] = (0, import_react4.useState)(false);
562
662
  const save = async (patch) => take(await settingsApi.saveNotify(locale(), patch), t.sSaved);
563
- (0, import_react3.useEffect)(() => {
663
+ (0, import_react4.useEffect)(() => {
564
664
  const zone = browserZone();
565
665
  if (notify.timeZone === "" && zone !== "") void settingsApi.saveNotify(locale(), { timeZone: zone }).then((r) => take(r));
566
666
  }, [notify.timeZone, locale]);
@@ -569,14 +669,14 @@ function NotifySection({ view, lang, locale, take }) {
569
669
  const r = await settingsApi.testNotify(locale(), channel);
570
670
  setTested({ ...tested, [channel]: r.ok ? { ok: true, text: t.nTestSent } : { ok: false, text: r.message } });
571
671
  };
572
- const time = (value, onChange) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "time", step: 60, value, onChange: (e) => {
672
+ const time = (value, onChange) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "time", step: 60, value, onChange: (e) => {
573
673
  if (e.target.value !== "") onChange(e.target.value);
574
674
  } });
575
675
  const last = view.notify.last;
576
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
577
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-notify-row", children: [
578
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-check", children: [
579
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: notify.brief.enabled, onChange: (e) => {
676
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
677
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-notify-row", children: [
678
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-check", children: [
679
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", checked: notify.brief.enabled, onChange: (e) => {
580
680
  void save({ brief: { ...notify.brief, enabled: e.target.checked } });
581
681
  } }),
582
682
  t.nBrief
@@ -585,15 +685,15 @@ function NotifySection({ view, lang, locale, take }) {
585
685
  void save({ brief: { ...notify.brief, time: value } });
586
686
  })
587
687
  ] }),
588
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-notify-row", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-check", children: [
589
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: notify.urgent, onChange: (e) => {
688
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-notify-row", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-check", children: [
689
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", checked: notify.urgent, onChange: (e) => {
590
690
  void save({ urgent: e.target.checked });
591
691
  } }),
592
692
  t.nUrgent
593
693
  ] }) }),
594
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-notify-row", children: [
595
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-check", children: [
596
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: notify.quiet.enabled, onChange: (e) => {
694
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-notify-row", children: [
695
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-check", children: [
696
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", checked: notify.quiet.enabled, onChange: (e) => {
597
697
  void save({ quiet: { ...notify.quiet, enabled: e.target.checked } });
598
698
  } }),
599
699
  t.nQuiet
@@ -601,19 +701,22 @@ function NotifySection({ view, lang, locale, take }) {
601
701
  time(notify.quiet.from, (value) => {
602
702
  void save({ quiet: { ...notify.quiet, from: value } });
603
703
  }),
604
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-hint", children: t.nTo }),
704
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mishu-hint", children: t.nTo }),
605
705
  time(notify.quiet.to, (value) => {
606
706
  void save({ quiet: { ...notify.quiet, to: value } });
607
707
  })
608
708
  ] }),
609
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.nZone(notify.timeZone || browserZone()) }),
610
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: t.nChannels }),
709
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.nZone(notify.timeZone || browserZone()) }),
710
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: t.nChannels }),
611
711
  view.notify.channels.map((channel) => {
612
712
  const result = tested[channel.id];
613
713
  const feishu = channel.id === "feishu";
614
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-card", children: [
615
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-notify-row", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-check", children: [
616
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
714
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
715
+ Fold,
716
+ {
717
+ id: `channel-${channel.id}`,
718
+ title: feishu ? t.nFeishu : t.nDesktop,
719
+ aside: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { className: "mishu-check mishu-check-inline", title: channel.available ? void 0 : channel.why, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
617
720
  "input",
618
721
  {
619
722
  type: "checkbox",
@@ -623,24 +726,26 @@ function NotifySection({ view, lang, locale, take }) {
623
726
  void save({ channels: { ...notify.channels, [channel.id]: e.target.checked } });
624
727
  }
625
728
  }
626
- ),
627
- feishu ? t.nFeishu : t.nDesktop
628
- ] }) }),
629
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `mishu-card-note ${channel.available ? "" : "mishu-warn"}`, children: channel.available ? feishu ? t.nFeishuOn : t.nDesktopOn : channel.why }),
630
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
631
- channel.available ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
632
- void test(channel.id);
633
- }, children: t.nTest }) : null,
634
- feishu ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: view.notify.feishu.configured ? "mishu-btn" : "mishu-btn primary", onClick: () => setFeishuOpen(true), children: view.notify.feishu.configured ? t.nFeishuChange : t.nFeishuConnect }) : null,
635
- feishu && view.notify.feishu.configured ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
636
- if (window.confirm(t.nFeishuRemoveConfirm)) void settingsApi.deleteFeishu(locale()).then((r) => take(r));
637
- }, children: t.nFeishuRemove }) : null,
638
- result === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: result.ok ? "mishu-hint" : "mishu-hint mishu-danger", children: result.text })
639
- ] })
640
- ] }, channel.id);
729
+ ) }),
730
+ children: [
731
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `mishu-card-note ${channel.available ? "" : "mishu-warn"}`, children: channel.available ? feishu ? t.nFeishuOn : t.nDesktopOn : channel.why }),
732
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
733
+ channel.available ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
734
+ void test(channel.id);
735
+ }, children: t.nTest }) : null,
736
+ feishu ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: view.notify.feishu.configured ? "mishu-btn" : "mishu-btn primary", onClick: () => setFeishuOpen(true), children: view.notify.feishu.configured ? t.nFeishuChange : t.nFeishuConnect }) : null,
737
+ feishu && view.notify.feishu.configured ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
738
+ if (window.confirm(t.nFeishuRemoveConfirm)) void settingsApi.deleteFeishu(locale()).then((r) => take(r));
739
+ }, children: t.nFeishuRemove }) : null,
740
+ result === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: result.ok ? "mishu-hint" : "mishu-hint mishu-danger", children: result.text })
741
+ ] })
742
+ ]
743
+ },
744
+ channel.id
745
+ );
641
746
  }),
642
- last === null ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.nLast(new Date(last.at).toLocaleString(), last.kind, last.results) }),
643
- feishuOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FeishuDialog, { lang, locale, onDone: (next) => {
747
+ last === null ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.nLast(new Date(last.at).toLocaleString(), last.kind, last.results) }),
748
+ feishuOpen ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FeishuDialog, { lang, locale, onDone: (next) => {
644
749
  setFeishuOpen(false);
645
750
  if (next !== void 0) take({ ok: true, view: next }, t.nFeishuSaved);
646
751
  } }) : null
@@ -648,10 +753,10 @@ function NotifySection({ view, lang, locale, take }) {
648
753
  }
649
754
  function FeishuDialog({ lang, locale, onDone }) {
650
755
  const t = TEXT[lang];
651
- const [webhook, setWebhook] = (0, import_react3.useState)("");
652
- const [secret, setSecret] = (0, import_react3.useState)("");
653
- const [busy, setBusy] = (0, import_react3.useState)(false);
654
- const [error, setError] = (0, import_react3.useState)();
756
+ const [webhook, setWebhook] = (0, import_react4.useState)("");
757
+ const [secret, setSecret] = (0, import_react4.useState)("");
758
+ const [busy, setBusy] = (0, import_react4.useState)(false);
759
+ const [error, setError] = (0, import_react4.useState)();
655
760
  const connect = async () => {
656
761
  setBusy(true);
657
762
  setError(void 0);
@@ -660,46 +765,47 @@ function FeishuDialog({ lang, locale, onDone }) {
660
765
  if (r.ok) onDone(r.view);
661
766
  else setError(r.message);
662
767
  };
663
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Modal, { title: t.nFeishuConnect, onClose: () => onDone(), children: [
664
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-steps", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ol", { children: t.nFeishuSteps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { children: step }, i)) }) }),
665
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
768
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Modal, { title: t.nFeishuConnect, onClose: () => onDone(), children: [
769
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-steps", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ol", { children: t.nFeishuSteps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: step }, i)) }) }),
770
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
666
771
  t.nWebhook,
667
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: webhook, autoComplete: "off", spellCheck: false, placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/\u2026", onChange: (e) => {
772
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: webhook, autoComplete: "off", spellCheck: false, placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/\u2026", onChange: (e) => {
668
773
  setWebhook(e.target.value);
669
774
  setError(void 0);
670
775
  } })
671
776
  ] }),
672
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
777
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
673
778
  t.nSecret,
674
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "password", value: secret, autoComplete: "off", spellCheck: false, onChange: (e) => {
779
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "password", value: secret, autoComplete: "off", spellCheck: false, onChange: (e) => {
675
780
  setSecret(e.target.value);
676
781
  setError(void 0);
677
782
  } })
678
783
  ] }),
679
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.nFeishuPrivacy }),
680
- error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-preview mishu-danger", children: error }),
681
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
682
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || webhook.trim() === "", onClick: () => {
784
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.nFeishuPrivacy }),
785
+ error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-preview mishu-danger", children: error }),
786
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
787
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || webhook.trim() === "", onClick: () => {
683
788
  void connect();
684
789
  }, children: busy ? t.sTesting : t.nFeishuTry }),
685
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
790
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
686
791
  ] })
687
792
  ] });
688
793
  }
689
794
 
690
795
  // src/client/Settings.tsx
691
- var import_jsx_runtime4 = require("react/jsx-runtime");
796
+ var import_jsx_runtime5 = require("react/jsx-runtime");
692
797
  var CATEGORIES = ["document", "bill", "birthday", "renewal", "other"];
693
798
  function MishuSettings({ lang, locale, openChat: openChat2 }) {
694
799
  const t = TEXT[lang];
695
- const [view, setView] = (0, import_react4.useState)();
696
- const [error, setError] = (0, import_react4.useState)();
697
- const [note, setNote] = (0, import_react4.useState)();
698
- const [lead, setLead] = (0, import_react4.useState)({});
699
- const [githubTest, setGithubTest] = (0, import_react4.useState)();
700
- const [confirmOn, setConfirmOn] = (0, import_react4.useState)(false);
701
- const [pasting, setPasting] = (0, import_react4.useState)(false);
702
- const [editing, setEditing] = (0, import_react4.useState)();
800
+ const [view, setView] = (0, import_react5.useState)();
801
+ const [error, setError] = (0, import_react5.useState)();
802
+ const [note, setNote] = (0, import_react5.useState)();
803
+ const [lead, setLead] = (0, import_react5.useState)({});
804
+ const [githubTest, setGithubTest] = (0, import_react5.useState)();
805
+ const [confirmOn, setConfirmOn] = (0, import_react5.useState)(false);
806
+ const [pasting, setPasting] = (0, import_react5.useState)(false);
807
+ const [editing, setEditing] = (0, import_react5.useState)();
808
+ const [watching, setWatching] = (0, import_react5.useState)();
703
809
  const take = (result, saved) => {
704
810
  if (result.ok) {
705
811
  setView(result.view);
@@ -710,11 +816,11 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
710
816
  setError(result.message);
711
817
  }
712
818
  };
713
- (0, import_react4.useEffect)(() => {
819
+ (0, import_react5.useEffect)(() => {
714
820
  void settingsApi.load(locale()).then((r) => take(r));
715
821
  }, [locale]);
716
822
  if (view === void 0) {
717
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-settings", children: 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: [
823
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-settings", children: error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-error", children: [
718
824
  t.failed,
719
825
  error
720
826
  ] }) });
@@ -722,72 +828,71 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
722
828
  const save = async (settings) => take(await settingsApi.save(locale(), settings), t.sSaved);
723
829
  const token = view.github.token;
724
830
  const secretKind = t.secretKinds[view.secrets.kind] ?? view.secrets.kind;
725
- const markRead = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
726
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
831
+ const markRead = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
832
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
727
833
  t.sMarkRead,
728
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { value: view.settings.markRead, onChange: (e) => {
834
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { value: view.settings.markRead, onChange: (e) => {
729
835
  const value = e.target.value;
730
836
  if (value === "on") setConfirmOn(true);
731
837
  else void save({ markRead: value });
732
838
  }, children: [
733
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "off", children: t.sMarkOff }),
734
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "shadow", children: t.sMarkShadow }),
735
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "on", children: t.sMarkOn })
839
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "off", children: t.sMarkOff }),
840
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "shadow", children: t.sMarkShadow }),
841
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "on", children: t.sMarkOn })
736
842
  ] })
737
843
  ] }),
738
- confirmOn ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-banner", children: [
739
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { children: t.sMarkConfirm }),
740
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
741
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
844
+ confirmOn ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-banner", children: [
845
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: t.sMarkConfirm }),
846
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
847
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
742
848
  setConfirmOn(false);
743
849
  void save({ markRead: "on" });
744
850
  }, children: t.sConfirm }),
745
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setConfirmOn(false), children: t.sCancel })
851
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setConfirmOn(false), children: t.sCancel })
746
852
  ] })
747
853
  ] }) : null
748
854
  ] });
749
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-settings", children: [
750
- error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-error", children: [
855
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FoldGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-settings", children: [
856
+ error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-error", children: [
751
857
  t.failed,
752
858
  error
753
859
  ] }),
754
- note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-ok", children: note }),
755
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mishu-panel", children: [
756
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { children: t.bSources }),
757
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.bSourcesHint }),
758
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: t.sGithub }),
759
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-check", children: [
760
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", checked: view.settings.githubEnabled, onChange: (e) => {
860
+ note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-ok", children: note }),
861
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Fold, { id: "sources", className: "mishu-panel", title: t.bSources, children: [
862
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.bSourcesHint }),
863
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { children: t.sGithub }),
864
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-check", children: [
865
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: view.settings.githubEnabled, onChange: (e) => {
761
866
  void save({ githubEnabled: e.target.checked });
762
867
  } }),
763
868
  t.sGithubOn
764
869
  ] }),
765
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-row-explain", children: [
766
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mishu-row-label", children: t.sToken }),
767
- /* @__PURE__ */ (0, import_jsx_runtime4.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 })
870
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row-explain", children: [
871
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mishu-row-label", children: t.sToken }),
872
+ /* @__PURE__ */ (0, import_jsx_runtime5.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 })
768
873
  ] }),
769
- token.found ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
770
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
874
+ token.found ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
771
876
  setGithubTest(t.sTesting);
772
877
  void settingsApi.testGithub(locale()).then((r) => setGithubTest(r.ok ? t.sGithubOk(r.login) : `${t.failed}${r.message}`));
773
878
  }, children: t.sTest }),
774
- token.from === "env" || pasting ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setPasting(true), children: t.sTokenReplace }),
775
- token.from === "keychain" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
879
+ token.from === "env" || pasting ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setPasting(true), children: t.sTokenReplace }),
880
+ token.from === "keychain" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
776
881
  if (window.confirm(t.sTokenRemoveConfirm)) void settingsApi.deleteToken(locale()).then((r) => {
777
882
  setGithubTest(void 0);
778
883
  take(r);
779
884
  });
780
885
  }, children: t.sTokenRemove }) : null,
781
- githubTest === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mishu-hint", children: githubTest })
886
+ githubTest === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mishu-hint", children: githubTest })
782
887
  ] }) : null,
783
- !token.found || pasting ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GithubConnect, { view, lang, locale, onSaved: (next, login) => {
888
+ !token.found || pasting ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GithubConnect, { view, lang, locale, onSaved: (next, login) => {
784
889
  setPasting(false);
785
890
  setGithubTest(t.sTokenSaved(login));
786
891
  take({ ok: true, view: next });
787
892
  }, onCancel: token.found ? () => setPasting(false) : void 0 }) : null,
788
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: t.sMail }),
789
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.sMailPrivacy }),
790
- view.accounts.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-empty", children: t.sNoAccounts }) : view.accounts.map((account) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
893
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { children: t.sMail }),
894
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.sMailPrivacy }),
895
+ view.accounts.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-empty", children: t.sNoAccounts }) : view.accounts.map((account) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
791
896
  AccountRow,
792
897
  {
793
898
  account,
@@ -800,8 +905,8 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
800
905
  },
801
906
  account.id
802
907
  )),
803
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setEditing({ preset: "custom", sinceDays: 14, enabled: true }), children: t.sAddAccount }),
804
- editing === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
908
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setEditing({ preset: "custom", sinceDays: 14, enabled: true }), children: t.sAddAccount }),
909
+ editing === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
805
910
  MailDialog,
806
911
  {
807
912
  draft: editing,
@@ -814,58 +919,80 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
814
919
  if (next !== void 0) take({ ok: true, view: next }, note2 ?? t.sSaved);
815
920
  }
816
921
  }
922
+ ),
923
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { children: t.sWatch }),
924
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.sWatchHint }),
925
+ view.watches.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-empty", children: t.sNoWatches }) : view.watches.map((watch) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
926
+ WatchRow,
927
+ {
928
+ watch,
929
+ lang,
930
+ locale,
931
+ openChat: openChat2,
932
+ onEdit: () => setWatching({ ...watch }),
933
+ onView: (next) => take(next)
934
+ },
935
+ watch.id
936
+ )),
937
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setWatching({ label: "", url: "", keywords: "", enabled: true, intervalMinutes: 60 }), children: t.sAddWatch }),
938
+ watching === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
939
+ WatchDialog,
940
+ {
941
+ draft: watching,
942
+ lang,
943
+ locale,
944
+ openChat: openChat2,
945
+ onDone: (next, note2) => {
946
+ setWatching(void 0);
947
+ if (next !== void 0) take({ ok: true, view: next }, note2 ?? t.sSaved);
948
+ }
949
+ }
817
950
  )
818
951
  ] }),
819
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mishu-panel", children: [
820
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { children: t.bWhat }),
821
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.bUrgentRule }),
822
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-field", children: t.sLead }),
823
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-grid5", children: CATEGORIES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
952
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Fold, { id: "what", className: "mishu-panel", title: t.bWhat, children: [
953
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.bUrgentRule }),
954
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-field", children: t.sLead }),
955
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-grid5", children: CATEGORIES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
824
956
  t.categories[c],
825
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "number", min: 0, max: 366, value: lead[c] ?? 0, onChange: (e) => setLead({ ...lead, [c]: Number(e.target.value) }) })
957
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "number", min: 0, max: 366, value: lead[c] ?? 0, onChange: (e) => setLead({ ...lead, [c]: Number(e.target.value) }) })
826
958
  ] }, c)) }),
827
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
959
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
828
960
  void save({ leadDays: lead });
829
961
  }, children: t.sSave })
830
962
  ] }),
831
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mishu-panel", children: [
832
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { children: t.bWhen }),
833
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NotifySection, { view, lang, locale, take })
834
- ] }),
835
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mishu-panel", children: [
836
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { children: t.bDo }),
963
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Fold, { id: "when", className: "mishu-panel", title: t.bWhen, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(NotifySection, { view, lang, locale, take }) }),
964
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Fold, { id: "do", className: "mishu-panel", title: t.bDo, children: [
837
965
  markRead,
838
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.bMailReadOnly })
966
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.bMailReadOnly })
839
967
  ] }),
840
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mishu-panel", children: [
841
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { children: t.sGeneral }),
842
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
968
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Fold, { id: "general", className: "mishu-panel", title: t.sGeneral, children: [
969
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
843
970
  t.sLanguage,
844
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { value: view.settings.language, onChange: (e) => {
971
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { value: view.settings.language, onChange: (e) => {
845
972
  void save({ language: e.target.value });
846
973
  }, children: [
847
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "auto", children: t.sLanguageAuto }),
848
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }),
849
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "en", children: "English" })
974
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "auto", children: t.sLanguageAuto }),
975
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }),
976
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "en", children: "English" })
850
977
  ] })
851
978
  ] }),
852
- /* @__PURE__ */ (0, import_jsx_runtime4.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) })
979
+ /* @__PURE__ */ (0, import_jsx_runtime5.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) })
853
980
  ] })
854
- ] });
981
+ ] }) });
855
982
  }
856
983
  function GithubConnect({ view, lang, locale, onSaved, onCancel }) {
857
984
  const t = TEXT[lang];
858
- const [signingIn, setSigningIn] = (0, import_react4.useState)(false);
859
- const [paste, setPaste] = (0, import_react4.useState)(!view.github.deviceLogin);
860
- if (!view.github.deviceLogin) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TokenForm, { view, lang, locale, onSaved, onCancel });
861
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
862
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
863
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => setSigningIn(true), children: t.gLogin }),
864
- paste ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => setPaste(true), children: t.gPasteInstead }),
865
- onCancel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: onCancel, children: t.sCancel })
985
+ const [signingIn, setSigningIn] = (0, import_react5.useState)(false);
986
+ const [paste, setPaste] = (0, import_react5.useState)(!view.github.deviceLogin);
987
+ if (!view.github.deviceLogin) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TokenForm, { view, lang, locale, onSaved, onCancel });
988
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
989
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
990
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => setSigningIn(true), children: t.gLogin }),
991
+ paste ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => setPaste(true), children: t.gPasteInstead }),
992
+ onCancel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: onCancel, children: t.sCancel })
866
993
  ] }),
867
- paste ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TokenForm, { view, lang, locale, onSaved, onCancel: void 0 }) : null,
868
- signingIn ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GithubLoginDialog, { lang, locale, onClose: () => setSigningIn(false), onSaved: (next, login) => {
994
+ paste ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TokenForm, { view, lang, locale, onSaved, onCancel: void 0 }) : null,
995
+ signingIn ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GithubLoginDialog, { lang, locale, onClose: () => setSigningIn(false), onSaved: (next, login) => {
869
996
  setSigningIn(false);
870
997
  onSaved(next, login);
871
998
  } }) : null
@@ -873,12 +1000,12 @@ function GithubConnect({ view, lang, locale, onSaved, onCancel }) {
873
1000
  }
874
1001
  function GithubLoginDialog({ lang, locale, onClose, onSaved }) {
875
1002
  const t = TEXT[lang];
876
- const [login, setLogin] = (0, import_react4.useState)();
877
- const [error, setError] = (0, import_react4.useState)();
878
- const [copied, setCopied] = (0, import_react4.useState)(false);
879
- const [attempt, setAttempt] = (0, import_react4.useState)(0);
880
- const saved = (0, import_react4.useRef)(void 0);
881
- (0, import_react4.useEffect)(() => {
1003
+ const [login, setLogin] = (0, import_react5.useState)();
1004
+ const [error, setError] = (0, import_react5.useState)();
1005
+ const [copied, setCopied] = (0, import_react5.useState)(false);
1006
+ const [attempt, setAttempt] = (0, import_react5.useState)(0);
1007
+ const saved = (0, import_react5.useRef)(void 0);
1008
+ (0, import_react5.useEffect)(() => {
882
1009
  let alive = true;
883
1010
  let timer;
884
1011
  setLogin(void 0);
@@ -922,42 +1049,42 @@ function GithubLoginDialog({ lang, locale, onClose, onSaved }) {
922
1049
  const copy2 = (code) => {
923
1050
  void navigator.clipboard?.writeText(code).then(() => setCopied(true), () => setCopied(false));
924
1051
  };
925
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Modal, { title: t.gLogin, onClose: close, children: error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
926
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-preview mishu-danger", children: error }),
927
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-actions", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: close, children: t.gClose }) })
928
- ] }) : login === void 0 || login.state === "idle" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.gStarting }) : login.state === "waiting" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
929
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-field", children: t.gStep1 }),
930
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-code-row", children: [
931
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { className: "mishu-code", children: login.userCode }),
932
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => copy2(login.userCode), children: copied ? t.gCopied : t.gCopy })
1052
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Modal, { title: t.gLogin, onClose: close, children: error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1053
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-preview mishu-danger", children: error }),
1054
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-actions", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: close, children: t.gClose }) })
1055
+ ] }) : login === void 0 || login.state === "idle" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.gStarting }) : login.state === "waiting" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1056
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-field", children: t.gStep1 }),
1057
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-code-row", children: [
1058
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { className: "mishu-code", children: login.userCode }),
1059
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => copy2(login.userCode), children: copied ? t.gCopied : t.gCopy })
933
1060
  ] }),
934
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-field", children: t.gStep2 }),
935
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
936
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => window.open(login.verificationUri, "_blank", "noopener"), children: t.gOpen }),
937
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mishu-hint", children: t.gWaiting })
1061
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-field", children: t.gStep2 }),
1062
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1063
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => window.open(login.verificationUri, "_blank", "noopener"), children: t.gOpen }),
1064
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mishu-hint", children: t.gWaiting })
938
1065
  ] }),
939
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.gScopes })
940
- ] }) : login.state === "done" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
941
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-ok", children: t.gDone(login.login) }),
942
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-actions", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: close, children: t.gClose }) })
943
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
944
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-preview mishu-danger", children: login.message }),
945
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
946
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
1066
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.gScopes })
1067
+ ] }) : login.state === "done" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1068
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-ok", children: t.gDone(login.login) }),
1069
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-actions", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: close, children: t.gClose }) })
1070
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1071
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-preview mishu-danger", children: login.message }),
1072
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1073
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
947
1074
  setCopied(false);
948
1075
  setAttempt(attempt + 1);
949
1076
  }, children: t.gRetry }),
950
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: close, children: t.gClose })
1077
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: close, children: t.gClose })
951
1078
  ] })
952
1079
  ] }) });
953
1080
  }
954
1081
  function TokenForm({ view, lang, locale, onSaved, onCancel }) {
955
1082
  const t = TEXT[lang];
956
- const [token, setToken] = (0, import_react4.useState)("");
957
- const [busy, setBusy] = (0, import_react4.useState)(false);
958
- const [message, setMessage] = (0, import_react4.useState)();
1083
+ const [token, setToken] = (0, import_react5.useState)("");
1084
+ const [busy, setBusy] = (0, import_react5.useState)(false);
1085
+ const [message, setMessage] = (0, import_react5.useState)();
959
1086
  if (!view.secrets.available) {
960
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sTokenNoKeychain(view.github.tokenEnv, view.secrets.why ?? "") });
1087
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sTokenNoKeychain(view.github.tokenEnv, view.secrets.why ?? "") });
961
1088
  }
962
1089
  const save = async () => {
963
1090
  setBusy(true);
@@ -971,58 +1098,54 @@ function TokenForm({ view, lang, locale, onSaved, onCancel }) {
971
1098
  setMessage(r.message);
972
1099
  }
973
1100
  };
974
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-add", children: [
975
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1101
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-add", children: [
1102
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
976
1103
  t.sTokenPaste,
977
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "password", value: token, autoComplete: "off", spellCheck: false, placeholder: "ghp_\u2026", onChange: (e) => {
1104
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "password", value: token, autoComplete: "off", spellCheck: false, placeholder: "ghp_\u2026", onChange: (e) => {
978
1105
  setToken(e.target.value);
979
1106
  setMessage(void 0);
980
1107
  } })
981
1108
  ] }),
982
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.sTokenHow }),
983
- message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-preview mishu-danger", children: message }),
984
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
985
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => window.open(view.github.newTokenUrl, "_blank", "noopener"), children: t.sTokenNew }),
986
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || token.trim() === "", onClick: () => {
1109
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.sTokenHow }),
1110
+ message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-preview mishu-danger", children: message }),
1111
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1112
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => window.open(view.github.newTokenUrl, "_blank", "noopener"), children: t.sTokenNew }),
1113
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || token.trim() === "", onClick: () => {
987
1114
  void save();
988
1115
  }, children: busy ? t.sTesting : t.sTokenSave }),
989
- onCancel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: onCancel, children: t.sCancel })
1116
+ onCancel === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: onCancel, children: t.sCancel })
990
1117
  ] })
991
1118
  ] });
992
1119
  }
993
1120
  function AccountRow({ account, secretsOk, lang, locale, openChat: openChat2, onEdit, onView }) {
994
1121
  const t = TEXT[lang];
995
- const [busy, setBusy] = (0, import_react4.useState)(false);
1122
+ const [busy, setBusy] = (0, import_react5.useState)(false);
996
1123
  const report = account.report;
997
1124
  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`;
998
1125
  const failed = !account.hasPassword || report?.error !== void 0;
999
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-card", children: [
1000
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-card-title", children: [
1001
- account.label,
1002
- account.enabled ? "" : ` (${lang === "zh" ? "\u5DF2\u505C\u7528" : "disabled"})`
1003
- ] }),
1004
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-card-meta", children: [
1126
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Fold, { id: `account-${account.id}`, title: `${account.label}${account.enabled ? "" : ` (${lang === "zh" ? "\u5DF2\u505C\u7528" : "disabled"})`}`, children: [
1127
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-card-meta", children: [
1005
1128
  account.address,
1006
1129
  " \xB7 ",
1007
1130
  account.host,
1008
1131
  ":",
1009
1132
  account.port
1010
1133
  ] }),
1011
- account.mismatch === null ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mishu-card-note mishu-warn", children: account.mismatch }),
1012
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `mishu-card-note ${failed ? "mishu-danger" : ""}`, children: [
1134
+ account.mismatch === null ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-card-note mishu-warn", children: account.mismatch }),
1135
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `mishu-card-note ${failed ? "mishu-danger" : ""}`, children: [
1013
1136
  status,
1014
- account.hasPassword && report?.error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: { kind: "mail-error", accountId: account.id }, lang, locale, openChat: openChat2, compact: true }) : null
1137
+ account.hasPassword && report?.error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "mail-error", accountId: account.id }, lang, locale, openChat: openChat2, compact: true }) : null
1015
1138
  ] }),
1016
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
1017
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy || !account.hasPassword, onClick: () => {
1139
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1140
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy || !account.hasPassword, onClick: () => {
1018
1141
  setBusy(true);
1019
1142
  void settingsApi.syncMail(locale(), account.id).then((r) => {
1020
1143
  setBusy(false);
1021
1144
  onView(r);
1022
1145
  });
1023
1146
  }, children: busy ? t.sTesting : t.sCheckNow }),
1024
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: account.hasPassword && account.mismatch === null ? "mishu-btn" : "mishu-btn primary", onClick: onEdit, children: t.sEdit }),
1025
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
1147
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: account.hasPassword && account.mismatch === null ? "mishu-btn" : "mishu-btn primary", onClick: onEdit, children: t.sEdit }),
1148
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
1026
1149
  if (window.confirm(t.sDeleteConfirm)) void settingsApi.deleteMail(locale(), account.id).then(onView);
1027
1150
  }, children: t.sDelete })
1028
1151
  ] })
@@ -1031,12 +1154,12 @@ function AccountRow({ account, secretsOk, lang, locale, openChat: openChat2, onE
1031
1154
  function MailDialog({ draft, view, lang, locale, openChat: openChat2, onDone }) {
1032
1155
  const t = TEXT[lang];
1033
1156
  const existing = draft.id !== void 0;
1034
- const [account, setAccount] = (0, import_react4.useState)(draft);
1035
- const [picked, setPicked] = (0, import_react4.useState)(existing);
1036
- const [password, setPassword] = (0, import_react4.useState)("");
1037
- const [message, setMessage] = (0, import_react4.useState)();
1038
- const [failedTest, setFailedTest] = (0, import_react4.useState)(false);
1039
- const [busy, setBusy] = (0, import_react4.useState)(false);
1157
+ const [account, setAccount] = (0, import_react5.useState)(draft);
1158
+ const [picked, setPicked] = (0, import_react5.useState)(existing);
1159
+ const [password, setPassword] = (0, import_react5.useState)("");
1160
+ const [message, setMessage] = (0, import_react5.useState)();
1161
+ const [failedTest, setFailedTest] = (0, import_react5.useState)(false);
1162
+ const [busy, setBusy] = (0, import_react5.useState)(false);
1040
1163
  const preset = view.presets.find((p) => p.id === account.preset) ?? view.presets[view.presets.length - 1];
1041
1164
  const custom = preset.id === "custom";
1042
1165
  const set = (patch) => {
@@ -1069,93 +1192,220 @@ function MailDialog({ draft, view, lang, locale, openChat: openChat2, onDone })
1069
1192
  setMessage({ ok: false, text: r.message });
1070
1193
  }
1071
1194
  };
1072
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Modal, { title: existing ? t.mTitleEdit : t.mTitleAdd, onClose: () => onDone(), children: [
1073
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1195
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Modal, { title: existing ? t.mTitleEdit : t.mTitleAdd, onClose: () => onDone(), children: [
1196
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1074
1197
  t.sAddress,
1075
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "email", value: account.address ?? "", autoComplete: "off", autoFocus: !existing, onChange: (e) => setAddress(e.target.value) })
1198
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "email", value: account.address ?? "", autoComplete: "off", autoFocus: !existing, onChange: (e) => setAddress(e.target.value) })
1076
1199
  ] }),
1077
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1200
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1078
1201
  t.sProvider,
1079
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { value: account.preset, onChange: (e) => {
1202
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { value: account.preset, onChange: (e) => {
1080
1203
  setPicked(true);
1081
1204
  set({ preset: e.target.value });
1082
- }, children: view.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: p.id, children: p.label }, p.id)) })
1205
+ }, children: view.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: p.id, children: p.label }, p.id)) })
1083
1206
  ] }),
1084
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `mishu-steps${preset.supported ? "" : " mishu-danger"}${failedTest ? " attention" : ""}`, children: [
1085
- preset.steps.length === 0 ? preset.howTo : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ol", { children: preset.steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { children: [
1207
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `mishu-steps${preset.supported ? "" : " mishu-danger"}${failedTest ? " attention" : ""}`, children: [
1208
+ preset.steps.length === 0 ? preset.howTo : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ol", { children: preset.steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { children: [
1086
1209
  step.text,
1087
- step.link === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1210
+ step.link === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1088
1211
  " ",
1089
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => window.open(step.link.url, "_blank", "noopener"), children: step.link.label })
1212
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => window.open(step.link.url, "_blank", "noopener"), children: step.link.label })
1090
1213
  ] })
1091
1214
  ] }, i)) }),
1092
- preset.supported ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-steps-help", children: [
1215
+ preset.supported ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-steps-help", children: [
1093
1216
  t.mStepsHelp,
1094
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id }, lang, locale, openChat: openChat2, compact: true })
1217
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id }, lang, locale, openChat: openChat2, compact: true })
1095
1218
  ] }) : null
1096
1219
  ] }),
1097
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1220
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1098
1221
  t.sPassword,
1099
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "password", value: password, autoComplete: "new-password", placeholder: existing && view.secrets.available ? t.sPasswordKeep : "", onChange: (e) => {
1222
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "password", value: password, autoComplete: "new-password", placeholder: existing && view.secrets.available ? t.sPasswordKeep : "", onChange: (e) => {
1100
1223
  setPassword(e.target.value);
1101
1224
  setMessage(void 0);
1102
1225
  setFailedTest(false);
1103
1226
  } })
1104
1227
  ] }),
1105
- lengthOff ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint mishu-warn", children: t.mLength(preset.label, preset.passwordLength, typed.length) }) : null,
1106
- view.secrets.available ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sPasswordTestOnly }),
1107
- custom ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-row", children: [
1108
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1228
+ lengthOff ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint mishu-warn", children: t.mLength(preset.label, preset.passwordLength, typed.length) }) : null,
1229
+ view.secrets.available ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint mishu-warn", children: t.sPasswordTestOnly }),
1230
+ custom ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row", children: [
1231
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1109
1232
  t.sHost,
1110
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: account.host ?? "", placeholder: "imap.example.com", onChange: (e) => set({ host: e.target.value }) })
1233
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: account.host ?? "", placeholder: "imap.example.com", onChange: (e) => set({ host: e.target.value }) })
1111
1234
  ] }),
1112
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1235
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1113
1236
  t.sPort,
1114
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "number", value: account.port ?? 993, onChange: (e) => set({ port: Number(e.target.value) }) })
1237
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "number", value: account.port ?? 993, onChange: (e) => set({ port: Number(e.target.value) }) })
1115
1238
  ] })
1116
1239
  ] }) : null,
1117
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("details", { className: "mishu-more", children: [
1118
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("summary", { children: t.mMore }),
1119
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-row", children: [
1120
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1240
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { className: "mishu-more", children: [
1241
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("summary", { children: t.mMore }),
1242
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row", children: [
1243
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1121
1244
  t.sLabel,
1122
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: account.label ?? "", placeholder: account.address ?? "", onChange: (e) => set({ label: e.target.value }) })
1245
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: account.label ?? "", placeholder: account.address ?? "", onChange: (e) => set({ label: e.target.value }) })
1123
1246
  ] }),
1124
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1247
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1125
1248
  t.sUser,
1126
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: account.user ?? "", placeholder: account.address ?? "", autoComplete: "off", onChange: (e) => set({ user: e.target.value }) })
1249
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: account.user ?? "", placeholder: account.address ?? "", autoComplete: "off", onChange: (e) => set({ user: e.target.value }) })
1127
1250
  ] })
1128
1251
  ] }),
1129
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-row", children: [
1130
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
1252
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row", children: [
1253
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1131
1254
  t.sSince,
1132
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "number", min: 1, max: 90, value: account.sinceDays ?? 14, onChange: (e) => set({ sinceDays: Number(e.target.value) }) })
1255
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "number", min: 1, max: 90, value: account.sinceDays ?? 14, onChange: (e) => set({ sinceDays: Number(e.target.value) }) })
1133
1256
  ] }),
1134
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-check", children: [
1135
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", checked: account.enabled !== false, onChange: (e) => set({ enabled: e.target.checked }) }),
1257
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-check", children: [
1258
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: account.enabled !== false, onChange: (e) => set({ enabled: e.target.checked }) }),
1136
1259
  t.sEnabled
1137
1260
  ] })
1138
1261
  ] })
1139
1262
  ] }),
1140
- message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `mishu-preview ${message.ok ? "" : "mishu-danger"}`, children: [
1263
+ message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `mishu-preview ${message.ok ? "" : "mishu-danger"}`, children: [
1141
1264
  message.text,
1142
- message.ok || !preset.supported ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id, error: message.text }, lang, locale, openChat: openChat2, compact: true })
1265
+ message.ok || !preset.supported ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id, error: message.text }, lang, locale, openChat: openChat2, compact: true })
1143
1266
  ] }),
1144
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mishu-actions", children: [
1145
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || !preset.supported || (account.address ?? "") === "", onClick: () => {
1267
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1268
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || !preset.supported || (account.address ?? "") === "", onClick: () => {
1146
1269
  void testAndSave();
1147
1270
  }, children: busy ? t.sTesting : t.mTestSave }),
1148
- failedTest ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", disabled: busy, onClick: () => {
1271
+ failedTest ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", disabled: busy, onClick: () => {
1149
1272
  setBusy(true);
1150
1273
  void save();
1151
1274
  }, children: t.mSaveAnyway }) : null,
1152
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
1275
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
1276
+ ] })
1277
+ ] });
1278
+ }
1279
+ function WatchRow({ watch, lang, locale, openChat: openChat2, onEdit, onView }) {
1280
+ const t = TEXT[lang];
1281
+ const [busy, setBusy] = (0, import_react5.useState)(false);
1282
+ const failed = watch.report?.error !== void 0;
1283
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Fold, { id: `watch-${watch.id}`, title: `${watch.label}${watch.enabled ? "" : ` (${t.wDisabled})`}`, children: [
1284
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-card-meta", children: [
1285
+ watch.url,
1286
+ " \xB7 ",
1287
+ t.wEveryUnit(watch.intervalMinutes)
1288
+ ] }),
1289
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-card-meta", children: watch.summary }),
1290
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `mishu-card-note ${failed ? "mishu-danger" : ""}`, children: [
1291
+ watch.status,
1292
+ failed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "watch-error", watchId: watch.id }, lang, locale, openChat: openChat2, compact: true }) : null
1293
+ ] }),
1294
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1295
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy, onClick: () => {
1296
+ setBusy(true);
1297
+ void settingsApi.syncWatch(locale(), watch.id).then((r) => {
1298
+ setBusy(false);
1299
+ onView(r);
1300
+ });
1301
+ }, children: busy ? t.wTesting : t.wCheckNow }),
1302
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: onEdit, children: t.sEdit }),
1303
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
1304
+ if (window.confirm(t.wDeleteConfirm)) void settingsApi.deleteWatch(locale(), watch.id).then(onView);
1305
+ }, children: t.sDelete })
1306
+ ] })
1307
+ ] });
1308
+ }
1309
+ function WatchDialog({ draft, lang, locale, openChat: openChat2, onDone }) {
1310
+ const t = TEXT[lang];
1311
+ const existing = draft.id !== void 0;
1312
+ const [watch, setWatch] = (0, import_react5.useState)(draft);
1313
+ const [message, setMessage] = (0, import_react5.useState)();
1314
+ const [tested, setTested] = (0, import_react5.useState)();
1315
+ const [busy, setBusy] = (0, import_react5.useState)(false);
1316
+ const set = (patch) => {
1317
+ setWatch({ ...watch, ...patch });
1318
+ setMessage(void 0);
1319
+ setTested(void 0);
1320
+ };
1321
+ const save = async (thenCheck = false) => {
1322
+ setBusy(true);
1323
+ const r = await settingsApi.saveWatch(locale(), watch);
1324
+ if (!r.ok) {
1325
+ setBusy(false);
1326
+ setMessage({ ok: false, text: r.message });
1327
+ return;
1328
+ }
1329
+ let view = r.view;
1330
+ if (thenCheck) {
1331
+ const checked = await settingsApi.syncWatch(locale(), r.id);
1332
+ if (checked.ok) view = checked.view;
1333
+ }
1334
+ setBusy(false);
1335
+ onDone(view, t.sSaved);
1336
+ };
1337
+ const test = async () => {
1338
+ setBusy(true);
1339
+ setMessage({ ok: true, text: t.wTesting });
1340
+ const r = await settingsApi.testWatch(locale(), watch);
1341
+ setBusy(false);
1342
+ if (!r.ok) {
1343
+ setMessage({ ok: false, text: r.message });
1344
+ return;
1345
+ }
1346
+ setTested(r);
1347
+ const hit = r.keywordHit === void 0 ? void 0 : r.keyword;
1348
+ setMessage({
1349
+ ok: true,
1350
+ text: r.keywordHit === false && hit !== void 0 ? `${t.wTestOk(r.items, r.title)} ${t.wTestNoHit(hit)}` : r.keywordHit === true && hit !== void 0 ? `${t.wTestOk(r.items, r.title)} ${t.wTestHit(hit)}` : t.wTestOk(r.items, r.title)
1351
+ });
1352
+ };
1353
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Modal, { title: existing ? t.wTitleEdit : t.wTitleAdd, onClose: () => onDone(), children: [
1354
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1355
+ t.wUrl,
1356
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: watch.url, autoComplete: "off", autoFocus: !existing, placeholder: "https://example.com/news.xml", onChange: (e) => set({ url: e.target.value }) })
1357
+ ] }),
1358
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.wUrlHint }),
1359
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1360
+ t.wLabel,
1361
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: watch.label, placeholder: hostOf(watch.url), onChange: (e) => set({ label: e.target.value }) })
1362
+ ] }),
1363
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1364
+ t.wKeywords,
1365
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: watch.keywords, placeholder: lang === "zh" ? "\u4E0A\u65B0, \u8865\u4E01, \u9762\u8BD5" : "release, patch, interview", onChange: (e) => set({ keywords: e.target.value }) })
1366
+ ] }),
1367
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.wKeywordsHint }),
1368
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row", children: [
1369
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1370
+ t.wEvery,
1371
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "number", min: 15, max: 1440, step: 15, value: watch.intervalMinutes, onChange: (e) => set({ intervalMinutes: Number(e.target.value) }) })
1372
+ ] }),
1373
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-check", children: [
1374
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: watch.enabled, onChange: (e) => set({ enabled: e.target.checked }) }),
1375
+ t.sEnabled
1376
+ ] })
1377
+ ] }),
1378
+ tested === void 0 ? null : tested.excerpt === "" ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-preview", children: tested.excerpt }),
1379
+ message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `mishu-preview ${message.ok ? "" : "mishu-danger"}`, children: [
1380
+ message.text,
1381
+ message.ok ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "watch-setup" }, lang, locale, openChat: openChat2, compact: true })
1382
+ ] }),
1383
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1384
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy || watch.url.trim() === "", onClick: () => {
1385
+ void test();
1386
+ }, children: t.wTest }),
1387
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || watch.url.trim() === "", onClick: () => {
1388
+ void save(true);
1389
+ }, children: busy ? t.wTesting : t.wSaveAndCheck }),
1390
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
1391
+ ] }),
1392
+ existing ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "mishu-hint", children: [
1393
+ t.wAskSetup,
1394
+ " ",
1395
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "watch-setup" }, lang, locale, openChat: openChat2, compact: true })
1153
1396
  ] })
1154
1397
  ] });
1155
1398
  }
1399
+ function hostOf(url) {
1400
+ try {
1401
+ return new URL(url).hostname;
1402
+ } catch {
1403
+ return "";
1404
+ }
1405
+ }
1156
1406
 
1157
1407
  // src/client/Board.tsx
1158
- var import_jsx_runtime5 = require("react/jsx-runtime");
1408
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1159
1409
  var SOURCE_KEY = "dsh-mishu.source";
1160
1410
  function loadSource() {
1161
1411
  try {
@@ -1191,15 +1441,15 @@ function saveWidths(widths) {
1191
1441
  }
1192
1442
  }
1193
1443
  function MishuBoard({ locale, openChat: openChat2 }) {
1194
- const [board, setBoard] = (0, import_react5.useState)();
1195
- const [error, setError] = (0, import_react5.useState)();
1196
- const [busy, setBusy] = (0, import_react5.useState)(false);
1197
- const [syncing, setSyncing] = (0, import_react5.useState)(false);
1198
- const [dropOn, setDropOn] = (0, import_react5.useState)();
1199
- const [widths, setWidths] = (0, import_react5.useState)(loadWidths);
1200
- const [tab, setTab] = (0, import_react5.useState)("board");
1201
- const [openCard, setOpenCard] = (0, import_react5.useState)();
1202
- const [source, setSourceState] = (0, import_react5.useState)(loadSource);
1444
+ const [board, setBoard] = (0, import_react6.useState)();
1445
+ const [error, setError] = (0, import_react6.useState)();
1446
+ const [busy, setBusy] = (0, import_react6.useState)(false);
1447
+ const [syncing, setSyncing] = (0, import_react6.useState)(false);
1448
+ const [dropOn, setDropOn] = (0, import_react6.useState)();
1449
+ const [widths, setWidths] = (0, import_react6.useState)(loadWidths);
1450
+ const [tab, setTab] = (0, import_react6.useState)("board");
1451
+ const [openCard, setOpenCard] = (0, import_react6.useState)();
1452
+ const [source, setSourceState] = (0, import_react6.useState)(loadSource);
1203
1453
  const setSource = (next) => {
1204
1454
  setSourceState(next);
1205
1455
  try {
@@ -1207,11 +1457,11 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1207
1457
  } catch {
1208
1458
  }
1209
1459
  };
1210
- const dragged = (0, import_react5.useRef)(void 0);
1211
- const columnsRef = (0, import_react5.useRef)(null);
1460
+ const dragged = (0, import_react6.useRef)(void 0);
1461
+ const columnsRef = (0, import_react6.useRef)(null);
1212
1462
  const lang = board?.lang ?? uiLang(locale());
1213
1463
  const t = TEXT[lang];
1214
- const take = (0, import_react5.useCallback)((result) => {
1464
+ const take = (0, import_react6.useCallback)((result) => {
1215
1465
  if (result.ok) {
1216
1466
  setBoard(result.board);
1217
1467
  setError(void 0);
@@ -1219,8 +1469,8 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1219
1469
  setError(result.message);
1220
1470
  }
1221
1471
  }, []);
1222
- const load = (0, import_react5.useCallback)(() => mishuApi.board(locale()).then(take), [locale, take]);
1223
- (0, import_react5.useEffect)(() => {
1472
+ const load = (0, import_react6.useCallback)(() => mishuApi.board(locale()).then(take), [locale, take]);
1473
+ (0, import_react6.useEffect)(() => {
1224
1474
  void load();
1225
1475
  const timer = setInterval(() => {
1226
1476
  void load();
@@ -1315,7 +1565,7 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1315
1565
  const key = cardKey(item);
1316
1566
  setOpenCard((current) => current === key ? void 0 : key);
1317
1567
  };
1318
- const card = (item, column) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1568
+ const card = (item, column) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1319
1569
  Card,
1320
1570
  {
1321
1571
  item,
@@ -1341,12 +1591,12 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1341
1591
  cardKey(item)
1342
1592
  );
1343
1593
  if (board === void 0) {
1344
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-page", children: [
1345
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-head", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-title", children: [
1346
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { children: t.title }),
1347
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RestartButton, { lang, locale })
1594
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-page", children: [
1595
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-head", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-title", children: [
1596
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h1", { children: t.title }),
1597
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RestartButton, { lang, locale })
1348
1598
  ] }) }),
1349
- error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-error", children: [
1599
+ error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-error", children: [
1350
1600
  t.failed,
1351
1601
  error
1352
1602
  ] })
@@ -1368,10 +1618,11 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1368
1618
  { id: "all", label: t.all },
1369
1619
  { id: "github", label: t.sourceGithub },
1370
1620
  { id: "mail", label: t.sourceMail },
1621
+ { id: "watch", label: t.sourceWatch },
1371
1622
  { id: "manual", label: t.sourceManual }
1372
1623
  ];
1373
1624
  const template = `minmax(0, ${widths[0]}fr) 10px minmax(0, ${widths[1]}fr) 10px minmax(0, ${widths[2]}fr)`;
1374
- const divider = (index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1625
+ const divider = (index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1375
1626
  "div",
1376
1627
  {
1377
1628
  className: "mishu-divider",
@@ -1382,107 +1633,112 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1382
1633
  onDoubleClick: resetWidths
1383
1634
  }
1384
1635
  );
1385
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-page", "data-mishu-board": "", children: [
1386
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-head", children: [
1387
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-title", children: [
1388
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { children: t.title }),
1389
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-tabs", role: "tablist", children: [
1390
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "board", className: tab === "board" ? "active" : "", onClick: () => setTab("board"), children: t.tabBoard }),
1391
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "settings", className: tab === "settings" ? "active" : "", onClick: () => setTab("settings"), children: t.tabSettings })
1636
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-page", "data-mishu-board": "", children: [
1637
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-head", children: [
1638
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-title", children: [
1639
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h1", { children: t.title }),
1640
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-tabs", role: "tablist", children: [
1641
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "board", className: tab === "board" ? "active" : "", onClick: () => setTab("board"), children: t.tabBoard }),
1642
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "settings", className: tab === "settings" ? "active" : "", onClick: () => setTab("settings"), children: t.tabSettings })
1392
1643
  ] }),
1393
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RestartButton, { lang, locale })
1644
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RestartButton, { lang, locale })
1394
1645
  ] }),
1395
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-sources", children: [
1396
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
1397
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("i", { className: `mishu-dot ${board.sources.github.state}` }),
1646
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-sources", children: [
1647
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1648
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("i", { className: `mishu-dot ${board.sources.github.state}` }),
1398
1649
  board.sources.github.text,
1399
- board.sources.github.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "github-error" }, lang, locale, openChat: openChat2, compact: true }) : null
1650
+ board.sources.github.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AskAI, { topic: { kind: "github-error" }, lang, locale, openChat: openChat2, compact: true }) : null
1400
1651
  ] }),
1401
- board.sources.mail.map((m) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
1402
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("i", { className: `mishu-dot ${m.state}` }),
1652
+ board.sources.mail.map((m) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1653
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("i", { className: `mishu-dot ${m.state}` }),
1403
1654
  m.text,
1404
- m.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "mail-error", accountId: m.id }, lang, locale, openChat: openChat2, compact: true }) : null
1655
+ m.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AskAI, { topic: { kind: "mail-error", accountId: m.id }, lang, locale, openChat: openChat2, compact: true }) : null
1405
1656
  ] }, m.id)),
1406
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", disabled: syncing, onClick: () => {
1657
+ board.sources.watch.map((w) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1658
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("i", { className: `mishu-dot ${w.state}` }),
1659
+ w.text,
1660
+ w.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AskAI, { topic: { kind: "watch-error", watchId: w.id }, lang, locale, openChat: openChat2, compact: true }) : null
1661
+ ] }, `watch-${w.id}`)),
1662
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mishu-btn", disabled: syncing, onClick: () => {
1407
1663
  void sync();
1408
1664
  }, children: syncing ? t.syncing : t.sync })
1409
1665
  ] })
1410
1666
  ] }),
1411
- tab === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MishuSettings, { lang, locale, openChat: openChat2 }) : null,
1412
- tab === "settings" ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1413
- error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-error", children: [
1667
+ tab === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MishuSettings, { lang, locale, openChat: openChat2 }) : null,
1668
+ tab === "settings" ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1669
+ error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-error", children: [
1414
1670
  t.failed,
1415
1671
  error
1416
1672
  ] }),
1417
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "mishu-summary", children: [
1673
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mishu-summary", children: [
1418
1674
  board.summary,
1419
1675
  " ",
1420
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: { kind: "summary" }, lang, locale, openChat: openChat2, compact: true })
1676
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AskAI, { topic: { kind: "summary" }, lang, locale, openChat: openChat2, compact: true })
1421
1677
  ] }),
1422
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-metrics", children: [
1423
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-metric", children: [
1424
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-metric-label", children: t.metricHandle }),
1425
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-metric-value", children: [
1678
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-metrics", children: [
1679
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-metric", children: [
1680
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-metric-label", children: t.metricHandle }),
1681
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-metric-value", children: [
1426
1682
  metrics.handle,
1427
- metrics.overdue > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("small", { className: "mishu-danger", children: [
1683
+ metrics.overdue > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("small", { className: "mishu-danger", children: [
1428
1684
  metrics.overdue,
1429
1685
  " ",
1430
1686
  t.metricOverdue
1431
1687
  ] }) : null
1432
1688
  ] })
1433
1689
  ] }),
1434
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-metric", children: [
1435
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-metric-label", children: t.metricSoon }),
1436
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-metric-value", children: metrics.dueSoon })
1690
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-metric", children: [
1691
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-metric-label", children: t.metricSoon }),
1692
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-metric-value", children: metrics.dueSoon })
1437
1693
  ] }),
1438
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-metric", children: [
1439
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-metric-label", children: t.metricClosed }),
1440
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-metric-value", children: metrics.closedToday })
1694
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-metric", children: [
1695
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-metric-label", children: t.metricClosed }),
1696
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-metric-value", children: metrics.closedToday })
1441
1697
  ] }),
1442
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-metric", children: [
1443
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-metric-label", children: t.metricShadow }),
1444
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-metric-value", children: [
1698
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-metric", children: [
1699
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-metric-label", children: t.metricShadow }),
1700
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-metric-value", children: [
1445
1701
  metrics.shadow,
1446
- board.markRead === "shadow" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("small", { className: "mishu-warn", children: t.shadowTag }) : null
1702
+ board.markRead === "shadow" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("small", { className: "mishu-warn", children: t.shadowTag }) : null
1447
1703
  ] })
1448
1704
  ] })
1449
1705
  ] }),
1450
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-filters", role: "group", children: sources.map((s) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", "aria-pressed": source === s.id, className: `mishu-chip ${source === s.id ? "active" : ""}`, onClick: () => setSource(s.id), children: [
1706
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-filters", role: "group", children: sources.map((s) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { type: "button", "aria-pressed": source === s.id, className: `mishu-chip ${source === s.id ? "active" : ""}`, onClick: () => setSource(s.id), children: [
1451
1707
  s.label,
1452
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: count(s.id) })
1708
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: count(s.id) })
1453
1709
  ] }, s.id)) }),
1454
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-columns", ref: columnsRef, style: { ["--mishu-cols"]: template }, children: [
1455
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: `mishu-col ${dropOn === "handle" ? "drop" : ""}`, ...dropProps("handle"), "aria-label": t.handle, children: [
1456
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-col-head", children: [
1710
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-columns", ref: columnsRef, style: { ["--mishu-cols"]: template }, children: [
1711
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: `mishu-col ${dropOn === "handle" ? "drop" : ""}`, ...dropProps("handle"), "aria-label": t.handle, children: [
1712
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-col-head", children: [
1457
1713
  t.handle,
1458
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: columns.handle.length })
1714
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: columns.handle.length })
1459
1715
  ] }),
1460
- columns.handle.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-empty", children: t.emptyHandle }) : columns.handle.map((item) => card(item, "handle"))
1716
+ columns.handle.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-empty", children: t.emptyHandle }) : columns.handle.map((item) => card(item, "handle"))
1461
1717
  ] }),
1462
1718
  divider(0),
1463
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: `mishu-col ${dropOn === "remember" ? "drop" : ""}`, ...dropProps("remember"), "aria-label": t.remember, title: t.dropRemember, children: [
1464
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-col-head", children: [
1719
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: `mishu-col ${dropOn === "remember" ? "drop" : ""}`, ...dropProps("remember"), "aria-label": t.remember, title: t.dropRemember, children: [
1720
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-col-head", children: [
1465
1721
  t.remember,
1466
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: columns.remember.length })
1722
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: columns.remember.length })
1467
1723
  ] }),
1468
- columns.remember.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-empty", children: t.emptyRemember }) : columns.remember.map((item) => card(item, "remember")),
1469
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AddForm, { lang, locale, onAdded: (next) => setBoard(next) })
1724
+ columns.remember.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-empty", children: t.emptyRemember }) : columns.remember.map((item) => card(item, "remember")),
1725
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AddForm, { lang, locale, onAdded: (next) => setBoard(next) })
1470
1726
  ] }),
1471
1727
  divider(1),
1472
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: `mishu-col ${dropOn === "done" ? "drop" : ""}`, ...dropProps("done"), "aria-label": t.done, title: t.dropDone, children: [
1473
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-col-head", children: [
1728
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: `mishu-col ${dropOn === "done" ? "drop" : ""}`, ...dropProps("done"), "aria-label": t.done, title: t.dropDone, children: [
1729
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-col-head", children: [
1474
1730
  t.done,
1475
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: columns.done.total })
1731
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: columns.done.total })
1476
1732
  ] }),
1477
- columns.done.groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-empty", children: t.emptyDone }) : columns.done.groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { className: "mishu-group", children: [
1478
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("summary", { children: [
1733
+ columns.done.groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-empty", children: t.emptyDone }) : columns.done.groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("details", { className: "mishu-group", children: [
1734
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("summary", { children: [
1479
1735
  group.label,
1480
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: group.items.length })
1736
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: group.items.length })
1481
1737
  ] }),
1482
1738
  group.items.map((item) => card(item, "done"))
1483
1739
  ] }, group.reason)),
1484
- columns.done.total > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.doneHint }) : null,
1485
- metrics.shadow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-banner", children: t.shadow(metrics.shadow) }) : null
1740
+ columns.done.total > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mishu-hint", children: t.doneHint }) : null,
1741
+ metrics.shadow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-banner", children: t.shadow(metrics.shadow) }) : null
1486
1742
  ] })
1487
1743
  ] })
1488
1744
  ] })
@@ -1490,10 +1746,10 @@ function MishuBoard({ locale, openChat: openChat2 }) {
1490
1746
  }
1491
1747
  function Card({ item, column, lang, locale, busy, label, openChat: openChat2, open, onToggle, onAct, onDragStart, onDragEnd }) {
1492
1748
  const t = TEXT[lang];
1493
- const [detail, setDetail] = (0, import_react5.useState)();
1749
+ const [detail, setDetail] = (0, import_react6.useState)();
1494
1750
  const explain = item.explain;
1495
1751
  const compact = column === "done";
1496
- (0, import_react5.useEffect)(() => {
1752
+ (0, import_react6.useEffect)(() => {
1497
1753
  if (!open || item.target !== "matter" || detail !== void 0) return;
1498
1754
  let alive = true;
1499
1755
  void mishuApi.detail(locale(), item.id).then((r) => {
@@ -1503,11 +1759,11 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, op
1503
1759
  alive = false;
1504
1760
  };
1505
1761
  }, [open, item.target, item.id, detail, locale]);
1506
- const row = (name, text, className = "") => text === null || text === void 0 || text === "" ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `mishu-row-explain ${className}`, children: [
1507
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mishu-row-label", children: name }),
1508
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: text })
1762
+ const row = (name, text, className = "") => text === null || text === void 0 || text === "" ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `mishu-row-explain ${className}`, children: [
1763
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mishu-row-label", children: name }),
1764
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: text })
1509
1765
  ] });
1510
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1766
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1511
1767
  "div",
1512
1768
  {
1513
1769
  className: `mishu-card ${open ? "open" : ""} ${item.tone === "normal" ? "" : item.tone}`,
@@ -1518,7 +1774,7 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, op
1518
1774
  },
1519
1775
  onDragEnd,
1520
1776
  children: [
1521
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1777
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1522
1778
  "div",
1523
1779
  {
1524
1780
  className: "mishu-card-head",
@@ -1533,40 +1789,40 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, op
1533
1789
  onToggle();
1534
1790
  },
1535
1791
  children: [
1536
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mishu-caret", "aria-hidden": "true" }),
1537
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mishu-card-title", children: item.title })
1792
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mishu-caret", "aria-hidden": "true" }),
1793
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mishu-card-title", children: item.title })
1538
1794
  ]
1539
1795
  }
1540
1796
  ),
1541
- open ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-card-body", children: [
1542
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-card-meta", children: item.meta }),
1543
- !compact && explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-explain", children: [
1797
+ open ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-card-body", children: [
1798
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-card-meta", children: item.meta }),
1799
+ !compact && explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-explain", children: [
1544
1800
  row(t.what, explain.what),
1545
1801
  row(column === "remember" ? t.whyKeep : t.why, explain.why),
1546
1802
  row(t.fix, explain.fix, "mishu-fix")
1547
1803
  ] }) : null,
1548
- !compact && explain === null && item.note !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-card-note", children: item.note }) : null,
1549
- item.target === "matter" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-detail", children: detail === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-empty", children: t.loading }) : "error" in detail ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-danger", children: detail.error }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1550
- compact && detail.explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1804
+ !compact && explain === null && item.note !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-card-note", children: item.note }) : null,
1805
+ item.target === "matter" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-detail", children: detail === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-empty", children: t.loading }) : "error" in detail ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-danger", children: detail.error }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1806
+ compact && detail.explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1551
1807
  row(t.what, detail.explain.what),
1552
1808
  row(t.whyDone, detail.explain.why)
1553
1809
  ] }) : null,
1554
- detail.did.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row-explain", children: [
1555
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mishu-row-label", children: t.did }),
1556
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: detail.did.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: line }, i)) })
1810
+ detail.did.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-row-explain", children: [
1811
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mishu-row-label", children: t.did }),
1812
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: detail.did.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: line }, i)) })
1557
1813
  ] }) : null,
1558
- detail.messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-messages", children: [
1559
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mishu-row-label", children: t.messages(detail.messages.length) }),
1560
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { children: detail.messages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { children: [
1561
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: m.at }),
1814
+ detail.messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-messages", children: [
1815
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mishu-row-label", children: t.messages(detail.messages.length) }),
1816
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { children: detail.messages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { children: [
1817
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: m.at }),
1562
1818
  " ",
1563
1819
  m.title
1564
1820
  ] }, i)) })
1565
1821
  ] }) : null
1566
1822
  ] }) }) : null,
1567
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1568
- column === "handle" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2 }) : null,
1569
- item.actions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1823
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-actions", children: [
1824
+ column === "handle" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2 }) : null,
1825
+ item.actions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1570
1826
  "button",
1571
1827
  {
1572
1828
  type: "button",
@@ -1577,7 +1833,7 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, op
1577
1833
  },
1578
1834
  action
1579
1835
  )),
1580
- column === "handle" ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2, compact: true })
1836
+ column === "handle" ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2, compact: true })
1581
1837
  ] })
1582
1838
  ] }) : null
1583
1839
  ]
@@ -1587,11 +1843,11 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, op
1587
1843
  var EMPTY = { title: "", due: "", repeat: "none", category: "other", note: "" };
1588
1844
  function AddForm({ lang, locale, onAdded }) {
1589
1845
  const t = TEXT[lang];
1590
- const [open, setOpen] = (0, import_react5.useState)(false);
1591
- const [item, setItem] = (0, import_react5.useState)(EMPTY);
1592
- const [preview, setPreview] = (0, import_react5.useState)();
1593
- const [saving, setSaving] = (0, import_react5.useState)(false);
1594
- (0, import_react5.useEffect)(() => {
1846
+ const [open, setOpen] = (0, import_react6.useState)(false);
1847
+ const [item, setItem] = (0, import_react6.useState)(EMPTY);
1848
+ const [preview, setPreview] = (0, import_react6.useState)();
1849
+ const [saving, setSaving] = (0, import_react6.useState)(false);
1850
+ (0, import_react6.useEffect)(() => {
1595
1851
  if (!open || item.title.trim() === "" || item.due === "") {
1596
1852
  setPreview(void 0);
1597
1853
  return;
@@ -1602,7 +1858,7 @@ function AddForm({ lang, locale, onAdded }) {
1602
1858
  return () => clearTimeout(timer);
1603
1859
  }, [open, item, locale]);
1604
1860
  if (!open) {
1605
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setOpen(true), children: [
1861
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setOpen(true), children: [
1606
1862
  "+ ",
1607
1863
  t.add
1608
1864
  ] });
@@ -1620,49 +1876,49 @@ function AddForm({ lang, locale, onAdded }) {
1620
1876
  setPreview({ ok: false, text: result.message });
1621
1877
  }
1622
1878
  };
1623
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-add", children: [
1624
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1879
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-add", children: [
1880
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "mishu-field", children: [
1625
1881
  t.addTitle,
1626
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: item.title, placeholder: t.addTitlePlaceholder, onChange: set("title") })
1882
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { value: item.title, placeholder: t.addTitlePlaceholder, onChange: set("title") })
1627
1883
  ] }),
1628
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row", children: [
1629
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1884
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-row", children: [
1885
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "mishu-field", children: [
1630
1886
  t.addDue,
1631
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "date", value: item.due, onChange: set("due") })
1887
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "date", value: item.due, onChange: set("due") })
1632
1888
  ] }),
1633
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1889
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "mishu-field", children: [
1634
1890
  t.addRepeat,
1635
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { value: item.repeat, onChange: set("repeat"), children: Object.entries(t.repeats).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value, children: text }, value)) })
1891
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { value: item.repeat, onChange: set("repeat"), children: Object.entries(t.repeats).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value, children: text }, value)) })
1636
1892
  ] })
1637
1893
  ] }),
1638
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-row", children: [
1639
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1894
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-row", children: [
1895
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "mishu-field", children: [
1640
1896
  t.addCategory,
1641
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { value: item.category, onChange: set("category"), children: Object.entries(t.categories).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value, children: text }, value)) })
1897
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { value: item.category, onChange: set("category"), children: Object.entries(t.categories).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value, children: text }, value)) })
1642
1898
  ] }),
1643
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mishu-field", children: [
1899
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "mishu-field", children: [
1644
1900
  t.addNote,
1645
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { value: item.note, onChange: set("note") })
1901
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { value: item.note, onChange: set("note") })
1646
1902
  ] })
1647
1903
  ] }),
1648
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `mishu-preview ${preview?.ok === false ? "mishu-danger" : ""}`, children: preview?.text ?? t.previewHint }),
1649
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mishu-actions", children: [
1650
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: saving || preview?.ok !== true, onClick: () => {
1904
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `mishu-preview ${preview?.ok === false ? "mishu-danger" : ""}`, children: preview?.text ?? t.previewHint }),
1905
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mishu-actions", children: [
1906
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: saving || preview?.ok !== true, onClick: () => {
1651
1907
  void save();
1652
1908
  }, children: t.save }),
1653
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
1909
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
1654
1910
  setOpen(false);
1655
1911
  setItem(EMPTY);
1656
1912
  }, children: t.cancel })
1657
1913
  ] }),
1658
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mishu-hint", children: t.chatHint })
1914
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mishu-hint", children: t.chatHint })
1659
1915
  ] });
1660
1916
  }
1661
1917
  function RestartButton({ lang, locale }) {
1662
1918
  const t = TEXT[lang];
1663
- const [why, setWhy] = (0, import_react5.useState)();
1664
- const [status, setStatus] = (0, import_react5.useState)();
1665
- (0, import_react5.useEffect)(() => {
1919
+ const [why, setWhy] = (0, import_react6.useState)();
1920
+ const [status, setStatus] = (0, import_react6.useState)();
1921
+ (0, import_react6.useEffect)(() => {
1666
1922
  void restartApi.info(locale()).then((r) => {
1667
1923
  if (r.ok && !r.supported) setWhy(r.why);
1668
1924
  });
@@ -1682,12 +1938,12 @@ function RestartButton({ lang, locale }) {
1682
1938
  setStatus({ ok: true, text: await reconnect(locale) ? t.restartReloading : t.restartSlow });
1683
1939
  }
1684
1940
  };
1685
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1686
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mishu-btn", title: why === void 0 ? t.restartTip : `${t.restartTip}
1941
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1942
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mishu-btn", title: why === void 0 ? t.restartTip : `${t.restartTip}
1687
1943
  ${why}`, disabled: status?.ok === true, onClick: () => {
1688
1944
  void restart();
1689
1945
  }, children: t.restart }),
1690
- status === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: status.ok ? "mishu-hint" : "mishu-hint mishu-warn", children: status.text })
1946
+ status === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: status.ok ? "mishu-hint" : "mishu-hint mishu-warn", children: status.text })
1691
1947
  ] });
1692
1948
  }
1693
1949
  async function reconnect(locale) {
@@ -1813,10 +2069,17 @@ var STYLES = `
1813
2069
  .mishu-chip span{color:${FAINT}}
1814
2070
  .mishu-chip.active{border-color:${ACCENT};color:${ACCENT}}
1815
2071
  .mishu-chip.active span{color:${ACCENT}}
1816
- .mishu-settings{display:flex;flex-direction:column;gap:12px;max-width:760px}
1817
- .mishu-panel{background:${LAYER1};border-radius:12px;padding:12px 14px}
1818
- .mishu-panel h2{font-size:14px;font-weight:600;margin:0 0 8px}
2072
+ .mishu-settings{display:flex;flex-direction:column;gap:8px;max-width:760px}
2073
+ .mishu-panel{background:${LAYER1};border:1px solid transparent;border-radius:12px;padding:6px 10px}
2074
+ .mishu-panel.open{border-color:${LINE}}
2075
+ .mishu-panel .mishu-card-head{font-size:14px;padding:6px 4px}
2076
+ .mishu-panel .mishu-card-body{padding:2px 6px 8px}
1819
2077
  .mishu-panel h3{font-size:13px;font-weight:600;margin:14px 0 6px}
2078
+ .mishu-fold+.mishu-fold{margin-top:6px}
2079
+ .mishu-fold .mishu-fold{background:${LAYER2}}
2080
+ .mishu-card-aside{flex:0 0 auto;display:inline-flex;align-items:center;margin-left:auto}
2081
+ .mishu-check-inline{margin:0}
2082
+ .mishu-check-inline input{cursor:pointer}
1820
2083
  .mishu-notify-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:6px}
1821
2084
  .mishu-notify-row input[type=time]{font:inherit;font-size:13px;color:${TEXT2};background:${LAYER2};border:1px solid ${LINE_STRONG};border-radius:6px;padding:2px 6px}
1822
2085
  .mishu-grid5{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px;margin-bottom:8px}
@@ -1834,18 +2097,18 @@ var STYLES = `
1834
2097
  `;
1835
2098
 
1836
2099
  // src/client/index.tsx
1837
- var import_jsx_runtime6 = require("react/jsx-runtime");
2100
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1838
2101
  var PACKAGE_NAME = "dsh-mishu";
1839
2102
  var inject = ["slots", "locale"];
1840
2103
  var PANEL_ID = "dsh-mishu";
1841
2104
  var NS = "dsh-mishu";
1842
2105
  var openChat;
1843
2106
  function MishuIcon({ size }) {
1844
- return /* @__PURE__ */ (0, import_jsx_runtime6.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: [
1845
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "5", y: "4", width: "14", height: "17", rx: "2" }),
1846
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 4h6v3H9z" }),
1847
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 12l2 2 4-4" }),
1848
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 17h6" })
2107
+ return /* @__PURE__ */ (0, import_jsx_runtime7.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: [
2108
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "5", y: "4", width: "14", height: "17", rx: "2" }),
2109
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 4h6v3H9z" }),
2110
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 12l2 2 4-4" }),
2111
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 17h6" })
1849
2112
  ] });
1850
2113
  }
1851
2114
  function apply(ctx) {