dsh-mishu 0.0.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +271 -0
- package/cordis.patch.yml +5 -0
- package/lib/client.js +1242 -0
- package/lib/core/ask.js +132 -0
- package/lib/core/board.js +200 -0
- package/lib/core/brief.js +208 -0
- package/lib/core/explain.js +71 -0
- package/lib/core/fold.js +89 -0
- package/lib/core/github/client.js +142 -0
- package/lib/core/github/facts.js +173 -0
- package/lib/core/github/rules.js +274 -0
- package/lib/core/github/sync.js +112 -0
- package/lib/core/i18n.js +54 -0
- package/lib/core/index.js +65 -0
- package/lib/core/mail/account.js +76 -0
- package/lib/core/mail/imap.js +98 -0
- package/lib/core/mail/rules.js +69 -0
- package/lib/core/mail/sync.js +69 -0
- package/lib/core/manual.js +157 -0
- package/lib/core/matters.js +54 -0
- package/lib/core/recur.js +73 -0
- package/lib/core/secrets.js +122 -0
- package/lib/core/settings.js +95 -0
- package/lib/core/store.js +322 -0
- package/lib/core/time.js +111 -0
- package/lib/dsh/api.js +264 -0
- package/lib/dsh/config.js +23 -0
- package/lib/dsh/plugin.js +167 -0
- package/lib/dsh/runtime.js +116 -0
- package/lib/dsh/tools.js +184 -0
- package/lib/index.js +11 -0
- package/lib/types/core/ask.d.ts +40 -0
- package/lib/types/core/board.d.ts +108 -0
- package/lib/types/core/brief.d.ts +33 -0
- package/lib/types/core/explain.d.ts +22 -0
- package/lib/types/core/fold.d.ts +28 -0
- package/lib/types/core/github/client.d.ts +150 -0
- package/lib/types/core/github/facts.d.ts +104 -0
- package/lib/types/core/github/rules.d.ts +39 -0
- package/lib/types/core/github/sync.d.ts +37 -0
- package/lib/types/core/i18n.d.ts +31 -0
- package/lib/types/core/index.d.ts +42 -0
- package/lib/types/core/mail/account.d.ts +72 -0
- package/lib/types/core/mail/imap.d.ts +44 -0
- package/lib/types/core/mail/rules.d.ts +12 -0
- package/lib/types/core/mail/sync.d.ts +30 -0
- package/lib/types/core/manual.d.ts +54 -0
- package/lib/types/core/matters.d.ts +32 -0
- package/lib/types/core/recur.d.ts +30 -0
- package/lib/types/core/secrets.d.ts +35 -0
- package/lib/types/core/settings.d.ts +37 -0
- package/lib/types/core/store.d.ts +143 -0
- package/lib/types/core/time.d.ts +37 -0
- package/lib/types/dsh/api.d.ts +20 -0
- package/lib/types/dsh/config.d.ts +25 -0
- package/lib/types/dsh/plugin.d.ts +13 -0
- package/lib/types/dsh/runtime.d.ts +38 -0
- package/lib/types/dsh/tools.d.ts +43 -0
- package/lib/types/index.d.ts +11 -0
- package/package.json +50 -4
- package/docs//350/260/203/347/240/224/344/270/216/350/256/276/350/256/241.md +0 -90
package/lib/client.js
ADDED
|
@@ -0,0 +1,1242 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-mishu",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
"use strict";
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
|
+
|
|
25
|
+
// src/client/index.tsx
|
|
26
|
+
var index_exports = {};
|
|
27
|
+
__export(index_exports, {
|
|
28
|
+
PACKAGE_NAME: () => PACKAGE_NAME,
|
|
29
|
+
PANEL_ID: () => PANEL_ID,
|
|
30
|
+
apply: () => apply,
|
|
31
|
+
inject: () => inject
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
|
+
|
|
35
|
+
// src/client/Board.tsx
|
|
36
|
+
var import_react3 = require("react");
|
|
37
|
+
|
|
38
|
+
// src/client/api.ts
|
|
39
|
+
async function post(path, body) {
|
|
40
|
+
try {
|
|
41
|
+
const res = await fetch(new URL(`/api/dsh-mishu${path}`, document.baseURI), {
|
|
42
|
+
method: "POST",
|
|
43
|
+
credentials: "same-origin",
|
|
44
|
+
headers: { "content-type": "application/json" },
|
|
45
|
+
body: JSON.stringify(body)
|
|
46
|
+
});
|
|
47
|
+
const value = await res.json().catch(() => null);
|
|
48
|
+
if (value === null) return { ok: false, message: `HTTP ${res.status}` };
|
|
49
|
+
return value;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
var mishuApi = {
|
|
55
|
+
board: (lang) => post("/board", { lang }),
|
|
56
|
+
sync: (lang) => post("/sync", { lang }),
|
|
57
|
+
action: (lang, target, id, action, days) => post("/action", { lang, target, id, action, ...days === void 0 ? {} : { days } }),
|
|
58
|
+
detail: (lang, id) => post("/detail", { lang, id }),
|
|
59
|
+
preview: (lang, item) => post("/preview", { lang, item }),
|
|
60
|
+
add: (lang, item) => post("/add", { lang, item }),
|
|
61
|
+
ask: (lang, ask) => post("/ask", { lang, ask })
|
|
62
|
+
};
|
|
63
|
+
var settingsApi = {
|
|
64
|
+
load: (lang) => post("/settings", { lang }),
|
|
65
|
+
save: (lang, settings) => post("/settings/save", { lang, settings }),
|
|
66
|
+
testGithub: (lang) => post("/github/test", { lang }),
|
|
67
|
+
saveMail: (lang, account, password) => post("/mail/save", { lang, account, password }),
|
|
68
|
+
testMail: (lang, account, password) => post("/mail/test", { lang, account, password }),
|
|
69
|
+
deleteMail: (lang, id) => post("/mail/delete", { lang, id }),
|
|
70
|
+
syncMail: (lang, id) => post("/mail/sync", { lang, id })
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// src/client/AskAI.tsx
|
|
74
|
+
var import_react = require("react");
|
|
75
|
+
|
|
76
|
+
// src/client/text.ts
|
|
77
|
+
function uiLang(locale) {
|
|
78
|
+
return (locale ?? "").toLowerCase().startsWith("zh") ? "zh" : "en";
|
|
79
|
+
}
|
|
80
|
+
var zh = {
|
|
81
|
+
title: "\u5C0F\u79D8\u4E66",
|
|
82
|
+
sync: "\u540C\u6B65",
|
|
83
|
+
syncing: "\u540C\u6B65\u4E2D\u2026",
|
|
84
|
+
loading: "\u6B63\u5728\u8BFB\u53D6\u2026",
|
|
85
|
+
handle: "\u8981\u4F60\u5904\u7406",
|
|
86
|
+
remember: "\u6211\u8BB0\u7740",
|
|
87
|
+
done: "\u66FF\u4F60\u529E\u4E86",
|
|
88
|
+
metricHandle: "\u8981\u4F60\u5904\u7406",
|
|
89
|
+
metricOverdue: "\u8FC7\u671F",
|
|
90
|
+
metricSoon: "7 \u5929\u5185\u5230\u671F",
|
|
91
|
+
metricClosed: "\u4ECA\u5929\u66FF\u4F60\u5173\u6389",
|
|
92
|
+
metricShadow: "\u5F85\u4F60\u6838\u5BF9",
|
|
93
|
+
shadowTag: "\u5F71\u5B50",
|
|
94
|
+
open: "\u6253\u5F00",
|
|
95
|
+
markDone: "\u529E\u5B8C\u4E86",
|
|
96
|
+
snooze: "\u660E\u5929\u518D\u8BF4",
|
|
97
|
+
dismiss: "\u5FFD\u7565",
|
|
98
|
+
unsnooze: "\u73B0\u5728\u5904\u7406",
|
|
99
|
+
reopen: "\u6062\u590D",
|
|
100
|
+
stop: "\u4E0D\u518D\u63D0\u9192",
|
|
101
|
+
emptyHandle: "\u6CA1\u6709\u8981\u4F60\u5904\u7406\u7684\u4E8B\u3002",
|
|
102
|
+
emptyRemember: "\u8FD8\u6CA1\u6709\u8981\u8BB0\u7740\u7684\u4E8B\u3002",
|
|
103
|
+
emptyDone: "\u6700\u8FD1 7 \u5929\u6CA1\u6709\u66FF\u4F60\u5173\u6389\u4EC0\u4E48\u3002",
|
|
104
|
+
doneHint: '\u5224\u9519\u4E86\u5C31\u70B9"\u6062\u590D"\uFF0C\u8FD9\u6761\u89C4\u5219\u4F1A\u8BB0\u4E0B\u8FD9\u6B21\u7EA0\u6B63\u3002',
|
|
105
|
+
shadow: (n) => `\u5F71\u5B50\u6A21\u5F0F\uFF1A\u5DF2\u5224\u5B9A\u7ED3\u675F\u7684 ${n} \u6761 GitHub \u901A\u77E5\uFF0C\u6253\u5F00\u81EA\u52A8\u6807\u5DF2\u8BFB\u540E\u4F1A\u88AB\u6807\u6210\u5DF2\u8BFB\u3002\u73B0\u5728\u4E00\u6761\u4E5F\u6CA1\u6807\u3002`,
|
|
106
|
+
dropDone: "\u653E\u5230\u8FD9\u91CC = \u529E\u5B8C\u4E86",
|
|
107
|
+
dropRemember: "\u653E\u5230\u8FD9\u91CC = \u660E\u5929\u518D\u63D0\u9192",
|
|
108
|
+
add: "\u4EA4\u4EE3\u4E00\u4EF6\u4E8B",
|
|
109
|
+
addTitle: "\u4E8B\u9879",
|
|
110
|
+
addTitlePlaceholder: "\u4EA4\u623F\u79DF",
|
|
111
|
+
addDue: "\u65E5\u671F",
|
|
112
|
+
addRepeat: "\u91CD\u590D",
|
|
113
|
+
addCategory: "\u7C7B\u522B",
|
|
114
|
+
addNote: "\u5907\u6CE8",
|
|
115
|
+
repeats: { none: "\u4E0D\u91CD\u590D", weekly: "\u6BCF\u5468", monthly: "\u6BCF\u6708", yearly: "\u6BCF\u5E74" },
|
|
116
|
+
categories: { other: "\u5176\u4ED6", bill: "\u8D26\u5355", document: "\u8BC1\u4EF6", birthday: "\u751F\u65E5\u7EAA\u5FF5\u65E5", renewal: "\u7EED\u8D39\u7EED\u4FDD" },
|
|
117
|
+
save: "\u8BB0\u4E0B",
|
|
118
|
+
cancel: "\u53D6\u6D88",
|
|
119
|
+
previewHint: "\u586B\u597D\u4E8B\u9879\u548C\u65E5\u671F\u540E\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u5C0F\u79D8\u4E66\u7406\u89E3\u7684\u5185\u5BB9\u3002",
|
|
120
|
+
chatHint: '\u4E5F\u53EF\u4EE5\u76F4\u63A5\u5728\u5BF9\u8BDD\u91CC\u8BF4\uFF0C\u6BD4\u5982"\u62A4\u7167 2027 \u5E74 3 \u6708 10 \u65E5\u5230\u671F"\u3002',
|
|
121
|
+
failed: "\u64CD\u4F5C\u6CA1\u6210\u529F\uFF1A",
|
|
122
|
+
what: "\u662F\u4EC0\u4E48",
|
|
123
|
+
why: "\u95EE\u9898\u5728\u54EA",
|
|
124
|
+
whyDone: "\u4E3A\u4EC0\u4E48\u5173\u6389",
|
|
125
|
+
whyKeep: "\u60C5\u51B5",
|
|
126
|
+
fix: "\u600E\u4E48\u529E",
|
|
127
|
+
did: "\u5C0F\u79D8\u4E66\u505A\u4E86\u4EC0\u4E48",
|
|
128
|
+
messages: (n) => `\u6765\u81EA\u8FD9 ${n} \u6761\u901A\u77E5`,
|
|
129
|
+
explainDone: "\u600E\u4E48\u56DE\u4E8B",
|
|
130
|
+
detail: "\u8BE6\u60C5",
|
|
131
|
+
hide: "\u6536\u8D77",
|
|
132
|
+
resize: "\u62D6\u52A8\u8C03\u6574\u5BBD\u5EA6\uFF0C\u53CC\u51FB\u6062\u590D\u7B49\u5BBD",
|
|
133
|
+
tabBoard: "\u770B\u677F",
|
|
134
|
+
tabSettings: "\u8BBE\u7F6E",
|
|
135
|
+
all: "\u5168\u90E8",
|
|
136
|
+
sourceGithub: "GitHub",
|
|
137
|
+
sourceMail: "\u90AE\u4EF6",
|
|
138
|
+
sourceManual: "\u4EA4\u4EE3",
|
|
139
|
+
sGeneral: "\u901A\u7528",
|
|
140
|
+
sLanguage: "\u8BED\u8A00",
|
|
141
|
+
sLanguageAuto: "\u8DDF\u968F\u7CFB\u7EDF",
|
|
142
|
+
sLead: "\u63D0\u524D\u591A\u5C11\u5929\u63D0\u9192\uFF08\u6309\u7C7B\u522B\uFF09",
|
|
143
|
+
sSave: "\u4FDD\u5B58",
|
|
144
|
+
sSaved: "\u5DF2\u4FDD\u5B58",
|
|
145
|
+
sGithub: "GitHub",
|
|
146
|
+
sGithubOn: "\u76EF\u7740 GitHub \u901A\u77E5",
|
|
147
|
+
sToken: "Token",
|
|
148
|
+
sTokenEnv: (name) => `\u4ECE\u73AF\u5883\u53D8\u91CF ${name} \u8BFB\u53D6`,
|
|
149
|
+
sTokenGh: "\u7528 GitHub CLI\uFF08gh\uFF09\u767B\u5F55\u7684\u8D26\u53F7\uFF0Ctoken \u5728\u7CFB\u7EDF\u94A5\u5319\u4E32\u91CC",
|
|
150
|
+
sTest: "\u6D4B\u8BD5\u8FDE\u63A5",
|
|
151
|
+
sTesting: "\u6B63\u5728\u6D4B\u8BD5\u2026",
|
|
152
|
+
sGithubOk: (login) => `\u8FDE\u4E0A\u4E86\uFF0C\u8D26\u53F7 ${login}`,
|
|
153
|
+
sMarkRead: "\u5728 GitHub \u4E0A\u6807\u5DF2\u8BFB",
|
|
154
|
+
sMarkOff: "\u5173\u95ED\uFF1A\u5B8C\u5168\u4E0D\u78B0 GitHub \u4E0A\u7684\u5DF2\u8BFB\u72B6\u6001",
|
|
155
|
+
sMarkShadow: "\u5F71\u5B50\u6A21\u5F0F\uFF1A\u53EA\u8BB0\u4E0B\u4F1A\u6807\u54EA\u4E9B\uFF0C\u4E0D\u771F\u6807\uFF08\u63A8\u8350\u5148\u7528\uFF09",
|
|
156
|
+
sMarkOn: "\u6253\u5F00\uFF1A\u628A\u5224\u5B9A\u7ED3\u675F\u7684\u901A\u77E5\u5728 GitHub \u4E0A\u6807\u6210\u5DF2\u8BFB",
|
|
157
|
+
sMarkConfirm: '\u6253\u5F00\u540E\uFF0C\u5C0F\u79D8\u4E66\u4F1A\u5728 GitHub \u4E0A\u628A\u5224\u5B9A\u5DF2\u7ECF\u7ED3\u675F\u7684\u901A\u77E5\u6807\u6210\u5DF2\u8BFB\uFF08\u8FD8\u5728"\u8981\u4F60\u5904\u7406"\u91CC\u7684\u6C38\u8FDC\u4E0D\u4F1A\u88AB\u6807\uFF09\u3002\u6807\u9519\u7684\u53EF\u4EE5\u5728 GitHub \u4E0A\u91CD\u65B0\u6807\u6210\u672A\u8BFB\u3002\u786E\u8BA4\u6253\u5F00\u5417\uFF1F',
|
|
158
|
+
sConfirm: "\u786E\u8BA4\u6253\u5F00",
|
|
159
|
+
sCancel: "\u53D6\u6D88",
|
|
160
|
+
sMail: "\u90AE\u7BB1",
|
|
161
|
+
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",
|
|
162
|
+
sSecretsAt: (kind) => `\u5BC6\u7801\u4FDD\u5B58\u5728\uFF1A${kind}\uFF08\u52A0\u5BC6\u4FDD\u5B58\uFF0C\u4E0D\u5199\u8FDB\u4EFB\u4F55\u6587\u4EF6\uFF09`,
|
|
163
|
+
sSecretsNone: "\u8FD9\u53F0\u7535\u8111\u4E0A\u6CA1\u627E\u5230\u53EF\u7528\u7684\u7CFB\u7EDF\u94A5\u5319\u4E32\uFF0C\u6CA1\u6CD5\u4FDD\u5B58\u5BC6\u7801\u3002\u53EF\u4EE5\u6539\u7528\u73AF\u5883\u53D8\u91CF\uFF0C\u540D\u5B57\u89C1\u6BCF\u4E2A\u8D26\u6237\u4E0B\u9762\u3002",
|
|
164
|
+
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" },
|
|
165
|
+
sNoAccounts: "\u8FD8\u6CA1\u6709\u6DFB\u52A0\u90AE\u7BB1\u3002",
|
|
166
|
+
sAddAccount: "+ \u6DFB\u52A0\u90AE\u7BB1",
|
|
167
|
+
sEdit: "\u7F16\u8F91",
|
|
168
|
+
sDelete: "\u5220\u9664",
|
|
169
|
+
sDeleteConfirm: "\u5220\u9664\u8FD9\u4E2A\u90AE\u7BB1\u8D26\u6237\uFF1F\u5B83\u7684\u5BC6\u7801\u4F1A\u4ECE\u94A5\u5319\u4E32\u91CC\u5220\u6389\uFF0C\u8FD8\u6CA1\u5904\u7406\u7684\u90AE\u4EF6\u4E8B\u9879\u4F1A\u88AB\u5173\u6389\u3002",
|
|
170
|
+
sCheckNow: "\u73B0\u5728\u6536\u4E00\u6B21",
|
|
171
|
+
sProvider: "\u90AE\u7BB1\u670D\u52A1\u5546",
|
|
172
|
+
sAddress: "\u90AE\u7BB1\u5730\u5740",
|
|
173
|
+
sLabel: "\u540D\u79F0\uFF08\u53EF\u9009\uFF09",
|
|
174
|
+
sUser: "\u7528\u6237\u540D\uFF08\u4E00\u822C\u5C31\u662F\u90AE\u7BB1\u5730\u5740\uFF09",
|
|
175
|
+
sPassword: "\u5BC6\u7801 / \u6388\u6743\u7801",
|
|
176
|
+
sPasswordKeep: "\u5DF2\u4FDD\u5B58\uFF1B\u4E0D\u6539\u5C31\u7559\u7A7A",
|
|
177
|
+
sHost: "IMAP \u670D\u52A1\u5668",
|
|
178
|
+
sPort: "\u7AEF\u53E3",
|
|
179
|
+
sSecure: "SSL/TLS",
|
|
180
|
+
sSince: "\u53EA\u770B\u6700\u8FD1\u51E0\u5929\u7684\u672A\u8BFB\u90AE\u4EF6",
|
|
181
|
+
sEnabled: "\u542F\u7528",
|
|
182
|
+
sMailOk: (n) => `\u8FDE\u4E0A\u4E86\uFF0C\u6700\u8FD1\u6709 ${n} \u5C01\u672A\u8BFB\u90AE\u4EF6`,
|
|
183
|
+
sEnvHint: (name) => `\u6CA1\u6709\u94A5\u5319\u4E32\u65F6\uFF0C\u53EF\u4EE5\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF ${name}`,
|
|
184
|
+
sNeverChecked: "\u8FD8\u6CA1\u6536\u8FC7",
|
|
185
|
+
sFeishu: "\u98DE\u4E66",
|
|
186
|
+
sComing: "\u5373\u5C06\u63A5\u5165",
|
|
187
|
+
ai: "+AI",
|
|
188
|
+
aiTitle: "\u5728\u5BF9\u8BDD\u91CC\u95EE AI\uFF1A\u628A\u8FD9\u4EF6\u4E8B\u653E\u8FDB\u4E00\u4E2A\u65B0\u5BF9\u8BDD\u7684\u8F93\u5165\u6846\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u53D1\u9001\uFF0C\u4F60\u770B\u8FC7\u518D\u6309\u53D1\u9001",
|
|
189
|
+
aiOpened: "\u5DF2\u653E\u8FDB\u65B0\u5BF9\u8BDD\u7684\u8F93\u5165\u6846\uFF0C\u770B\u8FC7\u540E\u6309\u53D1\u9001\u5C31\u884C",
|
|
190
|
+
aiCopied: "\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\uFF0C\u7C98\u8D34\u5230\u5BF9\u8BDD\u91CC\u5C31\u80FD\u95EE",
|
|
191
|
+
aiFailed: "\u6CA1\u80FD\u6253\u5F00\u5BF9\u8BDD\uFF1A"
|
|
192
|
+
};
|
|
193
|
+
var en = {
|
|
194
|
+
title: "Secretary",
|
|
195
|
+
sync: "Sync",
|
|
196
|
+
syncing: "Syncing\u2026",
|
|
197
|
+
loading: "Loading\u2026",
|
|
198
|
+
handle: "To handle",
|
|
199
|
+
remember: "Keeping for you",
|
|
200
|
+
done: "Done for you",
|
|
201
|
+
metricHandle: "To handle",
|
|
202
|
+
metricOverdue: "overdue",
|
|
203
|
+
metricSoon: "Due in 7 days",
|
|
204
|
+
metricClosed: "Closed today",
|
|
205
|
+
metricShadow: "To review",
|
|
206
|
+
shadowTag: "shadow",
|
|
207
|
+
open: "Open",
|
|
208
|
+
markDone: "Done",
|
|
209
|
+
snooze: "Tomorrow",
|
|
210
|
+
dismiss: "Dismiss",
|
|
211
|
+
unsnooze: "Handle now",
|
|
212
|
+
reopen: "Reopen",
|
|
213
|
+
stop: "Stop",
|
|
214
|
+
emptyHandle: "Nothing needs you right now.",
|
|
215
|
+
emptyRemember: "Nothing to keep yet.",
|
|
216
|
+
emptyDone: "Nothing closed in the last 7 days.",
|
|
217
|
+
doneHint: "If one is wrong, reopen it; the rule records the correction.",
|
|
218
|
+
shadow: (n) => `Shadow mode: ${n} resolved GitHub notifications would be marked read once you turn it on. None has been.`,
|
|
219
|
+
dropDone: "Drop here to mark done",
|
|
220
|
+
dropRemember: "Drop here to snooze until tomorrow",
|
|
221
|
+
add: "Tell me something",
|
|
222
|
+
addTitle: "What",
|
|
223
|
+
addTitlePlaceholder: "Pay rent",
|
|
224
|
+
addDue: "Date",
|
|
225
|
+
addRepeat: "Repeat",
|
|
226
|
+
addCategory: "Category",
|
|
227
|
+
addNote: "Note",
|
|
228
|
+
repeats: { none: "Once", weekly: "Weekly", monthly: "Monthly", yearly: "Yearly" },
|
|
229
|
+
categories: { other: "Other", bill: "Bill", document: "Document", birthday: "Birthday", renewal: "Renewal" },
|
|
230
|
+
save: "Save",
|
|
231
|
+
cancel: "Cancel",
|
|
232
|
+
previewHint: "Fill in what and when to see what the secretary understood.",
|
|
233
|
+
chatHint: 'You can also say it in the chat, e.g. "my passport expires on 2027-03-10".',
|
|
234
|
+
failed: "That did not work: ",
|
|
235
|
+
what: "What",
|
|
236
|
+
why: "The problem",
|
|
237
|
+
whyDone: "Why it was closed",
|
|
238
|
+
whyKeep: "Status",
|
|
239
|
+
fix: "What to do",
|
|
240
|
+
did: "What the secretary did",
|
|
241
|
+
messages: (n) => `From these ${n} notifications`,
|
|
242
|
+
explainDone: "What happened",
|
|
243
|
+
detail: "Details",
|
|
244
|
+
hide: "Hide",
|
|
245
|
+
resize: "Drag to resize; double-click to make them equal",
|
|
246
|
+
tabBoard: "Board",
|
|
247
|
+
tabSettings: "Settings",
|
|
248
|
+
all: "All",
|
|
249
|
+
sourceGithub: "GitHub",
|
|
250
|
+
sourceMail: "Mail",
|
|
251
|
+
sourceManual: "Noted",
|
|
252
|
+
sGeneral: "General",
|
|
253
|
+
sLanguage: "Language",
|
|
254
|
+
sLanguageAuto: "Follow the system",
|
|
255
|
+
sLead: "Days of warning, by category",
|
|
256
|
+
sSave: "Save",
|
|
257
|
+
sSaved: "Saved",
|
|
258
|
+
sGithub: "GitHub",
|
|
259
|
+
sGithubOn: "Watch GitHub notifications",
|
|
260
|
+
sToken: "Token",
|
|
261
|
+
sTokenEnv: (name) => `Read from the environment variable ${name}`,
|
|
262
|
+
sTokenGh: "The account the GitHub CLI (gh) is signed in to; the token stays in the system keychain",
|
|
263
|
+
sTest: "Test connection",
|
|
264
|
+
sTesting: "Testing\u2026",
|
|
265
|
+
sGithubOk: (login) => `Connected as ${login}`,
|
|
266
|
+
sMarkRead: "Mark read on GitHub",
|
|
267
|
+
sMarkOff: "Off: never touch read state on GitHub",
|
|
268
|
+
sMarkShadow: "Shadow: only record what would be marked (start here)",
|
|
269
|
+
sMarkOn: "On: mark resolved notifications read on GitHub",
|
|
270
|
+
sMarkConfirm: 'Once on, the secretary marks notifications it judged resolved as read on GitHub (anything still under "To handle" is never marked). You can mark them unread again on GitHub. Turn it on?',
|
|
271
|
+
sConfirm: "Turn on",
|
|
272
|
+
sCancel: "Cancel",
|
|
273
|
+
sMail: "Mail",
|
|
274
|
+
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.",
|
|
275
|
+
sSecretsAt: (kind) => `Passwords are kept in: ${kind} (encrypted, never written to a file)`,
|
|
276
|
+
sSecretsNone: "No usable system keychain on this computer, so passwords cannot be saved. Use the environment variable shown under each account instead.",
|
|
277
|
+
secretKinds: { macos: "the macOS Keychain", windows: "Windows Credential Manager", linux: "the Linux keyring (Secret Service)", memory: "memory (tests)" },
|
|
278
|
+
sNoAccounts: "No mail account yet.",
|
|
279
|
+
sAddAccount: "+ Add a mail account",
|
|
280
|
+
sEdit: "Edit",
|
|
281
|
+
sDelete: "Delete",
|
|
282
|
+
sDeleteConfirm: "Delete this mail account? Its password is removed from the keychain and its open mail items are closed.",
|
|
283
|
+
sCheckNow: "Check now",
|
|
284
|
+
sProvider: "Provider",
|
|
285
|
+
sAddress: "Email address",
|
|
286
|
+
sLabel: "Name (optional)",
|
|
287
|
+
sUser: "User name (usually the address)",
|
|
288
|
+
sPassword: "Password / app password",
|
|
289
|
+
sPasswordKeep: "Saved; leave empty to keep it",
|
|
290
|
+
sHost: "IMAP server",
|
|
291
|
+
sPort: "Port",
|
|
292
|
+
sSecure: "SSL/TLS",
|
|
293
|
+
sSince: "Only look at unread mail from the last \u2026 days",
|
|
294
|
+
sEnabled: "Enabled",
|
|
295
|
+
sMailOk: (n) => `Connected; ${n} unread messages recently`,
|
|
296
|
+
sEnvHint: (name) => `Without a keychain, set the environment variable ${name}`,
|
|
297
|
+
sNeverChecked: "Not checked yet",
|
|
298
|
+
sFeishu: "Feishu / Lark",
|
|
299
|
+
sComing: "Coming soon",
|
|
300
|
+
ai: "+AI",
|
|
301
|
+
aiTitle: "Ask AI in a chat: puts this into a new chat's input box, unsent; read it, then press send",
|
|
302
|
+
aiOpened: "Put into a new chat's input box; read it and press send",
|
|
303
|
+
aiCopied: "Copied; paste it into a chat to ask",
|
|
304
|
+
aiFailed: "Could not open a chat: "
|
|
305
|
+
};
|
|
306
|
+
var TEXT = { zh, en };
|
|
307
|
+
|
|
308
|
+
// src/client/AskAI.tsx
|
|
309
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
310
|
+
async function copy(text) {
|
|
311
|
+
try {
|
|
312
|
+
await navigator.clipboard.writeText(text);
|
|
313
|
+
return true;
|
|
314
|
+
} catch {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function AskAI({ topic, lang, locale, openChat: openChat2, compact = false }) {
|
|
319
|
+
const t = TEXT[lang];
|
|
320
|
+
const [note, setNote] = (0, import_react.useState)();
|
|
321
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
322
|
+
const ask = async () => {
|
|
323
|
+
setBusy(true);
|
|
324
|
+
const result = await mishuApi.ask(locale(), topic);
|
|
325
|
+
setBusy(false);
|
|
326
|
+
if (!result.ok) {
|
|
327
|
+
setNote({ ok: false, text: `${t.aiFailed}${result.message}` });
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (openChat2(result.prompt)) {
|
|
331
|
+
setNote({ ok: true, text: t.aiOpened });
|
|
332
|
+
} else {
|
|
333
|
+
setNote(await copy(result.prompt) ? { ok: true, text: t.aiCopied } : { ok: false, text: `${t.aiFailed}clipboard` });
|
|
334
|
+
}
|
|
335
|
+
setTimeout(() => setNote(void 0), 6e3);
|
|
336
|
+
};
|
|
337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "mishu-ai-wrap", children: [
|
|
338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
339
|
+
"button",
|
|
340
|
+
{
|
|
341
|
+
type: "button",
|
|
342
|
+
className: `mishu-ai ${compact ? "compact" : ""}`,
|
|
343
|
+
title: t.aiTitle,
|
|
344
|
+
"aria-label": t.aiTitle,
|
|
345
|
+
disabled: busy,
|
|
346
|
+
onClick: (event) => {
|
|
347
|
+
event.stopPropagation();
|
|
348
|
+
void ask();
|
|
349
|
+
},
|
|
350
|
+
children: t.ai
|
|
351
|
+
}
|
|
352
|
+
),
|
|
353
|
+
note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `mishu-ai-note ${note.ok ? "" : "mishu-danger"}`, role: "status", children: note.text })
|
|
354
|
+
] });
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// src/client/Settings.tsx
|
|
358
|
+
var import_react2 = require("react");
|
|
359
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
360
|
+
var CATEGORIES = ["document", "bill", "birthday", "renewal", "other"];
|
|
361
|
+
function MishuSettings({ lang, locale, openChat: openChat2 }) {
|
|
362
|
+
const t = TEXT[lang];
|
|
363
|
+
const [view, setView] = (0, import_react2.useState)();
|
|
364
|
+
const [error, setError] = (0, import_react2.useState)();
|
|
365
|
+
const [note, setNote] = (0, import_react2.useState)();
|
|
366
|
+
const [lead, setLead] = (0, import_react2.useState)({});
|
|
367
|
+
const [githubTest, setGithubTest] = (0, import_react2.useState)();
|
|
368
|
+
const [confirmOn, setConfirmOn] = (0, import_react2.useState)(false);
|
|
369
|
+
const [editing, setEditing] = (0, import_react2.useState)();
|
|
370
|
+
const take = (result, saved) => {
|
|
371
|
+
if (result.ok) {
|
|
372
|
+
setView(result.view);
|
|
373
|
+
setLead(result.view.settings.leadDays);
|
|
374
|
+
setError(void 0);
|
|
375
|
+
setNote(saved);
|
|
376
|
+
} else {
|
|
377
|
+
setError(result.message);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
(0, import_react2.useEffect)(() => {
|
|
381
|
+
void settingsApi.load(locale()).then((r) => take(r));
|
|
382
|
+
}, [locale]);
|
|
383
|
+
if (view === void 0) {
|
|
384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-settings", children: error === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-empty", children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-error", children: [
|
|
385
|
+
t.failed,
|
|
386
|
+
error
|
|
387
|
+
] }) });
|
|
388
|
+
}
|
|
389
|
+
const save = async (settings) => take(await settingsApi.save(locale(), settings), t.sSaved);
|
|
390
|
+
const token = view.github.token;
|
|
391
|
+
const secretKind = t.secretKinds[view.secrets.kind] ?? view.secrets.kind;
|
|
392
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-settings", children: [
|
|
393
|
+
error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-error", children: [
|
|
394
|
+
t.failed,
|
|
395
|
+
error
|
|
396
|
+
] }),
|
|
397
|
+
note === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-ok", children: note }),
|
|
398
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
|
|
399
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sGeneral }),
|
|
400
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
401
|
+
t.sLanguage,
|
|
402
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("select", { value: view.settings.language, onChange: (e) => {
|
|
403
|
+
void save({ language: e.target.value });
|
|
404
|
+
}, children: [
|
|
405
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "auto", children: t.sLanguageAuto }),
|
|
406
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }),
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "en", children: "English" })
|
|
408
|
+
] })
|
|
409
|
+
] }),
|
|
410
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-field", children: t.sLead }),
|
|
411
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-grid5", children: CATEGORIES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
412
|
+
t.categories[c],
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", min: 0, max: 366, value: lead[c] ?? 0, onChange: (e) => setLead({ ...lead, [c]: Number(e.target.value) }) })
|
|
414
|
+
] }, c)) }),
|
|
415
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
|
|
416
|
+
void save({ leadDays: lead });
|
|
417
|
+
}, children: t.sSave })
|
|
418
|
+
] }),
|
|
419
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sGithub }),
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-check", children: [
|
|
422
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: view.settings.githubEnabled, onChange: (e) => {
|
|
423
|
+
void save({ githubEnabled: e.target.checked });
|
|
424
|
+
} }),
|
|
425
|
+
t.sGithubOn
|
|
426
|
+
] }),
|
|
427
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row-explain", children: [
|
|
428
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mishu-row-label", children: t.sToken }),
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: token.found ? "" : "mishu-danger", children: token.found ? token.from === "env" ? t.sTokenEnv(view.github.tokenEnv) : t.sTokenGh : token.text })
|
|
430
|
+
] }),
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
|
|
432
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
|
|
433
|
+
setGithubTest(t.sTesting);
|
|
434
|
+
void settingsApi.testGithub(locale()).then((r) => setGithubTest(r.ok ? t.sGithubOk(r.login) : `${t.failed}${r.message}`));
|
|
435
|
+
}, children: t.sTest }),
|
|
436
|
+
githubTest === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "mishu-hint", children: githubTest })
|
|
437
|
+
] }),
|
|
438
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
439
|
+
t.sMarkRead,
|
|
440
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("select", { value: view.settings.markRead, onChange: (e) => {
|
|
441
|
+
const value = e.target.value;
|
|
442
|
+
if (value === "on") setConfirmOn(true);
|
|
443
|
+
else void save({ markRead: value });
|
|
444
|
+
}, children: [
|
|
445
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "off", children: t.sMarkOff }),
|
|
446
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "shadow", children: t.sMarkShadow }),
|
|
447
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "on", children: t.sMarkOn })
|
|
448
|
+
] })
|
|
449
|
+
] }),
|
|
450
|
+
confirmOn ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-banner", children: [
|
|
451
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: t.sMarkConfirm }),
|
|
452
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
|
|
453
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn primary", onClick: () => {
|
|
454
|
+
setConfirmOn(false);
|
|
455
|
+
void save({ markRead: "on" });
|
|
456
|
+
}, children: t.sConfirm }),
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => setConfirmOn(false), children: t.sCancel })
|
|
458
|
+
] })
|
|
459
|
+
] }) : null
|
|
460
|
+
] }),
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sMail }),
|
|
463
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-hint", children: t.sMailPrivacy }),
|
|
464
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: view.secrets.available ? "mishu-hint" : "mishu-hint mishu-warn", children: view.secrets.available ? t.sSecretsAt(secretKind) : t.sSecretsNone }),
|
|
465
|
+
view.accounts.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-empty", children: t.sNoAccounts }) : view.accounts.map((account) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
466
|
+
AccountRow,
|
|
467
|
+
{
|
|
468
|
+
account,
|
|
469
|
+
lang,
|
|
470
|
+
locale,
|
|
471
|
+
openChat: openChat2,
|
|
472
|
+
onEdit: () => setEditing({ ...account }),
|
|
473
|
+
onView: (next) => take(next)
|
|
474
|
+
},
|
|
475
|
+
account.id
|
|
476
|
+
)),
|
|
477
|
+
editing === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setEditing({ preset: "qq", sinceDays: 14, enabled: true }), children: t.sAddAccount }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AccountForm, { draft: editing, view, lang, locale, openChat: openChat2, onDone: (next) => {
|
|
478
|
+
setEditing(void 0);
|
|
479
|
+
if (next !== void 0) take({ ok: true, view: next }, t.sSaved);
|
|
480
|
+
} })
|
|
481
|
+
] }),
|
|
482
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "mishu-panel", children: [
|
|
483
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.sFeishu }),
|
|
484
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mishu-hint", children: t.sComing })
|
|
485
|
+
] })
|
|
486
|
+
] });
|
|
487
|
+
}
|
|
488
|
+
function AccountRow({ account, lang, locale, openChat: openChat2, onEdit, onView }) {
|
|
489
|
+
const t = TEXT[lang];
|
|
490
|
+
const [busy, setBusy] = (0, import_react2.useState)(false);
|
|
491
|
+
const report = account.report;
|
|
492
|
+
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`;
|
|
493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-card", children: [
|
|
494
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-card-title", children: [
|
|
495
|
+
account.label,
|
|
496
|
+
account.enabled ? "" : ` (${lang === "zh" ? "\u5DF2\u505C\u7528" : "disabled"})`
|
|
497
|
+
] }),
|
|
498
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-card-meta", children: [
|
|
499
|
+
account.address,
|
|
500
|
+
" \xB7 ",
|
|
501
|
+
account.host,
|
|
502
|
+
":",
|
|
503
|
+
account.port
|
|
504
|
+
] }),
|
|
505
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `mishu-card-note ${report?.error === void 0 ? "" : "mishu-danger"}`, children: [
|
|
506
|
+
status,
|
|
507
|
+
report?.error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AskAI, { topic: { kind: "mail-error", accountId: account.id }, lang, locale, openChat: openChat2, compact: true })
|
|
508
|
+
] }),
|
|
509
|
+
account.hasPassword ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mishu-card-note mishu-warn", children: t.sEnvHint(account.envName) }),
|
|
510
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
|
|
511
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy, onClick: () => {
|
|
512
|
+
setBusy(true);
|
|
513
|
+
void settingsApi.syncMail(locale(), account.id).then((r) => {
|
|
514
|
+
setBusy(false);
|
|
515
|
+
onView(r);
|
|
516
|
+
});
|
|
517
|
+
}, children: busy ? t.sTesting : t.sCheckNow }),
|
|
518
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: onEdit, children: t.sEdit }),
|
|
519
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", onClick: () => {
|
|
520
|
+
if (window.confirm(t.sDeleteConfirm)) void settingsApi.deleteMail(locale(), account.id).then(onView);
|
|
521
|
+
}, children: t.sDelete })
|
|
522
|
+
] })
|
|
523
|
+
] });
|
|
524
|
+
}
|
|
525
|
+
function AccountForm({ draft, view, lang, locale, openChat: openChat2, onDone }) {
|
|
526
|
+
const t = TEXT[lang];
|
|
527
|
+
const [account, setAccount] = (0, import_react2.useState)(draft);
|
|
528
|
+
const [password, setPassword] = (0, import_react2.useState)("");
|
|
529
|
+
const [message, setMessage] = (0, import_react2.useState)();
|
|
530
|
+
const [busy, setBusy] = (0, import_react2.useState)(false);
|
|
531
|
+
const preset = view.presets.find((p) => p.id === account.preset) ?? view.presets[view.presets.length - 1];
|
|
532
|
+
const custom = preset.id === "custom";
|
|
533
|
+
const existing = draft.id !== void 0;
|
|
534
|
+
const set = (patch) => {
|
|
535
|
+
setAccount({ ...account, ...patch });
|
|
536
|
+
setMessage(void 0);
|
|
537
|
+
};
|
|
538
|
+
const test = async () => {
|
|
539
|
+
setBusy(true);
|
|
540
|
+
setMessage({ ok: true, text: t.sTesting });
|
|
541
|
+
const r = await settingsApi.testMail(locale(), account, password);
|
|
542
|
+
setBusy(false);
|
|
543
|
+
setMessage(r.ok ? { ok: true, text: t.sMailOk(r.unread) } : { ok: false, text: r.message });
|
|
544
|
+
};
|
|
545
|
+
const save = async () => {
|
|
546
|
+
setBusy(true);
|
|
547
|
+
const r = await settingsApi.saveMail(locale(), account, password);
|
|
548
|
+
setBusy(false);
|
|
549
|
+
if (r.ok) {
|
|
550
|
+
setPassword("");
|
|
551
|
+
onDone(r.view);
|
|
552
|
+
} else {
|
|
553
|
+
setMessage({ ok: false, text: r.message });
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-add", children: [
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
558
|
+
t.sProvider,
|
|
559
|
+
/* @__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)) })
|
|
560
|
+
] }),
|
|
561
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: preset.supported ? "mishu-hint" : "mishu-hint mishu-danger", children: [
|
|
562
|
+
preset.howTo,
|
|
563
|
+
preset.supported ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AskAI, { topic: { kind: "mail-setup", preset: preset.id }, lang, locale, openChat: openChat2, compact: true }) : null
|
|
564
|
+
] }),
|
|
565
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
566
|
+
t.sAddress,
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "email", value: account.address ?? "", autoComplete: "off", onChange: (e) => set({ address: e.target.value }) })
|
|
568
|
+
] }),
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row", children: [
|
|
570
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
571
|
+
t.sLabel,
|
|
572
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: account.label ?? "", onChange: (e) => set({ label: e.target.value }) })
|
|
573
|
+
] }),
|
|
574
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
575
|
+
t.sUser,
|
|
576
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: account.user ?? "", placeholder: account.address ?? "", autoComplete: "off", onChange: (e) => set({ user: e.target.value }) })
|
|
577
|
+
] })
|
|
578
|
+
] }),
|
|
579
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
580
|
+
t.sPassword,
|
|
581
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "password", value: password, autoComplete: "new-password", placeholder: existing ? t.sPasswordKeep : "", onChange: (e) => {
|
|
582
|
+
setPassword(e.target.value);
|
|
583
|
+
setMessage(void 0);
|
|
584
|
+
} })
|
|
585
|
+
] }),
|
|
586
|
+
custom ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row", children: [
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
588
|
+
t.sHost,
|
|
589
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: account.host ?? "", onChange: (e) => set({ host: e.target.value }) })
|
|
590
|
+
] }),
|
|
591
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
592
|
+
t.sPort,
|
|
593
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", value: account.port ?? 993, onChange: (e) => set({ port: Number(e.target.value) }) })
|
|
594
|
+
] })
|
|
595
|
+
] }) : null,
|
|
596
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-row", children: [
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-field", children: [
|
|
598
|
+
t.sSince,
|
|
599
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "number", min: 1, max: 90, value: account.sinceDays ?? 14, onChange: (e) => set({ sinceDays: Number(e.target.value) }) })
|
|
600
|
+
] }),
|
|
601
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "mishu-check", children: [
|
|
602
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: account.enabled !== false, onChange: (e) => set({ enabled: e.target.checked }) }),
|
|
603
|
+
t.sEnabled
|
|
604
|
+
] })
|
|
605
|
+
] }),
|
|
606
|
+
message === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: `mishu-preview ${message.ok ? "" : "mishu-danger"}`, children: message.text }),
|
|
607
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mishu-actions", children: [
|
|
608
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", disabled: busy || !preset.supported, onClick: () => {
|
|
609
|
+
void test();
|
|
610
|
+
}, children: t.sTest }),
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: busy || !preset.supported, onClick: () => {
|
|
612
|
+
void save();
|
|
613
|
+
}, children: t.sSave }),
|
|
614
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => onDone(), children: t.sCancel })
|
|
615
|
+
] })
|
|
616
|
+
] });
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// src/client/Board.tsx
|
|
620
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
621
|
+
var SOURCE_KEY = "dsh-mishu.source";
|
|
622
|
+
function loadSource() {
|
|
623
|
+
try {
|
|
624
|
+
const value = localStorage.getItem(SOURCE_KEY);
|
|
625
|
+
if (value === "github" || value === "mail" || value === "manual") return value;
|
|
626
|
+
} catch {
|
|
627
|
+
}
|
|
628
|
+
return "all";
|
|
629
|
+
}
|
|
630
|
+
var REFRESH_MS = 6e4;
|
|
631
|
+
var WIDTHS_KEY = "dsh-mishu.columns";
|
|
632
|
+
var EQUAL = [1, 1, 1];
|
|
633
|
+
var MIN_COLUMN_PX = 220;
|
|
634
|
+
function dropAction(card, from, to) {
|
|
635
|
+
if (card.target !== "matter" || from === to) return void 0;
|
|
636
|
+
if (to === "done") return "done";
|
|
637
|
+
if (to === "remember" && from === "handle") return "snooze";
|
|
638
|
+
if (to === "handle" && from === "remember") return "unsnooze";
|
|
639
|
+
return void 0;
|
|
640
|
+
}
|
|
641
|
+
function loadWidths() {
|
|
642
|
+
try {
|
|
643
|
+
const value = JSON.parse(localStorage.getItem(WIDTHS_KEY) ?? "null");
|
|
644
|
+
if (Array.isArray(value) && value.length === 3 && value.every((v2) => typeof v2 === "number" && v2 > 0)) return value;
|
|
645
|
+
} catch {
|
|
646
|
+
}
|
|
647
|
+
return EQUAL;
|
|
648
|
+
}
|
|
649
|
+
function saveWidths(widths) {
|
|
650
|
+
try {
|
|
651
|
+
localStorage.setItem(WIDTHS_KEY, JSON.stringify(widths));
|
|
652
|
+
} catch {
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
function MishuBoard({ locale, openChat: openChat2 }) {
|
|
656
|
+
const [board, setBoard] = (0, import_react3.useState)();
|
|
657
|
+
const [error, setError] = (0, import_react3.useState)();
|
|
658
|
+
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
659
|
+
const [syncing, setSyncing] = (0, import_react3.useState)(false);
|
|
660
|
+
const [dropOn, setDropOn] = (0, import_react3.useState)();
|
|
661
|
+
const [widths, setWidths] = (0, import_react3.useState)(loadWidths);
|
|
662
|
+
const [tab, setTab] = (0, import_react3.useState)("board");
|
|
663
|
+
const [source, setSourceState] = (0, import_react3.useState)(loadSource);
|
|
664
|
+
const setSource = (next) => {
|
|
665
|
+
setSourceState(next);
|
|
666
|
+
try {
|
|
667
|
+
localStorage.setItem(SOURCE_KEY, next);
|
|
668
|
+
} catch {
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
const dragged = (0, import_react3.useRef)(void 0);
|
|
672
|
+
const columnsRef = (0, import_react3.useRef)(null);
|
|
673
|
+
const lang = board?.lang ?? uiLang(locale());
|
|
674
|
+
const t = TEXT[lang];
|
|
675
|
+
const take = (0, import_react3.useCallback)((result) => {
|
|
676
|
+
if (result.ok) {
|
|
677
|
+
setBoard(result.board);
|
|
678
|
+
setError(void 0);
|
|
679
|
+
} else {
|
|
680
|
+
setError(result.message);
|
|
681
|
+
}
|
|
682
|
+
}, []);
|
|
683
|
+
const load = (0, import_react3.useCallback)(() => mishuApi.board(locale()).then(take), [locale, take]);
|
|
684
|
+
(0, import_react3.useEffect)(() => {
|
|
685
|
+
void load();
|
|
686
|
+
const timer = setInterval(() => {
|
|
687
|
+
void load();
|
|
688
|
+
}, REFRESH_MS);
|
|
689
|
+
const onFocus = () => {
|
|
690
|
+
void load();
|
|
691
|
+
};
|
|
692
|
+
window.addEventListener("focus", onFocus);
|
|
693
|
+
return () => {
|
|
694
|
+
clearInterval(timer);
|
|
695
|
+
window.removeEventListener("focus", onFocus);
|
|
696
|
+
};
|
|
697
|
+
}, [load]);
|
|
698
|
+
const act = async (card2, action) => {
|
|
699
|
+
if (action === "open") {
|
|
700
|
+
if (card2.url !== null) window.open(card2.url, "_blank", "noopener");
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
setBusy(true);
|
|
704
|
+
take(await mishuApi.action(locale(), card2.target, card2.id, action));
|
|
705
|
+
setBusy(false);
|
|
706
|
+
};
|
|
707
|
+
const sync = async () => {
|
|
708
|
+
setSyncing(true);
|
|
709
|
+
take(await mishuApi.sync(locale()));
|
|
710
|
+
setSyncing(false);
|
|
711
|
+
};
|
|
712
|
+
const startResize = (index) => (event) => {
|
|
713
|
+
const container = columnsRef.current;
|
|
714
|
+
if (container === null) return;
|
|
715
|
+
event.preventDefault();
|
|
716
|
+
const handle = event.currentTarget;
|
|
717
|
+
handle.setPointerCapture(event.pointerId);
|
|
718
|
+
const startX = event.clientX;
|
|
719
|
+
const start = widths;
|
|
720
|
+
const total = start[0] + start[1] + start[2];
|
|
721
|
+
const usable = container.getBoundingClientRect().width - 2 * 10;
|
|
722
|
+
const minFr = MIN_COLUMN_PX / usable * total;
|
|
723
|
+
let latest = start;
|
|
724
|
+
const move = (e) => {
|
|
725
|
+
const delta = (e.clientX - startX) / usable * total;
|
|
726
|
+
const pair = start[index] + start[index + 1];
|
|
727
|
+
const left = Math.min(pair - minFr, Math.max(minFr, start[index] + delta));
|
|
728
|
+
const next = [...start];
|
|
729
|
+
next[index] = left;
|
|
730
|
+
next[index + 1] = pair - left;
|
|
731
|
+
latest = next;
|
|
732
|
+
setWidths(next);
|
|
733
|
+
};
|
|
734
|
+
const up = () => {
|
|
735
|
+
handle.removeEventListener("pointermove", move);
|
|
736
|
+
handle.removeEventListener("pointerup", up);
|
|
737
|
+
handle.removeEventListener("pointercancel", up);
|
|
738
|
+
saveWidths(latest);
|
|
739
|
+
};
|
|
740
|
+
handle.addEventListener("pointermove", move);
|
|
741
|
+
handle.addEventListener("pointerup", up);
|
|
742
|
+
handle.addEventListener("pointercancel", up);
|
|
743
|
+
};
|
|
744
|
+
const resetWidths = () => {
|
|
745
|
+
setWidths(EQUAL);
|
|
746
|
+
saveWidths(EQUAL);
|
|
747
|
+
};
|
|
748
|
+
const dropProps = (column) => ({
|
|
749
|
+
onDragOver: (event) => {
|
|
750
|
+
const drag = dragged.current;
|
|
751
|
+
if (drag === void 0 || dropAction(drag.card, drag.from, column) === void 0) return;
|
|
752
|
+
event.preventDefault();
|
|
753
|
+
setDropOn(column);
|
|
754
|
+
},
|
|
755
|
+
onDragLeave: () => setDropOn((current) => current === column ? void 0 : current),
|
|
756
|
+
onDrop: (event) => {
|
|
757
|
+
event.preventDefault();
|
|
758
|
+
setDropOn(void 0);
|
|
759
|
+
const drag = dragged.current;
|
|
760
|
+
dragged.current = void 0;
|
|
761
|
+
const action = drag === void 0 ? void 0 : dropAction(drag.card, drag.from, column);
|
|
762
|
+
if (drag !== void 0 && action !== void 0) void act(drag.card, action);
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
const label = {
|
|
766
|
+
open: t.open,
|
|
767
|
+
done: t.markDone,
|
|
768
|
+
snooze: t.snooze,
|
|
769
|
+
dismiss: t.dismiss,
|
|
770
|
+
unsnooze: t.unsnooze,
|
|
771
|
+
reopen: t.reopen,
|
|
772
|
+
stop: t.stop
|
|
773
|
+
};
|
|
774
|
+
const card = (item, column) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
775
|
+
Card,
|
|
776
|
+
{
|
|
777
|
+
item,
|
|
778
|
+
column,
|
|
779
|
+
lang,
|
|
780
|
+
locale,
|
|
781
|
+
busy,
|
|
782
|
+
label,
|
|
783
|
+
openChat: openChat2,
|
|
784
|
+
onAct: (action) => {
|
|
785
|
+
void act(item, action);
|
|
786
|
+
},
|
|
787
|
+
onDragStart: () => {
|
|
788
|
+
dragged.current = { card: item, from: column };
|
|
789
|
+
},
|
|
790
|
+
onDragEnd: () => {
|
|
791
|
+
dragged.current = void 0;
|
|
792
|
+
setDropOn(void 0);
|
|
793
|
+
}
|
|
794
|
+
},
|
|
795
|
+
`${item.target}-${item.id}`
|
|
796
|
+
);
|
|
797
|
+
if (board === void 0) {
|
|
798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-page", children: [
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-head", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: t.title }) }),
|
|
800
|
+
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: [
|
|
801
|
+
t.failed,
|
|
802
|
+
error
|
|
803
|
+
] })
|
|
804
|
+
] });
|
|
805
|
+
}
|
|
806
|
+
const { metrics } = board;
|
|
807
|
+
const keep = (card2) => source === "all" || card2.source === source;
|
|
808
|
+
const columns = {
|
|
809
|
+
handle: board.columns.handle.filter(keep),
|
|
810
|
+
remember: board.columns.remember.filter(keep),
|
|
811
|
+
done: (() => {
|
|
812
|
+
const groups = board.columns.done.groups.map((g) => ({ ...g, items: g.items.filter(keep) })).filter((g) => g.items.length > 0);
|
|
813
|
+
return { total: groups.reduce((n, g) => n + g.items.length, 0), groups };
|
|
814
|
+
})()
|
|
815
|
+
};
|
|
816
|
+
const everything = [...board.columns.handle, ...board.columns.remember, ...board.columns.done.groups.flatMap((g) => g.items)];
|
|
817
|
+
const count = (s) => everything.filter((c) => s === "all" || c.source === s).length;
|
|
818
|
+
const sources = [
|
|
819
|
+
{ id: "all", label: t.all },
|
|
820
|
+
{ id: "github", label: t.sourceGithub },
|
|
821
|
+
{ id: "mail", label: t.sourceMail },
|
|
822
|
+
{ id: "manual", label: t.sourceManual }
|
|
823
|
+
];
|
|
824
|
+
const template = `minmax(0, ${widths[0]}fr) 10px minmax(0, ${widths[1]}fr) 10px minmax(0, ${widths[2]}fr)`;
|
|
825
|
+
const divider = (index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
826
|
+
"div",
|
|
827
|
+
{
|
|
828
|
+
className: "mishu-divider",
|
|
829
|
+
role: "separator",
|
|
830
|
+
"aria-orientation": "vertical",
|
|
831
|
+
title: t.resize,
|
|
832
|
+
onPointerDown: startResize(index),
|
|
833
|
+
onDoubleClick: resetWidths
|
|
834
|
+
}
|
|
835
|
+
);
|
|
836
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-page", "data-mishu-board": "", children: [
|
|
837
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-head", children: [
|
|
838
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-title", children: [
|
|
839
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: t.title }),
|
|
840
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-tabs", role: "tablist", children: [
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "board", className: tab === "board" ? "active" : "", onClick: () => setTab("board"), children: t.tabBoard }),
|
|
842
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", role: "tab", "aria-selected": tab === "settings", className: tab === "settings" ? "active" : "", onClick: () => setTab("settings"), children: t.tabSettings })
|
|
843
|
+
] })
|
|
844
|
+
] }),
|
|
845
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-sources", children: [
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
847
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: `mishu-dot ${board.sources.github.state}` }),
|
|
848
|
+
board.sources.github.text,
|
|
849
|
+
board.sources.github.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "github-error" }, lang, locale, openChat: openChat2, compact: true }) : null
|
|
850
|
+
] }),
|
|
851
|
+
board.sources.mail.map((m) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: `mishu-dot ${m.state}` }),
|
|
853
|
+
m.text,
|
|
854
|
+
m.state === "error" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "mail-error", accountId: m.id }, lang, locale, openChat: openChat2, compact: true }) : null
|
|
855
|
+
] }, m.id)),
|
|
856
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", disabled: syncing, onClick: () => {
|
|
857
|
+
void sync();
|
|
858
|
+
}, children: syncing ? t.syncing : t.sync })
|
|
859
|
+
] })
|
|
860
|
+
] }),
|
|
861
|
+
tab === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MishuSettings, { lang, locale, openChat: openChat2 }) : null,
|
|
862
|
+
tab === "settings" ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
863
|
+
error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-error", children: [
|
|
864
|
+
t.failed,
|
|
865
|
+
error
|
|
866
|
+
] }),
|
|
867
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "mishu-summary", children: [
|
|
868
|
+
board.summary,
|
|
869
|
+
" ",
|
|
870
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: { kind: "summary" }, lang, locale, openChat: openChat2, compact: true })
|
|
871
|
+
] }),
|
|
872
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metrics", children: [
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
|
|
874
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricHandle }),
|
|
875
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric-value", children: [
|
|
876
|
+
metrics.handle,
|
|
877
|
+
metrics.overdue > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("small", { className: "mishu-danger", children: [
|
|
878
|
+
metrics.overdue,
|
|
879
|
+
" ",
|
|
880
|
+
t.metricOverdue
|
|
881
|
+
] }) : null
|
|
882
|
+
] })
|
|
883
|
+
] }),
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
|
|
885
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricSoon }),
|
|
886
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-value", children: metrics.dueSoon })
|
|
887
|
+
] }),
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
|
|
889
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricClosed }),
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-value", children: metrics.closedToday })
|
|
891
|
+
] }),
|
|
892
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric", children: [
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-metric-label", children: t.metricShadow }),
|
|
894
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-metric-value", children: [
|
|
895
|
+
metrics.shadow,
|
|
896
|
+
board.markRead === "shadow" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { className: "mishu-warn", children: t.shadowTag }) : null
|
|
897
|
+
] })
|
|
898
|
+
] })
|
|
899
|
+
] }),
|
|
900
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-filters", role: "group", children: sources.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", "aria-pressed": source === s.id, className: `mishu-chip ${source === s.id ? "active" : ""}`, onClick: () => setSource(s.id), children: [
|
|
901
|
+
s.label,
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: count(s.id) })
|
|
903
|
+
] }, s.id)) }),
|
|
904
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-columns", ref: columnsRef, style: { ["--mishu-cols"]: template }, children: [
|
|
905
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: `mishu-col ${dropOn === "handle" ? "drop" : ""}`, ...dropProps("handle"), "aria-label": t.handle, children: [
|
|
906
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-col-head", children: [
|
|
907
|
+
t.handle,
|
|
908
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: columns.handle.length })
|
|
909
|
+
] }),
|
|
910
|
+
columns.handle.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.emptyHandle }) : columns.handle.map((item) => card(item, "handle"))
|
|
911
|
+
] }),
|
|
912
|
+
divider(0),
|
|
913
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: `mishu-col ${dropOn === "remember" ? "drop" : ""}`, ...dropProps("remember"), "aria-label": t.remember, title: t.dropRemember, children: [
|
|
914
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-col-head", children: [
|
|
915
|
+
t.remember,
|
|
916
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: columns.remember.length })
|
|
917
|
+
] }),
|
|
918
|
+
columns.remember.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.emptyRemember }) : columns.remember.map((item) => card(item, "remember")),
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AddForm, { lang, locale, onAdded: (next) => setBoard(next) })
|
|
920
|
+
] }),
|
|
921
|
+
divider(1),
|
|
922
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: `mishu-col ${dropOn === "done" ? "drop" : ""}`, ...dropProps("done"), "aria-label": t.done, title: t.dropDone, children: [
|
|
923
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-col-head", children: [
|
|
924
|
+
t.done,
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: columns.done.total })
|
|
926
|
+
] }),
|
|
927
|
+
columns.done.groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.emptyDone }) : columns.done.groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("details", { className: "mishu-group", children: [
|
|
928
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("summary", { children: [
|
|
929
|
+
group.label,
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: group.items.length })
|
|
931
|
+
] }),
|
|
932
|
+
group.items.map((item) => card(item, "done"))
|
|
933
|
+
] }, group.reason)),
|
|
934
|
+
columns.done.total > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.doneHint }) : null,
|
|
935
|
+
metrics.shadow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-banner", children: t.shadow(metrics.shadow) }) : null
|
|
936
|
+
] })
|
|
937
|
+
] })
|
|
938
|
+
] })
|
|
939
|
+
] });
|
|
940
|
+
}
|
|
941
|
+
function Card({ item, column, lang, locale, busy, label, openChat: openChat2, onAct, onDragStart, onDragEnd }) {
|
|
942
|
+
const t = TEXT[lang];
|
|
943
|
+
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
944
|
+
const [detail, setDetail] = (0, import_react3.useState)();
|
|
945
|
+
const explain = item.explain;
|
|
946
|
+
const compact = column === "done";
|
|
947
|
+
const toggle = () => {
|
|
948
|
+
const next = !open;
|
|
949
|
+
setOpen(next);
|
|
950
|
+
if (next && item.target === "matter") {
|
|
951
|
+
void mishuApi.detail(locale(), item.id).then((r) => setDetail(r.ok ? r.detail : { error: r.message }));
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
const row = (name, text, className = "") => text === null || text === void 0 || text === "" ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `mishu-row-explain ${className}`, children: [
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-row-label", children: name }),
|
|
956
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: text })
|
|
957
|
+
] });
|
|
958
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
959
|
+
"div",
|
|
960
|
+
{
|
|
961
|
+
className: `mishu-card ${item.tone === "normal" ? "" : item.tone}`,
|
|
962
|
+
draggable: item.target === "matter" && column !== "done",
|
|
963
|
+
onDragStart: (event) => {
|
|
964
|
+
event.dataTransfer.effectAllowed = "move";
|
|
965
|
+
onDragStart();
|
|
966
|
+
},
|
|
967
|
+
onDragEnd,
|
|
968
|
+
children: [
|
|
969
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-card-title", children: item.title }),
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-card-meta", children: item.meta }),
|
|
971
|
+
!compact && explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-explain", children: [
|
|
972
|
+
row(t.what, explain.what),
|
|
973
|
+
row(column === "remember" ? t.whyKeep : t.why, explain.why),
|
|
974
|
+
row(t.fix, explain.fix, "mishu-fix")
|
|
975
|
+
] }) : null,
|
|
976
|
+
!compact && explain === null && item.note !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-card-note", children: item.note }) : null,
|
|
977
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-detail", children: detail === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-empty", children: t.loading }) : "error" in detail ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-danger", children: detail.error }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
978
|
+
compact && detail.explain !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
979
|
+
row(t.what, detail.explain.what),
|
|
980
|
+
row(t.whyDone, detail.explain.why)
|
|
981
|
+
] }) : null,
|
|
982
|
+
detail.did.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row-explain", children: [
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mishu-row-label", children: t.did }),
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: detail.did.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: line }, i)) })
|
|
985
|
+
] }) : null,
|
|
986
|
+
detail.messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-messages", children: [
|
|
987
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mishu-row-label", children: t.messages(detail.messages.length) }),
|
|
988
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { children: detail.messages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
989
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: m.at }),
|
|
990
|
+
" ",
|
|
991
|
+
m.title
|
|
992
|
+
] }, i)) })
|
|
993
|
+
] }) : null
|
|
994
|
+
] }) }) : null,
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
|
|
996
|
+
column === "handle" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2 }) : null,
|
|
997
|
+
item.actions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
998
|
+
"button",
|
|
999
|
+
{
|
|
1000
|
+
type: "button",
|
|
1001
|
+
className: `mishu-btn ${index === 0 ? "primary" : ""}`,
|
|
1002
|
+
disabled: busy && action !== "open",
|
|
1003
|
+
onClick: () => onAct(action),
|
|
1004
|
+
children: action === "open" && explain?.link !== void 0 ? explain.link.label : label[action]
|
|
1005
|
+
},
|
|
1006
|
+
action
|
|
1007
|
+
)),
|
|
1008
|
+
item.target === "matter" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn mishu-btn-quiet", "aria-expanded": open, onClick: toggle, children: open ? t.hide : compact ? t.explainDone : t.detail }) : null,
|
|
1009
|
+
column === "handle" ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AskAI, { topic: item.target === "series" ? { kind: "series", id: item.id } : { kind: "matter", id: item.id }, lang, locale, openChat: openChat2, compact: true })
|
|
1010
|
+
] })
|
|
1011
|
+
]
|
|
1012
|
+
}
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
var EMPTY = { title: "", due: "", repeat: "none", category: "other", note: "" };
|
|
1016
|
+
function AddForm({ lang, locale, onAdded }) {
|
|
1017
|
+
const t = TEXT[lang];
|
|
1018
|
+
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
1019
|
+
const [item, setItem] = (0, import_react3.useState)(EMPTY);
|
|
1020
|
+
const [preview, setPreview] = (0, import_react3.useState)();
|
|
1021
|
+
const [saving, setSaving] = (0, import_react3.useState)(false);
|
|
1022
|
+
(0, import_react3.useEffect)(() => {
|
|
1023
|
+
if (!open || item.title.trim() === "" || item.due === "") {
|
|
1024
|
+
setPreview(void 0);
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const timer = setTimeout(() => {
|
|
1028
|
+
void mishuApi.preview(locale(), item).then((r) => setPreview(r.ok ? { ok: true, text: r.text } : { ok: false, text: r.message }));
|
|
1029
|
+
}, 250);
|
|
1030
|
+
return () => clearTimeout(timer);
|
|
1031
|
+
}, [open, item, locale]);
|
|
1032
|
+
if (!open) {
|
|
1033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "mishu-btn mishu-add-toggle", onClick: () => setOpen(true), children: [
|
|
1034
|
+
"+ ",
|
|
1035
|
+
t.add
|
|
1036
|
+
] });
|
|
1037
|
+
}
|
|
1038
|
+
const set = (key) => (event) => setItem({ ...item, [key]: event.target.value });
|
|
1039
|
+
const save = async () => {
|
|
1040
|
+
setSaving(true);
|
|
1041
|
+
const result = await mishuApi.add(locale(), item);
|
|
1042
|
+
setSaving(false);
|
|
1043
|
+
if (result.ok) {
|
|
1044
|
+
onAdded(result.board);
|
|
1045
|
+
setItem(EMPTY);
|
|
1046
|
+
setOpen(false);
|
|
1047
|
+
} else {
|
|
1048
|
+
setPreview({ ok: false, text: result.message });
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-add", children: [
|
|
1052
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
1053
|
+
t.addTitle,
|
|
1054
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: item.title, placeholder: t.addTitlePlaceholder, onChange: set("title") })
|
|
1055
|
+
] }),
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row", children: [
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
1058
|
+
t.addDue,
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "date", value: item.due, onChange: set("due") })
|
|
1060
|
+
] }),
|
|
1061
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
1062
|
+
t.addRepeat,
|
|
1063
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("select", { value: item.repeat, onChange: set("repeat"), children: Object.entries(t.repeats).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value, children: text }, value)) })
|
|
1064
|
+
] })
|
|
1065
|
+
] }),
|
|
1066
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-row", children: [
|
|
1067
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
1068
|
+
t.addCategory,
|
|
1069
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("select", { value: item.category, onChange: set("category"), children: Object.entries(t.categories).map(([value, text]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value, children: text }, value)) })
|
|
1070
|
+
] }),
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mishu-field", children: [
|
|
1072
|
+
t.addNote,
|
|
1073
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: item.note, onChange: set("note") })
|
|
1074
|
+
] })
|
|
1075
|
+
] }),
|
|
1076
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `mishu-preview ${preview?.ok === false ? "mishu-danger" : ""}`, children: preview?.text ?? t.previewHint }),
|
|
1077
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mishu-actions", children: [
|
|
1078
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn primary", disabled: saving || preview?.ok !== true, onClick: () => {
|
|
1079
|
+
void save();
|
|
1080
|
+
}, children: t.save }),
|
|
1081
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mishu-btn", onClick: () => {
|
|
1082
|
+
setOpen(false);
|
|
1083
|
+
setItem(EMPTY);
|
|
1084
|
+
}, children: t.cancel })
|
|
1085
|
+
] }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mishu-hint", children: t.chatHint })
|
|
1087
|
+
] });
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// src/client/styles.ts
|
|
1091
|
+
var v = (name, fallback) => `var(--dsw-alias-${name}, ${fallback})`;
|
|
1092
|
+
var TEXT2 = v("label-primary", "CanvasText");
|
|
1093
|
+
var MUTED = v("label-secondary", "GrayText");
|
|
1094
|
+
var FAINT = v("label-tertiary", "GrayText");
|
|
1095
|
+
var LINE = v("border-l2", "rgba(127,127,127,.22)");
|
|
1096
|
+
var LINE_STRONG = v("border-l3", "rgba(127,127,127,.35)");
|
|
1097
|
+
var LAYER1 = v("bg-layer-1", "rgba(127,127,127,.06)");
|
|
1098
|
+
var LAYER2 = v("bg-layer-2", "rgba(127,127,127,.10)");
|
|
1099
|
+
var HOVER = v("interactive-bg-hover", "rgba(127,127,127,.12)");
|
|
1100
|
+
var DANGER = v("state-error-primary", "#d14343");
|
|
1101
|
+
var WARN = v("state-warn-primary", "#b7791f");
|
|
1102
|
+
var OK = v("state-success-primary", "#2f855a");
|
|
1103
|
+
var ACCENT = v("brand-primary", "#4d6bfe");
|
|
1104
|
+
var STYLES = `
|
|
1105
|
+
.mishu-page{box-sizing:border-box;height:100%;overflow:auto;padding:20px 24px 32px;color:${TEXT2};font-size:13px;line-height:1.5}
|
|
1106
|
+
.mishu-page *{box-sizing:border-box}
|
|
1107
|
+
.mishu-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:8px}
|
|
1108
|
+
.mishu-head h1{font-size:18px;font-weight:600;margin:0}
|
|
1109
|
+
.mishu-sources{display:flex;align-items:center;gap:10px;color:${MUTED};font-size:12px;flex-wrap:wrap}
|
|
1110
|
+
.mishu-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:4px;vertical-align:1px;background:${FAINT}}
|
|
1111
|
+
.mishu-dot.ok{background:${OK}}.mishu-dot.error{background:${DANGER}}
|
|
1112
|
+
.mishu-summary{font-size:15px;margin:4px 0 14px;max-width:72ch}
|
|
1113
|
+
.mishu-metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:16px}
|
|
1114
|
+
.mishu-metric{background:${LAYER1};border-radius:10px;padding:10px 12px}
|
|
1115
|
+
.mishu-metric-label{font-size:12px;color:${MUTED}}
|
|
1116
|
+
.mishu-metric-value{font-size:22px;font-weight:600;line-height:1.3}
|
|
1117
|
+
.mishu-metric-value small{font-size:12px;font-weight:400;margin-left:6px}
|
|
1118
|
+
.mishu-danger{color:${DANGER}}.mishu-warn{color:${WARN}}
|
|
1119
|
+
.mishu-columns{display:grid;grid-template-columns:var(--mishu-cols,minmax(0,1fr) 10px minmax(0,1fr) 10px minmax(0,1fr));gap:0;align-items:stretch}
|
|
1120
|
+
.mishu-divider{cursor:col-resize;position:relative;touch-action:none}
|
|
1121
|
+
.mishu-divider::after{content:'';position:absolute;top:8px;bottom:8px;left:4px;width:2px;border-radius:1px;background:transparent;transition:background .12s}
|
|
1122
|
+
.mishu-divider:hover::after,.mishu-divider:active::after{background:${ACCENT}}
|
|
1123
|
+
.mishu-col{background:${LAYER1};border-radius:12px;padding:10px;min-height:120px;min-width:0;border:1px solid transparent;transition:border-color .12s;align-self:start}
|
|
1124
|
+
.mishu-col.drop{border-color:${ACCENT};border-style:dashed}
|
|
1125
|
+
.mishu-col-head{display:flex;justify-content:space-between;align-items:baseline;font-weight:600;margin:2px 4px 8px}
|
|
1126
|
+
.mishu-col-head span{color:${MUTED};font-weight:400}
|
|
1127
|
+
.mishu-empty{color:${FAINT};padding:8px 4px}
|
|
1128
|
+
.mishu-card{background:${LAYER2};border:1px solid ${LINE};border-radius:8px;padding:8px 10px;margin-bottom:8px}
|
|
1129
|
+
.mishu-card[draggable=true]{cursor:grab}
|
|
1130
|
+
.mishu-card.danger{border-color:${DANGER}}
|
|
1131
|
+
.mishu-card-title{font-weight:600;word-break:break-word}
|
|
1132
|
+
.mishu-card-meta{font-size:12px;color:${MUTED};margin-top:2px}
|
|
1133
|
+
.mishu-card.danger .mishu-card-meta{color:${DANGER}}
|
|
1134
|
+
.mishu-card.warn .mishu-card-meta{color:${WARN}}
|
|
1135
|
+
.mishu-card-note{font-size:12px;color:${MUTED};margin-top:4px;word-break:break-word}
|
|
1136
|
+
.mishu-actions{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}
|
|
1137
|
+
.mishu-explain{margin-top:6px;display:flex;flex-direction:column;gap:4px}
|
|
1138
|
+
.mishu-row-explain{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;font-size:12px;line-height:1.55;word-break:break-word}
|
|
1139
|
+
.mishu-row-label{color:${FAINT};white-space:nowrap;font-size:12px}
|
|
1140
|
+
.mishu-fix span:last-child{color:${TEXT2}}
|
|
1141
|
+
.mishu-detail{margin-top:8px;padding-top:8px;border-top:1px dashed ${LINE};display:flex;flex-direction:column;gap:6px}
|
|
1142
|
+
.mishu-messages ul{margin:4px 0 0;padding-left:16px;font-size:12px;color:${MUTED}}
|
|
1143
|
+
.mishu-messages li span{color:${FAINT};margin-right:4px}
|
|
1144
|
+
.mishu-btn-quiet{border-color:transparent;color:${MUTED}}
|
|
1145
|
+
.mishu-btn{font:inherit;font-size:12px;color:${TEXT2};background:transparent;border:1px solid ${LINE_STRONG};border-radius:6px;padding:2px 9px;cursor:pointer}
|
|
1146
|
+
.mishu-btn:hover{background:${HOVER}}
|
|
1147
|
+
.mishu-btn:disabled{opacity:.5;cursor:default}
|
|
1148
|
+
.mishu-btn.primary{border-color:${ACCENT};color:${ACCENT}}
|
|
1149
|
+
.mishu-group{border-top:1px solid ${LINE};padding:6px 4px}
|
|
1150
|
+
.mishu-group summary{cursor:pointer;display:flex;justify-content:space-between;list-style:none}
|
|
1151
|
+
.mishu-group summary::-webkit-details-marker{display:none}
|
|
1152
|
+
.mishu-group summary span{color:${MUTED}}
|
|
1153
|
+
.mishu-group .mishu-card{margin-top:6px}
|
|
1154
|
+
.mishu-hint{font-size:12px;color:${FAINT};margin:6px 4px 0}
|
|
1155
|
+
.mishu-banner{margin-top:10px;padding:8px 10px;border-radius:8px;border:1px solid ${WARN};color:${WARN};font-size:12px}
|
|
1156
|
+
.mishu-error{margin-bottom:12px;padding:8px 10px;border-radius:8px;border:1px solid ${DANGER};color:${DANGER};font-size:12px}
|
|
1157
|
+
.mishu-add{border:1px dashed ${LINE_STRONG};border-radius:8px;padding:8px;margin-top:4px}
|
|
1158
|
+
.mishu-add-toggle{width:100%;text-align:left;border-style:dashed}
|
|
1159
|
+
.mishu-field{display:flex;flex-direction:column;gap:2px;margin-bottom:6px;font-size:12px;color:${MUTED}}
|
|
1160
|
+
.mishu-field input,.mishu-field select{font:inherit;font-size:13px;color:${TEXT2};background:${LAYER2};border:1px solid ${LINE_STRONG};border-radius:6px;padding:4px 6px;width:100%}
|
|
1161
|
+
.mishu-row{display:grid;grid-template-columns:1fr 1fr;gap:6px}
|
|
1162
|
+
.mishu-preview{white-space:pre-wrap;font-size:12px;background:${LAYER2};border-radius:6px;padding:6px 8px;margin:4px 0 6px;color:${TEXT2}}
|
|
1163
|
+
.mishu-title{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
|
|
1164
|
+
.mishu-tabs{display:flex;gap:2px;background:${LAYER1};border-radius:8px;padding:2px}
|
|
1165
|
+
.mishu-tabs button{font:inherit;font-size:13px;color:${MUTED};background:transparent;border:0;border-radius:6px;padding:3px 12px;cursor:pointer}
|
|
1166
|
+
.mishu-tabs button.active{background:${LAYER2};color:${TEXT2}}
|
|
1167
|
+
.mishu-filters{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 10px}
|
|
1168
|
+
.mishu-chip{font:inherit;font-size:12px;color:${MUTED};background:transparent;border:1px solid ${LINE_STRONG};border-radius:999px;padding:2px 10px;cursor:pointer;display:inline-flex;gap:6px;align-items:center}
|
|
1169
|
+
.mishu-chip span{color:${FAINT}}
|
|
1170
|
+
.mishu-chip.active{border-color:${ACCENT};color:${ACCENT}}
|
|
1171
|
+
.mishu-chip.active span{color:${ACCENT}}
|
|
1172
|
+
.mishu-settings{display:flex;flex-direction:column;gap:12px;max-width:760px}
|
|
1173
|
+
.mishu-panel{background:${LAYER1};border-radius:12px;padding:12px 14px}
|
|
1174
|
+
.mishu-panel h2{font-size:14px;font-weight:600;margin:0 0 8px}
|
|
1175
|
+
.mishu-grid5{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px;margin-bottom:8px}
|
|
1176
|
+
.mishu-check{display:flex;align-items:center;gap:6px;font-size:13px;margin:4px 0 8px;color:${TEXT2}}
|
|
1177
|
+
.mishu-ok{padding:6px 10px;border-radius:8px;border:1px solid ${OK};color:${OK};font-size:12px}
|
|
1178
|
+
.mishu-ai-wrap{display:inline-flex;align-items:center;gap:6px;vertical-align:middle;flex-wrap:wrap}
|
|
1179
|
+
.mishu-ai{font:inherit;font-size:12px;font-weight:700;letter-spacing:.02em;color:#fff;border:0;border-radius:999px;padding:3px 11px;cursor:pointer;background:linear-gradient(120deg,#6d5dfc 0%,#c850c0 50%,#ff8a3d 100%);background-size:160% 100%;transition:background-position .3s,transform .1s}
|
|
1180
|
+
.mishu-ai:hover{background-position:100% 0}
|
|
1181
|
+
.mishu-ai:active{transform:scale(.97)}
|
|
1182
|
+
.mishu-ai:disabled{opacity:.6;cursor:default}
|
|
1183
|
+
.mishu-ai.compact{font-size:11px;padding:1px 8px;margin-left:4px}
|
|
1184
|
+
.mishu-ai:focus-visible{outline:2px solid ${ACCENT};outline-offset:2px}
|
|
1185
|
+
.mishu-ai-note{font-size:11px;color:${MUTED}}
|
|
1186
|
+
@media (max-width:820px){.mishu-columns{grid-template-columns:1fr;gap:12px}.mishu-divider{display:none}.mishu-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.mishu-grid5{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
|
1187
|
+
`;
|
|
1188
|
+
|
|
1189
|
+
// src/client/index.tsx
|
|
1190
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1191
|
+
var PACKAGE_NAME = "dsh-mishu";
|
|
1192
|
+
var inject = ["slots", "locale"];
|
|
1193
|
+
var PANEL_ID = "dsh-mishu";
|
|
1194
|
+
var NS = "dsh-mishu";
|
|
1195
|
+
var openChat;
|
|
1196
|
+
function MishuIcon({ size }) {
|
|
1197
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1198
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "5", y: "4", width: "14", height: "17", rx: "2" }),
|
|
1199
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 4h6v3H9z" }),
|
|
1200
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 12l2 2 4-4" }),
|
|
1201
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 17h6" })
|
|
1202
|
+
] });
|
|
1203
|
+
}
|
|
1204
|
+
function apply(ctx) {
|
|
1205
|
+
ctx.effect(() => ctx.locale.register(NS, { zh: { panel: "\u5C0F\u79D8\u4E66" }, en: { panel: "Secretary" } }), "dsh-mishu: dictionaries");
|
|
1206
|
+
ctx.effect(() => {
|
|
1207
|
+
const style = document.createElement("style");
|
|
1208
|
+
style.dataset.dshPlugin = PACKAGE_NAME;
|
|
1209
|
+
style.textContent = STYLES;
|
|
1210
|
+
document.head.append(style);
|
|
1211
|
+
return () => {
|
|
1212
|
+
style.remove();
|
|
1213
|
+
};
|
|
1214
|
+
}, "dsh-mishu: styles");
|
|
1215
|
+
const t = ctx.locale.bind(NS);
|
|
1216
|
+
const locale = () => ctx.locale.getSnapshot().active;
|
|
1217
|
+
ctx.inject(["uiWorkspace"], (workspaceCtx) => {
|
|
1218
|
+
workspaceCtx.effect(() => {
|
|
1219
|
+
openChat = (prompt) => workspaceCtx.uiWorkspace.startSession(void 0, { prompt, clearPreviousDraft: true });
|
|
1220
|
+
return () => {
|
|
1221
|
+
openChat = void 0;
|
|
1222
|
+
};
|
|
1223
|
+
}, "dsh-mishu: +AI opens a chat");
|
|
1224
|
+
});
|
|
1225
|
+
ctx.slots.inject("main", () => ctx.slots.register({
|
|
1226
|
+
name: "main",
|
|
1227
|
+
key: PANEL_ID,
|
|
1228
|
+
locale: NS,
|
|
1229
|
+
inject: () => ({ locale, openChat: (prompt) => openChat === void 0 ? false : (openChat(prompt), true) })
|
|
1230
|
+
}, MishuBoard));
|
|
1231
|
+
ctx.slots.inject("sidebar.panellist", () => ctx.slots.register({
|
|
1232
|
+
name: "sidebar.panellist",
|
|
1233
|
+
id: PANEL_ID,
|
|
1234
|
+
order: 30,
|
|
1235
|
+
locale: NS,
|
|
1236
|
+
label: () => t("panel")
|
|
1237
|
+
}, MishuIcon));
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
return module.exports;
|
|
1241
|
+
}
|
|
1242
|
+
});
|