@michengai/dsh-codex-ui 0.2.101 → 0.2.102
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/CHANGELOG.md +28 -0
- package/CHANGELOG.zh-CN.md +28 -0
- package/README.md +1 -2
- package/README.zh-CN.md +1 -2
- package/{dist → lib}/client.js +2514 -749
- package/{dist → lib}/index.mjs +556 -19
- package/package.json +45 -27
- /package/{dist → lib}/index.d.mts +0 -0
package/{dist → lib}/client.js
RENAMED
|
@@ -297,7 +297,7 @@ window.__ModuleLoader__.load({
|
|
|
297
297
|
running: row.running === true
|
|
298
298
|
};
|
|
299
299
|
}
|
|
300
|
-
function parseChannelGroups(payload) {
|
|
300
|
+
function parseChannelGroups(payload, fallbackLabel = "") {
|
|
301
301
|
const root = payload !== null && typeof payload === "object" ? payload : {};
|
|
302
302
|
return (Array.isArray(root.groups) ? root.groups : Array.isArray(payload) ? payload : []).flatMap((item, index) => {
|
|
303
303
|
if (item === null || typeof item !== "object") return [];
|
|
@@ -308,13 +308,13 @@ window.__ModuleLoader__.load({
|
|
|
308
308
|
}) : [];
|
|
309
309
|
return [{
|
|
310
310
|
id: text(group.id, `channel-${index}`),
|
|
311
|
-
label: text(group.label, text(group.title,
|
|
311
|
+
label: text(group.label, text(group.title, fallbackLabel)),
|
|
312
312
|
sessions
|
|
313
313
|
}];
|
|
314
314
|
});
|
|
315
315
|
}
|
|
316
316
|
/** 读取 IM 频道分组;失败时交给界面显示空态或错误。 */
|
|
317
|
-
async function loadChannelGroups(signal) {
|
|
317
|
+
async function loadChannelGroups(signal, fallbackLabel = "") {
|
|
318
318
|
const response = await fetch(CHANNELS_ENDPOINT, {
|
|
319
319
|
cache: "no-store",
|
|
320
320
|
signal
|
|
@@ -328,66 +328,244 @@ window.__ModuleLoader__.load({
|
|
|
328
328
|
const root = payload !== null && typeof payload === "object" ? payload : {};
|
|
329
329
|
if (!response.ok) throw new Error(text(root.error, "无法读取频道会话"));
|
|
330
330
|
if (root.ok === false) throw new Error(text(root.error, "无法读取频道会话"));
|
|
331
|
-
return parseChannelGroups(payload);
|
|
331
|
+
return parseChannelGroups(payload, fallbackLabel);
|
|
332
332
|
}
|
|
333
333
|
//#endregion
|
|
334
|
-
//#region src/
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
334
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs
|
|
335
|
+
/**
|
|
336
|
+
* @license lucide-react v1.39.0 - ISC
|
|
337
|
+
*
|
|
338
|
+
* This source code is licensed under the ISC license.
|
|
339
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
340
|
+
*/
|
|
341
|
+
const mergeClasses = (...classes) => classes.filter((className, index, array) => {
|
|
342
|
+
return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
|
|
343
|
+
}).join(" ").trim();
|
|
344
|
+
//#endregion
|
|
345
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs
|
|
346
|
+
/**
|
|
347
|
+
* @license lucide-react v1.39.0 - ISC
|
|
348
|
+
*
|
|
349
|
+
* This source code is licensed under the ISC license.
|
|
350
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
351
|
+
*/
|
|
352
|
+
const toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
353
|
+
//#endregion
|
|
354
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs
|
|
355
|
+
/**
|
|
356
|
+
* @license lucide-react v1.39.0 - ISC
|
|
357
|
+
*
|
|
358
|
+
* This source code is licensed under the ISC license.
|
|
359
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
360
|
+
*/
|
|
361
|
+
const toCamelCase = (string) => string.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase());
|
|
362
|
+
//#endregion
|
|
363
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs
|
|
364
|
+
/**
|
|
365
|
+
* @license lucide-react v1.39.0 - ISC
|
|
366
|
+
*
|
|
367
|
+
* This source code is licensed under the ISC license.
|
|
368
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
369
|
+
*/
|
|
370
|
+
const toPascalCase = (string) => {
|
|
371
|
+
const camelCase = toCamelCase(string);
|
|
372
|
+
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
373
|
+
};
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/defaultAttributes.mjs
|
|
376
|
+
/**
|
|
377
|
+
* @license lucide-react v1.39.0 - ISC
|
|
378
|
+
*
|
|
379
|
+
* This source code is licensed under the ISC license.
|
|
380
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
381
|
+
*/
|
|
382
|
+
var defaultAttributes = {
|
|
383
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
384
|
+
width: 24,
|
|
385
|
+
height: 24,
|
|
386
|
+
viewBox: "0 0 24 24",
|
|
387
|
+
fill: "none",
|
|
388
|
+
stroke: "currentColor",
|
|
389
|
+
strokeWidth: 2,
|
|
390
|
+
strokeLinecap: "round",
|
|
391
|
+
strokeLinejoin: "round"
|
|
392
|
+
};
|
|
393
|
+
//#endregion
|
|
394
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs
|
|
395
|
+
/**
|
|
396
|
+
* @license lucide-react v1.39.0 - ISC
|
|
397
|
+
*
|
|
398
|
+
* This source code is licensed under the ISC license.
|
|
399
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
400
|
+
*/
|
|
401
|
+
const hasA11yProp = (props) => {
|
|
402
|
+
for (const prop in props) if (prop.startsWith("aria-") || prop === "role" || prop === "title") return true;
|
|
403
|
+
return false;
|
|
404
|
+
};
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/context.mjs
|
|
407
|
+
/**
|
|
408
|
+
* @license lucide-react v1.39.0 - ISC
|
|
409
|
+
*
|
|
410
|
+
* This source code is licensed under the ISC license.
|
|
411
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
412
|
+
*/
|
|
413
|
+
const LucideContext = (0, react.createContext)({});
|
|
414
|
+
const useLucideContext = () => (0, react.useContext)(LucideContext);
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/Icon.mjs
|
|
417
|
+
/**
|
|
418
|
+
* @license lucide-react v1.39.0 - ISC
|
|
419
|
+
*
|
|
420
|
+
* This source code is licensed under the ISC license.
|
|
421
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
422
|
+
*/
|
|
423
|
+
const Icon = (0, react.forwardRef)(({ color, size, strokeWidth, absoluteStrokeWidth, className = "", children, iconNode, ...rest }, ref) => {
|
|
424
|
+
const { size: contextSize = 24, strokeWidth: contextStrokeWidth = 2, absoluteStrokeWidth: contextAbsoluteStrokeWidth = false, color: contextColor = "currentColor", className: contextClass = "" } = useLucideContext() ?? {};
|
|
425
|
+
const calculatedStrokeWidth = absoluteStrokeWidth ?? contextAbsoluteStrokeWidth ? Number(strokeWidth ?? contextStrokeWidth) * 24 / Number(size ?? contextSize) : strokeWidth ?? contextStrokeWidth;
|
|
426
|
+
return (0, react.createElement)("svg", {
|
|
427
|
+
ref,
|
|
428
|
+
...defaultAttributes,
|
|
429
|
+
width: size ?? contextSize ?? defaultAttributes.width,
|
|
430
|
+
height: size ?? contextSize ?? defaultAttributes.height,
|
|
431
|
+
stroke: color ?? contextColor,
|
|
432
|
+
strokeWidth: calculatedStrokeWidth,
|
|
433
|
+
className: mergeClasses("lucide", contextClass, className),
|
|
434
|
+
...!children && !hasA11yProp(rest) && { "aria-hidden": "true" },
|
|
435
|
+
...rest
|
|
436
|
+
}, [...iconNode.map(([tag, attrs]) => (0, react.createElement)(tag, attrs)), ...Array.isArray(children) ? children : [children]]);
|
|
437
|
+
});
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region node_modules/.pnpm/lucide-react@1.39.0_react@18.3.1/node_modules/lucide-react/dist/esm/createLucideIcon.mjs
|
|
440
|
+
/**
|
|
441
|
+
* @license lucide-react v1.39.0 - ISC
|
|
442
|
+
*
|
|
443
|
+
* This source code is licensed under the ISC license.
|
|
444
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
445
|
+
*/
|
|
446
|
+
const createLucideIcon = (iconName, iconNode) => {
|
|
447
|
+
const Component = (0, react.forwardRef)(({ className, ...props }, ref) => (0, react.createElement)(Icon, {
|
|
448
|
+
ref,
|
|
449
|
+
iconNode,
|
|
450
|
+
className: mergeClasses(`lucide-${toKebabCase(toPascalCase(iconName))}`, `lucide-${iconName}`, className),
|
|
451
|
+
...props
|
|
452
|
+
}));
|
|
453
|
+
Component.displayName = toPascalCase(iconName);
|
|
454
|
+
return Component;
|
|
455
|
+
};
|
|
456
|
+
/**
|
|
457
|
+
* @license lucide-react v1.39.0 - ISC
|
|
458
|
+
*
|
|
459
|
+
* This source code is licensed under the ISC license.
|
|
460
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
461
|
+
*/
|
|
462
|
+
const Archive = createLucideIcon("archive", [
|
|
463
|
+
["rect", {
|
|
464
|
+
width: "20",
|
|
465
|
+
height: "5",
|
|
466
|
+
x: "2",
|
|
467
|
+
y: "3",
|
|
468
|
+
rx: "1",
|
|
469
|
+
key: "1wp1u1"
|
|
470
|
+
}],
|
|
471
|
+
["path", {
|
|
472
|
+
d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8",
|
|
473
|
+
key: "1s80jp"
|
|
474
|
+
}],
|
|
475
|
+
["path", {
|
|
476
|
+
d: "M10 12h4",
|
|
477
|
+
key: "a56b0p"
|
|
478
|
+
}]
|
|
479
|
+
]);
|
|
480
|
+
/**
|
|
481
|
+
* @license lucide-react v1.39.0 - ISC
|
|
482
|
+
*
|
|
483
|
+
* This source code is licensed under the ISC license.
|
|
484
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
485
|
+
*/
|
|
486
|
+
const EyeOff = createLucideIcon("eye-off", [
|
|
487
|
+
["path", {
|
|
488
|
+
d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",
|
|
489
|
+
key: "ct8e1f"
|
|
490
|
+
}],
|
|
491
|
+
["path", {
|
|
492
|
+
d: "M14.084 14.158a3 3 0 0 1-4.242-4.242",
|
|
493
|
+
key: "151rxh"
|
|
494
|
+
}],
|
|
495
|
+
["path", {
|
|
496
|
+
d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",
|
|
497
|
+
key: "13bj9a"
|
|
498
|
+
}],
|
|
499
|
+
["path", {
|
|
500
|
+
d: "m2 2 20 20",
|
|
501
|
+
key: "1ooewy"
|
|
502
|
+
}]
|
|
503
|
+
]);
|
|
504
|
+
/**
|
|
505
|
+
* @license lucide-react v1.39.0 - ISC
|
|
506
|
+
*
|
|
507
|
+
* This source code is licensed under the ISC license.
|
|
508
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
509
|
+
*/
|
|
510
|
+
const Eye = createLucideIcon("eye", [["path", {
|
|
511
|
+
d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",
|
|
512
|
+
key: "1nclc0"
|
|
513
|
+
}], ["circle", {
|
|
514
|
+
cx: "12",
|
|
515
|
+
cy: "12",
|
|
516
|
+
r: "3",
|
|
517
|
+
key: "1v7zrd"
|
|
518
|
+
}]]);
|
|
519
|
+
/**
|
|
520
|
+
* @license lucide-react v1.39.0 - ISC
|
|
521
|
+
*
|
|
522
|
+
* This source code is licensed under the ISC license.
|
|
523
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
524
|
+
*/
|
|
525
|
+
const MessageCircle = createLucideIcon("message-circle", [["path", {
|
|
526
|
+
d: "M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",
|
|
527
|
+
key: "1sd12s"
|
|
528
|
+
}]]);
|
|
529
|
+
/**
|
|
530
|
+
* @license lucide-react v1.39.0 - ISC
|
|
531
|
+
*
|
|
532
|
+
* This source code is licensed under the ISC license.
|
|
533
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
534
|
+
*/
|
|
535
|
+
const Pin = createLucideIcon("pin", [["path", {
|
|
536
|
+
d: "M12 17v5",
|
|
537
|
+
key: "bb1du9"
|
|
538
|
+
}], ["path", {
|
|
539
|
+
d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z",
|
|
540
|
+
key: "1nkz8b"
|
|
541
|
+
}]]);
|
|
542
|
+
/**
|
|
543
|
+
* @license lucide-react v1.39.0 - ISC
|
|
544
|
+
*
|
|
545
|
+
* This source code is licensed under the ISC license.
|
|
546
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
547
|
+
*/
|
|
548
|
+
const SquarePen = createLucideIcon("square-pen", [["path", {
|
|
549
|
+
d: "M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7",
|
|
550
|
+
key: "1m0v6g"
|
|
551
|
+
}], ["path", {
|
|
552
|
+
d: "M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z",
|
|
553
|
+
key: "ohrbg2"
|
|
554
|
+
}]]);
|
|
368
555
|
//#endregion
|
|
369
556
|
//#region src/client/session-tree.tsx
|
|
370
557
|
function PinIcon() {
|
|
371
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
372
|
-
viewBox: "0 0 16 16",
|
|
373
|
-
width: 16,
|
|
374
|
-
height: 16,
|
|
558
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pin, {
|
|
375
559
|
"aria-hidden": "true",
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
fill: "none",
|
|
379
|
-
stroke: "currentColor",
|
|
380
|
-
strokeWidth: "1.35",
|
|
381
|
-
strokeLinecap: "round",
|
|
382
|
-
strokeLinejoin: "round"
|
|
383
|
-
})
|
|
560
|
+
size: 16,
|
|
561
|
+
strokeWidth: 1.5
|
|
384
562
|
});
|
|
385
563
|
}
|
|
386
|
-
function
|
|
387
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
388
|
-
viewBox: "0 0 16 16",
|
|
564
|
+
function QuickArchiveIcon() {
|
|
565
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Archive, {
|
|
389
566
|
"aria-hidden": "true",
|
|
390
|
-
|
|
567
|
+
size: 16,
|
|
568
|
+
strokeWidth: 1.5
|
|
391
569
|
});
|
|
392
570
|
}
|
|
393
571
|
function SessionHoverCard({ tip, onEnter, onLeave }) {
|
|
@@ -402,7 +580,10 @@ window.__ModuleLoader__.load({
|
|
|
402
580
|
children: [
|
|
403
581
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
404
582
|
className: "dcu-wb-tip-title",
|
|
405
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
583
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
584
|
+
className: "dcu-wb-tip-title-main",
|
|
585
|
+
children: tip.title
|
|
586
|
+
}), tip.time !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
406
587
|
className: "dcu-wb-tip-time",
|
|
407
588
|
children: tip.time
|
|
408
589
|
})]
|
|
@@ -431,15 +612,18 @@ window.__ModuleLoader__.load({
|
|
|
431
612
|
label: t("sessions.rename"),
|
|
432
613
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 16 })
|
|
433
614
|
},
|
|
434
|
-
{
|
|
435
|
-
id: "pin",
|
|
436
|
-
label: t(options.pinned ? "sessions.unpin" : "sessions.pin"),
|
|
437
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinIcon, {})
|
|
438
|
-
},
|
|
439
615
|
{
|
|
440
616
|
id: "unread",
|
|
441
617
|
label: t(options.unread ? "sessions.markRead" : "sessions.markUnread"),
|
|
442
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
618
|
+
icon: options.unread ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EyeOff, {
|
|
619
|
+
"aria-hidden": "true",
|
|
620
|
+
size: 16,
|
|
621
|
+
strokeWidth: 1.5
|
|
622
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Eye, {
|
|
623
|
+
"aria-hidden": "true",
|
|
624
|
+
size: 16,
|
|
625
|
+
strokeWidth: 1.5
|
|
626
|
+
})
|
|
443
627
|
},
|
|
444
628
|
{
|
|
445
629
|
id: "archive",
|
|
@@ -454,10 +638,6 @@ window.__ModuleLoader__.load({
|
|
|
454
638
|
id: "fork",
|
|
455
639
|
label: t("sessions.fork"),
|
|
456
640
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 })
|
|
457
|
-
},
|
|
458
|
-
{
|
|
459
|
-
type: "separator",
|
|
460
|
-
id: "copy-separator"
|
|
461
641
|
}
|
|
462
642
|
];
|
|
463
643
|
if (options.includePath === true) items.push({
|
|
@@ -465,25 +645,35 @@ window.__ModuleLoader__.load({
|
|
|
465
645
|
label: t("sessions.openPath"),
|
|
466
646
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, { size: 16 }),
|
|
467
647
|
disabled: options.path === void 0
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
648
|
+
});
|
|
649
|
+
if (options.moveTargets !== void 0) items.push({
|
|
650
|
+
id: "moveWorkspace",
|
|
651
|
+
label: t("sessions.moveWorkspace"),
|
|
652
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 }),
|
|
653
|
+
disabled: options.moveTargets.length === 0,
|
|
654
|
+
submenu: options.moveTargets.map((target) => ({
|
|
655
|
+
id: target.id,
|
|
656
|
+
label: target.label,
|
|
657
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
658
|
+
}))
|
|
473
659
|
});
|
|
474
660
|
items.push({
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, { size: 16 })
|
|
661
|
+
type: "separator",
|
|
662
|
+
id: "copy-separator"
|
|
478
663
|
}, {
|
|
479
664
|
id: "copyId",
|
|
480
665
|
label: t("sessions.copyId"),
|
|
481
666
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 })
|
|
482
667
|
}, {
|
|
483
|
-
id: "
|
|
484
|
-
label: t("sessions.
|
|
485
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
486
|
-
}, {
|
|
668
|
+
id: "copyTitle",
|
|
669
|
+
label: t("sessions.copyTitle"),
|
|
670
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, { size: 16 })
|
|
671
|
+
}, ...options.includePath === true ? [{
|
|
672
|
+
id: "copyPath",
|
|
673
|
+
label: t("sessions.copyPath"),
|
|
674
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutline16, { size: 16 }),
|
|
675
|
+
disabled: options.path === void 0
|
|
676
|
+
}] : [], {
|
|
487
677
|
type: "separator",
|
|
488
678
|
id: "delete-separator"
|
|
489
679
|
}, {
|
|
@@ -494,9 +684,6 @@ window.__ModuleLoader__.load({
|
|
|
494
684
|
});
|
|
495
685
|
return items;
|
|
496
686
|
}
|
|
497
|
-
function copySessionLink(sessionId) {
|
|
498
|
-
return sessionDeepLink(typeof window === "undefined" || window.location.origin === "null" ? "http://dsh.internal/" : `${window.location.origin}/`, sessionId);
|
|
499
|
-
}
|
|
500
687
|
/** 把右键落点收成 Menu 的锚点矩形,让列表贴着指针打开。 */
|
|
501
688
|
function pointerMenuRect(x, y) {
|
|
502
689
|
return new DOMRect(x, y, 0, 0);
|
|
@@ -535,7 +722,7 @@ window.__ModuleLoader__.load({
|
|
|
535
722
|
});
|
|
536
723
|
return null;
|
|
537
724
|
}
|
|
538
|
-
function SessionRow({ id, title, selected, menuOpen,
|
|
725
|
+
function SessionRow({ id, title, selected, menuOpen, unread, running, pendingInteraction, t, menuItems, onOpen, onMenuChange, onSelectAction, onArchive, onHover, onLeave, onContextMenu, menuPoint, subtitle, flat, draggable, dropActive, onDragStart, onDragEnd, onDragOver, onDrop }) {
|
|
539
726
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
540
727
|
className: `dcu-wb-session${selected ? " dcu-wb-selected" : ""}${menuOpen ? " dcu-wb-menu-open" : ""}${dropActive === true ? " dcu-wb-drop" : ""}${flat === true ? " dcu-wb-session-flat" : ""}`,
|
|
541
728
|
role: "treeitem",
|
|
@@ -563,29 +750,15 @@ window.__ModuleLoader__.load({
|
|
|
563
750
|
className: "dcu-wb-session-title",
|
|
564
751
|
children: title.split(/\r?\n/)[0] ?? title
|
|
565
752
|
}),
|
|
566
|
-
pinned && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
567
|
-
className: "dcu-wb-pin",
|
|
568
|
-
"aria-label": t("sessions.pinned"),
|
|
569
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinMark, {})
|
|
570
|
-
}),
|
|
571
753
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionState, {
|
|
572
754
|
pendingInteraction,
|
|
573
755
|
unread,
|
|
574
756
|
running,
|
|
575
757
|
t
|
|
576
758
|
}),
|
|
577
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
759
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
578
760
|
className: "dcu-wb-quick-actions",
|
|
579
|
-
children:
|
|
580
|
-
type: "button",
|
|
581
|
-
className: "dcu-wb-more dcu-wb-quick-pin",
|
|
582
|
-
"aria-label": t(pinned ? "sessions.unpin" : "sessions.pin"),
|
|
583
|
-
onClick: (event) => {
|
|
584
|
-
event.stopPropagation();
|
|
585
|
-
onPin();
|
|
586
|
-
},
|
|
587
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinMark, {})
|
|
588
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
761
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
589
762
|
type: "button",
|
|
590
763
|
className: "dcu-wb-more",
|
|
591
764
|
"aria-label": t("sessions.archive"),
|
|
@@ -593,8 +766,8 @@ window.__ModuleLoader__.load({
|
|
|
593
766
|
event.stopPropagation();
|
|
594
767
|
onArchive();
|
|
595
768
|
},
|
|
596
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
597
|
-
})
|
|
769
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickArchiveIcon, {})
|
|
770
|
+
})
|
|
598
771
|
}),
|
|
599
772
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
600
773
|
className: "dcu-wb-actions",
|
|
@@ -667,13 +840,151 @@ window.__ModuleLoader__.load({
|
|
|
667
840
|
default: return;
|
|
668
841
|
}
|
|
669
842
|
}
|
|
843
|
+
/** 旧版 SessionSummary 的兼容读取;alpha.5 已将该状态迁移到独立 Store。 */
|
|
844
|
+
function legacyPendingInteraction(summary) {
|
|
845
|
+
if (typeof summary !== "object" || summary === null || !("pendingInteraction" in summary)) return void 0;
|
|
846
|
+
return summary.pendingInteraction;
|
|
847
|
+
}
|
|
670
848
|
function pendingInteractionForSession(sessionId, pendingInteractions, summaryKind) {
|
|
671
849
|
return visiblePendingKind(summaryKind) ?? visiblePendingKind(pendingInteractions.get(sessionId)?.kind);
|
|
672
850
|
}
|
|
851
|
+
const WORKSPACE_GROUP_ERROR_MESSAGES = {
|
|
852
|
+
"group-invalid": "分组信息无效。",
|
|
853
|
+
"workspace-invalid": "项目标识无效。",
|
|
854
|
+
"group-missing": "目标分组不存在。",
|
|
855
|
+
"order-anchor-missing": "排序锚点不存在。"
|
|
856
|
+
};
|
|
857
|
+
/** 以稳定错误码承载分组业务失败,诊断文案不参与界面控制逻辑。 */
|
|
858
|
+
var WorkspaceGroupError = class extends Error {
|
|
859
|
+
code;
|
|
860
|
+
name = "WorkspaceGroupError";
|
|
861
|
+
constructor(code, message = WORKSPACE_GROUP_ERROR_MESSAGES[code]) {
|
|
862
|
+
super(message);
|
|
863
|
+
this.code = code;
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
/** 对持久化分组做严格校验,避免一个项目同时出现在多个分组。 */
|
|
867
|
+
function parseWorkspaceGroups(value) {
|
|
868
|
+
if (!Array.isArray(value) || value.length > 100) return void 0;
|
|
869
|
+
const groupIds = /* @__PURE__ */ new Set();
|
|
870
|
+
const groupTitles = /* @__PURE__ */ new Set();
|
|
871
|
+
const workspaceIds = /* @__PURE__ */ new Set();
|
|
872
|
+
const groups = [];
|
|
873
|
+
for (const valueGroup of value) {
|
|
874
|
+
if (valueGroup === null || typeof valueGroup !== "object") return void 0;
|
|
875
|
+
const group = valueGroup;
|
|
876
|
+
const id = typeof group.id === "string" ? group.id.trim() : "";
|
|
877
|
+
const title = typeof group.title === "string" ? group.title.trim() : "";
|
|
878
|
+
if (id === "" || id.length > 128 || title === "" || title.length > 80) return void 0;
|
|
879
|
+
if (groupIds.has(id) || groupTitles.has(title.toLocaleLowerCase())) return void 0;
|
|
880
|
+
if (!Array.isArray(group.workspaceIds) || group.workspaceIds.length > 1e3) return void 0;
|
|
881
|
+
const normalizedIds = [...new Set(group.workspaceIds)];
|
|
882
|
+
if (!normalizedIds.every((workspaceId) => typeof workspaceId === "string" && workspaceId.trim() !== "" && workspaceId.length <= 256)) return void 0;
|
|
883
|
+
if (normalizedIds.some((workspaceId) => workspaceIds.has(workspaceId))) return void 0;
|
|
884
|
+
groupIds.add(id);
|
|
885
|
+
groupTitles.add(title.toLocaleLowerCase());
|
|
886
|
+
normalizedIds.forEach((workspaceId) => workspaceIds.add(workspaceId));
|
|
887
|
+
groups.push({
|
|
888
|
+
id,
|
|
889
|
+
title,
|
|
890
|
+
workspaceIds: normalizedIds
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
return groups;
|
|
894
|
+
}
|
|
895
|
+
/** 新建空分组;项目只有被显式移动后才会进入其中。 */
|
|
896
|
+
function createWorkspaceGroup(groups, group) {
|
|
897
|
+
const next = parseWorkspaceGroups([...groups, {
|
|
898
|
+
...group,
|
|
899
|
+
workspaceIds: []
|
|
900
|
+
}]);
|
|
901
|
+
if (next === void 0) throw new WorkspaceGroupError("group-invalid");
|
|
902
|
+
return next;
|
|
903
|
+
}
|
|
904
|
+
/** 将项目放入指定分组;未传分组时退回未分组区。 */
|
|
905
|
+
function assignWorkspaceToGroup(groups, workspaceId, groupId) {
|
|
906
|
+
if (workspaceId.trim() === "" || workspaceId.length > 256) throw new WorkspaceGroupError("workspace-invalid");
|
|
907
|
+
if (groupId !== void 0 && !groups.some((group) => group.id === groupId)) throw new WorkspaceGroupError("group-missing");
|
|
908
|
+
return groups.map((group) => ({
|
|
909
|
+
...group,
|
|
910
|
+
workspaceIds: group.id === groupId ? [...group.workspaceIds.filter((id) => id !== workspaceId), workspaceId] : group.workspaceIds.filter((id) => id !== workspaceId)
|
|
911
|
+
}));
|
|
912
|
+
}
|
|
913
|
+
/** 将项目插入目标分组的指定位置,同时从原分组移除。 */
|
|
914
|
+
function placeWorkspaceInGroup(groups, workspaceId, groupId, beforeId) {
|
|
915
|
+
if (workspaceId.trim() === "" || workspaceId.length > 256) throw new WorkspaceGroupError("workspace-invalid");
|
|
916
|
+
const target = groups.find((group) => group.id === groupId);
|
|
917
|
+
if (target === void 0) throw new WorkspaceGroupError("group-missing");
|
|
918
|
+
const targetIds = target.workspaceIds.filter((id) => id !== workspaceId);
|
|
919
|
+
const index = beforeId === void 0 ? targetIds.length : targetIds.indexOf(beforeId);
|
|
920
|
+
if (index < 0) throw new WorkspaceGroupError("order-anchor-missing");
|
|
921
|
+
targetIds.splice(index, 0, workspaceId);
|
|
922
|
+
return groups.map((group) => ({
|
|
923
|
+
...group,
|
|
924
|
+
workspaceIds: group.id === groupId ? targetIds : group.workspaceIds.filter((id) => id !== workspaceId)
|
|
925
|
+
}));
|
|
926
|
+
}
|
|
927
|
+
/** 在同一分组内移动项目;省略锚点时放到分组末尾。 */
|
|
928
|
+
function moveWorkspaceGroupMember(groups, workspaceId, groupId, beforeId) {
|
|
929
|
+
const target = groups.find((group) => group.id === groupId);
|
|
930
|
+
if (target === void 0) throw new WorkspaceGroupError("group-missing");
|
|
931
|
+
if (!target.workspaceIds.includes(workspaceId)) return groups.map((group) => ({
|
|
932
|
+
...group,
|
|
933
|
+
workspaceIds: [...group.workspaceIds]
|
|
934
|
+
}));
|
|
935
|
+
const remaining = target.workspaceIds.filter((id) => id !== workspaceId);
|
|
936
|
+
const index = beforeId === void 0 ? remaining.length : remaining.indexOf(beforeId);
|
|
937
|
+
if (index < 0) throw new WorkspaceGroupError("order-anchor-missing");
|
|
938
|
+
const workspaceIds = [...remaining];
|
|
939
|
+
workspaceIds.splice(index, 0, workspaceId);
|
|
940
|
+
return groups.map((group) => group.id === groupId ? {
|
|
941
|
+
...group,
|
|
942
|
+
workspaceIds
|
|
943
|
+
} : {
|
|
944
|
+
...group,
|
|
945
|
+
workspaceIds: [...group.workspaceIds]
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
/** 调整自定义分组顺序;省略锚点时移动到所有自定义分组末尾。 */
|
|
949
|
+
function moveWorkspaceGroup(groups, groupId, beforeGroupId) {
|
|
950
|
+
const moved = groups.find((group) => group.id === groupId);
|
|
951
|
+
if (moved === void 0) throw new WorkspaceGroupError("group-missing");
|
|
952
|
+
if (beforeGroupId === groupId) return groups.map((group) => ({
|
|
953
|
+
...group,
|
|
954
|
+
workspaceIds: [...group.workspaceIds]
|
|
955
|
+
}));
|
|
956
|
+
const remaining = groups.filter((group) => group.id !== groupId);
|
|
957
|
+
const index = beforeGroupId === void 0 ? remaining.length : remaining.findIndex((group) => group.id === beforeGroupId);
|
|
958
|
+
if (index < 0) throw new WorkspaceGroupError("order-anchor-missing");
|
|
959
|
+
remaining.splice(index, 0, moved);
|
|
960
|
+
return remaining.map((group) => ({
|
|
961
|
+
...group,
|
|
962
|
+
workspaceIds: [...group.workspaceIds]
|
|
963
|
+
}));
|
|
964
|
+
}
|
|
965
|
+
/** 删除分组时仅解除归属,不影响工作区本身。 */
|
|
966
|
+
function deleteWorkspaceGroup(groups, groupId) {
|
|
967
|
+
return groups.filter((group) => group.id !== groupId).map((group) => ({
|
|
968
|
+
...group,
|
|
969
|
+
workspaceIds: [...group.workspaceIds]
|
|
970
|
+
}));
|
|
971
|
+
}
|
|
972
|
+
/** 工作区清单变化后清理失效归属,但保留空分组供用户继续使用。 */
|
|
973
|
+
function pruneWorkspaceGroups(groups, validIds) {
|
|
974
|
+
const valid = new Set(validIds);
|
|
975
|
+
return groups.map((group) => ({
|
|
976
|
+
...group,
|
|
977
|
+
workspaceIds: group.workspaceIds.filter((id) => valid.has(id))
|
|
978
|
+
}));
|
|
979
|
+
}
|
|
980
|
+
function groupedWorkspaceIds(groups) {
|
|
981
|
+
return groups.flatMap((group) => group.workspaceIds);
|
|
982
|
+
}
|
|
673
983
|
//#endregion
|
|
674
984
|
//#region src/client/pinned-workspaces.ts
|
|
675
|
-
/**
|
|
985
|
+
/** 浏览器本地持久化键;用于工作区偏好的首帧恢复与 Host 故障兜底。 */
|
|
676
986
|
const PINNED_WORKSPACES_STORAGE_KEY = "dsh-codex-ui.pinned-workspace-ids";
|
|
987
|
+
const WORKSPACE_GROUPS_STORAGE_KEY = "dsh-codex-ui.workspace-groups.v1";
|
|
677
988
|
const WORKSPACE_PREFERENCES_ENDPOINT = "/api/michengai/codex-ui/preferences";
|
|
678
989
|
/** 清理无效或重复的工作区标识。 */
|
|
679
990
|
function normalizePinnedWorkspaceIds(ids) {
|
|
@@ -685,23 +996,29 @@ window.__ModuleLoader__.load({
|
|
|
685
996
|
const next = ids.filter((id) => valid.has(id));
|
|
686
997
|
return next.length === ids.length ? [...ids] : next;
|
|
687
998
|
}
|
|
688
|
-
/** Host
|
|
689
|
-
function
|
|
690
|
-
if (
|
|
691
|
-
|
|
999
|
+
/** Host 数据优先;旧 Host 或待同步分组使用本地缓存,读取期间的用户操作始终优先。 */
|
|
1000
|
+
function resolveWorkspacePreferencesHydration(local, host, dirty, localWorkspaceGroupsPendingHostSync = false) {
|
|
1001
|
+
if (dirty !== void 0) return {
|
|
1002
|
+
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(dirty.pinnedWorkspaceIds),
|
|
1003
|
+
workspaceGroups: dirty.workspaceGroups,
|
|
692
1004
|
writeHost: true
|
|
693
1005
|
};
|
|
694
|
-
if (host.exists)
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
1006
|
+
if (host.exists) {
|
|
1007
|
+
const preserveLocalGroups = host.workspaceGroupsSupported === false || localWorkspaceGroupsPendingHostSync;
|
|
1008
|
+
return {
|
|
1009
|
+
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(host.pinnedWorkspaceIds),
|
|
1010
|
+
workspaceGroups: preserveLocalGroups ? local.workspaceGroups : host.workspaceGroups,
|
|
1011
|
+
writeHost: localWorkspaceGroupsPendingHostSync && host.workspaceGroupsSupported !== false
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
const pinnedWorkspaceIds = normalizePinnedWorkspaceIds(local.pinnedWorkspaceIds);
|
|
699
1015
|
return {
|
|
700
|
-
|
|
701
|
-
|
|
1016
|
+
pinnedWorkspaceIds,
|
|
1017
|
+
workspaceGroups: local.workspaceGroups,
|
|
1018
|
+
writeHost: pinnedWorkspaceIds.length > 0 || local.workspaceGroups.length > 0
|
|
702
1019
|
};
|
|
703
1020
|
}
|
|
704
|
-
async function
|
|
1021
|
+
async function readHostWorkspacePreferences(fetcher = fetch) {
|
|
705
1022
|
const response = await fetcher(WORKSPACE_PREFERENCES_ENDPOINT, {
|
|
706
1023
|
method: "GET",
|
|
707
1024
|
cache: "no-store",
|
|
@@ -711,22 +1028,35 @@ window.__ModuleLoader__.load({
|
|
|
711
1028
|
const payload = await response.json();
|
|
712
1029
|
if (payload === null || typeof payload !== "object") throw new Error("置顶偏好响应格式无效。");
|
|
713
1030
|
const record = payload;
|
|
714
|
-
|
|
1031
|
+
const workspaceGroupsSupported = Object.prototype.hasOwnProperty.call(record, "workspaceGroups");
|
|
1032
|
+
const workspaceGroups = workspaceGroupsSupported ? parseWorkspaceGroups(record.workspaceGroups) : [];
|
|
1033
|
+
if (typeof record.exists !== "boolean" || !Array.isArray(record.pinnedWorkspaceIds) || !record.pinnedWorkspaceIds.every((id) => typeof id === "string") || workspaceGroups === void 0) throw new Error("置顶偏好响应格式无效。");
|
|
715
1034
|
return {
|
|
716
1035
|
exists: record.exists,
|
|
717
|
-
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(record.pinnedWorkspaceIds)
|
|
1036
|
+
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(record.pinnedWorkspaceIds),
|
|
1037
|
+
workspaceGroups,
|
|
1038
|
+
workspaceGroupsSupported
|
|
718
1039
|
};
|
|
719
1040
|
}
|
|
720
|
-
async function
|
|
1041
|
+
async function writeHostWorkspacePreferences(pinnedWorkspaceIds, workspaceGroups, fetcher = fetch) {
|
|
1042
|
+
const groups = parseWorkspaceGroups([...workspaceGroups]);
|
|
1043
|
+
if (groups === void 0) throw new Error("工作区分组数据无效。");
|
|
721
1044
|
const response = await fetcher(WORKSPACE_PREFERENCES_ENDPOINT, {
|
|
722
1045
|
method: "PUT",
|
|
723
1046
|
cache: "no-store",
|
|
724
1047
|
headers: { "content-type": "application/json" },
|
|
725
|
-
body: JSON.stringify({
|
|
1048
|
+
body: JSON.stringify({
|
|
1049
|
+
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(pinnedWorkspaceIds),
|
|
1050
|
+
workspaceGroups: groups
|
|
1051
|
+
}),
|
|
726
1052
|
signal: AbortSignal.timeout(5e3)
|
|
727
1053
|
});
|
|
728
1054
|
if (!response.ok) throw new Error(`保存置顶偏好失败:HTTP ${response.status}`);
|
|
729
1055
|
}
|
|
1056
|
+
/** 兼容旧调用方;新代码应同时写入分组。 */
|
|
1057
|
+
async function readHostPinnedWorkspaceIds(fetcher = fetch) {
|
|
1058
|
+
return readHostWorkspacePreferences(fetcher);
|
|
1059
|
+
}
|
|
730
1060
|
/** 在置顶列表中切换一个工作区。 */
|
|
731
1061
|
/** 把工作区插入置顶列表的指定位置;省略锚点时追加到末尾。 */
|
|
732
1062
|
function insertPinnedWorkspace(ids, id, beforeId) {
|
|
@@ -757,6 +1087,80 @@ window.__ModuleLoader__.load({
|
|
|
757
1087
|
storage.setItem(PINNED_WORKSPACES_STORAGE_KEY, JSON.stringify(normalizePinnedWorkspaceIds(ids)));
|
|
758
1088
|
} catch {}
|
|
759
1089
|
}
|
|
1090
|
+
/** 分组缓存用于首帧恢复和 Host 暂时不可用时兜底,并记录尚未完成的 Host 迁移。 */
|
|
1091
|
+
function readWorkspaceGroupsCache(storage) {
|
|
1092
|
+
if (storage === void 0) return {
|
|
1093
|
+
workspaceGroups: [],
|
|
1094
|
+
pendingHostSync: false
|
|
1095
|
+
};
|
|
1096
|
+
try {
|
|
1097
|
+
const value = JSON.parse(storage.getItem("dsh-codex-ui.workspace-groups.v1") ?? "{\"version\":1,\"workspaceGroups\":[],\"pendingHostSync\":false}");
|
|
1098
|
+
if (value === null || typeof value !== "object") return {
|
|
1099
|
+
workspaceGroups: [],
|
|
1100
|
+
pendingHostSync: false
|
|
1101
|
+
};
|
|
1102
|
+
const record = value;
|
|
1103
|
+
const workspaceGroups = record.version === 1 ? parseWorkspaceGroups(record.workspaceGroups) : void 0;
|
|
1104
|
+
if (workspaceGroups === void 0 || typeof record.pendingHostSync !== "boolean") return {
|
|
1105
|
+
workspaceGroups: [],
|
|
1106
|
+
pendingHostSync: false
|
|
1107
|
+
};
|
|
1108
|
+
return {
|
|
1109
|
+
workspaceGroups,
|
|
1110
|
+
pendingHostSync: record.pendingHostSync
|
|
1111
|
+
};
|
|
1112
|
+
} catch {
|
|
1113
|
+
return {
|
|
1114
|
+
workspaceGroups: [],
|
|
1115
|
+
pendingHostSync: false
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
function saveWorkspaceGroupsCache(storage, groups, pendingHostSync) {
|
|
1120
|
+
if (storage === void 0) return;
|
|
1121
|
+
const workspaceGroups = parseWorkspaceGroups([...groups]);
|
|
1122
|
+
if (workspaceGroups === void 0) return;
|
|
1123
|
+
try {
|
|
1124
|
+
storage.setItem(WORKSPACE_GROUPS_STORAGE_KEY, JSON.stringify({
|
|
1125
|
+
version: 1,
|
|
1126
|
+
workspaceGroups,
|
|
1127
|
+
pendingHostSync
|
|
1128
|
+
}));
|
|
1129
|
+
} catch {}
|
|
1130
|
+
}
|
|
1131
|
+
//#endregion
|
|
1132
|
+
//#region src/client/session-manager.ts
|
|
1133
|
+
const SESSION_UNREAD_STORAGE_KEY = "dsh.session-unread.v1";
|
|
1134
|
+
function normalizeSessionIds(ids) {
|
|
1135
|
+
return [...new Set(ids.filter((id) => id.trim() !== ""))];
|
|
1136
|
+
}
|
|
1137
|
+
function toggleSessionId(ids, sessionId) {
|
|
1138
|
+
return ids.includes(sessionId) ? ids.filter((id) => id !== sessionId) : [sessionId, ...ids.filter((id) => id !== sessionId)];
|
|
1139
|
+
}
|
|
1140
|
+
/** 返回本次刷新中结束、且不在当前会话中的后台会话。 */
|
|
1141
|
+
function completedBackgroundSessionIds(previous, current, currentSessionId) {
|
|
1142
|
+
return Object.entries(current).flatMap(([id, running]) => previous[id] === true && running !== true && id !== currentSessionId ? [id] : []);
|
|
1143
|
+
}
|
|
1144
|
+
function readSessionIds(storage, key) {
|
|
1145
|
+
if (storage === void 0) return [];
|
|
1146
|
+
try {
|
|
1147
|
+
const value = JSON.parse(storage.getItem(key) ?? "{\"version\":1,\"ids\":[]}");
|
|
1148
|
+
if (value === null || typeof value !== "object") return [];
|
|
1149
|
+
const ids = value.ids;
|
|
1150
|
+
return Array.isArray(ids) && ids.every((id) => typeof id === "string") ? normalizeSessionIds(ids) : [];
|
|
1151
|
+
} catch {
|
|
1152
|
+
return [];
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
function writeSessionIds(storage, key, ids) {
|
|
1156
|
+
if (storage === void 0) return;
|
|
1157
|
+
try {
|
|
1158
|
+
storage.setItem(key, JSON.stringify({
|
|
1159
|
+
version: 1,
|
|
1160
|
+
ids: normalizeSessionIds(ids)
|
|
1161
|
+
}));
|
|
1162
|
+
} catch {}
|
|
1163
|
+
}
|
|
760
1164
|
//#endregion
|
|
761
1165
|
//#region src/client/hover-tip.ts
|
|
762
1166
|
/** 把悬停卡片限制在视口内,避免贴边裁切。 */
|
|
@@ -775,12 +1179,12 @@ window.__ModuleLoader__.load({
|
|
|
775
1179
|
};
|
|
776
1180
|
}
|
|
777
1181
|
/** Codex 会话卡片右上角的紧凑相对时间。 */
|
|
778
|
-
function formatHoverTime(updatedAt, now = Date.now()) {
|
|
1182
|
+
function formatHoverTime(updatedAt, t, now = Date.now()) {
|
|
779
1183
|
const seconds = Math.max(0, Math.round((now - updatedAt) / 1e3));
|
|
780
|
-
if (seconds < 60) return "
|
|
781
|
-
if (seconds < 3600) return
|
|
782
|
-
if (seconds < 86400) return
|
|
783
|
-
return
|
|
1184
|
+
if (seconds < 60) return t("time.justNow");
|
|
1185
|
+
if (seconds < 3600) return t("time.minutes", { count: Math.floor(seconds / 60) });
|
|
1186
|
+
if (seconds < 86400) return t("time.hours", { count: Math.floor(seconds / 3600) });
|
|
1187
|
+
return t("time.days", { count: Math.floor(seconds / 86400) });
|
|
784
1188
|
}
|
|
785
1189
|
//#endregion
|
|
786
1190
|
//#region src/client/conversation-bubbles.ts
|
|
@@ -1023,6 +1427,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1023
1427
|
//#endregion
|
|
1024
1428
|
//#region src/client/hover-shell.tsx
|
|
1025
1429
|
const HOVER_TIP_SHOW_DELAY_MS = 1e3;
|
|
1430
|
+
const WORKSPACE_HOVER_CARD_ESTIMATED_HEIGHT = 152;
|
|
1026
1431
|
const HoverDispatchContext = (0, react.createContext)({
|
|
1027
1432
|
showTip: () => {},
|
|
1028
1433
|
hideTip: () => {},
|
|
@@ -1043,7 +1448,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1043
1448
|
tipRef.current = hoverTip;
|
|
1044
1449
|
const place = (tip) => ({
|
|
1045
1450
|
...tip,
|
|
1046
|
-
...clampHoverCardPosition(tip.left, tip.top, 248, 148, window.innerWidth, window.innerHeight)
|
|
1451
|
+
...clampHoverCardPosition(tip.left, tip.top, tip.kind === "workspace" ? 316 : 248, tip.kind === "workspace" ? WORKSPACE_HOVER_CARD_ESTIMATED_HEIGHT : 148, window.innerWidth, window.innerHeight)
|
|
1047
1452
|
});
|
|
1048
1453
|
const dispatch = (0, react.useMemo)(() => ({
|
|
1049
1454
|
showTip: (tip, options) => {
|
|
@@ -1121,7 +1526,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1121
1526
|
//#endregion
|
|
1122
1527
|
//#region src/client/workspace-hover-card.tsx
|
|
1123
1528
|
/** 只订阅悬停值,避免工作区树随鼠标移动整树重绘。 */
|
|
1124
|
-
function WorkspaceHoverCard({ t, onEditWorkspace }) {
|
|
1529
|
+
function WorkspaceHoverCard({ t, onEditWorkspace, onToggleWorkspacePin }) {
|
|
1125
1530
|
const hoverTip = useHoverValue();
|
|
1126
1531
|
const { keepTip, hideTip, dismissTip } = useHoverDispatch();
|
|
1127
1532
|
(0, react.useEffect)(() => {
|
|
@@ -1138,8 +1543,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1138
1543
|
};
|
|
1139
1544
|
}, [hoverTip, dismissTip]);
|
|
1140
1545
|
if (hoverTip === void 0) return null;
|
|
1546
|
+
const workspace = hoverTip.kind === "workspace";
|
|
1547
|
+
const workspaceId = workspace ? hoverTip.id : void 0;
|
|
1548
|
+
const taskSummary = hoverTip.unreadCount !== void 0 && hoverTip.unreadCount > 0 ? t("workspace.taskSummary", {
|
|
1549
|
+
count: hoverTip.count ?? 0,
|
|
1550
|
+
unreadCount: hoverTip.unreadCount
|
|
1551
|
+
}) : t("workspace.taskCount", { count: hoverTip.count ?? 0 });
|
|
1141
1552
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1142
|
-
className: "dcu-wb-tip"
|
|
1553
|
+
className: `dcu-wb-tip${workspace ? " dcu-wb-tip-workspace" : ""}`,
|
|
1143
1554
|
style: {
|
|
1144
1555
|
left: hoverTip.left,
|
|
1145
1556
|
top: hoverTip.top
|
|
@@ -1150,59 +1561,69 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1150
1561
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1151
1562
|
className: "dcu-wb-tip-title",
|
|
1152
1563
|
children: [
|
|
1153
|
-
|
|
1564
|
+
workspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1154
1565
|
className: "dcu-wb-folder",
|
|
1155
1566
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
1156
1567
|
}),
|
|
1157
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1158
|
-
|
|
1568
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1569
|
+
className: "dcu-wb-tip-title-main",
|
|
1570
|
+
children: hoverTip.title
|
|
1571
|
+
}),
|
|
1572
|
+
workspaceId !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1573
|
+
type: "button",
|
|
1574
|
+
className: "dcu-wb-tip-pin",
|
|
1575
|
+
"aria-label": t(hoverTip.pinned === true ? "workspace.unpin" : "workspace.pin"),
|
|
1576
|
+
onClick: () => {
|
|
1577
|
+
onToggleWorkspacePin(workspaceId);
|
|
1578
|
+
dismissTip();
|
|
1579
|
+
},
|
|
1580
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinIcon, {})
|
|
1581
|
+
}) : hoverTip.time !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1159
1582
|
className: "dcu-wb-tip-time",
|
|
1160
1583
|
children: hoverTip.time
|
|
1161
1584
|
})
|
|
1162
1585
|
]
|
|
1163
1586
|
}),
|
|
1164
|
-
|
|
1587
|
+
workspace && hoverTip.count !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1165
1588
|
className: "dcu-wb-tip-meta",
|
|
1166
|
-
children:
|
|
1589
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessageCircle, {
|
|
1590
|
+
"aria-hidden": "true",
|
|
1591
|
+
size: 16,
|
|
1592
|
+
strokeWidth: 1.5
|
|
1593
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: taskSummary })]
|
|
1167
1594
|
}),
|
|
1168
|
-
|
|
1169
|
-
className: "dcu-wb-tip-row",
|
|
1595
|
+
workspace && hoverTip.path !== void 0 && hoverTip.path !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1596
|
+
className: "dcu-wb-tip-row dcu-wb-tip-path",
|
|
1170
1597
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1171
1598
|
className: "dcu-wb-folder",
|
|
1172
1599
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
1173
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1600
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1601
|
+
className: "dcu-wb-tip-path-copy",
|
|
1602
|
+
children: hoverTip.path
|
|
1603
|
+
})]
|
|
1174
1604
|
}),
|
|
1175
|
-
|
|
1605
|
+
!workspace && hoverTip.project !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1176
1606
|
className: "dcu-wb-tip-row",
|
|
1177
1607
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1178
1608
|
className: "dcu-wb-folder",
|
|
1179
1609
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
1180
1610
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: hoverTip.project })]
|
|
1181
1611
|
}),
|
|
1182
|
-
|
|
1612
|
+
!workspace && hoverTip.branch !== void 0 && hoverTip.branch !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1183
1613
|
className: "dcu-wb-tip-row",
|
|
1184
1614
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1185
1615
|
className: "dcu-wb-folder",
|
|
1186
1616
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 })
|
|
1187
1617
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: hoverTip.branch })]
|
|
1188
1618
|
}),
|
|
1189
|
-
|
|
1619
|
+
workspaceId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "dcu-wb-tip-sep" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1190
1620
|
type: "button",
|
|
1191
1621
|
className: "dcu-wb-tip-edit",
|
|
1192
1622
|
onClick: () => {
|
|
1193
|
-
onEditWorkspace(
|
|
1623
|
+
onEditWorkspace(workspaceId, hoverTip.title);
|
|
1194
1624
|
dismissTip();
|
|
1195
1625
|
},
|
|
1196
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1197
|
-
viewBox: "0 0 16 16",
|
|
1198
|
-
width: 16,
|
|
1199
|
-
height: 16,
|
|
1200
|
-
"aria-hidden": "true",
|
|
1201
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1202
|
-
fill: "currentColor",
|
|
1203
|
-
d: "M8 1.4A6.6 6.6 0 1 0 8 14.6 6.6 6.6 0 0 0 8 1.4Zm0 1.4a5.2 5.2 0 1 1 0 10.4A5.2 5.2 0 0 1 8 2.8Zm-.7 2.3h1.4v3.05l2.2 1.3-.7 1.18L7.3 9.1V5.1Z"
|
|
1204
|
-
})
|
|
1205
|
-
}), t("workspace.edit")]
|
|
1626
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), t("workspace.edit")]
|
|
1206
1627
|
})] })
|
|
1207
1628
|
]
|
|
1208
1629
|
});
|
|
@@ -1218,7 +1639,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1218
1639
|
return name !== void 0 && name !== "" ? name : title.trim();
|
|
1219
1640
|
}
|
|
1220
1641
|
/** 把定时运行会话按任务名收成和任务树一样的分组。 */
|
|
1221
|
-
function groupScheduleSessions(items) {
|
|
1642
|
+
function groupScheduleSessions(items, locale = "zh-CN") {
|
|
1222
1643
|
const groups = /* @__PURE__ */ new Map();
|
|
1223
1644
|
for (const item of items) {
|
|
1224
1645
|
if (!isScheduleSession(item.id, item.title)) continue;
|
|
@@ -1234,7 +1655,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1234
1655
|
return [...groups.values()].map((group) => ({
|
|
1235
1656
|
...group,
|
|
1236
1657
|
sessions: [...group.sessions].sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))
|
|
1237
|
-
})).sort((left, right) => left.label.localeCompare(right.label,
|
|
1658
|
+
})).sort((left, right) => left.label.localeCompare(right.label, locale, {
|
|
1238
1659
|
numeric: true,
|
|
1239
1660
|
sensitivity: "base"
|
|
1240
1661
|
}));
|
|
@@ -1303,10 +1724,39 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1303
1724
|
return item === void 0 ? [] : [item];
|
|
1304
1725
|
});
|
|
1305
1726
|
}
|
|
1727
|
+
/** 展开移动目标的全部父级,保证页面重载并选中会话后该行仍然可见。 */
|
|
1728
|
+
function expandedForSessionMove(current, target) {
|
|
1729
|
+
const next = { ...current };
|
|
1730
|
+
if (target.pinned) {
|
|
1731
|
+
next["section:pinned"] = true;
|
|
1732
|
+
next[`pin:${target.workspaceId}`] = true;
|
|
1733
|
+
return next;
|
|
1734
|
+
}
|
|
1735
|
+
next["section:projects"] = true;
|
|
1736
|
+
next[target.workspaceId] = true;
|
|
1737
|
+
if (target.groupId !== void 0) next[`workspace-group:${target.groupId}`] = true;
|
|
1738
|
+
else if (target.hasGroups) next["workspace-group:ungrouped"] = true;
|
|
1739
|
+
return next;
|
|
1740
|
+
}
|
|
1741
|
+
/** 仅提供真正改变归属的目标;未分组目标固定排在自定义分组之后。 */
|
|
1742
|
+
function workspaceGroupMoveTargets(groups, workspaceId) {
|
|
1743
|
+
const currentGroupId = groups.find((group) => group.workspaceIds.includes(workspaceId))?.id;
|
|
1744
|
+
const targets = groups.filter((group) => group.id !== currentGroupId).map((group) => ({
|
|
1745
|
+
groupId: group.id,
|
|
1746
|
+
title: group.title
|
|
1747
|
+
}));
|
|
1748
|
+
if (currentGroupId !== void 0) targets.push({
|
|
1749
|
+
groupId: void 0,
|
|
1750
|
+
title: void 0
|
|
1751
|
+
});
|
|
1752
|
+
return targets;
|
|
1753
|
+
}
|
|
1306
1754
|
const SESSION_DRAG_TYPE = "application/x-dcu-session";
|
|
1307
1755
|
const WORKSPACE_DRAG_TYPE = "application/x-dcu-workspace";
|
|
1756
|
+
const WORKSPACE_GROUP_DRAG_TYPE = "application/x-dcu-workspace-group";
|
|
1308
1757
|
const SESSION_DRAG_PREFIX = "dcu-session:";
|
|
1309
1758
|
const WORKSPACE_DRAG_PREFIX = "dcu-workspace:";
|
|
1759
|
+
const WORKSPACE_GROUP_DRAG_PREFIX = "dcu-workspace-group:";
|
|
1310
1760
|
function textPayload(data) {
|
|
1311
1761
|
try {
|
|
1312
1762
|
return data?.getData("text/plain") ?? "";
|
|
@@ -1325,6 +1775,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1325
1775
|
data.setData("text/plain", `${WORKSPACE_DRAG_PREFIX}${workspaceId}`);
|
|
1326
1776
|
data.setData(WORKSPACE_DRAG_TYPE, workspaceId);
|
|
1327
1777
|
}
|
|
1778
|
+
function writeWorkspaceGroupDrag(data, groupId, title) {
|
|
1779
|
+
data.effectAllowed = "move";
|
|
1780
|
+
data.setData("text/plain", `${WORKSPACE_GROUP_DRAG_PREFIX}${groupId}`);
|
|
1781
|
+
data.setData(WORKSPACE_GROUP_DRAG_TYPE, groupId);
|
|
1782
|
+
}
|
|
1328
1783
|
function readSessionDrag(data, fallback) {
|
|
1329
1784
|
try {
|
|
1330
1785
|
const typed = data?.getData(SESSION_DRAG_TYPE);
|
|
@@ -1334,9 +1789,23 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1334
1789
|
if (text.startsWith(SESSION_DRAG_PREFIX)) return text.slice(12);
|
|
1335
1790
|
return fallback !== void 0 && fallback.trim() !== "" ? fallback : void 0;
|
|
1336
1791
|
}
|
|
1792
|
+
function sessionDropAction(sourceWorkspaceId, targetWorkspaceId) {
|
|
1793
|
+
return sourceWorkspaceId !== void 0 && sourceWorkspaceId === targetWorkspaceId ? "reorder" : "move";
|
|
1794
|
+
}
|
|
1795
|
+
function readWorkspaceGroupDrag(data, fallback) {
|
|
1796
|
+
if (readSessionDrag(data) !== void 0) return void 0;
|
|
1797
|
+
try {
|
|
1798
|
+
const typed = data?.getData(WORKSPACE_GROUP_DRAG_TYPE);
|
|
1799
|
+
if (typed !== void 0 && typed.trim() !== "") return typed;
|
|
1800
|
+
} catch {}
|
|
1801
|
+
const text = textPayload(data);
|
|
1802
|
+
if (text.startsWith(WORKSPACE_GROUP_DRAG_PREFIX)) return text.slice(20);
|
|
1803
|
+
return fallback !== void 0 && fallback.trim() !== "" ? fallback : void 0;
|
|
1804
|
+
}
|
|
1337
1805
|
/** 会话拖拽优先;有会话载荷时不得再把父项目置顶。 */
|
|
1338
1806
|
function readWorkspaceDrag(data, fallback) {
|
|
1339
1807
|
if (readSessionDrag(data) !== void 0) return void 0;
|
|
1808
|
+
if (readWorkspaceGroupDrag(data) !== void 0) return void 0;
|
|
1340
1809
|
try {
|
|
1341
1810
|
const typed = data?.getData(WORKSPACE_DRAG_TYPE);
|
|
1342
1811
|
if (typed !== void 0 && typed.trim() !== "") return typed;
|
|
@@ -1380,60 +1849,364 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1380
1849
|
} catch {}
|
|
1381
1850
|
}
|
|
1382
1851
|
//#endregion
|
|
1383
|
-
//#region src/client/
|
|
1384
|
-
|
|
1385
|
-
.
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
.
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
.
|
|
1394
|
-
|
|
1395
|
-
.
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
.
|
|
1399
|
-
|
|
1400
|
-
.
|
|
1401
|
-
|
|
1402
|
-
.
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
.
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1852
|
+
//#region src/client/workspace-compat.ts
|
|
1853
|
+
function hasStartSession(value) {
|
|
1854
|
+
return value !== null && typeof value === "object" && "startSession" in value && typeof value.startSession === "function";
|
|
1855
|
+
}
|
|
1856
|
+
function hasConnectWorkspace(value) {
|
|
1857
|
+
return value !== null && typeof value === "object" && "connectWorkspace" in value && typeof value.connectWorkspace === "function";
|
|
1858
|
+
}
|
|
1859
|
+
/** 与 DSH 官方最近工作区策略一致;时间相同时保留 Host 工作区顺序。 */
|
|
1860
|
+
function recentWorkspaceId(workspaces, sessions) {
|
|
1861
|
+
let selected;
|
|
1862
|
+
let selectedTime = Number.NEGATIVE_INFINITY;
|
|
1863
|
+
for (const workspace of workspaces) {
|
|
1864
|
+
let latest = Number.NEGATIVE_INFINITY;
|
|
1865
|
+
for (const sessionId of workspace.sessionIds) {
|
|
1866
|
+
const session = sessions[sessionId];
|
|
1867
|
+
if (session !== void 0) latest = Math.max(latest, session.updatedAt);
|
|
1868
|
+
}
|
|
1869
|
+
if (latest === Number.NEGATIVE_INFINITY) latest = Date.parse(workspace.createdAt);
|
|
1870
|
+
if (selected === void 0 || latest > selectedTime) {
|
|
1871
|
+
selected = workspace.workspaceId;
|
|
1872
|
+
selectedTime = latest;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
return selected;
|
|
1876
|
+
}
|
|
1877
|
+
/** 旧版提供聚合字段;alpha.5 起由工作区和会话两个 Store 分别报告基线阶段。 */
|
|
1878
|
+
function workspaceBaselinesReady(workspaces, sessions) {
|
|
1879
|
+
if ("baselinesReady" in workspaces) return workspaces.baselinesReady === true;
|
|
1880
|
+
return "phase" in workspaces && workspaces.phase === "ready" && "phase" in sessions && sessions.phase === "ready";
|
|
1881
|
+
}
|
|
1882
|
+
//#endregion
|
|
1883
|
+
//#region src/client/user-error.ts
|
|
1884
|
+
const WORKSPACE_GROUP_ERROR_KEYS = {
|
|
1885
|
+
"group-invalid": "errors.groupInvalid",
|
|
1886
|
+
"workspace-invalid": "errors.workspaceInvalid",
|
|
1887
|
+
"group-missing": "errors.groupMissing",
|
|
1888
|
+
"order-anchor-missing": "errors.orderAnchorMissing"
|
|
1889
|
+
};
|
|
1890
|
+
const HOST_ACTION_DEFAULT_KEYS = {
|
|
1891
|
+
rename: "sessions.renameFailed",
|
|
1892
|
+
delete: "sessions.deleteFailed",
|
|
1893
|
+
archive: "sessions.archiveFailed",
|
|
1894
|
+
fork: "sessions.forkFailed"
|
|
1895
|
+
};
|
|
1896
|
+
const HOST_ACTION_ERROR_KEYS = {
|
|
1897
|
+
rename: {
|
|
1898
|
+
"session/not-found": "sessions.unknown",
|
|
1899
|
+
"session/title-invalid": "sessions.renameInvalid"
|
|
1900
|
+
},
|
|
1901
|
+
delete: { "session/not-found": "sessions.unknown" },
|
|
1902
|
+
archive: { "session/not-found": "sessions.unknown" },
|
|
1903
|
+
fork: {
|
|
1904
|
+
"session/not-found": "sessions.unknown",
|
|
1905
|
+
"session/fork-unavailable": "sessions.forkUnavailable"
|
|
1906
|
+
}
|
|
1907
|
+
};
|
|
1908
|
+
const INSTALL_ERROR_KEYS = [
|
|
1909
|
+
[/没有进入当前 Profile|did not enter this profile/i, "about.installUnchanged"],
|
|
1910
|
+
[/完全退出桌面端|无法覆盖正在运行的插件文件|running plugin files|quit DSH Desktop/i, "about.installExitDesktop"],
|
|
1911
|
+
[/pnpm 仓库不一致|pnpm store do not match/i, "about.installStoreMismatch"],
|
|
1912
|
+
[/构建脚本策略|build-script policy/i, "about.installBuildPolicy"],
|
|
1913
|
+
[/找不到 pnpm|pnpm (?:is )?not (?:available|found)/i, "about.installPnpmMissing"],
|
|
1914
|
+
[/安装超时|installation timed out/i, "about.installTimeout"],
|
|
1915
|
+
[/服务尚未就绪|Profile 信息无效|dependency service is not ready/i, "about.installServiceUnavailable"]
|
|
1916
|
+
];
|
|
1917
|
+
/** 仅显式构造的本地化错误允许原样进入界面。 */
|
|
1918
|
+
var UserFacingError = class extends Error {};
|
|
1919
|
+
/** 保留 Host 结构化失败及操作语境,界面只消费受控映射。 */
|
|
1920
|
+
var HostActionError = class extends Error {
|
|
1921
|
+
action;
|
|
1922
|
+
reason;
|
|
1923
|
+
name = "HostActionError";
|
|
1924
|
+
constructor(action, reason) {
|
|
1925
|
+
super(`Host ${action} 操作失败`);
|
|
1926
|
+
this.action = action;
|
|
1927
|
+
this.reason = reason;
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
function objectRecord(value) {
|
|
1931
|
+
return value !== null && typeof value === "object" ? value : void 0;
|
|
1932
|
+
}
|
|
1933
|
+
/** DSH 明确要求跨 bundle 按结构标记识别 RemoteFailure,不能使用 instanceof。 */
|
|
1934
|
+
function remoteFailureCode(value) {
|
|
1935
|
+
const record = objectRecord(value);
|
|
1936
|
+
if (record === void 0) return void 0;
|
|
1937
|
+
if (record.isDSHRemoteError === true && typeof record.code === "string") return record.code;
|
|
1938
|
+
return record.rpcError === value ? void 0 : remoteFailureCode(record.rpcError);
|
|
1939
|
+
}
|
|
1940
|
+
function diagnosticMessage(value) {
|
|
1941
|
+
if (value instanceof Error) return value.message;
|
|
1942
|
+
const record = objectRecord(value);
|
|
1943
|
+
return typeof record?.message === "string" ? record.message : void 0;
|
|
1944
|
+
}
|
|
1945
|
+
function hostActionErrorKey(error) {
|
|
1946
|
+
const code = remoteFailureCode(error.reason);
|
|
1947
|
+
if (code !== void 0) {
|
|
1948
|
+
const key = HOST_ACTION_ERROR_KEYS[error.action][code];
|
|
1949
|
+
if (key !== void 0) return key;
|
|
1950
|
+
}
|
|
1951
|
+
if (error.action === "delete" && diagnosticMessage(error.reason)?.includes("UNKNOWN_SESSION") === true) return "sessions.unknown";
|
|
1952
|
+
return HOST_ACTION_DEFAULT_KEYS[error.action];
|
|
1953
|
+
}
|
|
1954
|
+
/** 将业务错误映射为当前语言,未知底层错误统一脱敏。 */
|
|
1955
|
+
function userErrorText(error, t) {
|
|
1956
|
+
if (error instanceof UserFacingError) return error.message;
|
|
1957
|
+
if (error instanceof WorkspaceGroupError) return t(WORKSPACE_GROUP_ERROR_KEYS[error.code]);
|
|
1958
|
+
if (error instanceof HostActionError) return t(hostActionErrorKey(error));
|
|
1959
|
+
return t("errors.generic");
|
|
1960
|
+
}
|
|
1961
|
+
/** 安装错误保留用户可执行的处理建议,但不直接展示 Host 原文。 */
|
|
1962
|
+
function installErrorText(error, t) {
|
|
1963
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1964
|
+
return t(INSTALL_ERROR_KEYS.find(([pattern]) => pattern.test(message))?.[1] ?? "about.installFailed");
|
|
1965
|
+
}
|
|
1966
|
+
//#endregion
|
|
1967
|
+
//#region src/client/session-move.ts
|
|
1968
|
+
const SESSION_MOVE_ENDPOINT = "/api/michengai/codex-ui/session-move";
|
|
1969
|
+
const MOVE_ACTION_PREFIX = "move-session:";
|
|
1970
|
+
const SESSION_MOVE_ERROR_KEYS = {
|
|
1971
|
+
"session-move/unavailable": "sessions.moveUnavailable",
|
|
1972
|
+
"session-move/service-unavailable": "sessions.moveUnavailable",
|
|
1973
|
+
"session-move/session-not-found": "sessions.moveNotFound",
|
|
1974
|
+
"session-move/workspace-not-found": "sessions.moveNotFound",
|
|
1975
|
+
"session-move/subagent-unsupported": "sessions.moveSubagent",
|
|
1976
|
+
"session-move/busy": "sessions.moveBusy",
|
|
1977
|
+
"session-move/rollback-failed": "sessions.moveRollbackFailed"
|
|
1978
|
+
};
|
|
1979
|
+
var SessionMoveRequestError = class extends Error {
|
|
1980
|
+
code;
|
|
1981
|
+
constructor(code) {
|
|
1982
|
+
super(code);
|
|
1983
|
+
this.code = code;
|
|
1984
|
+
this.name = "SessionMoveRequestError";
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
/** 将 Host 公开错误码映射为受控 i18n 键,未知错误统一使用安全兜底。 */
|
|
1988
|
+
function sessionMoveErrorKey(code) {
|
|
1989
|
+
return SESSION_MOVE_ERROR_KEYS[code] ?? "sessions.moveFailed";
|
|
1990
|
+
}
|
|
1991
|
+
function moveSessionActionId(workspaceId) {
|
|
1992
|
+
return `${MOVE_ACTION_PREFIX}${encodeURIComponent(workspaceId)}`;
|
|
1993
|
+
}
|
|
1994
|
+
function parseMoveSessionActionId(actionId) {
|
|
1995
|
+
if (!actionId.startsWith(MOVE_ACTION_PREFIX)) return void 0;
|
|
1996
|
+
try {
|
|
1997
|
+
const workspaceId = decodeURIComponent(actionId.slice(13));
|
|
1998
|
+
return workspaceId === "" ? void 0 : workspaceId;
|
|
1999
|
+
} catch {
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
/** 按 Host 项目顺序生成目标列表,并排除会话当前所属项目。 */
|
|
2004
|
+
function sessionMoveTargets(workspaces, sessionId) {
|
|
2005
|
+
return workspaces.filter((workspace) => !workspace.sessionIds.includes(sessionId)).map((workspace) => ({
|
|
2006
|
+
id: workspace.workspaceId,
|
|
2007
|
+
label: workspace.title || workspace.workspaceId
|
|
2008
|
+
}));
|
|
2009
|
+
}
|
|
2010
|
+
async function requestSessionMove(sessionId, targetWorkspaceId, fetcher = fetch) {
|
|
2011
|
+
let response;
|
|
2012
|
+
try {
|
|
2013
|
+
response = await fetcher(SESSION_MOVE_ENDPOINT, {
|
|
2014
|
+
method: "POST",
|
|
2015
|
+
cache: "no-store",
|
|
2016
|
+
headers: { "content-type": "application/json" },
|
|
2017
|
+
body: JSON.stringify({
|
|
2018
|
+
sessionId,
|
|
2019
|
+
targetWorkspaceId
|
|
2020
|
+
}),
|
|
2021
|
+
signal: AbortSignal.timeout(3e4)
|
|
2022
|
+
});
|
|
2023
|
+
} catch {
|
|
2024
|
+
throw new SessionMoveRequestError("session-move/unavailable");
|
|
2025
|
+
}
|
|
2026
|
+
let payload;
|
|
2027
|
+
try {
|
|
2028
|
+
payload = await response.json();
|
|
2029
|
+
} catch {
|
|
2030
|
+
throw new SessionMoveRequestError("session-move/unavailable");
|
|
2031
|
+
}
|
|
2032
|
+
const code = payload !== null && typeof payload === "object" && typeof payload.code === "string" ? payload.code : void 0;
|
|
2033
|
+
if (!response.ok || payload === null || typeof payload !== "object" || payload.ok !== true) throw new SessionMoveRequestError(code ?? "session-move/failed");
|
|
2034
|
+
}
|
|
2035
|
+
/** 通过现有深链入口选中移动后的会话,同时用页面重建清除 DSH 保留的只读会话对象。 */
|
|
2036
|
+
function finishSessionMove({ sessionId, currentUrl, navigate }) {
|
|
2037
|
+
const targetUrl = new URL(currentUrl);
|
|
2038
|
+
targetUrl.searchParams.set("session", sessionId);
|
|
2039
|
+
navigate(targetUrl.toString());
|
|
2040
|
+
}
|
|
2041
|
+
//#endregion
|
|
2042
|
+
//#region src/client/workspace-archive.ts
|
|
2043
|
+
/** 按项目顺序归档会话;失败后停止,交由调用方显示并允许用户重试。 */
|
|
2044
|
+
async function archiveWorkspaceSessions(sessionIds, archiveSession) {
|
|
2045
|
+
for (const sessionId of new Set(sessionIds)) await archiveSession(sessionId);
|
|
2046
|
+
}
|
|
2047
|
+
//#endregion
|
|
2048
|
+
//#region src/client/CodexWorkspaceBrowser.tsx
|
|
2049
|
+
const DISCLOSURE_EXIT_MS = 180;
|
|
2050
|
+
function NewSessionIcon() {
|
|
2051
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SquarePen, {
|
|
2052
|
+
"aria-hidden": "true",
|
|
2053
|
+
size: 16,
|
|
2054
|
+
strokeWidth: 1.5
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
/** 使用独立节点生成稳定的拖拽预览,避免浏览器把目标高亮和操作按钮截入默认快照。 */
|
|
2058
|
+
function setDragPreview(dataTransfer, title, icon) {
|
|
2059
|
+
const preview = document.createElement("div");
|
|
2060
|
+
preview.className = "dcu-wb-drag-ghost";
|
|
2061
|
+
if (icon !== void 0 && icon !== null) {
|
|
2062
|
+
const previewIcon = icon.cloneNode(true);
|
|
2063
|
+
previewIcon.className = "dcu-wb-drag-ghost-icon";
|
|
2064
|
+
previewIcon.setAttribute("aria-hidden", "true");
|
|
2065
|
+
preview.appendChild(previewIcon);
|
|
2066
|
+
}
|
|
2067
|
+
const previewTitle = document.createElement("span");
|
|
2068
|
+
previewTitle.className = "dcu-wb-drag-ghost-title";
|
|
2069
|
+
previewTitle.textContent = title.split(/\r?\n/)[0] ?? title;
|
|
2070
|
+
preview.appendChild(previewTitle);
|
|
2071
|
+
document.body.appendChild(preview);
|
|
2072
|
+
preview.offsetWidth;
|
|
2073
|
+
dataTransfer.setDragImage(preview, 16, 15);
|
|
2074
|
+
window.requestAnimationFrame(() => {
|
|
2075
|
+
preview.remove();
|
|
2076
|
+
});
|
|
2077
|
+
}
|
|
2078
|
+
function animateDisclosure(body, wasOpen, open) {
|
|
2079
|
+
if (wasOpen === open || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return void 0;
|
|
2080
|
+
const height = `${body.scrollHeight}px`;
|
|
2081
|
+
const from = wasOpen ? {
|
|
2082
|
+
height,
|
|
2083
|
+
opacity: 1,
|
|
2084
|
+
transform: "translateY(0)"
|
|
2085
|
+
} : {
|
|
2086
|
+
height: "0px",
|
|
2087
|
+
opacity: 0,
|
|
2088
|
+
transform: "translateY(-2px)"
|
|
2089
|
+
};
|
|
2090
|
+
const to = open ? {
|
|
2091
|
+
height,
|
|
2092
|
+
opacity: 1,
|
|
2093
|
+
transform: "translateY(0)"
|
|
2094
|
+
} : {
|
|
2095
|
+
height: "0px",
|
|
2096
|
+
opacity: 0,
|
|
2097
|
+
transform: "translateY(-2px)"
|
|
2098
|
+
};
|
|
2099
|
+
return body.animate([from, to], {
|
|
2100
|
+
duration: DISCLOSURE_EXIT_MS,
|
|
2101
|
+
easing: "cubic-bezier(.16, 1, .3, 1)",
|
|
2102
|
+
fill: "none"
|
|
2103
|
+
});
|
|
2104
|
+
}
|
|
2105
|
+
/** 所有可折叠层级使用同一套原生高度动画,兼容宿主内核对 auto 高度过渡的差异。 */
|
|
2106
|
+
function DisclosureBody({ className, children, open }) {
|
|
2107
|
+
const bodyRef = (0, react.useRef)(null);
|
|
2108
|
+
const previousOpen = (0, react.useRef)(open);
|
|
2109
|
+
(0, react.useLayoutEffect)(() => {
|
|
2110
|
+
const body = bodyRef.current;
|
|
2111
|
+
if (body === null) return;
|
|
2112
|
+
body.inert = !open;
|
|
2113
|
+
const animation = animateDisclosure(body, previousOpen.current, open);
|
|
2114
|
+
previousOpen.current = open;
|
|
2115
|
+
return () => {
|
|
2116
|
+
animation?.cancel();
|
|
2117
|
+
};
|
|
2118
|
+
}, [open]);
|
|
2119
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2120
|
+
ref: bodyRef,
|
|
2121
|
+
className,
|
|
2122
|
+
"data-open": open,
|
|
2123
|
+
"aria-hidden": !open,
|
|
2124
|
+
children
|
|
2125
|
+
});
|
|
2126
|
+
}
|
|
2127
|
+
/** 顶层分区使用已有结构,通过统一监听器复用与项目、分组一致的原生动画。 */
|
|
2128
|
+
function useSectionDisclosureMotion(rootRef) {
|
|
2129
|
+
const previousOpen = (0, react.useRef)(/* @__PURE__ */ new WeakMap());
|
|
2130
|
+
(0, react.useLayoutEffect)(() => {
|
|
2131
|
+
const bodies = rootRef.current?.querySelectorAll(".dcu-wb-section-body") ?? [];
|
|
2132
|
+
for (const body of bodies) {
|
|
2133
|
+
const open = body.dataset.open === "true";
|
|
2134
|
+
const previous = previousOpen.current.get(body);
|
|
2135
|
+
previousOpen.current.set(body, open);
|
|
2136
|
+
body.inert = !open;
|
|
2137
|
+
if (previous !== void 0) animateDisclosure(body, previous, open);
|
|
2138
|
+
}
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
function sameWorkspaceDropTarget(left, right) {
|
|
2142
|
+
if (left === void 0 || right === void 0) return left === right;
|
|
2143
|
+
if (left.zone !== right.zone) return false;
|
|
2144
|
+
if (left.zone === "group" && right.zone === "group") return left.groupId === right.groupId && left.beforeId === right.beforeId && left.ontoGroup === right.ontoGroup && left.crossGroup === right.crossGroup;
|
|
2145
|
+
if (left.zone === "ungrouped" && right.zone === "ungrouped") return left.beforeId === right.beforeId && left.ontoSection === right.ontoSection && left.crossGroup === right.crossGroup;
|
|
2146
|
+
return "beforeId" in left && "beforeId" in right && left.beforeId === right.beforeId;
|
|
2147
|
+
}
|
|
2148
|
+
function sameWorkspaceGroups(left, right) {
|
|
2149
|
+
return left.length === right.length && left.every((group, index) => group.id === right[index]?.id && group.title === right[index]?.title && sameIds(group.workspaceIds, right[index]?.workspaceIds ?? []));
|
|
2150
|
+
}
|
|
2151
|
+
function newWorkspaceGroupId() {
|
|
2152
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return `group-${crypto.randomUUID()}`;
|
|
2153
|
+
return `group-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
2154
|
+
}
|
|
2155
|
+
function workspaceGroupMoveActionId(groupId) {
|
|
2156
|
+
return `moveWorkspaceToGroup:${groupId ?? ""}`;
|
|
2157
|
+
}
|
|
2158
|
+
const stylesheet$4 = `
|
|
2159
|
+
.dcu-wb{--dcu-wb-inset:8px;display:flex;flex:1;min-height:0;flex-direction:column;padding:4px var(--dcu-wb-inset) 8px;color:var(--dcu-sidebar-primary)}
|
|
2160
|
+
.dcu-wb *{box-sizing:border-box}
|
|
2161
|
+
.dcu-wb-tree{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;padding-bottom:16px;scrollbar-gutter:auto;user-select:none;-webkit-user-select:none}
|
|
2162
|
+
.dcu-wb-section+.dcu-wb-section{margin-top:12px}
|
|
2163
|
+
.dcu-wb-section-head{position:relative;display:flex;align-items:center;min-height:24px;padding:0;border-radius:6px}.dcu-wb-section-head:hover .dcu-wb-actions{display:flex}.dcu-wb-section-label{position:relative;display:flex;align-items:center;gap:4px;flex:1;min-width:0;min-height:24px;border:0;padding:2px 4px 2px 12px;background:transparent;color:var(--dcu-sidebar-tertiary);font:13px/20px var(--dcu-font,inherit);font-weight:400;letter-spacing:0;text-align:left;cursor:pointer}.dcu-wb-section-caret{display:grid;place-items:center;flex:none;width:12px;height:12px;color:currentColor;opacity:0;transform:rotate(0deg);transform-origin:50% 50%;transition:opacity 120ms ease,transform 160ms ease}.dcu-wb-section-head .dcu-wb-section-caret{position:absolute;left:0;top:6px}.dcu-wb-section-caret svg{display:block}.dcu-wb-section-head:hover .dcu-wb-section-caret,.dcu-wb-section-label:focus-visible .dcu-wb-section-caret{opacity:.78}.dcu-wb-section-label[aria-expanded=true] .dcu-wb-section-caret{transform:rotate(90deg)}.dcu-wb-section-body{display:block}.dcu-wb-section-body[data-open=false]{display:none}.dcu-wb-section-body>div{min-height:0}.dcu-wb-section-body[data-open=true]>div{animation:dcu-wb-section-in 140ms cubic-bezier(.16,1,.3,1)}@keyframes dcu-wb-section-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}@media (prefers-reduced-motion:reduce){.dcu-wb-section-caret{transition:none}.dcu-wb-section-body[data-open=true]>div{animation:none}}
|
|
2164
|
+
.dcu-wb-project{position:relative;min-width:0}
|
|
2165
|
+
.dcu-wb-collections{display:grid;min-width:0;gap:4px}.dcu-wb-collection,.dcu-wb-ungrouped{position:relative;min-width:0;overflow:visible}.dcu-wb-collection-head{display:flex;align-items:center;min-height:28px;padding:0 4px;border-radius:6px;transition:background 120ms ease}.dcu-wb-collection-head:hover,.dcu-wb-collection-head:focus-within,.dcu-wb-collection-head.dcu-wb-group-drop{background:var(--dcu-sidebar-hover)}.dcu-wb-collection-head.dcu-wb-group-drop{outline:1px solid var(--dsw-alias-state-business-primary)}.dcu-wb-collection-head[draggable=true],.dcu-wb-collection-head[draggable=true] .dcu-wb-collection-label{cursor:grab}.dcu-wb-collection-head[draggable=true]:active,.dcu-wb-collection-head[draggable=true]:active .dcu-wb-collection-label{cursor:grabbing}.dcu-wb-collection-label{display:flex;align-items:center;gap:5px;min-width:0;flex:1;border:0;padding:4px;background:transparent;color:var(--dcu-sidebar-primary);font:13px/20px var(--dcu-font,inherit);text-align:left;cursor:pointer}.dcu-wb-collection-label .dcu-wb-section-caret{position:static;order:-1;opacity:.78}.dcu-wb-collection-label[aria-expanded=true] .dcu-wb-section-caret{transform:rotate(90deg)}.dcu-wb-collection-count{margin-left:auto;color:var(--dcu-sidebar-secondary);font-variant-numeric:tabular-nums}.dcu-wb-collection-body{position:relative;min-width:0;padding-left:12px}.dcu-wb-collection-body::before{content:"";position:absolute;left:31px;top:0;bottom:8px;width:1px;background:var(--dcu-sidebar-border)}.dcu-wb-group-member{position:relative}.dcu-wb-group-member.dcu-wb-drop::before,.dcu-wb-collection.dcu-wb-group-order-drop::before,.dcu-wb-ungrouped.dcu-wb-group-order-drop::before{content:"";position:absolute;z-index:2;left:7px;right:8px;top:-8px;height:8px;pointer-events:none;background:radial-gradient(circle at 4px 50%,transparent 1.75px,var(--dsw-alias-state-business-primary) 2px 3.75px,transparent 4px),linear-gradient(var(--dsw-alias-state-business-primary),var(--dsw-alias-state-business-primary)) 10px 50%/calc(100% - 10px) 2px no-repeat}.dcu-wb-group-member.dcu-wb-drop-after::before{top:auto;bottom:-8px}.dcu-wb-collection-body .dcu-wb-project-head{padding-left:12px}
|
|
2166
|
+
.dcu-wb-collection.dcu-wb-workspace-move-drop,.dcu-wb-ungrouped.dcu-wb-workspace-move-drop{border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 9%,transparent);outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}
|
|
2167
|
+
.dcu-wb-project-head,.dcu-wb-session{position:relative;display:flex;align-items:center;gap:6px;width:100%;min-width:0;border-radius:10px;padding:0 8px;color:var(--dcu-sidebar-primary);cursor:pointer}
|
|
2168
|
+
.dcu-wb-collection-body::before{left:calc(4px + 4px + 6px)}
|
|
2169
|
+
.dcu-wb-project-head{height:30px;background:transparent;font:inherit;text-align:left}
|
|
2170
|
+
.dcu-wb-project-head:hover,.dcu-wb-project-head.dcu-wb-menu-open,.dcu-wb-session:hover,.dcu-wb-session.dcu-wb-selected,.dcu-wb-session.dcu-wb-menu-open{background:var(--dcu-sidebar-hover)}.dcu-wb-project.dcu-wb-session-drop>.dcu-wb-project-head{border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 9%,transparent);outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}.dcu-wb-project.dcu-wb-session-move-drop{border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 9%,transparent);outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}.dcu-wb-project.dcu-wb-session-move-drop>.dcu-wb-project-head{background:transparent;outline:0}.dcu-wb-project-body>.dcu-wb-session:first-child,.dcu-wb-project-body>.dcu-wb-nochat:first-child{margin-top:4px}.dcu-wb-session+.dcu-wb-session{margin-top:2px}
|
|
2171
|
+
.dcu-wb-project-head[draggable=true],.dcu-wb-session[draggable=true]{cursor:grab}
|
|
2172
|
+
.dcu-wb-project-head[draggable=true]:active,.dcu-wb-session[draggable=true]:active{cursor:grabbing}
|
|
2173
|
+
.dcu-wb-section,.dcu-wb-section:focus,.dcu-wb-section:focus-visible,.dcu-wb-project-head:focus,.dcu-wb-session:focus{outline:0}.dcu-wb-pin-end,.dcu-wb-pin-start{position:relative;height:8px}.dcu-wb-project.dcu-wb-drop::before,.dcu-wb-session.dcu-wb-drop::before,.dcu-wb-pin-end.dcu-wb-drop::before,.dcu-wb-pin-start.dcu-wb-drop::before{content:"";position:absolute;z-index:2;left:7px;right:8px;top:-8px;height:8px;pointer-events:none;background:radial-gradient(circle at 4px 50%,transparent 1.75px,var(--dsw-alias-state-business-primary) 2px 3.75px,transparent 4px),linear-gradient(var(--dsw-alias-state-business-primary),var(--dsw-alias-state-business-primary)) 10px 50%/calc(100% - 10px) 2px no-repeat}.dcu-wb-pin-start.dcu-wb-drop::before{top:0}.dcu-wb-pinned-list>.dcu-wb-project:first-child.dcu-wb-drop::before{top:-4px}.dcu-wb-project.dcu-wb-drop-after::before,.dcu-wb-session.dcu-wb-drop-after::before{top:auto;bottom:-8px}.dcu-wb-dragging{opacity:.28}.dcu-wb-drag-ghost{position:fixed;top:0;left:0;transform:translate(-200vw,-200vh);z-index:10040;display:flex;align-items:center;gap:8px;max-width:220px;height:30px;padding:0 10px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;background:var(--dcu-sidebar-hover);box-shadow:0 4px 12px rgba(0,0,0,.24);color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font,inherit);white-space:nowrap;pointer-events:none}.dcu-wb-drag-ghost-icon{display:grid;place-items:center;flex:none;width:16px;height:16px;color:var(--dcu-sidebar-icon)}.dcu-wb-drag-ghost-icon svg{display:block;width:16px;height:16px}.dcu-wb-drag-ghost-title{min-width:0;overflow:hidden;text-overflow:ellipsis}
|
|
2174
|
+
.dcu-wb-folder{display:grid;place-items:center;flex:none;width:16px;height:20px;color:var(--dcu-sidebar-icon)}.dcu-wb-brand{display:block;width:16px;height:16px}
|
|
2175
|
+
.dcu-wb-project-title,.dcu-wb-session-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px}
|
|
2176
|
+
.dcu-wb-project-title{flex:1;font-weight:400;color:var(--dcu-sidebar-primary)}
|
|
2177
|
+
.dcu-wb-session{position:relative;min-width:0;min-height:30px;gap:0;overflow:hidden;padding-left:28px;padding-right:28px}
|
|
2178
|
+
.dcu-wb-session-title{flex:1;margin-left:0}.dcu-wb-session-copy{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center}.dcu-wb-session-sub{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dcu-sidebar-tertiary);font-size:12px;line-height:16px}.dcu-wb-session-flat,.dcu-wb-session-top{padding-left:8px}
|
|
2179
|
+
.dcu-wb-actions{display:none;align-items:center;gap:8px;flex:none}
|
|
2180
|
+
.dcu-wb-quick-actions{position:absolute;right:8px;top:50%;display:flex;align-items:center;gap:2px;opacity:0;pointer-events:none;transform:translateY(-50%);background:var(--dcu-sidebar-hover);border-radius:6px}
|
|
2181
|
+
.dcu-wb-project-head:hover .dcu-wb-actions,.dcu-wb-project-head.dcu-wb-menu-open .dcu-wb-actions,.dcu-wb-session.dcu-wb-menu-open .dcu-wb-actions{display:flex}
|
|
2182
|
+
.dcu-wb-session:hover .dcu-wb-quick-actions,.dcu-wb-session.dcu-wb-menu-open .dcu-wb-quick-actions{opacity:1;pointer-events:auto}.dcu-wb-session:hover .dcu-wb-running,.dcu-wb-session.dcu-wb-menu-open .dcu-wb-running,.dcu-wb-session:hover .dcu-wb-pending,.dcu-wb-session.dcu-wb-menu-open .dcu-wb-pending,.dcu-wb-session:hover .dcu-wb-unread,.dcu-wb-session.dcu-wb-menu-open .dcu-wb-unread{visibility:hidden}
|
|
2183
|
+
.dcu-wb-more{display:grid;place-items:center;width:20px;height:20px;border:0;border-radius:4px;padding:0;background:transparent;color:var(--dcu-sidebar-tertiary);cursor:pointer}
|
|
2184
|
+
.dcu-wb-more:hover{color:var(--dcu-sidebar-primary)}
|
|
2185
|
+
.dcu-wb-context-anchor{opacity:0;pointer-events:none}
|
|
2186
|
+
.dcu-wb-tip{position:fixed;z-index:10050;min-width:220px;max-width:280px;padding:10px 12px;border:1px solid var(--dcu-sidebar-border);border-radius:12px;background:var(--dcu-tip-bg,#fff);box-shadow:var(--dcu-tip-shadow,0 8px 28px rgba(31,39,36,.16));color:var(--dcu-sidebar-primary);animation:dcu-tip-in 180ms cubic-bezier(.16,1,.3,1)}.dcu-wb-tip-workspace{width:316px;min-width:0;max-width:calc(100vw - 16px);padding:10px 8px 8px}@keyframes dcu-tip-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}@media (prefers-reduced-motion:reduce){.dcu-wb-tip{animation:none}}.dcu-wb-tip-title{display:flex;align-items:center;gap:6px;min-width:0;min-height:20px;font-size:14px;line-height:20px;font-weight:500}.dcu-wb-tip-title-main{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-wb-tip-time{flex:none;margin-left:auto;color:var(--dcu-sidebar-tertiary);font-size:12px;line-height:18px;font-weight:400}.dcu-wb-tip-pin{display:grid;place-items:center;flex:none;width:20px;height:20px;border:0;border-radius:4px;padding:0;background:transparent;color:var(--dcu-sidebar-tertiary);cursor:pointer}.dcu-wb-tip-pin:hover{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary)}.dcu-wb-tip-meta,.dcu-wb-tip-row{display:flex;align-items:center;gap:6px;min-width:0;margin-top:4px;color:var(--dcu-sidebar-secondary);font-size:14px;line-height:20px}.dcu-wb-tip-meta svg,.dcu-wb-tip-row svg{flex:none}.dcu-wb-tip-row>span:not(.dcu-wb-folder){min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-wb-tip-path{align-items:flex-start;margin-top:8px}.dcu-wb-tip-path-copy{min-width:0;overflow-wrap:anywhere;white-space:normal}.dcu-wb-tip-sep{height:1px;margin:8px 0 4px;background:var(--dcu-sidebar-border)}.dcu-wb-tip-edit{display:flex;align-items:center;gap:6px;width:100%;min-height:24px;border:0;padding:2px 0;background:transparent;color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font,inherit);text-align:left;cursor:pointer}.dcu-wb-tip-edit svg{flex:none;color:var(--dcu-sidebar-secondary)}
|
|
2187
|
+
.dcu-wb-session:has(.dcu-wb-pending){padding-right:112px}.dcu-wb-unread{position:absolute;right:13px;top:50%;width:7px;height:7px;margin:-3.5px 0 0;border-radius:50%;background:var(--dsw-alias-state-business-primary)}
|
|
2188
|
+
.dcu-wb-pending{position:absolute;right:10px;top:50%;display:flex;align-items:center;gap:4px;max-width:88px;margin:0;transform:translateY(-50%);color:var(--dsw-alias-state-warn-label,#b45309);font-size:11px;line-height:16px;white-space:nowrap}.dcu-wb-pending-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-state-warn-primary,#f59e0b)}.dcu-wb-pending-label{min-width:0;overflow:hidden;text-overflow:ellipsis}
|
|
2189
|
+
.dcu-wb-empty{padding:14px 8px;color:var(--dcu-sidebar-tertiary);font-size:13px}
|
|
2190
|
+
.dcu-wb-error{margin:4px 0;padding:6px 8px;border-radius:6px;background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary);font-size:12px}
|
|
2191
|
+
.dcu-wb-rail{display:none}
|
|
2192
|
+
.dcu-wb-rename-actions{display:flex;justify-content:flex-end;gap:8px}
|
|
2193
|
+
.dcu-wb-delete-button{color:var(--dsw-alias-state-error-primary)!important}
|
|
2194
|
+
.dcu-wb-delete-copy{margin:0;color:var(--dcu-sidebar-secondary);font-size:13px;line-height:20px}
|
|
2195
|
+
.dcu-wb-move-target{display:flex;min-width:0;align-items:center;gap:8px;margin-top:4px;color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font,inherit)}.dcu-wb-move-target svg{flex:none;color:var(--dcu-sidebar-secondary)}.dcu-wb-move-target-copy{min-width:0}.dcu-wb-move-project,.dcu-wb-move-path{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-wb-move-path{color:var(--dcu-sidebar-tertiary);font-size:12px}
|
|
1421
2196
|
.dcu-wb-rename-input{box-sizing:border-box;width:100%;height:36px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:7px 10px;outline:0;background:var(--dsw-alias-background-secondary);color:var(--dsw-alias-label-primary);font:14px/20px var(--dsw-font-family,inherit);caret-color:var(--dsw-alias-state-business-primary);transition:border-color 120ms ease,box-shadow 120ms ease}
|
|
1422
2197
|
.dcu-wb-rename-input:hover{border-color:color-mix(in srgb,var(--dsw-alias-label-primary) 32%,var(--dsw-alias-border-l2))}
|
|
1423
2198
|
.dcu-wb-rename-input:focus{border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 1px color-mix(in srgb,var(--dsw-alias-state-business-primary) 28%,transparent)}
|
|
1424
2199
|
`;
|
|
1425
|
-
const runningStyles = `.dcu-wb-running{flex:none;width:12px;height:12px;border:2px solid color-mix(in srgb,var(--dcu-sidebar-secondary) 25%,transparent);border-top-color:var(--dcu-sidebar-secondary);border-radius:50%;animation:dcu-wb-spin .8s linear infinite}@keyframes dcu-wb-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.dcu-wb-running{animation:none}}`;
|
|
1426
|
-
const typographyStyles = `.dcu-wb{font:14px/20px var(--dcu-font,var(--dsw-font-family))}.dcu-wb-section-label{color:var(--dcu-sidebar-
|
|
1427
|
-
const
|
|
2200
|
+
const runningStyles = `.dcu-wb-running{position:absolute;right:10px;top:50%;flex:none;width:12px;height:12px;margin-top:-6px;border:2px solid color-mix(in srgb,var(--dcu-sidebar-secondary) 25%,transparent);border-top-color:var(--dcu-sidebar-secondary);border-radius:50%;animation:dcu-wb-spin .8s linear infinite}@keyframes dcu-wb-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.dcu-wb-running{animation:none}}`;
|
|
2201
|
+
const typographyStyles = `.dcu-wb{--dcu-wb-disclosure-duration:180ms;--dcu-wb-disclosure-ease:cubic-bezier(.16,1,.3,1);font:14px/20px var(--dcu-font,var(--dsw-font-family))}.dcu-wb-section-label{color:var(--dcu-sidebar-secondary);font:13px/20px var(--dcu-font,var(--dsw-font-family));font-weight:400;letter-spacing:0;padding-left:0}.dcu-wb-section-caret{transition:opacity var(--dcu-wb-disclosure-duration) var(--dcu-wb-disclosure-ease),transform var(--dcu-wb-disclosure-duration) var(--dcu-wb-disclosure-ease)}.dcu-wb-section-head .dcu-wb-section-caret{position:static;left:auto;top:auto;opacity:.78}.dcu-wb-section-body,.dcu-wb-project-body,.dcu-wb-collection-body{display:block;min-height:0;height:auto;overflow:clip;opacity:1;transform:none;visibility:visible}.dcu-wb-section-body[data-open=false],.dcu-wb-project-body[data-open=false],.dcu-wb-collection-body[data-open=false]{display:block;height:0;opacity:0;transform:translateY(-2px);pointer-events:none}.dcu-wb-section-body[data-open=true]:has(.dcu-wb-drop),.dcu-wb-project-body[data-open=true]:has(.dcu-wb-drop),.dcu-wb-collection-body[data-open=true]:has(.dcu-wb-drop){overflow:visible}.dcu-wb-section-body[data-open=true]>div{animation:none}@media (prefers-reduced-motion:reduce){.dcu-wb-section-caret{transition:none}}.dcu-wb-project-title{font-size:14px;line-height:20px;font-weight:400;color:var(--dcu-sidebar-primary)}.dcu-wb-session-title{font-size:14px;line-height:20px;font-weight:400;color:var(--dcu-sidebar-secondary)}.dcu-wb-session.dcu-wb-selected .dcu-wb-session-title,.dcu-wb-session:hover .dcu-wb-session-title{color:var(--dcu-sidebar-primary)}.dcu-wb-empty{color:var(--dcu-sidebar-tertiary);font-size:13px;line-height:18px}.dcu-wb-nochat{padding:0 8px 4px 28px;color:var(--dcu-sidebar-tertiary);font-size:14px;line-height:20px}`;
|
|
2202
|
+
const collectionLayoutStyles = `.dcu-wb-collection-body{padding-left:0}.dcu-wb-collection-body .dcu-wb-project-head{padding-left:8px}.dcu-wb-collection-body::before,.dcu-wb-group-member::after{display:none}.dcu-wb-collection-head,.dcu-wb-collection-head:focus-within{background:color-mix(in srgb,var(--dcu-sidebar-hover) 28%,transparent)}.dcu-wb-collection-head:hover{background:var(--dcu-sidebar-hover)}.dcu-wb-collection-head.dcu-wb-group-drop{background:var(--dcu-sidebar-hover)}.dcu-wb-workspace-move-drop>.dcu-wb-collection-head{background:transparent}`;
|
|
2203
|
+
const WORKSPACE_TREE_STYLE = stylesheet$4 + runningStyles + typographyStyles + collectionLayoutStyles;
|
|
1428
2204
|
function storage$1() {
|
|
1429
2205
|
return browserStorage();
|
|
1430
2206
|
}
|
|
1431
2207
|
function sameIds(left, right) {
|
|
1432
2208
|
return left.length === right.length && left.every((id, index) => id === right[index]);
|
|
1433
2209
|
}
|
|
1434
|
-
function browserBase() {
|
|
1435
|
-
return typeof window === "undefined" || window.location.origin === "null" ? "http://dsh.internal/" : `${window.location.origin}/`;
|
|
1436
|
-
}
|
|
1437
2210
|
function optionalText(value, key) {
|
|
1438
2211
|
if (!(key in value)) return void 0;
|
|
1439
2212
|
const next = value[key];
|
|
@@ -1443,14 +2216,21 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1443
2216
|
function CodexWorkspaceBrowser(props) {
|
|
1444
2217
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HoverShell, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexWorkspaceTree, { ...props }) });
|
|
1445
2218
|
}
|
|
1446
|
-
function CodexWorkspaceTree({ wide, useSessions, useSessionPendingInteraction, useWorkspaces, t, archiveSession, deleteSession, deleteWorkspace, forkSession, insertSessionBefore, insertWorkspaceBefore, openPath, openSession, renameSession, renameWorkspace, startSession }) {
|
|
2219
|
+
function CodexWorkspaceTree({ wide, useSessions, useSessionPendingInteraction, useWorkspaces, t, archiveSession, deleteSession, deleteWorkspace, forkSession, insertSessionBefore, insertWorkspaceBefore, moveSession, openPath, openSession, renameSession, renameWorkspace, startSession }) {
|
|
1447
2220
|
const sessions = useSessions((state) => state);
|
|
1448
2221
|
const pendingInteractions = (useSessionPendingInteraction ?? useEmptySessionPendingInteraction)((state) => state);
|
|
1449
2222
|
const workspaces = useWorkspaces((state) => state);
|
|
2223
|
+
const baselinesReady = workspaceBaselinesReady(workspaces, sessions);
|
|
1450
2224
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY));
|
|
1451
2225
|
const [pinnedWorkspaceIds, setPinnedWorkspaceIdsState] = (0, react.useState)(() => readPinnedWorkspaceIds(storage$1()));
|
|
2226
|
+
const initialWorkspaceGroups = (0, react.useMemo)(() => readWorkspaceGroupsCache(storage$1()), []);
|
|
2227
|
+
const [workspaceGroups, setWorkspaceGroupsState] = (0, react.useState)(() => initialWorkspaceGroups.workspaceGroups);
|
|
1452
2228
|
const pinnedWorkspaceIdsRef = (0, react.useRef)(pinnedWorkspaceIds);
|
|
1453
2229
|
pinnedWorkspaceIdsRef.current = pinnedWorkspaceIds;
|
|
2230
|
+
const workspaceGroupsRef = (0, react.useRef)(workspaceGroups);
|
|
2231
|
+
workspaceGroupsRef.current = workspaceGroups;
|
|
2232
|
+
const workspaceGroupsPendingHostSyncRef = (0, react.useRef)(initialWorkspaceGroups.pendingHostSync);
|
|
2233
|
+
const pinnedHostSupportsWorkspaceGroupsRef = (0, react.useRef)(false);
|
|
1454
2234
|
const pinnedHostHydratedRef = (0, react.useRef)(false);
|
|
1455
2235
|
const pinnedHostDirtyRef = (0, react.useRef)(false);
|
|
1456
2236
|
const pinnedHostSkipWriteRef = (0, react.useRef)();
|
|
@@ -1460,12 +2240,24 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1460
2240
|
validIds: []
|
|
1461
2241
|
});
|
|
1462
2242
|
workspaceBaselineRef.current = {
|
|
1463
|
-
ready:
|
|
2243
|
+
ready: baselinesReady,
|
|
1464
2244
|
validIds: workspaces.items.map((workspace) => String(workspace.workspaceId))
|
|
1465
2245
|
};
|
|
1466
|
-
const queuePinnedHostWrite = (ids) => {
|
|
1467
|
-
const snapshot =
|
|
1468
|
-
|
|
2246
|
+
const queuePinnedHostWrite = (ids, groups) => {
|
|
2247
|
+
const snapshot = {
|
|
2248
|
+
pinnedWorkspaceIds: [...ids],
|
|
2249
|
+
workspaceGroups: groups.map((group) => ({
|
|
2250
|
+
...group,
|
|
2251
|
+
workspaceIds: [...group.workspaceIds]
|
|
2252
|
+
}))
|
|
2253
|
+
};
|
|
2254
|
+
const pending = pinnedHostWriteRef.current.then(async () => {
|
|
2255
|
+
await writeHostWorkspacePreferences(snapshot.pinnedWorkspaceIds, snapshot.workspaceGroups);
|
|
2256
|
+
if (!pinnedHostSupportsWorkspaceGroupsRef.current) return;
|
|
2257
|
+
if (!sameIds(pinnedWorkspaceIdsRef.current, snapshot.pinnedWorkspaceIds) || !sameWorkspaceGroups(workspaceGroupsRef.current, snapshot.workspaceGroups)) return;
|
|
2258
|
+
workspaceGroupsPendingHostSyncRef.current = false;
|
|
2259
|
+
saveWorkspaceGroupsCache(storage$1(), snapshot.workspaceGroups, false);
|
|
2260
|
+
});
|
|
1469
2261
|
pinnedHostWriteRef.current = pending.catch(() => void 0);
|
|
1470
2262
|
};
|
|
1471
2263
|
const setPinnedWorkspaceIds = (update) => {
|
|
@@ -1475,11 +2267,21 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1475
2267
|
pinnedWorkspaceIdsRef.current = next;
|
|
1476
2268
|
setPinnedWorkspaceIdsState(next);
|
|
1477
2269
|
};
|
|
1478
|
-
const
|
|
2270
|
+
const setWorkspaceGroups = (update) => {
|
|
2271
|
+
pinnedHostDirtyRef.current = true;
|
|
2272
|
+
workspaceGroupsPendingHostSyncRef.current = true;
|
|
2273
|
+
const current = workspaceGroupsRef.current;
|
|
2274
|
+
const next = typeof update === "function" ? update(current) : update;
|
|
2275
|
+
workspaceGroupsRef.current = next;
|
|
2276
|
+
setWorkspaceGroupsState(next);
|
|
2277
|
+
};
|
|
1479
2278
|
const [unreadSessionIds, setUnreadSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY));
|
|
2279
|
+
const previousSessionRunningRef = (0, react.useRef)();
|
|
1480
2280
|
const [menu, setMenu] = (0, react.useState)();
|
|
1481
2281
|
const [renameTarget, setRenameTarget] = (0, react.useState)();
|
|
1482
2282
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)();
|
|
2283
|
+
const [archiveWorkspaceTarget, setArchiveWorkspaceTarget] = (0, react.useState)();
|
|
2284
|
+
const [sessionMoveTarget, setSessionMoveTarget] = (0, react.useState)();
|
|
1483
2285
|
const { showTip: publishTip, hideTip, dismissTip, isShowing } = useHoverDispatch();
|
|
1484
2286
|
const showTip = (tip, options) => {
|
|
1485
2287
|
if (menu !== void 0) return;
|
|
@@ -1491,8 +2293,17 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1491
2293
|
const [error, setError] = (0, react.useState)();
|
|
1492
2294
|
const [workspaceDragId, setWorkspaceDragId] = (0, react.useState)();
|
|
1493
2295
|
const [workspaceDropTarget, setWorkspaceDropTargetState] = (0, react.useState)();
|
|
2296
|
+
const [workspaceGroupDragId, setWorkspaceGroupDragId] = (0, react.useState)();
|
|
2297
|
+
const [workspaceGroupDropTarget, setWorkspaceGroupDropTargetState] = (0, react.useState)();
|
|
2298
|
+
const setWorkspaceGroupDropTarget = (target) => {
|
|
2299
|
+
setWorkspaceGroupDropTargetState((current) => {
|
|
2300
|
+
if (current === void 0 || target === void 0) return current === target ? current : target;
|
|
2301
|
+
return current.beforeId === target.beforeId ? current : target;
|
|
2302
|
+
});
|
|
2303
|
+
};
|
|
1494
2304
|
const workspaceDropTargetRef = (0, react.useRef)();
|
|
1495
2305
|
const setWorkspaceDropTarget = (target) => {
|
|
2306
|
+
if (sameWorkspaceDropTarget(workspaceDropTargetRef.current, target)) return;
|
|
1496
2307
|
workspaceDropTargetRef.current = target;
|
|
1497
2308
|
setWorkspaceDropTargetState(target);
|
|
1498
2309
|
};
|
|
@@ -1502,75 +2313,108 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1502
2313
|
const headerMenuPointerAt = (0, react.useRef)(0);
|
|
1503
2314
|
const [sessionDrag, setSessionDrag] = (0, react.useState)();
|
|
1504
2315
|
const [sessionDropTarget, setSessionDropTarget] = (0, react.useState)();
|
|
2316
|
+
const [createGroupOpen, setCreateGroupOpen] = (0, react.useState)(false);
|
|
2317
|
+
const [groupTitleDraft, setGroupTitleDraft] = (0, react.useState)("");
|
|
2318
|
+
const [deleteGroupId, setDeleteGroupId] = (0, react.useState)();
|
|
2319
|
+
const [groupMenuOpen, setGroupMenuOpen] = (0, react.useState)(false);
|
|
1505
2320
|
(0, react.useEffect)(() => {
|
|
1506
2321
|
writeTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY, expanded);
|
|
1507
2322
|
}, [expanded]);
|
|
1508
2323
|
(0, react.useEffect)(() => {
|
|
1509
2324
|
savePinnedWorkspaceIds(storage$1(), pinnedWorkspaceIds);
|
|
2325
|
+
saveWorkspaceGroupsCache(storage$1(), workspaceGroups, workspaceGroupsPendingHostSyncRef.current);
|
|
1510
2326
|
if (!pinnedHostHydratedRef.current) return;
|
|
1511
2327
|
const skippedHydration = pinnedHostSkipWriteRef.current;
|
|
1512
2328
|
pinnedHostSkipWriteRef.current = void 0;
|
|
1513
|
-
if (skippedHydration !== void 0 && sameIds(skippedHydration, pinnedWorkspaceIds)) return;
|
|
1514
|
-
queuePinnedHostWrite(pinnedWorkspaceIds);
|
|
1515
|
-
}, [pinnedWorkspaceIds]);
|
|
2329
|
+
if (skippedHydration !== void 0 && sameIds(skippedHydration.pinnedWorkspaceIds, pinnedWorkspaceIds) && sameWorkspaceGroups(skippedHydration.workspaceGroups, workspaceGroups)) return;
|
|
2330
|
+
queuePinnedHostWrite(pinnedWorkspaceIds, workspaceGroups);
|
|
2331
|
+
}, [pinnedWorkspaceIds, workspaceGroups]);
|
|
1516
2332
|
(0, react.useEffect)(() => {
|
|
1517
2333
|
let alive = true;
|
|
1518
|
-
const
|
|
2334
|
+
const local = {
|
|
2335
|
+
pinnedWorkspaceIds: [...pinnedWorkspaceIdsRef.current],
|
|
2336
|
+
workspaceGroups: workspaceGroupsRef.current
|
|
2337
|
+
};
|
|
1519
2338
|
readHostPinnedWorkspaceIds().then((host) => {
|
|
1520
2339
|
if (!alive) return;
|
|
1521
|
-
const
|
|
2340
|
+
const dirty = pinnedHostDirtyRef.current ? {
|
|
2341
|
+
pinnedWorkspaceIds: pinnedWorkspaceIdsRef.current,
|
|
2342
|
+
workspaceGroups: workspaceGroupsRef.current
|
|
2343
|
+
} : void 0;
|
|
2344
|
+
const hydration = resolveWorkspacePreferencesHydration(local, host, dirty, workspaceGroupsPendingHostSyncRef.current);
|
|
1522
2345
|
const baseline = workspaceBaselineRef.current;
|
|
1523
|
-
const ids = baseline.ready ? prunePinnedWorkspaceIds(hydration.
|
|
1524
|
-
const
|
|
2346
|
+
const ids = baseline.ready ? prunePinnedWorkspaceIds(hydration.pinnedWorkspaceIds, baseline.validIds) : hydration.pinnedWorkspaceIds;
|
|
2347
|
+
const groups = baseline.ready ? pruneWorkspaceGroups(hydration.workspaceGroups, baseline.validIds) : hydration.workspaceGroups;
|
|
2348
|
+
const writeHost = hydration.writeHost || !sameIds(ids, hydration.pinnedWorkspaceIds) || !sameWorkspaceGroups(groups, hydration.workspaceGroups);
|
|
2349
|
+
pinnedHostSupportsWorkspaceGroupsRef.current = host.workspaceGroupsSupported !== false;
|
|
2350
|
+
workspaceGroupsPendingHostSyncRef.current = workspaceGroupsPendingHostSyncRef.current || host.workspaceGroupsSupported === false && groups.length > 0 || !host.exists && local.workspaceGroups.length > 0;
|
|
1525
2351
|
pinnedHostHydratedRef.current = true;
|
|
1526
|
-
if (!sameIds(pinnedWorkspaceIdsRef.current, ids)) {
|
|
1527
|
-
pinnedHostSkipWriteRef.current =
|
|
2352
|
+
if (!sameIds(pinnedWorkspaceIdsRef.current, ids) || !sameWorkspaceGroups(workspaceGroupsRef.current, groups)) {
|
|
2353
|
+
pinnedHostSkipWriteRef.current = {
|
|
2354
|
+
pinnedWorkspaceIds: [...ids],
|
|
2355
|
+
workspaceGroups: groups
|
|
2356
|
+
};
|
|
1528
2357
|
pinnedWorkspaceIdsRef.current = ids;
|
|
2358
|
+
workspaceGroupsRef.current = groups;
|
|
1529
2359
|
setPinnedWorkspaceIdsState(ids);
|
|
2360
|
+
setWorkspaceGroupsState(groups);
|
|
1530
2361
|
}
|
|
1531
2362
|
savePinnedWorkspaceIds(storage$1(), ids);
|
|
1532
|
-
if (writeHost) queuePinnedHostWrite(ids);
|
|
1533
|
-
}).catch(() => {
|
|
2363
|
+
if (writeHost) queuePinnedHostWrite(ids, groups);
|
|
2364
|
+
}).catch(() => {
|
|
2365
|
+
pinnedHostHydratedRef.current = true;
|
|
2366
|
+
});
|
|
1534
2367
|
return () => {
|
|
1535
2368
|
alive = false;
|
|
1536
2369
|
};
|
|
1537
2370
|
}, []);
|
|
1538
|
-
(0, react.useEffect)(() => {
|
|
1539
|
-
writeSessionIds(storage$1(), SESSION_PINS_STORAGE_KEY, pinnedSessionIds);
|
|
1540
|
-
}, [pinnedSessionIds]);
|
|
1541
2371
|
(0, react.useEffect)(() => {
|
|
1542
2372
|
writeSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY, unreadSessionIds);
|
|
1543
2373
|
}, [unreadSessionIds]);
|
|
1544
2374
|
(0, react.useEffect)(() => {
|
|
1545
|
-
if (
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
2375
|
+
if (!baselinesReady) return;
|
|
2376
|
+
const validIds = workspaces.items.map((workspace) => String(workspace.workspaceId));
|
|
2377
|
+
const nextPinned = prunePinnedWorkspaceIds(pinnedWorkspaceIdsRef.current, validIds);
|
|
2378
|
+
const nextGroups = pruneWorkspaceGroups(workspaceGroupsRef.current, validIds);
|
|
2379
|
+
if (!sameIds(pinnedWorkspaceIdsRef.current, nextPinned)) {
|
|
2380
|
+
pinnedWorkspaceIdsRef.current = nextPinned;
|
|
2381
|
+
setPinnedWorkspaceIdsState(nextPinned);
|
|
2382
|
+
}
|
|
2383
|
+
if (!sameWorkspaceGroups(workspaceGroupsRef.current, nextGroups)) {
|
|
2384
|
+
workspaceGroupsRef.current = nextGroups;
|
|
2385
|
+
setWorkspaceGroupsState(nextGroups);
|
|
2386
|
+
}
|
|
2387
|
+
}, [baselinesReady, workspaces.items]);
|
|
1551
2388
|
(0, react.useEffect)(() => {
|
|
1552
2389
|
const current = sessions.current;
|
|
1553
2390
|
if (current !== void 0) setUnreadSessionIds((ids) => ids.filter((id) => id !== current));
|
|
1554
2391
|
}, [sessions.current]);
|
|
2392
|
+
(0, react.useEffect)(() => {
|
|
2393
|
+
const next = Object.fromEntries(Object.entries(sessions.byId).map(([id, session]) => [id, session.running === true]));
|
|
2394
|
+
const previous = previousSessionRunningRef.current;
|
|
2395
|
+
previousSessionRunningRef.current = next;
|
|
2396
|
+
if (previous === void 0) return;
|
|
2397
|
+
const completed = completedBackgroundSessionIds(previous, next, sessions.current);
|
|
2398
|
+
if (completed.length > 0) setUnreadSessionIds((ids) => [...completed, ...ids.filter((id) => !completed.includes(id))]);
|
|
2399
|
+
}, [sessions.byId, sessions.current]);
|
|
1555
2400
|
const groups = (0, react.useMemo)(() => {
|
|
1556
2401
|
const archived = workspaces.archivedSessionIds;
|
|
1557
|
-
const visible = (ids) => visibleSessionIds(ids, sessions.byId, archived)
|
|
1558
|
-
const leftPinned = pinnedSessionIds.indexOf(left);
|
|
1559
|
-
const rightPinned = pinnedSessionIds.indexOf(right);
|
|
1560
|
-
if (leftPinned !== -1 || rightPinned !== -1) return (leftPinned === -1 ? Number.MAX_SAFE_INTEGER : leftPinned) - (rightPinned === -1 ? Number.MAX_SAFE_INTEGER : rightPinned);
|
|
1561
|
-
return 0;
|
|
1562
|
-
});
|
|
2402
|
+
const visible = (ids) => visibleSessionIds(ids, sessions.byId, archived);
|
|
1563
2403
|
return { items: workspaces.items.map((workspace) => ({
|
|
1564
2404
|
...workspace,
|
|
1565
2405
|
visibleIds: visible(workspace.sessionIds)
|
|
1566
2406
|
})) };
|
|
1567
2407
|
}, [
|
|
1568
|
-
pinnedSessionIds,
|
|
1569
2408
|
sessions.byId,
|
|
1570
2409
|
sessions.ids,
|
|
1571
2410
|
workspaces.archivedSessionIds,
|
|
1572
2411
|
workspaces.items
|
|
1573
2412
|
]);
|
|
2413
|
+
const sourceWorkspaceIdForSession = (sessionId) => {
|
|
2414
|
+
if (sessionDrag?.sessionId === sessionId && sessionDrag.workspaceId !== "") return sessionDrag.workspaceId;
|
|
2415
|
+
const source = groups.items.find((workspace) => workspace.sessionIds.some((id) => String(id) === sessionId));
|
|
2416
|
+
return source === void 0 ? void 0 : String(source.workspaceId);
|
|
2417
|
+
};
|
|
1574
2418
|
(0, react.useEffect)(() => {
|
|
1575
2419
|
const onPointerDown = () => {
|
|
1576
2420
|
if (headerMenuRef.current !== void 0) headerMenuPointerAt.current = performance.now();
|
|
@@ -1596,6 +2440,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1596
2440
|
title: workspace.title,
|
|
1597
2441
|
path: workspace.path,
|
|
1598
2442
|
count: workspace.visibleIds.length,
|
|
2443
|
+
unreadCount: workspace.visibleIds.filter((id) => unreadSessionIds.includes(String(id))).length,
|
|
2444
|
+
pinned: pinnedWorkspaceIds.includes(String(workspace.workspaceId)),
|
|
1599
2445
|
left: detail.left,
|
|
1600
2446
|
top: detail.top
|
|
1601
2447
|
}, { immediate: true });
|
|
@@ -1624,7 +2470,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1624
2470
|
}, [
|
|
1625
2471
|
groups.items,
|
|
1626
2472
|
sessions.current,
|
|
1627
|
-
menu
|
|
2473
|
+
menu,
|
|
2474
|
+
pinnedWorkspaceIds,
|
|
2475
|
+
unreadSessionIds
|
|
1628
2476
|
]);
|
|
1629
2477
|
const projectPinned = (id) => pinnedWorkspaceIds.includes(String(id));
|
|
1630
2478
|
const pinnedGroups = orderByIds(groups.items, pinnedWorkspaceIds, (workspace) => String(workspace.workspaceId));
|
|
@@ -1632,6 +2480,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1632
2480
|
const pinDragActive = workspaceDragId !== void 0;
|
|
1633
2481
|
const pinnedGroupIds = pinnedGroups.map((workspace) => String(workspace.workspaceId));
|
|
1634
2482
|
const regularGroupIds = regularGroups.map((workspace) => String(workspace.workspaceId));
|
|
2483
|
+
const groupedIds = new Set(groupedWorkspaceIds(workspaceGroups));
|
|
2484
|
+
const workspaceGroupIds = workspaceGroups.map((group) => group.id);
|
|
2485
|
+
const ungroupedGroups = regularGroups.filter((workspace) => !groupedIds.has(String(workspace.workspaceId)));
|
|
2486
|
+
const ungroupedGroupIds = ungroupedGroups.map((workspace) => String(workspace.workspaceId));
|
|
2487
|
+
const workspaceById = new Map(regularGroups.map((workspace) => [String(workspace.workspaceId), workspace]));
|
|
1635
2488
|
const pinnedHeaderDrop = workspaceDropTarget?.zone === "pinned" && workspaceDropTarget.beforeId === pinnedGroupIds[0] ? pinnedHeaderDropIndicator(pinnedGroupIds) : void 0;
|
|
1636
2489
|
const assignedIds = workspaces.items.flatMap((workspace) => workspace.sessionIds.map((id) => String(id)));
|
|
1637
2490
|
const recentIds = ungroupedSessionIds(sessions.ids ?? Object.keys(sessions.byId), sessions.byId, assignedIds, workspaces.archivedSessionIds).sort((left, right) => (sessions.byId[right]?.updatedAt ?? 0) - (sessions.byId[left]?.updatedAt ?? 0));
|
|
@@ -1644,7 +2497,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1644
2497
|
await action();
|
|
1645
2498
|
setMenu(void 0);
|
|
1646
2499
|
} catch (reason) {
|
|
1647
|
-
setError(reason
|
|
2500
|
+
setError(userErrorText(reason, t));
|
|
1648
2501
|
} finally {
|
|
1649
2502
|
busyRef.current = void 0;
|
|
1650
2503
|
setBusy(void 0);
|
|
@@ -1674,7 +2527,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1674
2527
|
run(operation, async () => {
|
|
1675
2528
|
if (target.kind === "session") {
|
|
1676
2529
|
await deleteSession(target.id);
|
|
1677
|
-
setPinnedSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
1678
2530
|
setUnreadSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
1679
2531
|
} else {
|
|
1680
2532
|
await deleteWorkspace(target.id);
|
|
@@ -1683,6 +2535,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1683
2535
|
setDeleteTarget(void 0);
|
|
1684
2536
|
});
|
|
1685
2537
|
};
|
|
2538
|
+
const submitArchiveWorkspace = () => {
|
|
2539
|
+
if (archiveWorkspaceTarget === void 0) return;
|
|
2540
|
+
const target = archiveWorkspaceTarget;
|
|
2541
|
+
run("archive-workspace", async () => {
|
|
2542
|
+
await archiveWorkspaceSessions(target.sessionIds, (sessionId) => archiveSession(sessionId));
|
|
2543
|
+
setUnreadSessionIds((ids) => ids.filter((id) => !target.sessionIds.includes(id)));
|
|
2544
|
+
setArchiveWorkspaceTarget(void 0);
|
|
2545
|
+
});
|
|
2546
|
+
};
|
|
1686
2547
|
const copy = (value) => {
|
|
1687
2548
|
if (value === void 0 || value === "") return;
|
|
1688
2549
|
run("copy", async () => {
|
|
@@ -1700,6 +2561,19 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1700
2561
|
[key]: !(current[key] ?? defaultOpen)
|
|
1701
2562
|
}));
|
|
1702
2563
|
};
|
|
2564
|
+
const submitCreateGroup = () => {
|
|
2565
|
+
if (groupTitleDraft.trim() === "") return;
|
|
2566
|
+
try {
|
|
2567
|
+
setWorkspaceGroups((current) => createWorkspaceGroup(current, {
|
|
2568
|
+
id: newWorkspaceGroupId(),
|
|
2569
|
+
title: groupTitleDraft
|
|
2570
|
+
}));
|
|
2571
|
+
setCreateGroupOpen(false);
|
|
2572
|
+
setGroupTitleDraft("");
|
|
2573
|
+
} catch (reason) {
|
|
2574
|
+
setError(userErrorText(reason, t));
|
|
2575
|
+
}
|
|
2576
|
+
};
|
|
1703
2577
|
const sectionOpen = (id) => expanded[`section:${id}`] ?? true;
|
|
1704
2578
|
const toggleSection = (id) => {
|
|
1705
2579
|
setExpanded((current) => ({
|
|
@@ -1707,44 +2581,150 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1707
2581
|
[`section:${id}`]: !(current[`section:${id}`] ?? true)
|
|
1708
2582
|
}));
|
|
1709
2583
|
};
|
|
1710
|
-
const
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
2584
|
+
const workspaceGroupIdFor = (workspaceId) => workspaceGroups.find((group) => group.workspaceIds.includes(workspaceId))?.id;
|
|
2585
|
+
const moveWorkspaceToGroup = (workspaceId, groupId) => {
|
|
2586
|
+
setWorkspaceGroups((current) => assignWorkspaceToGroup(current, workspaceId, groupId));
|
|
2587
|
+
if (pinnedWorkspaceIdsRef.current.includes(workspaceId)) setPinnedWorkspaceIds((ids) => ids.filter((id) => id !== workspaceId));
|
|
2588
|
+
};
|
|
2589
|
+
const projectMenu = (workspace) => {
|
|
2590
|
+
const workspaceId = String(workspace.workspaceId);
|
|
2591
|
+
const moveTargets = workspaceGroupMoveTargets(workspaceGroups, workspaceId).map((target) => ({
|
|
2592
|
+
id: workspaceGroupMoveActionId(target.groupId),
|
|
2593
|
+
label: target.title ?? t("workspace.removeFromGroup"),
|
|
2594
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
2595
|
+
}));
|
|
2596
|
+
return [
|
|
2597
|
+
{
|
|
2598
|
+
id: "pin",
|
|
2599
|
+
label: t(projectPinned(workspace.workspaceId) ? "workspace.unpin" : "workspace.pin"),
|
|
2600
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinIcon, {})
|
|
2601
|
+
},
|
|
2602
|
+
{
|
|
2603
|
+
id: "rename",
|
|
2604
|
+
label: t("workspace.rename"),
|
|
2605
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 16 })
|
|
2606
|
+
},
|
|
2607
|
+
{
|
|
2608
|
+
type: "separator",
|
|
2609
|
+
id: "project-main-separator"
|
|
2610
|
+
},
|
|
2611
|
+
{
|
|
2612
|
+
id: "moveToGroup",
|
|
2613
|
+
label: t("workspace.moveToGroup"),
|
|
2614
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 }),
|
|
2615
|
+
disabled: moveTargets.length === 0,
|
|
2616
|
+
submenu: moveTargets
|
|
2617
|
+
},
|
|
2618
|
+
{
|
|
2619
|
+
id: "openPath",
|
|
2620
|
+
label: t("workspace.openPath"),
|
|
2621
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderOpenOutline16, { size: 16 })
|
|
2622
|
+
},
|
|
2623
|
+
{
|
|
2624
|
+
type: "separator",
|
|
2625
|
+
id: "project-archive-separator"
|
|
2626
|
+
},
|
|
2627
|
+
{
|
|
2628
|
+
id: "archiveWorkspace",
|
|
2629
|
+
label: t("workspace.archive"),
|
|
2630
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconArchiveOutline20, { size: 16 }),
|
|
2631
|
+
disabled: workspace.visibleIds.length === 0
|
|
2632
|
+
},
|
|
2633
|
+
{
|
|
2634
|
+
type: "separator",
|
|
2635
|
+
id: "project-delete-separator"
|
|
2636
|
+
},
|
|
2637
|
+
{
|
|
2638
|
+
id: "delete",
|
|
2639
|
+
label: t("workspace.delete"),
|
|
2640
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: 16 }),
|
|
2641
|
+
danger: true
|
|
2642
|
+
}
|
|
2643
|
+
];
|
|
2644
|
+
};
|
|
2645
|
+
const handleProjectMenuAction = (workspace, id) => {
|
|
2646
|
+
if (busy !== void 0) return;
|
|
2647
|
+
const workspaceId = String(workspace.workspaceId);
|
|
2648
|
+
const targetGroup = workspaceGroups.find((group) => id === workspaceGroupMoveActionId(group.id));
|
|
2649
|
+
if (targetGroup !== void 0 || id === workspaceGroupMoveActionId()) {
|
|
2650
|
+
moveWorkspaceToGroup(workspaceId, targetGroup?.id);
|
|
2651
|
+
setMenu(void 0);
|
|
2652
|
+
return;
|
|
1740
2653
|
}
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
2654
|
+
if (id === "rename") beginRename("workspace", workspace.workspaceId, workspace.title);
|
|
2655
|
+
if (id === "pin") {
|
|
2656
|
+
setPinnedWorkspaceIds((ids) => togglePinnedWorkspace(ids, workspace.workspaceId));
|
|
2657
|
+
setMenu(void 0);
|
|
2658
|
+
}
|
|
2659
|
+
if (id === "archiveWorkspace") {
|
|
2660
|
+
setArchiveWorkspaceTarget({
|
|
2661
|
+
id: workspaceId,
|
|
2662
|
+
title: workspace.title,
|
|
2663
|
+
sessionIds: [...workspace.visibleIds]
|
|
2664
|
+
});
|
|
2665
|
+
setError(void 0);
|
|
2666
|
+
setMenu(void 0);
|
|
2667
|
+
}
|
|
2668
|
+
if (id === "openPath") openPathImmediately(workspace.path);
|
|
2669
|
+
if (id === "delete") {
|
|
2670
|
+
setDeleteTarget({
|
|
2671
|
+
id: workspace.workspaceId,
|
|
2672
|
+
kind: "workspace",
|
|
2673
|
+
title: workspace.title
|
|
2674
|
+
});
|
|
2675
|
+
setError(void 0);
|
|
2676
|
+
setMenu(void 0);
|
|
2677
|
+
}
|
|
2678
|
+
};
|
|
2679
|
+
const sessionMenu = (sessionId, path) => sessionMenuItems(t, {
|
|
1744
2680
|
unread: unreadSessionIds.includes(sessionId),
|
|
1745
2681
|
path,
|
|
1746
|
-
includePath: true
|
|
2682
|
+
includePath: true,
|
|
2683
|
+
moveTargets: sessionMoveTargets(groups.items, sessionId).map((target) => ({
|
|
2684
|
+
...target,
|
|
2685
|
+
id: moveSessionActionId(target.id)
|
|
2686
|
+
}))
|
|
1747
2687
|
});
|
|
2688
|
+
const requestSessionMove = (sessionId, targetWorkspaceId) => {
|
|
2689
|
+
const targetWorkspace = groups.items.find((workspace) => String(workspace.workspaceId) === targetWorkspaceId);
|
|
2690
|
+
const session = sessions.byId[sessionId];
|
|
2691
|
+
if (targetWorkspace === void 0 || session === void 0) {
|
|
2692
|
+
setError(t("sessions.moveNotFound"));
|
|
2693
|
+
return;
|
|
2694
|
+
}
|
|
2695
|
+
setMenu(void 0);
|
|
2696
|
+
setHeaderMenu(void 0);
|
|
2697
|
+
setError(void 0);
|
|
2698
|
+
setSessionMoveTarget({
|
|
2699
|
+
sessionId,
|
|
2700
|
+
sessionTitle: session.displayTitle,
|
|
2701
|
+
targetWorkspaceId,
|
|
2702
|
+
targetWorkspaceTitle: targetWorkspace.title,
|
|
2703
|
+
targetPath: targetWorkspace.path
|
|
2704
|
+
});
|
|
2705
|
+
};
|
|
2706
|
+
const runSessionMoveAction = (action, sessionId) => {
|
|
2707
|
+
const targetWorkspaceId = parseMoveSessionActionId(action);
|
|
2708
|
+
if (targetWorkspaceId === void 0) return false;
|
|
2709
|
+
requestSessionMove(sessionId, targetWorkspaceId);
|
|
2710
|
+
return true;
|
|
2711
|
+
};
|
|
2712
|
+
const submitSessionMove = () => {
|
|
2713
|
+
const target = sessionMoveTarget;
|
|
2714
|
+
if (target === void 0) return;
|
|
2715
|
+
run("session-move", async () => {
|
|
2716
|
+
const nextExpanded = expandedForSessionMove(expanded, {
|
|
2717
|
+
workspaceId: target.targetWorkspaceId,
|
|
2718
|
+
pinned: projectPinned(target.targetWorkspaceId),
|
|
2719
|
+
groupId: workspaceGroupIdFor(target.targetWorkspaceId),
|
|
2720
|
+
hasGroups: workspaceGroups.length > 0
|
|
2721
|
+
});
|
|
2722
|
+
setExpanded(nextExpanded);
|
|
2723
|
+
writeTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY, nextExpanded);
|
|
2724
|
+
await moveSession(target.sessionId, target.targetWorkspaceId);
|
|
2725
|
+
setSessionMoveTarget(void 0);
|
|
2726
|
+
});
|
|
2727
|
+
};
|
|
1748
2728
|
const pinWorkspaceAt = (id, beforeId) => {
|
|
1749
2729
|
setPinnedWorkspaceIds((ids) => insertPinnedWorkspace(ids, id, beforeId));
|
|
1750
2730
|
};
|
|
@@ -1757,207 +2737,222 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1757
2737
|
x: menu.x,
|
|
1758
2738
|
y: menu.y
|
|
1759
2739
|
} : void 0;
|
|
1760
|
-
const isCurrentWorkspace = sessions.current !== void 0 && workspace.visibleIds.includes(sessions.current);
|
|
1761
2740
|
const isPinnedHeaderDrop = zone === "pinned" && pinnedHeaderDrop?.kind === "workspace" && pinnedHeaderDrop.workspaceId === String(workspace.workspaceId);
|
|
1762
2741
|
const workspaceId = String(workspace.workspaceId);
|
|
1763
2742
|
const zoneIds = zone === "pinned" ? pinnedGroupIds : regularGroupIds;
|
|
1764
2743
|
const dropsBefore = workspaceDropTarget?.zone === zone && workspaceDropTarget.beforeId === workspaceId;
|
|
1765
2744
|
const dropsAfterLast = zone === "projects" && workspaceDropTarget?.zone === zone && workspaceDropTarget.beforeId === void 0 && zoneIds[zoneIds.length - 1] === workspaceId;
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
2745
|
+
const projectSessionDrop = sessionDropTarget?.workspaceId === workspaceId && sessionDropTarget.ontoProject === true;
|
|
2746
|
+
const projectSessionMoveDrop = projectSessionDrop && sessionDropTarget.crossWorkspace === true;
|
|
2747
|
+
const handleProjectDragOver = (event) => {
|
|
2748
|
+
const draggedWorkspace = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
2749
|
+
if (draggedWorkspace !== void 0) {
|
|
1770
2750
|
event.preventDefault();
|
|
1771
2751
|
event.stopPropagation();
|
|
1772
2752
|
event.dataTransfer.dropEffect = "move";
|
|
1773
2753
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
1774
|
-
const
|
|
1775
|
-
|
|
2754
|
+
const beforeId = reorderDropBeforeId(zoneIds, draggedWorkspace, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
2755
|
+
setSessionDropTarget(void 0);
|
|
1776
2756
|
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
1777
2757
|
zone,
|
|
1778
2758
|
beforeId
|
|
1779
2759
|
});
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
const draggedSessionId = readSessionDrag(event.dataTransfer, sessionDrag?.sessionId);
|
|
2763
|
+
if (draggedSessionId === void 0) return;
|
|
2764
|
+
event.preventDefault();
|
|
2765
|
+
event.stopPropagation();
|
|
2766
|
+
event.dataTransfer.dropEffect = "move";
|
|
2767
|
+
const action = sessionDropAction(sourceWorkspaceIdForSession(draggedSessionId), workspaceId);
|
|
2768
|
+
setWorkspaceDropTarget(void 0);
|
|
2769
|
+
setSessionDropTarget({
|
|
2770
|
+
workspaceId,
|
|
2771
|
+
beforeId: action === "reorder" ? shownIds[0] : void 0,
|
|
2772
|
+
ontoProject: true,
|
|
2773
|
+
crossWorkspace: action === "move"
|
|
2774
|
+
});
|
|
2775
|
+
};
|
|
2776
|
+
const handleProjectDrop = (event) => {
|
|
2777
|
+
const draggedWorkspace = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
2778
|
+
if (draggedWorkspace !== void 0) {
|
|
1786
2779
|
event.preventDefault();
|
|
1787
2780
|
event.stopPropagation();
|
|
1788
|
-
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
1789
2781
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
1790
|
-
const
|
|
2782
|
+
const beforeId = reorderDropBeforeId(zoneIds, draggedWorkspace, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
1791
2783
|
setWorkspaceDragId(void 0);
|
|
1792
2784
|
setWorkspaceDropTarget(void 0);
|
|
1793
|
-
if (dragged === void 0) return;
|
|
1794
|
-
const beforeId = reorderDropBeforeId(zoneIds, dragged, workspaceId, after);
|
|
1795
2785
|
if (beforeId === null) return;
|
|
1796
2786
|
if (zone === "pinned") {
|
|
1797
|
-
pinWorkspaceAt(
|
|
2787
|
+
pinWorkspaceAt(draggedWorkspace, beforeId);
|
|
1798
2788
|
return;
|
|
1799
2789
|
}
|
|
1800
|
-
setPinnedWorkspaceIds((ids) => ids.filter((id) => id !== dragged));
|
|
1801
2790
|
const hostIds = groups.items.map((item) => String(item.workspaceId));
|
|
1802
|
-
if (moveBefore(hostIds,
|
|
2791
|
+
if (moveBefore(hostIds, draggedWorkspace, beforeId).some((id, index) => id !== hostIds[index])) run("workspace-order", () => insertWorkspaceBefore(draggedWorkspace, beforeId));
|
|
2792
|
+
return;
|
|
2793
|
+
}
|
|
2794
|
+
const draggedSessionId = readSessionDrag(event.dataTransfer, sessionDrag?.sessionId);
|
|
2795
|
+
if (draggedSessionId === void 0) return;
|
|
2796
|
+
event.preventDefault();
|
|
2797
|
+
event.stopPropagation();
|
|
2798
|
+
const action = sessionDropAction(sourceWorkspaceIdForSession(draggedSessionId), workspaceId);
|
|
2799
|
+
setSessionDrag(void 0);
|
|
2800
|
+
setSessionDropTarget(void 0);
|
|
2801
|
+
setWorkspaceDropTarget(void 0);
|
|
2802
|
+
if (action === "move") {
|
|
2803
|
+
requestSessionMove(draggedSessionId, workspaceId);
|
|
2804
|
+
return;
|
|
2805
|
+
}
|
|
2806
|
+
run("session-order", () => insertSessionBefore(workspace.workspaceId, draggedSessionId, shownIds[0]));
|
|
2807
|
+
};
|
|
2808
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2809
|
+
className: `dcu-wb-project${isPinnedHeaderDrop || dropsBefore ? " dcu-wb-drop" : ""}${dropsAfterLast ? " dcu-wb-drop dcu-wb-drop-after" : ""}${projectSessionDrop ? " dcu-wb-session-drop" : ""}${projectSessionMoveDrop ? " dcu-wb-session-move-drop" : ""}`,
|
|
2810
|
+
onDragOver: handleProjectDragOver,
|
|
2811
|
+
onDragLeave: (event) => {
|
|
2812
|
+
if (event.currentTarget.contains(event.relatedTarget)) return;
|
|
2813
|
+
setWorkspaceDropTarget(void 0);
|
|
2814
|
+
setSessionDropTarget(void 0);
|
|
1803
2815
|
},
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
2816
|
+
onDrop: handleProjectDrop,
|
|
2817
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2818
|
+
className: `dcu-wb-project-head${menuOpen ? " dcu-wb-menu-open" : ""}${workspaceDragId === workspaceId ? " dcu-wb-dragging" : ""}`,
|
|
2819
|
+
role: "treeitem",
|
|
2820
|
+
"aria-expanded": isExpanded,
|
|
2821
|
+
tabIndex: 0,
|
|
2822
|
+
draggable: true,
|
|
2823
|
+
onDragStart: (event) => {
|
|
2824
|
+
event.stopPropagation();
|
|
2825
|
+
setSessionDrag(void 0);
|
|
2826
|
+
setSessionDropTarget(void 0);
|
|
2827
|
+
setWorkspaceGroupDragId(void 0);
|
|
2828
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
2829
|
+
writeWorkspaceDrag(event.dataTransfer, workspaceId, workspace.title);
|
|
2830
|
+
setDragPreview(event.dataTransfer, workspace.title, event.currentTarget.querySelector(".dcu-wb-folder"));
|
|
2831
|
+
setWorkspaceDragId(workspaceId);
|
|
2832
|
+
},
|
|
2833
|
+
onDragEnd: () => {
|
|
2834
|
+
setWorkspaceDragId(void 0);
|
|
2835
|
+
setWorkspaceDropTarget(void 0);
|
|
2836
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
2837
|
+
},
|
|
2838
|
+
onClick: () => {
|
|
2839
|
+
toggleGroup(expandKey, true);
|
|
2840
|
+
},
|
|
2841
|
+
onContextMenu: (event) => {
|
|
2842
|
+
event.preventDefault();
|
|
2843
|
+
event.stopPropagation();
|
|
2844
|
+
dismissTip();
|
|
2845
|
+
setMenu({
|
|
2846
|
+
id: workspace.workspaceId,
|
|
2847
|
+
type: "workspace",
|
|
2848
|
+
x: event.clientX,
|
|
2849
|
+
y: event.clientY
|
|
2850
|
+
});
|
|
2851
|
+
},
|
|
2852
|
+
onMouseEnter: (event) => {
|
|
2853
|
+
const box = hoverCardAnchor(event.currentTarget.getBoundingClientRect());
|
|
2854
|
+
showTip({
|
|
2855
|
+
kind: "workspace",
|
|
2856
|
+
id: workspace.workspaceId,
|
|
2857
|
+
title: workspace.title,
|
|
2858
|
+
path: workspace.path,
|
|
2859
|
+
count: workspace.visibleIds.length,
|
|
2860
|
+
unreadCount: workspace.visibleIds.filter((id) => unreadSessionIds.includes(String(id))).length,
|
|
2861
|
+
pinned: projectPinned(workspace.workspaceId),
|
|
2862
|
+
left: box.left,
|
|
2863
|
+
top: box.top
|
|
2864
|
+
});
|
|
2865
|
+
},
|
|
2866
|
+
onMouseLeave: hideTip,
|
|
2867
|
+
onKeyDown: (event) => {
|
|
2868
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1834
2869
|
event.preventDefault();
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
}
|
|
1873
|
-
showTip({
|
|
1874
|
-
kind: "workspace",
|
|
1875
|
-
id: workspace.workspaceId,
|
|
1876
|
-
title: workspace.title,
|
|
1877
|
-
path: workspace.path,
|
|
1878
|
-
count: workspace.visibleIds.length,
|
|
1879
|
-
left: box.left,
|
|
1880
|
-
top: box.top
|
|
1881
|
-
}, { immediate: true });
|
|
2870
|
+
toggleGroup(expandKey, true);
|
|
2871
|
+
}
|
|
2872
|
+
},
|
|
2873
|
+
children: [
|
|
2874
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2875
|
+
className: "dcu-wb-folder",
|
|
2876
|
+
onClick: (event) => {
|
|
2877
|
+
event.stopPropagation();
|
|
2878
|
+
const box = hoverCardAnchor(event.currentTarget.getBoundingClientRect());
|
|
2879
|
+
if (isShowing("workspace", workspace.workspaceId)) {
|
|
2880
|
+
dismissTip();
|
|
2881
|
+
return;
|
|
2882
|
+
}
|
|
2883
|
+
showTip({
|
|
2884
|
+
kind: "workspace",
|
|
2885
|
+
id: workspace.workspaceId,
|
|
2886
|
+
title: workspace.title,
|
|
2887
|
+
path: workspace.path,
|
|
2888
|
+
count: workspace.visibleIds.length,
|
|
2889
|
+
unreadCount: workspace.visibleIds.filter((id) => unreadSessionIds.includes(String(id))).length,
|
|
2890
|
+
pinned: projectPinned(workspace.workspaceId),
|
|
2891
|
+
left: box.left,
|
|
2892
|
+
top: box.top
|
|
2893
|
+
}, { immediate: true });
|
|
2894
|
+
},
|
|
2895
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
2896
|
+
}),
|
|
2897
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2898
|
+
className: "dcu-wb-project-title",
|
|
2899
|
+
children: workspace.title
|
|
2900
|
+
}),
|
|
2901
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2902
|
+
className: "dcu-wb-actions",
|
|
2903
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
2904
|
+
open: menuOpen,
|
|
2905
|
+
onClose: () => {
|
|
2906
|
+
setMenu(void 0);
|
|
1882
2907
|
},
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
open: menuOpen,
|
|
1893
|
-
onClose: () => {
|
|
1894
|
-
setMenu(void 0);
|
|
1895
|
-
},
|
|
1896
|
-
items: projectMenu(workspace),
|
|
1897
|
-
onSelect: (id) => {
|
|
1898
|
-
if (busy !== void 0) return;
|
|
1899
|
-
if (id === "new") {
|
|
1900
|
-
startSession(workspace.workspaceId);
|
|
1901
|
-
setMenu(void 0);
|
|
1902
|
-
}
|
|
1903
|
-
if (id === "rename") beginRename("workspace", workspace.workspaceId, workspace.title);
|
|
1904
|
-
if (id === "pin") {
|
|
1905
|
-
setPinnedWorkspaceIds((ids) => togglePinnedWorkspace(ids, workspace.workspaceId));
|
|
1906
|
-
setMenu(void 0);
|
|
1907
|
-
}
|
|
1908
|
-
if (id === "openPath") openPathImmediately(workspace.path);
|
|
1909
|
-
if (id === "delete") {
|
|
1910
|
-
setDeleteTarget({
|
|
1911
|
-
id: workspace.workspaceId,
|
|
1912
|
-
kind: "workspace",
|
|
1913
|
-
title: workspace.title
|
|
1914
|
-
});
|
|
1915
|
-
setError(void 0);
|
|
1916
|
-
setMenu(void 0);
|
|
1917
|
-
}
|
|
1918
|
-
},
|
|
1919
|
-
portal: true,
|
|
1920
|
-
dense: true,
|
|
1921
|
-
compact: true,
|
|
1922
|
-
getAnchorRect: menuAt === void 0 ? void 0 : () => pointerMenuRect(menuAt.x, menuAt.y),
|
|
1923
|
-
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1924
|
-
type: "button",
|
|
1925
|
-
className: "dcu-wb-more",
|
|
1926
|
-
"aria-label": t("workspace.actions", { name: workspace.title }),
|
|
1927
|
-
onClick: (event) => {
|
|
1928
|
-
event.stopPropagation();
|
|
1929
|
-
setMenu((current) => current?.id === workspace.workspaceId && current.type === "workspace" ? void 0 : {
|
|
1930
|
-
id: workspace.workspaceId,
|
|
1931
|
-
type: "workspace"
|
|
1932
|
-
});
|
|
1933
|
-
},
|
|
1934
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
1935
|
-
})
|
|
1936
|
-
})
|
|
1937
|
-
}),
|
|
1938
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1939
|
-
className: "dcu-wb-actions",
|
|
1940
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2908
|
+
items: projectMenu(workspace),
|
|
2909
|
+
onSelect: (id) => {
|
|
2910
|
+
handleProjectMenuAction(workspace, id);
|
|
2911
|
+
},
|
|
2912
|
+
portal: true,
|
|
2913
|
+
dense: true,
|
|
2914
|
+
compact: true,
|
|
2915
|
+
getAnchorRect: menuAt === void 0 ? void 0 : () => pointerMenuRect(menuAt.x, menuAt.y),
|
|
2916
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1941
2917
|
type: "button",
|
|
1942
2918
|
className: "dcu-wb-more",
|
|
1943
|
-
"aria-label": t("workspace.
|
|
2919
|
+
"aria-label": t("workspace.actions", { name: workspace.title }),
|
|
1944
2920
|
onClick: (event) => {
|
|
1945
2921
|
event.stopPropagation();
|
|
1946
|
-
|
|
2922
|
+
dismissTip();
|
|
2923
|
+
setMenu((current) => current?.id === workspace.workspaceId && current?.type === "workspace" ? void 0 : {
|
|
2924
|
+
id: workspace.workspaceId,
|
|
2925
|
+
type: "workspace"
|
|
2926
|
+
});
|
|
1947
2927
|
},
|
|
1948
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
2928
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
1949
2929
|
})
|
|
1950
2930
|
})
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
2931
|
+
}),
|
|
2932
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2933
|
+
className: "dcu-wb-actions",
|
|
2934
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2935
|
+
type: "button",
|
|
2936
|
+
className: "dcu-wb-more",
|
|
2937
|
+
"aria-label": t("workspace.newSession"),
|
|
2938
|
+
onClick: (event) => {
|
|
2939
|
+
event.stopPropagation();
|
|
2940
|
+
startSession(workspace.workspaceId);
|
|
2941
|
+
},
|
|
2942
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NewSessionIcon, {})
|
|
2943
|
+
})
|
|
2944
|
+
})
|
|
2945
|
+
]
|
|
2946
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DisclosureBody, {
|
|
2947
|
+
className: "dcu-wb-project-body",
|
|
2948
|
+
open: isExpanded,
|
|
2949
|
+
children: [shownIds.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1954
2950
|
className: "dcu-wb-nochat",
|
|
1955
2951
|
children: t("workspace.noChat")
|
|
1956
|
-
}),
|
|
1957
|
-
isExpanded && shownIds.map((id) => {
|
|
2952
|
+
}), shownIds.map((id) => {
|
|
1958
2953
|
const session = sessions.byId[id];
|
|
1959
2954
|
if (session === void 0) return null;
|
|
1960
|
-
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, session
|
|
2955
|
+
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, legacyPendingInteraction(session));
|
|
1961
2956
|
const path = session.cwd ?? workspace.path;
|
|
1962
2957
|
const selected = sessions.current === id;
|
|
1963
2958
|
const sessionMenuOpen = menu?.type === "session" && menu.id === id;
|
|
@@ -1965,8 +2960,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1965
2960
|
x: menu.x,
|
|
1966
2961
|
y: menu.y
|
|
1967
2962
|
} : void 0;
|
|
1968
|
-
const dropsBeforeSession = sessionDropTarget?.workspaceId === workspaceId && sessionDropTarget.beforeId === id;
|
|
1969
|
-
const dropsAfterLastSession = sessionDropTarget?.workspaceId === workspaceId && sessionDropTarget.beforeId === void 0 && shownIds[shownIds.length - 1] === id;
|
|
2963
|
+
const dropsBeforeSession = sessionDropTarget?.workspaceId === workspaceId && sessionDropTarget.ontoProject !== true && sessionDropTarget.beforeId === id;
|
|
2964
|
+
const dropsAfterLastSession = sessionDropTarget?.workspaceId === workspaceId && sessionDropTarget.ontoProject !== true && sessionDropTarget.beforeId === void 0 && shownIds[shownIds.length - 1] === id;
|
|
1970
2965
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1971
2966
|
className: `dcu-wb-session${selected ? " dcu-wb-selected" : ""}${sessionMenuOpen ? " dcu-wb-menu-open" : ""}${dropsBeforeSession ? " dcu-wb-drop" : ""}${dropsAfterLastSession ? " dcu-wb-drop dcu-wb-drop-after" : ""}`,
|
|
1972
2967
|
role: "treeitem",
|
|
@@ -1976,15 +2971,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1976
2971
|
event.stopPropagation();
|
|
1977
2972
|
setWorkspaceDragId(void 0);
|
|
1978
2973
|
setWorkspaceDropTarget(void 0);
|
|
2974
|
+
setWorkspaceGroupDragId(void 0);
|
|
2975
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
1979
2976
|
writeSessionDrag(event.dataTransfer, id, session.displayTitle);
|
|
1980
|
-
|
|
1981
|
-
preview.className = "dcu-wb-drag-ghost";
|
|
1982
|
-
preview.textContent = session.displayTitle;
|
|
1983
|
-
document.body.appendChild(preview);
|
|
1984
|
-
event.dataTransfer.setDragImage(preview, 16, 18);
|
|
1985
|
-
window.requestAnimationFrame(() => {
|
|
1986
|
-
preview.remove();
|
|
1987
|
-
});
|
|
2977
|
+
setDragPreview(event.dataTransfer, session.displayTitle);
|
|
1988
2978
|
setSessionDrag({
|
|
1989
2979
|
sessionId: id,
|
|
1990
2980
|
workspaceId
|
|
@@ -1993,14 +2983,16 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1993
2983
|
onDragEnd: () => {
|
|
1994
2984
|
setSessionDrag(void 0);
|
|
1995
2985
|
setSessionDropTarget(void 0);
|
|
2986
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
1996
2987
|
},
|
|
1997
2988
|
onDragOver: (event) => {
|
|
1998
|
-
|
|
2989
|
+
const drag = sessionDrag;
|
|
2990
|
+
if (drag === void 0 || drag.workspaceId !== workspaceId) return;
|
|
1999
2991
|
event.preventDefault();
|
|
2000
2992
|
event.stopPropagation();
|
|
2001
2993
|
event.dataTransfer.dropEffect = "move";
|
|
2002
2994
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
2003
|
-
const beforeId = reorderDropBeforeId(shownIds,
|
|
2995
|
+
const beforeId = reorderDropBeforeId(shownIds, drag.sessionId, id, event.clientY > rect.top + rect.height / 2);
|
|
2004
2996
|
setSessionDropTarget(beforeId === null ? void 0 : {
|
|
2005
2997
|
workspaceId,
|
|
2006
2998
|
beforeId
|
|
@@ -2011,13 +3003,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2011
3003
|
setSessionDropTarget(void 0);
|
|
2012
3004
|
},
|
|
2013
3005
|
onDrop: (event) => {
|
|
3006
|
+
const drag = sessionDrag;
|
|
3007
|
+
if (drag === void 0 || drag.workspaceId !== workspaceId) return;
|
|
2014
3008
|
event.preventDefault();
|
|
2015
3009
|
event.stopPropagation();
|
|
2016
|
-
const drag = sessionDrag;
|
|
2017
3010
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
2018
3011
|
setSessionDrag(void 0);
|
|
2019
3012
|
setSessionDropTarget(void 0);
|
|
2020
|
-
if (drag === void 0 || drag.workspaceId !== workspaceId) return;
|
|
2021
3013
|
const beforeId = reorderDropBeforeId(shownIds, drag.sessionId, id, event.clientY > rect.top + rect.height / 2);
|
|
2022
3014
|
if (beforeId !== null) run("session-order", () => insertSessionBefore(workspace.workspaceId, drag.sessionId, beforeId));
|
|
2023
3015
|
},
|
|
@@ -2046,7 +3038,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2046
3038
|
project: workspace.title,
|
|
2047
3039
|
path,
|
|
2048
3040
|
branch,
|
|
2049
|
-
time: formatHoverTime(session.updatedAt),
|
|
3041
|
+
time: formatHoverTime(session.updatedAt, t),
|
|
2050
3042
|
left: box.left,
|
|
2051
3043
|
top: box.top
|
|
2052
3044
|
});
|
|
@@ -2057,37 +3049,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2057
3049
|
className: "dcu-wb-session-title",
|
|
2058
3050
|
children: session.displayTitle.split(/\r?\n/)[0] ?? session.displayTitle
|
|
2059
3051
|
}),
|
|
2060
|
-
pinnedSessionIds.includes(id) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2061
|
-
className: "dcu-wb-pin",
|
|
2062
|
-
"aria-label": t("sessions.pinned"),
|
|
2063
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2064
|
-
viewBox: "0 0 16 16",
|
|
2065
|
-
"aria-hidden": "true",
|
|
2066
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M5 2.5h6M5 2.5v2L3.75 6v1h8.5V6L11 4.5v-2M8 7v6" })
|
|
2067
|
-
})
|
|
2068
|
-
}),
|
|
2069
3052
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionState, {
|
|
2070
3053
|
pendingInteraction,
|
|
2071
3054
|
unread: unreadSessionIds.includes(id),
|
|
2072
3055
|
running: session.running === true,
|
|
2073
3056
|
t
|
|
2074
3057
|
}),
|
|
2075
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3058
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2076
3059
|
className: "dcu-wb-quick-actions",
|
|
2077
|
-
children:
|
|
2078
|
-
type: "button",
|
|
2079
|
-
className: "dcu-wb-more dcu-wb-quick-pin",
|
|
2080
|
-
"aria-label": t(pinnedSessionIds.includes(id) ? "sessions.unpin" : "sessions.pin"),
|
|
2081
|
-
onClick: (event) => {
|
|
2082
|
-
event.stopPropagation();
|
|
2083
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2084
|
-
},
|
|
2085
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2086
|
-
viewBox: "0 0 16 16",
|
|
2087
|
-
"aria-hidden": "true",
|
|
2088
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M5 2.5h6M5 2.5v2L3.75 6v1h8.5V6L11 4.5v-2M8 7v6" })
|
|
2089
|
-
})
|
|
2090
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3060
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2091
3061
|
type: "button",
|
|
2092
3062
|
className: "dcu-wb-more",
|
|
2093
3063
|
"aria-label": t("sessions.archive"),
|
|
@@ -2095,8 +3065,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2095
3065
|
event.stopPropagation();
|
|
2096
3066
|
run("archive", () => archiveSession(id));
|
|
2097
3067
|
},
|
|
2098
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2099
|
-
})
|
|
3068
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickArchiveIcon, {})
|
|
3069
|
+
})
|
|
2100
3070
|
}),
|
|
2101
3071
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2102
3072
|
className: "dcu-wb-actions",
|
|
@@ -2105,15 +3075,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2105
3075
|
onClose: () => {
|
|
2106
3076
|
setMenu(void 0);
|
|
2107
3077
|
},
|
|
2108
|
-
items: sessionMenu(id,
|
|
3078
|
+
items: sessionMenu(id, path),
|
|
2109
3079
|
onSelect: (action) => {
|
|
2110
|
-
if (busy !== void 0) return;
|
|
2111
|
-
const link = sessionDeepLink(browserBase(), id);
|
|
3080
|
+
if (busy !== void 0 || runSessionMoveAction(action, id)) return;
|
|
2112
3081
|
if (action === "rename") beginRename("session", id, session.displayTitle);
|
|
2113
|
-
if (action === "pin") {
|
|
2114
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2115
|
-
setMenu(void 0);
|
|
2116
|
-
}
|
|
2117
3082
|
if (action === "unread") {
|
|
2118
3083
|
setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2119
3084
|
setMenu(void 0);
|
|
@@ -2133,7 +3098,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2133
3098
|
if (action === "copyPath") copy(path);
|
|
2134
3099
|
if (action === "copyTitle") copy(session.displayTitle);
|
|
2135
3100
|
if (action === "copyId") copy(id);
|
|
2136
|
-
if (action === "copyLink") copy(link);
|
|
2137
3101
|
},
|
|
2138
3102
|
portal: true,
|
|
2139
3103
|
dense: true,
|
|
@@ -2145,7 +3109,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2145
3109
|
"aria-label": t("sessions.actions", { name: session.displayTitle }),
|
|
2146
3110
|
onClick: (event) => {
|
|
2147
3111
|
event.stopPropagation();
|
|
2148
|
-
setMenu((current) => current?.id === id && current
|
|
3112
|
+
setMenu((current) => current?.id === id && current?.type === "session" ? void 0 : {
|
|
2149
3113
|
id,
|
|
2150
3114
|
type: "session"
|
|
2151
3115
|
});
|
|
@@ -2156,10 +3120,326 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2156
3120
|
})
|
|
2157
3121
|
]
|
|
2158
3122
|
}, id);
|
|
2159
|
-
})
|
|
2160
|
-
]
|
|
3123
|
+
})]
|
|
3124
|
+
})]
|
|
2161
3125
|
}, workspace.workspaceId);
|
|
2162
3126
|
};
|
|
3127
|
+
const renderWorkspaceCollection = (group) => {
|
|
3128
|
+
const groupId = group.id;
|
|
3129
|
+
const expandKey = `workspace-group:${group.id}`;
|
|
3130
|
+
const isExpanded = expanded[expandKey] ?? true;
|
|
3131
|
+
const members = group.workspaceIds.flatMap((id) => {
|
|
3132
|
+
const workspace = workspaceById.get(id);
|
|
3133
|
+
return workspace === void 0 ? [] : [workspace];
|
|
3134
|
+
});
|
|
3135
|
+
const memberIds = members.map((workspace) => String(workspace.workspaceId));
|
|
3136
|
+
const groupWorkspaceMoveDrop = workspaceDropTarget?.zone === "group" && workspaceDropTarget.groupId === group.id && workspaceDropTarget.crossGroup === true;
|
|
3137
|
+
const groupOrderDrop = workspaceGroupDropTarget?.beforeId === groupId;
|
|
3138
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3139
|
+
className: `dcu-wb-collection${groupOrderDrop ? " dcu-wb-group-order-drop" : ""}${groupWorkspaceMoveDrop ? " dcu-wb-workspace-move-drop" : ""}`,
|
|
3140
|
+
onDragOver: (event) => {
|
|
3141
|
+
const draggedGroupId = readWorkspaceGroupDrag(event.dataTransfer, workspaceGroupDragId);
|
|
3142
|
+
if (draggedGroupId !== void 0) {
|
|
3143
|
+
event.preventDefault();
|
|
3144
|
+
event.stopPropagation();
|
|
3145
|
+
event.dataTransfer.dropEffect = "move";
|
|
3146
|
+
setWorkspaceDropTarget(void 0);
|
|
3147
|
+
const rect = event.currentTarget.querySelector(":scope > .dcu-wb-collection-head")?.getBoundingClientRect() ?? event.currentTarget.getBoundingClientRect();
|
|
3148
|
+
const beforeId = reorderDropBeforeId(workspaceGroupIds, draggedGroupId, groupId, event.clientY > rect.top + rect.height / 2);
|
|
3149
|
+
setWorkspaceGroupDropTarget(beforeId === null ? void 0 : { beforeId });
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
3152
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3153
|
+
if (dragged === void 0) return;
|
|
3154
|
+
event.preventDefault();
|
|
3155
|
+
event.stopPropagation();
|
|
3156
|
+
event.dataTransfer.dropEffect = "move";
|
|
3157
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3158
|
+
if (workspaceGroupIdFor(dragged) === groupId) {
|
|
3159
|
+
const lastId = memberIds[memberIds.length - 1];
|
|
3160
|
+
const beforeId = lastId === void 0 ? null : reorderDropBeforeId(memberIds, dragged, lastId, true);
|
|
3161
|
+
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
3162
|
+
zone: "group",
|
|
3163
|
+
groupId,
|
|
3164
|
+
beforeId
|
|
3165
|
+
});
|
|
3166
|
+
return;
|
|
3167
|
+
}
|
|
3168
|
+
setWorkspaceDropTarget({
|
|
3169
|
+
zone: "group",
|
|
3170
|
+
groupId,
|
|
3171
|
+
ontoGroup: true,
|
|
3172
|
+
crossGroup: true
|
|
3173
|
+
});
|
|
3174
|
+
},
|
|
3175
|
+
onDragLeave: (event) => {
|
|
3176
|
+
if (event.currentTarget.contains(event.relatedTarget)) return;
|
|
3177
|
+
setWorkspaceDropTarget(void 0);
|
|
3178
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3179
|
+
},
|
|
3180
|
+
onDrop: (event) => {
|
|
3181
|
+
const draggedGroupId = readWorkspaceGroupDrag(event.dataTransfer, workspaceGroupDragId);
|
|
3182
|
+
if (draggedGroupId !== void 0) {
|
|
3183
|
+
event.preventDefault();
|
|
3184
|
+
event.stopPropagation();
|
|
3185
|
+
const rect = event.currentTarget.querySelector(":scope > .dcu-wb-collection-head")?.getBoundingClientRect() ?? event.currentTarget.getBoundingClientRect();
|
|
3186
|
+
const beforeId = reorderDropBeforeId(workspaceGroupIds, draggedGroupId, groupId, event.clientY > rect.top + rect.height / 2);
|
|
3187
|
+
setWorkspaceGroupDragId(void 0);
|
|
3188
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3189
|
+
if (beforeId !== null) setWorkspaceGroups((current) => moveWorkspaceGroup(current, draggedGroupId, beforeId));
|
|
3190
|
+
return;
|
|
3191
|
+
}
|
|
3192
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3193
|
+
if (dragged === void 0) return;
|
|
3194
|
+
event.preventDefault();
|
|
3195
|
+
event.stopPropagation();
|
|
3196
|
+
setWorkspaceDragId(void 0);
|
|
3197
|
+
setWorkspaceDropTarget(void 0);
|
|
3198
|
+
setWorkspaceGroups((current) => current.find((candidate) => candidate.workspaceIds.includes(dragged))?.id === groupId ? moveWorkspaceGroupMember(current, dragged, groupId) : assignWorkspaceToGroup(current, dragged, groupId));
|
|
3199
|
+
},
|
|
3200
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3201
|
+
className: `dcu-wb-collection-head${workspaceGroupDragId === groupId ? " dcu-wb-dragging" : ""}`,
|
|
3202
|
+
draggable: true,
|
|
3203
|
+
onDragStart: (event) => {
|
|
3204
|
+
event.stopPropagation();
|
|
3205
|
+
setSessionDrag(void 0);
|
|
3206
|
+
setSessionDropTarget(void 0);
|
|
3207
|
+
setWorkspaceDragId(void 0);
|
|
3208
|
+
setWorkspaceDropTarget(void 0);
|
|
3209
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3210
|
+
writeWorkspaceGroupDrag(event.dataTransfer, groupId, group.title);
|
|
3211
|
+
setDragPreview(event.dataTransfer, group.title);
|
|
3212
|
+
setWorkspaceGroupDragId(groupId);
|
|
3213
|
+
},
|
|
3214
|
+
onDragEnd: () => {
|
|
3215
|
+
setWorkspaceGroupDragId(void 0);
|
|
3216
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3217
|
+
},
|
|
3218
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3219
|
+
type: "button",
|
|
3220
|
+
className: "dcu-wb-collection-label",
|
|
3221
|
+
"aria-expanded": isExpanded,
|
|
3222
|
+
onClick: () => {
|
|
3223
|
+
toggleGroup(expandKey, true);
|
|
3224
|
+
},
|
|
3225
|
+
children: [
|
|
3226
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3227
|
+
className: "dcu-wb-section-caret",
|
|
3228
|
+
"aria-hidden": "true",
|
|
3229
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
3230
|
+
viewBox: "0 0 16 16",
|
|
3231
|
+
width: "12",
|
|
3232
|
+
height: "12",
|
|
3233
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
3234
|
+
d: "M6.25 4.25 10.25 8 6.25 11.75",
|
|
3235
|
+
fill: "none",
|
|
3236
|
+
stroke: "currentColor",
|
|
3237
|
+
strokeWidth: "1.5",
|
|
3238
|
+
strokeLinecap: "round",
|
|
3239
|
+
strokeLinejoin: "round"
|
|
3240
|
+
})
|
|
3241
|
+
})
|
|
3242
|
+
}),
|
|
3243
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: group.title }),
|
|
3244
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3245
|
+
className: "dcu-wb-collection-count",
|
|
3246
|
+
children: members.length
|
|
3247
|
+
})
|
|
3248
|
+
]
|
|
3249
|
+
})
|
|
3250
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DisclosureBody, {
|
|
3251
|
+
className: "dcu-wb-collection-body",
|
|
3252
|
+
open: isExpanded,
|
|
3253
|
+
children: [members.map((workspace) => {
|
|
3254
|
+
const workspaceId = String(workspace.workspaceId);
|
|
3255
|
+
const preciseTarget = workspaceDropTarget?.zone === "group" && workspaceDropTarget.groupId === groupId && workspaceDropTarget.ontoGroup !== true && workspaceDropTarget.crossGroup !== true;
|
|
3256
|
+
const orderDrop = preciseTarget && workspaceDropTarget.beforeId === workspaceId;
|
|
3257
|
+
const orderDropAfter = preciseTarget && workspaceDropTarget.beforeId === void 0 && memberIds[memberIds.length - 1] === workspaceId;
|
|
3258
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3259
|
+
"data-dcu-group-member": true,
|
|
3260
|
+
className: `dcu-wb-group-member${orderDrop ? " dcu-wb-drop" : ""}${orderDropAfter ? " dcu-wb-drop dcu-wb-drop-after" : ""}`,
|
|
3261
|
+
onDragOverCapture: (event) => {
|
|
3262
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3263
|
+
if (dragged === void 0) return;
|
|
3264
|
+
event.preventDefault();
|
|
3265
|
+
event.stopPropagation();
|
|
3266
|
+
event.dataTransfer.dropEffect = "move";
|
|
3267
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
3268
|
+
const beforeId = reorderDropBeforeId(memberIds, dragged, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
3269
|
+
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
3270
|
+
zone: "group",
|
|
3271
|
+
groupId,
|
|
3272
|
+
beforeId,
|
|
3273
|
+
crossGroup: workspaceGroupIdFor(dragged) !== groupId
|
|
3274
|
+
});
|
|
3275
|
+
},
|
|
3276
|
+
onDropCapture: (event) => {
|
|
3277
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3278
|
+
if (dragged === void 0) return;
|
|
3279
|
+
event.preventDefault();
|
|
3280
|
+
event.stopPropagation();
|
|
3281
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
3282
|
+
const beforeId = reorderDropBeforeId(memberIds, dragged, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
3283
|
+
setWorkspaceDragId(void 0);
|
|
3284
|
+
setWorkspaceDropTarget(void 0);
|
|
3285
|
+
if (beforeId === null) return;
|
|
3286
|
+
setWorkspaceGroups((current) => current.find((candidate) => candidate.workspaceIds.includes(dragged))?.id === groupId ? moveWorkspaceGroupMember(current, dragged, groupId, beforeId) : placeWorkspaceInGroup(current, dragged, groupId, beforeId));
|
|
3287
|
+
},
|
|
3288
|
+
children: renderGroup(workspace, "projects")
|
|
3289
|
+
}, workspaceId);
|
|
3290
|
+
}), members.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3291
|
+
className: "dcu-wb-empty",
|
|
3292
|
+
children: t("workspace.empty")
|
|
3293
|
+
})]
|
|
3294
|
+
})]
|
|
3295
|
+
}, group.id);
|
|
3296
|
+
};
|
|
3297
|
+
const renderUngroupedCollection = () => {
|
|
3298
|
+
const ungroupedExpandKey = "workspace-group:ungrouped";
|
|
3299
|
+
const ungroupedExpanded = expanded[ungroupedExpandKey] ?? true;
|
|
3300
|
+
const ungroupedWorkspaceMoveDrop = workspaceDropTarget?.zone === "ungrouped" && workspaceDropTarget.crossGroup === true;
|
|
3301
|
+
const groupOrderDrop = workspaceGroupDropTarget !== void 0 && workspaceGroupDropTarget.beforeId === void 0;
|
|
3302
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3303
|
+
className: `dcu-wb-ungrouped${groupOrderDrop ? " dcu-wb-group-order-drop" : ""}${ungroupedWorkspaceMoveDrop ? " dcu-wb-workspace-move-drop" : ""}`,
|
|
3304
|
+
onDragOver: (event) => {
|
|
3305
|
+
const draggedGroupId = readWorkspaceGroupDrag(event.dataTransfer, workspaceGroupDragId);
|
|
3306
|
+
if (draggedGroupId !== void 0) {
|
|
3307
|
+
event.preventDefault();
|
|
3308
|
+
event.stopPropagation();
|
|
3309
|
+
event.dataTransfer.dropEffect = "move";
|
|
3310
|
+
setWorkspaceDropTarget(void 0);
|
|
3311
|
+
const lastGroupId = workspaceGroupIds[workspaceGroupIds.length - 1];
|
|
3312
|
+
const beforeId = lastGroupId === void 0 ? null : reorderDropBeforeId(workspaceGroupIds, draggedGroupId, lastGroupId, true);
|
|
3313
|
+
setWorkspaceGroupDropTarget(beforeId === null ? void 0 : { beforeId: void 0 });
|
|
3314
|
+
return;
|
|
3315
|
+
}
|
|
3316
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3317
|
+
if (dragged === void 0) return;
|
|
3318
|
+
event.preventDefault();
|
|
3319
|
+
event.stopPropagation();
|
|
3320
|
+
event.dataTransfer.dropEffect = "move";
|
|
3321
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3322
|
+
if (workspaceGroupIdFor(dragged) === void 0) {
|
|
3323
|
+
const lastId = ungroupedGroupIds[ungroupedGroupIds.length - 1];
|
|
3324
|
+
const beforeId = lastId === void 0 ? null : reorderDropBeforeId(ungroupedGroupIds, dragged, lastId, true);
|
|
3325
|
+
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
3326
|
+
zone: "ungrouped",
|
|
3327
|
+
beforeId
|
|
3328
|
+
});
|
|
3329
|
+
return;
|
|
3330
|
+
}
|
|
3331
|
+
setWorkspaceDropTarget({
|
|
3332
|
+
zone: "ungrouped",
|
|
3333
|
+
ontoSection: true,
|
|
3334
|
+
crossGroup: true
|
|
3335
|
+
});
|
|
3336
|
+
},
|
|
3337
|
+
onDragLeave: (event) => {
|
|
3338
|
+
if (event.currentTarget.contains(event.relatedTarget)) return;
|
|
3339
|
+
setWorkspaceDropTarget(void 0);
|
|
3340
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3341
|
+
},
|
|
3342
|
+
onDrop: (event) => {
|
|
3343
|
+
const draggedGroupId = readWorkspaceGroupDrag(event.dataTransfer, workspaceGroupDragId);
|
|
3344
|
+
if (draggedGroupId !== void 0) {
|
|
3345
|
+
event.preventDefault();
|
|
3346
|
+
event.stopPropagation();
|
|
3347
|
+
const lastGroupId = workspaceGroupIds[workspaceGroupIds.length - 1];
|
|
3348
|
+
const beforeId = lastGroupId === void 0 ? null : reorderDropBeforeId(workspaceGroupIds, draggedGroupId, lastGroupId, true);
|
|
3349
|
+
setWorkspaceGroupDragId(void 0);
|
|
3350
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
3351
|
+
if (beforeId !== null) setWorkspaceGroups((current) => moveWorkspaceGroup(current, draggedGroupId));
|
|
3352
|
+
return;
|
|
3353
|
+
}
|
|
3354
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3355
|
+
if (dragged === void 0) return;
|
|
3356
|
+
event.preventDefault();
|
|
3357
|
+
event.stopPropagation();
|
|
3358
|
+
setWorkspaceDragId(void 0);
|
|
3359
|
+
setWorkspaceDropTarget(void 0);
|
|
3360
|
+
setWorkspaceGroups((current) => assignWorkspaceToGroup(current, dragged));
|
|
3361
|
+
run("workspace-order", () => insertWorkspaceBefore(dragged));
|
|
3362
|
+
},
|
|
3363
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3364
|
+
className: "dcu-wb-collection-head",
|
|
3365
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3366
|
+
type: "button",
|
|
3367
|
+
className: "dcu-wb-collection-label",
|
|
3368
|
+
"aria-expanded": ungroupedExpanded,
|
|
3369
|
+
onClick: () => {
|
|
3370
|
+
toggleGroup(ungroupedExpandKey, true);
|
|
3371
|
+
},
|
|
3372
|
+
children: [
|
|
3373
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3374
|
+
className: "dcu-wb-section-caret",
|
|
3375
|
+
"aria-hidden": "true",
|
|
3376
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
3377
|
+
viewBox: "0 0 16 16",
|
|
3378
|
+
width: "12",
|
|
3379
|
+
height: "12",
|
|
3380
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
3381
|
+
d: "M6.25 4.25 10.25 8 6.25 11.75",
|
|
3382
|
+
fill: "none",
|
|
3383
|
+
stroke: "currentColor",
|
|
3384
|
+
strokeWidth: "1.5",
|
|
3385
|
+
strokeLinecap: "round",
|
|
3386
|
+
strokeLinejoin: "round"
|
|
3387
|
+
})
|
|
3388
|
+
})
|
|
3389
|
+
}),
|
|
3390
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("workspace.ungrouped") }),
|
|
3391
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3392
|
+
className: "dcu-wb-collection-count",
|
|
3393
|
+
children: ungroupedGroups.length
|
|
3394
|
+
})
|
|
3395
|
+
]
|
|
3396
|
+
})
|
|
3397
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DisclosureBody, {
|
|
3398
|
+
className: "dcu-wb-collection-body",
|
|
3399
|
+
open: ungroupedExpanded,
|
|
3400
|
+
children: ungroupedGroups.map((workspace) => {
|
|
3401
|
+
const workspaceId = String(workspace.workspaceId);
|
|
3402
|
+
const preciseTarget = workspaceDropTarget?.zone === "ungrouped" && workspaceDropTarget.ontoSection !== true && workspaceDropTarget.crossGroup !== true;
|
|
3403
|
+
const orderDrop = preciseTarget && workspaceDropTarget.beforeId === workspaceId;
|
|
3404
|
+
const orderDropAfter = preciseTarget && workspaceDropTarget.beforeId === void 0 && ungroupedGroupIds[ungroupedGroupIds.length - 1] === workspaceId;
|
|
3405
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3406
|
+
"data-dcu-ungrouped-member": true,
|
|
3407
|
+
className: `dcu-wb-group-member dcu-wb-ungrouped-member${orderDrop ? " dcu-wb-drop" : ""}${orderDropAfter ? " dcu-wb-drop dcu-wb-drop-after" : ""}`,
|
|
3408
|
+
onDragOverCapture: (event) => {
|
|
3409
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3410
|
+
if (dragged === void 0) return;
|
|
3411
|
+
event.preventDefault();
|
|
3412
|
+
event.stopPropagation();
|
|
3413
|
+
event.dataTransfer.dropEffect = "move";
|
|
3414
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
3415
|
+
const beforeId = reorderDropBeforeId(ungroupedGroupIds, dragged, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
3416
|
+
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
3417
|
+
zone: "ungrouped",
|
|
3418
|
+
beforeId,
|
|
3419
|
+
crossGroup: workspaceGroupIdFor(dragged) !== void 0
|
|
3420
|
+
});
|
|
3421
|
+
},
|
|
3422
|
+
onDropCapture: (event) => {
|
|
3423
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3424
|
+
if (dragged === void 0) return;
|
|
3425
|
+
event.preventDefault();
|
|
3426
|
+
event.stopPropagation();
|
|
3427
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
3428
|
+
const beforeId = reorderDropBeforeId(ungroupedGroupIds, dragged, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
3429
|
+
setWorkspaceDragId(void 0);
|
|
3430
|
+
setWorkspaceDropTarget(void 0);
|
|
3431
|
+
if (beforeId === null) return;
|
|
3432
|
+
if (groupedIds.has(dragged)) setWorkspaceGroups((current) => assignWorkspaceToGroup(current, dragged));
|
|
3433
|
+
run("workspace-order", () => insertWorkspaceBefore(dragged, beforeId));
|
|
3434
|
+
},
|
|
3435
|
+
children: renderGroup(workspace, "projects")
|
|
3436
|
+
}, workspaceId);
|
|
3437
|
+
})
|
|
3438
|
+
})]
|
|
3439
|
+
});
|
|
3440
|
+
};
|
|
3441
|
+
const treeRef = (0, react.useRef)(null);
|
|
3442
|
+
useSectionDisclosureMotion(treeRef);
|
|
2163
3443
|
if (!wide) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2164
3444
|
className: "dcu-wb dcu-wb-rail",
|
|
2165
3445
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$4 })
|
|
@@ -2171,7 +3451,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2171
3451
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("style", { children: [
|
|
2172
3452
|
stylesheet$4,
|
|
2173
3453
|
runningStyles,
|
|
2174
|
-
typographyStyles
|
|
3454
|
+
typographyStyles,
|
|
3455
|
+
collectionLayoutStyles
|
|
2175
3456
|
] }),
|
|
2176
3457
|
error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2177
3458
|
className: "dcu-wb-error",
|
|
@@ -2179,6 +3460,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2179
3460
|
children: t("sessions.failed", { message: error })
|
|
2180
3461
|
}),
|
|
2181
3462
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3463
|
+
ref: treeRef,
|
|
2182
3464
|
className: "dcu-wb-tree",
|
|
2183
3465
|
role: "tree",
|
|
2184
3466
|
children: [
|
|
@@ -2189,7 +3471,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2189
3471
|
if (!pinDragActive) return;
|
|
2190
3472
|
event.preventDefault();
|
|
2191
3473
|
event.dataTransfer.dropEffect = "move";
|
|
2192
|
-
if (event.target === event.currentTarget || event.target instanceof Element && event.target.closest(".dcu-wb-section-head") !== null) {
|
|
3474
|
+
if (pinnedGroups.length === 0 || event.target === event.currentTarget || event.target instanceof Element && event.target.closest(".dcu-wb-section-head") !== null) {
|
|
2193
3475
|
const firstId = pinnedGroupIds[0];
|
|
2194
3476
|
const beforeId = firstId === void 0 ? void 0 : reorderDropBeforeId(pinnedGroupIds, workspaceDragId, firstId, false);
|
|
2195
3477
|
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
@@ -2240,46 +3522,53 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2240
3522
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2241
3523
|
className: "dcu-wb-section-body",
|
|
2242
3524
|
"data-open": sectionOpen("pinned"),
|
|
2243
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
event
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
event
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
beforeId
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
3525
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3526
|
+
className: "dcu-wb-pinned-list",
|
|
3527
|
+
children: [
|
|
3528
|
+
pinDragActive && pinnedGroups.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3529
|
+
className: `dcu-wb-pin-start${pinnedHeaderDrop?.kind === "empty" ? " dcu-wb-drop" : ""}`,
|
|
3530
|
+
onDragOver: (event) => {
|
|
3531
|
+
event.preventDefault();
|
|
3532
|
+
event.stopPropagation();
|
|
3533
|
+
event.dataTransfer.dropEffect = "move";
|
|
3534
|
+
setWorkspaceDropTarget({
|
|
3535
|
+
zone: "pinned",
|
|
3536
|
+
beforeId: void 0
|
|
3537
|
+
});
|
|
3538
|
+
}
|
|
3539
|
+
}),
|
|
3540
|
+
pinnedGroups.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3541
|
+
className: "dcu-wb-empty",
|
|
3542
|
+
children: t("workspace.pinnedEmpty")
|
|
3543
|
+
}),
|
|
3544
|
+
pinnedGroups.map((workspace) => renderGroup(workspace, "pinned")),
|
|
3545
|
+
pinDragActive && pinnedGroups.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3546
|
+
className: `dcu-wb-pin-end${workspaceDropTarget?.zone === "pinned" && workspaceDropTarget.beforeId === void 0 ? " dcu-wb-drop" : ""}`,
|
|
3547
|
+
onDragOver: (event) => {
|
|
3548
|
+
if (!pinDragActive) return;
|
|
3549
|
+
event.preventDefault();
|
|
3550
|
+
event.stopPropagation();
|
|
3551
|
+
event.dataTransfer.dropEffect = "move";
|
|
3552
|
+
const lastId = pinnedGroupIds[pinnedGroupIds.length - 1];
|
|
3553
|
+
if (lastId === void 0 || workspaceDragId === void 0) return;
|
|
3554
|
+
const beforeId = reorderDropBeforeId(pinnedGroupIds, workspaceDragId, lastId, true);
|
|
3555
|
+
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
3556
|
+
zone: "pinned",
|
|
3557
|
+
beforeId
|
|
3558
|
+
});
|
|
3559
|
+
}
|
|
3560
|
+
})
|
|
3561
|
+
]
|
|
3562
|
+
})
|
|
2278
3563
|
})]
|
|
2279
3564
|
}),
|
|
2280
3565
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2281
3566
|
className: "dcu-wb-section",
|
|
2282
3567
|
"aria-label": t("workspace.projects"),
|
|
3568
|
+
onDropCapture: (event) => {
|
|
3569
|
+
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
3570
|
+
if (dragged !== void 0 && projectPinned(dragged)) setPinnedWorkspaceIds((ids) => ids.filter((id) => id !== dragged));
|
|
3571
|
+
},
|
|
2283
3572
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2284
3573
|
className: "dcu-wb-section-head",
|
|
2285
3574
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -2306,26 +3595,66 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2306
3595
|
})
|
|
2307
3596
|
})
|
|
2308
3597
|
})]
|
|
2309
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
3598
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2310
3599
|
className: "dcu-wb-actions",
|
|
2311
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3600
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2312
3601
|
type: "button",
|
|
2313
3602
|
className: "dcu-wb-more",
|
|
2314
|
-
"aria-label": t("workspace.
|
|
3603
|
+
"aria-label": t("workspace.createGroup"),
|
|
3604
|
+
title: t("workspace.createGroup"),
|
|
2315
3605
|
onClick: (event) => {
|
|
2316
3606
|
event.stopPropagation();
|
|
2317
|
-
|
|
3607
|
+
setGroupTitleDraft("");
|
|
3608
|
+
setError(void 0);
|
|
3609
|
+
setCreateGroupOpen(true);
|
|
2318
3610
|
},
|
|
2319
3611
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 16 })
|
|
2320
|
-
})
|
|
3612
|
+
}), workspaceGroups.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
3613
|
+
open: groupMenuOpen,
|
|
3614
|
+
onClose: () => {
|
|
3615
|
+
setGroupMenuOpen(false);
|
|
3616
|
+
},
|
|
3617
|
+
items: workspaceGroups.map((group) => ({
|
|
3618
|
+
id: group.id,
|
|
3619
|
+
label: t("workspace.deleteGroup", { name: group.title }),
|
|
3620
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16, { size: 16 }),
|
|
3621
|
+
danger: true
|
|
3622
|
+
})),
|
|
3623
|
+
onSelect: (id) => {
|
|
3624
|
+
setDeleteGroupId(id);
|
|
3625
|
+
setGroupMenuOpen(false);
|
|
3626
|
+
},
|
|
3627
|
+
portal: true,
|
|
3628
|
+
dense: true,
|
|
3629
|
+
compact: true,
|
|
3630
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3631
|
+
type: "button",
|
|
3632
|
+
className: "dcu-wb-more",
|
|
3633
|
+
"aria-label": t("workspace.manageGroups"),
|
|
3634
|
+
title: t("workspace.manageGroups"),
|
|
3635
|
+
onClick: (event) => {
|
|
3636
|
+
event.stopPropagation();
|
|
3637
|
+
setGroupMenuOpen((current) => !current);
|
|
3638
|
+
},
|
|
3639
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
3640
|
+
})
|
|
3641
|
+
})]
|
|
2321
3642
|
})]
|
|
2322
3643
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2323
3644
|
className: "dcu-wb-section-body",
|
|
2324
3645
|
"data-open": sectionOpen("projects"),
|
|
2325
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2326
|
-
className: "dcu-wb-
|
|
2327
|
-
children:
|
|
2328
|
-
|
|
3646
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3647
|
+
className: "dcu-wb-collections",
|
|
3648
|
+
children: [
|
|
3649
|
+
workspaceGroups.map(renderWorkspaceCollection),
|
|
3650
|
+
workspaceGroups.length > 0 && renderUngroupedCollection(),
|
|
3651
|
+
workspaceGroups.length === 0 && ungroupedGroups.map((workspace) => renderGroup(workspace, "projects")),
|
|
3652
|
+
workspaceGroups.length === 0 && ungroupedGroups.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3653
|
+
className: "dcu-wb-empty",
|
|
3654
|
+
children: t("workspace.empty")
|
|
3655
|
+
})
|
|
3656
|
+
]
|
|
3657
|
+
})
|
|
2329
3658
|
})]
|
|
2330
3659
|
}),
|
|
2331
3660
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
@@ -2368,34 +3697,27 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2368
3697
|
const session = sessions.byId[id];
|
|
2369
3698
|
if (session === void 0) return null;
|
|
2370
3699
|
const title = session.displayTitle;
|
|
2371
|
-
const pinned = pinnedSessionIds.includes(id);
|
|
2372
3700
|
const unread = unreadSessionIds.includes(id);
|
|
2373
|
-
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, session
|
|
3701
|
+
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, legacyPendingInteraction(session));
|
|
2374
3702
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
2375
3703
|
id,
|
|
2376
3704
|
title,
|
|
2377
3705
|
selected: sessions.current === id,
|
|
2378
3706
|
menuOpen: menu?.type === "session" && menu.id === id,
|
|
2379
|
-
pinned,
|
|
2380
3707
|
unread,
|
|
2381
3708
|
running: session.running === true,
|
|
2382
3709
|
pendingInteraction,
|
|
2383
3710
|
t,
|
|
2384
|
-
menuItems: sessionMenu(id,
|
|
3711
|
+
menuItems: sessionMenu(id, session.cwd),
|
|
2385
3712
|
draggable: true,
|
|
2386
3713
|
onDragStart: (event) => {
|
|
2387
3714
|
event.stopPropagation();
|
|
2388
3715
|
setWorkspaceDragId(void 0);
|
|
2389
3716
|
setWorkspaceDropTarget(void 0);
|
|
3717
|
+
setWorkspaceGroupDragId(void 0);
|
|
3718
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
2390
3719
|
writeSessionDrag(event.dataTransfer, id, title);
|
|
2391
|
-
|
|
2392
|
-
preview.className = "dcu-wb-drag-ghost";
|
|
2393
|
-
preview.textContent = title;
|
|
2394
|
-
document.body.appendChild(preview);
|
|
2395
|
-
event.dataTransfer.setDragImage(preview, 16, 18);
|
|
2396
|
-
window.requestAnimationFrame(() => {
|
|
2397
|
-
preview.remove();
|
|
2398
|
-
});
|
|
3720
|
+
setDragPreview(event.dataTransfer, title);
|
|
2399
3721
|
setSessionDrag({
|
|
2400
3722
|
sessionId: id,
|
|
2401
3723
|
workspaceId: ""
|
|
@@ -2405,6 +3727,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2405
3727
|
setSessionDrag(void 0);
|
|
2406
3728
|
setSessionDropTarget(void 0);
|
|
2407
3729
|
setWorkspaceDropTarget(void 0);
|
|
3730
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
2408
3731
|
},
|
|
2409
3732
|
menuPoint: menu?.type === "session" && menu.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
2410
3733
|
x: menu.x,
|
|
@@ -2420,9 +3743,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2420
3743
|
type: "session"
|
|
2421
3744
|
} : void 0);
|
|
2422
3745
|
},
|
|
2423
|
-
onPin: () => {
|
|
2424
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2425
|
-
},
|
|
2426
3746
|
onArchive: () => {
|
|
2427
3747
|
run("archive", () => archiveSession(id));
|
|
2428
3748
|
},
|
|
@@ -2432,7 +3752,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2432
3752
|
kind: "session",
|
|
2433
3753
|
id,
|
|
2434
3754
|
title,
|
|
2435
|
-
time: formatHoverTime(session.updatedAt),
|
|
3755
|
+
time: formatHoverTime(session.updatedAt, t),
|
|
2436
3756
|
left: box.left,
|
|
2437
3757
|
top: box.top
|
|
2438
3758
|
});
|
|
@@ -2450,12 +3770,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2450
3770
|
});
|
|
2451
3771
|
},
|
|
2452
3772
|
onSelectAction: (action) => {
|
|
2453
|
-
if (busy !== void 0) return;
|
|
3773
|
+
if (busy !== void 0 || runSessionMoveAction(action, id)) return;
|
|
2454
3774
|
if (action === "rename") beginRename("session", id, title);
|
|
2455
|
-
if (action === "pin") {
|
|
2456
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2457
|
-
setMenu(void 0);
|
|
2458
|
-
}
|
|
2459
3775
|
if (action === "unread") {
|
|
2460
3776
|
setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2461
3777
|
setMenu(void 0);
|
|
@@ -2475,7 +3791,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2475
3791
|
if (action === "copyPath") copy(session.cwd);
|
|
2476
3792
|
if (action === "copyTitle") copy(title);
|
|
2477
3793
|
if (action === "copyId") copy(id);
|
|
2478
|
-
if (action === "copyLink") copy(sessionDeepLink(browserBase(), id));
|
|
2479
3794
|
}
|
|
2480
3795
|
}, id);
|
|
2481
3796
|
})] })
|
|
@@ -2488,15 +3803,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2488
3803
|
onClose: () => {
|
|
2489
3804
|
setHeaderMenu(void 0);
|
|
2490
3805
|
},
|
|
2491
|
-
items: sessionMenu(headerMenu.id, sessions.byId[headerMenu.id].
|
|
3806
|
+
items: sessionMenu(headerMenu.id, sessions.byId[headerMenu.id].cwd ?? groups.items.find((item) => item.visibleIds.includes(headerMenu.id))?.path),
|
|
2492
3807
|
onSelect: (action) => {
|
|
2493
3808
|
const id = headerMenu.id;
|
|
2494
3809
|
const session = sessions.byId[id];
|
|
2495
|
-
if (session === void 0 || busy !== void 0) return;
|
|
3810
|
+
if (session === void 0 || busy !== void 0 || runSessionMoveAction(action, id)) return;
|
|
2496
3811
|
const path = session.cwd ?? groups.items.find((item) => item.visibleIds.includes(id))?.path;
|
|
2497
|
-
const link = sessionDeepLink(browserBase(), id);
|
|
2498
3812
|
if (action === "rename") beginRename("session", id, session.displayTitle);
|
|
2499
|
-
if (action === "pin") setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2500
3813
|
if (action === "unread") setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2501
3814
|
if (action === "archive") run("archive", () => archiveSession(id));
|
|
2502
3815
|
if (action === "delete") {
|
|
@@ -2512,7 +3825,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2512
3825
|
if (action === "copyPath") copy(path);
|
|
2513
3826
|
if (action === "copyTitle") copy(session.displayTitle);
|
|
2514
3827
|
if (action === "copyId") copy(id);
|
|
2515
|
-
if (action === "copyLink") copy(link);
|
|
2516
3828
|
setHeaderMenu(void 0);
|
|
2517
3829
|
},
|
|
2518
3830
|
portal: true,
|
|
@@ -2527,8 +3839,89 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2527
3839
|
t,
|
|
2528
3840
|
onEditWorkspace: (id, title) => {
|
|
2529
3841
|
beginRename("workspace", id, title);
|
|
3842
|
+
},
|
|
3843
|
+
onToggleWorkspacePin: (id) => {
|
|
3844
|
+
setPinnedWorkspaceIds((ids) => togglePinnedWorkspace(ids, id));
|
|
2530
3845
|
}
|
|
2531
3846
|
}),
|
|
3847
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3848
|
+
open: createGroupOpen,
|
|
3849
|
+
onClose: () => {
|
|
3850
|
+
setCreateGroupOpen(false);
|
|
3851
|
+
setGroupTitleDraft("");
|
|
3852
|
+
setError(void 0);
|
|
3853
|
+
},
|
|
3854
|
+
closeLabel: t("sessions.close"),
|
|
3855
|
+
title: t("workspace.createGroup"),
|
|
3856
|
+
description: t("workspace.createGroupDescription"),
|
|
3857
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3858
|
+
className: "dcu-wb-rename-actions",
|
|
3859
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3860
|
+
variant: "outline",
|
|
3861
|
+
onClick: () => {
|
|
3862
|
+
setCreateGroupOpen(false);
|
|
3863
|
+
setGroupTitleDraft("");
|
|
3864
|
+
setError(void 0);
|
|
3865
|
+
},
|
|
3866
|
+
children: t("sessions.cancel")
|
|
3867
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3868
|
+
variant: "primary",
|
|
3869
|
+
disabled: groupTitleDraft.trim() === "",
|
|
3870
|
+
onClick: submitCreateGroup,
|
|
3871
|
+
children: t("sessions.save")
|
|
3872
|
+
})]
|
|
3873
|
+
}),
|
|
3874
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3875
|
+
className: "dcu-wb-rename-input",
|
|
3876
|
+
"aria-label": t("workspace.groupName"),
|
|
3877
|
+
value: groupTitleDraft,
|
|
3878
|
+
autoFocus: true,
|
|
3879
|
+
onChange: (event) => {
|
|
3880
|
+
setGroupTitleDraft(event.target.value);
|
|
3881
|
+
setError(void 0);
|
|
3882
|
+
},
|
|
3883
|
+
onKeyDown: (event) => {
|
|
3884
|
+
if (event.key === "Enter") {
|
|
3885
|
+
event.preventDefault();
|
|
3886
|
+
submitCreateGroup();
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
}), error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3890
|
+
className: "dcu-wb-error",
|
|
3891
|
+
role: "alert",
|
|
3892
|
+
children: t("sessions.failed", { message: error })
|
|
3893
|
+
})]
|
|
3894
|
+
}),
|
|
3895
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3896
|
+
open: deleteGroupId !== void 0,
|
|
3897
|
+
onClose: () => {
|
|
3898
|
+
setDeleteGroupId(void 0);
|
|
3899
|
+
},
|
|
3900
|
+
closeLabel: t("sessions.close"),
|
|
3901
|
+
title: t("workspace.deleteGroup", { name: workspaceGroups.find((group) => group.id === deleteGroupId)?.title ?? "" }),
|
|
3902
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3903
|
+
className: "dcu-wb-rename-actions",
|
|
3904
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3905
|
+
variant: "outline",
|
|
3906
|
+
onClick: () => {
|
|
3907
|
+
setDeleteGroupId(void 0);
|
|
3908
|
+
},
|
|
3909
|
+
children: t("sessions.cancel")
|
|
3910
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3911
|
+
variant: "outline",
|
|
3912
|
+
className: "dcu-wb-delete-button",
|
|
3913
|
+
onClick: () => {
|
|
3914
|
+
if (deleteGroupId !== void 0) setWorkspaceGroups((current) => deleteWorkspaceGroup(current, deleteGroupId));
|
|
3915
|
+
setDeleteGroupId(void 0);
|
|
3916
|
+
},
|
|
3917
|
+
children: t("workspace.deleteGroupAction")
|
|
3918
|
+
})]
|
|
3919
|
+
}),
|
|
3920
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3921
|
+
className: "dcu-wb-delete-copy",
|
|
3922
|
+
children: t("workspace.deleteGroupDescription")
|
|
3923
|
+
})
|
|
3924
|
+
}),
|
|
2532
3925
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2533
3926
|
open: renameTarget !== void 0,
|
|
2534
3927
|
onClose: () => {
|
|
@@ -2574,6 +3967,98 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2574
3967
|
children: t("sessions.failed", { message: error })
|
|
2575
3968
|
})]
|
|
2576
3969
|
}),
|
|
3970
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
3971
|
+
open: archiveWorkspaceTarget !== void 0,
|
|
3972
|
+
onClose: () => {
|
|
3973
|
+
if (busy !== "archive-workspace") {
|
|
3974
|
+
setArchiveWorkspaceTarget(void 0);
|
|
3975
|
+
setError(void 0);
|
|
3976
|
+
}
|
|
3977
|
+
},
|
|
3978
|
+
closeLabel: t("sessions.close"),
|
|
3979
|
+
title: t("workspace.archiveTitle", { count: archiveWorkspaceTarget?.sessionIds.length ?? 0 }),
|
|
3980
|
+
description: archiveWorkspaceTarget === void 0 ? void 0 : t("workspace.archiveDescription", { name: archiveWorkspaceTarget.title }),
|
|
3981
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3982
|
+
className: "dcu-wb-rename-actions",
|
|
3983
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3984
|
+
variant: "outline",
|
|
3985
|
+
disabled: busy === "archive-workspace",
|
|
3986
|
+
onClick: () => {
|
|
3987
|
+
setArchiveWorkspaceTarget(void 0);
|
|
3988
|
+
setError(void 0);
|
|
3989
|
+
},
|
|
3990
|
+
children: t("sessions.cancel")
|
|
3991
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3992
|
+
variant: "primary",
|
|
3993
|
+
disabled: busy === "archive-workspace",
|
|
3994
|
+
onClick: submitArchiveWorkspace,
|
|
3995
|
+
children: t("workspace.archiveConfirm")
|
|
3996
|
+
})]
|
|
3997
|
+
}),
|
|
3998
|
+
children: [busy === "archive-workspace" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3999
|
+
className: "dcu-wb-error",
|
|
4000
|
+
role: "status",
|
|
4001
|
+
children: t("workspace.archivePending")
|
|
4002
|
+
}), error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4003
|
+
className: "dcu-wb-error",
|
|
4004
|
+
role: "alert",
|
|
4005
|
+
children: t("sessions.failed", { message: error })
|
|
4006
|
+
})]
|
|
4007
|
+
}),
|
|
4008
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
4009
|
+
open: sessionMoveTarget !== void 0,
|
|
4010
|
+
onClose: () => {
|
|
4011
|
+
if (busy !== "session-move") {
|
|
4012
|
+
setSessionMoveTarget(void 0);
|
|
4013
|
+
setError(void 0);
|
|
4014
|
+
}
|
|
4015
|
+
},
|
|
4016
|
+
closeLabel: t("sessions.close"),
|
|
4017
|
+
title: t("sessions.moveConfirmTitle", { project: sessionMoveTarget?.targetWorkspaceTitle ?? "" }),
|
|
4018
|
+
description: sessionMoveTarget === void 0 ? void 0 : t("sessions.moveConfirmDescription", { name: sessionMoveTarget.sessionTitle }),
|
|
4019
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4020
|
+
className: "dcu-wb-rename-actions",
|
|
4021
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4022
|
+
variant: "outline",
|
|
4023
|
+
disabled: busy === "session-move",
|
|
4024
|
+
onClick: () => {
|
|
4025
|
+
setSessionMoveTarget(void 0);
|
|
4026
|
+
setError(void 0);
|
|
4027
|
+
},
|
|
4028
|
+
children: t("sessions.cancel")
|
|
4029
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4030
|
+
variant: "primary",
|
|
4031
|
+
disabled: busy === "session-move",
|
|
4032
|
+
onClick: submitSessionMove,
|
|
4033
|
+
children: t("sessions.moveConfirmAction")
|
|
4034
|
+
})]
|
|
4035
|
+
}),
|
|
4036
|
+
children: [
|
|
4037
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4038
|
+
className: "dcu-wb-move-target",
|
|
4039
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4040
|
+
className: "dcu-wb-move-target-copy",
|
|
4041
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4042
|
+
className: "dcu-wb-move-project",
|
|
4043
|
+
children: sessionMoveTarget?.targetWorkspaceTitle
|
|
4044
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4045
|
+
className: "dcu-wb-move-path",
|
|
4046
|
+
children: sessionMoveTarget?.targetPath
|
|
4047
|
+
})]
|
|
4048
|
+
})]
|
|
4049
|
+
}),
|
|
4050
|
+
busy === "session-move" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4051
|
+
className: "dcu-wb-error",
|
|
4052
|
+
role: "status",
|
|
4053
|
+
children: t("sessions.movePending")
|
|
4054
|
+
}),
|
|
4055
|
+
error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4056
|
+
className: "dcu-wb-error",
|
|
4057
|
+
role: "alert",
|
|
4058
|
+
children: t("sessions.failed", { message: error })
|
|
4059
|
+
})
|
|
4060
|
+
]
|
|
4061
|
+
}),
|
|
2577
4062
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2578
4063
|
open: deleteTarget !== void 0,
|
|
2579
4064
|
onClose: () => {
|
|
@@ -2632,13 +4117,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2632
4117
|
function storage() {
|
|
2633
4118
|
return browserStorage();
|
|
2634
4119
|
}
|
|
2635
|
-
/**
|
|
4120
|
+
/** 频道/定时共用的本地未读标记。 */
|
|
2636
4121
|
function useSessionFlags(current) {
|
|
2637
|
-
const [pinnedSessionIds, setPinnedSessionIds] = (0, react.useState)(() => readSessionIds(storage(), SESSION_PINS_STORAGE_KEY));
|
|
2638
4122
|
const [unreadSessionIds, setUnreadSessionIds] = (0, react.useState)(() => readSessionIds(storage(), SESSION_UNREAD_STORAGE_KEY));
|
|
2639
|
-
(0, react.useEffect)(() => {
|
|
2640
|
-
writeSessionIds(storage(), SESSION_PINS_STORAGE_KEY, pinnedSessionIds);
|
|
2641
|
-
}, [pinnedSessionIds]);
|
|
2642
4123
|
(0, react.useEffect)(() => {
|
|
2643
4124
|
writeSessionIds(storage(), SESSION_UNREAD_STORAGE_KEY, unreadSessionIds);
|
|
2644
4125
|
}, [unreadSessionIds]);
|
|
@@ -2646,8 +4127,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2646
4127
|
if (current !== void 0) setUnreadSessionIds((ids) => ids.filter((id) => id !== current));
|
|
2647
4128
|
}, [current]);
|
|
2648
4129
|
return {
|
|
2649
|
-
pinnedSessionIds,
|
|
2650
|
-
setPinnedSessionIds,
|
|
2651
4130
|
unreadSessionIds,
|
|
2652
4131
|
setUnreadSessionIds
|
|
2653
4132
|
};
|
|
@@ -2662,7 +4141,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2662
4141
|
onLeave: hideTip
|
|
2663
4142
|
});
|
|
2664
4143
|
}
|
|
2665
|
-
function useBusyAction(onSuccess) {
|
|
4144
|
+
function useBusyAction(t, onSuccess) {
|
|
2666
4145
|
const [busy, setBusy] = (0, react.useState)();
|
|
2667
4146
|
const [error, setError] = (0, react.useState)();
|
|
2668
4147
|
const busyRef = (0, react.useRef)();
|
|
@@ -2675,7 +4154,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2675
4154
|
await action();
|
|
2676
4155
|
onSuccess?.();
|
|
2677
4156
|
} catch (reason) {
|
|
2678
|
-
setError(reason
|
|
4157
|
+
setError(userErrorText(reason, t));
|
|
2679
4158
|
} finally {
|
|
2680
4159
|
busyRef.current = void 0;
|
|
2681
4160
|
setBusy(void 0);
|
|
@@ -2705,7 +4184,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2705
4184
|
const target = deleteTarget;
|
|
2706
4185
|
run("delete", async () => {
|
|
2707
4186
|
await actions.deleteSession(target.id);
|
|
2708
|
-
flags.setPinnedSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
2709
4187
|
flags.setUnreadSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
2710
4188
|
setDeleteTarget(void 0);
|
|
2711
4189
|
});
|
|
@@ -2719,10 +4197,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2719
4197
|
setRenameDraft(title);
|
|
2720
4198
|
closeMenu();
|
|
2721
4199
|
}
|
|
2722
|
-
if (action === "pin") {
|
|
2723
|
-
flags.setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2724
|
-
closeMenu();
|
|
2725
|
-
}
|
|
2726
4200
|
if (action === "unread") {
|
|
2727
4201
|
flags.setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2728
4202
|
closeMenu();
|
|
@@ -2742,9 +4216,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2742
4216
|
if (action === "copyId") run("copy", async () => {
|
|
2743
4217
|
await (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(id);
|
|
2744
4218
|
});
|
|
2745
|
-
if (action === "copyLink") run("copy", async () => {
|
|
2746
|
-
await (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(copySessionLink(id));
|
|
2747
|
-
});
|
|
2748
4219
|
};
|
|
2749
4220
|
return {
|
|
2750
4221
|
renameTarget,
|
|
@@ -2877,15 +4348,16 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2877
4348
|
})
|
|
2878
4349
|
});
|
|
2879
4350
|
}
|
|
2880
|
-
function ChannelBrowserTree({ openSession, archiveSession, deleteSession, forkSession, renameSession, useSessions, useSessionPendingInteraction, t, menu, setMenu }) {
|
|
4351
|
+
function ChannelBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useWorkspaces, t, menu, setMenu }) {
|
|
2881
4352
|
const sessions = useSessions((state) => state);
|
|
4353
|
+
const workspaces = useWorkspaces?.((state) => state);
|
|
2882
4354
|
const pendingInteractions = (useSessionPendingInteraction ?? useEmptySessionPendingInteraction)((state) => state);
|
|
2883
4355
|
const [groups, setGroups] = (0, react.useState)([]);
|
|
2884
4356
|
const [pollError, setPollError] = (0, react.useState)();
|
|
2885
4357
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(browserStorage(), CHANNEL_EXPANSION_STORAGE_KEY));
|
|
2886
4358
|
const flags = useSessionFlags(sessions.current);
|
|
2887
4359
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
2888
|
-
const { busy, error, setError, run } = useBusyAction(() => {
|
|
4360
|
+
const { busy, error, setError, run } = useBusyAction(t, () => {
|
|
2889
4361
|
setMenu(void 0);
|
|
2890
4362
|
});
|
|
2891
4363
|
const dialogs = useSessionDialogs({
|
|
@@ -2910,7 +4382,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2910
4382
|
const timeout = window.setTimeout(() => {
|
|
2911
4383
|
controller.abort();
|
|
2912
4384
|
}, 8e3);
|
|
2913
|
-
loadChannelGroups(controller.signal).then((next) => {
|
|
4385
|
+
loadChannelGroups(controller.signal, t("channel.unknown")).then((next) => {
|
|
2914
4386
|
if (!disposed) {
|
|
2915
4387
|
setGroups(next);
|
|
2916
4388
|
setPollError(void 0);
|
|
@@ -2975,22 +4447,24 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2975
4447
|
const selected = sessions.current === id;
|
|
2976
4448
|
const running = session.running || sessions.byId[id]?.running === true;
|
|
2977
4449
|
const updatedAt = session.updatedAt ?? sessions.byId[id]?.updatedAt;
|
|
2978
|
-
const pinned = flags.pinnedSessionIds.includes(id);
|
|
2979
4450
|
const unread = flags.unreadSessionIds.includes(id);
|
|
2980
4451
|
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, sessions.byId[id]?.pendingInteraction);
|
|
4452
|
+
const moveTargets = moveSession === void 0 || workspaces === void 0 ? void 0 : sessionMoveTargets(workspaces.items, id).map((target) => ({
|
|
4453
|
+
...target,
|
|
4454
|
+
id: moveSessionActionId(target.id)
|
|
4455
|
+
}));
|
|
2981
4456
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
2982
4457
|
id,
|
|
2983
4458
|
title,
|
|
2984
4459
|
selected,
|
|
2985
4460
|
menuOpen: menu?.id === id,
|
|
2986
|
-
pinned,
|
|
2987
4461
|
unread,
|
|
2988
4462
|
running,
|
|
2989
4463
|
pendingInteraction,
|
|
2990
4464
|
t,
|
|
2991
4465
|
menuItems: sessionMenuItems(t, {
|
|
2992
|
-
|
|
2993
|
-
|
|
4466
|
+
unread,
|
|
4467
|
+
moveTargets
|
|
2994
4468
|
}),
|
|
2995
4469
|
menuPoint: menu?.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
2996
4470
|
x: menu.x,
|
|
@@ -3003,9 +4477,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3003
4477
|
onMenuChange: (open) => {
|
|
3004
4478
|
setMenu(open ? { id } : void 0);
|
|
3005
4479
|
},
|
|
3006
|
-
onPin: () => {
|
|
3007
|
-
flags.setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
3008
|
-
},
|
|
3009
4480
|
onArchive: () => {
|
|
3010
4481
|
run("archive", () => archiveSession(id));
|
|
3011
4482
|
},
|
|
@@ -3014,7 +4485,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3014
4485
|
showTip({
|
|
3015
4486
|
title,
|
|
3016
4487
|
project: label,
|
|
3017
|
-
time: updatedAt === void 0 ? void 0 : formatHoverTime(updatedAt),
|
|
4488
|
+
time: updatedAt === void 0 ? void 0 : formatHoverTime(updatedAt, t),
|
|
3018
4489
|
left: box.left,
|
|
3019
4490
|
top: box.top
|
|
3020
4491
|
});
|
|
@@ -3031,7 +4502,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3031
4502
|
});
|
|
3032
4503
|
},
|
|
3033
4504
|
onSelectAction: (action) => {
|
|
3034
|
-
if (busy
|
|
4505
|
+
if (busy !== void 0) return;
|
|
4506
|
+
const targetWorkspaceId = parseMoveSessionActionId(action);
|
|
4507
|
+
if (targetWorkspaceId !== void 0 && moveSession !== void 0) {
|
|
4508
|
+
setMenu(void 0);
|
|
4509
|
+
run("session-move", () => moveSession(id, targetWorkspaceId));
|
|
4510
|
+
return;
|
|
4511
|
+
}
|
|
4512
|
+
dialogs.handleAction(action, id, title);
|
|
3035
4513
|
}
|
|
3036
4514
|
}, id);
|
|
3037
4515
|
})]
|
|
@@ -3134,7 +4612,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3134
4612
|
})]
|
|
3135
4613
|
});
|
|
3136
4614
|
}
|
|
3137
|
-
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, renameSession, useSessions, useSessionPendingInteraction, useWorkspaces, t, openTaskSettings, menu, setMenu }) {
|
|
4615
|
+
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useWorkspaces, t, openTaskSettings, menu, setMenu }) {
|
|
3138
4616
|
const sessions = useSessions((state) => state);
|
|
3139
4617
|
const pendingInteractions = (useSessionPendingInteraction ?? useEmptySessionPendingInteraction)((state) => state);
|
|
3140
4618
|
const workspaces = useWorkspaces((state) => state);
|
|
@@ -3143,7 +4621,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3143
4621
|
const [archiveGroupTarget, setArchiveGroupTarget] = (0, react.useState)();
|
|
3144
4622
|
const flags = useSessionFlags(sessions.current);
|
|
3145
4623
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
3146
|
-
const { busy, error, setError, run } = useBusyAction(() => {
|
|
4624
|
+
const { busy, error, setError, run } = useBusyAction(t, () => {
|
|
3147
4625
|
setMenu(void 0);
|
|
3148
4626
|
});
|
|
3149
4627
|
const dialogs = useSessionDialogs({
|
|
@@ -3186,10 +4664,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3186
4664
|
updatedAt: session.updatedAt,
|
|
3187
4665
|
running: session.running === true
|
|
3188
4666
|
}];
|
|
3189
|
-
}));
|
|
4667
|
+
}), t("meta.locale"));
|
|
3190
4668
|
}, [
|
|
3191
4669
|
sessions.byId,
|
|
3192
4670
|
sessions.ids,
|
|
4671
|
+
t,
|
|
3193
4672
|
workspaces.archivedSessionIds
|
|
3194
4673
|
]);
|
|
3195
4674
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
@@ -3267,22 +4746,24 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3267
4746
|
}), isExpanded && group.sessions.map((session) => {
|
|
3268
4747
|
const id = session.id;
|
|
3269
4748
|
const title = session.title;
|
|
3270
|
-
const pinned = flags.pinnedSessionIds.includes(id);
|
|
3271
4749
|
const unread = flags.unreadSessionIds.includes(id);
|
|
3272
4750
|
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, sessions.byId[id]?.pendingInteraction);
|
|
4751
|
+
const moveTargets = moveSession === void 0 ? void 0 : sessionMoveTargets(workspaces.items ?? [], id).map((target) => ({
|
|
4752
|
+
...target,
|
|
4753
|
+
id: moveSessionActionId(target.id)
|
|
4754
|
+
}));
|
|
3273
4755
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
3274
4756
|
id,
|
|
3275
4757
|
title,
|
|
3276
4758
|
selected: sessions.current === id,
|
|
3277
4759
|
menuOpen: menu?.id === id,
|
|
3278
|
-
pinned,
|
|
3279
4760
|
unread,
|
|
3280
4761
|
running: session.running,
|
|
3281
4762
|
pendingInteraction,
|
|
3282
4763
|
t,
|
|
3283
4764
|
menuItems: sessionMenuItems(t, {
|
|
3284
|
-
|
|
3285
|
-
|
|
4765
|
+
unread,
|
|
4766
|
+
moveTargets
|
|
3286
4767
|
}),
|
|
3287
4768
|
menuPoint: menu?.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
3288
4769
|
x: menu.x,
|
|
@@ -3295,9 +4776,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3295
4776
|
onMenuChange: (open) => {
|
|
3296
4777
|
setMenu(open ? { id } : void 0);
|
|
3297
4778
|
},
|
|
3298
|
-
onPin: () => {
|
|
3299
|
-
flags.setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
3300
|
-
},
|
|
3301
4779
|
onArchive: () => {
|
|
3302
4780
|
run("archive", () => archiveSession(id));
|
|
3303
4781
|
},
|
|
@@ -3306,7 +4784,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3306
4784
|
showTip({
|
|
3307
4785
|
title,
|
|
3308
4786
|
project: group.label,
|
|
3309
|
-
time: session.updatedAt === void 0 ? void 0 : formatHoverTime(session.updatedAt),
|
|
4787
|
+
time: session.updatedAt === void 0 ? void 0 : formatHoverTime(session.updatedAt, t),
|
|
3310
4788
|
left: box.left,
|
|
3311
4789
|
top: box.top
|
|
3312
4790
|
});
|
|
@@ -3323,7 +4801,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3323
4801
|
});
|
|
3324
4802
|
},
|
|
3325
4803
|
onSelectAction: (action) => {
|
|
3326
|
-
if (busy
|
|
4804
|
+
if (busy !== void 0) return;
|
|
4805
|
+
const targetWorkspaceId = parseMoveSessionActionId(action);
|
|
4806
|
+
if (targetWorkspaceId !== void 0 && moveSession !== void 0) {
|
|
4807
|
+
setMenu(void 0);
|
|
4808
|
+
run("session-move", () => moveSession(id, targetWorkspaceId));
|
|
4809
|
+
return;
|
|
4810
|
+
}
|
|
4811
|
+
dialogs.handleAction(action, id, title);
|
|
3327
4812
|
}
|
|
3328
4813
|
}, id);
|
|
3329
4814
|
})]
|
|
@@ -3368,14 +4853,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3368
4853
|
const target = archiveGroupTarget;
|
|
3369
4854
|
run("archive-group", async () => {
|
|
3370
4855
|
const result = await archiveScheduleGroup(target.sessionIds, (id) => archiveSession(id));
|
|
3371
|
-
flags.setPinnedSessionIds((ids) => ids.filter((id) => !result.archivedIds.includes(id)));
|
|
3372
4856
|
flags.setUnreadSessionIds((ids) => ids.filter((id) => !result.archivedIds.includes(id)));
|
|
3373
4857
|
if (result.failedIds.length > 0) {
|
|
3374
4858
|
setArchiveGroupTarget({
|
|
3375
4859
|
...target,
|
|
3376
4860
|
sessionIds: result.failedIds
|
|
3377
4861
|
});
|
|
3378
|
-
throw new
|
|
4862
|
+
throw new UserFacingError(t("schedule.archiveGroupPartial", {
|
|
3379
4863
|
archived: result.archivedIds.length,
|
|
3380
4864
|
failed: result.failedIds.length
|
|
3381
4865
|
}));
|
|
@@ -3409,9 +4893,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3409
4893
|
]
|
|
3410
4894
|
});
|
|
3411
4895
|
}
|
|
4896
|
+
const visibleSidebarWidths = /* @__PURE__ */ new WeakMap();
|
|
3412
4897
|
/** 解析宿主 AppFrame 的 grid-template-columns。 */
|
|
3413
4898
|
function parseSidebarGrid(value) {
|
|
3414
|
-
const match = /^(\d+(?:\.\d+)?)px\s+(minmax\(0
|
|
4899
|
+
const match = /^(\d+(?:\.\d+)?)px\s+(minmax\(0(?:px)?,\s*1fr\))\s+(\d+(?:\.\d+)?)px$/.exec(value.trim());
|
|
3415
4900
|
if (match === null) return void 0;
|
|
3416
4901
|
return {
|
|
3417
4902
|
sidebar: Number(match[1]),
|
|
@@ -3419,41 +4904,41 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3419
4904
|
details: Number(match[3])
|
|
3420
4905
|
};
|
|
3421
4906
|
}
|
|
3422
|
-
/**
|
|
3423
|
-
* Translate the DSH host's 264–420px drag range to Codex's measured
|
|
3424
|
-
* 240–520px range, preserving the 280px-host / 275px-Codex default anchor.
|
|
3425
|
-
*/
|
|
3426
|
-
function slimedSidebarWidth(hostWidth, collapsed, viewportWidth = Number.POSITIVE_INFINITY) {
|
|
3427
|
-
if (collapsed || hostWidth <= 80) return hostWidth;
|
|
3428
|
-
const maximum = Math.max(240, Math.min(520, viewportWidth - 240));
|
|
3429
|
-
const source = Math.max(264, Math.min(420, hostWidth));
|
|
3430
|
-
if (source <= 280) return 240 + (source - 264) * 35 / 16;
|
|
3431
|
-
return 275 + (source - 280) * (maximum - 275) / 140;
|
|
3432
|
-
}
|
|
3433
|
-
function slimedGridTemplate(tracks, collapsed, viewportWidth = Number.POSITIVE_INFINITY) {
|
|
3434
|
-
return `${slimedSidebarWidth(tracks.sidebar, collapsed, viewportWidth)}px ${tracks.middle} ${tracks.details}px`;
|
|
3435
|
-
}
|
|
3436
4907
|
function findSidebarFrame(root) {
|
|
3437
4908
|
const marked = root.querySelector("[data-sidebar-collapsed]");
|
|
3438
4909
|
if (marked !== null) return marked;
|
|
3439
4910
|
for (const node of root.querySelectorAll("div")) if (parseSidebarGrid(node.style.gridTemplateColumns) !== void 0) return node;
|
|
3440
4911
|
}
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
frame.removeAttribute("data-dcu-codex-sidebar-grid");
|
|
3444
|
-
return false;
|
|
3445
|
-
}
|
|
4912
|
+
/** 同步侧栏网格和拖拽柄,保证两者始终使用同一个可见宽度。 */
|
|
4913
|
+
function applySidebarWidth(frame, width) {
|
|
3446
4914
|
const tracks = parseSidebarGrid(frame.style.gridTemplateColumns);
|
|
3447
|
-
if (tracks === void 0) return false;
|
|
3448
|
-
|
|
3449
|
-
const next =
|
|
3450
|
-
|
|
3451
|
-
if (frame.style.gridTemplateColumns
|
|
3452
|
-
frame.style.gridTemplateColumns = next;
|
|
3453
|
-
frame.setAttribute("data-dcu-codex-sidebar-grid", next);
|
|
4915
|
+
if (tracks === void 0 || frame.hasAttribute("data-sidebar-collapsed")) return false;
|
|
4916
|
+
visibleSidebarWidths.set(frame, width);
|
|
4917
|
+
const next = `${width}px ${tracks.middle} ${tracks.details}px`;
|
|
4918
|
+
const changed = frame.style.gridTemplateColumns !== next;
|
|
4919
|
+
if (changed) frame.style.gridTemplateColumns = next;
|
|
3454
4920
|
const handle = frame.querySelector("[data-side=\"sidebar\"]");
|
|
3455
|
-
if (handle !== null
|
|
3456
|
-
return
|
|
4921
|
+
if (handle !== null) handle.style.left = `${width}px`;
|
|
4922
|
+
return changed;
|
|
4923
|
+
}
|
|
4924
|
+
function applySlimSidebar(frame) {
|
|
4925
|
+
if (frame.hasAttribute("data-dragging")) return false;
|
|
4926
|
+
if (parseSidebarGrid(frame.style.gridTemplateColumns) === void 0 || frame.hasAttribute("data-sidebar-collapsed")) return false;
|
|
4927
|
+
const changed = applySidebarWidth(frame, frame.hasAttribute("data-dcu-codex-sidebar-initialized") ? visibleSidebarWidths.get(frame) ?? 240 : 240);
|
|
4928
|
+
frame.setAttribute("data-dcu-codex-sidebar-initialized", "");
|
|
4929
|
+
return changed;
|
|
4930
|
+
}
|
|
4931
|
+
/** 仅在首帧覆盖宿主默认宽度时关闭过渡,避免刷新出现收缩动画。 */
|
|
4932
|
+
function pauseInitialSidebarTransition(frame) {
|
|
4933
|
+
const handle = frame.querySelector("[data-side=\"sidebar\"]");
|
|
4934
|
+
const frameTransition = frame.style.transition;
|
|
4935
|
+
const handleTransition = handle?.style.transition;
|
|
4936
|
+
frame.style.transition = "none";
|
|
4937
|
+
if (handle !== null) handle.style.transition = "none";
|
|
4938
|
+
return () => {
|
|
4939
|
+
frame.style.transition = frameTransition;
|
|
4940
|
+
if (handle !== null && handleTransition !== void 0) handle.style.transition = handleTransition;
|
|
4941
|
+
};
|
|
3457
4942
|
}
|
|
3458
4943
|
function observeSlimSidebar() {
|
|
3459
4944
|
if (typeof document === "undefined" || document.body === null) return () => {};
|
|
@@ -3472,7 +4957,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3472
4957
|
attributeFilter: [
|
|
3473
4958
|
"style",
|
|
3474
4959
|
"data-sidebar-collapsed",
|
|
3475
|
-
"data-dragging"
|
|
4960
|
+
"data-dragging",
|
|
4961
|
+
"data-dcu-codex-sidebar-initialized"
|
|
3476
4962
|
]
|
|
3477
4963
|
});
|
|
3478
4964
|
};
|
|
@@ -3481,7 +4967,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3481
4967
|
applying = true;
|
|
3482
4968
|
try {
|
|
3483
4969
|
if (frame === void 0 || !frame.isConnected) watchFrame(findSidebarFrame(document));
|
|
3484
|
-
if (frame !== void 0)
|
|
4970
|
+
if (frame !== void 0) {
|
|
4971
|
+
const restoreTransition = frame.hasAttribute("data-dcu-codex-sidebar-initialized") ? void 0 : pauseInitialSidebarTransition(frame);
|
|
4972
|
+
const changed = applySlimSidebar(frame);
|
|
4973
|
+
if (restoreTransition !== void 0) {
|
|
4974
|
+
if (!changed) restoreTransition();
|
|
4975
|
+
else window.requestAnimationFrame(() => window.requestAnimationFrame(restoreTransition));
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
3485
4978
|
} finally {
|
|
3486
4979
|
applying = false;
|
|
3487
4980
|
}
|
|
@@ -3509,9 +5002,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3509
5002
|
}
|
|
3510
5003
|
//#endregion
|
|
3511
5004
|
//#region src/client/sidebar-drag.ts
|
|
3512
|
-
|
|
5005
|
+
const SIDEBAR_MAX_PX = 420;
|
|
5006
|
+
/** 左移超过开始宽度的一半时收起侧栏,避免轻微拖动误触。 */
|
|
3513
5007
|
function shouldCollapseOnSidebarDrag(startWidth, startX, endX) {
|
|
3514
|
-
return
|
|
5008
|
+
return startX - endX > startWidth / 2;
|
|
5009
|
+
}
|
|
5010
|
+
/** 直接按可见宽度计算拖拽结果,绕开宿主与 Codex 不一致的最小宽度。 */
|
|
5011
|
+
function sidebarWidthDuringDrag(startWidth, startX, currentX) {
|
|
5012
|
+
return Math.min(SIDEBAR_MAX_PX, Math.max(240, startWidth + currentX - startX));
|
|
3515
5013
|
}
|
|
3516
5014
|
function isSidebarDragHandle(target) {
|
|
3517
5015
|
if (target === null || typeof target !== "object" || !("closest" in target)) return false;
|
|
@@ -3554,20 +5052,34 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3554
5052
|
const subscribeEmptyCompanionTabs = () => () => {};
|
|
3555
5053
|
const getEmptyCompanionTabs = () => EMPTY_COMPANION_TABS;
|
|
3556
5054
|
const SIDEBAR_COLLAPSE_SETTLE_MS = 140;
|
|
5055
|
+
const SIDEBAR_EXPANSION_STORAGE_KEY = "dsh-codex-ui.sidebar-expansion.v1";
|
|
5056
|
+
const EXTENSIONS_EXPANSION_KEY = "extensions";
|
|
5057
|
+
function readExtensionsOpen() {
|
|
5058
|
+
return readTreeExpansionState(browserStorage(), SIDEBAR_EXPANSION_STORAGE_KEY)[EXTENSIONS_EXPANSION_KEY] !== false;
|
|
5059
|
+
}
|
|
5060
|
+
function writeExtensionsOpen(open) {
|
|
5061
|
+
const storage = browserStorage();
|
|
5062
|
+
const expanded = readTreeExpansionState(storage, SIDEBAR_EXPANSION_STORAGE_KEY);
|
|
5063
|
+
writeTreeExpansionState(storage, SIDEBAR_EXPANSION_STORAGE_KEY, {
|
|
5064
|
+
...expanded,
|
|
5065
|
+
[EXTENSIONS_EXPANSION_KEY]: open
|
|
5066
|
+
});
|
|
5067
|
+
}
|
|
3557
5068
|
const stylesheet$3 = `
|
|
3558
|
-
.dcu-root{--dcu-font:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei UI",sans-serif;--dcu-sidebar-
|
|
3559
|
-
.dcu-expanded-shell{display:flex;width:
|
|
5069
|
+
.dcu-root{--dcu-font:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei UI",sans-serif;--dcu-sidebar-primary:#393d3e;--dcu-sidebar-secondary:#676b6c;--dcu-sidebar-tertiary:#9a9f9f;--dcu-sidebar-navigation:#4e5253;--dcu-sidebar-icon:#4e5253;--dcu-sidebar-hover:#dfe8e5;--dcu-sidebar-border:rgba(37,46,41,.10);--dcu-tip-bg:#ffffff;--dcu-tip-shadow:0 10px 32px rgba(31,39,36,.22);width:100%;height:100%;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden;background:#eef7f5;color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font)}body[data-ds-dark-theme] .dcu-root{background:#1d2120;--dcu-sidebar-primary:#b9bab9;--dcu-sidebar-secondary:#909191;--dcu-sidebar-tertiary:#666867;--dcu-sidebar-navigation:#b9bab9;--dcu-sidebar-icon:#afafaf;--dcu-sidebar-hover:#303432;--dcu-sidebar-border:rgba(255,255,255,.08);--dcu-tip-bg:#2a2a2a;--dcu-tip-shadow:0 10px 30px rgba(0,0,0,.28)}
|
|
5070
|
+
.dcu-expanded-shell{display:flex;width:100%;min-height:0;flex:1 1 0;overflow:hidden;flex-direction:column;transform-origin:left center;transition:opacity 140ms ease-out,transform 180ms cubic-bezier(.16,1,.3,1);animation:dcu-sidebar-expanded-in 180ms cubic-bezier(.16,1,.3,1)}.dcu-compact-shell{display:none;width:56px}.dcu-root.dcu-collapsing .dcu-expanded-shell{opacity:0;transform:translateX(-6px);pointer-events:none}.dcu-root.dcu-compact .dcu-expanded-shell{display:none}.dcu-root.dcu-compact .dcu-compact-shell{display:flex;min-height:0;flex:1;flex-direction:column;align-items:center;animation:dcu-sidebar-compact-in 140ms ease-out}@keyframes dcu-sidebar-expanded-in{from{opacity:0;transform:translateX(-6px)}to{opacity:1;transform:none}}@keyframes dcu-sidebar-compact-in{from{opacity:0;transform:translateX(-4px)}to{opacity:1;transform:none}}
|
|
3560
5071
|
.dcu-root *{box-sizing:border-box}.dcu-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:8px;height:60px;padding:8px 8px 8px 12px}.dcu-brand{border:0;background:transparent;color:inherit;padding:0;display:flex;align-items:center;min-width:0;overflow:hidden}.dcu-brand svg{display:block;width:auto;max-width:100%;height:24px;min-width:0}.dcu-head-actions{display:grid;grid-auto-flow:column;grid-auto-columns:28px;align-items:center;column-gap:8px;height:28px}
|
|
3561
5072
|
.dcu-icon,.dcu-menu button,.dcu-footer-link{appearance:none;border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}.dcu-icon{display:grid;place-items:center;width:36px;height:36px;border-radius:8px;color:var(--dcu-sidebar-icon)}.dcu-head .dcu-icon{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;margin:0;padding:0;border-radius:50%;line-height:0}.dcu-head .dcu-icon svg{display:block;width:16px;height:16px}
|
|
3562
5073
|
.dcu-icon:hover,.dcu-menu button:hover:not(:disabled),.dcu-footer-link:hover{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary)}
|
|
3563
5074
|
.dcu-menu{padding:0 6px 8px;display:grid;gap:2px}.dcu-menu button,.dcu-footer-link{display:grid;grid-template-columns:20px minmax(0,1fr);column-gap:8px;align-items:center;width:100%;min-height:36px;padding:0 4px;border-radius:8px;color:var(--dcu-sidebar-navigation);font-size:14px;line-height:20px;text-align:left;font-weight:400}
|
|
3564
5075
|
.dcu-menu-icon{display:grid;place-items:center start;width:20px;height:20px}.dcu-menu-icon svg,.dcu-footer-link svg{display:block;width:16px;height:16px;color:var(--dcu-sidebar-icon)}.dcu-menu button:disabled{color:var(--dcu-sidebar-secondary);cursor:default;opacity:1}.dcu-menu button:disabled svg{color:var(--dcu-sidebar-secondary)}
|
|
3565
|
-
.dcu-extension-items{display:grid;gap:1px;margin:1px 0 4px 28px}.dcu-extension-items button{min-height:32px;color:var(--dcu-sidebar-secondary);font-size:13px;font-weight:400}
|
|
3566
|
-
.dcu-workspaces{display:flex;min-height:0;flex:1;flex-direction:column;margin-top:2px;padding-top:8px;border-top:1px solid var(--dcu-sidebar-border)}.dcu-workspaces.dcu-workspaces-tabs{padding-top:0;border-top:0}.dcu-im-tabs{display:flex;gap:16px;margin:0 8px 12px;padding:0;border-bottom:1px solid var(--dcu-sidebar-border)}.dcu-im-tab{appearance:none;border:0;background:transparent;color:var(--dcu-sidebar-secondary);padding:8px 0 7px;font:14px/22px var(--dcu-font);font-weight:500;cursor:pointer}.dcu-im-tab[data-on=true]{color:var(--dcu-sidebar-primary);font-weight:600;box-shadow:inset 0 -2px 0 currentColor}.dcu-native-workspaces{display:flex;min-height:0;flex:1}.dcu-native-workspaces>*{min-width:0;flex:1}.dcu-native-workspaces .ima-tabs,.dcu-native-workspaces [role=tablist]{display:none!important}.dcu-schedule-browser{display:flex;min-height:0;flex:1;flex-direction:column}.dcu-native-workspaces .dcu-schedule-views{display:flex!important;flex:none;min-height:30px;margin:0 8px 8px;padding:2px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;background:rgba(255,255,255,.025)}.dcu-schedule-views button{appearance:none;flex:1;min-width:0;height:24px;border:0;border-radius:6px;background:transparent;color:var(--dcu-sidebar-secondary);font:600 12px/18px var(--dcu-font);cursor:pointer}.dcu-schedule-views button[aria-selected=true]{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary);box-shadow:inset 0 0 0 1px var(--dcu-sidebar-border)}.dcu-schedule-pane{display:flex;min-height:0;flex:1}.dcu-schedule-pane>*{min-width:0;flex:1}.dcu-schedule-pane>[data-slot="sidebar.schedule"]{display:flex!important;width:100%;min-width:0;flex:1}.dcu-schedule-pane>[data-slot="sidebar.schedule"]>.dsh-st-rail{width:100%;min-width:0;padding-right:8px;scrollbar-gutter:auto}.dcu-schedule-pane .dsh-st-overview{padding-right:8px}.dcu-foot{display:grid;width:
|
|
5076
|
+
.dcu-extensions-group{display:grid}.dcu-extension-leading{position:relative;display:block;width:16px;height:16px}.dcu-extension-leading svg{position:absolute;inset:0;transition:opacity 140ms ease-out,transform 220ms cubic-bezier(.16,1,.3,1)}.dcu-extension-default-icon{opacity:1}.dcu-extension-state-arrow{opacity:0;transform:rotate(0)}.dcu-extensions-group:hover .dcu-extension-default-icon,.dcu-extensions-toggle:focus-visible .dcu-extension-default-icon{opacity:0}.dcu-extensions-group:hover .dcu-extension-state-arrow,.dcu-extensions-toggle:focus-visible .dcu-extension-state-arrow{opacity:1}.dcu-extensions-toggle[aria-expanded=true] .dcu-extension-state-arrow{transform:rotate(90deg)}.dcu-extension-panel{display:grid;grid-template-rows:1fr;opacity:1;transition:grid-template-rows 220ms cubic-bezier(.16,1,.3,1),opacity 160ms ease-out}.dcu-extension-panel[data-open=false]{grid-template-rows:0fr;opacity:0;pointer-events:none}.dcu-extension-panel-inner{position:relative;min-height:0;overflow:hidden}.dcu-extension-items{position:relative;display:grid;gap:1px;margin:1px 0 4px 28px}.dcu-extension-items::before{content:"";position:absolute;left:-16px;top:0;bottom:4px;width:1px;background:var(--dcu-sidebar-border)}.dcu-extension-items button{grid-template-columns:minmax(0,1fr);min-height:32px;color:var(--dcu-sidebar-secondary);font-size:13px;font-weight:400}.dcu-extension-items .dcu-menu-icon{display:none}
|
|
5077
|
+
.dcu-workspaces{display:flex;min-height:0;flex:1;flex-direction:column;margin-top:2px;padding-top:8px;border-top:1px solid var(--dcu-sidebar-border)}.dcu-workspaces.dcu-workspaces-tabs{padding-top:0;border-top:0}.dcu-im-tabs{display:flex;gap:16px;margin:0 8px 12px;padding:0;border-bottom:1px solid var(--dcu-sidebar-border)}.dcu-im-tab{appearance:none;border:0;background:transparent;color:var(--dcu-sidebar-secondary);padding:8px 0 7px;font:14px/22px var(--dcu-font);font-weight:500;cursor:pointer}.dcu-im-tab[data-on=true]{color:var(--dcu-sidebar-primary);font-weight:600;box-shadow:inset 0 -2px 0 currentColor}.dcu-native-workspaces{display:flex;min-height:0;flex:1}.dcu-native-workspaces>*{min-width:0;flex:1}.dcu-native-workspaces .ima-tabs,.dcu-native-workspaces [role=tablist]{display:none!important}.dcu-schedule-browser{display:flex;min-height:0;flex:1;flex-direction:column}.dcu-native-workspaces .dcu-schedule-views{display:flex!important;flex:none;min-height:30px;margin:0 8px 8px;padding:2px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;background:rgba(255,255,255,.025)}.dcu-schedule-views button{appearance:none;flex:1;min-width:0;height:24px;border:0;border-radius:6px;background:transparent;color:var(--dcu-sidebar-secondary);font:600 12px/18px var(--dcu-font);cursor:pointer}.dcu-schedule-views button[aria-selected=true]{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary);box-shadow:inset 0 0 0 1px var(--dcu-sidebar-border)}.dcu-schedule-pane{display:flex;min-height:0;flex:1}.dcu-schedule-pane>*{min-width:0;flex:1}.dcu-schedule-pane>[data-slot="sidebar.schedule"]{display:flex!important;width:100%;min-width:0;flex:1}.dcu-schedule-pane>[data-slot="sidebar.schedule"]>.dsh-st-rail{width:100%;min-width:0;padding-right:8px;scrollbar-gutter:auto}.dcu-schedule-pane .dsh-st-overview{padding-right:8px}.dcu-foot{display:grid;width:100%;gap:4px;padding:8px 6px 12px;border-top:1px solid var(--dcu-sidebar-border);transition:opacity 120ms ease-out,transform 160ms cubic-bezier(.16,1,.3,1)}.dcu-root.dcu-collapsing>.dcu-foot{opacity:0;transform:translateX(-4px);pointer-events:none}.dcu-footer-actions:empty,.dcu-settings-seat:empty{display:none}.dcu-settings-seat>button{width:100%;min-height:36px;padding-left:4px!important;color:var(--dcu-sidebar-navigation);font:14px/20px var(--dcu-font);font-weight:400}.dcu-compact{width:100%;align-items:flex-start;overflow:hidden;padding:10px 0 8px}.dcu-compact-nav{display:flex;flex:1;min-height:0;flex-direction:column;align-items:center;gap:2px;overflow:auto;padding:6px 0}.dcu-compact .dcu-icon{width:36px;height:36px;flex:none}.dcu-compact .dcu-foot{width:36px;margin-top:auto;margin-left:10px;padding:8px 0;border-top:0}.dcu-compact .dcu-settings-seat{width:36px;overflow:hidden}.dcu-compact .dcu-settings-seat>button{display:grid;place-items:center;width:36px;min-height:36px;padding:0!important;font-size:0!important;line-height:0}.dcu-compact .dcu-settings-seat>button svg{width:16px;height:16px}.dcu-compact .dcu-footer-link{display:flex;justify-content:center;width:36px;padding:0;font-size:0}.dcu-compact .dcu-footer-link svg{width:16px;height:16px}
|
|
5078
|
+
.dcu-expanded-shell,.dcu-foot{width:100%}
|
|
3567
5079
|
.dcu-native-workspaces{flex-direction:column}.dcu-native-workspaces>[data-mcp-connector-top-mount=true]{flex:none}.dcu-root .mcpConnectorLauncher,.dcu-root [data-mcp-connector-top-mount=true]{display:none!important}
|
|
3568
5080
|
.dcu-dependency-notice{margin:0 10px 8px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;padding:8px;color:var(--dcu-sidebar-secondary);font-size:12px;line-height:18px}
|
|
3569
5081
|
[role="dialog"][aria-labelledby]{width:min(1000px,calc(100vw - 48px));max-width:calc(100vw - 48px);height:min(800px,calc(100vh - 48px))}
|
|
3570
|
-
.dcu-search-scrim{position:fixed;z-index:10020;inset:0;display:flex;justify-content:center;align-items:flex-start;padding:72px 20px;background:color-mix(in srgb,#000 48%,transparent);animation:dcu-search-scrim-in 140ms ease-out}.dcu-search-dialog{width:min(560px,100%);max-height:min(640px,calc(100vh - 120px));overflow:auto;border:1px solid var(--dcu-sidebar-border);border-radius:16px;padding:10px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv4);animation:dcu-search-dialog-in 180ms cubic-bezier(.16,1,.3,1)}@keyframes dcu-search-scrim-in{from{opacity:0}to{opacity:1}}@keyframes dcu-search-dialog-in{from{opacity:0;transform:translateY(-6px) scale(.985)}to{opacity:1
|
|
5082
|
+
.dcu-search-scrim{position:fixed;z-index:10020;inset:0;display:flex;justify-content:center;align-items:flex-start;padding:72px 20px;background:color-mix(in srgb,#000 48%,transparent);animation:dcu-search-scrim-in 140ms ease-out}.dcu-search-dialog{width:min(560px,100%);max-height:min(640px,calc(100vh - 120px));overflow:auto;border:1px solid var(--dcu-sidebar-border);border-radius:16px;padding:10px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv4);animation:dcu-search-dialog-in 180ms cubic-bezier(.16,1,.3,1)}@keyframes dcu-search-scrim-in{from{opacity:0}to{opacity:1}}@keyframes dcu-search-dialog-in{from{opacity:0;transform:translateY(-6px) scale(.985)}to{opacity:1}}.dcu-search-input{margin-bottom:8px}.dcu-search-section{padding:6px 0}.dcu-search-title{padding:0 8px 4px;color:var(--dcu-sidebar-tertiary);font-size:12px;font-weight:600}.dcu-search-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;width:100%;min-height:34px;border:0;border-radius:8px;padding:6px 8px;background:transparent;color:var(--dcu-sidebar-primary);font:inherit;text-align:left;cursor:pointer}.dcu-search-row:hover,.dcu-search-row[data-active=true]{background:var(--dcu-sidebar-hover)}.dcu-search-main{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-search-detail{max-width:160px;overflow:hidden;color:var(--dcu-sidebar-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-search-empty{padding:18px 8px;color:var(--dcu-sidebar-tertiary);font-size:13px}@media (prefers-reduced-motion:reduce){.dcu-expanded-shell,.dcu-root.dcu-compact .dcu-compact-shell,.dcu-foot,.dcu-search-scrim,.dcu-search-dialog,.dcu-extension-panel,.dcu-extension-leading svg{animation:none;transition:none}}
|
|
3571
5083
|
[data-conversation-scroll]{--dsh-composer-card-max-width:calc(var(--dsh-chat-content-width) + 32px);--dsh-composer-side-clearance:24px}[data-conversation-scroll] [data-composer-card]{min-height:96px;padding-top:10px;border-radius:16px;box-shadow:var(--dsw-shadow-lv3);transition:border-color 180ms ease,box-shadow 180ms ease}[data-conversation-scroll] [data-composer-card]:focus-within{border-color:var(--dsw-alias-button-info-fill);box-shadow:0 0 0 2px var(--dsw-static-deepseek-50),var(--dsw-shadow-lv3)}[data-conversation-scroll] [data-input-mirror]{min-height:44px}@media (prefers-reduced-motion:reduce){[data-conversation-scroll] [data-composer-card]{transition:none}}
|
|
3572
5084
|
html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:has([data-dcu-official-turn-navigator]) .dcu-turn-navigator{display:none}
|
|
3573
5085
|
[data-dcu-official-turn-navigator]{right:auto!important;left:calc(12px - (var(--dsh-composer-side-clearance) + 16px))!important}
|
|
@@ -3883,12 +5395,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
3883
5395
|
});
|
|
3884
5396
|
});
|
|
3885
5397
|
/** Codex 风格的 DSH 侧栏,只替换导航外观,项目浏览和设置仍由 DSH 官方组件提供。 */
|
|
3886
|
-
function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useSessionPendingInteraction, useWorkspaces }) {
|
|
5398
|
+
function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, moveSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useSessionPendingInteraction, useWorkspaces }) {
|
|
3887
5399
|
const compact = collapsed || width < 80;
|
|
3888
5400
|
const [visualCompact, setVisualCompact] = (0, react.useState)(compact);
|
|
3889
5401
|
const [collapsing, setCollapsing] = (0, react.useState)(false);
|
|
3890
|
-
const lastWideWidth = (0, react.useRef)(width >= 80 ? width : 275);
|
|
3891
|
-
if (!compact) lastWideWidth.current = width;
|
|
3892
5402
|
const settingsSeat = (0, react.useRef)(null);
|
|
3893
5403
|
const search = (0, react.useRef)(null);
|
|
3894
5404
|
const toggleSidebarRef = (0, react.useRef)(toggleSidebar);
|
|
@@ -3896,7 +5406,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
3896
5406
|
const expandSidebar = (0, react.useCallback)(() => {
|
|
3897
5407
|
toggleSidebarRef.current();
|
|
3898
5408
|
}, []);
|
|
3899
|
-
const [extensionsOpen, setExtensionsOpen] = (0, react.useState)(
|
|
5409
|
+
const [extensionsOpen, setExtensionsOpen] = (0, react.useState)(readExtensionsOpen);
|
|
3900
5410
|
const [imTab, setImTab] = (0, react.useState)("tasks");
|
|
3901
5411
|
const companionTabs = (0, react.useSyncExternalStore)(companionSlots?.subscribe ?? subscribeEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs);
|
|
3902
5412
|
const showChannels = companionTabs.channels;
|
|
@@ -3930,42 +5440,77 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
3930
5440
|
]);
|
|
3931
5441
|
(0, react.useEffect)(() => {
|
|
3932
5442
|
let startX = 0;
|
|
3933
|
-
let startWidth =
|
|
5443
|
+
let startWidth = 240;
|
|
3934
5444
|
let dragging = false;
|
|
3935
5445
|
let pointerId;
|
|
5446
|
+
let frame;
|
|
5447
|
+
let handle;
|
|
5448
|
+
const stopHostDrag = (event) => {
|
|
5449
|
+
event.preventDefault();
|
|
5450
|
+
event.stopPropagation();
|
|
5451
|
+
};
|
|
5452
|
+
const finishDrag = () => {
|
|
5453
|
+
frame?.removeAttribute("data-dragging");
|
|
5454
|
+
handle?.removeAttribute("data-dragging");
|
|
5455
|
+
if (handle !== void 0 && pointerId !== void 0 && handle.hasPointerCapture?.(pointerId)) handle.releasePointerCapture(pointerId);
|
|
5456
|
+
dragging = false;
|
|
5457
|
+
pointerId = void 0;
|
|
5458
|
+
frame = void 0;
|
|
5459
|
+
handle = void 0;
|
|
5460
|
+
};
|
|
3936
5461
|
const onDown = (event) => {
|
|
3937
5462
|
if (dragging || !isSidebarDragHandle(event.target)) return;
|
|
5463
|
+
const nextFrame = findSidebarFrame(document);
|
|
5464
|
+
const tracks = nextFrame === void 0 ? void 0 : parseSidebarGrid(nextFrame.style.gridTemplateColumns);
|
|
5465
|
+
const nextHandle = event.target instanceof Element ? event.target.closest("[data-side=\"sidebar\"]") ?? void 0 : void 0;
|
|
5466
|
+
if (nextFrame === void 0 || tracks === void 0 || nextHandle === void 0) return;
|
|
5467
|
+
stopHostDrag(event);
|
|
3938
5468
|
dragging = true;
|
|
3939
5469
|
pointerId = event.pointerId;
|
|
3940
5470
|
startX = event.clientX;
|
|
3941
|
-
|
|
3942
|
-
|
|
5471
|
+
startWidth = tracks.sidebar;
|
|
5472
|
+
frame = nextFrame;
|
|
5473
|
+
handle = nextHandle;
|
|
5474
|
+
frame.setAttribute("data-dragging", "");
|
|
5475
|
+
handle.setAttribute("data-dragging", "true");
|
|
5476
|
+
try {
|
|
5477
|
+
handle.setPointerCapture(event.pointerId);
|
|
5478
|
+
} catch {}
|
|
5479
|
+
};
|
|
5480
|
+
const onMove = (event) => {
|
|
5481
|
+
if (!dragging || event.pointerId !== pointerId || frame === void 0) return;
|
|
5482
|
+
stopHostDrag(event);
|
|
5483
|
+
applySidebarWidth(frame, sidebarWidthDuringDrag(startWidth, startX, event.clientX));
|
|
3943
5484
|
};
|
|
3944
5485
|
const onUp = (event) => {
|
|
3945
5486
|
if (!dragging || event.pointerId !== pointerId) return;
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
5487
|
+
stopHostDrag(event);
|
|
5488
|
+
if (frame !== void 0) applySidebarWidth(frame, sidebarWidthDuringDrag(startWidth, startX, event.clientX));
|
|
5489
|
+
const collapse = shouldCollapseOnSidebarDrag(startWidth, startX, event.clientX);
|
|
5490
|
+
finishDrag();
|
|
5491
|
+
if (collapse) window.requestAnimationFrame(() => {
|
|
3950
5492
|
window.requestAnimationFrame(() => {
|
|
3951
|
-
|
|
5493
|
+
toggleSidebarRef.current();
|
|
3952
5494
|
});
|
|
3953
5495
|
});
|
|
3954
5496
|
};
|
|
3955
5497
|
const onCancel = (event) => {
|
|
3956
5498
|
if (event.pointerId !== pointerId) return;
|
|
3957
|
-
|
|
3958
|
-
|
|
5499
|
+
stopHostDrag(event);
|
|
5500
|
+
finishDrag();
|
|
3959
5501
|
};
|
|
3960
5502
|
window.addEventListener("pointerdown", onDown, true);
|
|
5503
|
+
window.addEventListener("pointermove", onMove, true);
|
|
3961
5504
|
window.addEventListener("pointerup", onUp, true);
|
|
3962
5505
|
window.addEventListener("pointercancel", onCancel, true);
|
|
3963
5506
|
return () => {
|
|
5507
|
+
finishDrag();
|
|
3964
5508
|
window.removeEventListener("pointerdown", onDown, true);
|
|
5509
|
+
window.removeEventListener("pointermove", onMove, true);
|
|
3965
5510
|
window.removeEventListener("pointerup", onUp, true);
|
|
3966
5511
|
window.removeEventListener("pointercancel", onCancel, true);
|
|
3967
5512
|
};
|
|
3968
|
-
}, [
|
|
5513
|
+
}, []);
|
|
3969
5514
|
(0, react.useLayoutEffect)(() => {
|
|
3970
5515
|
if (!compact) {
|
|
3971
5516
|
setCollapsing(false);
|
|
@@ -4001,6 +5546,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4001
5546
|
archiveSession,
|
|
4002
5547
|
deleteSession,
|
|
4003
5548
|
forkSession,
|
|
5549
|
+
moveSession,
|
|
4004
5550
|
renameSession,
|
|
4005
5551
|
openPath,
|
|
4006
5552
|
useSessions,
|
|
@@ -4013,6 +5559,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4013
5559
|
deleteSession,
|
|
4014
5560
|
expandSidebar,
|
|
4015
5561
|
forkSession,
|
|
5562
|
+
moveSession,
|
|
4016
5563
|
openPath,
|
|
4017
5564
|
openSession,
|
|
4018
5565
|
renameSession,
|
|
@@ -4020,10 +5567,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4020
5567
|
useSessions,
|
|
4021
5568
|
useWorkspaces
|
|
4022
5569
|
]);
|
|
4023
|
-
const sidebarStyle = { "--dcu-sidebar-wide-width": `${slimedSidebarWidth(lastWideWidth.current, false, window.innerWidth)}px` };
|
|
4024
5570
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
4025
5571
|
className: `dcu-root${visualCompact ? " dcu-compact" : ""}${collapsing ? " dcu-collapsing" : ""}`,
|
|
4026
|
-
style: sidebarStyle,
|
|
4027
5572
|
"aria-label": t("sidebar.label"),
|
|
4028
5573
|
children: [
|
|
4029
5574
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$3 }),
|
|
@@ -4070,46 +5615,73 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4070
5615
|
},
|
|
4071
5616
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: 16 }) }), t("sidebar.newTask")]
|
|
4072
5617
|
}),
|
|
4073
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
4074
|
-
|
|
4075
|
-
"
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
5618
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5619
|
+
className: "dcu-extensions-group",
|
|
5620
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5621
|
+
type: "button",
|
|
5622
|
+
className: "dcu-extensions-toggle",
|
|
5623
|
+
"aria-expanded": extensionsOpen,
|
|
5624
|
+
"aria-controls": "dcu-extension-items",
|
|
5625
|
+
onClick: () => {
|
|
5626
|
+
setExtensionsOpen((open) => {
|
|
5627
|
+
const next = !open;
|
|
5628
|
+
writeExtensionsOpen(next);
|
|
5629
|
+
return next;
|
|
5630
|
+
});
|
|
5631
|
+
},
|
|
5632
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5633
|
+
className: "dcu-extension-leading",
|
|
5634
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEnhanceOutline16, {
|
|
5635
|
+
className: "dcu-extension-default-icon",
|
|
5636
|
+
size: 16
|
|
5637
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, { className: "dcu-extension-state-arrow" })]
|
|
5638
|
+
}) }), t("sidebar.extensions")]
|
|
5639
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5640
|
+
id: "dcu-extension-items",
|
|
5641
|
+
className: "dcu-extension-panel",
|
|
5642
|
+
"data-open": extensionsOpen,
|
|
5643
|
+
"aria-hidden": !extensionsOpen,
|
|
5644
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5645
|
+
className: "dcu-extension-panel-inner",
|
|
5646
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5647
|
+
className: "dcu-extension-items",
|
|
5648
|
+
children: [
|
|
5649
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5650
|
+
type: "button",
|
|
5651
|
+
tabIndex: extensionsOpen ? 0 : -1,
|
|
5652
|
+
onClick: () => {
|
|
5653
|
+
selectExternalSection(t("sidebar.experts"));
|
|
5654
|
+
},
|
|
5655
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUserOutline16, { size: 16 }) }), t("sidebar.experts")]
|
|
5656
|
+
}),
|
|
5657
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5658
|
+
type: "button",
|
|
5659
|
+
tabIndex: extensionsOpen ? 0 : -1,
|
|
5660
|
+
onClick: () => {
|
|
5661
|
+
selectExternalSection(t("sidebar.skills"));
|
|
5662
|
+
},
|
|
5663
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSkillOutline16, { size: 16 }) }), t("sidebar.skills")]
|
|
5664
|
+
}),
|
|
5665
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5666
|
+
type: "button",
|
|
5667
|
+
tabIndex: extensionsOpen ? 0 : -1,
|
|
5668
|
+
onClick: () => {
|
|
5669
|
+
selectPluginSection();
|
|
5670
|
+
},
|
|
5671
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPersonalizationOutline16, { size: 16 }) }), t("sidebar.plugins")]
|
|
5672
|
+
}),
|
|
5673
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5674
|
+
type: "button",
|
|
5675
|
+
tabIndex: extensionsOpen ? 0 : -1,
|
|
5676
|
+
onClick: () => {
|
|
5677
|
+
selectSection(t("sidebar.connectors"));
|
|
5678
|
+
},
|
|
5679
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MenuIcon, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline16, { size: 16 }) }), t("sidebar.connectors")]
|
|
5680
|
+
})
|
|
5681
|
+
]
|
|
5682
|
+
})
|
|
4111
5683
|
})
|
|
4112
|
-
]
|
|
5684
|
+
})]
|
|
4113
5685
|
}),
|
|
4114
5686
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4115
5687
|
type: "button",
|
|
@@ -4165,9 +5737,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4165
5737
|
archiveSession,
|
|
4166
5738
|
deleteSession,
|
|
4167
5739
|
forkSession,
|
|
5740
|
+
moveSession,
|
|
4168
5741
|
renameSession,
|
|
4169
5742
|
useSessions,
|
|
4170
5743
|
useSessionPendingInteraction,
|
|
5744
|
+
useWorkspaces,
|
|
4171
5745
|
t
|
|
4172
5746
|
})
|
|
4173
5747
|
}) : imTab === "schedule" && showSchedule ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -4177,6 +5751,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4177
5751
|
archiveSession,
|
|
4178
5752
|
deleteSession,
|
|
4179
5753
|
forkSession,
|
|
5754
|
+
moveSession,
|
|
4180
5755
|
renameSession,
|
|
4181
5756
|
useSessions,
|
|
4182
5757
|
useSessionPendingInteraction,
|
|
@@ -4356,7 +5931,22 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4356
5931
|
const endpoint = "/api/michengai/codex-ui/dependencies";
|
|
4357
5932
|
const stylesheet$2 = `
|
|
4358
5933
|
.dcu-about{color:var(--dsw-alias-label-primary)}.dcu-about h2{margin:0;font-size:20px;line-height:28px}.dcu-about-intro{margin:6px 0 22px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}.dcu-about h3{margin:24px 0 8px;font-size:14px;line-height:20px}.dcu-about-features{margin:0;padding-left:20px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:24px}.dcu-about-dependencies-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:24px}.dcu-about-dependencies-heading h3{margin:0}.dcu-about-dependencies-heading+.dcu-about-intro{margin-bottom:14px}.dcu-about-dependencies{overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px}.dcu-about-dependency{display:flex;align-items:center;gap:12px;min-height:64px;padding:12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dcu-about-dependency:last-child{border-bottom:0}.dcu-about-copy{min-width:0;flex:1}.dcu-about-name{font-size:13px;line-height:20px;font-weight:600}.dcu-about-package{overflow:hidden;margin-top:2px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-about-status{display:flex;align-items:center;gap:5px;font-size:12px}.dcu-about-status[data-installed=true]{color:var(--dsw-alias-state-success-primary)}.dcu-about-status[data-installed=false]{color:var(--dsw-alias-state-error-primary)}.dcu-about-status[data-update=true]{color:var(--dsw-alias-state-warning-primary)}.dcu-about-install{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:6px 9px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;cursor:pointer}.dcu-about-install:hover:not(:disabled){background:var(--dsw-specific-menu-item-hover)}.dcu-about-install:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}.dcu-about-install:disabled{cursor:wait;opacity:.65}.dcu-about-update-all{min-width:92px}.dcu-about-message{margin:10px 0 0;border-radius:8px;padding:9px 10px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.dcu-about-message[data-error=true]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary)}.dcu-about-progress{display:grid;grid-template-columns:auto 1fr auto;gap:8px 10px;align-items:center;margin-top:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:9px 10px}.dcu-about-progress code{min-width:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-about-progress-pct{color:var(--dsw-alias-label-tertiary);font-size:12px;font-variant-numeric:tabular-nums}.dcu-about-progress-bar{grid-column:1/-1;height:4px;overflow:hidden;border-radius:99px;background:var(--dsw-alias-border-l2)}.dcu-about-progress-fill{height:100%;background:var(--dsw-alias-state-business-primary);transition:width .2s ease}.dcu-about-progress-fill[data-wave=true]{width:28%;animation:dcu-about-progress-wave 1.2s ease-in-out infinite}@keyframes dcu-about-progress-wave{0%{transform:translateX(-60%)}100%{transform:translateX(280%)}}
|
|
5934
|
+
.dcu-about-title-row{display:flex;align-items:center;gap:8px;min-width:0}.dcu-about-links{display:flex;align-items:center;gap:4px}.dcu-about-external-link{display:inline-flex;align-items:center;gap:5px;min-height:28px;padding:0 8px;color:var(--dsw-alias-label-secondary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;font-size:12px;font-weight:500;line-height:18px;text-decoration:none;white-space:nowrap}.dcu-about-external-link:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dcu-about-external-link:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}.dcu-about-external-link svg{flex:none}@media(max-width:720px){.dcu-about-title-row{flex-wrap:wrap}}
|
|
4359
5935
|
`;
|
|
5936
|
+
/** 宿主图标库不提供 GitHub 品牌标识,内联后可离线使用并继承当前文字颜色。 */
|
|
5937
|
+
function GithubMark16() {
|
|
5938
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
5939
|
+
viewBox: "0 0 16 16",
|
|
5940
|
+
width: 16,
|
|
5941
|
+
height: 16,
|
|
5942
|
+
"aria-hidden": "true",
|
|
5943
|
+
focusable: "false",
|
|
5944
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
5945
|
+
fill: "currentColor",
|
|
5946
|
+
d: "M8 0a8 8 0 0 0-2.53 15.59c.4.074.547-.173.547-.385 0-.19-.007-.693-.01-1.36-2.226.484-2.695-1.073-2.695-1.073-.364-.924-.89-1.17-.89-1.17-.726-.496.055-.486.055-.486.803.056 1.225.824 1.225.824.714 1.223 1.872.87 2.328.665.072-.517.28-.87.508-1.07-1.777-.202-3.645-.888-3.645-3.956 0-.874.31-1.588.823-2.148-.083-.202-.357-1.017.078-2.12 0 0 .672-.215 2.2.82A7.65 7.65 0 0 1 8 4.8c.68.003 1.365.092 2.004.27 1.527-1.035 2.197-.82 2.197-.82.437 1.103.162 1.918.08 2.12.513.56.822 1.274.822 2.148 0 3.076-1.872 3.752-3.654 3.95.288.248.544.735.544 1.482 0 1.07-.01 1.932-.01 2.195 0 .214.144.463.55.384A8.001 8.001 0 0 0 8 0Z"
|
|
5947
|
+
})
|
|
5948
|
+
});
|
|
5949
|
+
}
|
|
4360
5950
|
function isDependencyStatus(value) {
|
|
4361
5951
|
if (value === null || typeof value !== "object") return false;
|
|
4362
5952
|
const status = value;
|
|
@@ -4371,11 +5961,6 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4371
5961
|
const currentPackage = progress.currentPackage;
|
|
4372
5962
|
return typeof progress.active === "boolean" && typeof progress.target === "string" && typeof progress.seconds === "number" && Number.isInteger(progress.seconds) && progress.seconds >= 0 && typeof progress.lastLine === "string" && (phase === null || typeof phase === "string" && PROGRESS_PHASES.has(phase)) && typeof progress.done === "number" && Number.isInteger(progress.done) && progress.done >= 0 && (total === null || typeof total === "number" && Number.isInteger(total) && total >= 0) && (percent === null || typeof percent === "number" && Number.isFinite(percent) && percent >= 0 && percent <= 100) && (currentPackage === null || typeof currentPackage === "string");
|
|
4373
5963
|
}
|
|
4374
|
-
function installErrorText(error, t) {
|
|
4375
|
-
const message = error instanceof Error ? error.message : "";
|
|
4376
|
-
if (message.includes("没有进入当前 Profile") || message.includes("did not enter this profile")) return t("about.installUnchanged");
|
|
4377
|
-
return message !== "" ? message : t("about.installFailed");
|
|
4378
|
-
}
|
|
4379
5964
|
function progressLabel(progress, t) {
|
|
4380
5965
|
if (progress.phase !== null) {
|
|
4381
5966
|
const current = progress.currentPackage === null || progress.currentPackage === "" ? "" : ` · ${progress.currentPackage}`;
|
|
@@ -4537,7 +6122,27 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4537
6122
|
"aria-label": t("about.nav"),
|
|
4538
6123
|
children: [
|
|
4539
6124
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$2 }),
|
|
4540
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6125
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6126
|
+
className: "dcu-about-title-row",
|
|
6127
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("about.title") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6128
|
+
className: "dcu-about-links",
|
|
6129
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
6130
|
+
className: "dcu-about-external-link",
|
|
6131
|
+
href: "https://github.com/MichengAI/dsh-codex-ui",
|
|
6132
|
+
target: "_blank",
|
|
6133
|
+
rel: "noreferrer",
|
|
6134
|
+
"aria-label": t("about.viewProject"),
|
|
6135
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GithubMark16, {}), t("about.viewProject")]
|
|
6136
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
6137
|
+
className: "dcu-about-external-link",
|
|
6138
|
+
href: "https://github.com/MichengAI/dsh-codex-ui/issues",
|
|
6139
|
+
target: "_blank",
|
|
6140
|
+
rel: "noreferrer",
|
|
6141
|
+
"aria-label": t("about.feedback"),
|
|
6142
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconListPenOutline16, {}), t("about.feedback")]
|
|
6143
|
+
})]
|
|
6144
|
+
})]
|
|
6145
|
+
}),
|
|
4541
6146
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4542
6147
|
className: "dcu-about-intro",
|
|
4543
6148
|
children: t("about.description")
|
|
@@ -4678,7 +6283,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4678
6283
|
}
|
|
4679
6284
|
style.textContent = document.body.hasAttribute("data-ds-dark-theme") ? frameDarkTheme : frameLightTheme;
|
|
4680
6285
|
}
|
|
4681
|
-
function ConnectorMarket({ startPromptSession }) {
|
|
6286
|
+
function ConnectorMarket({ startPromptSession, t }) {
|
|
4682
6287
|
const frameRef = (0, react.useRef)(null);
|
|
4683
6288
|
(0, react.useEffect)(() => {
|
|
4684
6289
|
const onMessage = (event) => {
|
|
@@ -4695,9 +6300,9 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4695
6300
|
}, window.location.origin);
|
|
4696
6301
|
};
|
|
4697
6302
|
startPromptSession(prompt).then(() => {
|
|
4698
|
-
reply(true, "
|
|
6303
|
+
reply(true, t("connectors.promptReady"));
|
|
4699
6304
|
}, (error) => {
|
|
4700
|
-
reply(false, error
|
|
6305
|
+
reply(false, userErrorText(error, t));
|
|
4701
6306
|
});
|
|
4702
6307
|
};
|
|
4703
6308
|
const syncTheme = () => {
|
|
@@ -4713,12 +6318,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4713
6318
|
observer.disconnect();
|
|
4714
6319
|
window.removeEventListener("message", onMessage);
|
|
4715
6320
|
};
|
|
4716
|
-
}, [startPromptSession]);
|
|
6321
|
+
}, [startPromptSession, t]);
|
|
4717
6322
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
|
|
4718
6323
|
ref: frameRef,
|
|
4719
6324
|
className: "dcu-connector-frame",
|
|
4720
6325
|
src: MCP_CONNECTOR_UI,
|
|
4721
|
-
title: "
|
|
6326
|
+
title: t("connectors.title"),
|
|
4722
6327
|
onLoad: () => {
|
|
4723
6328
|
syncFrameTheme(frameRef.current);
|
|
4724
6329
|
}
|
|
@@ -4810,7 +6415,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4810
6415
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$1 }), marketAvailable === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4811
6416
|
className: "dcu-connector-empty",
|
|
4812
6417
|
children: t("connectors.loading")
|
|
4813
|
-
}) : marketAvailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorMarket, {
|
|
6418
|
+
}) : marketAvailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorMarket, {
|
|
6419
|
+
startPromptSession,
|
|
6420
|
+
t
|
|
6421
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4814
6422
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("connectors.title") }),
|
|
4815
6423
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("connectors.description") }),
|
|
4816
6424
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NativeConnectorList, {
|
|
@@ -4854,6 +6462,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4854
6462
|
"channel.wecom": "企业微信",
|
|
4855
6463
|
"channel.qq": "QQ",
|
|
4856
6464
|
"channel.telegram": "Telegram",
|
|
6465
|
+
"channel.unknown": "频道",
|
|
4857
6466
|
"schedule.empty": "还没有定时任务运行记录。",
|
|
4858
6467
|
"schedule.groupActions": "{name} 的任务操作",
|
|
4859
6468
|
"schedule.taskSettings": "任务设置",
|
|
@@ -4871,30 +6480,43 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4871
6480
|
"workspace.pinned": "置顶",
|
|
4872
6481
|
"workspace.pinnedEmpty": "拖动项目到此处置顶",
|
|
4873
6482
|
"workspace.projects": "项目",
|
|
6483
|
+
"workspace.ungrouped": "未分组",
|
|
6484
|
+
"workspace.createGroup": "新建分组",
|
|
6485
|
+
"workspace.createGroupDescription": "输入分组名称,项目不会自动移动。",
|
|
6486
|
+
"workspace.groupName": "分组名称",
|
|
6487
|
+
"workspace.moveToGroup": "移动到分组",
|
|
6488
|
+
"workspace.removeFromGroup": "移至未分组",
|
|
6489
|
+
"workspace.deleteGroup": "删除分组“{name}”",
|
|
6490
|
+
"workspace.deleteGroupAction": "删除分组",
|
|
6491
|
+
"workspace.deleteGroupDescription": "删除分组只会将其中项目移至未分组,不会删除项目或会话。",
|
|
6492
|
+
"workspace.manageGroups": "管理分组",
|
|
4874
6493
|
"workspace.recent": "最近",
|
|
4875
6494
|
"workspace.recentEmpty": "无聊天",
|
|
4876
6495
|
"workspace.noChat": "没有聊天",
|
|
4877
|
-
"workspace.empty": "
|
|
6496
|
+
"workspace.empty": "暂无项目",
|
|
4878
6497
|
"workspace.newSession": "新建会话",
|
|
4879
|
-
"workspace.rename": "
|
|
6498
|
+
"workspace.rename": "重命名项目",
|
|
4880
6499
|
"workspace.pin": "置顶项目",
|
|
4881
6500
|
"workspace.unpin": "取消置顶",
|
|
6501
|
+
"workspace.archive": "归档所有会话",
|
|
6502
|
+
"workspace.archiveTitle": "归档 {count} 个会话?",
|
|
6503
|
+
"workspace.archiveDescription": "这会归档“{name}”中的全部会话,项目和文件夹仍会保留。",
|
|
6504
|
+
"workspace.archiveConfirm": "全部归档",
|
|
6505
|
+
"workspace.archivePending": "正在归档会话…",
|
|
4882
6506
|
"workspace.openPath": "在资源管理器中打开",
|
|
4883
|
-
"workspace.delete": "
|
|
6507
|
+
"workspace.delete": "移除项目",
|
|
4884
6508
|
"workspace.deleteDescription": "将把“{name}”从项目列表中移除。文件夹和会话记录会保留。",
|
|
4885
|
-
"workspace.deletePending": "
|
|
6509
|
+
"workspace.deletePending": "正在移除项目…",
|
|
4886
6510
|
"workspace.actions": "{name} 的项目操作",
|
|
4887
6511
|
"workspace.taskCount": "{count} 个任务",
|
|
4888
|
-
"workspace.
|
|
6512
|
+
"workspace.taskSummary": "{count} 个任务 · {unreadCount} 条未读",
|
|
6513
|
+
"workspace.edit": "重命名项目",
|
|
4889
6514
|
"sessions.close": "关闭",
|
|
4890
6515
|
"sessions.cancel": "取消",
|
|
4891
6516
|
"sessions.save": "保存",
|
|
4892
6517
|
"sessions.failed": "操作失败:{message}",
|
|
4893
6518
|
"sessions.unknown": "找不到该会话。",
|
|
4894
6519
|
"sessions.actions": "{name} 的会话操作",
|
|
4895
|
-
"sessions.pin": "置顶会话",
|
|
4896
|
-
"sessions.unpin": "取消置顶",
|
|
4897
|
-
"sessions.pinned": "已置顶",
|
|
4898
6520
|
"sessions.markUnread": "标记为未读",
|
|
4899
6521
|
"sessions.markRead": "标记为已读",
|
|
4900
6522
|
"sessions.unread": "未读",
|
|
@@ -4903,17 +6525,33 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4903
6525
|
"sessions.planReview": "计划待审",
|
|
4904
6526
|
"sessions.rename": "重命名会话",
|
|
4905
6527
|
"sessions.renameDescription": "保持简短且易于识别",
|
|
6528
|
+
"sessions.renameInvalid": "会话名称无效,请修改后重试。",
|
|
6529
|
+
"sessions.renameFailed": "暂时无法重命名该会话,请稍后重试。",
|
|
4906
6530
|
"sessions.archive": "归档会话",
|
|
6531
|
+
"sessions.archiveFailed": "暂时无法归档该会话,请稍后重试。",
|
|
4907
6532
|
"sessions.delete": "删除会话",
|
|
4908
6533
|
"sessions.deleteDescription": "将永久删除会话“{name}”及其全部记录,此操作不可恢复。",
|
|
4909
6534
|
"sessions.deletePending": "正在删除会话…",
|
|
4910
6535
|
"sessions.deleteUnavailable": "未安装或无法连接归档管理插件。",
|
|
6536
|
+
"sessions.deleteFailed": "暂时无法删除该会话,请稍后重试。",
|
|
4911
6537
|
"sessions.fork": "在新会话中继续",
|
|
6538
|
+
"sessions.forkUnavailable": "当前会话暂时无法在新会话中继续,请等待本轮结束后重试。",
|
|
6539
|
+
"sessions.forkFailed": "暂时无法创建新会话,请稍后重试。",
|
|
4912
6540
|
"sessions.openPath": "在资源管理器中打开",
|
|
6541
|
+
"sessions.moveWorkspace": "项目",
|
|
6542
|
+
"sessions.moveUnavailable": "会话移动服务暂不可用,请重启 DSH 后重试。",
|
|
6543
|
+
"sessions.moveNotFound": "会话或目标项目已不存在,请刷新后重试。",
|
|
6544
|
+
"sessions.moveSubagent": "子代理会话不能移动到其他项目。",
|
|
6545
|
+
"sessions.moveBusy": "该会话正在移动,请稍后重试。",
|
|
6546
|
+
"sessions.moveRollbackFailed": "会话移动失败,自动恢复未完整完成,请查看 DSH 服务端日志。",
|
|
6547
|
+
"sessions.moveFailed": "暂时无法移动该会话,原会话已保留。",
|
|
6548
|
+
"sessions.moveConfirmTitle": "将会话移至“{project}”?",
|
|
6549
|
+
"sessions.moveConfirmDescription": "“{name}”将移动到此项目,工作目录也会随之更改。",
|
|
6550
|
+
"sessions.moveConfirmAction": "移动",
|
|
6551
|
+
"sessions.movePending": "正在移动会话…",
|
|
4913
6552
|
"sessions.copyPath": "复制工作目录",
|
|
4914
6553
|
"sessions.copyTitle": "复制会话标题",
|
|
4915
6554
|
"sessions.copyId": "复制会话 ID",
|
|
4916
|
-
"sessions.copyLink": "复制会话链接",
|
|
4917
6555
|
"connectors.title": "连接器",
|
|
4918
6556
|
"connectors.description": "显示当前会话可用的 MCP 连接器及其工具,不显示地址、命令或凭证。",
|
|
4919
6557
|
"connectors.openSession": "请先打开一个会话以读取连接器。",
|
|
@@ -4921,8 +6559,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4921
6559
|
"connectors.failed": "连接器目录暂不可用,请稍后重试。",
|
|
4922
6560
|
"connectors.toolCount": "{count} 个工具",
|
|
4923
6561
|
"connectors.empty": "当前会话没有可用的 MCP 连接器。",
|
|
4924
|
-
"
|
|
6562
|
+
"connectors.promptReady": "已带入新会话",
|
|
6563
|
+
"connectors.promptRequired": "Prompt 不能为空。",
|
|
6564
|
+
"connectors.workspacesLoading": "DSH 工作区数据尚未就绪,请稍后重试。",
|
|
6565
|
+
"connectors.workspaceRequired": "请先选择一个工作区,再使用示例 Prompt。",
|
|
6566
|
+
"connectors.workspaceUnavailable": "DSH 工作区服务尚未就绪,请稍后重试。",
|
|
6567
|
+
"connectors.conversationUnavailable": "DSH 对话服务尚未就绪,请稍后重试。",
|
|
6568
|
+
"connectors.sessionPending": "新会话尚未就绪,请稍后重试。",
|
|
6569
|
+
"about.nav": "Codex UI",
|
|
4925
6570
|
"about.title": "Codex UI",
|
|
6571
|
+
"about.viewProject": "GitHub",
|
|
6572
|
+
"about.feedback": "问题反馈",
|
|
4926
6573
|
"about.description": "为 DSH 提供 Codex 风格的侧栏、工作区会话管理、搜索与会话轮次导航。",
|
|
4927
6574
|
"about.features": "基本功能",
|
|
4928
6575
|
"about.feature.sidebar": "Codex 风格侧栏、全局会话搜索与设置入口",
|
|
@@ -4946,6 +6593,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4946
6593
|
"about.upToDate": "所有配套插件均已安装并为最新版本。",
|
|
4947
6594
|
"about.installFailed": "依赖安装失败,请稍后重试。",
|
|
4948
6595
|
"about.installUnchanged": "安装命令已结束,但插件没有进入当前 Profile。请重试。",
|
|
6596
|
+
"about.installExitDesktop": "请先完全退出 DSH Desktop,再重新打开后更新。",
|
|
6597
|
+
"about.installStoreMismatch": "插件目录与 pnpm 仓库不一致。请完全退出 DSH Desktop 后再更新。",
|
|
6598
|
+
"about.installBuildPolicy": "插件依赖的 pnpm 构建脚本策略尚未确认,请更新 Profile 配置后重试。",
|
|
6599
|
+
"about.installPnpmMissing": "当前环境找不到 pnpm,请安装 pnpm 并重启 DSH 后重试。",
|
|
6600
|
+
"about.installTimeout": "插件安装超时,请检查网络后重试。",
|
|
6601
|
+
"about.installServiceUnavailable": "DSH Desktop 依赖管理服务尚未就绪,请重启后重试。",
|
|
4949
6602
|
"about.restartRequired": "正在热更新插件,窗口会自动刷新。",
|
|
4950
6603
|
"about.restartManually": "安装完成。当前 Web 无法自动重启,请重启 DSH Web 后刷新页面。",
|
|
4951
6604
|
"about.progressHint": "正在安装插件…",
|
|
@@ -4965,7 +6618,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4965
6618
|
"about.dependency.market": "插件市场",
|
|
4966
6619
|
"turns.label": "当前会话轮次导航",
|
|
4967
6620
|
"turns.untitled": "未命名提问",
|
|
4968
|
-
"turns.jump": "跳转到第 {index} 轮:{summary}"
|
|
6621
|
+
"turns.jump": "跳转到第 {index} 轮:{summary}",
|
|
6622
|
+
"time.justNow": "刚刚",
|
|
6623
|
+
"time.minutes": "{count}分",
|
|
6624
|
+
"time.hours": "{count}小时",
|
|
6625
|
+
"time.days": "{count}天",
|
|
6626
|
+
"errors.generic": "操作未完成,请重试。",
|
|
6627
|
+
"errors.groupInvalid": "分组信息无效。",
|
|
6628
|
+
"errors.workspaceInvalid": "项目标识无效。",
|
|
6629
|
+
"errors.groupMissing": "目标分组不存在。",
|
|
6630
|
+
"errors.orderAnchorMissing": "排序位置已失效,请重试。",
|
|
6631
|
+
"meta.locale": "zh-CN"
|
|
4969
6632
|
};
|
|
4970
6633
|
const en = {
|
|
4971
6634
|
"sidebar.label": "DSH navigation",
|
|
@@ -4997,6 +6660,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4997
6660
|
"channel.wecom": "WeCom",
|
|
4998
6661
|
"channel.qq": "QQ",
|
|
4999
6662
|
"channel.telegram": "Telegram",
|
|
6663
|
+
"channel.unknown": "Channel",
|
|
5000
6664
|
"schedule.empty": "No scheduled-task runs yet.",
|
|
5001
6665
|
"schedule.groupActions": "Task actions for {name}",
|
|
5002
6666
|
"schedule.taskSettings": "Task settings",
|
|
@@ -5012,32 +6676,45 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5012
6676
|
"search.actions": "Quick actions",
|
|
5013
6677
|
"workspace.label": "Workspace conversations",
|
|
5014
6678
|
"workspace.projects": "Projects",
|
|
6679
|
+
"workspace.ungrouped": "Ungrouped",
|
|
6680
|
+
"workspace.createGroup": "Create group",
|
|
6681
|
+
"workspace.createGroupDescription": "Enter a group name. Projects will not move automatically.",
|
|
6682
|
+
"workspace.groupName": "Group name",
|
|
6683
|
+
"workspace.moveToGroup": "Move to group",
|
|
6684
|
+
"workspace.removeFromGroup": "Move to ungrouped",
|
|
6685
|
+
"workspace.deleteGroup": "Delete group {name}",
|
|
6686
|
+
"workspace.deleteGroupAction": "Delete group",
|
|
6687
|
+
"workspace.deleteGroupDescription": "Deleting this group moves its projects to Ungrouped. It does not delete projects or conversations.",
|
|
6688
|
+
"workspace.manageGroups": "Manage groups",
|
|
5015
6689
|
"workspace.recent": "Recents",
|
|
5016
6690
|
"workspace.recentEmpty": "No chats",
|
|
5017
6691
|
"workspace.noChat": "No chats",
|
|
5018
|
-
"workspace.empty": "No
|
|
6692
|
+
"workspace.empty": "No projects",
|
|
5019
6693
|
"workspace.newSession": "New conversation",
|
|
5020
|
-
"workspace.rename": "
|
|
6694
|
+
"workspace.rename": "Rename project",
|
|
5021
6695
|
"workspace.pin": "Pin project",
|
|
5022
6696
|
"workspace.unpin": "Unpin",
|
|
6697
|
+
"workspace.archive": "Archive all conversations",
|
|
6698
|
+
"workspace.archiveTitle": "Archive {count} conversations?",
|
|
6699
|
+
"workspace.archiveDescription": "This archives every conversation in “{name}”. The project and folder remain available.",
|
|
6700
|
+
"workspace.archiveConfirm": "Archive all",
|
|
6701
|
+
"workspace.archivePending": "Archiving conversations…",
|
|
5023
6702
|
"workspace.pinned": "Pinned",
|
|
5024
6703
|
"workspace.pinnedEmpty": "Drag a project here to pin it",
|
|
5025
6704
|
"workspace.openPath": "Open in file explorer",
|
|
5026
|
-
"workspace.delete": "
|
|
6705
|
+
"workspace.delete": "Remove project",
|
|
5027
6706
|
"workspace.deleteDescription": "This removes “{name}” from the project list. The folder and conversation records remain.",
|
|
5028
|
-
"workspace.deletePending": "
|
|
6707
|
+
"workspace.deletePending": "Removing project…",
|
|
5029
6708
|
"workspace.actions": "Project actions for {name}",
|
|
5030
6709
|
"workspace.taskCount": "{count} tasks",
|
|
5031
|
-
"workspace.
|
|
6710
|
+
"workspace.taskSummary": "{count} tasks · {unreadCount} unread",
|
|
6711
|
+
"workspace.edit": "Rename project",
|
|
5032
6712
|
"sessions.close": "Close",
|
|
5033
6713
|
"sessions.cancel": "Cancel",
|
|
5034
6714
|
"sessions.save": "Save",
|
|
5035
6715
|
"sessions.failed": "Action failed: {message}",
|
|
5036
6716
|
"sessions.unknown": "Conversation not found.",
|
|
5037
6717
|
"sessions.actions": "Conversation actions for {name}",
|
|
5038
|
-
"sessions.pin": "Pin conversation",
|
|
5039
|
-
"sessions.unpin": "Unpin",
|
|
5040
|
-
"sessions.pinned": "Pinned",
|
|
5041
6718
|
"sessions.markUnread": "Mark as unread",
|
|
5042
6719
|
"sessions.markRead": "Mark as read",
|
|
5043
6720
|
"sessions.unread": "Unread",
|
|
@@ -5046,17 +6723,33 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5046
6723
|
"sessions.planReview": "Plan awaiting review",
|
|
5047
6724
|
"sessions.rename": "Rename conversation",
|
|
5048
6725
|
"sessions.renameDescription": "Keep it short and easy to recognize.",
|
|
6726
|
+
"sessions.renameInvalid": "The conversation name is invalid. Change it and try again.",
|
|
6727
|
+
"sessions.renameFailed": "The conversation could not be renamed. Try again later.",
|
|
5049
6728
|
"sessions.archive": "Archive conversation",
|
|
6729
|
+
"sessions.archiveFailed": "The conversation could not be archived. Try again later.",
|
|
5050
6730
|
"sessions.delete": "Delete conversation",
|
|
5051
6731
|
"sessions.deleteDescription": "This permanently deletes “{name}” and all of its records. This cannot be undone.",
|
|
5052
6732
|
"sessions.deletePending": "Deleting conversation…",
|
|
5053
6733
|
"sessions.deleteUnavailable": "The archive manager plugin is not installed or unavailable.",
|
|
6734
|
+
"sessions.deleteFailed": "The conversation could not be deleted. Try again later.",
|
|
5054
6735
|
"sessions.fork": "Continue in new conversation",
|
|
6736
|
+
"sessions.forkUnavailable": "This conversation cannot be continued in a new conversation right now. Try again after the current turn finishes.",
|
|
6737
|
+
"sessions.forkFailed": "A new conversation could not be created. Try again later.",
|
|
5055
6738
|
"sessions.openPath": "Open in file explorer",
|
|
6739
|
+
"sessions.moveWorkspace": "Project",
|
|
6740
|
+
"sessions.moveUnavailable": "Conversation moving is unavailable. Restart DSH and try again.",
|
|
6741
|
+
"sessions.moveNotFound": "The conversation or target project no longer exists. Refresh and try again.",
|
|
6742
|
+
"sessions.moveSubagent": "Subagent conversations cannot be moved to another project.",
|
|
6743
|
+
"sessions.moveBusy": "This conversation is already being moved. Try again shortly.",
|
|
6744
|
+
"sessions.moveRollbackFailed": "The conversation could not be moved, and automatic recovery did not complete. Check the DSH server logs.",
|
|
6745
|
+
"sessions.moveFailed": "The conversation could not be moved. The original conversation was preserved.",
|
|
6746
|
+
"sessions.moveConfirmTitle": "Move conversation to “{project}”?",
|
|
6747
|
+
"sessions.moveConfirmDescription": "“{name}” will move to this project, and its working directory will change with it.",
|
|
6748
|
+
"sessions.moveConfirmAction": "Move",
|
|
6749
|
+
"sessions.movePending": "Moving conversation…",
|
|
5056
6750
|
"sessions.copyPath": "Copy working directory",
|
|
5057
6751
|
"sessions.copyTitle": "Copy conversation title",
|
|
5058
6752
|
"sessions.copyId": "Copy conversation ID",
|
|
5059
|
-
"sessions.copyLink": "Copy conversation link",
|
|
5060
6753
|
"connectors.title": "Connectors",
|
|
5061
6754
|
"connectors.description": "Shows MCP connectors and tools available to this session without exposing addresses, commands, or credentials.",
|
|
5062
6755
|
"connectors.openSession": "Open a conversation to load connectors.",
|
|
@@ -5064,8 +6757,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5064
6757
|
"connectors.failed": "Connectors are unavailable. Try again shortly.",
|
|
5065
6758
|
"connectors.toolCount": "{count} tools",
|
|
5066
6759
|
"connectors.empty": "This conversation has no available MCP connectors.",
|
|
5067
|
-
"
|
|
6760
|
+
"connectors.promptReady": "Added to a new conversation",
|
|
6761
|
+
"connectors.promptRequired": "The prompt cannot be empty.",
|
|
6762
|
+
"connectors.workspacesLoading": "DSH workspace data is still loading. Try again shortly.",
|
|
6763
|
+
"connectors.workspaceRequired": "Select a workspace before using an example prompt.",
|
|
6764
|
+
"connectors.workspaceUnavailable": "The DSH workspace service is not ready. Try again shortly.",
|
|
6765
|
+
"connectors.conversationUnavailable": "The DSH conversation service is not ready. Try again shortly.",
|
|
6766
|
+
"connectors.sessionPending": "The new conversation is not ready yet. Try again shortly.",
|
|
6767
|
+
"about.nav": "Codex UI",
|
|
5068
6768
|
"about.title": "Codex UI",
|
|
6769
|
+
"about.viewProject": "GitHub",
|
|
6770
|
+
"about.feedback": "Issues",
|
|
5069
6771
|
"about.description": "Adds a Codex-style sidebar, workspace conversation management, search, and turn navigation to DSH.",
|
|
5070
6772
|
"about.features": "Core features",
|
|
5071
6773
|
"about.feature.sidebar": "Codex-style sidebar, global conversation search, and settings entry points",
|
|
@@ -5089,6 +6791,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5089
6791
|
"about.upToDate": "All companion plugins are installed and up to date.",
|
|
5090
6792
|
"about.installFailed": "Dependency installation failed. Try again later.",
|
|
5091
6793
|
"about.installUnchanged": "The install command finished, but the plugin did not enter this profile. Try again.",
|
|
6794
|
+
"about.installExitDesktop": "Quit DSH Desktop completely, reopen it, and try the update again.",
|
|
6795
|
+
"about.installStoreMismatch": "The plugin directory and pnpm store do not match. Quit DSH Desktop completely and try again.",
|
|
6796
|
+
"about.installBuildPolicy": "The pnpm build-script policy for this plugin is not configured. Update the Profile configuration and try again.",
|
|
6797
|
+
"about.installPnpmMissing": "pnpm is not available. Install pnpm, restart DSH, and try again.",
|
|
6798
|
+
"about.installTimeout": "Plugin installation timed out. Check the network and try again.",
|
|
6799
|
+
"about.installServiceUnavailable": "The DSH Desktop dependency service is not ready. Restart DSH Desktop and try again.",
|
|
5092
6800
|
"about.restartRequired": "Updating plugins now. The window will refresh automatically.",
|
|
5093
6801
|
"about.restartManually": "Installation complete. This Web host cannot restart itself; restart DSH Web, then refresh the page.",
|
|
5094
6802
|
"about.progressHint": "Installing plugin…",
|
|
@@ -5108,7 +6816,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5108
6816
|
"about.dependency.market": "Plugin Market",
|
|
5109
6817
|
"turns.label": "Conversation turn navigation",
|
|
5110
6818
|
"turns.untitled": "Untitled prompt",
|
|
5111
|
-
"turns.jump": "Jump to turn {index}: {summary}"
|
|
6819
|
+
"turns.jump": "Jump to turn {index}: {summary}",
|
|
6820
|
+
"time.justNow": "Just now",
|
|
6821
|
+
"time.minutes": "{count}m",
|
|
6822
|
+
"time.hours": "{count}h",
|
|
6823
|
+
"time.days": "{count}d",
|
|
6824
|
+
"errors.generic": "The action could not be completed. Try again.",
|
|
6825
|
+
"errors.groupInvalid": "The group information is invalid.",
|
|
6826
|
+
"errors.workspaceInvalid": "The project identifier is invalid.",
|
|
6827
|
+
"errors.groupMissing": "The target group no longer exists.",
|
|
6828
|
+
"errors.orderAnchorMissing": "The target position is no longer available. Try again.",
|
|
6829
|
+
"meta.locale": "en-US"
|
|
5112
6830
|
};
|
|
5113
6831
|
//#endregion
|
|
5114
6832
|
//#region src/client/host-open-path.ts
|
|
@@ -5153,7 +6871,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5153
6871
|
[["定时任务", "Scheduled tasks"], "schedule"],
|
|
5154
6872
|
[["IM助理", "IM Assistant"], "assistant"],
|
|
5155
6873
|
[["已归档", "Archived"], "archive"],
|
|
5156
|
-
[["
|
|
6874
|
+
[["Codex UI"], "about"]
|
|
5157
6875
|
];
|
|
5158
6876
|
/** 按设置导航可见文案解析侧栏同款图标;插件市场复用插件图标。 */
|
|
5159
6877
|
function settingsNavIconId(label) {
|
|
@@ -5516,8 +7234,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5516
7234
|
}
|
|
5517
7235
|
function turnLinks(snapshot, fallback) {
|
|
5518
7236
|
const links = [];
|
|
5519
|
-
for (const key of snapshot.
|
|
5520
|
-
const node = snapshot.
|
|
7237
|
+
for (const key of snapshot.order) {
|
|
7238
|
+
const node = snapshot.nodes.get(key);
|
|
5521
7239
|
if (node?.kind !== "user") continue;
|
|
5522
7240
|
links.push({
|
|
5523
7241
|
key: node.key,
|
|
@@ -5529,14 +7247,21 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5529
7247
|
function equalTurns(left, right) {
|
|
5530
7248
|
return left.length === right.length && left.every((turn, index) => turn.key === right[index]?.key && turn.summary === right[index]?.summary);
|
|
5531
7249
|
}
|
|
7250
|
+
function legacyTurnLinks(useSession, fallback) {
|
|
7251
|
+
return useSession((snapshot) => {
|
|
7252
|
+
const chat = "chat" in snapshot ? snapshot.chat : void 0;
|
|
7253
|
+
return chat === void 0 ? [] : turnLinks(chat, fallback);
|
|
7254
|
+
}, equalTurns);
|
|
7255
|
+
}
|
|
5532
7256
|
function railLeftFromSidebar() {
|
|
5533
7257
|
const sidebar = document.querySelector(".dcu-root");
|
|
5534
7258
|
if (sidebar === null) return 288;
|
|
5535
7259
|
return Math.round(sidebar.getBoundingClientRect().right) + 16;
|
|
5536
7260
|
}
|
|
5537
7261
|
/** 当前会话的轮次导航;只读取原生聊天锚点并滚动,不改写会话数据或消息视图。 */
|
|
5538
|
-
function TurnNavigator({ useSession, t }) {
|
|
5539
|
-
const
|
|
7262
|
+
function TurnNavigator({ useChat, useSession, t }) {
|
|
7263
|
+
const fallback = t("turns.untitled");
|
|
7264
|
+
const turns = useChat === void 0 ? legacyTurnLinks(useSession, fallback) : useChat((snapshot) => turnLinks(snapshot, fallback), equalTurns);
|
|
5540
7265
|
const [current, setCurrent] = (0, react.useState)(turns[0]?.key ?? null);
|
|
5541
7266
|
const [hoverAt, setHoverAt] = (0, react.useState)(null);
|
|
5542
7267
|
const [railLeft, setRailLeft] = (0, react.useState)(288);
|
|
@@ -5696,8 +7421,13 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5696
7421
|
function hasDeleteSession(value) {
|
|
5697
7422
|
return value !== null && typeof value === "object" && "deleteSession" in value && typeof value.deleteSession === "function";
|
|
5698
7423
|
}
|
|
5699
|
-
function
|
|
5700
|
-
|
|
7424
|
+
async function runHostAction(action, execute) {
|
|
7425
|
+
try {
|
|
7426
|
+
return await execute();
|
|
7427
|
+
} catch (reason) {
|
|
7428
|
+
if (reason instanceof UserFacingError || reason instanceof HostActionError) throw reason;
|
|
7429
|
+
throw new HostActionError(action, reason);
|
|
7430
|
+
}
|
|
5701
7431
|
}
|
|
5702
7432
|
/** Archive Manager replaces the official ui-workspace row with this optional service. */
|
|
5703
7433
|
function startWorkspaceSession(ctx, workspaceId) {
|
|
@@ -5706,7 +7436,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5706
7436
|
uiWorkspace.startSession(workspaceId);
|
|
5707
7437
|
return;
|
|
5708
7438
|
}
|
|
5709
|
-
ctx.workspaces
|
|
7439
|
+
if (hasStartSession(ctx.workspaces)) {
|
|
7440
|
+
ctx.workspaces.startSession(workspaceId);
|
|
7441
|
+
return;
|
|
7442
|
+
}
|
|
7443
|
+
console.warn("DSH 工作空间服务尚未就绪,无法新建会话。");
|
|
5710
7444
|
}
|
|
5711
7445
|
/** 替换 DSH 的官方 sidebar 插槽,不修改 DSH 源码或会话数据。 */
|
|
5712
7446
|
function apply(ctx) {
|
|
@@ -5759,9 +7493,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5759
7493
|
toggleSidebar: () => {
|
|
5760
7494
|
ctx.layout.toggleSidebar();
|
|
5761
7495
|
},
|
|
5762
|
-
archiveSession
|
|
7496
|
+
archiveSession,
|
|
5763
7497
|
deleteSession,
|
|
5764
7498
|
forkSession,
|
|
7499
|
+
moveSession,
|
|
5765
7500
|
renameSession,
|
|
5766
7501
|
openPath,
|
|
5767
7502
|
companionSlots
|
|
@@ -5774,36 +7509,65 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5774
7509
|
locale: NS
|
|
5775
7510
|
}, TurnNavigator));
|
|
5776
7511
|
const forkSession = async (sessionId) => {
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
7512
|
+
await runHostAction("fork", async () => {
|
|
7513
|
+
const childId = await ctx.sessions.fork({
|
|
7514
|
+
sessionId,
|
|
7515
|
+
increaseTitle: true
|
|
7516
|
+
});
|
|
7517
|
+
ctx.sessions.open(childId);
|
|
5780
7518
|
});
|
|
5781
|
-
ctx.sessions.open(childId);
|
|
5782
7519
|
};
|
|
5783
7520
|
const renameSession = async (sessionId, title) => {
|
|
5784
7521
|
const session = ctx.sessions.binding(sessionId)?.session;
|
|
5785
|
-
if (session === void 0) throw new
|
|
5786
|
-
|
|
5787
|
-
|
|
7522
|
+
if (session === void 0) throw new UserFacingError(t("sessions.unknown"));
|
|
7523
|
+
await runHostAction("rename", async () => {
|
|
7524
|
+
const result = await session.rename(title);
|
|
7525
|
+
if (!result.ok) throw result.error;
|
|
7526
|
+
});
|
|
5788
7527
|
};
|
|
5789
7528
|
const deleteSession = async (sessionId) => {
|
|
5790
7529
|
const registry = ctx.get("remote.workspaceRegistry");
|
|
5791
|
-
if (!hasDeleteSession(registry)) throw new
|
|
5792
|
-
|
|
5793
|
-
|
|
7530
|
+
if (!hasDeleteSession(registry)) throw new UserFacingError(t("sessions.deleteUnavailable"));
|
|
7531
|
+
await runHostAction("delete", async () => {
|
|
7532
|
+
const result = await registry.deleteSession(sessionId);
|
|
7533
|
+
if (!result.ok) throw result.error === void 0 ? new UserFacingError(t("sessions.deleteUnavailable")) : result.error;
|
|
7534
|
+
});
|
|
7535
|
+
};
|
|
7536
|
+
const archiveSession = (sessionId) => runHostAction("archive", () => ctx.workspaces.archiveSession(sessionId));
|
|
7537
|
+
const moveSession = async (sessionId, targetWorkspaceId) => {
|
|
7538
|
+
try {
|
|
7539
|
+
await requestSessionMove(sessionId, targetWorkspaceId);
|
|
7540
|
+
} catch (error) {
|
|
7541
|
+
if (!(error instanceof SessionMoveRequestError)) throw error;
|
|
7542
|
+
throw new UserFacingError(t(sessionMoveErrorKey(error.code)));
|
|
7543
|
+
}
|
|
7544
|
+
finishSessionMove({
|
|
7545
|
+
sessionId,
|
|
7546
|
+
currentUrl: window.location.href,
|
|
7547
|
+
navigate: (url) => {
|
|
7548
|
+
window.location.replace(url);
|
|
7549
|
+
}
|
|
7550
|
+
});
|
|
5794
7551
|
};
|
|
5795
7552
|
const startConnectorPromptSession = async (promptText) => {
|
|
5796
7553
|
const prompt = promptText.trim();
|
|
5797
|
-
if (prompt === "") throw new
|
|
7554
|
+
if (prompt === "") throw new UserFacingError(t("connectors.promptRequired"));
|
|
5798
7555
|
const workspaces = ctx.workspaces.list.getSnapshot();
|
|
5799
|
-
const
|
|
5800
|
-
const
|
|
5801
|
-
|
|
5802
|
-
const
|
|
7556
|
+
const sessionSnapshot = ctx.sessions.list.getSnapshot();
|
|
7557
|
+
const currentSessionId = sessionSnapshot.current;
|
|
7558
|
+
const currentWorkspaceId = currentSessionId === void 0 ? void 0 : workspaces.items.find((workspace) => workspace.sessionIds.includes(currentSessionId))?.workspaceId;
|
|
7559
|
+
const baselinesReady = workspaceBaselinesReady(workspaces, sessionSnapshot);
|
|
7560
|
+
const targetWorkspaceId = currentWorkspaceId ?? (baselinesReady ? recentWorkspaceId(workspaces.items, sessionSnapshot.byId) : void 0);
|
|
7561
|
+
if (targetWorkspaceId === void 0 && !baselinesReady) throw new UserFacingError(t("connectors.workspacesLoading"));
|
|
7562
|
+
if (targetWorkspaceId === void 0) throw new UserFacingError(t("connectors.workspaceRequired"));
|
|
7563
|
+
const uiWorkspace = ctx.get("uiWorkspace");
|
|
7564
|
+
const workspaceNavigation = hasConnectWorkspace(uiWorkspace) ? uiWorkspace : hasConnectWorkspace(ctx.workspaces) ? ctx.workspaces : void 0;
|
|
7565
|
+
if (workspaceNavigation === void 0) throw new UserFacingError(t("connectors.workspaceUnavailable"));
|
|
7566
|
+
const sessionId = await workspaceNavigation.connectWorkspace(targetWorkspaceId);
|
|
5803
7567
|
const conversation = ctx.get("conversation");
|
|
5804
|
-
if (conversation === void 0) throw new
|
|
7568
|
+
if (conversation === void 0) throw new UserFacingError(t("connectors.conversationUnavailable"));
|
|
5805
7569
|
const binding = ctx.sessions.binding(sessionId);
|
|
5806
|
-
if (binding === void 0) throw new
|
|
7570
|
+
if (binding === void 0) throw new UserFacingError(t("connectors.sessionPending"));
|
|
5807
7571
|
conversation.input.for(binding.ctx).setDraft(prompt);
|
|
5808
7572
|
ctx.sessions.open(sessionId);
|
|
5809
7573
|
};
|
|
@@ -5812,10 +7576,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5812
7576
|
priority: -1,
|
|
5813
7577
|
locale: NS,
|
|
5814
7578
|
inject: () => ({
|
|
5815
|
-
archiveSession
|
|
7579
|
+
archiveSession,
|
|
5816
7580
|
deleteSession,
|
|
5817
7581
|
deleteWorkspace: (workspaceId) => ctx.workspaces.delete(workspaceId),
|
|
5818
7582
|
forkSession,
|
|
7583
|
+
moveSession,
|
|
5819
7584
|
openPath,
|
|
5820
7585
|
openSession: (sessionId) => {
|
|
5821
7586
|
ctx.sessions.open(sessionId);
|