dsh-better-workspace 0.7.0 → 0.7.2
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/dsh.plugin.json +1 -1
- package/package.json +3 -2
- package/src/client.js +31 -4
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-better-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"description": "侧边栏工作区层级树:名称中的 / 即虚拟分组(web/前端 · web/后端),添加工作区的目录流附所属分组弹窗,重命名即时重排层级,可新建空分组。Hierarchy tree for the DSH sidebar workspace list.",
|
|
6
6
|
"engines": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-better-workspace",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
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": {
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"LICENSE"
|
|
44
44
|
],
|
|
45
45
|
"scripts": {
|
|
46
|
-
"test": "node --test tests/smoke.mjs"
|
|
46
|
+
"test": "node --test tests/smoke.mjs",
|
|
47
|
+
"version": "node -e \"const fs=require('fs');const m=JSON.parse(fs.readFileSync('dsh.plugin.json','utf8'));const v=JSON.parse(fs.readFileSync('package.json','utf8')).version;m.version=v;fs.writeFileSync('dsh.plugin.json',JSON.stringify(m,null,2)+'\\n')\" && git add dsh.plugin.json"
|
|
47
48
|
},
|
|
48
49
|
"keywords": [
|
|
49
50
|
"dsh",
|
package/src/client.js
CHANGED
|
@@ -1157,6 +1157,12 @@ window.__ModuleLoader__.load({
|
|
|
1157
1157
|
const [customize, setCustomize] = React.useState(null) // { kind, entryKey, name }
|
|
1158
1158
|
const [errorText, setErrorText] = React.useState(null)
|
|
1159
1159
|
const [drag, setDrag] = React.useState(null) // { kind: 'workspace'|'session', source, over } | null
|
|
1160
|
+
// Workspace drags arm their state one frame LATE (see workspaceDragEvents):
|
|
1161
|
+
// arming synchronously re-renders during the dragstart dispatch, the chain
|
|
1162
|
+
// expansion inserts rows above the drag source, the cursor leaves the
|
|
1163
|
+
// source element, and Chromium cancels the whole gesture. dragEnd clears
|
|
1164
|
+
// the timer so a same-tick cancel never leaves a ghost drag behind.
|
|
1165
|
+
const wsDragArmTimer = React.useRef(null)
|
|
1160
1166
|
const normalizedQuery = query.trim().toLowerCase()
|
|
1161
1167
|
const now = Date.now()
|
|
1162
1168
|
|
|
@@ -1306,6 +1312,9 @@ window.__ModuleLoader__.load({
|
|
|
1306
1312
|
}
|
|
1307
1313
|
const dragMatches = (kind) => drag !== null && drag.kind === kind
|
|
1308
1314
|
const canDragWorkspace = typeof insertWorkspaceBefore === 'function'
|
|
1315
|
+
// Session REORDER needs the host insertSessionBefore action; dragging a
|
|
1316
|
+
// session onto a sub-group row (a pure rename) stays available without it.
|
|
1317
|
+
const canReorderSessions = typeof insertSessionBefore === 'function'
|
|
1309
1318
|
|
|
1310
1319
|
/* --------------------- workspace drag & drop -------------------- */
|
|
1311
1320
|
|
|
@@ -1332,9 +1341,20 @@ window.__ModuleLoader__.load({
|
|
|
1332
1341
|
const segs = splitTitleSegs(workspace.title)
|
|
1333
1342
|
const sourceLeaf = segs.length > 0 ? segs[segs.length - 1] : (workspace.leaf || String(workspace.workspaceId))
|
|
1334
1343
|
const sourceFolder = segs.length > 1 ? segs.slice(0, -1).join('/') : ''
|
|
1335
|
-
|
|
1344
|
+
// Deferred by one frame on purpose (Chromium cancels a just-started
|
|
1345
|
+
// drag whose source element is moved out from under the cursor; see
|
|
1346
|
+
// wsDragArmTimer above). By the next frame the gesture has settled
|
|
1347
|
+
// and the chain expansion is an ordinary mid-drag update.
|
|
1348
|
+
if (wsDragArmTimer.current !== null) clearTimeout(wsDragArmTimer.current)
|
|
1349
|
+
wsDragArmTimer.current = setTimeout(() => {
|
|
1350
|
+
wsDragArmTimer.current = null
|
|
1351
|
+
setDrag({ kind: 'workspace', source: { workspaceId: workspace.workspaceId, leaf: sourceLeaf, folderPath: sourceFolder }, over: null })
|
|
1352
|
+
}, 0)
|
|
1353
|
+
},
|
|
1354
|
+
onDragEnd: () => {
|
|
1355
|
+
if (wsDragArmTimer.current !== null) { clearTimeout(wsDragArmTimer.current); wsDragArmTimer.current = null }
|
|
1356
|
+
setDrag(null)
|
|
1336
1357
|
},
|
|
1337
|
-
onDragEnd: () => setDrag(null),
|
|
1338
1358
|
onDragOver: (event) => {
|
|
1339
1359
|
if (!dragMatches('workspace')) return
|
|
1340
1360
|
event.preventDefault()
|
|
@@ -1426,7 +1446,7 @@ window.__ModuleLoader__.load({
|
|
|
1426
1446
|
},
|
|
1427
1447
|
onDragEnd: () => setDrag(null),
|
|
1428
1448
|
onDragOver: (event) => {
|
|
1429
|
-
if (!dragMatches('session') || drag.source.workspaceId !== workspaceId) return
|
|
1449
|
+
if (!dragMatches('session') || !canReorderSessions || drag.source.workspaceId !== workspaceId) return
|
|
1430
1450
|
event.preventDefault()
|
|
1431
1451
|
event.stopPropagation()
|
|
1432
1452
|
try { event.dataTransfer.dropEffect = 'move' } catch { }
|
|
@@ -1436,7 +1456,7 @@ window.__ModuleLoader__.load({
|
|
|
1436
1456
|
: (current ? { ...current, over: { kind: 'session', target: session.id, half } } : current))
|
|
1437
1457
|
},
|
|
1438
1458
|
onDrop: (event) => {
|
|
1439
|
-
if (!dragMatches('session') || drag.source.workspaceId !== workspaceId) return
|
|
1459
|
+
if (!dragMatches('session') || !canReorderSessions || drag.source.workspaceId !== workspaceId) return
|
|
1440
1460
|
event.preventDefault()
|
|
1441
1461
|
event.stopPropagation()
|
|
1442
1462
|
const half = drag.over && drag.over.kind === 'session' && drag.over.target === session.id ? drag.over.half : rowHalf(event)
|
|
@@ -1463,6 +1483,7 @@ window.__ModuleLoader__.load({
|
|
|
1463
1483
|
const commitSessionDrop = (workspaceId, targetSessionId, half) => {
|
|
1464
1484
|
const source = drag.source
|
|
1465
1485
|
setDrag(null)
|
|
1486
|
+
if (!canReorderSessions) return
|
|
1466
1487
|
if (source.sessionId === targetSessionId) return
|
|
1467
1488
|
const workspace = (items || []).find(w => w.workspaceId === workspaceId)
|
|
1468
1489
|
if (!workspace) return
|
|
@@ -2012,6 +2033,12 @@ window.__ModuleLoader__.load({
|
|
|
2012
2033
|
insertWorkspaceBefore: typeof workspaces.insertBefore === 'function'
|
|
2013
2034
|
? (workspaceId, beforeWorkspaceId) => workspaces.insertBefore(workspaceId, beforeWorkspaceId)
|
|
2014
2035
|
: undefined,
|
|
2036
|
+
// Official contract exposes session reorder through the WORKSPACES
|
|
2037
|
+
// service (see dsh ui-workspace client index.ts); feature-probed so
|
|
2038
|
+
// older hosts degrade to "group-move only" instead of a TypeError.
|
|
2039
|
+
insertSessionBefore: typeof workspaces.insertSessionBefore === 'function'
|
|
2040
|
+
? (workspaceId, sessionId, beforeSessionId) => workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId)
|
|
2041
|
+
: undefined,
|
|
2015
2042
|
archiveSession: (sessionId) => uiWorkspace.archiveSession(sessionId),
|
|
2016
2043
|
createWorkspace: (input) => workspaces.create(input),
|
|
2017
2044
|
pickDirectory: () => uiWorkspace.pickDirectory(),
|