@michengai/dsh-codex-ui 0.2.71 → 0.2.72

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.
Files changed (2) hide show
  1. package/dist/client.js +17 -211
  2. package/package.json +6 -6
package/dist/client.js CHANGED
@@ -262,7 +262,6 @@ window.__ModuleLoader__.load({
262
262
  //#endregion
263
263
  //#region src/client/session-manager.ts
264
264
  const SESSION_PINS_STORAGE_KEY = "dsh.session-pins.v1";
265
- const SESSION_SECTION_PINS_STORAGE_KEY = "dsh-codex-ui.pinned-section-sessions.v1";
266
265
  const SESSION_UNREAD_STORAGE_KEY = "dsh.session-unread.v1";
267
266
  function normalizeSessionIds(ids) {
268
267
  return [...new Set(ids.filter((id) => id.trim() !== ""))];
@@ -295,15 +294,6 @@ window.__ModuleLoader__.load({
295
294
  url.searchParams.set("session", sessionId);
296
295
  return url.toString();
297
296
  }
298
- /** 把会话插入置顶列表的指定位置;省略锚点时追加到末尾。 */
299
- function insertSessionId(ids, id, beforeId) {
300
- const next = ids.filter((item) => item !== id);
301
- if (beforeId === void 0) return [...next, id];
302
- if (beforeId === id) return ids.includes(id) ? [...ids] : [...next, id];
303
- const index = next.indexOf(beforeId);
304
- next.splice(index < 0 ? next.length : index, 0, id);
305
- return next;
306
- }
307
297
  //#endregion
308
298
  //#region src/client/session-tree.tsx
309
299
  function PinIcon() {
@@ -1121,22 +1111,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1121
1111
  return item === void 0 ? [] : [item];
1122
1112
  });
1123
1113
  }
1124
- /** 置顶区的会话按拖入顺序展示;不因父项目已置顶而隐藏。 */
1125
- function standalonePinnedSessionIds(pinnedSessionIds) {
1126
- return [...pinnedSessionIds];
1127
- }
1128
- /** 置顶区已有会话时,不再同时展示任何项目文件夹,避免旧置顶项目叠成两条。 */
1129
- function workspaceIdsHiddenByPinnedSessions(workspaces, pinnedSessionIds) {
1130
- if (pinnedSessionIds.length === 0) return [];
1131
- return workspaces.map((workspace) => String(workspace.workspaceId));
1132
- }
1133
1114
  const SESSION_DRAG_TYPE = "application/x-dcu-session";
1134
1115
  const WORKSPACE_DRAG_TYPE = "application/x-dcu-workspace";
1135
1116
  const SESSION_DRAG_PREFIX = "dcu-session:";
1136
1117
  const WORKSPACE_DRAG_PREFIX = "dcu-workspace:";
1137
- function dragTypes(data) {
1138
- return data === void 0 ? [] : Array.from(data.types);
1139
- }
1140
1118
  function textPayload(data) {
1141
1119
  try {
1142
1120
  return data?.getData("text/plain") ?? "";
@@ -1144,11 +1122,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1144
1122
  return "";
1145
1123
  }
1146
1124
  }
1147
- /** 拖过置顶区时用来决定是否 preventDefault;只看 types,不读数据。 */
1148
- function isSidebarItemDrag(data) {
1149
- const types = dragTypes(data);
1150
- return types.includes("application/x-dcu-session") || types.includes("application/x-dcu-workspace") || types.includes("text/plain");
1151
- }
1152
1125
  /** 写入会话拖拽载荷;drop 时以这个为准,不依赖尚未刷新的 React 状态。 */
1153
1126
  function writeSessionDrag(data, sessionId, title) {
1154
1127
  data.effectAllowed = "move";
@@ -1190,11 +1163,11 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1190
1163
  .dcu-wb-section-head{position:relative;display:flex;align-items:center;min-height:24px;padding:0 4px;border-radius:6px}.dcu-wb-section-head:hover .dcu-wb-actions{display:flex}.dcu-wb-section-label{display:flex;align-items:center;gap:4px;flex:1;min-width:0;min-height:24px;border:0;padding:2px 4px;background:transparent;color:var(--dcu-sidebar-tertiary);font:13px/20px var(--dcu-font,inherit);font-weight:400;letter-spacing:.02em;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 140ms ease,transform 180ms ease}.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:grid;grid-template-rows:0fr;transition:grid-template-rows 220ms ease}.dcu-wb-section-body[data-open=true]{grid-template-rows:1fr}.dcu-wb-section-body>div{overflow:hidden;min-height:0}@media (prefers-reduced-motion:reduce){.dcu-wb-section-caret,.dcu-wb-section-body{transition:none}}
1191
1164
  .dcu-wb-project{position:relative}
1192
1165
  .dcu-wb-project-head,.dcu-wb-session{position:relative;display:flex;align-items:center;gap:6px;width:100%;border-radius:8px;padding:0 8px;color:var(--dcu-sidebar-primary);cursor:pointer}
1193
- .dcu-wb-project-head{height:34px;background:transparent;font:inherit;text-align:left}
1194
- .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-head+.dcu-wb-session,.dcu-wb-project-head+.dcu-wb-nochat{margin-top:4px}.dcu-wb-session+.dcu-wb-session{margin-top:2px}
1166
+ .dcu-wb-project-head{height:28px;background:transparent;font:inherit;text-align:left}
1167
+ .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-head+.dcu-wb-session,.dcu-wb-project-head+.dcu-wb-nochat{margin-top:0}.dcu-wb-session+.dcu-wb-session{margin-top:2px}
1195
1168
  .dcu-wb-project-head[draggable=true],.dcu-wb-session[draggable=true]{cursor:grab}
1196
1169
  .dcu-wb-project-head[draggable=true]:active,.dcu-wb-session[draggable=true]:active{cursor:grabbing}
1197
- .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-head.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;left:8px;right:8px;top:-4px;height:8px;pointer-events:none;background:radial-gradient(circle at 4px 50%,var(--dsw-alias-state-business-primary) 3.25px,transparent 3.45px),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-project-head.dcu-wb-drop-after::before,.dcu-wb-session.dcu-wb-drop-after::before{top:auto;bottom:-4px}.dcu-wb-dragging{opacity:.28}.dcu-wb-drag-ghost{position:fixed;top:-120px;left:-240px;z-index:10040;max-width:220px;height:32px;padding:0 10px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary);font:13px/32px var(--dcu-font,inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;opacity:0}
1170
+ .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-head.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;left:8px;right:8px;top:-4px;height:8px;pointer-events:none;background:radial-gradient(circle at 4px 50%,var(--dsw-alias-state-business-primary) 3.25px,transparent 3.45px),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,.dcu-wb-project-head.dcu-wb-drop::before,.dcu-wb-session.dcu-wb-drop::before{top:0}.dcu-wb-project-head.dcu-wb-drop-after::before,.dcu-wb-session.dcu-wb-drop-after::before{top:auto;bottom:0}.dcu-wb-dragging{opacity:.28}.dcu-wb-drag-ghost{position:fixed;top:-120px;left:-240px;z-index:10040;max-width:220px;height:32px;padding:0 10px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;background:var(--dcu-sidebar-hover);color:var(--dcu-sidebar-primary);font:13px/32px var(--dcu-font,inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;opacity:0}
1198
1171
  .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}
1199
1172
  .dcu-wb-project-current .dcu-wb-folder{color:var(--dsw-alias-state-business-primary)}
1200
1173
  .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}
@@ -1222,7 +1195,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1222
1195
  .dcu-wb-rename-input:focus{border-color:var(--dsw-alias-button-info-fill)}
1223
1196
  `;
1224
1197
  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}}`;
1225
- const typographyStyles = `.dcu-wb{font:14px/20px var(--dcu-font,var(--dsw-font-family))}.dcu-wb-section-label{color:var(--dcu-sidebar-tertiary);font-size:13px;font-weight:400;letter-spacing:.02em}.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:4px 8px 6px 28px;color:var(--dcu-sidebar-tertiary);font-size:14px;line-height:20px}`;
1198
+ const typographyStyles = `.dcu-wb{font:14px/20px var(--dcu-font,var(--dsw-font-family))}.dcu-wb-section-label{color:var(--dcu-sidebar-tertiary);font-size:13px;font-weight:400;letter-spacing:.02em}.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}`;
1226
1199
  const WORKSPACE_TREE_STYLE = stylesheet$4 + runningStyles + typographyStyles;
1227
1200
  function storage$1() {
1228
1201
  return typeof window === "undefined" ? void 0 : window.localStorage;
@@ -1245,7 +1218,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1245
1218
  const [expanded, setExpanded] = (0, react.useState)({});
1246
1219
  const [pinnedWorkspaceIds, setPinnedWorkspaceIds] = (0, react.useState)(() => readPinnedWorkspaceIds(storage$1()));
1247
1220
  const [pinnedSessionIds, setPinnedSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_PINS_STORAGE_KEY));
1248
- const [sectionSessionIds, setSectionSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_SECTION_PINS_STORAGE_KEY));
1249
1221
  const [unreadSessionIds, setUnreadSessionIds] = (0, react.useState)(() => readSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY));
1250
1222
  const [menu, setMenu] = (0, react.useState)();
1251
1223
  const [renameTarget, setRenameTarget] = (0, react.useState)();
@@ -1274,13 +1246,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1274
1246
  (0, react.useEffect)(() => {
1275
1247
  writeSessionIds(storage$1(), SESSION_PINS_STORAGE_KEY, pinnedSessionIds);
1276
1248
  }, [pinnedSessionIds]);
1277
- (0, react.useEffect)(() => {
1278
- writeSessionIds(storage$1(), SESSION_SECTION_PINS_STORAGE_KEY, sectionSessionIds);
1279
- }, [sectionSessionIds]);
1280
- (0, react.useEffect)(() => {
1281
- if (sectionSessionIds.length === 0) return;
1282
- setPinnedWorkspaceIds((ids) => ids.length === 0 ? ids : []);
1283
- }, [sectionSessionIds]);
1284
1249
  (0, react.useEffect)(() => {
1285
1250
  writeSessionIds(storage$1(), SESSION_UNREAD_STORAGE_KEY, unreadSessionIds);
1286
1251
  }, [unreadSessionIds]);
@@ -1367,14 +1332,12 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1367
1332
  sessions.current,
1368
1333
  menu
1369
1334
  ]);
1370
- const pinSectionSessions = standalonePinnedSessionIds(sectionSessionIds);
1371
- const hiddenPinnedWorkspaceIds = new Set(workspaceIdsHiddenByPinnedSessions(groups.items, pinSectionSessions));
1372
- const projectPinned = (id) => pinnedWorkspaceIds.includes(String(id)) && !hiddenPinnedWorkspaceIds.has(String(id));
1373
- const pinnedGroups = orderByIds(groups.items, pinnedWorkspaceIds, (workspace) => String(workspace.workspaceId)).filter((workspace) => !hiddenPinnedWorkspaceIds.has(String(workspace.workspaceId)));
1335
+ const projectPinned = (id) => pinnedWorkspaceIds.includes(String(id));
1336
+ const pinnedGroups = orderByIds(groups.items, pinnedWorkspaceIds, (workspace) => String(workspace.workspaceId));
1374
1337
  const regularGroups = groups.items.filter((workspace) => !projectPinned(workspace.workspaceId));
1375
- const pinDragActive = workspaceDragId !== void 0 || sessionDrag !== void 0;
1338
+ const pinDragActive = workspaceDragId !== void 0;
1376
1339
  const assignedIds = workspaces.items.flatMap((workspace) => workspace.sessionIds.map((id) => String(id)));
1377
- const recentIds = ungroupedSessionIds(sessions.ids ?? Object.keys(sessions.byId), sessions.byId, assignedIds, workspaces.archivedSessionIds).filter((id) => !pinSectionSessions.includes(id)).sort((left, right) => (sessions.byId[right]?.updatedAt ?? 0) - (sessions.byId[left]?.updatedAt ?? 0));
1340
+ 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));
1378
1341
  const run = async (key, action) => {
1379
1342
  setBusy(key);
1380
1343
  setError(void 0);
@@ -1412,7 +1375,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1412
1375
  if (target.kind === "session") {
1413
1376
  await deleteSession(target.id);
1414
1377
  setPinnedSessionIds((ids) => ids.filter((id) => id !== target.id));
1415
- setSectionSessionIds((ids) => ids.filter((id) => id !== target.id));
1416
1378
  setUnreadSessionIds((ids) => ids.filter((id) => id !== target.id));
1417
1379
  } else {
1418
1380
  await deleteWorkspace(target.id);
@@ -1481,14 +1443,10 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1481
1443
  const pinWorkspaceAt = (id, beforeId) => {
1482
1444
  setPinnedWorkspaceIds((ids) => insertPinnedWorkspace(ids, id, beforeId));
1483
1445
  };
1484
- const pinSessionAt = (id, beforeId) => {
1485
- setSectionSessionIds((ids) => insertSessionId(ids, id, beforeId));
1486
- setPinnedWorkspaceIds((ids) => ids.length === 0 ? ids : []);
1487
- };
1488
1446
  const renderGroup = (workspace, zone) => {
1489
1447
  const expandKey = zone === "pinned" ? `pin:${workspace.workspaceId}` : String(workspace.workspaceId);
1490
1448
  const isExpanded = expanded[expandKey] ?? true;
1491
- const shownIds = workspace.visibleIds.filter((id) => !pinSectionSessions.includes(id));
1449
+ const shownIds = workspace.visibleIds;
1492
1450
  const menuOpen = menu?.type === "workspace" && menu.id === workspace.workspaceId;
1493
1451
  const menuAt = menuOpen && menu.x !== void 0 && menu.y !== void 0 ? {
1494
1452
  x: menu.x,
@@ -1498,7 +1456,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1498
1456
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1499
1457
  className: `dcu-wb-project${isCurrentWorkspace ? " dcu-wb-project-current" : ""}`,
1500
1458
  onDragOver: (event) => {
1501
- if (workspaceDragId === void 0 && !isSidebarItemDrag(event.dataTransfer) && !(zone === "pinned" && sessionDrag !== void 0)) return;
1459
+ if (workspaceDragId === void 0) return;
1502
1460
  event.preventDefault();
1503
1461
  event.stopPropagation();
1504
1462
  event.dataTransfer.dropEffect = "move";
@@ -1519,17 +1477,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1519
1477
  onDrop: (event) => {
1520
1478
  event.preventDefault();
1521
1479
  event.stopPropagation();
1522
- const droppedSession = readSessionDrag(event.dataTransfer, sessionDrag?.sessionId);
1523
- if (zone === "pinned" && droppedSession !== void 0) {
1524
- setSessionDrag(void 0);
1525
- setSessionDropId(void 0);
1526
- setWorkspaceDragId(void 0);
1527
- setWorkspaceDropId(void 0);
1528
- setWorkspaceDropAfter(false);
1529
- setPinSlot(void 0);
1530
- pinSessionAt(droppedSession);
1531
- return;
1532
- }
1533
1480
  const dragged = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
1534
1481
  const after = event.clientY > event.currentTarget.getBoundingClientRect().top + event.currentTarget.getBoundingClientRect().height / 2;
1535
1482
  setWorkspaceDragId(void 0);
@@ -1918,27 +1865,20 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1918
1865
  className: "dcu-wb-section",
1919
1866
  "aria-label": t("workspace.pinned"),
1920
1867
  onDragOver: (event) => {
1921
- if (!pinDragActive && !isSidebarItemDrag(event.dataTransfer)) return;
1868
+ if (!pinDragActive) return;
1922
1869
  event.preventDefault();
1923
1870
  event.dataTransfer.dropEffect = "move";
1924
1871
  if (event.target === event.currentTarget || event.target instanceof Element && event.target.closest(".dcu-wb-section-head") !== null) setPinSlot("header");
1925
1872
  },
1926
1873
  onDrop: (event) => {
1927
1874
  event.preventDefault();
1928
- const draggedSession = readSessionDrag(event.dataTransfer, sessionDrag?.sessionId);
1929
1875
  const draggedWorkspace = readWorkspaceDrag(event.dataTransfer, workspaceDragId);
1930
1876
  const slot = pinSlot;
1931
1877
  setWorkspaceDragId(void 0);
1932
1878
  setWorkspaceDropId(void 0);
1933
1879
  setWorkspaceDropAfter(false);
1934
- setSessionDrag(void 0);
1935
- setSessionDropId(void 0);
1936
1880
  setPinSlot(void 0);
1937
- if (draggedSession !== void 0) {
1938
- pinSessionAt(draggedSession, slot === "header" ? pinSectionSessions[0] : slot === "end" || slot === void 0 || !pinSectionSessions.includes(slot) ? void 0 : slot);
1939
- return;
1940
- }
1941
- if (draggedWorkspace !== void 0) pinWorkspaceAt(draggedWorkspace, slot === "header" ? pinnedGroups[0] === void 0 ? void 0 : String(pinnedGroups[0].workspaceId) : slot === "end" || slot === void 0 || pinSectionSessions.includes(slot) ? void 0 : slot);
1881
+ if (draggedWorkspace !== void 0) pinWorkspaceAt(draggedWorkspace, slot === "header" ? pinnedGroups[0] === void 0 ? void 0 : String(pinnedGroups[0].workspaceId) : slot === "end" || slot === void 0 ? void 0 : slot);
1942
1882
  },
1943
1883
  onDragLeave: (event) => {
1944
1884
  if (event.currentTarget.contains(event.relatedTarget)) return;
@@ -1978,7 +1918,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1978
1918
  (pinDragActive || pinSlot === "header") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1979
1919
  className: `dcu-wb-pin-start${pinSlot === "header" ? " dcu-wb-drop" : ""}`,
1980
1920
  onDragOver: (event) => {
1981
- if (!pinDragActive && !isSidebarItemDrag(event.dataTransfer)) return;
1921
+ if (!pinDragActive) return;
1982
1922
  event.preventDefault();
1983
1923
  event.stopPropagation();
1984
1924
  event.dataTransfer.dropEffect = "move";
@@ -1987,149 +1927,15 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
1987
1927
  setWorkspaceDropAfter(false);
1988
1928
  }
1989
1929
  }),
1990
- pinSectionSessions.length === 0 && pinnedGroups.length === 0 && pinSlot !== "header" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1930
+ pinnedGroups.length === 0 && pinSlot !== "header" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1991
1931
  className: "dcu-wb-empty",
1992
1932
  children: t("workspace.pinnedEmpty")
1993
1933
  }),
1994
- pinSectionSessions.map((id) => {
1995
- const session = sessions.byId[id];
1996
- if (session === void 0) return null;
1997
- const title = session.displayTitle;
1998
- const workspace = groups.items.find((item) => item.visibleIds.includes(id));
1999
- const path = session.cwd ?? workspace?.path;
2000
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionRow, {
2001
- id,
2002
- title,
2003
- flat: true,
2004
- selected: sessions.current === id,
2005
- menuOpen: menu?.type === "session" && menu.id === id,
2006
- pinned: true,
2007
- unread: unreadSessionIds.includes(id),
2008
- running: session.running === true,
2009
- t,
2010
- menuItems: sessionMenu(id, title, path),
2011
- menuPoint: menu?.type === "session" && menu.id === id && menu.x !== void 0 && menu.y !== void 0 ? {
2012
- x: menu.x,
2013
- y: menu.y
2014
- } : void 0,
2015
- draggable: true,
2016
- dropActive: sessionDropId === id,
2017
- onDragStart: (event) => {
2018
- event.stopPropagation();
2019
- setWorkspaceDragId(void 0);
2020
- writeSessionDrag(event.dataTransfer, id, title);
2021
- const preview = document.createElement("div");
2022
- preview.className = "dcu-wb-drag-ghost";
2023
- preview.textContent = title;
2024
- document.body.appendChild(preview);
2025
- event.dataTransfer.setDragImage(preview, 16, 18);
2026
- window.requestAnimationFrame(() => {
2027
- preview.remove();
2028
- });
2029
- setSessionDrag({
2030
- sessionId: id,
2031
- workspaceId: workspace?.workspaceId ?? ""
2032
- });
2033
- },
2034
- onDragEnd: () => {
2035
- setSessionDrag(void 0);
2036
- setSessionDropId(void 0);
2037
- setPinSlot(void 0);
2038
- },
2039
- onDragOver: (event) => {
2040
- if (sessionDrag === void 0) return;
2041
- event.preventDefault();
2042
- event.stopPropagation();
2043
- setSessionDropId(id);
2044
- setPinSlot(id);
2045
- },
2046
- onDrop: (event) => {
2047
- event.preventDefault();
2048
- event.stopPropagation();
2049
- const draggedSession = readSessionDrag(event.dataTransfer, sessionDrag?.sessionId);
2050
- const after = event.clientY > event.currentTarget.getBoundingClientRect().top + event.currentTarget.getBoundingClientRect().height / 2;
2051
- setSessionDrag(void 0);
2052
- setSessionDropId(void 0);
2053
- setPinSlot(void 0);
2054
- if (draggedSession === void 0) return;
2055
- pinSessionAt(draggedSession, dropBeforeId(pinSectionSessions, id, after));
2056
- },
2057
- onOpen: () => {
2058
- setUnreadSessionIds((ids) => ids.filter((item) => item !== id));
2059
- openSession(id);
2060
- },
2061
- onMenuChange: (open) => {
2062
- setMenu(open ? {
2063
- id,
2064
- type: "session"
2065
- } : void 0);
2066
- },
2067
- onPin: () => {
2068
- setSectionSessionIds((ids) => ids.filter((item) => item !== id));
2069
- },
2070
- onArchive: () => {
2071
- run("archive", () => archiveSession(id));
2072
- },
2073
- onHover: (event) => {
2074
- const box = hoverCardAnchor(event.currentTarget.getBoundingClientRect());
2075
- showTip({
2076
- kind: "session",
2077
- id,
2078
- title,
2079
- project: workspace?.title,
2080
- path,
2081
- time: formatHoverTime(session.updatedAt),
2082
- left: box.left,
2083
- top: box.top
2084
- });
2085
- },
2086
- onLeave: hideTip,
2087
- onContextMenu: (event) => {
2088
- event.preventDefault();
2089
- event.stopPropagation();
2090
- dismissTip();
2091
- setMenu({
2092
- id,
2093
- type: "session",
2094
- x: event.clientX,
2095
- y: event.clientY
2096
- });
2097
- },
2098
- onSelectAction: (action) => {
2099
- if (busy !== void 0) return;
2100
- if (action === "rename") beginRename("session", id, title);
2101
- if (action === "pin") {
2102
- setSectionSessionIds((ids) => ids.filter((item) => item !== id));
2103
- setMenu(void 0);
2104
- }
2105
- if (action === "unread") {
2106
- setUnreadSessionIds((ids) => toggleSessionId(ids, id));
2107
- setMenu(void 0);
2108
- }
2109
- if (action === "archive") run("archive", () => archiveSession(id));
2110
- if (action === "delete") {
2111
- setDeleteTarget({
2112
- id,
2113
- kind: "session",
2114
- title
2115
- });
2116
- setError(void 0);
2117
- setMenu(void 0);
2118
- }
2119
- if (action === "fork") run("fork", () => forkSession(id));
2120
- if (action === "openPath" && path !== void 0) run("open-path", () => openPath(path));
2121
- if (action === "copyPath") copy(path);
2122
- if (action === "copyTitle") copy(title);
2123
- if (action === "copyId") copy(id);
2124
- if (action === "copyLink") copy(sessionDeepLink(browserBase(), id));
2125
- }
2126
- }, id);
2127
- }),
2128
1934
  pinnedGroups.map((workspace) => renderGroup(workspace, "pinned")),
2129
1935
  pinDragActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2130
1936
  className: `dcu-wb-pin-end${pinSlot === "end" ? " dcu-wb-drop" : ""}`,
2131
1937
  onDragOver: (event) => {
2132
- if (!pinDragActive && !isSidebarItemDrag(event.dataTransfer)) return;
1938
+ if (!pinDragActive) return;
2133
1939
  event.preventDefault();
2134
1940
  event.stopPropagation();
2135
1941
  event.dataTransfer.dropEffect = "move";
@@ -4066,7 +3872,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4066
3872
  "search.actions": "快捷操作",
4067
3873
  "workspace.label": "工作区会话",
4068
3874
  "workspace.pinned": "置顶",
4069
- "workspace.pinnedEmpty": "拖动项目或会话到此处置顶",
3875
+ "workspace.pinnedEmpty": "拖动项目到此处置顶",
4070
3876
  "workspace.projects": "项目",
4071
3877
  "workspace.recent": "最近",
4072
3878
  "workspace.recentEmpty": "无聊天",
@@ -4194,7 +4000,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
4194
4000
  "workspace.pin": "Pin project",
4195
4001
  "workspace.unpin": "Unpin",
4196
4002
  "workspace.pinned": "Pinned",
4197
- "workspace.pinnedEmpty": "Drag a project or chat here to pin it",
4003
+ "workspace.pinnedEmpty": "Drag a project here to pin it",
4198
4004
  "workspace.openPath": "Open in file explorer",
4199
4005
  "workspace.delete": "Delete project",
4200
4006
  "workspace.deleteDescription": "This removes “{name}” from the project list. The folder and conversation records remain.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-codex-ui",
3
- "version": "0.2.71",
3
+ "version": "0.2.72",
4
4
  "description": "以 Codex 风格重构 DSH Web 侧栏的独立客户端插件",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -51,6 +51,10 @@
51
51
  "platform": "web"
52
52
  }
53
53
  },
54
+ "scripts": {
55
+ "build": "tsc --noEmit && tsdown",
56
+ "test": "tsx tests/hover-tip.assert.ts && tsx tests/companion-slots.assert.ts && tsx tests/channel-api.assert.ts && tsx tests/schedule-sessions.assert.ts && tsx tests/session-tree.assert.ts && tsx tests/pinned-sessions.assert.ts && tsx tests/session-manager.assert.ts && tsx tests/workspace-browser.assert.ts && tsx tests/sidebar-search.assert.ts && tsx tests/settings-navigation.assert.ts && tsx tests/settings-nav-icons.assert.ts && tsx tests/locales.assert.ts && vitest run tests/client-runtime.integration.spec.ts && tsx tests/settings-integration.assert.ts && tsx tests/about-dependencies.assert.ts && tsx tests/dependency-manager.assert.ts && tsx tests/conversation-bubbles.assert.ts && tsx tests/conversation-header.assert.ts && tsx tests/conversation-visuals.assert.ts && tsdown && tsx tests/client-bundle.assert.ts && tsx tests/codex-suite.assert.ts"
57
+ },
54
58
  "peerDependencies": {
55
59
  "@deepseek-ai/cordis": ">=4.0.1 <5.0.0",
56
60
  "@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.0 <0.2.0",
@@ -96,9 +100,5 @@
96
100
  "tsx": "^4.22.4",
97
101
  "typescript": "^6.0.3",
98
102
  "vitest": "^4.1.8"
99
- },
100
- "scripts": {
101
- "build": "tsc --noEmit && tsdown",
102
- "test": "tsx tests/hover-tip.assert.ts && tsx tests/companion-slots.assert.ts && tsx tests/channel-api.assert.ts && tsx tests/schedule-sessions.assert.ts && tsx tests/session-tree.assert.ts && tsx tests/pinned-sessions.assert.ts && tsx tests/session-manager.assert.ts && tsx tests/workspace-browser.assert.ts && tsx tests/sidebar-search.assert.ts && tsx tests/settings-navigation.assert.ts && tsx tests/settings-nav-icons.assert.ts && tsx tests/locales.assert.ts && vitest run tests/client-runtime.integration.spec.ts && tsx tests/settings-integration.assert.ts && tsx tests/about-dependencies.assert.ts && tsx tests/dependency-manager.assert.ts && tsx tests/conversation-bubbles.assert.ts && tsx tests/conversation-header.assert.ts && tsx tests/conversation-visuals.assert.ts && tsdown && tsx tests/client-bundle.assert.ts && tsx tests/codex-suite.assert.ts"
103
103
  }
104
- }
104
+ }