dsh-sidebar-row-menu 1.3.4 → 1.4.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/AI_USAGE.en.md +2 -2
- package/AI_USAGE.md +2 -2
- package/CHANGELOG.md +69 -0
- package/NOTICE.en.md +2 -2
- package/NOTICE.md +2 -1
- package/README.en.md +90 -32
- package/README.md +73 -25
- package/lib/client.js +1343 -168
- package/lib/host/route.js +87 -6
- package/lib/host/session-delete.js +226 -0
- package/lib/index.js +23 -18
- package/package.json +4 -3
package/AI_USAGE.en.md
CHANGED
|
@@ -70,10 +70,10 @@ Not fully verified:
|
|
|
70
70
|
|
|
71
71
|
- The plugin runs locally and contains **no telemetry, analytics or remote requests**.
|
|
72
72
|
- The client reads workspace/session objects already in DSH's memory (title, `cwd`,
|
|
73
|
-
archived/pinned state) to build menus and copy paths
|
|
73
|
+
archived/pinned state) to build menus and copy paths.
|
|
74
74
|
- The host route accepts loopback requests only and opens **existing absolute
|
|
75
75
|
directories** only.
|
|
76
|
-
- Clipboard writes happen only when you click "Copy path / Copy
|
|
76
|
+
- Clipboard writes happen only when you click "Copy workspace path / Copy Session ID".
|
|
77
77
|
|
|
78
78
|
## 7. Recommendations
|
|
79
79
|
|
package/AI_USAGE.md
CHANGED
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
|
|
62
62
|
- 插件在本地运行,**不包含遥测、统计上报或远程请求**。
|
|
63
63
|
- 客户端只读取 DSH 已渲染到内存中的工作区/会话对象(标题、`cwd`、归档/置顶状态),
|
|
64
|
-
|
|
64
|
+
用于生成菜单与复制路径。
|
|
65
65
|
- 宿主路由只接受本机(loopback)请求,且只打开**已存在的绝对目录**。
|
|
66
|
-
-
|
|
66
|
+
- 剪贴板写入仅发生在你点击“复制工作区路径 / 复制 Session ID”时。
|
|
67
67
|
|
|
68
68
|
## 7. 使用建议
|
|
69
69
|
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.4.0 — 2026-11-03
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Open with** submenu on both workspace and session row menus. The app list comes
|
|
8
|
+
from DSH's built-in `open-in-app` endpoints (`/open-in-app/apps`,
|
|
9
|
+
`/open-in-app/open`, `/open-in-app/icon/<id>`), so it matches the apps DSH itself
|
|
10
|
+
offers. Hovering the row expands the submenu.
|
|
11
|
+
- **Pinned open-with apps**: a pinned app is shown directly at the top level (for
|
|
12
|
+
example "Open with Visual Studio Code"). Until configured, the first detected
|
|
13
|
+
editor is pinned automatically, otherwise the first catalog app. Pinning and
|
|
14
|
+
per-app visibility live in the plugin settings.
|
|
15
|
+
- **Delete session**: permanently deletes one archived session and its transcript.
|
|
16
|
+
The entry only appears on archived sessions.
|
|
17
|
+
- **Delete all archived sessions**: permanently deletes every archived session and
|
|
18
|
+
its transcript, again only from an archived row.
|
|
19
|
+
- **Settings section** ("Row menu") with switches for open with, delete session and
|
|
20
|
+
delete archived sessions, plus per-app visibility and pinning. Settings are stored
|
|
21
|
+
in `localStorage` and apply immediately.
|
|
22
|
+
- **Host route** `POST /dsh-sidebar-row-menu/session/delete` with the same loopback
|
|
23
|
+
fence as the open route; it stops a running session, detaches it, removes the
|
|
24
|
+
transcript directory after verifying its name, then clears archive/pin state and
|
|
25
|
+
emits `api-session/removed`.
|
|
26
|
+
- **Coexistence detection** with `dsh-session-menu`: when it is installed and owns a
|
|
27
|
+
matching entry (`session-menu-open-with`, `session-menu-delete`,
|
|
28
|
+
`session-menu-delete-archived`), the duplicate entry from this plugin is hidden and
|
|
29
|
+
the settings row explains the conflict.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- The workspace row menu is now drawn with `MenuSurface` + `MenuItemButton`, sharing
|
|
34
|
+
the same open-with submenu, app catalog and pinning as the session menu. The old
|
|
35
|
+
flat "Open in VS Code" / "Open in Explorer" items were replaced.
|
|
36
|
+
- Session row entries are now "pinned app" + "Open with" + archived-session deletion
|
|
37
|
+
instead of the flat VS Code / Explorer items.
|
|
38
|
+
- Group separators are back in both menus.
|
|
39
|
+
- Custom submenu panels use `role="group"` so meow-memory's `[role="menu"]` injection
|
|
40
|
+
does not add a fake "memory participation" row inside them.
|
|
41
|
+
|
|
42
|
+
### Notes
|
|
43
|
+
|
|
44
|
+
- Permanent deletion is irreversible. It only applies to archived sessions, does not
|
|
45
|
+
cascade to forked child sessions, and there is no recycle bin.
|
|
46
|
+
- The open-with feature needs DSH with the built-in `open-in-app` routes; on hosts
|
|
47
|
+
without them the submenu shows an "apps unavailable" hint.
|
|
48
|
+
|
|
49
|
+
### 中文摘要
|
|
50
|
+
|
|
51
|
+
- 工作区 / 会话右键菜单新增「打开方式」二级菜单(复用 DSH 内置 `open-in-app` 应用列表),
|
|
52
|
+
常用应用可置顶到一级菜单,默认自动置顶第一个编辑器。
|
|
53
|
+
- 已归档会话新增「永久删除会话」和「删除所有已归档会话」,由本插件宿主路由完成,
|
|
54
|
+
不级联删除 fork 子会话,无回收站。
|
|
55
|
+
- 设置 →「行菜单」新增各项开关、应用逐个显隐与置顶。
|
|
56
|
+
- 与 `dsh-session-menu` 共存时自动隐藏重复条目,并在设置里说明冲突。
|
|
57
|
+
- 工作区菜单改为 `MenuSurface` + `MenuItemButton` 自绘以支持子菜单,恢复分组分隔线。
|
|
58
|
+
|
|
59
|
+
## 1.3.5
|
|
60
|
+
|
|
61
|
+
- Release 1.3.5. See the GitHub release notes for details.
|
|
62
|
+
|
|
63
|
+
## 1.3.4
|
|
64
|
+
|
|
65
|
+
- Use the official toast for copy feedback and remove the redundant session-link item.
|
|
66
|
+
|
|
67
|
+
## 1.3.3
|
|
68
|
+
|
|
69
|
+
- Prime the row action pointer so menu extensions render in the first frame.
|
package/NOTICE.en.md
CHANGED
|
@@ -17,8 +17,8 @@ adapted portions; all remaining code is copyright its contributors.
|
|
|
17
17
|
detection, `vscode://file` encoding (now split across
|
|
18
18
|
`lib/host/security.js`, `lib/host/launch.js`, `lib/host/paths.js`,
|
|
19
19
|
`lib/host/route.js`);
|
|
20
|
-
- client: fiber lookup, official `Menu` mounting,
|
|
21
|
-
`contextmenu` installation.
|
|
20
|
+
- client: fiber lookup, official `Menu` mounting, `MenuSurface`/`MenuItemButton`
|
|
21
|
+
drawn rows, toast, capture-phase `contextmenu` installation.
|
|
22
22
|
|
|
23
23
|
## dsh-workspace-menu
|
|
24
24
|
|
package/NOTICE.md
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
- 宿主:loopback 围栏、JSON 请求体读取、detached spawn、VS Code 启动器探测、
|
|
16
16
|
`vscode://file` 编码(现拆分在 `lib/host/security.js`、`lib/host/launch.js`、
|
|
17
17
|
`lib/host/paths.js`、`lib/host/route.js`);
|
|
18
|
-
- 客户端:fiber 解析、官方 `Menu`
|
|
18
|
+
- 客户端:fiber 解析、官方 `Menu` 挂载、`MenuSurface`/`MenuItemButton` 自绘行、
|
|
19
|
+
toast、`contextmenu` 捕获安装方式。
|
|
19
20
|
|
|
20
21
|
## dsh-workspace-menu
|
|
21
22
|
|
package/README.en.md
CHANGED
|
@@ -14,15 +14,16 @@ Right-click menus for the sidebar of [DeepSeek Harness](https://github.com/deeps
|
|
|
14
14
|
- **Session rows nested under a workspace** — right-click opens that row's native
|
|
15
15
|
"…" menu at the pointer, with the plugin's own entries appended.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
The workspace menu is drawn with DSH's official `MenuSurface` + `MenuItemButton`
|
|
18
|
+
(the official `Menu` cannot nest submenus), so rows, icons, danger color and group
|
|
19
|
+
separators reuse the built-in look, and keyboard navigation plus click-outside
|
|
20
|
+
dismissal match the native menus. Session menu content comes from the
|
|
20
21
|
`sidebar.workspaces.session.menu.item` slot — built-in actions and other plugins'
|
|
21
22
|
actions are all there. This plugin only appends its own entries; it does not copy
|
|
22
23
|
or hardcode any built-in action.
|
|
23
24
|
|
|
24
|
-
> The "…" button menu stays exactly as DSH ships it. The plugin's
|
|
25
|
-
>
|
|
25
|
+
> The "…" button menu stays exactly as DSH ships it. The plugin's entries appear
|
|
26
|
+
> only when the menu is opened by right-click. A right-click menu does not
|
|
26
27
|
> close when the pointer leaves it (same as the workspace menu); it closes only on
|
|
27
28
|
> an outside click, an item selection, or Escape.
|
|
28
29
|
|
|
@@ -34,8 +35,8 @@ or hardcode any built-in action.
|
|
|
34
35
|
| --- | --- |
|
|
35
36
|
| New session | Expands the workspace and starts a session (same as the row's `+`) |
|
|
36
37
|
| Rename | Opens the official "Rename workspace" dialog |
|
|
37
|
-
| Open
|
|
38
|
-
| Open
|
|
38
|
+
| Pinned open-with app | A pinned app shows directly at the top level (e.g. "Open with Visual Studio Code") and opens the workspace directory |
|
|
39
|
+
| Open with | A submenu of external apps (editors, terminals, file managers) sharing the session menu's catalog, pinning and toggles; hover expands it |
|
|
39
40
|
| Copy workspace path | Copies the directory path |
|
|
40
41
|
| Open in new tab | Only when `dsh-project-tabs` (exposing `openWorkspaceInTab`) is installed |
|
|
41
42
|
| Delete workspace | Opens the official delete confirmation |
|
|
@@ -48,23 +49,56 @@ Right-click does not build a second menu; it opens the row's own "…" menu:
|
|
|
48
49
|
| --- | --- |
|
|
49
50
|
| DSH built-ins | Rename, Fork session, Pin / Unpin, Archive / Unarchive, Copy Session ID |
|
|
50
51
|
| Other plugins | Whatever they register into `sidebar.workspaces.session.menu.item` |
|
|
51
|
-
| This plugin |
|
|
52
|
+
| This plugin | Pinned open-with apps (top level), Open with (submenu), Delete session / Delete all archived sessions (archived rows only) |
|
|
52
53
|
|
|
53
|
-
The
|
|
54
|
+
The entries added by this plugin:
|
|
54
55
|
|
|
55
56
|
| Item | Behavior |
|
|
56
57
|
| --- | --- |
|
|
57
|
-
| Open
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
| Open with | A submenu of external apps provided by the host (editors, terminals, file managers) opening the session's `cwd`; falls back to its workspace directory. Hovering the row expands the submenu |
|
|
59
|
+
| Pinned open-with app | A pinned app shows directly at the top level (e.g. "Open with Visual Studio Code"). Until configured, the first detected editor is pinned automatically, otherwise the first catalog app |
|
|
60
|
+
| Delete session | Only on archived sessions; permanently deletes that one session and its transcript after confirmation |
|
|
61
|
+
| Delete all archived sessions | Only on archived sessions; permanently deletes every archived session and its transcript after confirmation |
|
|
62
|
+
|
|
63
|
+
The "Open with" catalog comes from DSH's built-in `open-in-app` routes, so it is the
|
|
64
|
+
same source DSH itself uses; labels and icons are rendered by this plugin, each app
|
|
65
|
+
can be hidden in Settings, and frequently used apps can be pinned to the top level.
|
|
66
|
+
Both delete entries are served by this plugin's own host route. They never
|
|
67
|
+
touch unarchived sessions and do not cascade into forked child sessions.
|
|
68
|
+
|
|
69
|
+
These entries are **right-click only**: they do not mount when the "…" button opens
|
|
62
70
|
the menu. A short-lived window flag is set before opening; outside that window the
|
|
63
71
|
entries render `null`.
|
|
64
72
|
|
|
65
73
|
Blank draft sessions have no native "…" menu and are left alone. Rows that are
|
|
66
74
|
neither a workspace nor a session (e.g. "Show more") are not intercepted.
|
|
67
75
|
|
|
76
|
+
### Settings
|
|
77
|
+
|
|
78
|
+
Settings → "Row menu" toggles every new entry:
|
|
79
|
+
|
|
80
|
+
| Switch | Effect |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| Open with | Hides "Open with" and every pinned app from workspace and session menus |
|
|
83
|
+
| Open with → applications | Hides individual applications; the adjacent "Pin" button promotes an app to the top level |
|
|
84
|
+
| Delete session | Hides the single-session delete entry on archived rows |
|
|
85
|
+
| Delete all archived sessions | Hides the bulk-delete entry |
|
|
86
|
+
|
|
87
|
+
Switches live in browser `localStorage` (`dsh.sidebar-row-menu.items.v1`,
|
|
88
|
+
`dsh.sidebar-row-menu.open-with.v1` and `dsh.sidebar-row-menu.open-with.pinned.v1`)
|
|
89
|
+
and apply immediately. Before the first explicit pin, the plugin derives one: the
|
|
90
|
+
first detected editor (usually VS Code), or the first catalog app when no editor
|
|
91
|
+
exists.
|
|
92
|
+
|
|
93
|
+
### Coexistence with dsh-session-menu
|
|
94
|
+
|
|
95
|
+
When [`dsh-session-menu`](https://github.com/big-head-pigeon/dsh-session-menu) is
|
|
96
|
+
installed, this plugin looks for its `session-menu-open-with` /
|
|
97
|
+
`session-menu-delete` / `session-menu-delete-archived` entries in the session menu slot. If present, the
|
|
98
|
+
matching entries here are hidden and the settings switches are disabled with a
|
|
99
|
+
"provided by dsh-session-menu" hint. No configuration of the other plugin is read
|
|
100
|
+
or changed.
|
|
101
|
+
|
|
68
102
|
## Install
|
|
69
103
|
|
|
70
104
|
Requirements:
|
|
@@ -90,13 +124,13 @@ resolve it directly by name:
|
|
|
90
124
|
Pin a version by appending it to the name:
|
|
91
125
|
|
|
92
126
|
```
|
|
93
|
-
dsh-sidebar-row-menu@1.
|
|
127
|
+
dsh-sidebar-row-menu@1.4.0
|
|
94
128
|
```
|
|
95
129
|
|
|
96
130
|
Equivalent command line:
|
|
97
131
|
|
|
98
132
|
```powershell
|
|
99
|
-
dsh plugin --profile desktop add dsh-sidebar-row-menu@1.
|
|
133
|
+
dsh plugin --profile desktop add dsh-sidebar-row-menu@1.4.0
|
|
100
134
|
```
|
|
101
135
|
|
|
102
136
|
### Install from GitHub
|
|
@@ -116,13 +150,13 @@ repository is already runnable, so **no local build is required**.
|
|
|
116
150
|
That URL tracks the latest commit on `main`. Pin a tag for a stable version:
|
|
117
151
|
|
|
118
152
|
```
|
|
119
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.
|
|
153
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.4.0
|
|
120
154
|
```
|
|
121
155
|
|
|
122
156
|
Or install the tarball built by Actions directly, without Git:
|
|
123
157
|
|
|
124
158
|
```
|
|
125
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.
|
|
159
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.4.0/dsh-sidebar-row-menu-1.4.0.tgz
|
|
126
160
|
```
|
|
127
161
|
|
|
128
162
|
Equivalent command line:
|
|
@@ -244,8 +278,8 @@ loopback checks, route status codes) and the client module (module id, exports,
|
|
|
244
278
|
dependency whitelist, listener install/uninstall, slot registry). Integration
|
|
245
279
|
tests use a fake `__reactFiber$`, DOM and `Menu` host to assert workspace menu
|
|
246
280
|
ordering, session right-click delegating to the native menu, blank rows being
|
|
247
|
-
skipped, and
|
|
248
|
-
a manual check in a running GUI.
|
|
281
|
+
skipped, and the success toast shown when copying a workspace path. Real fibers and
|
|
282
|
+
services still need a manual check in a running GUI.
|
|
249
283
|
|
|
250
284
|
Layout:
|
|
251
285
|
|
|
@@ -254,7 +288,8 @@ lib/index.js host entry: name / inject / apply plus re-exported helpers
|
|
|
254
288
|
lib/host/security.js loopback request fence
|
|
255
289
|
lib/host/paths.js path validation, vscode://file encoding
|
|
256
290
|
lib/host/launch.js VS Code / Explorer launching
|
|
257
|
-
lib/host/route.js /open
|
|
291
|
+
lib/host/route.js /open and /session/delete routes, HTTP status codes
|
|
292
|
+
lib/host/session-delete.js transcript verification and deletion (detach / rm / re-check)
|
|
258
293
|
lib/client.js browser half: fiber lookup, slot registration, menu mount
|
|
259
294
|
cordis.patch.yml bundle patch inserting the plugin into the profile tree
|
|
260
295
|
scripts/install.ps1 pnpm-free install / uninstall
|
|
@@ -288,7 +323,7 @@ party cannot re-layout someone else's slot.
|
|
|
288
323
|
|
|
289
324
|
Therefore a session right-click does exactly one thing: find the `Menu` in the
|
|
290
325
|
row's fiber subtree and trigger its anchor (the ellipsis button). The same slot
|
|
291
|
-
content opens. The plugin's own
|
|
326
|
+
content opens. The plugin's own actions are registered through
|
|
292
327
|
`ctx.slots.inject` + `ctx.slots.register`, so:
|
|
293
328
|
|
|
294
329
|
- they do not depend on built-in fork/pin entries existing;
|
|
@@ -296,6 +331,9 @@ content opens. The plugin's own three actions are registered through
|
|
|
296
331
|
- no built-in action is copied or hardcoded.
|
|
297
332
|
|
|
298
333
|
Workspace rows have no such slot, so their menu is still composed by this plugin.
|
|
334
|
+
The official `Menu` accepts only a flat `items` list and cannot express submenus, so
|
|
335
|
+
the workspace menu is drawn with `MenuSurface` + `MenuItemButton`: rows, icons,
|
|
336
|
+
danger styling and separators reuse the official controls.
|
|
299
337
|
|
|
300
338
|
### Why the session menu appears at the pointer
|
|
301
339
|
|
|
@@ -308,15 +346,15 @@ position.
|
|
|
308
346
|
|
|
309
347
|
The "…" menu and the right-click menu share one `Menu` instance and one slot
|
|
310
348
|
content; the only difference is the `rightClickMenuUntil` window — the plugin's
|
|
311
|
-
|
|
349
|
+
entries mount only inside it, and the window is cleared when the menu closes.
|
|
312
350
|
|
|
313
351
|
### Why the workspace menu is mounted imperatively
|
|
314
352
|
|
|
315
353
|
A contextmenu event is not part of React's render flow. The workspace menu creates
|
|
316
|
-
a `0×0`, `z-index:2147483647` host on demand
|
|
317
|
-
|
|
318
|
-
removes the host on close. The session menu mounts nothing new; it only opens
|
|
319
|
-
row's existing menu.
|
|
354
|
+
a `0×0`, `z-index:2147483647` host on demand and `createRoot`s a self-drawn panel;
|
|
355
|
+
after mount it measures once and clamps its corner into the viewport, then unmounts
|
|
356
|
+
and removes the host on close. The session menu mounts nothing new; it only opens
|
|
357
|
+
the row's existing menu.
|
|
320
358
|
|
|
321
359
|
### Host route
|
|
322
360
|
|
|
@@ -333,6 +371,23 @@ row's existing menu.
|
|
|
333
371
|
- spawn uses `detached + stdio:'ignore'` and deliberately does **not** set
|
|
334
372
|
`windowsHide` (otherwise Explorer windows would be hidden).
|
|
335
373
|
|
|
374
|
+
`POST /dsh-sidebar-row-menu/session/delete`, body `{ sessionIds: string[] }`.
|
|
375
|
+
|
|
376
|
+
- same loopback / POST / exact path / 64 KB body checks; `sessionIds` must be a
|
|
377
|
+
non-empty array of non-empty strings, at most 500;
|
|
378
|
+
- sequential deletion: cancel a running session, detach a live one, then locate the
|
|
379
|
+
transcript directory through `sessionPersistence.locate()`; the directory's
|
|
380
|
+
basename must equal the session id or deletion is refused (no parent-directory
|
|
381
|
+
misfires);
|
|
382
|
+
- after deleting, the directory is re-checked three times to ensure it did not come
|
|
383
|
+
back, then the `workspaceRegistry` archive/pin records are cleared and
|
|
384
|
+
`api-session/removed` is emitted;
|
|
385
|
+
- partial failures return `200` + `{ ok:false, deleted, failed, error }`; the dialog
|
|
386
|
+
stays open and reports the counts.
|
|
387
|
+
|
|
388
|
+
"Open with" does not touch this plugin's host: it calls DSH's built-in
|
|
389
|
+
`open-in-app/apps`, `open-in-app/open` and `open-in-app/icon/<id>` directly.
|
|
390
|
+
|
|
336
391
|
## Compatibility
|
|
337
392
|
|
|
338
393
|
Built against DSH client `0.2.1-rc.5` (`ProjectRowItem`, `SessionNodeItem`,
|
|
@@ -348,16 +403,19 @@ Built against DSH client `0.2.1-rc.5` (`ProjectRowItem`, `SessionNodeItem`,
|
|
|
348
403
|
- Session right-click depends on the row's `Menu` staying in the fiber subtree. If
|
|
349
404
|
it is not found, the plugin clicks the row-actions ellipsis button; failing that
|
|
350
405
|
it gives up — it never builds a competing menu and never triggers row open.
|
|
351
|
-
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
-
|
|
355
|
-
|
|
406
|
+
- Permanent deletion is offered for **archived** sessions only; unarchived sessions
|
|
407
|
+
still use the built-in archive/unarchive. Deletion does not cascade into forked
|
|
408
|
+
child sessions — delete those separately when needed.
|
|
409
|
+
- Deletion works directly on the transcript directory; the host has no trash bin.
|
|
410
|
+
The confirmation dialog states that it cannot be undone.
|
|
411
|
+
- The open-with directory for a session comes from `sessions.list`'s `cwd`,
|
|
412
|
+
falling back to the workspace directory. Ungrouped sessions may have no
|
|
356
413
|
directory; in that case a "no directory available" toast is shown.
|
|
357
414
|
|
|
358
415
|
## License and notices
|
|
359
416
|
|
|
360
417
|
- Code: [MIT](LICENSE).
|
|
418
|
+
- Changelog: [CHANGELOG.md](CHANGELOG.md).
|
|
361
419
|
- Third-party code and full license texts: [NOTICE.md](NOTICE.md) · [English](NOTICE.en.md).
|
|
362
420
|
- AI usage and code provenance: [AI_USAGE.md](AI_USAGE.md) · [English](AI_USAGE.en.md).
|
|
363
421
|
|
package/README.md
CHANGED
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
- **工作区行**:右键弹出菜单(复刻 `dsh-sidebar-context-menu` 的能力);
|
|
13
13
|
- **工作区下层的会话行**:右键在指针处展开该行内置的「…」菜单,并追加本插件的条目。
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
工作区菜单用 DSH 官方的 `MenuSurface` + `MenuItemButton` 自绘(官方 `Menu` 的条目不支持
|
|
16
|
+
子菜单),视觉、行高、图标、危险色与分组分隔线都复用官方控件,键盘导航和“点外部关闭”
|
|
17
|
+
与内置菜单一致。会话菜单的内容来自
|
|
17
18
|
`sidebar.workspaces.session.menu.item` slot —— 内置动作和其他插件的动作都在里面,
|
|
18
19
|
本插件只追加自己的条目,不复制、不硬编码任何内置动作。
|
|
19
20
|
|
|
20
|
-
> 点行尾「…」按钮看到的菜单保持 DSH
|
|
21
|
+
> 点行尾「…」按钮看到的菜单保持 DSH 原样;本插件自己的条目只在右键展开时出现。
|
|
21
22
|
> 右键展开的菜单不会因为鼠标移出而关闭(与工作区右键一致),只有点击外部、选中条目或按 Esc 才关闭。
|
|
22
23
|
|
|
23
24
|
## 功能
|
|
@@ -28,8 +29,8 @@
|
|
|
28
29
|
| --- | --- |
|
|
29
30
|
| 新会话 | 展开该工作区并新建会话(等价于行尾 `+`) |
|
|
30
31
|
| 重命名 | 打开官方“重命名工作区”对话框 |
|
|
31
|
-
|
|
|
32
|
-
|
|
|
32
|
+
| 置顶的打开方式 | 被置顶的应用直接显示在一级菜单(例如「用 Visual Studio Code 打开」),点击后用该应用打开工作区目录 |
|
|
33
|
+
| 打开方式 | 二级菜单列出宿主提供的外部应用(编辑器、终端、文件管理器);与会话菜单共用同一套应用列表、置顶与开关设置,鼠标悬浮自动展开 |
|
|
33
34
|
| 复制工作区路径 | 复制目录路径到剪贴板 |
|
|
34
35
|
| 在新标签中打开 | 仅在装有 `dsh-project-tabs`(暴露 `openWorkspaceInTab`)时出现 |
|
|
35
36
|
| 删除工作区 | 打开官方删除确认对话框 |
|
|
@@ -42,22 +43,51 @@
|
|
|
42
43
|
| --- | --- |
|
|
43
44
|
| DSH 内置 | 重命名、分叉会话、置顶 / 取消置顶、归档 / 取消归档、复制 Session ID |
|
|
44
45
|
| 其他插件 | 它们注册进 `sidebar.workspaces.session.menu.item` 的条目 |
|
|
45
|
-
| 本插件 |
|
|
46
|
+
| 本插件 | 置顶的打开方式(一级)、打开方式(二级菜单)、永久删除会话 / 删除所有已归档会话(仅已归档会话显示) |
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
本插件追加的条目:
|
|
48
49
|
|
|
49
50
|
| 菜单项 | 行为 |
|
|
50
51
|
| --- | --- |
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
52
|
+
| 打开方式 | 二级菜单列出宿主提供的外部应用(编辑器、终端、文件管理器),用会话自己的 `cwd` 打开;取不到时退回所属工作区目录 |
|
|
53
|
+
| 置顶的打开方式 | 被置顶的应用直接显示在一级菜单(例如「用 Visual Studio Code 打开」);未配置时自动置顶检测到的第一个编辑器,没有编辑器则置顶第一个应用。鼠标悬浮到「打开方式」会自动展开二级菜单 |
|
|
54
|
+
| 永久删除会话 | 只在已归档会话的右键菜单里出现;确认后永久删除这一个会话及其日志,不可恢复 |
|
|
55
|
+
| 删除所有已归档会话 | 只在已归档会话的右键菜单里出现;确认后永久删除全部已归档会话及其日志,不可恢复 |
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
「打开方式」的应用列表来自 DSH 内置的 `open-in-app` 路由,与 DSH 自己的「打开方式」
|
|
58
|
+
能力同源;应用名和图标都由本插件展示,可在设置里逐个隐藏,也可以把常用应用置顶到
|
|
59
|
+
一级菜单。两个删除入口由本插件自己的宿主路由完成,不会删除未归档会话,
|
|
60
|
+
也不级联删除 fork 子会话。
|
|
61
|
+
|
|
62
|
+
这些条目都是**右键专属**:点行尾「…」按钮时它们不挂载。实现上使用一个只在右键展开瞬间
|
|
56
63
|
有效的窗口标记,窗口外的渲染直接返回 `null`。
|
|
57
64
|
|
|
58
65
|
草稿会话(还没有任何消息的空白会话)没有内置「…」菜单,本插件同样不接管。
|
|
59
66
|
非工作区 / 非会话的侧边栏行(如“显示更多”)也不会被拦截。
|
|
60
67
|
|
|
68
|
+
### 设置
|
|
69
|
+
|
|
70
|
+
设置 →「行菜单」里可以开关本插件的每个新增项:
|
|
71
|
+
|
|
72
|
+
| 开关 | 作用 |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| 打开方式 | 关闭后工作区 / 会话菜单里不再出现「打开方式」和置顶应用 |
|
|
75
|
+
| 打开方式 → 应用 | 逐个隐藏应用;旁边的「置顶」按钮把应用移到一级菜单 |
|
|
76
|
+
| 永久删除会话 | 关闭后已归档会话菜单里不再出现单条删除入口 |
|
|
77
|
+
| 删除所有已归档会话 | 关闭后不再出现批量删除入口 |
|
|
78
|
+
|
|
79
|
+
开关存在浏览器 `localStorage`(`dsh.sidebar-row-menu.items.v1`、
|
|
80
|
+
`dsh.sidebar-row-menu.open-with.v1` 与 `dsh.sidebar-row-menu.open-with.pinned.v1`),
|
|
81
|
+
改完立即生效,不需要重启。置顶项在第一次配置前是自动推导的:优先置顶检测到的第一个
|
|
82
|
+
编辑器(通常是 VS Code),没有编辑器时置顶应用列表里的第一个。
|
|
83
|
+
|
|
84
|
+
### 与 dsh-session-menu 共存
|
|
85
|
+
|
|
86
|
+
同时安装 [`dsh-session-menu`](https://github.com/big-head-pigeon/dsh-session-menu) 时,
|
|
87
|
+
本插件会在会话菜单 slot 里检测对方注册的 `session-menu-open-with` /
|
|
88
|
+
`session-menu-delete` / `session-menu-delete-archived`,命中后自动隐藏自己的同名条目,设置页对应开关置灰并
|
|
89
|
+
提示“已由 dsh-session-menu 提供”。不会改动对方的配置,也不要求对方做任何适配。
|
|
90
|
+
|
|
61
91
|
## 安装
|
|
62
92
|
|
|
63
93
|
要求:
|
|
@@ -82,13 +112,13 @@
|
|
|
82
112
|
要固定版本,在包名后加版本号:
|
|
83
113
|
|
|
84
114
|
```
|
|
85
|
-
dsh-sidebar-row-menu@1.
|
|
115
|
+
dsh-sidebar-row-menu@1.4.0
|
|
86
116
|
```
|
|
87
117
|
|
|
88
118
|
命令行等价写法:
|
|
89
119
|
|
|
90
120
|
```powershell
|
|
91
|
-
dsh plugin --profile desktop add dsh-sidebar-row-menu@1.
|
|
121
|
+
dsh plugin --profile desktop add dsh-sidebar-row-menu@1.4.0
|
|
92
122
|
```
|
|
93
123
|
|
|
94
124
|
### 从 GitHub 安装
|
|
@@ -108,13 +138,13 @@ DSH 桌面端通过 pnpm 安装 Git 依赖;本仓库的 `lib/` 已是可直接
|
|
|
108
138
|
该地址跟随 `main` 的最新提交。要固定版本,在地址后加标签:
|
|
109
139
|
|
|
110
140
|
```
|
|
111
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.
|
|
141
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.4.0
|
|
112
142
|
```
|
|
113
143
|
|
|
114
144
|
也可以直接安装 Actions 打出的压缩包(不经过 Git):
|
|
115
145
|
|
|
116
146
|
```
|
|
117
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.
|
|
147
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.4.0/dsh-sidebar-row-menu-1.4.0.tgz
|
|
118
148
|
```
|
|
119
149
|
|
|
120
150
|
命令行等价写法:
|
|
@@ -219,7 +249,7 @@ npm run build # npm pack(prepack 会先跑 check),产出 .tgz
|
|
|
219
249
|
测试覆盖宿主侧纯函数(路径校验、`vscode://file` 编码、loopback 判定、路由状态码)
|
|
220
250
|
和客户端模块(模块 id、导出、依赖白名单、监听器安装/卸载、slot 注册表),并用伪造的
|
|
221
251
|
`__reactFiber$`、DOM 与 `Menu` 宿主做集成测试:工作区右键的菜单项顺序、会话右键是否
|
|
222
|
-
|
|
252
|
+
展开内置菜单而不是自建菜单、草稿行是否被放过、复制工作区路径的 Toast 反馈都在断言里。
|
|
223
253
|
真实 fiber 与服务仍需在运行中的 GUI 里做人工验证。
|
|
224
254
|
|
|
225
255
|
目录:
|
|
@@ -229,7 +259,8 @@ lib/index.js 宿主入口:name / inject / apply,再导出可测试
|
|
|
229
259
|
lib/host/security.js loopback 请求围栏
|
|
230
260
|
lib/host/paths.js 路径校验、vscode://file 编码
|
|
231
261
|
lib/host/launch.js VS Code / 资源管理器启动
|
|
232
|
-
lib/host/route.js /open
|
|
262
|
+
lib/host/route.js /open 与 /session/delete 路由、HTTP 状态码
|
|
263
|
+
lib/host/session-delete.js 会话日志目录的校验与删除(detach / rm / 复查)
|
|
233
264
|
lib/client.js 客户端半边:fiber 解析、slot 注册、菜单挂载
|
|
234
265
|
cordis.patch.yml bundle patch:把插件插进 profile 插件树
|
|
235
266
|
scripts/install.ps1 无 pnpm 的安装 / 卸载脚本
|
|
@@ -258,14 +289,16 @@ test/*.test.mjs node:test
|
|
|
258
289
|
每个条目只能渲染自己声明过的子 slot,第三方无法直接把手伸进别人的 slot 重新排版。
|
|
259
290
|
|
|
260
291
|
因此会话行右键只做一件事:在行组件的 fiber 子树里找到那个 `Menu`,触发它 anchor
|
|
261
|
-
(省略号按钮)的点击,展开的自然是同一份 slot
|
|
292
|
+
(省略号按钮)的点击,展开的自然是同一份 slot 内容。本插件自己的动作也通过
|
|
262
293
|
`ctx.slots.inject` + `ctx.slots.register` 注册进去,所以:
|
|
263
294
|
|
|
264
295
|
- 不依赖「分叉」「置顶」这些内置条目是否存在;
|
|
265
296
|
- 内置或别的插件以后新增条目,右键菜单自动出现;
|
|
266
297
|
- 不复制、不硬编码任何内置动作。
|
|
267
298
|
|
|
268
|
-
工作区行没有这样的 slot
|
|
299
|
+
工作区行没有这样的 slot,所以工作区菜单仍由本插件自己组项。官方 `Menu` 的
|
|
300
|
+
`items` 只支持单层条目,无法表达子菜单,因此工作区菜单用 `MenuSurface` +
|
|
301
|
+
`MenuItemButton` 自绘:行、图标、危险色和分隔线都复用官方控件,交互与官方菜单一致。
|
|
269
302
|
|
|
270
303
|
### 为什么会话菜单能贴着鼠标
|
|
271
304
|
|
|
@@ -275,13 +308,13 @@ test/*.test.mjs node:test
|
|
|
275
308
|
方法,不影响按钮菜单的默认位置。
|
|
276
309
|
|
|
277
310
|
「…」按钮菜单与右键菜单共用同一个 `Menu` 实例和同一份 slot 内容,区别只在
|
|
278
|
-
`rightClickMenuUntil`
|
|
311
|
+
`rightClickMenuUntil` 窗口:本插件条目只在窗口内挂载,窗口随菜单关闭一并清零。
|
|
279
312
|
|
|
280
313
|
### 为什么菜单是命令式挂载
|
|
281
314
|
|
|
282
315
|
右键事件不是 React 渲染流的一部分。工作区菜单按需创建一个 `0×0`、
|
|
283
|
-
`z-index:2147483647` 的容器,`createRoot`
|
|
284
|
-
|
|
316
|
+
`z-index:2147483647` 的容器,`createRoot` 渲染自绘面板;面板挂载后量一次尺寸,
|
|
317
|
+
再把左上角夹进视口,避免贴边时被裁掉。关闭时 `unmount()` 并移除容器。会话菜单不挂载任何
|
|
285
318
|
新容器,只是打开行内已有的官方菜单。
|
|
286
319
|
|
|
287
320
|
### 宿主路由
|
|
@@ -297,6 +330,19 @@ test/*.test.mjs node:test
|
|
|
297
330
|
都找不到时退回 `rundll32` 打开 `vscode://file/...`;
|
|
298
331
|
- spawn 用 `detached + stdio:'ignore'`,不设 `windowsHide`(否则资源管理器窗口会被隐藏)。
|
|
299
332
|
|
|
333
|
+
`POST /dsh-sidebar-row-menu/session/delete`,body `{ sessionIds: string[] }`。
|
|
334
|
+
|
|
335
|
+
- 同样的 loopback / POST / 路径 / 64 KB body 校验;`sessionIds` 必须是非空字符串数组,
|
|
336
|
+
最多 500 个;
|
|
337
|
+
- 串行删除:先取消运行中的会话、detach 活会话,再按 `sessionPersistence.locate()` 找到
|
|
338
|
+
会话目录;目录 basename 必须与会话 id 完全一致,否则拒绝删除(防误删父目录);
|
|
339
|
+
- 删除后 3 次复查目录没有复活,再清理 `workspaceRegistry` 的归档 / 置顶记录并发出
|
|
340
|
+
`api-session/removed`;
|
|
341
|
+
- 部分失败返回 `200` + `{ ok:false, deleted, failed, error }`,前端保留对话框并显示计数。
|
|
342
|
+
|
|
343
|
+
「打开方式」不经过本插件宿主:直接调用 DSH 内置的 `open-in-app/apps`、
|
|
344
|
+
`open-in-app/open`、`open-in-app/icon/<id>`。
|
|
345
|
+
|
|
300
346
|
## 兼容性
|
|
301
347
|
|
|
302
348
|
按 DSH 客户端 `0.2.1-rc.5` 的 `ProjectRowItem` / `SessionNodeItem` / `Menu` 实现。
|
|
@@ -310,14 +356,16 @@ DSH 升级若改动行组件或菜单定位实现:
|
|
|
310
356
|
- 依赖 DSH 内置行组件的 props 形状。DSH 升级若改了这两个组件,右键会静默不弹。
|
|
311
357
|
- 会话右键依赖行内 `Menu` 组件仍在 fiber 子树里。找不到时退回点击行内操作区的
|
|
312
358
|
省略号按钮,再找不到就放弃 —— 不会自建菜单,也不会误触行的打开动作。
|
|
313
|
-
-
|
|
314
|
-
|
|
315
|
-
-
|
|
359
|
+
- 永久删除只对**已归档**会话开放;未归档会话仍只能用内置的归档 / 取消归档。删除不会
|
|
360
|
+
级联删除 fork 出来的子会话,需要时请分别删除。
|
|
361
|
+
- 删除操作直接作用于会话日志目录,宿主没有回收站;确认框里已明确提示不可恢复。
|
|
362
|
+
- 会话行「打开方式」的目录来自 `sessions.list` 的 `cwd`,取不到时退回
|
|
316
363
|
所属工作区目录;未分组会话可能没有目录,此时会提示“没有可用的目录路径”。
|
|
317
364
|
|
|
318
365
|
## 许可与声明
|
|
319
366
|
|
|
320
367
|
- 代码:[MIT](LICENSE)。
|
|
368
|
+
- 更新日志:[CHANGELOG.md](CHANGELOG.md)。
|
|
321
369
|
- 第三方代码引用与许可证全文:[NOTICE.md](NOTICE.md) · [English](NOTICE.en.md)。
|
|
322
370
|
- AI 使用与代码来源声明:[AI_USAGE.md](AI_USAGE.md) · [English](AI_USAGE.en.md)。
|
|
323
371
|
|