dsh-sessions-manager 3.6.2 → 3.7.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/README.en.md +21 -10
- package/README.md +23 -12
- package/lib/client.js +990 -32
- package/lib/client.js.map +2 -2
- package/lib/index.js +921 -151
- package/lib/index.js.map +4 -4
- package/package.json +1 -1
- package/src/client/index.jsx +816 -33
- package/src/client/logic.js +285 -0
- package/src/empty-scan-index.js +118 -0
- package/src/index.js +340 -79
- package/src/lineage.js +18 -14
- package/src/move-notices.js +129 -0
- package/src/saved-filters.js +208 -0
- package/src/tag-index.js +308 -0
package/lib/client.js
CHANGED
|
@@ -152,6 +152,167 @@ function toastDurationFor(text, kind) {
|
|
|
152
152
|
const scaled = kind === "err" ? Math.round(readingMs * 1.25) : readingMs;
|
|
153
153
|
return Math.min(TOAST_MAX_MS, Math.max(TOAST_MIN_MS, scaled));
|
|
154
154
|
}
|
|
155
|
+
function pathTail(p) {
|
|
156
|
+
const parts = String(p == null ? "" : p).split(/[\\/]+/).filter(Boolean);
|
|
157
|
+
return parts.length ? parts[parts.length - 1] : "";
|
|
158
|
+
}
|
|
159
|
+
function moveNoticeText(n) {
|
|
160
|
+
const id = shortId(n && n.sessionId);
|
|
161
|
+
if (n && n.kind === "moved") {
|
|
162
|
+
const where = pathTail(n.targetPath);
|
|
163
|
+
return `\u6392\u961F\u4E2D\u7684\u79FB\u52A8\u5DF2\u5B8C\u6210\uFF1A${id}${where ? ` \u2192 \u300C${where}\u300D` : ""}`;
|
|
164
|
+
}
|
|
165
|
+
const reason = String(n && n.reason || "").split("\n")[0].slice(0, 120);
|
|
166
|
+
return `\u6392\u961F\u4E2D\u7684\u79FB\u52A8\u591A\u6B21\u5931\u8D25\u5DF2\u653E\u5F03\uFF1A${id}${reason ? `\uFF08${reason}\uFF09` : ""}\uFF0C\u53EF\u5728 \u8BBE\u7F6E \u2192 \u4F1A\u8BDD\u7BA1\u7406 \u2192 \u5F85\u79FB\u52A8\u961F\u5217 \u91CD\u65B0\u53D1\u8D77\u79FB\u52A8`;
|
|
167
|
+
}
|
|
168
|
+
function noticeToastPlan(raw, seenIds, max = 2) {
|
|
169
|
+
const list = (Array.isArray(raw) ? raw : []).filter((n) => n && typeof n.id === "string" && typeof n.sessionId === "string" && (n.kind === "moved" || n.kind === "abandoned") && !seenIds.has(String(n.id))).sort((a, b) => (a.at || 0) - (b.at || 0));
|
|
170
|
+
if (!list.length) return { text: null, kind: "ok", ackIds: [] };
|
|
171
|
+
const shown = list.slice(Math.max(0, list.length - Math.max(1, max)));
|
|
172
|
+
const parts = shown.map(moveNoticeText);
|
|
173
|
+
if (list.length > shown.length) parts.push(`\u53E6\u6709 ${list.length - shown.length} \u6761\u6392\u961F\u79FB\u52A8\u7684\u7ED3\u679C\uFF0C\u89C1 \u8BBE\u7F6E \u2192 \u4F1A\u8BDD\u7BA1\u7406 \u2192 \u5F85\u79FB\u52A8\u961F\u5217`);
|
|
174
|
+
return {
|
|
175
|
+
text: parts.join("\uFF1B"),
|
|
176
|
+
kind: shown.some((n) => n.kind === "abandoned") ? "err" : "ok",
|
|
177
|
+
ackIds: shown.map((n) => String(n.id))
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function branchTimeKey(item) {
|
|
181
|
+
const c = Number(item && item.createdAt);
|
|
182
|
+
if (Number.isFinite(c) && c > 0) return c;
|
|
183
|
+
const u = Number(item && item.updatedAt);
|
|
184
|
+
if (Number.isFinite(u) && u > 0) return u;
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
function ascBranchTime(a, b) {
|
|
188
|
+
const ta = String((a && a.sessionId) ?? "");
|
|
189
|
+
const tb = String((b && b.sessionId) ?? "");
|
|
190
|
+
return branchTimeKey(a) - branchTimeKey(b) || ta.localeCompare(tb);
|
|
191
|
+
}
|
|
192
|
+
function branchParentOf(id, table) {
|
|
193
|
+
const info = table[id];
|
|
194
|
+
if (!info || typeof info !== "object") return null;
|
|
195
|
+
if (info.origin === "subagent") return null;
|
|
196
|
+
const p = info.parentSession ? String(info.parentSession) : null;
|
|
197
|
+
if (!p || p === id) return null;
|
|
198
|
+
return p;
|
|
199
|
+
}
|
|
200
|
+
function foldBranches(items, lineage) {
|
|
201
|
+
const list = Array.isArray(items) ? items : [];
|
|
202
|
+
const table = lineage && typeof lineage === "object" ? lineage : {};
|
|
203
|
+
const byId = /* @__PURE__ */ new Map();
|
|
204
|
+
for (const it of list) {
|
|
205
|
+
if (it == null || it.sessionId == null) continue;
|
|
206
|
+
byId.set(String(it.sessionId), it);
|
|
207
|
+
}
|
|
208
|
+
const maxWalk = Object.keys(table).length + list.length + 2;
|
|
209
|
+
const anchorMemo = /* @__PURE__ */ new Map();
|
|
210
|
+
function resolveAnchor(id) {
|
|
211
|
+
if (anchorMemo.has(id)) return anchorMemo.get(id);
|
|
212
|
+
const seen = /* @__PURE__ */ new Set([id]);
|
|
213
|
+
let cur = id;
|
|
214
|
+
let steps = 0;
|
|
215
|
+
let anchor = null;
|
|
216
|
+
while (true) {
|
|
217
|
+
const p = branchParentOf(cur, table);
|
|
218
|
+
if (!p) {
|
|
219
|
+
anchor = steps === 0 ? null : cur;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
if (seen.has(p)) break;
|
|
223
|
+
seen.add(p);
|
|
224
|
+
steps++;
|
|
225
|
+
if (byId.has(p)) {
|
|
226
|
+
if (!branchParentOf(p, table)) {
|
|
227
|
+
anchor = p;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
cur = p;
|
|
231
|
+
if (steps > maxWalk) break;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (!branchParentOf(p, table)) {
|
|
235
|
+
anchor = p;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
cur = p;
|
|
239
|
+
if (steps > maxWalk) break;
|
|
240
|
+
}
|
|
241
|
+
anchorMemo.set(id, anchor);
|
|
242
|
+
return anchor;
|
|
243
|
+
}
|
|
244
|
+
const groupsOf = /* @__PURE__ */ new Map();
|
|
245
|
+
const anchorOfRow = /* @__PURE__ */ new Map();
|
|
246
|
+
let foldedCount = 0;
|
|
247
|
+
for (const it of list) {
|
|
248
|
+
if (it == null || it.sessionId == null) continue;
|
|
249
|
+
const id = String(it.sessionId);
|
|
250
|
+
if (!branchParentOf(id, table)) continue;
|
|
251
|
+
const anchor = resolveAnchor(id);
|
|
252
|
+
if (!anchor || anchor === id) continue;
|
|
253
|
+
if (!groupsOf.has(anchor)) groupsOf.set(anchor, []);
|
|
254
|
+
groupsOf.get(anchor).push(it);
|
|
255
|
+
anchorOfRow.set(it, anchor);
|
|
256
|
+
foldedCount++;
|
|
257
|
+
}
|
|
258
|
+
const earliest = /* @__PURE__ */ new Set();
|
|
259
|
+
for (const [anchor, members] of groupsOf) {
|
|
260
|
+
members.sort(ascBranchTime);
|
|
261
|
+
if (!byId.has(anchor)) earliest.add(members[0]);
|
|
262
|
+
}
|
|
263
|
+
const topList = [];
|
|
264
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
265
|
+
for (const it of list) {
|
|
266
|
+
const anchor = it == null ? void 0 : anchorOfRow.get(it);
|
|
267
|
+
if (anchor === void 0) {
|
|
268
|
+
topList.push(it);
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (!byId.has(anchor) && !emitted.has(anchor) && earliest.has(it)) {
|
|
272
|
+
emitted.add(anchor);
|
|
273
|
+
topList.push({ syntheticRoot: anchor, sessionId: "dsm-src:" + anchor });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
for (const [anchor, members] of groupsOf) {
|
|
277
|
+
if (!members.length) groupsOf.delete(anchor);
|
|
278
|
+
}
|
|
279
|
+
return { topList, branchGroupsOf: groupsOf, foldedCount, groupCount: groupsOf.size };
|
|
280
|
+
}
|
|
281
|
+
function applyTagFilter(list, tagId) {
|
|
282
|
+
const items = Array.isArray(list) ? list : [];
|
|
283
|
+
if (!tagId) return items;
|
|
284
|
+
const want = String(tagId);
|
|
285
|
+
return items.filter((item) => {
|
|
286
|
+
const tags = item && item.tags;
|
|
287
|
+
return Array.isArray(tags) && tags.some((t) => String(t) === want);
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
function tagDeleteConfirm(name) {
|
|
291
|
+
return `\u5220\u9664\u6807\u7B7E\u300C${String(name == null ? "" : name) || "(\u672A\u547D\u540D)"}\u300D\uFF1F\u53EA\u5220\u6807\u7B7E\uFF0C\u4E0D\u4F1A\u5220\u9664\u4F1A\u8BDD\uFF1B\u6253\u8FC7\u8FD9\u4E2A\u6807\u7B7E\u7684\u4F1A\u8BDD\u53EA\u662F\u5931\u53BB\u5B83\u3002`;
|
|
292
|
+
}
|
|
293
|
+
var SAVED_VIEWS = ["all", "active", "archived", "starred", "empty", "trash"];
|
|
294
|
+
var SAVED_SORTS = ["newest", "oldest", "title"];
|
|
295
|
+
function filterSnapshotOf({ filter = "all", workspaceFilter = "all", sortBy = "newest", tagFilter = "" } = {}) {
|
|
296
|
+
return {
|
|
297
|
+
view: SAVED_VIEWS.includes(filter) ? filter : "all",
|
|
298
|
+
workspace: typeof workspaceFilter === "string" && workspaceFilter ? workspaceFilter : "all",
|
|
299
|
+
sort: SAVED_SORTS.includes(sortBy) ? sortBy : "newest",
|
|
300
|
+
tag: typeof tagFilter === "string" ? tagFilter : ""
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function filterShapeFromSaved(item) {
|
|
304
|
+
const f = item && item.filters && typeof item.filters === "object" && !Array.isArray(item.filters) ? item.filters : {};
|
|
305
|
+
const degraded = [];
|
|
306
|
+
let view = typeof f.view === "string" && SAVED_VIEWS.includes(f.view) ? f.view : "all";
|
|
307
|
+
if (view === "all" && f.view !== "all") degraded.push("view");
|
|
308
|
+
let workspace = typeof f.workspace === "string" && f.workspace ? f.workspace : "all";
|
|
309
|
+
if (workspace === "all" && f.workspace !== "all") degraded.push("workspace");
|
|
310
|
+
let sort = typeof f.sort === "string" && SAVED_SORTS.includes(f.sort) ? f.sort : "newest";
|
|
311
|
+
if (sort === "newest" && f.sort !== "newest") degraded.push("sort");
|
|
312
|
+
let tag = typeof f.tag === "string" ? f.tag : "";
|
|
313
|
+
if (tag === "" && f.tag !== "") degraded.push("tag");
|
|
314
|
+
return { view, workspace, sort, tag, degraded };
|
|
315
|
+
}
|
|
155
316
|
|
|
156
317
|
// src/client/index.jsx
|
|
157
318
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -193,10 +354,14 @@ var CSS = `
|
|
|
193
354
|
.sess-fbtn-on{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3)}
|
|
194
355
|
.sess-tools{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin:0 0 8px}
|
|
195
356
|
.sess-tools-4{grid-template-columns:repeat(auto-fit,minmax(132px,1fr))}
|
|
357
|
+
/* T4 \u8D77\u641C\u7D22\u884C\u6709 5 \u4E2A\u5B57\u6BB5\uFF08\u641C\u7D22/\u5DE5\u4F5C\u533A/\u6807\u7B7E/\u6392\u5E8F/\u5206\u7EC4\uFF09\uFF1A\u6536\u7A84\u4E0B\u9650\u4FDD\u8BC1 800px \u5185\u4E00\u884C\u6392\u6EE1\u3002 */
|
|
358
|
+
.sess-tools-5{grid-template-columns:repeat(auto-fit,minmax(124px,1fr))}
|
|
196
359
|
.dsm-kids{display:flex;flex-direction:column;gap:6px;margin:10px 0 2px;margin-left:43px;padding-left:10px;border-left:2px solid var(--dsw-alias-border-l3)}
|
|
197
360
|
.dsm-kid .dsm-kids{margin-left:8px;margin-top:6px}
|
|
198
361
|
.dsm-kids-toggle{appearance:none;min-height:22px;padding:0 9px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-business-primary) 40%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,transparent);color:var(--dsw-alias-state-business-primary);border-radius:var(--dsm-radius-tag);font:inherit;font-size:11px;font-weight:500;cursor:pointer;flex:none;white-space:nowrap}
|
|
199
362
|
.dsm-kids-toggle:hover{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 18%,transparent)}
|
|
363
|
+
.dsm-src-head{display:flex;align-items:center;gap:8px;padding:5px 9px;border:1px dashed var(--dsw-alias-border-l3);border-radius:var(--dsm-radius-ctl);font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
364
|
+
.dsm-src-head .dsm-src-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
200
365
|
.dsm-kid{display:flex;flex-direction:column;gap:6px;min-width:0}
|
|
201
366
|
.dsm-kid-row{display:flex;align-items:center;gap:8px;min-width:0}
|
|
202
367
|
.dsm-kid-name{flex:1 1 auto;min-width:0;font-size:12px;color:var(--dsw-alias-label-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
@@ -206,7 +371,9 @@ var CSS = `
|
|
|
206
371
|
.sess-field{display:flex;flex-direction:column;gap:5px;min-width:0}
|
|
207
372
|
.sess-field label{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary)}
|
|
208
373
|
.sess-field input,.sess-field select{box-sizing:border-box;width:100%;min-height:36px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-ctl);background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);font:inherit;font-size:12px}
|
|
209
|
-
.sess-results{display:flex;
|
|
374
|
+
.sess-results{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary);margin:0 0 4px}
|
|
375
|
+
/* T4 \u540E\u8BA1\u6570\u884C\u53F3\u4FA7\u6302\u4E86\u300C\u4FDD\u5B58\u7B5B\u9009\u300D\u63A7\u4EF6\u7EC4\uFF0C\u6B63\u6587\u72EC\u5360\u5DE6\u4FA7\u53EF\u6536\u7F29\u3002 */
|
|
376
|
+
.sess-results-main{flex:1 1 auto;min-width:0}
|
|
210
377
|
.archv button:focus-visible,.archv input:focus-visible,.archv select:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
|
|
211
378
|
.sess-batch{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 2px 4px;margin-bottom:4px}
|
|
212
379
|
/* issue #7\uFF1A\u52FE\u9009\u540E\u6279\u91CF\u64CD\u4F5C\u680F\u5438\u9876\u2014\u2014\u5217\u8868\u518D\u957F\uFF0C\u64CD\u4F5C\u6309\u94AE\u4E5F\u4E00\u76F4\u5728\u624B\u8FB9\u3002 */
|
|
@@ -227,6 +394,10 @@ var CSS = `
|
|
|
227
394
|
.archv-date{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none}
|
|
228
395
|
.dsm-branch-chip{display:inline-flex;align-items:center;flex:none;min-height:22px;padding:0 9px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary) 45%,transparent);border-radius:var(--dsm-radius-tag);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent);color:var(--dsw-alias-state-success-primary);font-size:11px;font-weight:500;line-height:1;white-space:nowrap}
|
|
229
396
|
.dsm-empty-chip{display:inline-flex;align-items:center;flex:none;min-height:22px;padding:0 9px;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-tag);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:500;line-height:1;white-space:nowrap}
|
|
397
|
+
/* 3.7.0 T4 \u6807\u7B7E chip \u7CFB\uFF1A\u5361\u7247\u6807\u9898\u884C\u5185\u3001\u5206\u652F/\u7A7A\u767D chip \u4E4B\u540E\u3002\u8B66\u793A\u8272\u7CFB\u533A\u522B\u4E8E
|
|
398
|
+
\u5206\u652F\uFF08\u7EFF\uFF09/\u7A7A\u767D\uFF08\u7070\uFF09\uFF0C\u540D\u5B57\u8D85\u957F\u7701\u7565\u53F7\uFF1B+N \u8BA1\u6570 chip \u4E2D\u6027\u8272\u3002 */
|
|
399
|
+
.dsm-tagchip{display:inline-flex;align-items:center;flex:none;max-width:9em;min-height:22px;padding:0 8px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#EAB308) 45%,transparent);border-radius:var(--dsm-radius-tag);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#EAB308) 10%,transparent);color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:500;line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
400
|
+
.dsm-tagchip-more{max-width:none;color:var(--dsw-alias-label-tertiary);border-color:var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle)}
|
|
230
401
|
.archv-id{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;color:var(--dsw-alias-label-tertiary);flex:none;margin-left:auto;white-space:nowrap}
|
|
231
402
|
.archv-dot{color:var(--dsw-alias-border-l3);flex:none}
|
|
232
403
|
.archv-check{width:15px;height:15px;accent-color:var(--dsw-alias-state-business-primary);flex:none;cursor:pointer}
|
|
@@ -258,7 +429,7 @@ var CSS = `
|
|
|
258
429
|
/* \u5931\u8D25\u63D0\u793A\u7528\u8B66\u793A\u8272 + \u52A0\u7C97\uFF0C\u5E76\u505C\u7559\u66F4\u4E45\uFF08\u9700\u8981\u7528\u6237\u8BFB\u5B8C\u53BB\u505A\u4E0B\u4E00\u6B65\u64CD\u4F5C\uFF09\u3002 */
|
|
259
430
|
.archv-status-err{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);font-weight:500}
|
|
260
431
|
@media (prefers-reduced-motion:reduce){.archv-skel-card::after{animation:none}.archv-card,.archv-btn,.archv-star{transition:none}.archv-star:hover,.archv-star:active{transform:none}.archv-status,.archv-spin{animation:none}}
|
|
261
|
-
@media (max-width:640px){.archv-card{flex-direction:column;align-items:stretch;gap:10px}.archv-actions{justify-content:flex-end}.sess-tools,.sess-tools-4{grid-template-columns:1fr}.sess-fbtn,.archv-btn{min-height:40px}.archv-star{width:30px;height:30px}.archv-star svg{width:22px;height:22px}.dsm-kids{margin-left:10px}.archv-titlerow{flex-wrap:wrap}.dsm-kid-row{flex-wrap:wrap}.dsm-kid-acts{margin-left:0}}
|
|
432
|
+
@media (max-width:640px){.archv-card{flex-direction:column;align-items:stretch;gap:10px}.archv-actions{justify-content:flex-end}.sess-tools,.sess-tools-4,.sess-tools-5{grid-template-columns:1fr}.sess-fbtn,.archv-btn{min-height:40px}.archv-star{width:30px;height:30px}.archv-star svg{width:22px;height:22px}.dsm-kids{margin-left:10px}.archv-titlerow{flex-wrap:wrap}.dsm-kid-row{flex-wrap:wrap}.dsm-kid-acts{margin-left:0}}
|
|
262
433
|
.mv-sheet{width:100%;box-sizing:border-box;display:flex;flex-direction:column;gap:12px;margin-top:12px;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-sheet);background:var(--dsw-alias-fill-subtle)}
|
|
263
434
|
.mv-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
|
|
264
435
|
.mv-sheet-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);margin:0}
|
|
@@ -307,6 +478,25 @@ var CSS = `
|
|
|
307
478
|
.dlg-title{font-size:15px;font-weight:650;color:var(--dsw-alias-label-primary);margin:0}
|
|
308
479
|
.dlg-text{font-size:13px;line-height:1.6;color:var(--dsw-alias-label-secondary);margin:0;word-break:break-all}
|
|
309
480
|
.dlg-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:2px}
|
|
481
|
+
/* ---- T4 \u6807\u7B7E\u7F16\u8F91/\u7BA1\u7406 sheet \u4E0E\u7B5B\u9009\u4FDD\u5B58\u63A7\u4EF6\uFF08\u5168\u90E8\u8D70 --dsw token\uFF09 ---- */
|
|
482
|
+
.dsm-taglist{display:flex;flex-direction:column;gap:2px;max-height:240px;overflow:auto}
|
|
483
|
+
.dsm-tagcheck{display:flex;align-items:center;gap:8px;min-width:0;padding:5px 2px;font-size:12px;color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:7px}
|
|
484
|
+
.dsm-tagcheck:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
485
|
+
.dsm-tagcheck input{width:15px;height:15px;accent-color:var(--dsw-alias-state-business-primary);cursor:pointer;flex:none}
|
|
486
|
+
.dsm-tagcheck-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
487
|
+
.dsm-tagrow{display:flex;align-items:center;gap:8px;min-width:0;padding:6px 0;border-bottom:1px solid var(--dsw-alias-border-l2)}
|
|
488
|
+
.dsm-tagrow:last-child{border-bottom:none}
|
|
489
|
+
.dsm-tag-name{flex:0 1 auto;min-width:0;font-size:12.5px;color:var(--dsw-alias-label-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
490
|
+
.dsm-tag-input{box-sizing:border-box;flex:1 1 auto;min-width:0;min-height:28px;padding:0 8px;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-ctl);background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);font-size:12px;font-family:inherit}
|
|
491
|
+
.dsm-tag-input:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}
|
|
492
|
+
.dsm-tag-acts{display:flex;align-items:center;gap:6px;flex:none;margin-left:auto}
|
|
493
|
+
.dsm-tag-acts .archv-btn{min-height:26px;padding:0 9px;font-size:11px}
|
|
494
|
+
.dsm-tag-acts select{appearance:none;min-height:26px;padding:0 6px;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-ctl);background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-secondary);font-size:11px;font-family:inherit;max-width:10em}
|
|
495
|
+
.dsm-fbar{display:flex;align-items:center;gap:6px;flex:none;margin-left:auto;flex-wrap:wrap}
|
|
496
|
+
.dsm-fbar .archv-btn{min-height:24px;padding:0 8px;font-size:11px}
|
|
497
|
+
.dsm-fbar select{appearance:none;min-height:24px;padding:0 6px;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-ctl);background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-secondary);font-size:11px;font-family:inherit;max-width:12em}
|
|
498
|
+
.dsm-fbar input{box-sizing:border-box;min-width:9em;min-height:24px;padding:0 8px;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsm-radius-ctl);background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);font-size:11px;font-family:inherit}
|
|
499
|
+
@media (max-width:640px){.dsm-fbar{margin-left:0;width:100%;justify-content:flex-end}.dsm-tag-acts{margin-left:auto;flex-wrap:wrap;justify-content:flex-end}}
|
|
310
500
|
`;
|
|
311
501
|
function fmtDate(iso) {
|
|
312
502
|
if (!iso) return null;
|
|
@@ -463,6 +653,16 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
463
653
|
const [toast, setToast] = (0, import_react.useState)(null);
|
|
464
654
|
const [picking, setPicking] = (0, import_react.useState)(false);
|
|
465
655
|
const [trash, setTrash] = (0, import_react.useState)([]);
|
|
656
|
+
const [pendingQueue, setPendingQueue] = (0, import_react.useState)([]);
|
|
657
|
+
const cancelQueuedMove = async (sid) => {
|
|
658
|
+
try {
|
|
659
|
+
await postJSON("/archived-sessions/pending-moves/cancel", { sessionIds: [sid] });
|
|
660
|
+
showToast("\u5DF2\u53D6\u6D88\u6392\u961F\uFF0C\u4F1A\u8BDD\u7559\u5728\u539F\u5DE5\u4F5C\u533A", "ok");
|
|
661
|
+
setPendingQueue((q) => q.filter((x) => String(x.sessionId) !== String(sid)));
|
|
662
|
+
} catch (e) {
|
|
663
|
+
showToast("\u53D6\u6D88\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
664
|
+
}
|
|
665
|
+
};
|
|
466
666
|
const [trashBusy, setTrashBusy] = (0, import_react.useState)(null);
|
|
467
667
|
const [trashSettings, setTrashSettings] = (0, import_react.useState)({ retentionDays: 0 });
|
|
468
668
|
const [trashCheck, setTrashCheck] = (0, import_react.useState)(null);
|
|
@@ -488,7 +688,297 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
488
688
|
const dialogRef = (0, import_react.useRef)(null);
|
|
489
689
|
const [lineage, setLineage] = (0, import_react.useState)({});
|
|
490
690
|
const [openKids, setOpenKids] = (0, import_react.useState)({});
|
|
691
|
+
const [openBranches, setOpenBranches] = (0, import_react.useState)(() => {
|
|
692
|
+
try {
|
|
693
|
+
const v = JSON.parse(localStorage.getItem("dsm-branch-open-v1") || "[]");
|
|
694
|
+
const o = {};
|
|
695
|
+
for (const k of Array.isArray(v) ? v : []) if (typeof k === "string") o[k] = true;
|
|
696
|
+
return o;
|
|
697
|
+
} catch (e) {
|
|
698
|
+
return {};
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
const toggleBranch = (rootId) => setOpenBranches((prev) => {
|
|
702
|
+
const next = Object.assign({}, prev);
|
|
703
|
+
if (next[rootId]) delete next[rootId];
|
|
704
|
+
else next[rootId] = true;
|
|
705
|
+
try {
|
|
706
|
+
localStorage.setItem("dsm-branch-open-v1", JSON.stringify(Object.keys(next)));
|
|
707
|
+
} catch (e) {
|
|
708
|
+
}
|
|
709
|
+
return next;
|
|
710
|
+
});
|
|
491
711
|
const [groupByLineage, setGroupByLineage] = (0, import_react.useState)(() => initialPrefs.groupByLineage !== false);
|
|
712
|
+
const [tagDefs, setTagDefs] = (0, import_react.useState)([]);
|
|
713
|
+
const [assignments, setAssignments] = (0, import_react.useState)({});
|
|
714
|
+
const [tagsState, setTagsState] = (0, import_react.useState)("loading");
|
|
715
|
+
const tagsReady = tagsState === "ready";
|
|
716
|
+
const [tagFilter, setTagFilter] = (0, import_react.useState)("");
|
|
717
|
+
const [savedFilters, setSavedFilters] = (0, import_react.useState)([]);
|
|
718
|
+
const [openTags, setOpenTags] = (0, import_react.useState)(null);
|
|
719
|
+
const [openTagMgr, setOpenTagMgr] = (0, import_react.useState)(false);
|
|
720
|
+
const [tagBusy, setTagBusy] = (0, import_react.useState)(null);
|
|
721
|
+
const [mgrBusy, setMgrBusy] = (0, import_react.useState)(false);
|
|
722
|
+
const [cardTagName, setCardTagName] = (0, import_react.useState)("");
|
|
723
|
+
const [mgrTagName, setMgrTagName] = (0, import_react.useState)("");
|
|
724
|
+
const [renamingTagId, setRenamingTagId] = (0, import_react.useState)(null);
|
|
725
|
+
const [renameTagValue, setRenameTagValue] = (0, import_react.useState)("");
|
|
726
|
+
const [mergeTarget, setMergeTarget] = (0, import_react.useState)({});
|
|
727
|
+
const [saveFilterOpen, setSaveFilterOpen] = (0, import_react.useState)(false);
|
|
728
|
+
const [saveFilterName, setSaveFilterName] = (0, import_react.useState)("");
|
|
729
|
+
const [appliedSavedId, setAppliedSavedId] = (0, import_react.useState)("");
|
|
730
|
+
const tagFilterRef = (0, import_react.useRef)("");
|
|
731
|
+
tagFilterRef.current = tagFilter;
|
|
732
|
+
const tagMap = (0, import_react.useMemo)(() => new Map(tagDefs.map((t) => [String(t.id), String(t.name)])), [tagDefs]);
|
|
733
|
+
const tagUsage = (0, import_react.useMemo)(() => {
|
|
734
|
+
const m = {};
|
|
735
|
+
for (const ids of Object.values(assignments)) for (const id of Array.isArray(ids) ? ids : []) m[String(id)] = (m[String(id)] || 0) + 1;
|
|
736
|
+
return m;
|
|
737
|
+
}, [assignments]);
|
|
738
|
+
const tagsBlockedTitle = tagsState === "failed" ? "\u6807\u7B7E\u6570\u636E\u672A\u80FD\u52A0\u8F7D\uFF0C\u6682\u65F6\u65E0\u6CD5\u4F7F\u7528\u6807\u7B7E\u529F\u80FD\uFF08\u91CD\u65B0\u6253\u5F00\u8BBE\u7F6E\u9762\u677F\u53EF\u91CD\u8BD5\uFF09" : "\u6807\u7B7E\u6570\u636E\u52A0\u8F7D\u4E2D\uFF0C\u7A0D\u5019\u5373\u53EF\u4F7F\u7528";
|
|
739
|
+
const loadTags = () => postJSON("/archived-sessions/tags/list", {}).then((r) => {
|
|
740
|
+
const defs = r && Array.isArray(r.tags) ? r.tags : [];
|
|
741
|
+
setTagDefs(defs);
|
|
742
|
+
setAssignments(r && r.assignments && typeof r.assignments === "object" && !Array.isArray(r.assignments) ? r.assignments : {});
|
|
743
|
+
setTagsState("ready");
|
|
744
|
+
const cur = tagFilterRef.current;
|
|
745
|
+
if (cur && !defs.some((t) => String(t.id) === cur)) setTagFilter("");
|
|
746
|
+
}).catch(() => {
|
|
747
|
+
setTagDefs([]);
|
|
748
|
+
setAssignments({});
|
|
749
|
+
setTagsState("failed");
|
|
750
|
+
if (tagFilterRef.current) setTagFilter("");
|
|
751
|
+
});
|
|
752
|
+
const loadSavedFilters = () => postJSON("/archived-sessions/filters/list", {}).then((r) => setSavedFilters(r && Array.isArray(r.items) ? r.items : [])).catch(() => setSavedFilters([]));
|
|
753
|
+
const setSessionTags = async (sid, nextIds) => {
|
|
754
|
+
const key = String(sid);
|
|
755
|
+
const prev = Array.isArray(assignments[key]) ? assignments[key].slice() : [];
|
|
756
|
+
if (prev.length === nextIds.length && prev.every((t, i) => String(t) === String(nextIds[i]))) return;
|
|
757
|
+
const writeLocal = (ids) => {
|
|
758
|
+
setAssignments((a) => {
|
|
759
|
+
const n = Object.assign({}, a);
|
|
760
|
+
if (ids.length) n[key] = ids;
|
|
761
|
+
else delete n[key];
|
|
762
|
+
return n;
|
|
763
|
+
});
|
|
764
|
+
setSessions((s) => s && s.map((x) => String(x.sessionId) === key ? Object.assign({}, x, { tags: ids }) : x));
|
|
765
|
+
};
|
|
766
|
+
writeLocal(nextIds);
|
|
767
|
+
setTagBusy(key);
|
|
768
|
+
try {
|
|
769
|
+
const r = await postJSON("/archived-sessions/tags/set", { sessionId: sid, tagIds: nextIds });
|
|
770
|
+
const row = r && r.assignments && Array.isArray(r.assignments[key]) ? r.assignments[key].map(String) : nextIds.map(String);
|
|
771
|
+
writeLocal(row);
|
|
772
|
+
} catch (e) {
|
|
773
|
+
writeLocal(prev);
|
|
774
|
+
showToast("\u6807\u7B7E\u8BBE\u7F6E\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
775
|
+
} finally {
|
|
776
|
+
setTagBusy(null);
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
const toggleTagFor = (sid, tagId) => {
|
|
780
|
+
if (tagBusy !== null) return;
|
|
781
|
+
const key = String(sid);
|
|
782
|
+
const cur = Array.isArray(assignments[key]) ? assignments[key] : [];
|
|
783
|
+
const has = cur.some((t) => String(t) === String(tagId));
|
|
784
|
+
const next = has ? cur.filter((t) => String(t) !== String(tagId)) : cur.concat(String(tagId));
|
|
785
|
+
setSessionTags(sid, next);
|
|
786
|
+
};
|
|
787
|
+
const createTagAndAttach = async (sid) => {
|
|
788
|
+
const name = cardTagName.trim();
|
|
789
|
+
if (!name || tagBusy !== null) return;
|
|
790
|
+
setTagBusy(String(sid));
|
|
791
|
+
let fresh = null;
|
|
792
|
+
try {
|
|
793
|
+
const r = await postJSON("/archived-sessions/tags/create", { name });
|
|
794
|
+
if (r && r.tag && r.tag.id != null) fresh = r.tag;
|
|
795
|
+
else throw new Error("\u670D\u52A1\u7AEF\u672A\u8FD4\u56DE\u65B0\u6807\u7B7E");
|
|
796
|
+
} catch (e) {
|
|
797
|
+
showToast("\u65B0\u5EFA\u6807\u7B7E\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
798
|
+
}
|
|
799
|
+
if (!fresh) {
|
|
800
|
+
setTagBusy(null);
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
setTagDefs((d) => d.some((t) => String(t.id) === String(fresh.id)) ? d : d.concat(fresh));
|
|
804
|
+
const cur = Array.isArray(assignments[String(sid)]) ? assignments[String(sid)].slice() : [];
|
|
805
|
+
setCardTagName("");
|
|
806
|
+
await setSessionTags(sid, cur.concat(String(fresh.id)));
|
|
807
|
+
};
|
|
808
|
+
const createTag = async () => {
|
|
809
|
+
const name = mgrTagName.trim();
|
|
810
|
+
if (!name || mgrBusy) return;
|
|
811
|
+
setMgrBusy(true);
|
|
812
|
+
try {
|
|
813
|
+
const r = await postJSON("/archived-sessions/tags/create", { name });
|
|
814
|
+
if (r && r.tag && r.tag.id != null) {
|
|
815
|
+
const fresh = r.tag;
|
|
816
|
+
setTagDefs((d) => d.some((t) => String(t.id) === String(fresh.id)) ? d : d.concat(fresh));
|
|
817
|
+
setMgrTagName("");
|
|
818
|
+
}
|
|
819
|
+
} catch (e) {
|
|
820
|
+
showToast("\u65B0\u5EFA\u6807\u7B7E\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
821
|
+
} finally {
|
|
822
|
+
setMgrBusy(false);
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
const commitTagRename = async (tag) => {
|
|
826
|
+
const name = renameTagValue.trim();
|
|
827
|
+
if (!name || mgrBusy) {
|
|
828
|
+
setRenamingTagId(null);
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
if (name === tag.name) {
|
|
832
|
+
setRenamingTagId(null);
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
setMgrBusy(true);
|
|
836
|
+
try {
|
|
837
|
+
await postJSON("/archived-sessions/tags/rename", { id: tag.id, name });
|
|
838
|
+
setTagDefs((d) => d.map((t) => String(t.id) === String(tag.id) ? Object.assign({}, t, { name }) : t));
|
|
839
|
+
setRenamingTagId(null);
|
|
840
|
+
} catch (e) {
|
|
841
|
+
showToast("\u91CD\u547D\u540D\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
842
|
+
} finally {
|
|
843
|
+
setMgrBusy(false);
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
const deleteTag = async (tag) => {
|
|
847
|
+
if (mgrBusy) return;
|
|
848
|
+
if (!window.confirm(tagDeleteConfirm(tag.name))) return;
|
|
849
|
+
setMgrBusy(true);
|
|
850
|
+
try {
|
|
851
|
+
await postJSON("/archived-sessions/tags/delete", { id: tag.id });
|
|
852
|
+
const gone = String(tag.id);
|
|
853
|
+
setTagDefs((d) => d.filter((t) => String(t.id) !== gone));
|
|
854
|
+
setAssignments((a) => {
|
|
855
|
+
const n = {};
|
|
856
|
+
for (const [sid, ids] of Object.entries(a)) {
|
|
857
|
+
const kept = (Array.isArray(ids) ? ids : []).filter((id) => String(id) !== gone);
|
|
858
|
+
if (kept.length) n[sid] = kept;
|
|
859
|
+
}
|
|
860
|
+
return n;
|
|
861
|
+
});
|
|
862
|
+
setSessions((s) => s && s.map((x) => {
|
|
863
|
+
const curT = Array.isArray(x.tags) ? x.tags : [];
|
|
864
|
+
if (!curT.some((id) => String(id) === gone)) return x;
|
|
865
|
+
return Object.assign({}, x, { tags: curT.filter((id) => String(id) !== gone) });
|
|
866
|
+
}));
|
|
867
|
+
if (tagFilterRef.current === gone) setTagFilter("");
|
|
868
|
+
setMergeTarget((m) => {
|
|
869
|
+
const n = Object.assign({}, m);
|
|
870
|
+
delete n[gone];
|
|
871
|
+
return n;
|
|
872
|
+
});
|
|
873
|
+
} catch (e) {
|
|
874
|
+
showToast("\u5220\u9664\u6807\u7B7E\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
875
|
+
} finally {
|
|
876
|
+
setMgrBusy(false);
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
const mergeTag = async (from) => {
|
|
880
|
+
const toId = mergeTarget[String(from.id)];
|
|
881
|
+
if (!toId || mgrBusy) return;
|
|
882
|
+
setMgrBusy(true);
|
|
883
|
+
try {
|
|
884
|
+
await postJSON("/archived-sessions/tags/merge", { fromId: from.id, toId });
|
|
885
|
+
const gone = String(from.id);
|
|
886
|
+
setTagDefs((d) => d.filter((t) => String(t.id) !== gone));
|
|
887
|
+
setAssignments((a) => {
|
|
888
|
+
const n = {};
|
|
889
|
+
for (const [sid, ids] of Object.entries(a)) {
|
|
890
|
+
const kept = [];
|
|
891
|
+
const seen = /* @__PURE__ */ new Set();
|
|
892
|
+
for (const id of Array.isArray(ids) ? ids : []) {
|
|
893
|
+
const v = String(id) === gone ? String(toId) : String(id);
|
|
894
|
+
if (seen.has(v)) continue;
|
|
895
|
+
seen.add(v);
|
|
896
|
+
kept.push(v);
|
|
897
|
+
}
|
|
898
|
+
if (kept.length) n[sid] = kept;
|
|
899
|
+
}
|
|
900
|
+
return n;
|
|
901
|
+
});
|
|
902
|
+
if (tagFilterRef.current === gone) setTagFilter(String(toId));
|
|
903
|
+
setMergeTarget((m) => {
|
|
904
|
+
const n = Object.assign({}, m);
|
|
905
|
+
delete n[gone];
|
|
906
|
+
return n;
|
|
907
|
+
});
|
|
908
|
+
setSessions((s) => s && s.map((x) => {
|
|
909
|
+
const curT = Array.isArray(x.tags) ? x.tags : [];
|
|
910
|
+
if (!curT.some((id) => String(id) === gone)) return x;
|
|
911
|
+
const nextT = [];
|
|
912
|
+
const seenT = /* @__PURE__ */ new Set();
|
|
913
|
+
for (const id of curT) {
|
|
914
|
+
const v = String(id) === gone ? String(toId) : String(id);
|
|
915
|
+
if (seenT.has(v)) continue;
|
|
916
|
+
seenT.add(v);
|
|
917
|
+
nextT.push(v);
|
|
918
|
+
}
|
|
919
|
+
return Object.assign({}, x, { tags: nextT });
|
|
920
|
+
}));
|
|
921
|
+
showToast(`\u5DF2\u5E76\u5165\u300C${tagMap.get(String(toId)) || "\u76EE\u6807\u6807\u7B7E"}\u300D`);
|
|
922
|
+
} catch (e) {
|
|
923
|
+
showToast("\u5408\u5E76\u6807\u7B7E\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
924
|
+
} finally {
|
|
925
|
+
setMgrBusy(false);
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
const saveCurrentFilter = async () => {
|
|
929
|
+
const name = saveFilterName.trim();
|
|
930
|
+
if (!name || mgrBusy) return;
|
|
931
|
+
setMgrBusy(true);
|
|
932
|
+
try {
|
|
933
|
+
const r = await postJSON("/archived-sessions/filters/save", {
|
|
934
|
+
name,
|
|
935
|
+
filters: filterSnapshotOf({ filter, workspaceFilter, sortBy, tagFilter })
|
|
936
|
+
});
|
|
937
|
+
if (r && r.item) setSavedFilters((l) => l.some((x) => String(x.id) === String(r.item.id)) ? l : l.concat(r.item));
|
|
938
|
+
setSaveFilterOpen(false);
|
|
939
|
+
setSaveFilterName("");
|
|
940
|
+
showToast(`\u5DF2\u4FDD\u5B58\u7B5B\u9009\u300C${r && r.item && r.item.name || name}\u300D`);
|
|
941
|
+
} catch (e) {
|
|
942
|
+
showToast("\u4FDD\u5B58\u7B5B\u9009\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
943
|
+
} finally {
|
|
944
|
+
setMgrBusy(false);
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
const applySavedFilter = (id) => {
|
|
948
|
+
const key = String(id);
|
|
949
|
+
setAppliedSavedId(key);
|
|
950
|
+
if (!key) return;
|
|
951
|
+
const item = savedFilters.find((x) => String(x.id) === key);
|
|
952
|
+
if (!item) return;
|
|
953
|
+
const shape = filterShapeFromSaved(item);
|
|
954
|
+
const tagUnavailable = !!shape.tag && (!tagsReady || !tagMap.has(shape.tag));
|
|
955
|
+
const degraded = shape.degraded.slice();
|
|
956
|
+
if (tagUnavailable) degraded.push("tag");
|
|
957
|
+
setFilter(shape.view);
|
|
958
|
+
clearSel();
|
|
959
|
+
setConfirmBatch(false);
|
|
960
|
+
if (shape.view === "starred" || shape.view === "empty" || shape.view === "trash") setMoreOpen(true);
|
|
961
|
+
setWorkspaceFilter(shape.workspace);
|
|
962
|
+
setSortBy(shape.sort);
|
|
963
|
+
setTagFilter(tagUnavailable ? "" : shape.tag);
|
|
964
|
+
if (degraded.length) {
|
|
965
|
+
const labels = { view: "\u89C6\u56FE", workspace: "\u5DE5\u4F5C\u533A", sort: "\u6392\u5E8F", tag: "\u6807\u7B7E" };
|
|
966
|
+
showToast(`\u5DF2\u5E94\u7528\u7B5B\u9009\u300C${item.name}\u300D\uFF0C\u4F46\u5176\u4E2D ${[...new Set(degraded)].map((k) => labels[k] || k).join("\u3001")} \u6761\u4EF6\u5DF2\u5931\u6548\u5E76\u56DE\u843D\u9ED8\u8BA4`, "err");
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
const deleteSavedFilter = async (id) => {
|
|
970
|
+
if (mgrBusy) return;
|
|
971
|
+
setMgrBusy(true);
|
|
972
|
+
try {
|
|
973
|
+
await postJSON("/archived-sessions/filters/delete", { ids: [id] });
|
|
974
|
+
setSavedFilters((l) => l.filter((x) => String(x.id) !== String(id)));
|
|
975
|
+
if (String(appliedSavedId) === String(id)) setAppliedSavedId("");
|
|
976
|
+
} catch (e) {
|
|
977
|
+
showToast("\u5220\u9664\u5DF2\u5B58\u7B5B\u9009\u5931\u8D25\uFF1A" + String(e && e.message || e), "err");
|
|
978
|
+
} finally {
|
|
979
|
+
setMgrBusy(false);
|
|
980
|
+
}
|
|
981
|
+
};
|
|
492
982
|
const loadLineage = () => postJSON("/archived-sessions/sidebar-state", {}).then((r) => setLineage(r && r.lineage || {})).catch(() => {
|
|
493
983
|
});
|
|
494
984
|
const showToast = (msg, kind) => {
|
|
@@ -515,6 +1005,10 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
515
1005
|
loadLineage();
|
|
516
1006
|
if (!targetWs && works.items && works.items.length) setTargetWs(works.items[0].workspaceId);
|
|
517
1007
|
loadTrash();
|
|
1008
|
+
loadTags();
|
|
1009
|
+
loadSavedFilters();
|
|
1010
|
+
postJSON("/archived-sessions/pending-moves", {}).then((q) => setPendingQueue(q && q.items || [])).catch(() => {
|
|
1011
|
+
});
|
|
518
1012
|
if (storageOpen) loadStorage();
|
|
519
1013
|
else storageDirty.current = true;
|
|
520
1014
|
}).catch((e) => setError(String(e && e.message || e)));
|
|
@@ -530,6 +1024,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
530
1024
|
(0, import_react.useEffect)(() => dsmOnWarmDone(() => {
|
|
531
1025
|
if (refreshRef.current) refreshRef.current();
|
|
532
1026
|
}), []);
|
|
1027
|
+
(0, import_react.useEffect)(() => dsmOnNotice((text, kind) => showToast(text, kind)), []);
|
|
533
1028
|
(0, import_react.useEffect)(() => {
|
|
534
1029
|
try {
|
|
535
1030
|
localStorage.setItem(PANEL_PREFS_KEY, JSON.stringify({ filter, workspaceFilter, sortBy, groupByLineage }));
|
|
@@ -631,8 +1126,9 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
631
1126
|
const list = (0, import_react.useMemo)(() => {
|
|
632
1127
|
if (filter === "trash") return [];
|
|
633
1128
|
const base = filter === "archived" ? archivedList : filter === "active" ? activeList : filter === "starred" ? starredList : filter === "empty" ? emptyList : sessions || [];
|
|
1129
|
+
const tagPassed = applyTagFilter(base, tagsReady ? tagFilter : "");
|
|
634
1130
|
const needle = query.trim().toLocaleLowerCase();
|
|
635
|
-
const filtered =
|
|
1131
|
+
const filtered = tagPassed.filter((item) => {
|
|
636
1132
|
if (workspaceFilter !== "all" && (item.workspacePath || "") !== workspaceFilter) return false;
|
|
637
1133
|
if (!needle) return true;
|
|
638
1134
|
return [effectiveTitleOf(item, dsmAuthoritativeTitles), item.sessionId, item.workspaceTitle, item.workspacePath].some((value) => String(value || "").toLocaleLowerCase().includes(needle));
|
|
@@ -642,18 +1138,28 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
642
1138
|
if (sortBy === "title") return effectiveTitleOf(a, dsmAuthoritativeTitles).localeCompare(effectiveTitleOf(b, dsmAuthoritativeTitles), "zh-CN");
|
|
643
1139
|
return Number(b.createdAt || 0) - Number(a.createdAt || 0);
|
|
644
1140
|
});
|
|
645
|
-
}, [sessions, filter, query, workspaceFilter, sortBy, emptyList, starredList]);
|
|
1141
|
+
}, [sessions, filter, query, workspaceFilter, sortBy, emptyList, starredList, tagFilter, tagsReady]);
|
|
646
1142
|
const selIds = Object.keys(selected).filter((k) => selected[k]);
|
|
647
1143
|
const showSessionList = filter !== "trash";
|
|
648
|
-
const { topList, kidsOf, foldedCount } = (0, import_react.useMemo)(() => {
|
|
649
|
-
if (!groupByLineage) return { topList: list, kidsOf: /* @__PURE__ */ new Map(), foldedCount: 0 };
|
|
650
|
-
|
|
1144
|
+
const { topList, kidsOf, foldedCount, branchGroupsOf, branchFolded, branchGroupCount } = (0, import_react.useMemo)(() => {
|
|
1145
|
+
if (!groupByLineage) return { topList: list, kidsOf: /* @__PURE__ */ new Map(), foldedCount: 0, branchGroupsOf: /* @__PURE__ */ new Map(), branchFolded: 0, branchGroupCount: 0 };
|
|
1146
|
+
const kids = foldSubagents(list, lineage);
|
|
1147
|
+
const br = foldBranches(kids.topList, lineage);
|
|
1148
|
+
return { topList: br.topList, kidsOf: kids.kidsOf, foldedCount: kids.foldedCount, branchGroupsOf: br.branchGroupsOf, branchFolded: br.foldedCount, branchGroupCount: br.groupCount };
|
|
651
1149
|
}, [list, lineage, groupByLineage]);
|
|
1150
|
+
const matchIds = (0, import_react.useMemo)(() => {
|
|
1151
|
+
const needle = query.trim().toLocaleLowerCase();
|
|
1152
|
+
if (!needle) return null;
|
|
1153
|
+
return new Set((sessions || []).filter((item) => [effectiveTitleOf(item, dsmAuthoritativeTitles), item.sessionId, item.workspaceTitle, item.workspacePath].some((v) => String(v || "").toLocaleLowerCase().includes(needle))).map((i) => String(i.sessionId)));
|
|
1154
|
+
}, [sessions, query]);
|
|
1155
|
+
const kidsHit = (parentId) => !!(matchIds && (kidsOf.get(String(parentId)) || []).some((k) => matchIds.has(String(k.sessionId))));
|
|
1156
|
+
const branchHit = (rootId) => !!(matchIds && (branchGroupsOf.get(String(rootId)) || []).some((m) => matchIds.has(String(m.sessionId))));
|
|
1157
|
+
const syntheticCount = groupByLineage ? topList.reduce((n, it) => n + (it && it.syntheticRoot ? 1 : 0), 0) : 0;
|
|
652
1158
|
const kidsBadge = (sessionId) => {
|
|
653
1159
|
if (!groupByLineage) return null;
|
|
654
1160
|
const kids = kidsOf.get(String(sessionId)) || [];
|
|
655
1161
|
if (!kids.length) return null;
|
|
656
|
-
const open = !!openKids[sessionId];
|
|
1162
|
+
const open = !!openKids[sessionId] || kidsHit(sessionId);
|
|
657
1163
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
658
1164
|
"button",
|
|
659
1165
|
{
|
|
@@ -684,9 +1190,28 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
684
1190
|
if (!li || !li.empty) return null;
|
|
685
1191
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-empty-chip", title: "\u65E0\u5185\u5BB9\u7684\u7A7A\u767D\u4F1A\u8BDD", children: "\u7A7A\u767D" });
|
|
686
1192
|
};
|
|
1193
|
+
const tagChips = (sessionId) => {
|
|
1194
|
+
if (!tagsReady) return null;
|
|
1195
|
+
const ids = Array.isArray(assignments[String(sessionId)]) ? assignments[String(sessionId)] : [];
|
|
1196
|
+
const names = [];
|
|
1197
|
+
for (const id of ids) {
|
|
1198
|
+
const n = tagMap.get(String(id));
|
|
1199
|
+
if (n) names.push(n);
|
|
1200
|
+
}
|
|
1201
|
+
if (!names.length) return null;
|
|
1202
|
+
const shown = names.slice(0, 3);
|
|
1203
|
+
const rest = names.slice(3);
|
|
1204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1205
|
+
shown.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-tagchip", title: "\u6807\u7B7E\uFF1A" + n, children: n }, i)),
|
|
1206
|
+
rest.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-tagchip dsm-tagchip-more", title: "\u53E6\u6709\u6807\u7B7E\uFF1A" + rest.join("\u3001"), children: [
|
|
1207
|
+
"+",
|
|
1208
|
+
rest.length
|
|
1209
|
+
] })
|
|
1210
|
+
] });
|
|
1211
|
+
};
|
|
687
1212
|
const renderKids = (parentId, depth) => {
|
|
688
1213
|
const kids = kidsOf.get(String(parentId)) || [];
|
|
689
|
-
if (!kids.length || !openKids[parentId]) return null;
|
|
1214
|
+
if (!kids.length || !(openKids[parentId] || kidsHit(parentId))) return null;
|
|
690
1215
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsm-kids", children: kids.map((k) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-kid", children: [
|
|
691
1216
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-kid-row", children: [
|
|
692
1217
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-kid-name", title: k.title || k.sessionId, children: k.title || "(\u65E0\u6807\u9898)" }),
|
|
@@ -708,6 +1233,56 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
708
1233
|
(depth || 0) < 4 && renderKids(k.sessionId, (depth || 0) + 1)
|
|
709
1234
|
] }, k.sessionId)) });
|
|
710
1235
|
};
|
|
1236
|
+
const branchGroupBadge = (sessionId) => {
|
|
1237
|
+
if (!groupByLineage) return null;
|
|
1238
|
+
const members = branchGroupsOf.get(String(sessionId)) || [];
|
|
1239
|
+
if (!members.length) return null;
|
|
1240
|
+
const open = !!openBranches[sessionId] || branchHit(sessionId);
|
|
1241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1242
|
+
"button",
|
|
1243
|
+
{
|
|
1244
|
+
type: "button",
|
|
1245
|
+
className: "dsm-kids-toggle",
|
|
1246
|
+
"aria-expanded": open,
|
|
1247
|
+
title: (open ? "\u6536\u8D77 " : "\u5C55\u5F00 ") + members.length + " \u4E2A\u5206\u652F\u4F1A\u8BDD",
|
|
1248
|
+
onClick: () => toggleBranch(sessionId),
|
|
1249
|
+
children: [
|
|
1250
|
+
open ? "\u25BE" : "\u25B8",
|
|
1251
|
+
" ",
|
|
1252
|
+
members.length,
|
|
1253
|
+
" \u5206\u652F"
|
|
1254
|
+
]
|
|
1255
|
+
}
|
|
1256
|
+
);
|
|
1257
|
+
};
|
|
1258
|
+
const renderBranchGroup = (rootId) => {
|
|
1259
|
+
const members = branchGroupsOf.get(String(rootId)) || [];
|
|
1260
|
+
if (!members.length || !(openBranches[rootId] || branchHit(rootId))) return null;
|
|
1261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsm-kids", "aria-label": "\u5206\u652F\u4F1A\u8BDD", children: members.map((k) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-kid", children: [
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-kid-row", children: [
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-kid-name", title: k.title || k.sessionId, children: k.title || "(\u65E0\u6807\u9898)" }),
|
|
1264
|
+
branchBadge(k.sessionId),
|
|
1265
|
+
emptyBadge(k.sessionId),
|
|
1266
|
+
kidsBadge(k.sessionId),
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-kid-meta", children: [
|
|
1268
|
+
k.archived ? "\u5DF2\u5F52\u6863" : "\u6D3B\u52A8",
|
|
1269
|
+
fmtDate(k.createdAt) ? ` \xB7 ${fmtDate(k.createdAt)}` : ""
|
|
1270
|
+
] }),
|
|
1271
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-kid-acts", children: [
|
|
1272
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, title: "\u5207\u6362\u5230\u8FD9\u4E2A\u5206\u652F\u4F1A\u8BDD\uFF08\u8BBE\u7F6E\u9762\u677F\u6321\u7740\u4F1A\u8BDD\u533A\uFF0C\u5173\u6389\u5373\u53EF\u770B\u5230\uFF09", onClick: async () => {
|
|
1273
|
+
const name = k.title || String(k.sessionId).slice(0, 8) + "\u2026";
|
|
1274
|
+
const li = lineage[String(k.sessionId)];
|
|
1275
|
+
const res = await dsmOpenSessionById(k.sessionId, li && li.parentSession || rootId);
|
|
1276
|
+
const msg = openSubagentToast(res, name, "panel");
|
|
1277
|
+
showToast(msg.text, msg.kind);
|
|
1278
|
+
}, children: "\u6253\u5F00" }),
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, onClick: () => act(k.archived ? "restore" : "archive", k), children: k.archived ? "\u6062\u590D" : "\u5F52\u6863" }),
|
|
1280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: busy !== null, title: "\u79FB\u5165\u56DE\u6536\u7AD9\uFF0C\u53EF\u5728\u56DE\u6536\u7AD9\u6062\u590D", onClick: () => setDelTarget(k), children: "\u5220\u9664" })
|
|
1281
|
+
] })
|
|
1282
|
+
] }),
|
|
1283
|
+
renderKids(k.sessionId, 1)
|
|
1284
|
+
] }, k.sessionId)) });
|
|
1285
|
+
};
|
|
711
1286
|
const toggle = (id) => setSelected((s) => ({ ...s, [id]: !s[id] }));
|
|
712
1287
|
const clearSel = () => setSelected({});
|
|
713
1288
|
const selectAll = () => {
|
|
@@ -981,6 +1556,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
981
1556
|
setOpenMove(null);
|
|
982
1557
|
return;
|
|
983
1558
|
}
|
|
1559
|
+
setOpenTags(null);
|
|
984
1560
|
setTargetWs(workspaces.length ? targetWs || workspaces[0].workspaceId : "");
|
|
985
1561
|
setMoveMode("existing");
|
|
986
1562
|
setNewPath("");
|
|
@@ -1040,21 +1616,36 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1040
1616
|
if (wName) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", title: it.workspacePath || "", children: wName });
|
|
1041
1617
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", children: "\u672A\u5206\u7EC4" });
|
|
1042
1618
|
};
|
|
1619
|
+
const openTagsFor = (it) => {
|
|
1620
|
+
if (!tagsReady) {
|
|
1621
|
+
showToast(tagsState === "failed" ? "\u6807\u7B7E\u6570\u636E\u672A\u80FD\u52A0\u8F7D\uFF0C\u6682\u65F6\u65E0\u6CD5\u7F16\u8F91\u6807\u7B7E\uFF1B\u91CD\u65B0\u6253\u5F00\u8BBE\u7F6E\u9762\u677F\u53EF\u91CD\u8BD5" : "\u6807\u7B7E\u6570\u636E\u8FD8\u5728\u52A0\u8F7D\u4E2D\uFF0C\u7A0D\u5019\u518D\u8BD5", "err");
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
if (openTags === it.sessionId) {
|
|
1625
|
+
setOpenTags(null);
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
setOpenMove(null);
|
|
1629
|
+
setCardTagName("");
|
|
1630
|
+
setOpenTags(it.sessionId);
|
|
1631
|
+
};
|
|
1043
1632
|
const runMenu = (id, it) => {
|
|
1044
1633
|
setOpenMenu(null);
|
|
1045
1634
|
if (id === "restore") act("restore", it);
|
|
1046
1635
|
else if (id === "archive") act("archive", it);
|
|
1047
1636
|
else if (id === "delete") setDelTarget(it);
|
|
1048
1637
|
else if (id === "move") openMoveFor(it);
|
|
1638
|
+
else if (id === "tags") openTagsFor(it);
|
|
1049
1639
|
else if (id === "details") toggleDetails(it);
|
|
1050
1640
|
};
|
|
1051
1641
|
const rowMenu = (it) => {
|
|
1052
1642
|
const items = it.archived ? [
|
|
1053
1643
|
["restore", "\u6062\u590D"],
|
|
1054
1644
|
["move", openMove === it.sessionId ? "\u6536\u8D77\u79FB\u52A8" : "\u79FB\u52A8"],
|
|
1645
|
+
["tags", "\u6807\u7B7E"],
|
|
1055
1646
|
["details", openDetails === it.sessionId ? "\u6536\u8D77\u8BE6\u60C5" : "\u8BE6\u60C5"],
|
|
1056
1647
|
["delete", "\u5220\u9664"]
|
|
1057
|
-
] : [["archive", "\u5F52\u6863"], ["move", "\u79FB\u52A8"], ["details", "\u8BE6\u60C5"], ["delete", "\u5220\u9664"]];
|
|
1648
|
+
] : [["archive", "\u5F52\u6863"], ["move", "\u79FB\u52A8"], ["tags", openTags === it.sessionId ? "\u6536\u8D77\u6807\u7B7E" : "\u6807\u7B7E"], ["details", "\u8BE6\u60C5"], ["delete", "\u5220\u9664"]];
|
|
1058
1649
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: openMenu === it.sessionId ? menuRef : null, className: "more-wrap", children: [
|
|
1059
1650
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1060
1651
|
"button",
|
|
@@ -1072,7 +1663,8 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1072
1663
|
}
|
|
1073
1664
|
),
|
|
1074
1665
|
openMenu === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "more-menu", role: "menu", children: items.map(([id, label]) => {
|
|
1075
|
-
const blocked = id === "move" && !canMove.available;
|
|
1666
|
+
const blocked = id === "move" && !canMove.available || id === "tags" && !tagsReady;
|
|
1667
|
+
const blockedTitle = id === "move" ? canMove.reason : id === "tags" ? tagsBlockedTitle : void 0;
|
|
1076
1668
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1077
1669
|
"button",
|
|
1078
1670
|
{
|
|
@@ -1080,7 +1672,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1080
1672
|
role: "menuitem",
|
|
1081
1673
|
className: "more-item" + (id === "delete" ? " more-item-danger" : ""),
|
|
1082
1674
|
disabled: blocked,
|
|
1083
|
-
title: blocked ?
|
|
1675
|
+
title: blocked ? blockedTitle : void 0,
|
|
1084
1676
|
onClick: () => runMenu(id, it),
|
|
1085
1677
|
children: label
|
|
1086
1678
|
},
|
|
@@ -1174,8 +1766,122 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1174
1766
|
")"
|
|
1175
1767
|
] })
|
|
1176
1768
|
] }),
|
|
1177
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "sess-farrow", "aria-expanded": moreOpen, "aria-label": moreOpen ? "\u6536\u8D77\u66F4\u591A\u7B5B\u9009" : "\u5C55\u5F00\u66F4\u591A\u7B5B\u9009", title: moreOpen ? "\u6536\u8D77\u66F4\u591A\u7B5B\u9009" : "\u5C55\u5F00\u66F4\u591A\u7B5B\u9009\uFF08\u5DF2\u6536\u85CF / \u7A7A\u767D / \u56DE\u6536\u7AD9\uFF09", onClick: () => setMoreOpen(!moreOpen), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 2l4 4-4 4", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
|
|
1769
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "sess-farrow", "aria-expanded": moreOpen, "aria-label": moreOpen ? "\u6536\u8D77\u66F4\u591A\u7B5B\u9009" : "\u5C55\u5F00\u66F4\u591A\u7B5B\u9009", title: moreOpen ? "\u6536\u8D77\u66F4\u591A\u7B5B\u9009" : "\u5C55\u5F00\u66F4\u591A\u7B5B\u9009\uFF08\u5DF2\u6536\u85CF / \u7A7A\u767D / \u56DE\u6536\u7AD9\uFF09", onClick: () => setMoreOpen(!moreOpen), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 2l4 4-4 4", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
1770
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1771
|
+
"button",
|
|
1772
|
+
{
|
|
1773
|
+
type: "button",
|
|
1774
|
+
className: "archv-btn",
|
|
1775
|
+
"aria-expanded": openTagMgr,
|
|
1776
|
+
disabled: !tagsReady && !openTagMgr,
|
|
1777
|
+
title: tagsReady ? "\u65B0\u5EFA / \u91CD\u547D\u540D / \u5408\u5E76 / \u5220\u9664\u6807\u7B7E" : tagsBlockedTitle,
|
|
1778
|
+
onClick: () => {
|
|
1779
|
+
setOpenTagMgr(!openTagMgr);
|
|
1780
|
+
setRenamingTagId(null);
|
|
1781
|
+
},
|
|
1782
|
+
children: [
|
|
1783
|
+
"\u6807\u7B7E\u7BA1\u7406",
|
|
1784
|
+
tagsReady && tagDefs.length ? ` (${tagDefs.length})` : ""
|
|
1785
|
+
]
|
|
1786
|
+
}
|
|
1787
|
+
)
|
|
1178
1788
|
] }) }),
|
|
1789
|
+
openTagMgr && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", "aria-label": "\u6807\u7B7E\u7BA1\u7406", children: [
|
|
1790
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet-head", children: [
|
|
1791
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { className: "mv-sheet-title", children: [
|
|
1792
|
+
"\u6807\u7B7E\u7BA1\u7406 \xB7 ",
|
|
1793
|
+
tagDefs.length
|
|
1794
|
+
] }),
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "mv-sheet-close", "aria-label": "\u5173\u95ED", onClick: () => {
|
|
1796
|
+
setOpenTagMgr(false);
|
|
1797
|
+
setRenamingTagId(null);
|
|
1798
|
+
}, children: "\xD7" })
|
|
1799
|
+
] }),
|
|
1800
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-field", children: [
|
|
1801
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "mv-field-label", htmlFor: "dsm-tag-new", children: "\u65B0\u5EFA\u6807\u7B7E" }),
|
|
1802
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-browse-row", children: [
|
|
1803
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1804
|
+
"input",
|
|
1805
|
+
{
|
|
1806
|
+
id: "dsm-tag-new",
|
|
1807
|
+
type: "text",
|
|
1808
|
+
value: mgrTagName,
|
|
1809
|
+
disabled: mgrBusy,
|
|
1810
|
+
maxLength: 24,
|
|
1811
|
+
placeholder: "\u6807\u7B7E\u540D\uFF08\u4E0D\u80FD\u542B\u659C\u6760\uFF0C\u6700\u957F 24 \u5B57\uFF09",
|
|
1812
|
+
onChange: (e) => setMgrTagName(e.target.value),
|
|
1813
|
+
onKeyDown: (e) => {
|
|
1814
|
+
if (e.key === "Enter") {
|
|
1815
|
+
e.preventDefault();
|
|
1816
|
+
createTag();
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
),
|
|
1821
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: mgrBusy || !mgrTagName.trim(), onClick: createTag, children: "\u65B0\u5EFA" })
|
|
1822
|
+
] })
|
|
1823
|
+
] }),
|
|
1824
|
+
tagDefs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-note", children: "\u8FD8\u6CA1\u6709\u6807\u7B7E\u3002\u5728\u4E0A\u65B9\u8F93\u5165\u540D\u5B57\u5373\u53EF\u521B\u5EFA\uFF1B\u7ED9\u4F1A\u8BDD\u8D34\u6807\u7B7E\u4E5F\u53EF\u4EE5\u5728\u4F1A\u8BDD\u5361\u7247\u7684\u300C\u22EF \u2192 \u6807\u7B7E\u300D\u91CC\u8FDB\u884C\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: tagDefs.map((t) => {
|
|
1825
|
+
const others = tagDefs.filter((o) => String(o.id) !== String(t.id));
|
|
1826
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsm-tagrow", children: renamingTagId === String(t.id) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1827
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1828
|
+
"input",
|
|
1829
|
+
{
|
|
1830
|
+
className: "dsm-tag-input",
|
|
1831
|
+
type: "text",
|
|
1832
|
+
value: renameTagValue,
|
|
1833
|
+
disabled: mgrBusy,
|
|
1834
|
+
maxLength: 24,
|
|
1835
|
+
"aria-label": "\u91CD\u547D\u540D\u6807\u7B7E " + t.name,
|
|
1836
|
+
autoFocus: true,
|
|
1837
|
+
onChange: (e) => setRenameTagValue(e.target.value),
|
|
1838
|
+
onKeyDown: (e) => {
|
|
1839
|
+
if (e.key === "Enter") {
|
|
1840
|
+
e.preventDefault();
|
|
1841
|
+
commitTagRename(t);
|
|
1842
|
+
}
|
|
1843
|
+
if (e.key === "Escape") setRenamingTagId(null);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
),
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-tag-acts", children: [
|
|
1848
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-go", disabled: mgrBusy || !renameTagValue.trim(), onClick: () => commitTagRename(t), children: "\u4FDD\u5B58" }),
|
|
1849
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: mgrBusy, onClick: () => setRenamingTagId(null), children: "\u53D6\u6D88" })
|
|
1850
|
+
] })
|
|
1851
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1852
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-tag-name", title: t.name, children: t.name }),
|
|
1853
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "maint-note", children: [
|
|
1854
|
+
tagUsage[String(t.id)] || 0,
|
|
1855
|
+
" \u4E2A\u4F1A\u8BDD"
|
|
1856
|
+
] }),
|
|
1857
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-tag-acts", children: [
|
|
1858
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: mgrBusy || renamingTagId !== null, title: "\u91CD\u547D\u540D\u8FD9\u4E2A\u6807\u7B7E", onClick: () => {
|
|
1859
|
+
setRenamingTagId(String(t.id));
|
|
1860
|
+
setRenameTagValue(t.name);
|
|
1861
|
+
}, children: "\u91CD\u547D\u540D" }),
|
|
1862
|
+
others.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1863
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1864
|
+
"select",
|
|
1865
|
+
{
|
|
1866
|
+
"aria-label": "\u628A\u6807\u7B7E\u300C" + t.name + "\u300D\u5E76\u5165",
|
|
1867
|
+
value: mergeTarget[String(t.id)] || "",
|
|
1868
|
+
disabled: mgrBusy,
|
|
1869
|
+
title: "\u628A\u8FD9\u4E2A\u6807\u7B7E\u7684\u6240\u6709\u4F1A\u8BDD\u5E76\u5165\u53E6\u4E00\u4E2A\u6807\u7B7E\uFF08\u5E76\u5165\u540E\u672C\u6807\u7B7E\u5220\u9664\uFF09",
|
|
1870
|
+
onChange: (e) => setMergeTarget((m) => Object.assign({}, m, { [String(t.id)]: e.target.value })),
|
|
1871
|
+
children: [
|
|
1872
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5E76\u5165\u2026" }),
|
|
1873
|
+
others.map((o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: String(o.id), children: o.name }, String(o.id)))
|
|
1874
|
+
]
|
|
1875
|
+
}
|
|
1876
|
+
),
|
|
1877
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: mgrBusy || !mergeTarget[String(t.id)], title: mergeTarget[String(t.id)] ? "\u786E\u8BA4\u5E76\u5165\u6240\u9009\u6807\u7B7E" : "\u5148\u5728\u5DE6\u4FA7\u9009\u62E9\u5E76\u5165\u7684\u76EE\u6807\u6807\u7B7E", onClick: () => mergeTag(t), children: "\u786E\u8BA4" })
|
|
1878
|
+
] }),
|
|
1879
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: mgrBusy, title: "\u5220\u9664\u6807\u7B7E\uFF08\u53EA\u5220\u6807\u7B7E\uFF0C\u4E0D\u4F1A\u5220\u9664\u4F1A\u8BDD\uFF09", onClick: () => deleteTag(t), children: "\u5220\u9664" })
|
|
1880
|
+
] })
|
|
1881
|
+
] }) }, String(t.id));
|
|
1882
|
+
}) }),
|
|
1883
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-note", children: "\u6807\u7B7E\u662F\u4F1A\u8BDD\u7684\u81EA\u5B9A\u4E49\u6807\u8BB0\uFF1A\u65B0\u5EFA\u3001\u91CD\u547D\u540D\u3001\u5408\u5E76\u3001\u5220\u9664\u90FD\u53EA\u6539\u6807\u8BB0\u672C\u8EAB\uFF0C\u4E0D\u4F1A\u5220\u9664\u6216\u79FB\u52A8\u4EFB\u4F55\u4F1A\u8BDD\u3002\u5355\u4E2A\u4F1A\u8BDD\u7684\u6807\u7B7E\u6570\u91CF\u4E0E\u6807\u7B7E\u603B\u6570\u90FD\u6709\u670D\u52A1\u7AEF\u4E0A\u9650\uFF0C\u8D85\u9650\u65F6\u4F1A\u63D0\u793A\u5E76\u81EA\u52A8\u56DE\u9000\u672C\u5730\u6539\u52A8\u3002" })
|
|
1884
|
+
] }),
|
|
1179
1885
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "maint-bar", children: [
|
|
1180
1886
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "archv-btn", "aria-expanded": storageOpen, onClick: () => {
|
|
1181
1887
|
const next = !storageOpen;
|
|
@@ -1197,6 +1903,28 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1197
1903
|
" \u4E2A"
|
|
1198
1904
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "maint-note", children: "\u5C1A\u672A\u68C0\u67E5" })
|
|
1199
1905
|
] }),
|
|
1906
|
+
pendingQueue.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", "aria-label": "\u5F85\u79FB\u52A8\u961F\u5217", children: [
|
|
1907
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-sheet-head", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { className: "mv-sheet-title", children: [
|
|
1908
|
+
"\u5F85\u79FB\u52A8\u961F\u5217 \xB7 ",
|
|
1909
|
+
pendingQueue.length
|
|
1910
|
+
] }) }),
|
|
1911
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-note", children: "\u8FD9\u4E9B\u4F1A\u8BDD\u6B63\u88AB DSH \u6253\u5F00\u7740\uFF0C\u5B98\u65B9\u53EA\u5728\u8FDB\u7A0B\u9000\u51FA\u65F6\u91CA\u653E\u5199\u6743\u9650\uFF1B\u91CA\u653E\u540E\u63D2\u4EF6\u4F1A\u81EA\u52A8\u5B8C\u6210\u79FB\u52A8\uFF0C\u4E5F\u53EF\u91CD\u542F DSH \u8BA9\u5B83\u5728\u542F\u52A8\u5934\u51E0\u79D2\u62A2\u5148\u8865\u8DD1\u3002" }),
|
|
1912
|
+
pendingQueue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-kid-row", children: [
|
|
1913
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-kid-name", title: `${q.sessionId} \u2192 ${q.targetPath || ""}`, children: [
|
|
1914
|
+
shortId(q.sessionId),
|
|
1915
|
+
"\u2026 \u2192 ",
|
|
1916
|
+
pathTail(q.targetPath) || "\u76EE\u6807\u5DE5\u4F5C\u533A"
|
|
1917
|
+
] }),
|
|
1918
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-kid-acts", children: [
|
|
1919
|
+
Number.isSafeInteger(q.attempts) && q.attempts > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "maint-note", children: [
|
|
1920
|
+
"\u5DF2\u5931\u8D25 ",
|
|
1921
|
+
q.attempts,
|
|
1922
|
+
" \u6B21"
|
|
1923
|
+
] }) : null,
|
|
1924
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", onClick: () => cancelQueuedMove(q.sessionId), children: "\u53D6\u6D88" })
|
|
1925
|
+
] })
|
|
1926
|
+
] }, String(q.sessionId)))
|
|
1927
|
+
] }),
|
|
1200
1928
|
aaOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", "aria-label": "\u81EA\u52A8\u5F52\u6863\u8BBE\u7F6E", children: [
|
|
1201
1929
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet-head", children: [
|
|
1202
1930
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mv-sheet-title", children: "\u81EA\u52A8\u5F52\u6863" }),
|
|
@@ -1259,7 +1987,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1259
1987
|
] })
|
|
1260
1988
|
] }),
|
|
1261
1989
|
showSessionList && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1262
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-tools sess-tools-
|
|
1990
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-tools sess-tools-5", "aria-label": "\u67E5\u627E\u548C\u6574\u7406\u4F1A\u8BDD", children: [
|
|
1263
1991
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
|
|
1264
1992
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-search", children: "\u641C\u7D22\u4F1A\u8BDD" }),
|
|
1265
1993
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { id: "dsm-search", type: "search", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "\u6807\u9898\u3001\u4F1A\u8BDD ID \u6216\u5DE5\u4F5C\u533A" })
|
|
@@ -1268,9 +1996,31 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1268
1996
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-workspace-filter", children: "\u5DE5\u4F5C\u533A" }),
|
|
1269
1997
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "dsm-workspace-filter", value: workspaceFilter, onChange: (e) => setWorkspaceFilter(e.target.value), children: [
|
|
1270
1998
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "all", children: "\u5168\u90E8\u5DE5\u4F5C\u533A" }),
|
|
1271
|
-
workspaces.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: w.path, children: w.title }, w.workspaceId))
|
|
1999
|
+
workspaces.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: w.path, children: w.title }, w.workspaceId)),
|
|
2000
|
+
workspaceFilter !== "all" && !workspaces.some((w) => w.path === workspaceFilter) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: workspaceFilter, children: [
|
|
2001
|
+
"\u5DF2\u5220\u5DE5\u4F5C\u533A \xB7 ",
|
|
2002
|
+
pathName(workspaceFilter) || "?"
|
|
2003
|
+
] })
|
|
1272
2004
|
] })
|
|
1273
2005
|
] }),
|
|
2006
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
|
|
2007
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-tag-filter", children: "\u6807\u7B7E" }),
|
|
2008
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2009
|
+
"select",
|
|
2010
|
+
{
|
|
2011
|
+
id: "dsm-tag-filter",
|
|
2012
|
+
value: tagFilter,
|
|
2013
|
+
disabled: !tagsReady,
|
|
2014
|
+
title: !tagsReady ? tagsBlockedTitle : tagFilter ? "\u5F53\u524D\u6309\u300C" + (tagMap.get(tagFilter) || "\u6240\u9009\u6807\u7B7E") + "\u300D\u7B5B\u9009\uFF1B\u591A\u9009\u7EC4\u5408\u53EF\u7528\u300C\u4FDD\u5B58\u5F53\u524D\u7B5B\u9009\u300D\u56FA\u5316" : "\u6309\u6807\u7B7E\u7B5B\u9009\uFF08\u5355\u9009\uFF09",
|
|
2015
|
+
onChange: (e) => setTagFilter(e.target.value),
|
|
2016
|
+
children: [
|
|
2017
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5168\u90E8\u6807\u7B7E" }),
|
|
2018
|
+
tagDefs.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: t.id, children: t.name }, t.id)),
|
|
2019
|
+
tagFilter && !tagMap.has(tagFilter) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: tagFilter, children: "\uFF08\u5DF2\u5220\u6807\u7B7E\uFF09" })
|
|
2020
|
+
]
|
|
2021
|
+
}
|
|
2022
|
+
)
|
|
2023
|
+
] }),
|
|
1274
2024
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
|
|
1275
2025
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-sort", children: "\u6392\u5E8F" }),
|
|
1276
2026
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "dsm-sort", value: sortBy, onChange: (e) => setSortBy(e.target.value), children: [
|
|
@@ -1281,18 +2031,89 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1281
2031
|
] }),
|
|
1282
2032
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-field", children: [
|
|
1283
2033
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "dsm-group", children: "\u5206\u7EC4" }),
|
|
1284
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "dsm-group", value: groupByLineage ? "lineage" : "flat", onChange: (e) => setGroupByLineage(e.target.value === "lineage"), title: "\u8840\u7F18\u5206\u7EC4\uFF1A\u5B50\u4EE3\u7406\u6298\u53E0\
|
|
1285
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "lineage", children: "\u8840\u7F18\uFF08\
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "dsm-group", value: groupByLineage ? "lineage" : "flat", onChange: (e) => setGroupByLineage(e.target.value === "lineage"), title: "\u8840\u7F18\u5206\u7EC4\uFF1A\u5B50\u4EE3\u7406\u6298\u53E0\u3001\u5206\u652F\u805A\u62E2\u6210\u7EC4\uFF1B\u5E73\u94FA\uFF1A\u4E0E DSH \u539F\u751F\u4E00\u81F4\uFF0C\u5168\u90E8\u5E76\u5217", children: [
|
|
2035
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "lineage", children: "\u8840\u7F18\uFF08\u6298\u53E0\u5206\u7EC4\uFF09" }),
|
|
1286
2036
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "flat", children: "\u5E73\u94FA\uFF08\u5168\u90E8\u5E76\u5217\uFF09" })
|
|
1287
2037
|
] })
|
|
1288
2038
|
] })
|
|
1289
2039
|
] }),
|
|
1290
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1291
|
-
"
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
2040
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-results", children: [
|
|
2041
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "sess-results-main", role: "status", children: [
|
|
2042
|
+
"\u663E\u793A ",
|
|
2043
|
+
topList.length - syntheticCount,
|
|
2044
|
+
" \u4E2A\u4F1A\u8BDD",
|
|
2045
|
+
foldedCount || branchFolded ? `\uFF0C\u53E6\u6709 ${[foldedCount ? `${foldedCount} \u4E2A\u5B50\u4EE3\u7406\u6298\u53E0\u5728\u7236\u4F1A\u8BDD\u4E0B` : "", branchFolded ? `${branchFolded} \u4E2A\u5206\u652F\u805A\u6210 ${branchGroupCount} \u7EC4` : ""].filter(Boolean).join("\u3001")}` : query || workspaceFilter !== "all" || tagFilter ? `\uFF0C\u5171 ${filter === "archived" ? archivedList.length : filter === "active" ? activeList.length : filter === "starred" ? starredList.length : filter === "empty" ? emptyList.length : sessions.length} \u4E2A` : topList.length !== list.length ? `\uFF0C\u5171 ${list.length} \u4E2A` : ""
|
|
2046
|
+
] }),
|
|
2047
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dsm-fbar", children: [
|
|
2048
|
+
saveFilterOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2049
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2050
|
+
"input",
|
|
2051
|
+
{
|
|
2052
|
+
type: "text",
|
|
2053
|
+
value: saveFilterName,
|
|
2054
|
+
maxLength: 40,
|
|
2055
|
+
placeholder: "\u7B5B\u9009\u540D\u79F0",
|
|
2056
|
+
"aria-label": "\u4E3A\u5F53\u524D\u7B5B\u9009\u547D\u540D",
|
|
2057
|
+
autoFocus: true,
|
|
2058
|
+
disabled: mgrBusy,
|
|
2059
|
+
onChange: (e) => setSaveFilterName(e.target.value),
|
|
2060
|
+
onKeyDown: (e) => {
|
|
2061
|
+
if (e.key === "Enter") {
|
|
2062
|
+
e.preventDefault();
|
|
2063
|
+
saveCurrentFilter();
|
|
2064
|
+
}
|
|
2065
|
+
if (e.key === "Escape") {
|
|
2066
|
+
setSaveFilterOpen(false);
|
|
2067
|
+
setSaveFilterName("");
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
),
|
|
2072
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-go", disabled: mgrBusy || !saveFilterName.trim(), onClick: saveCurrentFilter, children: "\u4FDD\u5B58" }),
|
|
2073
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: mgrBusy, onClick: () => {
|
|
2074
|
+
setSaveFilterOpen(false);
|
|
2075
|
+
setSaveFilterName("");
|
|
2076
|
+
}, children: "\u53D6\u6D88" })
|
|
2077
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2078
|
+
"button",
|
|
2079
|
+
{
|
|
2080
|
+
type: "button",
|
|
2081
|
+
className: "archv-btn",
|
|
2082
|
+
title: "\u628A\u5F53\u524D\u89C6\u56FE / \u5DE5\u4F5C\u533A / \u6807\u7B7E / \u6392\u5E8F\u5B58\u4E3A\u4E00\u4E2A\u53EF\u590D\u7528\u7684\u7B5B\u9009",
|
|
2083
|
+
onClick: () => {
|
|
2084
|
+
setSaveFilterOpen(true);
|
|
2085
|
+
setSaveFilterName("");
|
|
2086
|
+
},
|
|
2087
|
+
children: "\u4FDD\u5B58\u5F53\u524D\u7B5B\u9009"
|
|
2088
|
+
}
|
|
2089
|
+
),
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2091
|
+
"select",
|
|
2092
|
+
{
|
|
2093
|
+
"aria-label": "\u5DF2\u5B58\u7B5B\u9009",
|
|
2094
|
+
value: savedFilters.some((f) => String(f.id) === appliedSavedId) ? appliedSavedId : "",
|
|
2095
|
+
disabled: !savedFilters.length || mgrBusy,
|
|
2096
|
+
title: !savedFilters.length ? "\u8FD8\u6CA1\u6709\u5DF2\u5B58\u7B5B\u9009\uFF1B\u70B9\u5DE6\u4FA7\u300C\u4FDD\u5B58\u5F53\u524D\u7B5B\u9009\u300D\u521B\u5EFA" : "\u9009\u62E9\u4E00\u4E2A\u5DF2\u5B58\u7B5B\u9009\u5E76\u7ACB\u5373\u5E94\u7528\uFF1B\u9009\u4E2D\u540E\u53F3\u4FA7\u53EF\u5220\u9664",
|
|
2097
|
+
onChange: (e) => applySavedFilter(e.target.value),
|
|
2098
|
+
children: [
|
|
2099
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: savedFilters.length ? "\u5DF2\u5B58\u7B5B\u9009\u2026" : "\u65E0\u5DF2\u5B58\u7B5B\u9009" }),
|
|
2100
|
+
savedFilters.map((f) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: f.id, children: f.name }, f.id))
|
|
2101
|
+
]
|
|
2102
|
+
}
|
|
2103
|
+
),
|
|
2104
|
+
appliedSavedId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2105
|
+
"button",
|
|
2106
|
+
{
|
|
2107
|
+
type: "button",
|
|
2108
|
+
className: "archv-btn archv-del",
|
|
2109
|
+
disabled: mgrBusy,
|
|
2110
|
+
title: "\u5220\u9664\u5DF2\u5B58\u7B5B\u9009\u300C" + ((savedFilters.find((f) => String(f.id) === appliedSavedId) || {}).name || appliedSavedId) + "\u300D\uFF08\u53EA\u5220\u8FD9\u6761\u4FDD\u5B58\u7684\u7B5B\u9009\uFF0C\u4E0D\u52A8\u4F1A\u8BDD\uFF09",
|
|
2111
|
+
onClick: () => deleteSavedFilter(appliedSavedId),
|
|
2112
|
+
children: "\u5220\u9664"
|
|
2113
|
+
}
|
|
2114
|
+
)
|
|
2115
|
+
] })
|
|
2116
|
+
] })
|
|
1296
2117
|
] }),
|
|
1297
2118
|
showSessionList && list.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-batch" + (selIds.length > 0 ? " sess-batch-pin" : ""), children: [
|
|
1298
2119
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sess-btntext", children: selIds.length ? `\u5DF2\u9009 ${selIds.length} \u9879` : filter === "archived" ? `\u5171 ${archivedList.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD` : filter === "starred" ? `\u5171 ${starredList.length} \u4E2A\u6536\u85CF\u4F1A\u8BDD` : `\u5171 ${sessions.length} \u4E2A\u4F1A\u8BDD\uFF08\u6D3B\u52A8 ${activeList.length} / \u5DF2\u5F52\u6863 ${archivedList.length}\uFF09` }),
|
|
@@ -1374,9 +2195,34 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1374
2195
|
] })
|
|
1375
2196
|
] })
|
|
1376
2197
|
] }),
|
|
1377
|
-
showSessionList && list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-empty", children: query || workspaceFilter !== "all" ? "\u6CA1\u6709\u5339\u914D\u7684\u4F1A\u8BDD\u3002\u8BF7\u8C03\u6574\u641C\u7D22\u8BCD\u6216\u5DE5\u4F5C\u533A\u7B5B\u9009\u3002" : filter === "archived" ? "\u76EE\u524D\u6CA1\u6709\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u201C\u5168\u90E8\u201D\u91CC\u9009\u4E2D\u4F1A\u8BDD\u70B9\u201C\u5F52\u6863\u201D\u5373\u53EF\u6536\u7EB3\u8FDB\u6765\u3002" : filter === "active" ? "\u76EE\u524D\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD\u3002" : filter === "starred" ? "\u8FD8\u6CA1\u6709\u6536\u85CF\u7684\u4F1A\u8BDD\u3002\u70B9\u51FB\u4F1A\u8BDD\u5DE6\u4FA7\u7684\u661F\u6807\u5373\u53EF\u6536\u85CF\u3002" : filter === "empty" ? "\u6CA1\u6709\u7A7A\u767D\u4F1A\u8BDD\u3002\u65B0\u5F00\u4F1A\u8BDD\u8FD8\u6CA1\u4EA7\u751F\u5185\u5BB9\u65F6\u4F1A\u5F52\u5230\u8FD9\u91CC\uFF0C\
|
|
2198
|
+
showSessionList && list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-empty", children: query || workspaceFilter !== "all" || tagFilter ? "\u6CA1\u6709\u5339\u914D\u7684\u4F1A\u8BDD\u3002\u8BF7\u8C03\u6574\u641C\u7D22\u8BCD\u3001\u6807\u7B7E\u6216\u5DE5\u4F5C\u533A\u7B5B\u9009\u3002" : filter === "archived" ? "\u76EE\u524D\u6CA1\u6709\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u201C\u5168\u90E8\u201D\u91CC\u9009\u4E2D\u4F1A\u8BDD\u70B9\u201C\u5F52\u6863\u201D\u5373\u53EF\u6536\u7EB3\u8FDB\u6765\u3002" : filter === "active" ? "\u76EE\u524D\u6CA1\u6709\u6D3B\u52A8\u4F1A\u8BDD\u3002" : filter === "starred" ? "\u8FD8\u6CA1\u6709\u6536\u85CF\u7684\u4F1A\u8BDD\u3002\u70B9\u51FB\u4F1A\u8BDD\u5DE6\u4FA7\u7684\u661F\u6807\u5373\u53EF\u6536\u85CF\u3002" : filter === "empty" ? "\u6CA1\u6709\u7A7A\u767D\u4F1A\u8BDD\u3002\u65B0\u5F00\u4F1A\u8BDD\u8FD8\u6CA1\u4EA7\u751F\u5185\u5BB9\u65F6\u4F1A\u5F52\u5230\u8FD9\u91CC\uFF0C\u4FA7\u680F\u4F1A\u81EA\u52A8\u9690\u85CF\u5B83\u4EEC\u3002" : "\u6682\u65E0\u53EF\u7BA1\u7406\u7684\u4F1A\u8BDD\u3002" }) : showSessionList ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-list", role: "list", children: topList.map((it) => {
|
|
2199
|
+
if (it && it.syntheticRoot) {
|
|
2200
|
+
const root = String(it.syntheticRoot);
|
|
2201
|
+
const members = branchGroupsOf.get(root) || [];
|
|
2202
|
+
const open = !!openBranches[root] || branchHit(root);
|
|
2203
|
+
const srcTitle = dsmAuthoritativeTitles.get(root);
|
|
2204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dsm-src-head", role: "listitem", children: [
|
|
2205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2206
|
+
"button",
|
|
2207
|
+
{
|
|
2208
|
+
type: "button",
|
|
2209
|
+
className: "dsm-kids-toggle",
|
|
2210
|
+
"aria-expanded": open,
|
|
2211
|
+
title: (open ? "\u6536\u8D77 " : "\u5C55\u5F00 ") + members.length + " \u4E2A\u5206\u652F\u4F1A\u8BDD\uFF08\u6765\u6E90\u4F1A\u8BDD\u4E0D\u5728\u5F53\u524D\u5217\u8868\uFF09",
|
|
2212
|
+
onClick: () => toggleBranch(root),
|
|
2213
|
+
children: [
|
|
2214
|
+
open ? "\u25BE" : "\u25B8",
|
|
2215
|
+
" ",
|
|
2216
|
+
members.length,
|
|
2217
|
+
" \u5206\u652F"
|
|
2218
|
+
]
|
|
2219
|
+
}
|
|
2220
|
+
),
|
|
2221
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-src-name", title: root, children: "\u6765\u6E90\uFF1A" + (srcTitle || shortId(root)) })
|
|
2222
|
+
] }, it.sessionId);
|
|
2223
|
+
}
|
|
1378
2224
|
const date = fmtDate(it.createdAt);
|
|
1379
|
-
const expanded = openMove === it.sessionId;
|
|
2225
|
+
const expanded = openMove === it.sessionId || openTags === it.sessionId;
|
|
1380
2226
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-card" + (expanded ? " archv-card-exp" : ""), role: "listitem", children: [
|
|
1381
2227
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-row", children: [
|
|
1382
2228
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1410,7 +2256,9 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1410
2256
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-name", title: it.title || "", children: it.title || "(\u65E0\u6807\u9898)" }),
|
|
1411
2257
|
branchBadge(it.sessionId),
|
|
1412
2258
|
emptyBadge(it.sessionId),
|
|
2259
|
+
tagChips(it.sessionId),
|
|
1413
2260
|
kidsBadge(it.sessionId),
|
|
2261
|
+
branchGroupBadge(it.sessionId),
|
|
1414
2262
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-id", title: it.sessionId, children: shortId(it.sessionId) })
|
|
1415
2263
|
] }),
|
|
1416
2264
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-meta", children: [
|
|
@@ -1426,6 +2274,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1426
2274
|
] })
|
|
1427
2275
|
] }),
|
|
1428
2276
|
groupByLineage && renderKids(it.sessionId, 0),
|
|
2277
|
+
groupByLineage && renderBranchGroup(it.sessionId),
|
|
1429
2278
|
expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", role: "region", "aria-label": "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A", children: [
|
|
1430
2279
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet-head", children: [
|
|
1431
2280
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mv-sheet-title", children: "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A" }),
|
|
@@ -1479,6 +2328,51 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1479
2328
|
] })
|
|
1480
2329
|
] })
|
|
1481
2330
|
] }),
|
|
2331
|
+
openTags === it.sessionId && (() => {
|
|
2332
|
+
const cur = Array.isArray(assignments[String(it.sessionId)]) ? assignments[String(it.sessionId)] : [];
|
|
2333
|
+
const locked = tagBusy !== null || !tagsReady;
|
|
2334
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", role: "region", "aria-label": "\u4F1A\u8BDD\u6807\u7B7E", children: [
|
|
2335
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet-head", children: [
|
|
2336
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { className: "mv-sheet-title", children: [
|
|
2337
|
+
"\u4F1A\u8BDD\u6807\u7B7E \xB7 ",
|
|
2338
|
+
it.title || shortId(it.sessionId)
|
|
2339
|
+
] }),
|
|
2340
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "mv-sheet-close", "aria-label": "\u5173\u95ED", onClick: () => setOpenTags(null), children: "\xD7" })
|
|
2341
|
+
] }),
|
|
2342
|
+
tagDefs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-note", children: "\u8FD8\u6CA1\u6709\u6807\u7B7E\uFF0C\u5728\u4E0B\u65B9\u65B0\u5EFA\u7B2C\u4E00\u4E2A\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dsm-taglist", children: tagDefs.map((t) => {
|
|
2343
|
+
const checked = cur.some((id) => String(id) === String(t.id));
|
|
2344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "dsm-tagcheck", children: [
|
|
2345
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked, disabled: locked, onChange: () => toggleTagFor(it.sessionId, t.id) }),
|
|
2346
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dsm-tagcheck-name", title: t.name, children: t.name })
|
|
2347
|
+
] }, String(t.id));
|
|
2348
|
+
}) }),
|
|
2349
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-field", children: [
|
|
2350
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "mv-field-label", htmlFor: "dsm-tag-attach-" + String(it.sessionId), children: "\u65B0\u5EFA\u6807\u7B7E\u5E76\u8D34\u4E0A" }),
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-browse-row", children: [
|
|
2352
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2353
|
+
"input",
|
|
2354
|
+
{
|
|
2355
|
+
id: "dsm-tag-attach-" + String(it.sessionId),
|
|
2356
|
+
type: "text",
|
|
2357
|
+
value: cardTagName,
|
|
2358
|
+
disabled: locked,
|
|
2359
|
+
maxLength: 24,
|
|
2360
|
+
placeholder: "\u6807\u7B7E\u540D\uFF08\u4E0D\u80FD\u542B\u659C\u6760\uFF0C\u6700\u957F 24 \u5B57\uFF09",
|
|
2361
|
+
onChange: (e) => setCardTagName(e.target.value),
|
|
2362
|
+
onKeyDown: (e) => {
|
|
2363
|
+
if (e.key === "Enter") {
|
|
2364
|
+
e.preventDefault();
|
|
2365
|
+
createTagAndAttach(it.sessionId);
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
),
|
|
2370
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: locked || !cardTagName.trim(), title: locked && !tagsReady ? "\u6807\u7B7E\u6570\u636E\u672A\u80FD\u52A0\u8F7D\uFF0C\u6682\u65F6\u65E0\u6CD5\u65B0\u5EFA\u6807\u7B7E" : "\u65B0\u5EFA\u8FD9\u4E2A\u6807\u7B7E\u5E76\u7ACB\u5373\u8D34\u5230\u5F53\u524D\u4F1A\u8BDD", onClick: () => createTagAndAttach(it.sessionId), children: "\u8D34\u4E0A" })
|
|
2371
|
+
] })
|
|
2372
|
+
] }),
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-note", children: "\u52FE\u9009\u5373\u65F6\u751F\u6548\uFF1B\u5355\u4E2A\u4F1A\u8BDD\u7684\u6807\u7B7E\u6570\u91CF\u4EE5\u670D\u52A1\u7AEF\u4E0A\u9650\u4E3A\u51C6\uFF0C\u8D85\u65F6\u4F1A\u63D0\u793A\u5E76\u56DE\u9000\u3002" })
|
|
2374
|
+
] });
|
|
2375
|
+
})(),
|
|
1482
2376
|
openDetails === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sheet", role: "region", "aria-label": "\u4F1A\u8BDD\u8BE6\u60C5", children: [
|
|
1483
2377
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sheet-head", children: [
|
|
1484
2378
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "dtl-sheet-title", children: "\u4F1A\u8BDD\u8BE6\u60C5" }),
|
|
@@ -1560,7 +2454,7 @@ function SessionPanel({ workspacesSvc }) {
|
|
|
1560
2454
|
] }, i)) })
|
|
1561
2455
|
] }),
|
|
1562
2456
|
d.lineage && (d.lineage.parentSessionId || d.lineage.children && d.lineage.children.length > 0 || d.lineage.subagents && d.lineage.subagents.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-sec", children: [
|
|
1563
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-sec-t", children: "\u8840\
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dtl-sec-t", children: "\u8840\u7F18" }),
|
|
1564
2458
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dtl-paths", children: [
|
|
1565
2459
|
d.lineage.parentSessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1566
2460
|
"\u7236\u4F1A\u8BDD: ",
|
|
@@ -1823,12 +2717,60 @@ var dsmTrashTick = 0;
|
|
|
1823
2717
|
var dsmCapabilities = null;
|
|
1824
2718
|
var dsmLineage = /* @__PURE__ */ new Map();
|
|
1825
2719
|
var dsmWarmPending = false;
|
|
2720
|
+
var dsmRefinePending = false;
|
|
1826
2721
|
var dsmTrashRetryTimer = null;
|
|
1827
2722
|
var dsmWarmDoneHooks = /* @__PURE__ */ new Set();
|
|
1828
2723
|
function dsmOnWarmDone(fn) {
|
|
1829
2724
|
dsmWarmDoneHooks.add(fn);
|
|
1830
2725
|
return () => dsmWarmDoneHooks.delete(fn);
|
|
1831
2726
|
}
|
|
2727
|
+
var DSM_KEY_SEEN_NOTICES = "dsm-move-notices-seen-v1";
|
|
2728
|
+
var dsmSeenNotices = null;
|
|
2729
|
+
function dsmLoadSeenNotices() {
|
|
2730
|
+
if (dsmSeenNotices) return dsmSeenNotices;
|
|
2731
|
+
try {
|
|
2732
|
+
dsmSeenNotices = new Set(JSON.parse(localStorage.getItem(DSM_KEY_SEEN_NOTICES) || "[]").map(String));
|
|
2733
|
+
} catch (e) {
|
|
2734
|
+
dsmSeenNotices = /* @__PURE__ */ new Set();
|
|
2735
|
+
}
|
|
2736
|
+
return dsmSeenNotices;
|
|
2737
|
+
}
|
|
2738
|
+
function dsmSaveSeenNotices(set) {
|
|
2739
|
+
try {
|
|
2740
|
+
localStorage.setItem(DSM_KEY_SEEN_NOTICES, JSON.stringify([...set].slice(-200)));
|
|
2741
|
+
} catch (e) {
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
var dsmNotifySink = null;
|
|
2745
|
+
var dsmNoticeHooks = /* @__PURE__ */ new Set();
|
|
2746
|
+
function dsmNotify(text, kind) {
|
|
2747
|
+
if (!text) return;
|
|
2748
|
+
if (dsmNotifySink && !sidebarAdapter.disabled) {
|
|
2749
|
+
try {
|
|
2750
|
+
dsmNotifySink(text, kind);
|
|
2751
|
+
return;
|
|
2752
|
+
} catch (e) {
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
let done = false;
|
|
2756
|
+
try {
|
|
2757
|
+
for (const fn of dsmNoticeHooks) {
|
|
2758
|
+
fn(text, kind);
|
|
2759
|
+
done = true;
|
|
2760
|
+
}
|
|
2761
|
+
} catch (e) {
|
|
2762
|
+
}
|
|
2763
|
+
if (!done) {
|
|
2764
|
+
try {
|
|
2765
|
+
console.warn("[dsh-sessions-manager] " + text);
|
|
2766
|
+
} catch (e) {
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
function dsmOnNotice(fn) {
|
|
2771
|
+
dsmNoticeHooks.add(fn);
|
|
2772
|
+
return () => dsmNoticeHooks.delete(fn);
|
|
2773
|
+
}
|
|
1832
2774
|
async function dsmLoadCapabilities() {
|
|
1833
2775
|
try {
|
|
1834
2776
|
dsmCapabilities = await postJSON("/archived-sessions/capabilities", {});
|
|
@@ -1853,14 +2795,26 @@ async function dsmLoadTrashIds() {
|
|
|
1853
2795
|
for (const [id, info] of Object.entries(r && r.lineage || {})) {
|
|
1854
2796
|
if (info && typeof info === "object") dsmLineage.set(String(id), info);
|
|
1855
2797
|
}
|
|
1856
|
-
const
|
|
2798
|
+
const wasBusy = dsmWarmPending || dsmRefinePending;
|
|
1857
2799
|
dsmWarmPending = !!(r && r.warmPending);
|
|
1858
|
-
|
|
2800
|
+
dsmRefinePending = !!(r && r.refinePending);
|
|
2801
|
+
if (wasBusy && !(dsmWarmPending || dsmRefinePending)) {
|
|
1859
2802
|
try {
|
|
1860
2803
|
for (const fn of dsmWarmDoneHooks) fn();
|
|
1861
2804
|
} catch (e) {
|
|
1862
2805
|
}
|
|
1863
2806
|
}
|
|
2807
|
+
{
|
|
2808
|
+
const plan = noticeToastPlan(r && r.moveNotices, dsmLoadSeenNotices(), 2);
|
|
2809
|
+
if (plan.ackIds.length) {
|
|
2810
|
+
const seen = dsmLoadSeenNotices();
|
|
2811
|
+
for (const id of plan.ackIds) seen.add(id);
|
|
2812
|
+
dsmSaveSeenNotices(seen);
|
|
2813
|
+
dsmNotify(plan.text, plan.kind);
|
|
2814
|
+
postJSON("/archived-sessions/pending-moves/notices/ack", { ids: plan.ackIds }).catch(() => {
|
|
2815
|
+
});
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
1864
2818
|
if (dsmRepaintDots) dsmRepaintDots();
|
|
1865
2819
|
} catch (e) {
|
|
1866
2820
|
if (dsmTrashRetryTimer == null) {
|
|
@@ -2467,10 +3421,13 @@ function installSidebarStatusDots() {
|
|
|
2467
3421
|
const t = document.createElement("div");
|
|
2468
3422
|
t.className = "dsm-toast" + (kind === "err" ? " dsm-toast-err" : "");
|
|
2469
3423
|
t.textContent = msg;
|
|
2470
|
-
t.
|
|
3424
|
+
t.setAttribute("role", "status");
|
|
3425
|
+
t.style.cssText = "position:fixed;left:50%;bottom:24px;transform:translateX(-50%);max-width:80%;padding:8px 14px;border-radius:8px;background:#2C2C2A;color:#F1EFE8;font-size:12px;line-height:1.5;z-index:9999;cursor:pointer";
|
|
3426
|
+
t.addEventListener("click", () => t.remove());
|
|
2471
3427
|
document.body.appendChild(t);
|
|
2472
|
-
setTimeout(() => t.remove(),
|
|
3428
|
+
setTimeout(() => t.remove(), toastDurationFor(msg, kind));
|
|
2473
3429
|
};
|
|
3430
|
+
dsmNotifySink = paintToast;
|
|
2474
3431
|
const DSM_KEY_SUBS = "dsm-subs-open-v1";
|
|
2475
3432
|
const dsmSubsOpen = /* @__PURE__ */ new Set();
|
|
2476
3433
|
try {
|
|
@@ -2661,7 +3618,7 @@ function installSidebarStatusDots() {
|
|
|
2661
3618
|
const FALLBACK_TICK_MS = 4e3;
|
|
2662
3619
|
const tick = () => {
|
|
2663
3620
|
if (typeof document !== "undefined" && document.hidden) return;
|
|
2664
|
-
const cadence = dsmWarmPending ? 1 : 8;
|
|
3621
|
+
const cadence = dsmWarmPending || dsmRefinePending ? 1 : 8;
|
|
2665
3622
|
if (++dsmTrashTick % cadence === 0) dsmLoadTrashIds();
|
|
2666
3623
|
paint();
|
|
2667
3624
|
};
|
|
@@ -2682,6 +3639,7 @@ function installSidebarStatusDots() {
|
|
|
2682
3639
|
clearInterval(tickTimer);
|
|
2683
3640
|
clearTimeout(coldSecondBeat);
|
|
2684
3641
|
obs.disconnect();
|
|
3642
|
+
dsmNotifySink = null;
|
|
2685
3643
|
dsmTeardownSidebarAug();
|
|
2686
3644
|
};
|
|
2687
3645
|
}
|
|
@@ -2714,7 +3672,7 @@ function installSidebarWorkspaceDrag() {
|
|
|
2714
3672
|
el.setAttribute("role", "status");
|
|
2715
3673
|
el.textContent = message;
|
|
2716
3674
|
document.body.appendChild(el);
|
|
2717
|
-
setTimeout(() => el.remove(),
|
|
3675
|
+
setTimeout(() => el.remove(), toastDurationFor(message));
|
|
2718
3676
|
};
|
|
2719
3677
|
const clearVisuals = () => {
|
|
2720
3678
|
document.querySelectorAll(".dsm-drag-source,.dsm-drop-target").forEach((el) => el.classList.remove("dsm-drag-source", "dsm-drop-target"));
|