dsh-better-workspace 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,7 +59,7 @@ web/ ← 虚拟分组(不是真实目录,纯命名层级)
59
59
  ### 其余亮点
60
60
 
61
61
  - **文件夹式收起**:点工作区行 = 收起/展开该工作区的全部会话(收起后行上保留会话数角标);会话分组同样可收起;搜索时自动全部展开。
62
- - **拖拽还原原版能力**:工作区行可拖拽——拖到另一工作区行上/下半即调整顺序(写回宿主 registry 序),拖到分组行则移动进该分组;会话行可拖拽——同工作区拖到另一会话上/下调整顺序,拖到会话子分组即移动进该分组。显示顺序 = 宿主手动序,拖拽结果立即生效。
62
+ - **拖拽还原原版能力**:工作区行可拖拽——拖到另一工作区行上/下半即调整顺序(写回宿主 registry 序),拖到分组行则移动进该分组;会话行可拖拽——同工作区拖到另一会话上/下调整顺序,拖到会话子分组即移动进该分组。显示顺序 = 宿主手动序,拖拽结果立即生效。拖拽工作区期间,单链合并显示的行(如 工作/A)临时展开回文件夹树——路径里的每一级都是可投放的分组行,松手后自动合并回去。
63
63
  - **不丢原生能力**:会话行(打开/重命名/分叉/归档)、每工作区「新会话」、当前会话高亮、官方状态灯(蓝色运行环 / 琥珀待交互 / 绿色完成提醒)、**活跃定时任务角标**(有活动 Schedule 的会话显示闹钟图标,与官方行一致)、未分组会话兜底、中英双语跟随界面语言。
64
64
  - **对话空态页同样生效**:会话空态页的「添加工作区」菜单走的也是本插件的拾取交互,同样带所属分组弹窗。
65
65
 
package/README_EN.md CHANGED
@@ -57,7 +57,7 @@ Session titles nest on `/` too (e.g. `test1/plugin maintenance`). Session groups
57
57
  ### More highlights
58
58
 
59
59
  - **Folder-style collapse**: clicking a workspace row collapses/expands all of its sessions (the row keeps a session counter when collapsed); session groups collapse too; search force-expands everything.
60
- - **Native drag restored**: drag a workspace row above/below another to reorder (writes back the host registry order) or onto a folder row to move it into that group; drag session rows to reorder within the same workspace or onto a session group to move. Display order = host manual order, drag results are visible immediately.
60
+ - **Native drag restored**: drag a workspace row above/below another to reorder (writes back the host registry order) or onto a folder row to move it into that group; drag session rows to reorder within the same workspace or onto a session group to move. Display order = host manual order, drag results are visible immediately. While dragging a workspace, merged single-chain rows (e.g. work/A) temporarily re-expand into folder rows — every level of the path becomes a drop target, and chains merge back when the drag ends.
61
61
  - **Native capabilities kept**: open/rename/fork/archive sessions, per-workspace new-session, current-session highlight, official status dots (blue running ring / amber pending / green done), **active-schedule badge** (alarm clock icon for sessions with active Schedule records, matching the official rows), ungrouped-session fallback, zh/en localization.
62
62
  - **Conversation hero too**: the empty-state “Add workspace” menu uses the same picking interaction with the same group popup.
63
63
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-better-workspace",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "DSH web plugin: a hierarchical workspace tree for the sidebar. Workspace titles containing \"/\" group into virtual folders (web/前端 · web/后端); the add-workspace directory flow gains a parent-group popup; renames re-derive the tree; a new-folder button creates empty levels.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/client.js CHANGED
@@ -65,7 +65,7 @@ window.__ModuleLoader__.load({
65
65
  'settings.expand': '展开',
66
66
  'settings.collapse': '收起',
67
67
  'settings.compactChains': '单链分组折叠显示',
68
- 'settings.compactChains.hint': '单层链合并为一行,出现多个子级时自动展开为树状;展开状态与自定义外观保存在当前浏览器。',
68
+ 'settings.compactChains.hint': '单层链合并为一行,出现多个子级时自动展开为树状;拖拽工作区期间单链临时展开回文件夹树,可放入任意一级;展开状态与自定义外观保存在当前浏览器。',
69
69
  'custom.title': '自定义外观',
70
70
  'custom.color': '颜色',
71
71
  'custom.glow': '发光',
@@ -151,7 +151,7 @@ window.__ModuleLoader__.load({
151
151
  'settings.expand': 'Expand',
152
152
  'settings.collapse': 'Collapse',
153
153
  'settings.compactChains': 'Merge single-child chains',
154
- 'settings.compactChains.hint': 'Single-child chains merge into one row; levels with multiple children expand as a tree. State and custom styling persist in this browser.',
154
+ 'settings.compactChains.hint': 'Single-child chains merge into one row; levels with multiple children expand as a tree. Chains re-expand into folder rows while you drag a workspace, so it can drop into any level. State and custom styling persist in this browser.',
155
155
  'custom.title': 'Customize',
156
156
  'custom.color': 'Color',
157
157
  'custom.glow': 'Glow',
@@ -1209,11 +1209,19 @@ window.__ModuleLoader__.load({
1209
1209
  ungrouped.sort((a, b) => b.updatedAt - a.updatedAt)
1210
1210
  }
1211
1211
 
1212
+ // While a workspace drag is active, single-child chains render UNCOMPRESSED:
1213
+ // a merged "group/workspace" row hides every folder level of the chain inside
1214
+ // its label, and those levels are exactly the drop targets for "move into
1215
+ // this group". Suspending the merge for the drag's duration re-exposes each
1216
+ // level as a real folder row (folder expansion defaults apply); when the
1217
+ // drag ends, the chains merge back. Session drags keep the merged view —
1218
+ // their drop targets live inside workspace rows, which compression merges.
1219
+ const draggingWorkspace = drag !== null && drag.kind === 'workspace'
1212
1220
  const tree = React.useMemo(() => {
1213
1221
  const built = buildTree(items, storeFolders)
1214
- if (!compactChains) return built
1222
+ if (!compactChains || draggingWorkspace) return built
1215
1223
  return { ...built, folders: built.folders.map(compressTree), workspaces: built.workspaces }
1216
- }, [items, storeFolders, compactChains])
1224
+ }, [items, storeFolders, compactChains, draggingWorkspace])
1217
1225
 
1218
1226
  const sessionsOf = (workspace) => {
1219
1227
  const rows = []
@@ -1316,7 +1324,15 @@ window.__ModuleLoader__.load({
1316
1324
  event.dataTransfer.effectAllowed = 'move'
1317
1325
  event.dataTransfer.setData('text/plain', workspace.workspaceId)
1318
1326
  } catch { /* drag payload is best-effort */ }
1319
- setDrag({ kind: 'workspace', source: { workspaceId: workspace.workspaceId, leaf: workspace.leaf, folderPath: workspace.folderPath || '' }, over: null })
1327
+ // Drag identity derives from the RAW title, never the displayed leaf:
1328
+ // a compressed single-chain row shows "group/workspace" as its leaf with
1329
+ // folderPath '' — carrying that would make move-into / cross-folder
1330
+ // drops rebuild titles like "x/group/workspace". The real leaf and
1331
+ // folder keep every drop target's rename correct.
1332
+ const segs = splitTitleSegs(workspace.title)
1333
+ const sourceLeaf = segs.length > 0 ? segs[segs.length - 1] : (workspace.leaf || String(workspace.workspaceId))
1334
+ const sourceFolder = segs.length > 1 ? segs.slice(0, -1).join('/') : ''
1335
+ setDrag({ kind: 'workspace', source: { workspaceId: workspace.workspaceId, leaf: sourceLeaf, folderPath: sourceFolder }, over: null })
1320
1336
  },
1321
1337
  onDragEnd: () => setDrag(null),
1322
1338
  onDragOver: (event) => {