@michengai/dsh-codex-ui 0.2.100 → 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 +45 -0
- package/CHANGELOG.zh-CN.md +45 -0
- package/README.md +1 -2
- package/README.zh-CN.md +1 -2
- package/{dist → lib}/client.js +2526 -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",
|
|
@@ -655,6 +828,10 @@ window.__ModuleLoader__.load({
|
|
|
655
828
|
}
|
|
656
829
|
//#endregion
|
|
657
830
|
//#region src/client/session-pending.ts
|
|
831
|
+
const EMPTY_PENDING_INTERACTIONS = /* @__PURE__ */ new Map();
|
|
832
|
+
function useEmptySessionPendingInteraction(selector) {
|
|
833
|
+
return selector(EMPTY_PENDING_INTERACTIONS);
|
|
834
|
+
}
|
|
658
835
|
function visiblePendingKind(kind) {
|
|
659
836
|
switch (kind) {
|
|
660
837
|
case "approval":
|
|
@@ -663,10 +840,151 @@ window.__ModuleLoader__.load({
|
|
|
663
840
|
default: return;
|
|
664
841
|
}
|
|
665
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
|
+
}
|
|
848
|
+
function pendingInteractionForSession(sessionId, pendingInteractions, summaryKind) {
|
|
849
|
+
return visiblePendingKind(summaryKind) ?? visiblePendingKind(pendingInteractions.get(sessionId)?.kind);
|
|
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
|
+
}
|
|
666
983
|
//#endregion
|
|
667
984
|
//#region src/client/pinned-workspaces.ts
|
|
668
|
-
/**
|
|
985
|
+
/** 浏览器本地持久化键;用于工作区偏好的首帧恢复与 Host 故障兜底。 */
|
|
669
986
|
const PINNED_WORKSPACES_STORAGE_KEY = "dsh-codex-ui.pinned-workspace-ids";
|
|
987
|
+
const WORKSPACE_GROUPS_STORAGE_KEY = "dsh-codex-ui.workspace-groups.v1";
|
|
670
988
|
const WORKSPACE_PREFERENCES_ENDPOINT = "/api/michengai/codex-ui/preferences";
|
|
671
989
|
/** 清理无效或重复的工作区标识。 */
|
|
672
990
|
function normalizePinnedWorkspaceIds(ids) {
|
|
@@ -678,23 +996,29 @@ window.__ModuleLoader__.load({
|
|
|
678
996
|
const next = ids.filter((id) => valid.has(id));
|
|
679
997
|
return next.length === ids.length ? [...ids] : next;
|
|
680
998
|
}
|
|
681
|
-
/** Host
|
|
682
|
-
function
|
|
683
|
-
if (
|
|
684
|
-
|
|
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,
|
|
685
1004
|
writeHost: true
|
|
686
1005
|
};
|
|
687
|
-
if (host.exists)
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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);
|
|
692
1015
|
return {
|
|
693
|
-
|
|
694
|
-
|
|
1016
|
+
pinnedWorkspaceIds,
|
|
1017
|
+
workspaceGroups: local.workspaceGroups,
|
|
1018
|
+
writeHost: pinnedWorkspaceIds.length > 0 || local.workspaceGroups.length > 0
|
|
695
1019
|
};
|
|
696
1020
|
}
|
|
697
|
-
async function
|
|
1021
|
+
async function readHostWorkspacePreferences(fetcher = fetch) {
|
|
698
1022
|
const response = await fetcher(WORKSPACE_PREFERENCES_ENDPOINT, {
|
|
699
1023
|
method: "GET",
|
|
700
1024
|
cache: "no-store",
|
|
@@ -704,22 +1028,35 @@ window.__ModuleLoader__.load({
|
|
|
704
1028
|
const payload = await response.json();
|
|
705
1029
|
if (payload === null || typeof payload !== "object") throw new Error("置顶偏好响应格式无效。");
|
|
706
1030
|
const record = payload;
|
|
707
|
-
|
|
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("置顶偏好响应格式无效。");
|
|
708
1034
|
return {
|
|
709
1035
|
exists: record.exists,
|
|
710
|
-
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(record.pinnedWorkspaceIds)
|
|
1036
|
+
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(record.pinnedWorkspaceIds),
|
|
1037
|
+
workspaceGroups,
|
|
1038
|
+
workspaceGroupsSupported
|
|
711
1039
|
};
|
|
712
1040
|
}
|
|
713
|
-
async function
|
|
1041
|
+
async function writeHostWorkspacePreferences(pinnedWorkspaceIds, workspaceGroups, fetcher = fetch) {
|
|
1042
|
+
const groups = parseWorkspaceGroups([...workspaceGroups]);
|
|
1043
|
+
if (groups === void 0) throw new Error("工作区分组数据无效。");
|
|
714
1044
|
const response = await fetcher(WORKSPACE_PREFERENCES_ENDPOINT, {
|
|
715
1045
|
method: "PUT",
|
|
716
1046
|
cache: "no-store",
|
|
717
1047
|
headers: { "content-type": "application/json" },
|
|
718
|
-
body: JSON.stringify({
|
|
1048
|
+
body: JSON.stringify({
|
|
1049
|
+
pinnedWorkspaceIds: normalizePinnedWorkspaceIds(pinnedWorkspaceIds),
|
|
1050
|
+
workspaceGroups: groups
|
|
1051
|
+
}),
|
|
719
1052
|
signal: AbortSignal.timeout(5e3)
|
|
720
1053
|
});
|
|
721
1054
|
if (!response.ok) throw new Error(`保存置顶偏好失败:HTTP ${response.status}`);
|
|
722
1055
|
}
|
|
1056
|
+
/** 兼容旧调用方;新代码应同时写入分组。 */
|
|
1057
|
+
async function readHostPinnedWorkspaceIds(fetcher = fetch) {
|
|
1058
|
+
return readHostWorkspacePreferences(fetcher);
|
|
1059
|
+
}
|
|
723
1060
|
/** 在置顶列表中切换一个工作区。 */
|
|
724
1061
|
/** 把工作区插入置顶列表的指定位置;省略锚点时追加到末尾。 */
|
|
725
1062
|
function insertPinnedWorkspace(ids, id, beforeId) {
|
|
@@ -750,6 +1087,80 @@ window.__ModuleLoader__.load({
|
|
|
750
1087
|
storage.setItem(PINNED_WORKSPACES_STORAGE_KEY, JSON.stringify(normalizePinnedWorkspaceIds(ids)));
|
|
751
1088
|
} catch {}
|
|
752
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
|
+
}
|
|
753
1164
|
//#endregion
|
|
754
1165
|
//#region src/client/hover-tip.ts
|
|
755
1166
|
/** 把悬停卡片限制在视口内,避免贴边裁切。 */
|
|
@@ -768,12 +1179,12 @@ window.__ModuleLoader__.load({
|
|
|
768
1179
|
};
|
|
769
1180
|
}
|
|
770
1181
|
/** Codex 会话卡片右上角的紧凑相对时间。 */
|
|
771
|
-
function formatHoverTime(updatedAt, now = Date.now()) {
|
|
1182
|
+
function formatHoverTime(updatedAt, t, now = Date.now()) {
|
|
772
1183
|
const seconds = Math.max(0, Math.round((now - updatedAt) / 1e3));
|
|
773
|
-
if (seconds < 60) return "
|
|
774
|
-
if (seconds < 3600) return
|
|
775
|
-
if (seconds < 86400) return
|
|
776
|
-
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) });
|
|
777
1188
|
}
|
|
778
1189
|
//#endregion
|
|
779
1190
|
//#region src/client/conversation-bubbles.ts
|
|
@@ -1016,6 +1427,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1016
1427
|
//#endregion
|
|
1017
1428
|
//#region src/client/hover-shell.tsx
|
|
1018
1429
|
const HOVER_TIP_SHOW_DELAY_MS = 1e3;
|
|
1430
|
+
const WORKSPACE_HOVER_CARD_ESTIMATED_HEIGHT = 152;
|
|
1019
1431
|
const HoverDispatchContext = (0, react.createContext)({
|
|
1020
1432
|
showTip: () => {},
|
|
1021
1433
|
hideTip: () => {},
|
|
@@ -1036,7 +1448,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1036
1448
|
tipRef.current = hoverTip;
|
|
1037
1449
|
const place = (tip) => ({
|
|
1038
1450
|
...tip,
|
|
1039
|
-
...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)
|
|
1040
1452
|
});
|
|
1041
1453
|
const dispatch = (0, react.useMemo)(() => ({
|
|
1042
1454
|
showTip: (tip, options) => {
|
|
@@ -1114,7 +1526,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1114
1526
|
//#endregion
|
|
1115
1527
|
//#region src/client/workspace-hover-card.tsx
|
|
1116
1528
|
/** 只订阅悬停值,避免工作区树随鼠标移动整树重绘。 */
|
|
1117
|
-
function WorkspaceHoverCard({ t, onEditWorkspace }) {
|
|
1529
|
+
function WorkspaceHoverCard({ t, onEditWorkspace, onToggleWorkspacePin }) {
|
|
1118
1530
|
const hoverTip = useHoverValue();
|
|
1119
1531
|
const { keepTip, hideTip, dismissTip } = useHoverDispatch();
|
|
1120
1532
|
(0, react.useEffect)(() => {
|
|
@@ -1131,8 +1543,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1131
1543
|
};
|
|
1132
1544
|
}, [hoverTip, dismissTip]);
|
|
1133
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 });
|
|
1134
1552
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1135
|
-
className: "dcu-wb-tip"
|
|
1553
|
+
className: `dcu-wb-tip${workspace ? " dcu-wb-tip-workspace" : ""}`,
|
|
1136
1554
|
style: {
|
|
1137
1555
|
left: hoverTip.left,
|
|
1138
1556
|
top: hoverTip.top
|
|
@@ -1143,59 +1561,69 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1143
1561
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1144
1562
|
className: "dcu-wb-tip-title",
|
|
1145
1563
|
children: [
|
|
1146
|
-
|
|
1564
|
+
workspace && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1147
1565
|
className: "dcu-wb-folder",
|
|
1148
1566
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
1149
1567
|
}),
|
|
1150
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1151
|
-
|
|
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", {
|
|
1152
1582
|
className: "dcu-wb-tip-time",
|
|
1153
1583
|
children: hoverTip.time
|
|
1154
1584
|
})
|
|
1155
1585
|
]
|
|
1156
1586
|
}),
|
|
1157
|
-
|
|
1587
|
+
workspace && hoverTip.count !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1158
1588
|
className: "dcu-wb-tip-meta",
|
|
1159
|
-
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 })]
|
|
1160
1594
|
}),
|
|
1161
|
-
|
|
1162
|
-
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",
|
|
1163
1597
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1164
1598
|
className: "dcu-wb-folder",
|
|
1165
1599
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
1166
|
-
}), /* @__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
|
+
})]
|
|
1167
1604
|
}),
|
|
1168
|
-
|
|
1605
|
+
!workspace && hoverTip.project !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1169
1606
|
className: "dcu-wb-tip-row",
|
|
1170
1607
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1171
1608
|
className: "dcu-wb-folder",
|
|
1172
1609
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 16 })
|
|
1173
1610
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: hoverTip.project })]
|
|
1174
1611
|
}),
|
|
1175
|
-
|
|
1612
|
+
!workspace && hoverTip.branch !== void 0 && hoverTip.branch !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1176
1613
|
className: "dcu-wb-tip-row",
|
|
1177
1614
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1178
1615
|
className: "dcu-wb-folder",
|
|
1179
1616
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, { size: 16 })
|
|
1180
1617
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: hoverTip.branch })]
|
|
1181
1618
|
}),
|
|
1182
|
-
|
|
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", {
|
|
1183
1620
|
type: "button",
|
|
1184
1621
|
className: "dcu-wb-tip-edit",
|
|
1185
1622
|
onClick: () => {
|
|
1186
|
-
onEditWorkspace(
|
|
1623
|
+
onEditWorkspace(workspaceId, hoverTip.title);
|
|
1187
1624
|
dismissTip();
|
|
1188
1625
|
},
|
|
1189
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1190
|
-
viewBox: "0 0 16 16",
|
|
1191
|
-
width: 16,
|
|
1192
|
-
height: 16,
|
|
1193
|
-
"aria-hidden": "true",
|
|
1194
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1195
|
-
fill: "currentColor",
|
|
1196
|
-
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"
|
|
1197
|
-
})
|
|
1198
|
-
}), t("workspace.edit")]
|
|
1626
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }), t("workspace.edit")]
|
|
1199
1627
|
})] })
|
|
1200
1628
|
]
|
|
1201
1629
|
});
|
|
@@ -1211,7 +1639,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1211
1639
|
return name !== void 0 && name !== "" ? name : title.trim();
|
|
1212
1640
|
}
|
|
1213
1641
|
/** 把定时运行会话按任务名收成和任务树一样的分组。 */
|
|
1214
|
-
function groupScheduleSessions(items) {
|
|
1642
|
+
function groupScheduleSessions(items, locale = "zh-CN") {
|
|
1215
1643
|
const groups = /* @__PURE__ */ new Map();
|
|
1216
1644
|
for (const item of items) {
|
|
1217
1645
|
if (!isScheduleSession(item.id, item.title)) continue;
|
|
@@ -1227,7 +1655,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1227
1655
|
return [...groups.values()].map((group) => ({
|
|
1228
1656
|
...group,
|
|
1229
1657
|
sessions: [...group.sessions].sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0))
|
|
1230
|
-
})).sort((left, right) => left.label.localeCompare(right.label,
|
|
1658
|
+
})).sort((left, right) => left.label.localeCompare(right.label, locale, {
|
|
1231
1659
|
numeric: true,
|
|
1232
1660
|
sensitivity: "base"
|
|
1233
1661
|
}));
|
|
@@ -1296,10 +1724,39 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1296
1724
|
return item === void 0 ? [] : [item];
|
|
1297
1725
|
});
|
|
1298
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
|
+
}
|
|
1299
1754
|
const SESSION_DRAG_TYPE = "application/x-dcu-session";
|
|
1300
1755
|
const WORKSPACE_DRAG_TYPE = "application/x-dcu-workspace";
|
|
1756
|
+
const WORKSPACE_GROUP_DRAG_TYPE = "application/x-dcu-workspace-group";
|
|
1301
1757
|
const SESSION_DRAG_PREFIX = "dcu-session:";
|
|
1302
1758
|
const WORKSPACE_DRAG_PREFIX = "dcu-workspace:";
|
|
1759
|
+
const WORKSPACE_GROUP_DRAG_PREFIX = "dcu-workspace-group:";
|
|
1303
1760
|
function textPayload(data) {
|
|
1304
1761
|
try {
|
|
1305
1762
|
return data?.getData("text/plain") ?? "";
|
|
@@ -1318,6 +1775,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1318
1775
|
data.setData("text/plain", `${WORKSPACE_DRAG_PREFIX}${workspaceId}`);
|
|
1319
1776
|
data.setData(WORKSPACE_DRAG_TYPE, workspaceId);
|
|
1320
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
|
+
}
|
|
1321
1783
|
function readSessionDrag(data, fallback) {
|
|
1322
1784
|
try {
|
|
1323
1785
|
const typed = data?.getData(SESSION_DRAG_TYPE);
|
|
@@ -1327,9 +1789,23 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1327
1789
|
if (text.startsWith(SESSION_DRAG_PREFIX)) return text.slice(12);
|
|
1328
1790
|
return fallback !== void 0 && fallback.trim() !== "" ? fallback : void 0;
|
|
1329
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
|
+
}
|
|
1330
1805
|
/** 会话拖拽优先;有会话载荷时不得再把父项目置顶。 */
|
|
1331
1806
|
function readWorkspaceDrag(data, fallback) {
|
|
1332
1807
|
if (readSessionDrag(data) !== void 0) return void 0;
|
|
1808
|
+
if (readWorkspaceGroupDrag(data) !== void 0) return void 0;
|
|
1333
1809
|
try {
|
|
1334
1810
|
const typed = data?.getData(WORKSPACE_DRAG_TYPE);
|
|
1335
1811
|
if (typed !== void 0 && typed.trim() !== "") return typed;
|
|
@@ -1373,60 +1849,364 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1373
1849
|
} catch {}
|
|
1374
1850
|
}
|
|
1375
1851
|
//#endregion
|
|
1376
|
-
//#region src/client/
|
|
1377
|
-
|
|
1378
|
-
.
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
.
|
|
1382
|
-
|
|
1383
|
-
|
|
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
|
-
|
|
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}
|
|
1412
2193
|
.dcu-wb-delete-button{color:var(--dsw-alias-state-error-primary)!important}
|
|
1413
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}
|
|
1414
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}
|
|
1415
2197
|
.dcu-wb-rename-input:hover{border-color:color-mix(in srgb,var(--dsw-alias-label-primary) 32%,var(--dsw-alias-border-l2))}
|
|
1416
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)}
|
|
1417
2199
|
`;
|
|
1418
|
-
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}}`;
|
|
1419
|
-
const typographyStyles = `.dcu-wb{font:14px/20px var(--dcu-font,var(--dsw-font-family))}.dcu-wb-section-label{color:var(--dcu-sidebar-
|
|
1420
|
-
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;
|
|
1421
2204
|
function storage$1() {
|
|
1422
2205
|
return browserStorage();
|
|
1423
2206
|
}
|
|
1424
2207
|
function sameIds(left, right) {
|
|
1425
2208
|
return left.length === right.length && left.every((id, index) => id === right[index]);
|
|
1426
2209
|
}
|
|
1427
|
-
function browserBase() {
|
|
1428
|
-
return typeof window === "undefined" || window.location.origin === "null" ? "http://dsh.internal/" : `${window.location.origin}/`;
|
|
1429
|
-
}
|
|
1430
2210
|
function optionalText(value, key) {
|
|
1431
2211
|
if (!(key in value)) return void 0;
|
|
1432
2212
|
const next = value[key];
|
|
@@ -1436,13 +2216,21 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1436
2216
|
function CodexWorkspaceBrowser(props) {
|
|
1437
2217
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HoverShell, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodexWorkspaceTree, { ...props }) });
|
|
1438
2218
|
}
|
|
1439
|
-
function CodexWorkspaceTree({ wide, useSessions, 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 }) {
|
|
1440
2220
|
const sessions = useSessions((state) => state);
|
|
2221
|
+
const pendingInteractions = (useSessionPendingInteraction ?? useEmptySessionPendingInteraction)((state) => state);
|
|
1441
2222
|
const workspaces = useWorkspaces((state) => state);
|
|
2223
|
+
const baselinesReady = workspaceBaselinesReady(workspaces, sessions);
|
|
1442
2224
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY));
|
|
1443
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);
|
|
1444
2228
|
const pinnedWorkspaceIdsRef = (0, react.useRef)(pinnedWorkspaceIds);
|
|
1445
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);
|
|
1446
2234
|
const pinnedHostHydratedRef = (0, react.useRef)(false);
|
|
1447
2235
|
const pinnedHostDirtyRef = (0, react.useRef)(false);
|
|
1448
2236
|
const pinnedHostSkipWriteRef = (0, react.useRef)();
|
|
@@ -1452,12 +2240,24 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1452
2240
|
validIds: []
|
|
1453
2241
|
});
|
|
1454
2242
|
workspaceBaselineRef.current = {
|
|
1455
|
-
ready:
|
|
2243
|
+
ready: baselinesReady,
|
|
1456
2244
|
validIds: workspaces.items.map((workspace) => String(workspace.workspaceId))
|
|
1457
2245
|
};
|
|
1458
|
-
const queuePinnedHostWrite = (ids) => {
|
|
1459
|
-
const snapshot =
|
|
1460
|
-
|
|
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
|
+
});
|
|
1461
2261
|
pinnedHostWriteRef.current = pending.catch(() => void 0);
|
|
1462
2262
|
};
|
|
1463
2263
|
const setPinnedWorkspaceIds = (update) => {
|
|
@@ -1467,11 +2267,21 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1467
2267
|
pinnedWorkspaceIdsRef.current = next;
|
|
1468
2268
|
setPinnedWorkspaceIdsState(next);
|
|
1469
2269
|
};
|
|
1470
|
-
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
|
+
};
|
|
1471
2278
|
const [unreadSessionIds, setUnreadSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY));
|
|
2279
|
+
const previousSessionRunningRef = (0, react.useRef)();
|
|
1472
2280
|
const [menu, setMenu] = (0, react.useState)();
|
|
1473
2281
|
const [renameTarget, setRenameTarget] = (0, react.useState)();
|
|
1474
2282
|
const [deleteTarget, setDeleteTarget] = (0, react.useState)();
|
|
2283
|
+
const [archiveWorkspaceTarget, setArchiveWorkspaceTarget] = (0, react.useState)();
|
|
2284
|
+
const [sessionMoveTarget, setSessionMoveTarget] = (0, react.useState)();
|
|
1475
2285
|
const { showTip: publishTip, hideTip, dismissTip, isShowing } = useHoverDispatch();
|
|
1476
2286
|
const showTip = (tip, options) => {
|
|
1477
2287
|
if (menu !== void 0) return;
|
|
@@ -1483,8 +2293,17 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1483
2293
|
const [error, setError] = (0, react.useState)();
|
|
1484
2294
|
const [workspaceDragId, setWorkspaceDragId] = (0, react.useState)();
|
|
1485
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
|
+
};
|
|
1486
2304
|
const workspaceDropTargetRef = (0, react.useRef)();
|
|
1487
2305
|
const setWorkspaceDropTarget = (target) => {
|
|
2306
|
+
if (sameWorkspaceDropTarget(workspaceDropTargetRef.current, target)) return;
|
|
1488
2307
|
workspaceDropTargetRef.current = target;
|
|
1489
2308
|
setWorkspaceDropTargetState(target);
|
|
1490
2309
|
};
|
|
@@ -1494,75 +2313,108 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1494
2313
|
const headerMenuPointerAt = (0, react.useRef)(0);
|
|
1495
2314
|
const [sessionDrag, setSessionDrag] = (0, react.useState)();
|
|
1496
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);
|
|
1497
2320
|
(0, react.useEffect)(() => {
|
|
1498
2321
|
writeTreeExpansionState(storage$1(), WORKSPACE_EXPANSION_STORAGE_KEY, expanded);
|
|
1499
2322
|
}, [expanded]);
|
|
1500
2323
|
(0, react.useEffect)(() => {
|
|
1501
2324
|
savePinnedWorkspaceIds(storage$1(), pinnedWorkspaceIds);
|
|
2325
|
+
saveWorkspaceGroupsCache(storage$1(), workspaceGroups, workspaceGroupsPendingHostSyncRef.current);
|
|
1502
2326
|
if (!pinnedHostHydratedRef.current) return;
|
|
1503
2327
|
const skippedHydration = pinnedHostSkipWriteRef.current;
|
|
1504
2328
|
pinnedHostSkipWriteRef.current = void 0;
|
|
1505
|
-
if (skippedHydration !== void 0 && sameIds(skippedHydration, pinnedWorkspaceIds)) return;
|
|
1506
|
-
queuePinnedHostWrite(pinnedWorkspaceIds);
|
|
1507
|
-
}, [pinnedWorkspaceIds]);
|
|
2329
|
+
if (skippedHydration !== void 0 && sameIds(skippedHydration.pinnedWorkspaceIds, pinnedWorkspaceIds) && sameWorkspaceGroups(skippedHydration.workspaceGroups, workspaceGroups)) return;
|
|
2330
|
+
queuePinnedHostWrite(pinnedWorkspaceIds, workspaceGroups);
|
|
2331
|
+
}, [pinnedWorkspaceIds, workspaceGroups]);
|
|
1508
2332
|
(0, react.useEffect)(() => {
|
|
1509
2333
|
let alive = true;
|
|
1510
|
-
const
|
|
2334
|
+
const local = {
|
|
2335
|
+
pinnedWorkspaceIds: [...pinnedWorkspaceIdsRef.current],
|
|
2336
|
+
workspaceGroups: workspaceGroupsRef.current
|
|
2337
|
+
};
|
|
1511
2338
|
readHostPinnedWorkspaceIds().then((host) => {
|
|
1512
2339
|
if (!alive) return;
|
|
1513
|
-
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);
|
|
1514
2345
|
const baseline = workspaceBaselineRef.current;
|
|
1515
|
-
const ids = baseline.ready ? prunePinnedWorkspaceIds(hydration.
|
|
1516
|
-
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;
|
|
1517
2351
|
pinnedHostHydratedRef.current = true;
|
|
1518
|
-
if (!sameIds(pinnedWorkspaceIdsRef.current, ids)) {
|
|
1519
|
-
pinnedHostSkipWriteRef.current =
|
|
2352
|
+
if (!sameIds(pinnedWorkspaceIdsRef.current, ids) || !sameWorkspaceGroups(workspaceGroupsRef.current, groups)) {
|
|
2353
|
+
pinnedHostSkipWriteRef.current = {
|
|
2354
|
+
pinnedWorkspaceIds: [...ids],
|
|
2355
|
+
workspaceGroups: groups
|
|
2356
|
+
};
|
|
1520
2357
|
pinnedWorkspaceIdsRef.current = ids;
|
|
2358
|
+
workspaceGroupsRef.current = groups;
|
|
1521
2359
|
setPinnedWorkspaceIdsState(ids);
|
|
2360
|
+
setWorkspaceGroupsState(groups);
|
|
1522
2361
|
}
|
|
1523
2362
|
savePinnedWorkspaceIds(storage$1(), ids);
|
|
1524
|
-
if (writeHost) queuePinnedHostWrite(ids);
|
|
1525
|
-
}).catch(() => {
|
|
2363
|
+
if (writeHost) queuePinnedHostWrite(ids, groups);
|
|
2364
|
+
}).catch(() => {
|
|
2365
|
+
pinnedHostHydratedRef.current = true;
|
|
2366
|
+
});
|
|
1526
2367
|
return () => {
|
|
1527
2368
|
alive = false;
|
|
1528
2369
|
};
|
|
1529
2370
|
}, []);
|
|
1530
|
-
(0, react.useEffect)(() => {
|
|
1531
|
-
writeSessionIds(storage$1(), SESSION_PINS_STORAGE_KEY, pinnedSessionIds);
|
|
1532
|
-
}, [pinnedSessionIds]);
|
|
1533
2371
|
(0, react.useEffect)(() => {
|
|
1534
2372
|
writeSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY, unreadSessionIds);
|
|
1535
2373
|
}, [unreadSessionIds]);
|
|
1536
2374
|
(0, react.useEffect)(() => {
|
|
1537
|
-
if (
|
|
1538
|
-
const
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
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]);
|
|
1543
2388
|
(0, react.useEffect)(() => {
|
|
1544
2389
|
const current = sessions.current;
|
|
1545
2390
|
if (current !== void 0) setUnreadSessionIds((ids) => ids.filter((id) => id !== current));
|
|
1546
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]);
|
|
1547
2400
|
const groups = (0, react.useMemo)(() => {
|
|
1548
2401
|
const archived = workspaces.archivedSessionIds;
|
|
1549
|
-
const visible = (ids) => visibleSessionIds(ids, sessions.byId, archived)
|
|
1550
|
-
const leftPinned = pinnedSessionIds.indexOf(left);
|
|
1551
|
-
const rightPinned = pinnedSessionIds.indexOf(right);
|
|
1552
|
-
if (leftPinned !== -1 || rightPinned !== -1) return (leftPinned === -1 ? Number.MAX_SAFE_INTEGER : leftPinned) - (rightPinned === -1 ? Number.MAX_SAFE_INTEGER : rightPinned);
|
|
1553
|
-
return 0;
|
|
1554
|
-
});
|
|
2402
|
+
const visible = (ids) => visibleSessionIds(ids, sessions.byId, archived);
|
|
1555
2403
|
return { items: workspaces.items.map((workspace) => ({
|
|
1556
2404
|
...workspace,
|
|
1557
2405
|
visibleIds: visible(workspace.sessionIds)
|
|
1558
2406
|
})) };
|
|
1559
2407
|
}, [
|
|
1560
|
-
pinnedSessionIds,
|
|
1561
2408
|
sessions.byId,
|
|
1562
2409
|
sessions.ids,
|
|
1563
2410
|
workspaces.archivedSessionIds,
|
|
1564
2411
|
workspaces.items
|
|
1565
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
|
+
};
|
|
1566
2418
|
(0, react.useEffect)(() => {
|
|
1567
2419
|
const onPointerDown = () => {
|
|
1568
2420
|
if (headerMenuRef.current !== void 0) headerMenuPointerAt.current = performance.now();
|
|
@@ -1588,6 +2440,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1588
2440
|
title: workspace.title,
|
|
1589
2441
|
path: workspace.path,
|
|
1590
2442
|
count: workspace.visibleIds.length,
|
|
2443
|
+
unreadCount: workspace.visibleIds.filter((id) => unreadSessionIds.includes(String(id))).length,
|
|
2444
|
+
pinned: pinnedWorkspaceIds.includes(String(workspace.workspaceId)),
|
|
1591
2445
|
left: detail.left,
|
|
1592
2446
|
top: detail.top
|
|
1593
2447
|
}, { immediate: true });
|
|
@@ -1616,7 +2470,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1616
2470
|
}, [
|
|
1617
2471
|
groups.items,
|
|
1618
2472
|
sessions.current,
|
|
1619
|
-
menu
|
|
2473
|
+
menu,
|
|
2474
|
+
pinnedWorkspaceIds,
|
|
2475
|
+
unreadSessionIds
|
|
1620
2476
|
]);
|
|
1621
2477
|
const projectPinned = (id) => pinnedWorkspaceIds.includes(String(id));
|
|
1622
2478
|
const pinnedGroups = orderByIds(groups.items, pinnedWorkspaceIds, (workspace) => String(workspace.workspaceId));
|
|
@@ -1624,6 +2480,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1624
2480
|
const pinDragActive = workspaceDragId !== void 0;
|
|
1625
2481
|
const pinnedGroupIds = pinnedGroups.map((workspace) => String(workspace.workspaceId));
|
|
1626
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]));
|
|
1627
2488
|
const pinnedHeaderDrop = workspaceDropTarget?.zone === "pinned" && workspaceDropTarget.beforeId === pinnedGroupIds[0] ? pinnedHeaderDropIndicator(pinnedGroupIds) : void 0;
|
|
1628
2489
|
const assignedIds = workspaces.items.flatMap((workspace) => workspace.sessionIds.map((id) => String(id)));
|
|
1629
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));
|
|
@@ -1636,7 +2497,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1636
2497
|
await action();
|
|
1637
2498
|
setMenu(void 0);
|
|
1638
2499
|
} catch (reason) {
|
|
1639
|
-
setError(reason
|
|
2500
|
+
setError(userErrorText(reason, t));
|
|
1640
2501
|
} finally {
|
|
1641
2502
|
busyRef.current = void 0;
|
|
1642
2503
|
setBusy(void 0);
|
|
@@ -1666,7 +2527,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1666
2527
|
run(operation, async () => {
|
|
1667
2528
|
if (target.kind === "session") {
|
|
1668
2529
|
await deleteSession(target.id);
|
|
1669
|
-
setPinnedSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
1670
2530
|
setUnreadSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
1671
2531
|
} else {
|
|
1672
2532
|
await deleteWorkspace(target.id);
|
|
@@ -1675,6 +2535,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1675
2535
|
setDeleteTarget(void 0);
|
|
1676
2536
|
});
|
|
1677
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
|
+
};
|
|
1678
2547
|
const copy = (value) => {
|
|
1679
2548
|
if (value === void 0 || value === "") return;
|
|
1680
2549
|
run("copy", async () => {
|
|
@@ -1692,6 +2561,19 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1692
2561
|
[key]: !(current[key] ?? defaultOpen)
|
|
1693
2562
|
}));
|
|
1694
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
|
+
};
|
|
1695
2577
|
const sectionOpen = (id) => expanded[`section:${id}`] ?? true;
|
|
1696
2578
|
const toggleSection = (id) => {
|
|
1697
2579
|
setExpanded((current) => ({
|
|
@@ -1699,44 +2581,150 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1699
2581
|
[`section:${id}`]: !(current[`section:${id}`] ?? true)
|
|
1700
2582
|
}));
|
|
1701
2583
|
};
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
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;
|
|
1732
2653
|
}
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
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, {
|
|
1736
2680
|
unread: unreadSessionIds.includes(sessionId),
|
|
1737
2681
|
path,
|
|
1738
|
-
includePath: true
|
|
2682
|
+
includePath: true,
|
|
2683
|
+
moveTargets: sessionMoveTargets(groups.items, sessionId).map((target) => ({
|
|
2684
|
+
...target,
|
|
2685
|
+
id: moveSessionActionId(target.id)
|
|
2686
|
+
}))
|
|
1739
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
|
+
};
|
|
1740
2728
|
const pinWorkspaceAt = (id, beforeId) => {
|
|
1741
2729
|
setPinnedWorkspaceIds((ids) => insertPinnedWorkspace(ids, id, beforeId));
|
|
1742
2730
|
};
|
|
@@ -1749,207 +2737,222 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1749
2737
|
x: menu.x,
|
|
1750
2738
|
y: menu.y
|
|
1751
2739
|
} : void 0;
|
|
1752
|
-
const isCurrentWorkspace = sessions.current !== void 0 && workspace.visibleIds.includes(sessions.current);
|
|
1753
2740
|
const isPinnedHeaderDrop = zone === "pinned" && pinnedHeaderDrop?.kind === "workspace" && pinnedHeaderDrop.workspaceId === String(workspace.workspaceId);
|
|
1754
2741
|
const workspaceId = String(workspace.workspaceId);
|
|
1755
2742
|
const zoneIds = zone === "pinned" ? pinnedGroupIds : regularGroupIds;
|
|
1756
2743
|
const dropsBefore = workspaceDropTarget?.zone === zone && workspaceDropTarget.beforeId === workspaceId;
|
|
1757
2744
|
const dropsAfterLast = zone === "projects" && workspaceDropTarget?.zone === zone && workspaceDropTarget.beforeId === void 0 && zoneIds[zoneIds.length - 1] === workspaceId;
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
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) {
|
|
1762
2750
|
event.preventDefault();
|
|
1763
2751
|
event.stopPropagation();
|
|
1764
2752
|
event.dataTransfer.dropEffect = "move";
|
|
1765
2753
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
1766
|
-
const
|
|
1767
|
-
|
|
2754
|
+
const beforeId = reorderDropBeforeId(zoneIds, draggedWorkspace, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
2755
|
+
setSessionDropTarget(void 0);
|
|
1768
2756
|
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
1769
2757
|
zone,
|
|
1770
2758
|
beforeId
|
|
1771
2759
|
});
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
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) {
|
|
1778
2779
|
event.preventDefault();
|
|
1779
2780
|
event.stopPropagation();
|
|
1780
|
-
const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
|
|
1781
2781
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
1782
|
-
const
|
|
2782
|
+
const beforeId = reorderDropBeforeId(zoneIds, draggedWorkspace, workspaceId, event.clientY > rect.top + rect.height / 2);
|
|
1783
2783
|
setWorkspaceDragId(void 0);
|
|
1784
2784
|
setWorkspaceDropTarget(void 0);
|
|
1785
|
-
if (dragged === void 0) return;
|
|
1786
|
-
const beforeId = reorderDropBeforeId(zoneIds, dragged, workspaceId, after);
|
|
1787
2785
|
if (beforeId === null) return;
|
|
1788
2786
|
if (zone === "pinned") {
|
|
1789
|
-
pinWorkspaceAt(
|
|
2787
|
+
pinWorkspaceAt(draggedWorkspace, beforeId);
|
|
1790
2788
|
return;
|
|
1791
2789
|
}
|
|
1792
|
-
setPinnedWorkspaceIds((ids) => ids.filter((id) => id !== dragged));
|
|
1793
2790
|
const hostIds = groups.items.map((item) => String(item.workspaceId));
|
|
1794
|
-
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);
|
|
1795
2815
|
},
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
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 === " ") {
|
|
1826
2869
|
event.preventDefault();
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
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
|
-
showTip({
|
|
1866
|
-
kind: "workspace",
|
|
1867
|
-
id: workspace.workspaceId,
|
|
1868
|
-
title: workspace.title,
|
|
1869
|
-
path: workspace.path,
|
|
1870
|
-
count: workspace.visibleIds.length,
|
|
1871
|
-
left: box.left,
|
|
1872
|
-
top: box.top
|
|
1873
|
-
}, { 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);
|
|
1874
2907
|
},
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
open: menuOpen,
|
|
1885
|
-
onClose: () => {
|
|
1886
|
-
setMenu(void 0);
|
|
1887
|
-
},
|
|
1888
|
-
items: projectMenu(workspace),
|
|
1889
|
-
onSelect: (id) => {
|
|
1890
|
-
if (busy !== void 0) return;
|
|
1891
|
-
if (id === "new") {
|
|
1892
|
-
startSession(workspace.workspaceId);
|
|
1893
|
-
setMenu(void 0);
|
|
1894
|
-
}
|
|
1895
|
-
if (id === "rename") beginRename("workspace", workspace.workspaceId, workspace.title);
|
|
1896
|
-
if (id === "pin") {
|
|
1897
|
-
setPinnedWorkspaceIds((ids) => togglePinnedWorkspace(ids, workspace.workspaceId));
|
|
1898
|
-
setMenu(void 0);
|
|
1899
|
-
}
|
|
1900
|
-
if (id === "openPath") openPathImmediately(workspace.path);
|
|
1901
|
-
if (id === "delete") {
|
|
1902
|
-
setDeleteTarget({
|
|
1903
|
-
id: workspace.workspaceId,
|
|
1904
|
-
kind: "workspace",
|
|
1905
|
-
title: workspace.title
|
|
1906
|
-
});
|
|
1907
|
-
setError(void 0);
|
|
1908
|
-
setMenu(void 0);
|
|
1909
|
-
}
|
|
1910
|
-
},
|
|
1911
|
-
portal: true,
|
|
1912
|
-
dense: true,
|
|
1913
|
-
compact: true,
|
|
1914
|
-
getAnchorRect: menuAt === void 0 ? void 0 : () => pointerMenuRect(menuAt.x, menuAt.y),
|
|
1915
|
-
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1916
|
-
type: "button",
|
|
1917
|
-
className: "dcu-wb-more",
|
|
1918
|
-
"aria-label": t("workspace.actions", { name: workspace.title }),
|
|
1919
|
-
onClick: (event) => {
|
|
1920
|
-
event.stopPropagation();
|
|
1921
|
-
setMenu((current) => current?.id === workspace.workspaceId && current.type === "workspace" ? void 0 : {
|
|
1922
|
-
id: workspace.workspaceId,
|
|
1923
|
-
type: "workspace"
|
|
1924
|
-
});
|
|
1925
|
-
},
|
|
1926
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutline16, { size: 16 })
|
|
1927
|
-
})
|
|
1928
|
-
})
|
|
1929
|
-
}),
|
|
1930
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1931
|
-
className: "dcu-wb-actions",
|
|
1932
|
-
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", {
|
|
1933
2917
|
type: "button",
|
|
1934
2918
|
className: "dcu-wb-more",
|
|
1935
|
-
"aria-label": t("workspace.
|
|
2919
|
+
"aria-label": t("workspace.actions", { name: workspace.title }),
|
|
1936
2920
|
onClick: (event) => {
|
|
1937
2921
|
event.stopPropagation();
|
|
1938
|
-
|
|
2922
|
+
dismissTip();
|
|
2923
|
+
setMenu((current) => current?.id === workspace.workspaceId && current?.type === "workspace" ? void 0 : {
|
|
2924
|
+
id: workspace.workspaceId,
|
|
2925
|
+
type: "workspace"
|
|
2926
|
+
});
|
|
1939
2927
|
},
|
|
1940
|
-
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 })
|
|
1941
2929
|
})
|
|
1942
2930
|
})
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
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", {
|
|
1946
2950
|
className: "dcu-wb-nochat",
|
|
1947
2951
|
children: t("workspace.noChat")
|
|
1948
|
-
}),
|
|
1949
|
-
isExpanded && shownIds.map((id) => {
|
|
2952
|
+
}), shownIds.map((id) => {
|
|
1950
2953
|
const session = sessions.byId[id];
|
|
1951
2954
|
if (session === void 0) return null;
|
|
1952
|
-
const pendingInteraction =
|
|
2955
|
+
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, legacyPendingInteraction(session));
|
|
1953
2956
|
const path = session.cwd ?? workspace.path;
|
|
1954
2957
|
const selected = sessions.current === id;
|
|
1955
2958
|
const sessionMenuOpen = menu?.type === "session" && menu.id === id;
|
|
@@ -1957,8 +2960,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1957
2960
|
x: menu.x,
|
|
1958
2961
|
y: menu.y
|
|
1959
2962
|
} : void 0;
|
|
1960
|
-
const dropsBeforeSession = sessionDropTarget?.workspaceId === workspaceId && sessionDropTarget.beforeId === id;
|
|
1961
|
-
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;
|
|
1962
2965
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1963
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" : ""}`,
|
|
1964
2967
|
role: "treeitem",
|
|
@@ -1968,15 +2971,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1968
2971
|
event.stopPropagation();
|
|
1969
2972
|
setWorkspaceDragId(void 0);
|
|
1970
2973
|
setWorkspaceDropTarget(void 0);
|
|
2974
|
+
setWorkspaceGroupDragId(void 0);
|
|
2975
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
1971
2976
|
writeSessionDrag(event.dataTransfer, id, session.displayTitle);
|
|
1972
|
-
|
|
1973
|
-
preview.className = "dcu-wb-drag-ghost";
|
|
1974
|
-
preview.textContent = session.displayTitle;
|
|
1975
|
-
document.body.appendChild(preview);
|
|
1976
|
-
event.dataTransfer.setDragImage(preview, 16, 18);
|
|
1977
|
-
window.requestAnimationFrame(() => {
|
|
1978
|
-
preview.remove();
|
|
1979
|
-
});
|
|
2977
|
+
setDragPreview(event.dataTransfer, session.displayTitle);
|
|
1980
2978
|
setSessionDrag({
|
|
1981
2979
|
sessionId: id,
|
|
1982
2980
|
workspaceId
|
|
@@ -1985,14 +2983,16 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
1985
2983
|
onDragEnd: () => {
|
|
1986
2984
|
setSessionDrag(void 0);
|
|
1987
2985
|
setSessionDropTarget(void 0);
|
|
2986
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
1988
2987
|
},
|
|
1989
2988
|
onDragOver: (event) => {
|
|
1990
|
-
|
|
2989
|
+
const drag = sessionDrag;
|
|
2990
|
+
if (drag === void 0 || drag.workspaceId !== workspaceId) return;
|
|
1991
2991
|
event.preventDefault();
|
|
1992
2992
|
event.stopPropagation();
|
|
1993
2993
|
event.dataTransfer.dropEffect = "move";
|
|
1994
2994
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
1995
|
-
const beforeId = reorderDropBeforeId(shownIds,
|
|
2995
|
+
const beforeId = reorderDropBeforeId(shownIds, drag.sessionId, id, event.clientY > rect.top + rect.height / 2);
|
|
1996
2996
|
setSessionDropTarget(beforeId === null ? void 0 : {
|
|
1997
2997
|
workspaceId,
|
|
1998
2998
|
beforeId
|
|
@@ -2003,13 +3003,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2003
3003
|
setSessionDropTarget(void 0);
|
|
2004
3004
|
},
|
|
2005
3005
|
onDrop: (event) => {
|
|
3006
|
+
const drag = sessionDrag;
|
|
3007
|
+
if (drag === void 0 || drag.workspaceId !== workspaceId) return;
|
|
2006
3008
|
event.preventDefault();
|
|
2007
3009
|
event.stopPropagation();
|
|
2008
|
-
const drag = sessionDrag;
|
|
2009
3010
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
2010
3011
|
setSessionDrag(void 0);
|
|
2011
3012
|
setSessionDropTarget(void 0);
|
|
2012
|
-
if (drag === void 0 || drag.workspaceId !== workspaceId) return;
|
|
2013
3013
|
const beforeId = reorderDropBeforeId(shownIds, drag.sessionId, id, event.clientY > rect.top + rect.height / 2);
|
|
2014
3014
|
if (beforeId !== null) run("session-order", () => insertSessionBefore(workspace.workspaceId, drag.sessionId, beforeId));
|
|
2015
3015
|
},
|
|
@@ -2038,7 +3038,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2038
3038
|
project: workspace.title,
|
|
2039
3039
|
path,
|
|
2040
3040
|
branch,
|
|
2041
|
-
time: formatHoverTime(session.updatedAt),
|
|
3041
|
+
time: formatHoverTime(session.updatedAt, t),
|
|
2042
3042
|
left: box.left,
|
|
2043
3043
|
top: box.top
|
|
2044
3044
|
});
|
|
@@ -2049,37 +3049,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2049
3049
|
className: "dcu-wb-session-title",
|
|
2050
3050
|
children: session.displayTitle.split(/\r?\n/)[0] ?? session.displayTitle
|
|
2051
3051
|
}),
|
|
2052
|
-
pinnedSessionIds.includes(id) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2053
|
-
className: "dcu-wb-pin",
|
|
2054
|
-
"aria-label": t("sessions.pinned"),
|
|
2055
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2056
|
-
viewBox: "0 0 16 16",
|
|
2057
|
-
"aria-hidden": "true",
|
|
2058
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M5 2.5h6M5 2.5v2L3.75 6v1h8.5V6L11 4.5v-2M8 7v6" })
|
|
2059
|
-
})
|
|
2060
|
-
}),
|
|
2061
3052
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionState, {
|
|
2062
3053
|
pendingInteraction,
|
|
2063
3054
|
unread: unreadSessionIds.includes(id),
|
|
2064
3055
|
running: session.running === true,
|
|
2065
3056
|
t
|
|
2066
3057
|
}),
|
|
2067
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3058
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2068
3059
|
className: "dcu-wb-quick-actions",
|
|
2069
|
-
children:
|
|
2070
|
-
type: "button",
|
|
2071
|
-
className: "dcu-wb-more dcu-wb-quick-pin",
|
|
2072
|
-
"aria-label": t(pinnedSessionIds.includes(id) ? "sessions.unpin" : "sessions.pin"),
|
|
2073
|
-
onClick: (event) => {
|
|
2074
|
-
event.stopPropagation();
|
|
2075
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2076
|
-
},
|
|
2077
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2078
|
-
viewBox: "0 0 16 16",
|
|
2079
|
-
"aria-hidden": "true",
|
|
2080
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M5 2.5h6M5 2.5v2L3.75 6v1h8.5V6L11 4.5v-2M8 7v6" })
|
|
2081
|
-
})
|
|
2082
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3060
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2083
3061
|
type: "button",
|
|
2084
3062
|
className: "dcu-wb-more",
|
|
2085
3063
|
"aria-label": t("sessions.archive"),
|
|
@@ -2087,8 +3065,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2087
3065
|
event.stopPropagation();
|
|
2088
3066
|
run("archive", () => archiveSession(id));
|
|
2089
3067
|
},
|
|
2090
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2091
|
-
})
|
|
3068
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickArchiveIcon, {})
|
|
3069
|
+
})
|
|
2092
3070
|
}),
|
|
2093
3071
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2094
3072
|
className: "dcu-wb-actions",
|
|
@@ -2097,15 +3075,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2097
3075
|
onClose: () => {
|
|
2098
3076
|
setMenu(void 0);
|
|
2099
3077
|
},
|
|
2100
|
-
items: sessionMenu(id,
|
|
3078
|
+
items: sessionMenu(id, path),
|
|
2101
3079
|
onSelect: (action) => {
|
|
2102
|
-
if (busy !== void 0) return;
|
|
2103
|
-
const link = sessionDeepLink(browserBase(), id);
|
|
3080
|
+
if (busy !== void 0 || runSessionMoveAction(action, id)) return;
|
|
2104
3081
|
if (action === "rename") beginRename("session", id, session.displayTitle);
|
|
2105
|
-
if (action === "pin") {
|
|
2106
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2107
|
-
setMenu(void 0);
|
|
2108
|
-
}
|
|
2109
3082
|
if (action === "unread") {
|
|
2110
3083
|
setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2111
3084
|
setMenu(void 0);
|
|
@@ -2125,7 +3098,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2125
3098
|
if (action === "copyPath") copy(path);
|
|
2126
3099
|
if (action === "copyTitle") copy(session.displayTitle);
|
|
2127
3100
|
if (action === "copyId") copy(id);
|
|
2128
|
-
if (action === "copyLink") copy(link);
|
|
2129
3101
|
},
|
|
2130
3102
|
portal: true,
|
|
2131
3103
|
dense: true,
|
|
@@ -2137,7 +3109,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2137
3109
|
"aria-label": t("sessions.actions", { name: session.displayTitle }),
|
|
2138
3110
|
onClick: (event) => {
|
|
2139
3111
|
event.stopPropagation();
|
|
2140
|
-
setMenu((current) => current?.id === id && current
|
|
3112
|
+
setMenu((current) => current?.id === id && current?.type === "session" ? void 0 : {
|
|
2141
3113
|
id,
|
|
2142
3114
|
type: "session"
|
|
2143
3115
|
});
|
|
@@ -2148,10 +3120,326 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2148
3120
|
})
|
|
2149
3121
|
]
|
|
2150
3122
|
}, id);
|
|
2151
|
-
})
|
|
2152
|
-
]
|
|
3123
|
+
})]
|
|
3124
|
+
})]
|
|
2153
3125
|
}, workspace.workspaceId);
|
|
2154
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);
|
|
2155
3443
|
if (!wide) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2156
3444
|
className: "dcu-wb dcu-wb-rail",
|
|
2157
3445
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$4 })
|
|
@@ -2163,7 +3451,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2163
3451
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("style", { children: [
|
|
2164
3452
|
stylesheet$4,
|
|
2165
3453
|
runningStyles,
|
|
2166
|
-
typographyStyles
|
|
3454
|
+
typographyStyles,
|
|
3455
|
+
collectionLayoutStyles
|
|
2167
3456
|
] }),
|
|
2168
3457
|
error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2169
3458
|
className: "dcu-wb-error",
|
|
@@ -2171,6 +3460,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2171
3460
|
children: t("sessions.failed", { message: error })
|
|
2172
3461
|
}),
|
|
2173
3462
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3463
|
+
ref: treeRef,
|
|
2174
3464
|
className: "dcu-wb-tree",
|
|
2175
3465
|
role: "tree",
|
|
2176
3466
|
children: [
|
|
@@ -2181,7 +3471,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2181
3471
|
if (!pinDragActive) return;
|
|
2182
3472
|
event.preventDefault();
|
|
2183
3473
|
event.dataTransfer.dropEffect = "move";
|
|
2184
|
-
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) {
|
|
2185
3475
|
const firstId = pinnedGroupIds[0];
|
|
2186
3476
|
const beforeId = firstId === void 0 ? void 0 : reorderDropBeforeId(pinnedGroupIds, workspaceDragId, firstId, false);
|
|
2187
3477
|
setWorkspaceDropTarget(beforeId === null ? void 0 : {
|
|
@@ -2232,46 +3522,53 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2232
3522
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2233
3523
|
className: "dcu-wb-section-body",
|
|
2234
3524
|
"data-open": sectionOpen("pinned"),
|
|
2235
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
event
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
event
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
beforeId
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
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
|
+
})
|
|
2270
3563
|
})]
|
|
2271
3564
|
}),
|
|
2272
3565
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2273
3566
|
className: "dcu-wb-section",
|
|
2274
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
|
+
},
|
|
2275
3572
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2276
3573
|
className: "dcu-wb-section-head",
|
|
2277
3574
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
@@ -2298,26 +3595,66 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2298
3595
|
})
|
|
2299
3596
|
})
|
|
2300
3597
|
})]
|
|
2301
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
3598
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2302
3599
|
className: "dcu-wb-actions",
|
|
2303
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3600
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2304
3601
|
type: "button",
|
|
2305
3602
|
className: "dcu-wb-more",
|
|
2306
|
-
"aria-label": t("workspace.
|
|
3603
|
+
"aria-label": t("workspace.createGroup"),
|
|
3604
|
+
title: t("workspace.createGroup"),
|
|
2307
3605
|
onClick: (event) => {
|
|
2308
3606
|
event.stopPropagation();
|
|
2309
|
-
|
|
3607
|
+
setGroupTitleDraft("");
|
|
3608
|
+
setError(void 0);
|
|
3609
|
+
setCreateGroupOpen(true);
|
|
2310
3610
|
},
|
|
2311
3611
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 16 })
|
|
2312
|
-
})
|
|
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
|
+
})]
|
|
2313
3642
|
})]
|
|
2314
3643
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2315
3644
|
className: "dcu-wb-section-body",
|
|
2316
3645
|
"data-open": sectionOpen("projects"),
|
|
2317
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2318
|
-
className: "dcu-wb-
|
|
2319
|
-
children:
|
|
2320
|
-
|
|
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
|
+
})
|
|
2321
3658
|
})]
|
|
2322
3659
|
}),
|
|
2323
3660
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
@@ -2360,34 +3697,27 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2360
3697
|
const session = sessions.byId[id];
|
|
2361
3698
|
if (session === void 0) return null;
|
|
2362
3699
|
const title = session.displayTitle;
|
|
2363
|
-
const pinned = pinnedSessionIds.includes(id);
|
|
2364
3700
|
const unread = unreadSessionIds.includes(id);
|
|
2365
|
-
const pendingInteraction =
|
|
3701
|
+
const pendingInteraction = pendingInteractionForSession(id, pendingInteractions, legacyPendingInteraction(session));
|
|
2366
3702
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
2367
3703
|
id,
|
|
2368
3704
|
title,
|
|
2369
3705
|
selected: sessions.current === id,
|
|
2370
3706
|
menuOpen: menu?.type === "session" && menu.id === id,
|
|
2371
|
-
pinned,
|
|
2372
3707
|
unread,
|
|
2373
3708
|
running: session.running === true,
|
|
2374
3709
|
pendingInteraction,
|
|
2375
3710
|
t,
|
|
2376
|
-
menuItems: sessionMenu(id,
|
|
3711
|
+
menuItems: sessionMenu(id, session.cwd),
|
|
2377
3712
|
draggable: true,
|
|
2378
3713
|
onDragStart: (event) => {
|
|
2379
3714
|
event.stopPropagation();
|
|
2380
3715
|
setWorkspaceDragId(void 0);
|
|
2381
3716
|
setWorkspaceDropTarget(void 0);
|
|
3717
|
+
setWorkspaceGroupDragId(void 0);
|
|
3718
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
2382
3719
|
writeSessionDrag(event.dataTransfer, id, title);
|
|
2383
|
-
|
|
2384
|
-
preview.className = "dcu-wb-drag-ghost";
|
|
2385
|
-
preview.textContent = title;
|
|
2386
|
-
document.body.appendChild(preview);
|
|
2387
|
-
event.dataTransfer.setDragImage(preview, 16, 18);
|
|
2388
|
-
window.requestAnimationFrame(() => {
|
|
2389
|
-
preview.remove();
|
|
2390
|
-
});
|
|
3720
|
+
setDragPreview(event.dataTransfer, title);
|
|
2391
3721
|
setSessionDrag({
|
|
2392
3722
|
sessionId: id,
|
|
2393
3723
|
workspaceId: ""
|
|
@@ -2397,6 +3727,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2397
3727
|
setSessionDrag(void 0);
|
|
2398
3728
|
setSessionDropTarget(void 0);
|
|
2399
3729
|
setWorkspaceDropTarget(void 0);
|
|
3730
|
+
setWorkspaceGroupDropTarget(void 0);
|
|
2400
3731
|
},
|
|
2401
3732
|
menuPoint: menu?.type === "session" && menu.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
2402
3733
|
x: menu.x,
|
|
@@ -2412,9 +3743,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2412
3743
|
type: "session"
|
|
2413
3744
|
} : void 0);
|
|
2414
3745
|
},
|
|
2415
|
-
onPin: () => {
|
|
2416
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2417
|
-
},
|
|
2418
3746
|
onArchive: () => {
|
|
2419
3747
|
run("archive", () => archiveSession(id));
|
|
2420
3748
|
},
|
|
@@ -2424,7 +3752,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2424
3752
|
kind: "session",
|
|
2425
3753
|
id,
|
|
2426
3754
|
title,
|
|
2427
|
-
time: formatHoverTime(session.updatedAt),
|
|
3755
|
+
time: formatHoverTime(session.updatedAt, t),
|
|
2428
3756
|
left: box.left,
|
|
2429
3757
|
top: box.top
|
|
2430
3758
|
});
|
|
@@ -2442,12 +3770,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2442
3770
|
});
|
|
2443
3771
|
},
|
|
2444
3772
|
onSelectAction: (action) => {
|
|
2445
|
-
if (busy !== void 0) return;
|
|
3773
|
+
if (busy !== void 0 || runSessionMoveAction(action, id)) return;
|
|
2446
3774
|
if (action === "rename") beginRename("session", id, title);
|
|
2447
|
-
if (action === "pin") {
|
|
2448
|
-
setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2449
|
-
setMenu(void 0);
|
|
2450
|
-
}
|
|
2451
3775
|
if (action === "unread") {
|
|
2452
3776
|
setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2453
3777
|
setMenu(void 0);
|
|
@@ -2467,7 +3791,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2467
3791
|
if (action === "copyPath") copy(session.cwd);
|
|
2468
3792
|
if (action === "copyTitle") copy(title);
|
|
2469
3793
|
if (action === "copyId") copy(id);
|
|
2470
|
-
if (action === "copyLink") copy(sessionDeepLink(browserBase(), id));
|
|
2471
3794
|
}
|
|
2472
3795
|
}, id);
|
|
2473
3796
|
})] })
|
|
@@ -2480,15 +3803,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2480
3803
|
onClose: () => {
|
|
2481
3804
|
setHeaderMenu(void 0);
|
|
2482
3805
|
},
|
|
2483
|
-
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),
|
|
2484
3807
|
onSelect: (action) => {
|
|
2485
3808
|
const id = headerMenu.id;
|
|
2486
3809
|
const session = sessions.byId[id];
|
|
2487
|
-
if (session === void 0 || busy !== void 0) return;
|
|
3810
|
+
if (session === void 0 || busy !== void 0 || runSessionMoveAction(action, id)) return;
|
|
2488
3811
|
const path = session.cwd ?? groups.items.find((item) => item.visibleIds.includes(id))?.path;
|
|
2489
|
-
const link = sessionDeepLink(browserBase(), id);
|
|
2490
3812
|
if (action === "rename") beginRename("session", id, session.displayTitle);
|
|
2491
|
-
if (action === "pin") setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2492
3813
|
if (action === "unread") setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2493
3814
|
if (action === "archive") run("archive", () => archiveSession(id));
|
|
2494
3815
|
if (action === "delete") {
|
|
@@ -2504,7 +3825,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2504
3825
|
if (action === "copyPath") copy(path);
|
|
2505
3826
|
if (action === "copyTitle") copy(session.displayTitle);
|
|
2506
3827
|
if (action === "copyId") copy(id);
|
|
2507
|
-
if (action === "copyLink") copy(link);
|
|
2508
3828
|
setHeaderMenu(void 0);
|
|
2509
3829
|
},
|
|
2510
3830
|
portal: true,
|
|
@@ -2519,8 +3839,89 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2519
3839
|
t,
|
|
2520
3840
|
onEditWorkspace: (id, title) => {
|
|
2521
3841
|
beginRename("workspace", id, title);
|
|
3842
|
+
},
|
|
3843
|
+
onToggleWorkspacePin: (id) => {
|
|
3844
|
+
setPinnedWorkspaceIds((ids) => togglePinnedWorkspace(ids, id));
|
|
2522
3845
|
}
|
|
2523
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
|
+
}),
|
|
2524
3925
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2525
3926
|
open: renameTarget !== void 0,
|
|
2526
3927
|
onClose: () => {
|
|
@@ -2566,6 +3967,98 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2566
3967
|
children: t("sessions.failed", { message: error })
|
|
2567
3968
|
})]
|
|
2568
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
|
+
}),
|
|
2569
4062
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
2570
4063
|
open: deleteTarget !== void 0,
|
|
2571
4064
|
onClose: () => {
|
|
@@ -2624,13 +4117,9 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2624
4117
|
function storage() {
|
|
2625
4118
|
return browserStorage();
|
|
2626
4119
|
}
|
|
2627
|
-
/**
|
|
4120
|
+
/** 频道/定时共用的本地未读标记。 */
|
|
2628
4121
|
function useSessionFlags(current) {
|
|
2629
|
-
const [pinnedSessionIds, setPinnedSessionIds] = (0, react.useState)(() => readSessionIds(storage(), SESSION_PINS_STORAGE_KEY));
|
|
2630
4122
|
const [unreadSessionIds, setUnreadSessionIds] = (0, react.useState)(() => readSessionIds(storage(), SESSION_UNREAD_STORAGE_KEY));
|
|
2631
|
-
(0, react.useEffect)(() => {
|
|
2632
|
-
writeSessionIds(storage(), SESSION_PINS_STORAGE_KEY, pinnedSessionIds);
|
|
2633
|
-
}, [pinnedSessionIds]);
|
|
2634
4123
|
(0, react.useEffect)(() => {
|
|
2635
4124
|
writeSessionIds(storage(), SESSION_UNREAD_STORAGE_KEY, unreadSessionIds);
|
|
2636
4125
|
}, [unreadSessionIds]);
|
|
@@ -2638,8 +4127,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2638
4127
|
if (current !== void 0) setUnreadSessionIds((ids) => ids.filter((id) => id !== current));
|
|
2639
4128
|
}, [current]);
|
|
2640
4129
|
return {
|
|
2641
|
-
pinnedSessionIds,
|
|
2642
|
-
setPinnedSessionIds,
|
|
2643
4130
|
unreadSessionIds,
|
|
2644
4131
|
setUnreadSessionIds
|
|
2645
4132
|
};
|
|
@@ -2654,7 +4141,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2654
4141
|
onLeave: hideTip
|
|
2655
4142
|
});
|
|
2656
4143
|
}
|
|
2657
|
-
function useBusyAction(onSuccess) {
|
|
4144
|
+
function useBusyAction(t, onSuccess) {
|
|
2658
4145
|
const [busy, setBusy] = (0, react.useState)();
|
|
2659
4146
|
const [error, setError] = (0, react.useState)();
|
|
2660
4147
|
const busyRef = (0, react.useRef)();
|
|
@@ -2667,7 +4154,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2667
4154
|
await action();
|
|
2668
4155
|
onSuccess?.();
|
|
2669
4156
|
} catch (reason) {
|
|
2670
|
-
setError(reason
|
|
4157
|
+
setError(userErrorText(reason, t));
|
|
2671
4158
|
} finally {
|
|
2672
4159
|
busyRef.current = void 0;
|
|
2673
4160
|
setBusy(void 0);
|
|
@@ -2697,7 +4184,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2697
4184
|
const target = deleteTarget;
|
|
2698
4185
|
run("delete", async () => {
|
|
2699
4186
|
await actions.deleteSession(target.id);
|
|
2700
|
-
flags.setPinnedSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
2701
4187
|
flags.setUnreadSessionIds((ids) => ids.filter((id) => id !== target.id));
|
|
2702
4188
|
setDeleteTarget(void 0);
|
|
2703
4189
|
});
|
|
@@ -2711,10 +4197,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2711
4197
|
setRenameDraft(title);
|
|
2712
4198
|
closeMenu();
|
|
2713
4199
|
}
|
|
2714
|
-
if (action === "pin") {
|
|
2715
|
-
flags.setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2716
|
-
closeMenu();
|
|
2717
|
-
}
|
|
2718
4200
|
if (action === "unread") {
|
|
2719
4201
|
flags.setUnreadSessionIds((ids) => toggleSessionId(ids, id));
|
|
2720
4202
|
closeMenu();
|
|
@@ -2734,9 +4216,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2734
4216
|
if (action === "copyId") run("copy", async () => {
|
|
2735
4217
|
await (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(id);
|
|
2736
4218
|
});
|
|
2737
|
-
if (action === "copyLink") run("copy", async () => {
|
|
2738
|
-
await (0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(copySessionLink(id));
|
|
2739
|
-
});
|
|
2740
4219
|
};
|
|
2741
4220
|
return {
|
|
2742
4221
|
renameTarget,
|
|
@@ -2869,14 +4348,16 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2869
4348
|
})
|
|
2870
4349
|
});
|
|
2871
4350
|
}
|
|
2872
|
-
function ChannelBrowserTree({ openSession, archiveSession, deleteSession, forkSession, renameSession, useSessions, t, menu, setMenu }) {
|
|
4351
|
+
function ChannelBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useWorkspaces, t, menu, setMenu }) {
|
|
2873
4352
|
const sessions = useSessions((state) => state);
|
|
4353
|
+
const workspaces = useWorkspaces?.((state) => state);
|
|
4354
|
+
const pendingInteractions = (useSessionPendingInteraction ?? useEmptySessionPendingInteraction)((state) => state);
|
|
2874
4355
|
const [groups, setGroups] = (0, react.useState)([]);
|
|
2875
4356
|
const [pollError, setPollError] = (0, react.useState)();
|
|
2876
4357
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(browserStorage(), CHANNEL_EXPANSION_STORAGE_KEY));
|
|
2877
4358
|
const flags = useSessionFlags(sessions.current);
|
|
2878
4359
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
2879
|
-
const { busy, error, setError, run } = useBusyAction(() => {
|
|
4360
|
+
const { busy, error, setError, run } = useBusyAction(t, () => {
|
|
2880
4361
|
setMenu(void 0);
|
|
2881
4362
|
});
|
|
2882
4363
|
const dialogs = useSessionDialogs({
|
|
@@ -2901,7 +4382,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2901
4382
|
const timeout = window.setTimeout(() => {
|
|
2902
4383
|
controller.abort();
|
|
2903
4384
|
}, 8e3);
|
|
2904
|
-
loadChannelGroups(controller.signal).then((next) => {
|
|
4385
|
+
loadChannelGroups(controller.signal, t("channel.unknown")).then((next) => {
|
|
2905
4386
|
if (!disposed) {
|
|
2906
4387
|
setGroups(next);
|
|
2907
4388
|
setPollError(void 0);
|
|
@@ -2966,22 +4447,24 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2966
4447
|
const selected = sessions.current === id;
|
|
2967
4448
|
const running = session.running || sessions.byId[id]?.running === true;
|
|
2968
4449
|
const updatedAt = session.updatedAt ?? sessions.byId[id]?.updatedAt;
|
|
2969
|
-
const pinned = flags.pinnedSessionIds.includes(id);
|
|
2970
4450
|
const unread = flags.unreadSessionIds.includes(id);
|
|
2971
|
-
const pendingInteraction =
|
|
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
|
+
}));
|
|
2972
4456
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
2973
4457
|
id,
|
|
2974
4458
|
title,
|
|
2975
4459
|
selected,
|
|
2976
4460
|
menuOpen: menu?.id === id,
|
|
2977
|
-
pinned,
|
|
2978
4461
|
unread,
|
|
2979
4462
|
running,
|
|
2980
4463
|
pendingInteraction,
|
|
2981
4464
|
t,
|
|
2982
4465
|
menuItems: sessionMenuItems(t, {
|
|
2983
|
-
|
|
2984
|
-
|
|
4466
|
+
unread,
|
|
4467
|
+
moveTargets
|
|
2985
4468
|
}),
|
|
2986
4469
|
menuPoint: menu?.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
2987
4470
|
x: menu.x,
|
|
@@ -2994,9 +4477,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
2994
4477
|
onMenuChange: (open) => {
|
|
2995
4478
|
setMenu(open ? { id } : void 0);
|
|
2996
4479
|
},
|
|
2997
|
-
onPin: () => {
|
|
2998
|
-
flags.setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
2999
|
-
},
|
|
3000
4480
|
onArchive: () => {
|
|
3001
4481
|
run("archive", () => archiveSession(id));
|
|
3002
4482
|
},
|
|
@@ -3005,7 +4485,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3005
4485
|
showTip({
|
|
3006
4486
|
title,
|
|
3007
4487
|
project: label,
|
|
3008
|
-
time: updatedAt === void 0 ? void 0 : formatHoverTime(updatedAt),
|
|
4488
|
+
time: updatedAt === void 0 ? void 0 : formatHoverTime(updatedAt, t),
|
|
3009
4489
|
left: box.left,
|
|
3010
4490
|
top: box.top
|
|
3011
4491
|
});
|
|
@@ -3022,7 +4502,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3022
4502
|
});
|
|
3023
4503
|
},
|
|
3024
4504
|
onSelectAction: (action) => {
|
|
3025
|
-
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);
|
|
3026
4513
|
}
|
|
3027
4514
|
}, id);
|
|
3028
4515
|
})]
|
|
@@ -3125,15 +4612,16 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3125
4612
|
})]
|
|
3126
4613
|
});
|
|
3127
4614
|
}
|
|
3128
|
-
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, renameSession, useSessions, useWorkspaces, t, openTaskSettings, menu, setMenu }) {
|
|
4615
|
+
function ScheduleBrowserTree({ openSession, archiveSession, deleteSession, forkSession, moveSession, renameSession, useSessions, useSessionPendingInteraction, useWorkspaces, t, openTaskSettings, menu, setMenu }) {
|
|
3129
4616
|
const sessions = useSessions((state) => state);
|
|
4617
|
+
const pendingInteractions = (useSessionPendingInteraction ?? useEmptySessionPendingInteraction)((state) => state);
|
|
3130
4618
|
const workspaces = useWorkspaces((state) => state);
|
|
3131
4619
|
const [expanded, setExpanded] = (0, react.useState)(() => readTreeExpansionState(browserStorage(), SCHEDULE_EXPANSION_STORAGE_KEY));
|
|
3132
4620
|
const [groupMenu, setGroupMenu] = (0, react.useState)();
|
|
3133
4621
|
const [archiveGroupTarget, setArchiveGroupTarget] = (0, react.useState)();
|
|
3134
4622
|
const flags = useSessionFlags(sessions.current);
|
|
3135
4623
|
const { showTip, hideTip, dismissTip } = useHoverDispatch();
|
|
3136
|
-
const { busy, error, setError, run } = useBusyAction(() => {
|
|
4624
|
+
const { busy, error, setError, run } = useBusyAction(t, () => {
|
|
3137
4625
|
setMenu(void 0);
|
|
3138
4626
|
});
|
|
3139
4627
|
const dialogs = useSessionDialogs({
|
|
@@ -3176,10 +4664,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3176
4664
|
updatedAt: session.updatedAt,
|
|
3177
4665
|
running: session.running === true
|
|
3178
4666
|
}];
|
|
3179
|
-
}));
|
|
4667
|
+
}), t("meta.locale"));
|
|
3180
4668
|
}, [
|
|
3181
4669
|
sessions.byId,
|
|
3182
4670
|
sessions.ids,
|
|
4671
|
+
t,
|
|
3183
4672
|
workspaces.archivedSessionIds
|
|
3184
4673
|
]);
|
|
3185
4674
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
@@ -3257,22 +4746,24 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3257
4746
|
}), isExpanded && group.sessions.map((session) => {
|
|
3258
4747
|
const id = session.id;
|
|
3259
4748
|
const title = session.title;
|
|
3260
|
-
const pinned = flags.pinnedSessionIds.includes(id);
|
|
3261
4749
|
const unread = flags.unreadSessionIds.includes(id);
|
|
3262
|
-
const pendingInteraction =
|
|
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
|
+
}));
|
|
3263
4755
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
|
|
3264
4756
|
id,
|
|
3265
4757
|
title,
|
|
3266
4758
|
selected: sessions.current === id,
|
|
3267
4759
|
menuOpen: menu?.id === id,
|
|
3268
|
-
pinned,
|
|
3269
4760
|
unread,
|
|
3270
4761
|
running: session.running,
|
|
3271
4762
|
pendingInteraction,
|
|
3272
4763
|
t,
|
|
3273
4764
|
menuItems: sessionMenuItems(t, {
|
|
3274
|
-
|
|
3275
|
-
|
|
4765
|
+
unread,
|
|
4766
|
+
moveTargets
|
|
3276
4767
|
}),
|
|
3277
4768
|
menuPoint: menu?.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
|
|
3278
4769
|
x: menu.x,
|
|
@@ -3285,9 +4776,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3285
4776
|
onMenuChange: (open) => {
|
|
3286
4777
|
setMenu(open ? { id } : void 0);
|
|
3287
4778
|
},
|
|
3288
|
-
onPin: () => {
|
|
3289
|
-
flags.setPinnedSessionIds((ids) => toggleSessionId(ids, id));
|
|
3290
|
-
},
|
|
3291
4779
|
onArchive: () => {
|
|
3292
4780
|
run("archive", () => archiveSession(id));
|
|
3293
4781
|
},
|
|
@@ -3296,7 +4784,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3296
4784
|
showTip({
|
|
3297
4785
|
title,
|
|
3298
4786
|
project: group.label,
|
|
3299
|
-
time: session.updatedAt === void 0 ? void 0 : formatHoverTime(session.updatedAt),
|
|
4787
|
+
time: session.updatedAt === void 0 ? void 0 : formatHoverTime(session.updatedAt, t),
|
|
3300
4788
|
left: box.left,
|
|
3301
4789
|
top: box.top
|
|
3302
4790
|
});
|
|
@@ -3313,7 +4801,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3313
4801
|
});
|
|
3314
4802
|
},
|
|
3315
4803
|
onSelectAction: (action) => {
|
|
3316
|
-
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);
|
|
3317
4812
|
}
|
|
3318
4813
|
}, id);
|
|
3319
4814
|
})]
|
|
@@ -3358,14 +4853,13 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3358
4853
|
const target = archiveGroupTarget;
|
|
3359
4854
|
run("archive-group", async () => {
|
|
3360
4855
|
const result = await archiveScheduleGroup(target.sessionIds, (id) => archiveSession(id));
|
|
3361
|
-
flags.setPinnedSessionIds((ids) => ids.filter((id) => !result.archivedIds.includes(id)));
|
|
3362
4856
|
flags.setUnreadSessionIds((ids) => ids.filter((id) => !result.archivedIds.includes(id)));
|
|
3363
4857
|
if (result.failedIds.length > 0) {
|
|
3364
4858
|
setArchiveGroupTarget({
|
|
3365
4859
|
...target,
|
|
3366
4860
|
sessionIds: result.failedIds
|
|
3367
4861
|
});
|
|
3368
|
-
throw new
|
|
4862
|
+
throw new UserFacingError(t("schedule.archiveGroupPartial", {
|
|
3369
4863
|
archived: result.archivedIds.length,
|
|
3370
4864
|
failed: result.failedIds.length
|
|
3371
4865
|
}));
|
|
@@ -3399,9 +4893,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3399
4893
|
]
|
|
3400
4894
|
});
|
|
3401
4895
|
}
|
|
4896
|
+
const visibleSidebarWidths = /* @__PURE__ */ new WeakMap();
|
|
3402
4897
|
/** 解析宿主 AppFrame 的 grid-template-columns。 */
|
|
3403
4898
|
function parseSidebarGrid(value) {
|
|
3404
|
-
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());
|
|
3405
4900
|
if (match === null) return void 0;
|
|
3406
4901
|
return {
|
|
3407
4902
|
sidebar: Number(match[1]),
|
|
@@ -3409,41 +4904,41 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3409
4904
|
details: Number(match[3])
|
|
3410
4905
|
};
|
|
3411
4906
|
}
|
|
3412
|
-
/**
|
|
3413
|
-
* Translate the DSH host's 264–420px drag range to Codex's measured
|
|
3414
|
-
* 240–520px range, preserving the 280px-host / 275px-Codex default anchor.
|
|
3415
|
-
*/
|
|
3416
|
-
function slimedSidebarWidth(hostWidth, collapsed, viewportWidth = Number.POSITIVE_INFINITY) {
|
|
3417
|
-
if (collapsed || hostWidth <= 80) return hostWidth;
|
|
3418
|
-
const maximum = Math.max(240, Math.min(520, viewportWidth - 240));
|
|
3419
|
-
const source = Math.max(264, Math.min(420, hostWidth));
|
|
3420
|
-
if (source <= 280) return 240 + (source - 264) * 35 / 16;
|
|
3421
|
-
return 275 + (source - 280) * (maximum - 275) / 140;
|
|
3422
|
-
}
|
|
3423
|
-
function slimedGridTemplate(tracks, collapsed, viewportWidth = Number.POSITIVE_INFINITY) {
|
|
3424
|
-
return `${slimedSidebarWidth(tracks.sidebar, collapsed, viewportWidth)}px ${tracks.middle} ${tracks.details}px`;
|
|
3425
|
-
}
|
|
3426
4907
|
function findSidebarFrame(root) {
|
|
3427
4908
|
const marked = root.querySelector("[data-sidebar-collapsed]");
|
|
3428
4909
|
if (marked !== null) return marked;
|
|
3429
4910
|
for (const node of root.querySelectorAll("div")) if (parseSidebarGrid(node.style.gridTemplateColumns) !== void 0) return node;
|
|
3430
4911
|
}
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
frame.removeAttribute("data-dcu-codex-sidebar-grid");
|
|
3434
|
-
return false;
|
|
3435
|
-
}
|
|
4912
|
+
/** 同步侧栏网格和拖拽柄,保证两者始终使用同一个可见宽度。 */
|
|
4913
|
+
function applySidebarWidth(frame, width) {
|
|
3436
4914
|
const tracks = parseSidebarGrid(frame.style.gridTemplateColumns);
|
|
3437
|
-
if (tracks === void 0) return false;
|
|
3438
|
-
|
|
3439
|
-
const next =
|
|
3440
|
-
|
|
3441
|
-
if (frame.style.gridTemplateColumns
|
|
3442
|
-
frame.style.gridTemplateColumns = next;
|
|
3443
|
-
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;
|
|
3444
4920
|
const handle = frame.querySelector("[data-side=\"sidebar\"]");
|
|
3445
|
-
if (handle !== null
|
|
3446
|
-
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
|
+
};
|
|
3447
4942
|
}
|
|
3448
4943
|
function observeSlimSidebar() {
|
|
3449
4944
|
if (typeof document === "undefined" || document.body === null) return () => {};
|
|
@@ -3462,7 +4957,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3462
4957
|
attributeFilter: [
|
|
3463
4958
|
"style",
|
|
3464
4959
|
"data-sidebar-collapsed",
|
|
3465
|
-
"data-dragging"
|
|
4960
|
+
"data-dragging",
|
|
4961
|
+
"data-dcu-codex-sidebar-initialized"
|
|
3466
4962
|
]
|
|
3467
4963
|
});
|
|
3468
4964
|
};
|
|
@@ -3471,7 +4967,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3471
4967
|
applying = true;
|
|
3472
4968
|
try {
|
|
3473
4969
|
if (frame === void 0 || !frame.isConnected) watchFrame(findSidebarFrame(document));
|
|
3474
|
-
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
|
+
}
|
|
3475
4978
|
} finally {
|
|
3476
4979
|
applying = false;
|
|
3477
4980
|
}
|
|
@@ -3499,9 +5002,14 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3499
5002
|
}
|
|
3500
5003
|
//#endregion
|
|
3501
5004
|
//#region src/client/sidebar-drag.ts
|
|
3502
|
-
|
|
5005
|
+
const SIDEBAR_MAX_PX = 420;
|
|
5006
|
+
/** 左移超过开始宽度的一半时收起侧栏,避免轻微拖动误触。 */
|
|
3503
5007
|
function shouldCollapseOnSidebarDrag(startWidth, startX, endX) {
|
|
3504
|
-
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));
|
|
3505
5013
|
}
|
|
3506
5014
|
function isSidebarDragHandle(target) {
|
|
3507
5015
|
if (target === null || typeof target !== "object" || !("closest" in target)) return false;
|
|
@@ -3544,20 +5052,34 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
|
|
|
3544
5052
|
const subscribeEmptyCompanionTabs = () => () => {};
|
|
3545
5053
|
const getEmptyCompanionTabs = () => EMPTY_COMPANION_TABS;
|
|
3546
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
|
+
}
|
|
3547
5068
|
const stylesheet$3 = `
|
|
3548
|
-
.dcu-root{--dcu-font:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei UI",sans-serif;--dcu-sidebar-
|
|
3549
|
-
.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}}
|
|
3550
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}
|
|
3551
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}
|
|
3552
5073
|
.dcu-icon:hover,.dcu-menu button:hover:not(:disabled),.dcu-footer-link:hover{background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary)}
|
|
3553
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}
|
|
3554
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)}
|
|
3555
|
-
.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}
|
|
3556
|
-
.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%}
|
|
3557
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}
|
|
3558
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}
|
|
3559
5081
|
[role="dialog"][aria-labelledby]{width:min(1000px,calc(100vw - 48px));max-width:calc(100vw - 48px);height:min(800px,calc(100vh - 48px))}
|
|
3560
|
-
.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}}
|
|
3561
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}}
|
|
3562
5084
|
html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:has([data-dcu-official-turn-navigator]) .dcu-turn-navigator{display:none}
|
|
3563
5085
|
[data-dcu-official-turn-navigator]{right:auto!important;left:calc(12px - (var(--dsh-composer-side-clearance) + 16px))!important}
|
|
@@ -3873,12 +5395,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
3873
5395
|
});
|
|
3874
5396
|
});
|
|
3875
5397
|
/** Codex 风格的 DSH 侧栏,只替换导航外观,项目浏览和设置仍由 DSH 官方组件提供。 */
|
|
3876
|
-
function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useWorkspaces }) {
|
|
5398
|
+
function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, moveSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useSessionPendingInteraction, useWorkspaces }) {
|
|
3877
5399
|
const compact = collapsed || width < 80;
|
|
3878
5400
|
const [visualCompact, setVisualCompact] = (0, react.useState)(compact);
|
|
3879
5401
|
const [collapsing, setCollapsing] = (0, react.useState)(false);
|
|
3880
|
-
const lastWideWidth = (0, react.useRef)(width >= 80 ? width : 275);
|
|
3881
|
-
if (!compact) lastWideWidth.current = width;
|
|
3882
5402
|
const settingsSeat = (0, react.useRef)(null);
|
|
3883
5403
|
const search = (0, react.useRef)(null);
|
|
3884
5404
|
const toggleSidebarRef = (0, react.useRef)(toggleSidebar);
|
|
@@ -3886,7 +5406,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
3886
5406
|
const expandSidebar = (0, react.useCallback)(() => {
|
|
3887
5407
|
toggleSidebarRef.current();
|
|
3888
5408
|
}, []);
|
|
3889
|
-
const [extensionsOpen, setExtensionsOpen] = (0, react.useState)(
|
|
5409
|
+
const [extensionsOpen, setExtensionsOpen] = (0, react.useState)(readExtensionsOpen);
|
|
3890
5410
|
const [imTab, setImTab] = (0, react.useState)("tasks");
|
|
3891
5411
|
const companionTabs = (0, react.useSyncExternalStore)(companionSlots?.subscribe ?? subscribeEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs, companionSlots?.getSnapshot ?? getEmptyCompanionTabs);
|
|
3892
5412
|
const showChannels = companionTabs.channels;
|
|
@@ -3920,42 +5440,77 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
3920
5440
|
]);
|
|
3921
5441
|
(0, react.useEffect)(() => {
|
|
3922
5442
|
let startX = 0;
|
|
3923
|
-
let startWidth =
|
|
5443
|
+
let startWidth = 240;
|
|
3924
5444
|
let dragging = false;
|
|
3925
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
|
+
};
|
|
3926
5461
|
const onDown = (event) => {
|
|
3927
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);
|
|
3928
5468
|
dragging = true;
|
|
3929
5469
|
pointerId = event.pointerId;
|
|
3930
5470
|
startX = event.clientX;
|
|
3931
|
-
|
|
3932
|
-
|
|
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));
|
|
3933
5484
|
};
|
|
3934
5485
|
const onUp = (event) => {
|
|
3935
5486
|
if (!dragging || event.pointerId !== pointerId) return;
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
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(() => {
|
|
3940
5492
|
window.requestAnimationFrame(() => {
|
|
3941
|
-
|
|
5493
|
+
toggleSidebarRef.current();
|
|
3942
5494
|
});
|
|
3943
5495
|
});
|
|
3944
5496
|
};
|
|
3945
5497
|
const onCancel = (event) => {
|
|
3946
5498
|
if (event.pointerId !== pointerId) return;
|
|
3947
|
-
|
|
3948
|
-
|
|
5499
|
+
stopHostDrag(event);
|
|
5500
|
+
finishDrag();
|
|
3949
5501
|
};
|
|
3950
5502
|
window.addEventListener("pointerdown", onDown, true);
|
|
5503
|
+
window.addEventListener("pointermove", onMove, true);
|
|
3951
5504
|
window.addEventListener("pointerup", onUp, true);
|
|
3952
5505
|
window.addEventListener("pointercancel", onCancel, true);
|
|
3953
5506
|
return () => {
|
|
5507
|
+
finishDrag();
|
|
3954
5508
|
window.removeEventListener("pointerdown", onDown, true);
|
|
5509
|
+
window.removeEventListener("pointermove", onMove, true);
|
|
3955
5510
|
window.removeEventListener("pointerup", onUp, true);
|
|
3956
5511
|
window.removeEventListener("pointercancel", onCancel, true);
|
|
3957
5512
|
};
|
|
3958
|
-
}, [
|
|
5513
|
+
}, []);
|
|
3959
5514
|
(0, react.useLayoutEffect)(() => {
|
|
3960
5515
|
if (!compact) {
|
|
3961
5516
|
setCollapsing(false);
|
|
@@ -3991,6 +5546,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
3991
5546
|
archiveSession,
|
|
3992
5547
|
deleteSession,
|
|
3993
5548
|
forkSession,
|
|
5549
|
+
moveSession,
|
|
3994
5550
|
renameSession,
|
|
3995
5551
|
openPath,
|
|
3996
5552
|
useSessions,
|
|
@@ -4003,6 +5559,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4003
5559
|
deleteSession,
|
|
4004
5560
|
expandSidebar,
|
|
4005
5561
|
forkSession,
|
|
5562
|
+
moveSession,
|
|
4006
5563
|
openPath,
|
|
4007
5564
|
openSession,
|
|
4008
5565
|
renameSession,
|
|
@@ -4010,10 +5567,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4010
5567
|
useSessions,
|
|
4011
5568
|
useWorkspaces
|
|
4012
5569
|
]);
|
|
4013
|
-
const sidebarStyle = { "--dcu-sidebar-wide-width": `${slimedSidebarWidth(lastWideWidth.current, false, window.innerWidth)}px` };
|
|
4014
5570
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
4015
5571
|
className: `dcu-root${visualCompact ? " dcu-compact" : ""}${collapsing ? " dcu-collapsing" : ""}`,
|
|
4016
|
-
style: sidebarStyle,
|
|
4017
5572
|
"aria-label": t("sidebar.label"),
|
|
4018
5573
|
children: [
|
|
4019
5574
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$3 }),
|
|
@@ -4060,46 +5615,73 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4060
5615
|
},
|
|
4061
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")]
|
|
4062
5617
|
}),
|
|
4063
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("
|
|
4064
|
-
|
|
4065
|
-
"
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
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
|
+
})
|
|
4101
5683
|
})
|
|
4102
|
-
]
|
|
5684
|
+
})]
|
|
4103
5685
|
}),
|
|
4104
5686
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4105
5687
|
type: "button",
|
|
@@ -4155,8 +5737,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4155
5737
|
archiveSession,
|
|
4156
5738
|
deleteSession,
|
|
4157
5739
|
forkSession,
|
|
5740
|
+
moveSession,
|
|
4158
5741
|
renameSession,
|
|
4159
5742
|
useSessions,
|
|
5743
|
+
useSessionPendingInteraction,
|
|
5744
|
+
useWorkspaces,
|
|
4160
5745
|
t
|
|
4161
5746
|
})
|
|
4162
5747
|
}) : imTab === "schedule" && showSchedule ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -4166,8 +5751,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4166
5751
|
archiveSession,
|
|
4167
5752
|
deleteSession,
|
|
4168
5753
|
forkSession,
|
|
5754
|
+
moveSession,
|
|
4169
5755
|
renameSession,
|
|
4170
5756
|
useSessions,
|
|
5757
|
+
useSessionPendingInteraction,
|
|
4171
5758
|
useWorkspaces,
|
|
4172
5759
|
t,
|
|
4173
5760
|
overviewContent: scheduleOverviewSlot,
|
|
@@ -4344,7 +5931,22 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4344
5931
|
const endpoint = "/api/michengai/codex-ui/dependencies";
|
|
4345
5932
|
const stylesheet$2 = `
|
|
4346
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}}
|
|
4347
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
|
+
}
|
|
4348
5950
|
function isDependencyStatus(value) {
|
|
4349
5951
|
if (value === null || typeof value !== "object") return false;
|
|
4350
5952
|
const status = value;
|
|
@@ -4359,11 +5961,6 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4359
5961
|
const currentPackage = progress.currentPackage;
|
|
4360
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");
|
|
4361
5963
|
}
|
|
4362
|
-
function installErrorText(error, t) {
|
|
4363
|
-
const message = error instanceof Error ? error.message : "";
|
|
4364
|
-
if (message.includes("没有进入当前 Profile") || message.includes("did not enter this profile")) return t("about.installUnchanged");
|
|
4365
|
-
return message !== "" ? message : t("about.installFailed");
|
|
4366
|
-
}
|
|
4367
5964
|
function progressLabel(progress, t) {
|
|
4368
5965
|
if (progress.phase !== null) {
|
|
4369
5966
|
const current = progress.currentPackage === null || progress.currentPackage === "" ? "" : ` · ${progress.currentPackage}`;
|
|
@@ -4525,7 +6122,27 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4525
6122
|
"aria-label": t("about.nav"),
|
|
4526
6123
|
children: [
|
|
4527
6124
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$2 }),
|
|
4528
|
-
/* @__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
|
+
}),
|
|
4529
6146
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4530
6147
|
className: "dcu-about-intro",
|
|
4531
6148
|
children: t("about.description")
|
|
@@ -4666,7 +6283,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4666
6283
|
}
|
|
4667
6284
|
style.textContent = document.body.hasAttribute("data-ds-dark-theme") ? frameDarkTheme : frameLightTheme;
|
|
4668
6285
|
}
|
|
4669
|
-
function ConnectorMarket({ startPromptSession }) {
|
|
6286
|
+
function ConnectorMarket({ startPromptSession, t }) {
|
|
4670
6287
|
const frameRef = (0, react.useRef)(null);
|
|
4671
6288
|
(0, react.useEffect)(() => {
|
|
4672
6289
|
const onMessage = (event) => {
|
|
@@ -4683,9 +6300,9 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4683
6300
|
}, window.location.origin);
|
|
4684
6301
|
};
|
|
4685
6302
|
startPromptSession(prompt).then(() => {
|
|
4686
|
-
reply(true, "
|
|
6303
|
+
reply(true, t("connectors.promptReady"));
|
|
4687
6304
|
}, (error) => {
|
|
4688
|
-
reply(false, error
|
|
6305
|
+
reply(false, userErrorText(error, t));
|
|
4689
6306
|
});
|
|
4690
6307
|
};
|
|
4691
6308
|
const syncTheme = () => {
|
|
@@ -4701,12 +6318,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4701
6318
|
observer.disconnect();
|
|
4702
6319
|
window.removeEventListener("message", onMessage);
|
|
4703
6320
|
};
|
|
4704
|
-
}, [startPromptSession]);
|
|
6321
|
+
}, [startPromptSession, t]);
|
|
4705
6322
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
|
|
4706
6323
|
ref: frameRef,
|
|
4707
6324
|
className: "dcu-connector-frame",
|
|
4708
6325
|
src: MCP_CONNECTOR_UI,
|
|
4709
|
-
title: "
|
|
6326
|
+
title: t("connectors.title"),
|
|
4710
6327
|
onLoad: () => {
|
|
4711
6328
|
syncFrameTheme(frameRef.current);
|
|
4712
6329
|
}
|
|
@@ -4798,7 +6415,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4798
6415
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$1 }), marketAvailable === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4799
6416
|
className: "dcu-connector-empty",
|
|
4800
6417
|
children: t("connectors.loading")
|
|
4801
|
-
}) : 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: [
|
|
4802
6422
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("connectors.title") }),
|
|
4803
6423
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("connectors.description") }),
|
|
4804
6424
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NativeConnectorList, {
|
|
@@ -4842,6 +6462,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4842
6462
|
"channel.wecom": "企业微信",
|
|
4843
6463
|
"channel.qq": "QQ",
|
|
4844
6464
|
"channel.telegram": "Telegram",
|
|
6465
|
+
"channel.unknown": "频道",
|
|
4845
6466
|
"schedule.empty": "还没有定时任务运行记录。",
|
|
4846
6467
|
"schedule.groupActions": "{name} 的任务操作",
|
|
4847
6468
|
"schedule.taskSettings": "任务设置",
|
|
@@ -4859,30 +6480,43 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4859
6480
|
"workspace.pinned": "置顶",
|
|
4860
6481
|
"workspace.pinnedEmpty": "拖动项目到此处置顶",
|
|
4861
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": "管理分组",
|
|
4862
6493
|
"workspace.recent": "最近",
|
|
4863
6494
|
"workspace.recentEmpty": "无聊天",
|
|
4864
6495
|
"workspace.noChat": "没有聊天",
|
|
4865
|
-
"workspace.empty": "
|
|
6496
|
+
"workspace.empty": "暂无项目",
|
|
4866
6497
|
"workspace.newSession": "新建会话",
|
|
4867
|
-
"workspace.rename": "
|
|
6498
|
+
"workspace.rename": "重命名项目",
|
|
4868
6499
|
"workspace.pin": "置顶项目",
|
|
4869
6500
|
"workspace.unpin": "取消置顶",
|
|
6501
|
+
"workspace.archive": "归档所有会话",
|
|
6502
|
+
"workspace.archiveTitle": "归档 {count} 个会话?",
|
|
6503
|
+
"workspace.archiveDescription": "这会归档“{name}”中的全部会话,项目和文件夹仍会保留。",
|
|
6504
|
+
"workspace.archiveConfirm": "全部归档",
|
|
6505
|
+
"workspace.archivePending": "正在归档会话…",
|
|
4870
6506
|
"workspace.openPath": "在资源管理器中打开",
|
|
4871
|
-
"workspace.delete": "
|
|
6507
|
+
"workspace.delete": "移除项目",
|
|
4872
6508
|
"workspace.deleteDescription": "将把“{name}”从项目列表中移除。文件夹和会话记录会保留。",
|
|
4873
|
-
"workspace.deletePending": "
|
|
6509
|
+
"workspace.deletePending": "正在移除项目…",
|
|
4874
6510
|
"workspace.actions": "{name} 的项目操作",
|
|
4875
6511
|
"workspace.taskCount": "{count} 个任务",
|
|
4876
|
-
"workspace.
|
|
6512
|
+
"workspace.taskSummary": "{count} 个任务 · {unreadCount} 条未读",
|
|
6513
|
+
"workspace.edit": "重命名项目",
|
|
4877
6514
|
"sessions.close": "关闭",
|
|
4878
6515
|
"sessions.cancel": "取消",
|
|
4879
6516
|
"sessions.save": "保存",
|
|
4880
6517
|
"sessions.failed": "操作失败:{message}",
|
|
4881
6518
|
"sessions.unknown": "找不到该会话。",
|
|
4882
6519
|
"sessions.actions": "{name} 的会话操作",
|
|
4883
|
-
"sessions.pin": "置顶会话",
|
|
4884
|
-
"sessions.unpin": "取消置顶",
|
|
4885
|
-
"sessions.pinned": "已置顶",
|
|
4886
6520
|
"sessions.markUnread": "标记为未读",
|
|
4887
6521
|
"sessions.markRead": "标记为已读",
|
|
4888
6522
|
"sessions.unread": "未读",
|
|
@@ -4891,17 +6525,33 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4891
6525
|
"sessions.planReview": "计划待审",
|
|
4892
6526
|
"sessions.rename": "重命名会话",
|
|
4893
6527
|
"sessions.renameDescription": "保持简短且易于识别",
|
|
6528
|
+
"sessions.renameInvalid": "会话名称无效,请修改后重试。",
|
|
6529
|
+
"sessions.renameFailed": "暂时无法重命名该会话,请稍后重试。",
|
|
4894
6530
|
"sessions.archive": "归档会话",
|
|
6531
|
+
"sessions.archiveFailed": "暂时无法归档该会话,请稍后重试。",
|
|
4895
6532
|
"sessions.delete": "删除会话",
|
|
4896
6533
|
"sessions.deleteDescription": "将永久删除会话“{name}”及其全部记录,此操作不可恢复。",
|
|
4897
6534
|
"sessions.deletePending": "正在删除会话…",
|
|
4898
6535
|
"sessions.deleteUnavailable": "未安装或无法连接归档管理插件。",
|
|
6536
|
+
"sessions.deleteFailed": "暂时无法删除该会话,请稍后重试。",
|
|
4899
6537
|
"sessions.fork": "在新会话中继续",
|
|
6538
|
+
"sessions.forkUnavailable": "当前会话暂时无法在新会话中继续,请等待本轮结束后重试。",
|
|
6539
|
+
"sessions.forkFailed": "暂时无法创建新会话,请稍后重试。",
|
|
4900
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": "正在移动会话…",
|
|
4901
6552
|
"sessions.copyPath": "复制工作目录",
|
|
4902
6553
|
"sessions.copyTitle": "复制会话标题",
|
|
4903
6554
|
"sessions.copyId": "复制会话 ID",
|
|
4904
|
-
"sessions.copyLink": "复制会话链接",
|
|
4905
6555
|
"connectors.title": "连接器",
|
|
4906
6556
|
"connectors.description": "显示当前会话可用的 MCP 连接器及其工具,不显示地址、命令或凭证。",
|
|
4907
6557
|
"connectors.openSession": "请先打开一个会话以读取连接器。",
|
|
@@ -4909,8 +6559,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4909
6559
|
"connectors.failed": "连接器目录暂不可用,请稍后重试。",
|
|
4910
6560
|
"connectors.toolCount": "{count} 个工具",
|
|
4911
6561
|
"connectors.empty": "当前会话没有可用的 MCP 连接器。",
|
|
4912
|
-
"
|
|
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",
|
|
4913
6570
|
"about.title": "Codex UI",
|
|
6571
|
+
"about.viewProject": "GitHub",
|
|
6572
|
+
"about.feedback": "问题反馈",
|
|
4914
6573
|
"about.description": "为 DSH 提供 Codex 风格的侧栏、工作区会话管理、搜索与会话轮次导航。",
|
|
4915
6574
|
"about.features": "基本功能",
|
|
4916
6575
|
"about.feature.sidebar": "Codex 风格侧栏、全局会话搜索与设置入口",
|
|
@@ -4934,6 +6593,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4934
6593
|
"about.upToDate": "所有配套插件均已安装并为最新版本。",
|
|
4935
6594
|
"about.installFailed": "依赖安装失败,请稍后重试。",
|
|
4936
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 依赖管理服务尚未就绪,请重启后重试。",
|
|
4937
6602
|
"about.restartRequired": "正在热更新插件,窗口会自动刷新。",
|
|
4938
6603
|
"about.restartManually": "安装完成。当前 Web 无法自动重启,请重启 DSH Web 后刷新页面。",
|
|
4939
6604
|
"about.progressHint": "正在安装插件…",
|
|
@@ -4953,7 +6618,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4953
6618
|
"about.dependency.market": "插件市场",
|
|
4954
6619
|
"turns.label": "当前会话轮次导航",
|
|
4955
6620
|
"turns.untitled": "未命名提问",
|
|
4956
|
-
"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"
|
|
4957
6632
|
};
|
|
4958
6633
|
const en = {
|
|
4959
6634
|
"sidebar.label": "DSH navigation",
|
|
@@ -4985,6 +6660,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
4985
6660
|
"channel.wecom": "WeCom",
|
|
4986
6661
|
"channel.qq": "QQ",
|
|
4987
6662
|
"channel.telegram": "Telegram",
|
|
6663
|
+
"channel.unknown": "Channel",
|
|
4988
6664
|
"schedule.empty": "No scheduled-task runs yet.",
|
|
4989
6665
|
"schedule.groupActions": "Task actions for {name}",
|
|
4990
6666
|
"schedule.taskSettings": "Task settings",
|
|
@@ -5000,32 +6676,45 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5000
6676
|
"search.actions": "Quick actions",
|
|
5001
6677
|
"workspace.label": "Workspace conversations",
|
|
5002
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",
|
|
5003
6689
|
"workspace.recent": "Recents",
|
|
5004
6690
|
"workspace.recentEmpty": "No chats",
|
|
5005
6691
|
"workspace.noChat": "No chats",
|
|
5006
|
-
"workspace.empty": "No
|
|
6692
|
+
"workspace.empty": "No projects",
|
|
5007
6693
|
"workspace.newSession": "New conversation",
|
|
5008
|
-
"workspace.rename": "
|
|
6694
|
+
"workspace.rename": "Rename project",
|
|
5009
6695
|
"workspace.pin": "Pin project",
|
|
5010
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…",
|
|
5011
6702
|
"workspace.pinned": "Pinned",
|
|
5012
6703
|
"workspace.pinnedEmpty": "Drag a project here to pin it",
|
|
5013
6704
|
"workspace.openPath": "Open in file explorer",
|
|
5014
|
-
"workspace.delete": "
|
|
6705
|
+
"workspace.delete": "Remove project",
|
|
5015
6706
|
"workspace.deleteDescription": "This removes “{name}” from the project list. The folder and conversation records remain.",
|
|
5016
|
-
"workspace.deletePending": "
|
|
6707
|
+
"workspace.deletePending": "Removing project…",
|
|
5017
6708
|
"workspace.actions": "Project actions for {name}",
|
|
5018
6709
|
"workspace.taskCount": "{count} tasks",
|
|
5019
|
-
"workspace.
|
|
6710
|
+
"workspace.taskSummary": "{count} tasks · {unreadCount} unread",
|
|
6711
|
+
"workspace.edit": "Rename project",
|
|
5020
6712
|
"sessions.close": "Close",
|
|
5021
6713
|
"sessions.cancel": "Cancel",
|
|
5022
6714
|
"sessions.save": "Save",
|
|
5023
6715
|
"sessions.failed": "Action failed: {message}",
|
|
5024
6716
|
"sessions.unknown": "Conversation not found.",
|
|
5025
6717
|
"sessions.actions": "Conversation actions for {name}",
|
|
5026
|
-
"sessions.pin": "Pin conversation",
|
|
5027
|
-
"sessions.unpin": "Unpin",
|
|
5028
|
-
"sessions.pinned": "Pinned",
|
|
5029
6718
|
"sessions.markUnread": "Mark as unread",
|
|
5030
6719
|
"sessions.markRead": "Mark as read",
|
|
5031
6720
|
"sessions.unread": "Unread",
|
|
@@ -5034,17 +6723,33 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5034
6723
|
"sessions.planReview": "Plan awaiting review",
|
|
5035
6724
|
"sessions.rename": "Rename conversation",
|
|
5036
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.",
|
|
5037
6728
|
"sessions.archive": "Archive conversation",
|
|
6729
|
+
"sessions.archiveFailed": "The conversation could not be archived. Try again later.",
|
|
5038
6730
|
"sessions.delete": "Delete conversation",
|
|
5039
6731
|
"sessions.deleteDescription": "This permanently deletes “{name}” and all of its records. This cannot be undone.",
|
|
5040
6732
|
"sessions.deletePending": "Deleting conversation…",
|
|
5041
6733
|
"sessions.deleteUnavailable": "The archive manager plugin is not installed or unavailable.",
|
|
6734
|
+
"sessions.deleteFailed": "The conversation could not be deleted. Try again later.",
|
|
5042
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.",
|
|
5043
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…",
|
|
5044
6750
|
"sessions.copyPath": "Copy working directory",
|
|
5045
6751
|
"sessions.copyTitle": "Copy conversation title",
|
|
5046
6752
|
"sessions.copyId": "Copy conversation ID",
|
|
5047
|
-
"sessions.copyLink": "Copy conversation link",
|
|
5048
6753
|
"connectors.title": "Connectors",
|
|
5049
6754
|
"connectors.description": "Shows MCP connectors and tools available to this session without exposing addresses, commands, or credentials.",
|
|
5050
6755
|
"connectors.openSession": "Open a conversation to load connectors.",
|
|
@@ -5052,8 +6757,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5052
6757
|
"connectors.failed": "Connectors are unavailable. Try again shortly.",
|
|
5053
6758
|
"connectors.toolCount": "{count} tools",
|
|
5054
6759
|
"connectors.empty": "This conversation has no available MCP connectors.",
|
|
5055
|
-
"
|
|
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",
|
|
5056
6768
|
"about.title": "Codex UI",
|
|
6769
|
+
"about.viewProject": "GitHub",
|
|
6770
|
+
"about.feedback": "Issues",
|
|
5057
6771
|
"about.description": "Adds a Codex-style sidebar, workspace conversation management, search, and turn navigation to DSH.",
|
|
5058
6772
|
"about.features": "Core features",
|
|
5059
6773
|
"about.feature.sidebar": "Codex-style sidebar, global conversation search, and settings entry points",
|
|
@@ -5077,6 +6791,12 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5077
6791
|
"about.upToDate": "All companion plugins are installed and up to date.",
|
|
5078
6792
|
"about.installFailed": "Dependency installation failed. Try again later.",
|
|
5079
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.",
|
|
5080
6800
|
"about.restartRequired": "Updating plugins now. The window will refresh automatically.",
|
|
5081
6801
|
"about.restartManually": "Installation complete. This Web host cannot restart itself; restart DSH Web, then refresh the page.",
|
|
5082
6802
|
"about.progressHint": "Installing plugin…",
|
|
@@ -5096,7 +6816,17 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5096
6816
|
"about.dependency.market": "Plugin Market",
|
|
5097
6817
|
"turns.label": "Conversation turn navigation",
|
|
5098
6818
|
"turns.untitled": "Untitled prompt",
|
|
5099
|
-
"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"
|
|
5100
6830
|
};
|
|
5101
6831
|
//#endregion
|
|
5102
6832
|
//#region src/client/host-open-path.ts
|
|
@@ -5141,7 +6871,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5141
6871
|
[["定时任务", "Scheduled tasks"], "schedule"],
|
|
5142
6872
|
[["IM助理", "IM Assistant"], "assistant"],
|
|
5143
6873
|
[["已归档", "Archived"], "archive"],
|
|
5144
|
-
[["
|
|
6874
|
+
[["Codex UI"], "about"]
|
|
5145
6875
|
];
|
|
5146
6876
|
/** 按设置导航可见文案解析侧栏同款图标;插件市场复用插件图标。 */
|
|
5147
6877
|
function settingsNavIconId(label) {
|
|
@@ -5504,8 +7234,8 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5504
7234
|
}
|
|
5505
7235
|
function turnLinks(snapshot, fallback) {
|
|
5506
7236
|
const links = [];
|
|
5507
|
-
for (const key of snapshot.
|
|
5508
|
-
const node = snapshot.
|
|
7237
|
+
for (const key of snapshot.order) {
|
|
7238
|
+
const node = snapshot.nodes.get(key);
|
|
5509
7239
|
if (node?.kind !== "user") continue;
|
|
5510
7240
|
links.push({
|
|
5511
7241
|
key: node.key,
|
|
@@ -5517,14 +7247,21 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5517
7247
|
function equalTurns(left, right) {
|
|
5518
7248
|
return left.length === right.length && left.every((turn, index) => turn.key === right[index]?.key && turn.summary === right[index]?.summary);
|
|
5519
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
|
+
}
|
|
5520
7256
|
function railLeftFromSidebar() {
|
|
5521
7257
|
const sidebar = document.querySelector(".dcu-root");
|
|
5522
7258
|
if (sidebar === null) return 288;
|
|
5523
7259
|
return Math.round(sidebar.getBoundingClientRect().right) + 16;
|
|
5524
7260
|
}
|
|
5525
7261
|
/** 当前会话的轮次导航;只读取原生聊天锚点并滚动,不改写会话数据或消息视图。 */
|
|
5526
|
-
function TurnNavigator({ useSession, t }) {
|
|
5527
|
-
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);
|
|
5528
7265
|
const [current, setCurrent] = (0, react.useState)(turns[0]?.key ?? null);
|
|
5529
7266
|
const [hoverAt, setHoverAt] = (0, react.useState)(null);
|
|
5530
7267
|
const [railLeft, setRailLeft] = (0, react.useState)(288);
|
|
@@ -5684,8 +7421,13 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5684
7421
|
function hasDeleteSession(value) {
|
|
5685
7422
|
return value !== null && typeof value === "object" && "deleteSession" in value && typeof value.deleteSession === "function";
|
|
5686
7423
|
}
|
|
5687
|
-
function
|
|
5688
|
-
|
|
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
|
+
}
|
|
5689
7431
|
}
|
|
5690
7432
|
/** Archive Manager replaces the official ui-workspace row with this optional service. */
|
|
5691
7433
|
function startWorkspaceSession(ctx, workspaceId) {
|
|
@@ -5694,7 +7436,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5694
7436
|
uiWorkspace.startSession(workspaceId);
|
|
5695
7437
|
return;
|
|
5696
7438
|
}
|
|
5697
|
-
ctx.workspaces
|
|
7439
|
+
if (hasStartSession(ctx.workspaces)) {
|
|
7440
|
+
ctx.workspaces.startSession(workspaceId);
|
|
7441
|
+
return;
|
|
7442
|
+
}
|
|
7443
|
+
console.warn("DSH 工作空间服务尚未就绪,无法新建会话。");
|
|
5698
7444
|
}
|
|
5699
7445
|
/** 替换 DSH 的官方 sidebar 插槽,不修改 DSH 源码或会话数据。 */
|
|
5700
7446
|
function apply(ctx) {
|
|
@@ -5747,9 +7493,10 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5747
7493
|
toggleSidebar: () => {
|
|
5748
7494
|
ctx.layout.toggleSidebar();
|
|
5749
7495
|
},
|
|
5750
|
-
archiveSession
|
|
7496
|
+
archiveSession,
|
|
5751
7497
|
deleteSession,
|
|
5752
7498
|
forkSession,
|
|
7499
|
+
moveSession,
|
|
5753
7500
|
renameSession,
|
|
5754
7501
|
openPath,
|
|
5755
7502
|
companionSlots
|
|
@@ -5762,36 +7509,65 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5762
7509
|
locale: NS
|
|
5763
7510
|
}, TurnNavigator));
|
|
5764
7511
|
const forkSession = async (sessionId) => {
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
7512
|
+
await runHostAction("fork", async () => {
|
|
7513
|
+
const childId = await ctx.sessions.fork({
|
|
7514
|
+
sessionId,
|
|
7515
|
+
increaseTitle: true
|
|
7516
|
+
});
|
|
7517
|
+
ctx.sessions.open(childId);
|
|
5768
7518
|
});
|
|
5769
|
-
ctx.sessions.open(childId);
|
|
5770
7519
|
};
|
|
5771
7520
|
const renameSession = async (sessionId, title) => {
|
|
5772
7521
|
const session = ctx.sessions.binding(sessionId)?.session;
|
|
5773
|
-
if (session === void 0) throw new
|
|
5774
|
-
|
|
5775
|
-
|
|
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
|
+
});
|
|
5776
7527
|
};
|
|
5777
7528
|
const deleteSession = async (sessionId) => {
|
|
5778
7529
|
const registry = ctx.get("remote.workspaceRegistry");
|
|
5779
|
-
if (!hasDeleteSession(registry)) throw new
|
|
5780
|
-
|
|
5781
|
-
|
|
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
|
+
});
|
|
5782
7551
|
};
|
|
5783
7552
|
const startConnectorPromptSession = async (promptText) => {
|
|
5784
7553
|
const prompt = promptText.trim();
|
|
5785
|
-
if (prompt === "") throw new
|
|
7554
|
+
if (prompt === "") throw new UserFacingError(t("connectors.promptRequired"));
|
|
5786
7555
|
const workspaces = ctx.workspaces.list.getSnapshot();
|
|
5787
|
-
const
|
|
5788
|
-
const
|
|
5789
|
-
|
|
5790
|
-
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);
|
|
5791
7567
|
const conversation = ctx.get("conversation");
|
|
5792
|
-
if (conversation === void 0) throw new
|
|
7568
|
+
if (conversation === void 0) throw new UserFacingError(t("connectors.conversationUnavailable"));
|
|
5793
7569
|
const binding = ctx.sessions.binding(sessionId);
|
|
5794
|
-
if (binding === void 0) throw new
|
|
7570
|
+
if (binding === void 0) throw new UserFacingError(t("connectors.sessionPending"));
|
|
5795
7571
|
conversation.input.for(binding.ctx).setDraft(prompt);
|
|
5796
7572
|
ctx.sessions.open(sessionId);
|
|
5797
7573
|
};
|
|
@@ -5800,10 +7576,11 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
|
|
|
5800
7576
|
priority: -1,
|
|
5801
7577
|
locale: NS,
|
|
5802
7578
|
inject: () => ({
|
|
5803
|
-
archiveSession
|
|
7579
|
+
archiveSession,
|
|
5804
7580
|
deleteSession,
|
|
5805
7581
|
deleteWorkspace: (workspaceId) => ctx.workspaces.delete(workspaceId),
|
|
5806
7582
|
forkSession,
|
|
7583
|
+
moveSession,
|
|
5807
7584
|
openPath,
|
|
5808
7585
|
openSession: (sessionId) => {
|
|
5809
7586
|
ctx.sessions.open(sessionId);
|