dsh-mishu 0.5.1 → 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 +20 -4
- package/lib/client.js +576 -275
- package/lib/core/github/device.js +129 -0
- package/lib/core/github/token.js +2 -0
- package/lib/core/index.js +6 -4
- package/lib/core/mail/account.js +61 -5
- package/lib/core/mail/sync.js +34 -5
- package/lib/core/restart.js +179 -0
- package/lib/core/secrets.js +102 -2
- package/lib/core/settings.js +2 -2
- package/lib/dsh/api.js +44 -5
- package/lib/dsh/config.js +2 -1
- package/lib/dsh/runtime.js +8 -3
- 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 -3
- 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 +88 -0
- 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 +10 -1
- 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) {
|
|
@@ -60,12 +60,19 @@ var mishuApi = {
|
|
|
60
60
|
add: (lang, item) => post("/add", { lang, item }),
|
|
61
61
|
ask: (lang, ask) => post("/ask", { lang, ask })
|
|
62
62
|
};
|
|
63
|
+
var restartApi = {
|
|
64
|
+
info: (lang) => post("/restart/info", { lang }),
|
|
65
|
+
restart: (lang) => post("/restart", { lang })
|
|
66
|
+
};
|
|
63
67
|
var settingsApi = {
|
|
64
68
|
load: (lang) => post("/settings", { lang }),
|
|
65
69
|
save: (lang, settings) => post("/settings/save", { lang, settings }),
|
|
66
70
|
testGithub: (lang) => post("/github/test", { lang }),
|
|
67
71
|
saveToken: (lang, token) => post("/github/token/save", { lang, token }),
|
|
68
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 }),
|
|
69
76
|
saveMail: (lang, account, password) => post("/mail/save", { lang, account, password }),
|
|
70
77
|
testMail: (lang, account, password) => post("/mail/test", { lang, account, password }),
|
|
71
78
|
deleteMail: (lang, id) => post("/mail/delete", { lang, id }),
|
|
@@ -134,6 +141,13 @@ var zh = {
|
|
|
134
141
|
resize: "\u62D6\u52A8\u8C03\u6574\u5BBD\u5EA6\uFF0C\u53CC\u51FB\u6062\u590D\u7B49\u5BBD",
|
|
135
142
|
tabBoard: "\u770B\u677F",
|
|
136
143
|
tabSettings: "\u8BBE\u7F6E",
|
|
144
|
+
restart: "\u91CD\u542F DSH",
|
|
145
|
+
restartTip: "\u91CD\u88C5\u6216\u5347\u7EA7\u63D2\u4EF6\u540E\uFF0C\u53EF\u4EE5\u7528\u8FD9\u4E2A\u6309\u952E\u91CD\u542F\u672C DSH",
|
|
146
|
+
restartConfirm: "\u91CD\u542F DSH\uFF1F\u5B89\u88C5\u63D2\u4EF6\u6216\u8005\u63D2\u4EF6\u66F4\u65B0\u540E\u9700\u8981\u91CD\u542F DSH\u3002",
|
|
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",
|
|
137
151
|
all: "\u5168\u90E8",
|
|
138
152
|
sourceGithub: "GitHub",
|
|
139
153
|
sourceMail: "\u90AE\u4EF6",
|
|
@@ -151,6 +165,19 @@ var zh = {
|
|
|
151
165
|
sTokenGh: "\u7528 GitHub CLI\uFF08gh\uFF09\u767B\u5F55\u7684\u8D26\u53F7\uFF0Ctoken \u5728\u7CFB\u7EDF\u94A5\u5319\u4E32\u91CC",
|
|
152
166
|
sTokenKeychain: "\u4F60\u5728\u8FD9\u91CC\u586B\u7684 token\uFF0C\u5B58\u5728\u7CFB\u7EDF\u94A5\u5319\u4E32\u91CC",
|
|
153
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",
|
|
154
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",
|
|
155
182
|
sTokenNew: "\u53BB GitHub \u751F\u6210\uFF08\u6743\u9650\u5DF2\u52FE\u597D\uFF09",
|
|
156
183
|
sTokenSave: "\u68C0\u67E5\u5E76\u4FDD\u5B58",
|
|
@@ -172,6 +199,7 @@ var zh = {
|
|
|
172
199
|
sMail: "\u90AE\u7BB1",
|
|
173
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",
|
|
174
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`,
|
|
175
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`,
|
|
176
204
|
sPasswordTestOnly: "\u6CA1\u6709\u94A5\u5319\u4E32\uFF1A\u8FD9\u91CC\u586B\u7684\u53EA\u7528\u6765\u6D4B\u8BD5\u8FDE\u63A5\uFF0C\u4E0D\u4F1A\u4FDD\u5B58",
|
|
177
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" },
|
|
@@ -195,6 +223,15 @@ var zh = {
|
|
|
195
223
|
sMailOk: (n) => `\u8FDE\u4E0A\u4E86\uFF0C\u6700\u8FD1\u6709 ${n} \u5C01\u672A\u8BFB\u90AE\u4EF6`,
|
|
196
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`,
|
|
197
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`,
|
|
198
235
|
sFeishu: "\u98DE\u4E66",
|
|
199
236
|
sComing: "\u5373\u5C06\u63A5\u5165",
|
|
200
237
|
ai: "+AI",
|
|
@@ -258,6 +295,13 @@ var en = {
|
|
|
258
295
|
resize: "Drag to resize; double-click to make them equal",
|
|
259
296
|
tabBoard: "Board",
|
|
260
297
|
tabSettings: "Settings",
|
|
298
|
+
restart: "Restart DSH",
|
|
299
|
+
restartTip: "After reinstalling or upgrading plugins, use this to restart DSH",
|
|
300
|
+
restartConfirm: "Restart DSH? DSH needs a restart after you install or update plugins.",
|
|
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.",
|
|
261
305
|
all: "All",
|
|
262
306
|
sourceGithub: "GitHub",
|
|
263
307
|
sourceMail: "Mail",
|
|
@@ -275,6 +319,19 @@ var en = {
|
|
|
275
319
|
sTokenGh: "The account the GitHub CLI (gh) is signed in to; the token stays in the system keychain",
|
|
276
320
|
sTokenKeychain: "The token you pasted here, kept in the system keychain",
|
|
277
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",
|
|
278
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.",
|
|
279
336
|
sTokenNew: "Create one on GitHub (scopes pre-ticked)",
|
|
280
337
|
sTokenSave: "Check and save",
|
|
@@ -296,6 +353,7 @@ var en = {
|
|
|
296
353
|
sMail: "Mail",
|
|
297
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.",
|
|
298
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.`,
|
|
299
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.`,
|
|
300
358
|
sPasswordTestOnly: "No keychain: used only to test the connection, not saved",
|
|
301
359
|
secretKinds: { macos: "the macOS Keychain", windows: "Windows Credential Manager", linux: "the Linux keyring (Secret Service)", memory: "memory (tests)" },
|
|
@@ -319,6 +377,15 @@ var en = {
|
|
|
319
377
|
sMailOk: (n) => `Connected; ${n} unread messages recently`,
|
|
320
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.`,
|
|
321
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.`,
|
|
322
389
|
sFeishu: "Feishu / Lark",
|
|
323
390
|
sComing: "Coming soon",
|
|
324
391
|
ai: "+AI",
|
|
@@ -379,19 +446,47 @@ function AskAI({ topic, lang, locale, openChat: openChat2, compact = false }) {
|
|
|
379
446
|
}
|
|
380
447
|
|
|
381
448
|
// src/client/Settings.tsx
|
|
449
|
+
var import_react3 = require("react");
|
|
450
|
+
|
|
451
|
+
// src/client/Modal.tsx
|
|
382
452
|
var import_react2 = require("react");
|
|
453
|
+
var import_react_dom = require("react-dom");
|
|
383
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");
|
|
384
479
|
var CATEGORIES = ["document", "bill", "birthday", "renewal", "other"];
|
|
385
480
|
function MishuSettings({ lang, locale, openChat: openChat2 }) {
|
|
386
481
|
const t = TEXT[lang];
|
|
387
|
-
const [view, setView] = (0,
|
|
388
|
-
const [error, setError] = (0,
|
|
389
|
-
const [note, setNote] = (0,
|
|
390
|
-
const [lead, setLead] = (0,
|
|
391
|
-
const [githubTest, setGithubTest] = (0,
|
|
392
|
-
const [confirmOn, setConfirmOn] = (0,
|
|
393
|
-
const [pasting, setPasting] = (0,
|
|
394
|
-
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)();
|
|
395
490
|
const take = (result, saved) => {
|
|
396
491
|
if (result.ok) {
|
|
397
492
|
setView(result.view);
|
|
@@ -402,11 +497,11 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
|
|
|
402
497
|
setError(result.message);
|
|
403
498
|
}
|
|
404
499
|
};
|
|
405
|
-
(0,
|
|
500
|
+
(0, import_react3.useEffect)(() => {
|
|
406
501
|
void settingsApi.load(locale()).then((r) => take(r));
|
|
407
502
|
}, [locale]);
|
|
408
503
|
if (view === void 0) {
|
|
409
|
-
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: [
|
|
410
505
|
t.failed,
|
|
411
506
|
error
|
|
412
507
|
] }) });
|
|
@@ -414,95 +509,96 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
|
|
|
414
509
|
const save = async (settings) => take(await settingsApi.save(locale(), settings), t.sSaved);
|
|
415
510
|
const token = view.github.token;
|
|
416
511
|
const secretKind = t.secretKinds[view.secrets.kind] ?? view.secrets.kind;
|
|
417
|
-
return /* @__PURE__ */ (0,
|
|
418
|
-
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: [
|
|
419
514
|
t.failed,
|
|
420
515
|
error
|
|
421
516
|
] }),
|
|
422
|
-
note === void 0 ? null : /* @__PURE__ */ (0,
|
|
423
|
-
/* @__PURE__ */ (0,
|
|
424
|
-
/* @__PURE__ */ (0,
|
|
425
|
-
/* @__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: [
|
|
426
521
|
t.sLanguage,
|
|
427
|
-
/* @__PURE__ */ (0,
|
|
522
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: view.settings.language, onChange: (e) => {
|
|
428
523
|
void save({ language: e.target.value });
|
|
429
524
|
}, children: [
|
|
430
|
-
/* @__PURE__ */ (0,
|
|
431
|
-
/* @__PURE__ */ (0,
|
|
432
|
-
/* @__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" })
|
|
433
528
|
] })
|
|
434
529
|
] }),
|
|
435
|
-
/* @__PURE__ */ (0,
|
|
436
|
-
/* @__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: [
|
|
437
532
|
t.categories[c],
|
|
438
|
-
/* @__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) }) })
|
|
439
534
|
] }, c)) }),
|
|
440
|
-
/* @__PURE__ */ (0,
|
|
535
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
|
|
441
536
|
void save({ leadDays: lead });
|
|
442
537
|
}, children: t.sSave })
|
|
443
538
|
] }),
|
|
444
|
-
/* @__PURE__ */ (0,
|
|
445
|
-
/* @__PURE__ */ (0,
|
|
446
|
-
/* @__PURE__ */ (0,
|
|
447
|
-
/* @__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) => {
|
|
448
543
|
void save({ githubEnabled: e.target.checked });
|
|
449
544
|
} }),
|
|
450
545
|
t.sGithubOn
|
|
451
546
|
] }),
|
|
452
|
-
/* @__PURE__ */ (0,
|
|
453
|
-
/* @__PURE__ */ (0,
|
|
454
|
-
/* @__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 })
|
|
455
550
|
] }),
|
|
456
|
-
token.found ? /* @__PURE__ */ (0,
|
|
457
|
-
/* @__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: () => {
|
|
458
553
|
setGithubTest(t.sTesting);
|
|
459
554
|
void settingsApi.testGithub(locale()).then((r) => setGithubTest(r.ok ? t.sGithubOk(r.login) : `${t.failed}${r.message}`));
|
|
460
555
|
}, children: t.sTest }),
|
|
461
|
-
token.from === "env" || pasting ? null : /* @__PURE__ */ (0,
|
|
462
|
-
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: () => {
|
|
463
558
|
if (window.confirm(t.sTokenRemoveConfirm)) void settingsApi.deleteToken(locale()).then((r) => {
|
|
464
559
|
setGithubTest(void 0);
|
|
465
560
|
take(r);
|
|
466
561
|
});
|
|
467
562
|
}, children: t.sTokenRemove }) : null,
|
|
468
|
-
githubTest === void 0 ? null : /* @__PURE__ */ (0,
|
|
563
|
+
githubTest === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-hint", children: githubTest })
|
|
469
564
|
] }) : null,
|
|
470
|
-
!token.found || pasting ? /* @__PURE__ */ (0,
|
|
565
|
+
!token.found || pasting ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GithubConnect, { view, lang, locale, onSaved: (next, login) => {
|
|
471
566
|
setPasting(false);
|
|
472
567
|
setGithubTest(t.sTokenSaved(login));
|
|
473
568
|
take({ ok: true, view: next });
|
|
474
569
|
}, onCancel: token.found ? () => setPasting(false) : void 0 }) : null,
|
|
475
|
-
/* @__PURE__ */ (0,
|
|
570
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
476
571
|
t.sMarkRead,
|
|
477
|
-
/* @__PURE__ */ (0,
|
|
572
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: view.settings.markRead, onChange: (e) => {
|
|
478
573
|
const value = e.target.value;
|
|
479
574
|
if (value === "on") setConfirmOn(true);
|
|
480
575
|
else void save({ markRead: value });
|
|
481
576
|
}, children: [
|
|
482
|
-
/* @__PURE__ */ (0,
|
|
483
|
-
/* @__PURE__ */ (0,
|
|
484
|
-
/* @__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 })
|
|
485
580
|
] })
|
|
486
581
|
] }),
|
|
487
|
-
confirmOn ? /* @__PURE__ */ (0,
|
|
488
|
-
/* @__PURE__ */ (0,
|
|
489
|
-
/* @__PURE__ */ (0,
|
|
490
|
-
/* @__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: () => {
|
|
491
586
|
setConfirmOn(false);
|
|
492
587
|
void save({ markRead: "on" });
|
|
493
588
|
}, children: t.sConfirm }),
|
|
494
|
-
/* @__PURE__ */ (0,
|
|
589
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setConfirmOn(false), children: t.sCancel })
|
|
495
590
|
] })
|
|
496
591
|
] }) : null
|
|
497
592
|
] }),
|
|
498
|
-
/* @__PURE__ */ (0,
|
|
499
|
-
/* @__PURE__ */ (0,
|
|
500
|
-
/* @__PURE__ */ (0,
|
|
501
|
-
/* @__PURE__ */ (0,
|
|
502
|
-
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)(
|
|
503
598
|
AccountRow,
|
|
504
599
|
{
|
|
505
600
|
account,
|
|
601
|
+
secretsOk: view.secrets.available,
|
|
506
602
|
lang,
|
|
507
603
|
locale,
|
|
508
604
|
openChat: openChat2,
|
|
@@ -511,24 +607,133 @@ function MishuSettings({ lang, locale, openChat: openChat2 }) {
|
|
|
511
607
|
},
|
|
512
608
|
account.id
|
|
513
609
|
)),
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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
|
+
)
|
|
518
625
|
] }),
|
|
519
|
-
/* @__PURE__ */ (0,
|
|
520
|
-
/* @__PURE__ */ (0,
|
|
521
|
-
/* @__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 })
|
|
522
629
|
] })
|
|
523
630
|
] });
|
|
524
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
|
+
}
|
|
525
730
|
function TokenForm({ view, lang, locale, onSaved, onCancel }) {
|
|
526
731
|
const t = TEXT[lang];
|
|
527
|
-
const [token, setToken] = (0,
|
|
528
|
-
const [busy, setBusy] = (0,
|
|
529
|
-
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)();
|
|
530
735
|
if (!view.secrets.available) {
|
|
531
|
-
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 ?? "") });
|
|
532
737
|
}
|
|
533
738
|
const save = async () => {
|
|
534
739
|
setBusy(true);
|
|
@@ -542,162 +747,191 @@ function TokenForm({ view, lang, locale, onSaved, onCancel }) {
|
|
|
542
747
|
setMessage(r.message);
|
|
543
748
|
}
|
|
544
749
|
};
|
|
545
|
-
return /* @__PURE__ */ (0,
|
|
546
|
-
/* @__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: [
|
|
547
752
|
t.sTokenPaste,
|
|
548
|
-
/* @__PURE__ */ (0,
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "password", value: token, autoComplete: "off", spellCheck: false, placeholder: "ghp_\u2026", onChange: (e) => {
|
|
549
754
|
setToken(e.target.value);
|
|
550
755
|
setMessage(void 0);
|
|
551
756
|
} })
|
|
552
757
|
] }),
|
|
553
|
-
/* @__PURE__ */ (0,
|
|
554
|
-
message === void 0 ? null : /* @__PURE__ */ (0,
|
|
555
|
-
/* @__PURE__ */ (0,
|
|
556
|
-
/* @__PURE__ */ (0,
|
|
557
|
-
/* @__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: () => {
|
|
558
763
|
void save();
|
|
559
764
|
}, children: busy ? t.sTesting : t.sTokenSave }),
|
|
560
|
-
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 })
|
|
561
766
|
] })
|
|
562
767
|
] });
|
|
563
768
|
}
|
|
564
|
-
function AccountRow({ account, lang, locale, openChat: openChat2, onEdit, onView }) {
|
|
769
|
+
function AccountRow({ account, secretsOk, lang, locale, openChat: openChat2, onEdit, onView }) {
|
|
565
770
|
const t = TEXT[lang];
|
|
566
|
-
const [busy, setBusy] = (0,
|
|
771
|
+
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
567
772
|
const report = account.report;
|
|
568
|
-
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`;
|
|
569
|
-
|
|
570
|
-
|
|
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: [
|
|
571
777
|
account.label,
|
|
572
778
|
account.enabled ? "" : ` (${lang === "zh" ? "\u5DF2\u505C\u7528" : "disabled"})`
|
|
573
779
|
] }),
|
|
574
|
-
/* @__PURE__ */ (0,
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-card-meta", children: [
|
|
575
781
|
account.address,
|
|
576
782
|
" \xB7 ",
|
|
577
783
|
account.host,
|
|
578
784
|
":",
|
|
579
785
|
account.port
|
|
580
786
|
] }),
|
|
581
|
-
/* @__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: [
|
|
582
789
|
status,
|
|
583
|
-
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
|
|
584
791
|
] }),
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
/* @__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: () => {
|
|
588
794
|
setBusy(true);
|
|
589
795
|
void settingsApi.syncMail(locale(), account.id).then((r) => {
|
|
590
796
|
setBusy(false);
|
|
591
797
|
onView(r);
|
|
592
798
|
});
|
|
593
799
|
}, children: busy ? t.sTesting : t.sCheckNow }),
|
|
594
|
-
/* @__PURE__ */ (0,
|
|
595
|
-
/* @__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: () => {
|
|
596
802
|
if (window.confirm(t.sDeleteConfirm)) void settingsApi.deleteMail(locale(), account.id).then(onView);
|
|
597
803
|
}, children: t.sDelete })
|
|
598
804
|
] })
|
|
599
805
|
] });
|
|
600
806
|
}
|
|
601
|
-
function
|
|
807
|
+
function MailDialog({ draft, view, lang, locale, openChat: openChat2, onDone }) {
|
|
602
808
|
const t = TEXT[lang];
|
|
603
|
-
const
|
|
604
|
-
const [
|
|
605
|
-
const [
|
|
606
|
-
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);
|
|
607
816
|
const preset = view.presets.find((p) => p.id === account.preset) ?? view.presets[view.presets.length - 1];
|
|
608
817
|
const custom = preset.id === "custom";
|
|
609
|
-
const existing = draft.id !== void 0;
|
|
610
818
|
const set = (patch) => {
|
|
611
819
|
setAccount({ ...account, ...patch });
|
|
612
820
|
setMessage(void 0);
|
|
821
|
+
setFailedTest(false);
|
|
613
822
|
};
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
setBusy(false);
|
|
619
|
-
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" } : {} });
|
|
620
827
|
};
|
|
621
|
-
const
|
|
622
|
-
|
|
828
|
+
const typed = password.replace(/\s+/g, "");
|
|
829
|
+
const lengthOff = preset.passwordLength !== null && typed !== "" && typed.length !== preset.passwordLength;
|
|
830
|
+
const save = async (unread) => {
|
|
623
831
|
const r = await settingsApi.saveMail(locale(), account, password);
|
|
624
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);
|
|
625
840
|
if (r.ok) {
|
|
626
|
-
|
|
627
|
-
onDone(r.view);
|
|
841
|
+
await save(r.unread);
|
|
628
842
|
} else {
|
|
843
|
+
setBusy(false);
|
|
844
|
+
setFailedTest(true);
|
|
629
845
|
setMessage({ ok: false, text: r.message });
|
|
630
846
|
}
|
|
631
847
|
};
|
|
632
|
-
return /* @__PURE__ */ (0,
|
|
633
|
-
/* @__PURE__ */ (0,
|
|
634
|
-
t.sProvider,
|
|
635
|
-
/* @__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)) })
|
|
636
|
-
] }),
|
|
637
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: preset.supported ? "mishu-hint" : "mishu-hint mishu-danger", children: [
|
|
638
|
-
preset.howTo,
|
|
639
|
-
preset.supported ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id }, lang, locale, openChat: openChat2, compact: true }) : null
|
|
640
|
-
] }),
|
|
641
|
-
/* @__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: [
|
|
642
850
|
t.sAddress,
|
|
643
|
-
/* @__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) })
|
|
644
852
|
] }),
|
|
645
|
-
/* @__PURE__ */ (0,
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
/* @__PURE__ */ (0,
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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)) })
|
|
859
|
+
] }),
|
|
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
|
|
654
872
|
] }),
|
|
655
|
-
/* @__PURE__ */ (0,
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
656
874
|
t.sPassword,
|
|
657
|
-
/* @__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) => {
|
|
658
876
|
setPassword(e.target.value);
|
|
659
877
|
setMessage(void 0);
|
|
878
|
+
setFailedTest(false);
|
|
660
879
|
} })
|
|
661
880
|
] }),
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
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: [
|
|
665
885
|
t.sHost,
|
|
666
|
-
/* @__PURE__ */ (0,
|
|
886
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: account.host ?? "", placeholder: "imap.example.com", onChange: (e) => set({ host: e.target.value }) })
|
|
667
887
|
] }),
|
|
668
|
-
/* @__PURE__ */ (0,
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
669
889
|
t.sPort,
|
|
670
|
-
/* @__PURE__ */ (0,
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "number", value: account.port ?? 993, onChange: (e) => set({ port: Number(e.target.value) }) })
|
|
671
891
|
] })
|
|
672
892
|
] }) : null,
|
|
673
|
-
/* @__PURE__ */ (0,
|
|
674
|
-
/* @__PURE__ */ (0,
|
|
675
|
-
|
|
676
|
-
/* @__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
|
+
] })
|
|
677
904
|
] }),
|
|
678
|
-
/* @__PURE__ */ (0,
|
|
679
|
-
/* @__PURE__ */ (0,
|
|
680
|
-
|
|
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
|
+
] })
|
|
681
914
|
] })
|
|
682
915
|
] }),
|
|
683
|
-
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: [
|
|
684
917
|
message.text,
|
|
685
|
-
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 })
|
|
686
919
|
] }),
|
|
687
|
-
/* @__PURE__ */ (0,
|
|
688
|
-
/* @__PURE__ */ (0,
|
|
689
|
-
void
|
|
690
|
-
}, children: t.
|
|
691
|
-
/* @__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);
|
|
692
926
|
void save();
|
|
693
|
-
}, children: t.
|
|
694
|
-
/* @__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 })
|
|
695
929
|
] })
|
|
696
930
|
] });
|
|
697
931
|
}
|
|
698
932
|
|
|
699
933
|
// src/client/Board.tsx
|
|
700
|
-
var
|
|
934
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
701
935
|
var SOURCE_KEY = "dsh-mishu.source";
|
|
702
936
|
function loadSource() {
|
|
703
937
|
try {
|
|
@@ -733,14 +967,14 @@ function saveWidths(widths) {
|
|
|
733
967
|
}
|
|
734
968
|
}
|
|
735
969
|
function MishuBoard({ locale, openChat: openChat2 }) {
|
|
736
|
-
const [board, setBoard] = (0,
|
|
737
|
-
const [error, setError] = (0,
|
|
738
|
-
const [busy, setBusy] = (0,
|
|
739
|
-
const [syncing, setSyncing] = (0,
|
|
740
|
-
const [dropOn, setDropOn] = (0,
|
|
741
|
-
const [widths, setWidths] = (0,
|
|
742
|
-
const [tab, setTab] = (0,
|
|
743
|
-
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);
|
|
744
978
|
const setSource = (next) => {
|
|
745
979
|
setSourceState(next);
|
|
746
980
|
try {
|
|
@@ -748,11 +982,11 @@ function MishuBoard({ locale, openChat: openChat2 }) {
|
|
|
748
982
|
} catch {
|
|
749
983
|
}
|
|
750
984
|
};
|
|
751
|
-
const dragged = (0,
|
|
752
|
-
const columnsRef = (0,
|
|
985
|
+
const dragged = (0, import_react4.useRef)(void 0);
|
|
986
|
+
const columnsRef = (0, import_react4.useRef)(null);
|
|
753
987
|
const lang = board?.lang ?? uiLang(locale());
|
|
754
988
|
const t = TEXT[lang];
|
|
755
|
-
const take = (0,
|
|
989
|
+
const take = (0, import_react4.useCallback)((result) => {
|
|
756
990
|
if (result.ok) {
|
|
757
991
|
setBoard(result.board);
|
|
758
992
|
setError(void 0);
|
|
@@ -760,8 +994,8 @@ function MishuBoard({ locale, openChat: openChat2 }) {
|
|
|
760
994
|
setError(result.message);
|
|
761
995
|
}
|
|
762
996
|
}, []);
|
|
763
|
-
const load = (0,
|
|
764
|
-
(0,
|
|
997
|
+
const load = (0, import_react4.useCallback)(() => mishuApi.board(locale()).then(take), [locale, take]);
|
|
998
|
+
(0, import_react4.useEffect)(() => {
|
|
765
999
|
void load();
|
|
766
1000
|
const timer = setInterval(() => {
|
|
767
1001
|
void load();
|
|
@@ -851,7 +1085,7 @@ function MishuBoard({ locale, openChat: openChat2 }) {
|
|
|
851
1085
|
reopen: t.reopen,
|
|
852
1086
|
stop: t.stop
|
|
853
1087
|
};
|
|
854
|
-
const card = (item, column) => /* @__PURE__ */ (0,
|
|
1088
|
+
const card = (item, column) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
855
1089
|
Card,
|
|
856
1090
|
{
|
|
857
1091
|
item,
|
|
@@ -875,9 +1109,12 @@ function MishuBoard({ locale, openChat: openChat2 }) {
|
|
|
875
1109
|
`${item.target}-${item.id}`
|
|
876
1110
|
);
|
|
877
1111
|
if (board === void 0) {
|
|
878
|
-
return /* @__PURE__ */ (0,
|
|
879
|
-
/* @__PURE__ */ (0,
|
|
880
|
-
|
|
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 })
|
|
1116
|
+
] }) }),
|
|
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: [
|
|
881
1118
|
t.failed,
|
|
882
1119
|
error
|
|
883
1120
|
] })
|
|
@@ -902,7 +1139,7 @@ function MishuBoard({ locale, openChat: openChat2 }) {
|
|
|
902
1139
|
{ id: "manual", label: t.sourceManual }
|
|
903
1140
|
];
|
|
904
1141
|
const template = `minmax(0, ${widths[0]}fr) 10px minmax(0, ${widths[1]}fr) 10px minmax(0, ${widths[2]}fr)`;
|
|
905
|
-
const divider = (index) => /* @__PURE__ */ (0,
|
|
1142
|
+
const divider = (index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
906
1143
|
"div",
|
|
907
1144
|
{
|
|
908
1145
|
className: "mishu-divider",
|
|
@@ -913,106 +1150,107 @@ function MishuBoard({ locale, openChat: openChat2 }) {
|
|
|
913
1150
|
onDoubleClick: resetWidths
|
|
914
1151
|
}
|
|
915
1152
|
);
|
|
916
|
-
return /* @__PURE__ */ (0,
|
|
917
|
-
/* @__PURE__ */ (0,
|
|
918
|
-
/* @__PURE__ */ (0,
|
|
919
|
-
/* @__PURE__ */ (0,
|
|
920
|
-
/* @__PURE__ */ (0,
|
|
921
|
-
/* @__PURE__ */ (0,
|
|
922
|
-
/* @__PURE__ */ (0,
|
|
923
|
-
] })
|
|
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 })
|
|
1160
|
+
] }),
|
|
1161
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RestartButton, { lang, locale })
|
|
924
1162
|
] }),
|
|
925
|
-
/* @__PURE__ */ (0,
|
|
926
|
-
/* @__PURE__ */ (0,
|
|
927
|
-
/* @__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}` }),
|
|
928
1166
|
board.sources.github.text,
|
|
929
|
-
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
|
|
930
1168
|
] }),
|
|
931
|
-
board.sources.mail.map((m) => /* @__PURE__ */ (0,
|
|
932
|
-
/* @__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}` }),
|
|
933
1171
|
m.text,
|
|
934
|
-
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
|
|
935
1173
|
] }, m.id)),
|
|
936
|
-
/* @__PURE__ */ (0,
|
|
1174
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", disabled: syncing, onClick: () => {
|
|
937
1175
|
void sync();
|
|
938
1176
|
}, children: syncing ? t.syncing : t.sync })
|
|
939
1177
|
] })
|
|
940
1178
|
] }),
|
|
941
|
-
tab === "settings" ? /* @__PURE__ */ (0,
|
|
942
|
-
tab === "settings" ? null : /* @__PURE__ */ (0,
|
|
943
|
-
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: [
|
|
944
1182
|
t.failed,
|
|
945
1183
|
error
|
|
946
1184
|
] }),
|
|
947
|
-
/* @__PURE__ */ (0,
|
|
1185
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mishu-summary", children: [
|
|
948
1186
|
board.summary,
|
|
949
1187
|
" ",
|
|
950
|
-
/* @__PURE__ */ (0,
|
|
1188
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AskAI, { topic: { kind: "summary" }, lang, locale, openChat: openChat2, compact: true })
|
|
951
1189
|
] }),
|
|
952
|
-
/* @__PURE__ */ (0,
|
|
953
|
-
/* @__PURE__ */ (0,
|
|
954
|
-
/* @__PURE__ */ (0,
|
|
955
|
-
/* @__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: [
|
|
956
1194
|
metrics.handle,
|
|
957
|
-
metrics.overdue > 0 ? /* @__PURE__ */ (0,
|
|
1195
|
+
metrics.overdue > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("small", { className: "mishu-danger", children: [
|
|
958
1196
|
metrics.overdue,
|
|
959
1197
|
" ",
|
|
960
1198
|
t.metricOverdue
|
|
961
1199
|
] }) : null
|
|
962
1200
|
] })
|
|
963
1201
|
] }),
|
|
964
|
-
/* @__PURE__ */ (0,
|
|
965
|
-
/* @__PURE__ */ (0,
|
|
966
|
-
/* @__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 })
|
|
967
1205
|
] }),
|
|
968
|
-
/* @__PURE__ */ (0,
|
|
969
|
-
/* @__PURE__ */ (0,
|
|
970
|
-
/* @__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 })
|
|
971
1209
|
] }),
|
|
972
|
-
/* @__PURE__ */ (0,
|
|
973
|
-
/* @__PURE__ */ (0,
|
|
974
|
-
/* @__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: [
|
|
975
1213
|
metrics.shadow,
|
|
976
|
-
board.markRead === "shadow" ? /* @__PURE__ */ (0,
|
|
1214
|
+
board.markRead === "shadow" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("small", { className: "mishu-warn", children: t.shadowTag }) : null
|
|
977
1215
|
] })
|
|
978
1216
|
] })
|
|
979
1217
|
] }),
|
|
980
|
-
/* @__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: [
|
|
981
1219
|
s.label,
|
|
982
|
-
/* @__PURE__ */ (0,
|
|
1220
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: count(s.id) })
|
|
983
1221
|
] }, s.id)) }),
|
|
984
|
-
/* @__PURE__ */ (0,
|
|
985
|
-
/* @__PURE__ */ (0,
|
|
986
|
-
/* @__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: [
|
|
987
1225
|
t.handle,
|
|
988
|
-
/* @__PURE__ */ (0,
|
|
1226
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: columns.handle.length })
|
|
989
1227
|
] }),
|
|
990
|
-
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"))
|
|
991
1229
|
] }),
|
|
992
1230
|
divider(0),
|
|
993
|
-
/* @__PURE__ */ (0,
|
|
994
|
-
/* @__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: [
|
|
995
1233
|
t.remember,
|
|
996
|
-
/* @__PURE__ */ (0,
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: columns.remember.length })
|
|
997
1235
|
] }),
|
|
998
|
-
columns.remember.length === 0 ? /* @__PURE__ */ (0,
|
|
999
|
-
/* @__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) })
|
|
1000
1238
|
] }),
|
|
1001
1239
|
divider(1),
|
|
1002
|
-
/* @__PURE__ */ (0,
|
|
1003
|
-
/* @__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: [
|
|
1004
1242
|
t.done,
|
|
1005
|
-
/* @__PURE__ */ (0,
|
|
1243
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: columns.done.total })
|
|
1006
1244
|
] }),
|
|
1007
|
-
columns.done.groups.length === 0 ? /* @__PURE__ */ (0,
|
|
1008
|
-
/* @__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: [
|
|
1009
1247
|
group.label,
|
|
1010
|
-
/* @__PURE__ */ (0,
|
|
1248
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: group.items.length })
|
|
1011
1249
|
] }),
|
|
1012
1250
|
group.items.map((item) => card(item, "done"))
|
|
1013
1251
|
] }, group.reason)),
|
|
1014
|
-
columns.done.total > 0 ? /* @__PURE__ */ (0,
|
|
1015
|
-
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
|
|
1016
1254
|
] })
|
|
1017
1255
|
] })
|
|
1018
1256
|
] })
|
|
@@ -1020,8 +1258,8 @@ function MishuBoard({ locale, openChat: openChat2 }) {
|
|
|
1020
1258
|
}
|
|
1021
1259
|
function Card({ item, column, lang, locale, busy, label, openChat: openChat2, onAct, onDragStart, onDragEnd }) {
|
|
1022
1260
|
const t = TEXT[lang];
|
|
1023
|
-
const [open, setOpen] = (0,
|
|
1024
|
-
const [detail, setDetail] = (0,
|
|
1261
|
+
const [open, setOpen] = (0, import_react4.useState)(false);
|
|
1262
|
+
const [detail, setDetail] = (0, import_react4.useState)();
|
|
1025
1263
|
const explain = item.explain;
|
|
1026
1264
|
const compact = column === "done";
|
|
1027
1265
|
const toggle = () => {
|
|
@@ -1031,11 +1269,11 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
|
|
|
1031
1269
|
void mishuApi.detail(locale(), item.id).then((r) => setDetail(r.ok ? r.detail : { error: r.message }));
|
|
1032
1270
|
}
|
|
1033
1271
|
};
|
|
1034
|
-
const row = (name, text, className = "") => text === null || text === void 0 || text === "" ? null : /* @__PURE__ */ (0,
|
|
1035
|
-
/* @__PURE__ */ (0,
|
|
1036
|
-
/* @__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 })
|
|
1037
1275
|
] });
|
|
1038
|
-
return /* @__PURE__ */ (0,
|
|
1276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1039
1277
|
"div",
|
|
1040
1278
|
{
|
|
1041
1279
|
className: `mishu-card ${item.tone === "normal" ? "" : item.tone}`,
|
|
@@ -1046,35 +1284,35 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
|
|
|
1046
1284
|
},
|
|
1047
1285
|
onDragEnd,
|
|
1048
1286
|
children: [
|
|
1049
|
-
/* @__PURE__ */ (0,
|
|
1050
|
-
/* @__PURE__ */ (0,
|
|
1051
|
-
!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: [
|
|
1052
1290
|
row(t.what, explain.what),
|
|
1053
1291
|
row(column === "remember" ? t.whyKeep : t.why, explain.why),
|
|
1054
1292
|
row(t.fix, explain.fix, "mishu-fix")
|
|
1055
1293
|
] }) : null,
|
|
1056
|
-
!compact && explain === null && item.note !== null ? /* @__PURE__ */ (0,
|
|
1057
|
-
open ? /* @__PURE__ */ (0,
|
|
1058
|
-
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: [
|
|
1059
1297
|
row(t.what, detail.explain.what),
|
|
1060
1298
|
row(t.whyDone, detail.explain.why)
|
|
1061
1299
|
] }) : null,
|
|
1062
|
-
detail.did.length > 0 ? /* @__PURE__ */ (0,
|
|
1063
|
-
/* @__PURE__ */ (0,
|
|
1064
|
-
/* @__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)) })
|
|
1065
1303
|
] }) : null,
|
|
1066
|
-
detail.messages.length > 0 ? /* @__PURE__ */ (0,
|
|
1067
|
-
/* @__PURE__ */ (0,
|
|
1068
|
-
/* @__PURE__ */ (0,
|
|
1069
|
-
/* @__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 }),
|
|
1070
1308
|
" ",
|
|
1071
1309
|
m.title
|
|
1072
1310
|
] }, i)) })
|
|
1073
1311
|
] }) : null
|
|
1074
1312
|
] }) }) : null,
|
|
1075
|
-
/* @__PURE__ */ (0,
|
|
1076
|
-
column === "handle" ? /* @__PURE__ */ (0,
|
|
1077
|
-
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)(
|
|
1078
1316
|
"button",
|
|
1079
1317
|
{
|
|
1080
1318
|
type: "button",
|
|
@@ -1085,8 +1323,8 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
|
|
|
1085
1323
|
},
|
|
1086
1324
|
action
|
|
1087
1325
|
)),
|
|
1088
|
-
item.target === "matter" ? /* @__PURE__ */ (0,
|
|
1089
|
-
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 })
|
|
1090
1328
|
] })
|
|
1091
1329
|
]
|
|
1092
1330
|
}
|
|
@@ -1095,11 +1333,11 @@ function Card({ item, column, lang, locale, busy, label, openChat: openChat2, on
|
|
|
1095
1333
|
var EMPTY = { title: "", due: "", repeat: "none", category: "other", note: "" };
|
|
1096
1334
|
function AddForm({ lang, locale, onAdded }) {
|
|
1097
1335
|
const t = TEXT[lang];
|
|
1098
|
-
const [open, setOpen] = (0,
|
|
1099
|
-
const [item, setItem] = (0,
|
|
1100
|
-
const [preview, setPreview] = (0,
|
|
1101
|
-
const [saving, setSaving] = (0,
|
|
1102
|
-
(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)(() => {
|
|
1103
1341
|
if (!open || item.title.trim() === "" || item.due === "") {
|
|
1104
1342
|
setPreview(void 0);
|
|
1105
1343
|
return;
|
|
@@ -1110,7 +1348,7 @@ function AddForm({ lang, locale, onAdded }) {
|
|
|
1110
1348
|
return () => clearTimeout(timer);
|
|
1111
1349
|
}, [open, item, locale]);
|
|
1112
1350
|
if (!open) {
|
|
1113
|
-
return /* @__PURE__ */ (0,
|
|
1351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setOpen(true), children: [
|
|
1114
1352
|
"+ ",
|
|
1115
1353
|
t.add
|
|
1116
1354
|
] });
|
|
@@ -1128,44 +1366,90 @@ function AddForm({ lang, locale, onAdded }) {
|
|
|
1128
1366
|
setPreview({ ok: false, text: result.message });
|
|
1129
1367
|
}
|
|
1130
1368
|
};
|
|
1131
|
-
return /* @__PURE__ */ (0,
|
|
1132
|
-
/* @__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: [
|
|
1133
1371
|
t.addTitle,
|
|
1134
|
-
/* @__PURE__ */ (0,
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: item.title, placeholder: t.addTitlePlaceholder, onChange: set("title") })
|
|
1135
1373
|
] }),
|
|
1136
|
-
/* @__PURE__ */ (0,
|
|
1137
|
-
/* @__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: [
|
|
1138
1376
|
t.addDue,
|
|
1139
|
-
/* @__PURE__ */ (0,
|
|
1377
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "date", value: item.due, onChange: set("due") })
|
|
1140
1378
|
] }),
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1379
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
|
|
1142
1380
|
t.addRepeat,
|
|
1143
|
-
/* @__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)) })
|
|
1144
1382
|
] })
|
|
1145
1383
|
] }),
|
|
1146
|
-
/* @__PURE__ */ (0,
|
|
1147
|
-
/* @__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: [
|
|
1148
1386
|
t.addCategory,
|
|
1149
|
-
/* @__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)) })
|
|
1150
1388
|
] }),
|
|
1151
|
-
/* @__PURE__ */ (0,
|
|
1389
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mishu-field", children: [
|
|
1152
1390
|
t.addNote,
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1391
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { value: item.note, onChange: set("note") })
|
|
1154
1392
|
] })
|
|
1155
1393
|
] }),
|
|
1156
|
-
/* @__PURE__ */ (0,
|
|
1157
|
-
/* @__PURE__ */ (0,
|
|
1158
|
-
/* @__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: () => {
|
|
1159
1397
|
void save();
|
|
1160
1398
|
}, children: t.save }),
|
|
1161
|
-
/* @__PURE__ */ (0,
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
|
|
1162
1400
|
setOpen(false);
|
|
1163
1401
|
setItem(EMPTY);
|
|
1164
1402
|
}, children: t.cancel })
|
|
1165
1403
|
] }),
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mishu-hint", children: t.chatHint })
|
|
1405
|
+
] });
|
|
1406
|
+
}
|
|
1407
|
+
function RestartButton({ lang, locale }) {
|
|
1408
|
+
const t = TEXT[lang];
|
|
1409
|
+
const [why, setWhy] = (0, import_react4.useState)();
|
|
1410
|
+
const [status, setStatus] = (0, import_react4.useState)();
|
|
1411
|
+
(0, import_react4.useEffect)(() => {
|
|
1412
|
+
void restartApi.info(locale()).then((r) => {
|
|
1413
|
+
if (r.ok && !r.supported) setWhy(r.why);
|
|
1414
|
+
});
|
|
1415
|
+
}, [locale]);
|
|
1416
|
+
const restart = async () => {
|
|
1417
|
+
if (why !== void 0) {
|
|
1418
|
+
setStatus({ ok: false, text: why });
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
if (!window.confirm(t.restartConfirm)) return;
|
|
1422
|
+
setStatus({ ok: true, text: t.restarting });
|
|
1423
|
+
const r = await restartApi.restart(locale());
|
|
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
|
+
}
|
|
1430
|
+
};
|
|
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}
|
|
1433
|
+
${why}`, disabled: status?.ok === true, onClick: () => {
|
|
1434
|
+
void restart();
|
|
1435
|
+
}, children: t.restart }),
|
|
1436
|
+
status === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: status.ok ? "mishu-hint" : "mishu-hint mishu-warn", children: status.text })
|
|
1167
1437
|
] });
|
|
1168
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
|
+
}
|
|
1169
1453
|
|
|
1170
1454
|
// src/client/styles.ts
|
|
1171
1455
|
var v = (name, fallback) => `var(--dsw-alias-${name}, ${fallback})`;
|
|
@@ -1181,6 +1465,7 @@ var DANGER = v("state-error-primary", "#d14343");
|
|
|
1181
1465
|
var WARN = v("state-warn-primary", "#b7791f");
|
|
1182
1466
|
var OK = v("state-success-primary", "#2f855a");
|
|
1183
1467
|
var ACCENT = v("brand-primary", "#4d6bfe");
|
|
1468
|
+
var SURFACE = v("bg-layer-0", v("bg-base", "Canvas"));
|
|
1184
1469
|
var STYLES = `
|
|
1185
1470
|
.mishu-page{box-sizing:border-box;height:100%;overflow:auto;padding:20px 24px 32px;color:${TEXT2};font-size:13px;line-height:1.5}
|
|
1186
1471
|
.mishu-page *{box-sizing:border-box}
|
|
@@ -1241,6 +1526,22 @@ var STYLES = `
|
|
|
1241
1526
|
.mishu-row{display:grid;grid-template-columns:1fr 1fr;gap:6px}
|
|
1242
1527
|
.mishu-preview{white-space:pre-wrap;font-size:12px;background:${LAYER2};border-radius:6px;padding:6px 8px;margin:4px 0 6px;color:${TEXT2}}
|
|
1243
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}}
|
|
1244
1545
|
.mishu-add>.mishu-hint{margin-bottom:8px}
|
|
1245
1546
|
.mishu-title{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
|
|
1246
1547
|
.mishu-tabs{display:flex;gap:2px;background:${LAYER1};border-radius:8px;padding:2px}
|
|
@@ -1269,18 +1570,18 @@ var STYLES = `
|
|
|
1269
1570
|
`;
|
|
1270
1571
|
|
|
1271
1572
|
// src/client/index.tsx
|
|
1272
|
-
var
|
|
1573
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1273
1574
|
var PACKAGE_NAME = "dsh-mishu";
|
|
1274
1575
|
var inject = ["slots", "locale"];
|
|
1275
1576
|
var PANEL_ID = "dsh-mishu";
|
|
1276
1577
|
var NS = "dsh-mishu";
|
|
1277
1578
|
var openChat;
|
|
1278
1579
|
function MishuIcon({ size }) {
|
|
1279
|
-
return /* @__PURE__ */ (0,
|
|
1280
|
-
/* @__PURE__ */ (0,
|
|
1281
|
-
/* @__PURE__ */ (0,
|
|
1282
|
-
/* @__PURE__ */ (0,
|
|
1283
|
-
/* @__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" })
|
|
1284
1585
|
] });
|
|
1285
1586
|
}
|
|
1286
1587
|
function apply(ctx) {
|