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