dsh-sidebar-row-menu 1.3.5 → 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/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, toast, capture-phase
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` 挂载、toast、`contextmenu` 捕获安装方式。
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
- Menus are rendered with DSH's official `Menu` component, so visuals, positioning,
18
- keyboard navigation and click-outside dismissal match the built-in "…" menus.
19
- The workspace menu is composed by this plugin. Session menu content comes from the
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 three entries
25
- > appear only when the menu is opened by right-click. A right-click menu does not
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 in VS Code | Host opens the workspace directory in a new window |
38
- | Open in Explorer | Host opens the system file manager |
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,22 +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 | Open in VS Code, Open in Explorer |
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 two entries added by this plugin:
54
+ The entries added by this plugin:
54
55
 
55
56
  | Item | Behavior |
56
57
  | --- | --- |
57
- | Open in VS Code | Uses the session's `cwd`, falling back to its workspace directory |
58
- | Open in Explorer | Same as above |
59
-
60
- These two are **right-click only**: they do not mount when the "…" button opens
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
61
70
  the menu. A short-lived window flag is set before opening; outside that window the
62
71
  entries render `null`.
63
72
 
64
73
  Blank draft sessions have no native "…" menu and are left alone. Rows that are
65
74
  neither a workspace nor a session (e.g. "Show more") are not intercepted.
66
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
+
67
102
  ## Install
68
103
 
69
104
  Requirements:
@@ -89,13 +124,13 @@ resolve it directly by name:
89
124
  Pin a version by appending it to the name:
90
125
 
91
126
  ```
92
- dsh-sidebar-row-menu@1.3.5
127
+ dsh-sidebar-row-menu@1.4.0
93
128
  ```
94
129
 
95
130
  Equivalent command line:
96
131
 
97
132
  ```powershell
98
- dsh plugin --profile desktop add dsh-sidebar-row-menu@1.3.5
133
+ dsh plugin --profile desktop add dsh-sidebar-row-menu@1.4.0
99
134
  ```
100
135
 
101
136
  ### Install from GitHub
@@ -115,13 +150,13 @@ repository is already runnable, so **no local build is required**.
115
150
  That URL tracks the latest commit on `main`. Pin a tag for a stable version:
116
151
 
117
152
  ```
118
- https://github.com/TLEWA/dsh-sidebar-row-menu#v1.3.5
153
+ https://github.com/TLEWA/dsh-sidebar-row-menu#v1.4.0
119
154
  ```
120
155
 
121
156
  Or install the tarball built by Actions directly, without Git:
122
157
 
123
158
  ```
124
- https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.3.5/dsh-sidebar-row-menu-1.3.5.tgz
159
+ https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.4.0/dsh-sidebar-row-menu-1.4.0.tgz
125
160
  ```
126
161
 
127
162
  Equivalent command line:
@@ -253,7 +288,8 @@ lib/index.js host entry: name / inject / apply plus re-exported helpers
253
288
  lib/host/security.js loopback request fence
254
289
  lib/host/paths.js path validation, vscode://file encoding
255
290
  lib/host/launch.js VS Code / Explorer launching
256
- lib/host/route.js /open route and HTTP status codes
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)
257
293
  lib/client.js browser half: fiber lookup, slot registration, menu mount
258
294
  cordis.patch.yml bundle patch inserting the plugin into the profile tree
259
295
  scripts/install.ps1 pnpm-free install / uninstall
@@ -287,7 +323,7 @@ party cannot re-layout someone else's slot.
287
323
 
288
324
  Therefore a session right-click does exactly one thing: find the `Menu` in the
289
325
  row's fiber subtree and trigger its anchor (the ellipsis button). The same slot
290
- content opens. The plugin's own three actions are registered through
326
+ content opens. The plugin's own actions are registered through
291
327
  `ctx.slots.inject` + `ctx.slots.register`, so:
292
328
 
293
329
  - they do not depend on built-in fork/pin entries existing;
@@ -295,6 +331,9 @@ content opens. The plugin's own three actions are registered through
295
331
  - no built-in action is copied or hardcoded.
296
332
 
297
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.
298
337
 
299
338
  ### Why the session menu appears at the pointer
300
339
 
@@ -307,15 +346,15 @@ position.
307
346
 
308
347
  The "…" menu and the right-click menu share one `Menu` instance and one slot
309
348
  content; the only difference is the `rightClickMenuUntil` window — the plugin's
310
- three entries mount only inside it, and the window is cleared when the menu closes.
349
+ entries mount only inside it, and the window is cleared when the menu closes.
311
350
 
312
351
  ### Why the workspace menu is mounted imperatively
313
352
 
314
353
  A contextmenu event is not part of React's render flow. The workspace menu creates
315
- a `0×0`, `z-index:2147483647` host on demand, `createRoot`s the official `Menu`
316
- (`portal` plus an explicit `getAnchorRect` pinned to the pointer), and unmounts and
317
- removes the host on close. The session menu mounts nothing new; it only opens the
318
- 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.
319
358
 
320
359
  ### Host route
321
360
 
@@ -332,6 +371,23 @@ row's existing menu.
332
371
  - spawn uses `detached + stdio:'ignore'` and deliberately does **not** set
333
372
  `windowsHide` (otherwise Explorer windows would be hidden).
334
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
+
335
391
  ## Compatibility
336
392
 
337
393
  Built against DSH client `0.2.1-rc.5` (`ProjectRowItem`, `SessionNodeItem`,
@@ -347,16 +403,19 @@ Built against DSH client `0.2.1-rc.5` (`ProjectRowItem`, `SessionNodeItem`,
347
403
  - Session right-click depends on the row's `Menu` staying in the fiber subtree. If
348
404
  it is not found, the plugin clicks the row-actions ellipsis button; failing that
349
405
  it gives up — it never builds a competing menu and never triggers row open.
350
- - Session "delete" is not offered: DSH officially supports archive (recoverable).
351
- Deleting records by force tends to leave orphan data. Archive/unarchive is
352
- handled by the built-in menu entry.
353
- - The VS Code / Explorer directory for a session comes from `sessions.list`'s
354
- `cwd`, falling back to the workspace directory. Ungrouped sessions may have no
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
355
413
  directory; in that case a "no directory available" toast is shown.
356
414
 
357
415
  ## License and notices
358
416
 
359
417
  - Code: [MIT](LICENSE).
418
+ - Changelog: [CHANGELOG.md](CHANGELOG.md).
360
419
  - Third-party code and full license texts: [NOTICE.md](NOTICE.md) · [English](NOTICE.en.md).
361
420
  - AI usage and code provenance: [AI_USAGE.md](AI_USAGE.md) · [English](AI_USAGE.en.md).
362
421
 
package/README.md CHANGED
@@ -12,12 +12,13 @@
12
12
  - **工作区行**:右键弹出菜单(复刻 `dsh-sidebar-context-menu` 的能力);
13
13
  - **工作区下层的会话行**:右键在指针处展开该行内置的「…」菜单,并追加本插件的条目。
14
14
 
15
- 菜单使用 DSH 官方的 `Menu` 组件渲染,视觉、定位、键盘导航和“点外部关闭”都与内置
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
- | 使用 VS Code 打开 | 宿主在新窗口打开该工作区目录 |
32
- | 在资源管理器中打开 | 宿主打开系统文件管理器 |
32
+ | 置顶的打开方式 | 被置顶的应用直接显示在一级菜单(例如「用 Visual Studio Code 打开」),点击后用该应用打开工作区目录 |
33
+ | 打开方式 | 二级菜单列出宿主提供的外部应用(编辑器、终端、文件管理器);与会话菜单共用同一套应用列表、置顶与开关设置,鼠标悬浮自动展开 |
33
34
  | 复制工作区路径 | 复制目录路径到剪贴板 |
34
35
  | 在新标签中打开 | 仅在装有 `dsh-project-tabs`(暴露 `openWorkspaceInTab`)时出现 |
35
36
  | 删除工作区 | 打开官方删除确认对话框 |
@@ -42,21 +43,51 @@
42
43
  | --- | --- |
43
44
  | DSH 内置 | 重命名、分叉会话、置顶 / 取消置顶、归档 / 取消归档、复制 Session ID |
44
45
  | 其他插件 | 它们注册进 `sidebar.workspaces.session.menu.item` 的条目 |
45
- | 本插件 | 使用 VS Code 打开、在资源管理器中打开 |
46
+ | 本插件 | 置顶的打开方式(一级)、打开方式(二级菜单)、永久删除会话 / 删除所有已归档会话(仅已归档会话显示) |
46
47
 
47
- 本插件追加的两个条目:
48
+ 本插件追加的条目:
48
49
 
49
50
  | 菜单项 | 行为 |
50
51
  | --- | --- |
51
- | 使用 VS Code 打开 | 优先用会话自己的 `cwd`,取不到则用所属工作区目录 |
52
- | 在资源管理器中打开 | 同上 |
52
+ | 打开方式 | 二级菜单列出宿主提供的外部应用(编辑器、终端、文件管理器),用会话自己的 `cwd` 打开;取不到时退回所属工作区目录 |
53
+ | 置顶的打开方式 | 被置顶的应用直接显示在一级菜单(例如「用 Visual Studio Code 打开」);未配置时自动置顶检测到的第一个编辑器,没有编辑器则置顶第一个应用。鼠标悬浮到「打开方式」会自动展开二级菜单 |
54
+ | 永久删除会话 | 只在已归档会话的右键菜单里出现;确认后永久删除这一个会话及其日志,不可恢复 |
55
+ | 删除所有已归档会话 | 只在已归档会话的右键菜单里出现;确认后永久删除全部已归档会话及其日志,不可恢复 |
53
56
 
54
- 这两条是**右键专属**:点行尾「…」按钮时它们不挂载。实现上使用一个只在右键展开瞬间
57
+ 「打开方式」的应用列表来自 DSH 内置的 `open-in-app` 路由,与 DSH 自己的「打开方式」
58
+ 能力同源;应用名和图标都由本插件展示,可在设置里逐个隐藏,也可以把常用应用置顶到
59
+ 一级菜单。两个删除入口由本插件自己的宿主路由完成,不会删除未归档会话,
60
+ 也不级联删除 fork 子会话。
61
+
62
+ 这些条目都是**右键专属**:点行尾「…」按钮时它们不挂载。实现上使用一个只在右键展开瞬间
55
63
  有效的窗口标记,窗口外的渲染直接返回 `null`。
56
64
 
57
65
  草稿会话(还没有任何消息的空白会话)没有内置「…」菜单,本插件同样不接管。
58
66
  非工作区 / 非会话的侧边栏行(如“显示更多”)也不会被拦截。
59
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
+
60
91
  ## 安装
61
92
 
62
93
  要求:
@@ -81,13 +112,13 @@
81
112
  要固定版本,在包名后加版本号:
82
113
 
83
114
  ```
84
- dsh-sidebar-row-menu@1.3.5
115
+ dsh-sidebar-row-menu@1.4.0
85
116
  ```
86
117
 
87
118
  命令行等价写法:
88
119
 
89
120
  ```powershell
90
- dsh plugin --profile desktop add dsh-sidebar-row-menu@1.3.5
121
+ dsh plugin --profile desktop add dsh-sidebar-row-menu@1.4.0
91
122
  ```
92
123
 
93
124
  ### 从 GitHub 安装
@@ -107,13 +138,13 @@ DSH 桌面端通过 pnpm 安装 Git 依赖;本仓库的 `lib/` 已是可直接
107
138
  该地址跟随 `main` 的最新提交。要固定版本,在地址后加标签:
108
139
 
109
140
  ```
110
- https://github.com/TLEWA/dsh-sidebar-row-menu#v1.3.5
141
+ https://github.com/TLEWA/dsh-sidebar-row-menu#v1.4.0
111
142
  ```
112
143
 
113
144
  也可以直接安装 Actions 打出的压缩包(不经过 Git):
114
145
 
115
146
  ```
116
- https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.3.5/dsh-sidebar-row-menu-1.3.5.tgz
147
+ https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.4.0/dsh-sidebar-row-menu-1.4.0.tgz
117
148
  ```
118
149
 
119
150
  命令行等价写法:
@@ -228,7 +259,8 @@ lib/index.js 宿主入口:name / inject / apply,再导出可测试
228
259
  lib/host/security.js loopback 请求围栏
229
260
  lib/host/paths.js 路径校验、vscode://file 编码
230
261
  lib/host/launch.js VS Code / 资源管理器启动
231
- lib/host/route.js /open 路由与 HTTP 状态码
262
+ lib/host/route.js /open 与 /session/delete 路由、HTTP 状态码
263
+ lib/host/session-delete.js 会话日志目录的校验与删除(detach / rm / 复查)
232
264
  lib/client.js 客户端半边:fiber 解析、slot 注册、菜单挂载
233
265
  cordis.patch.yml bundle patch:把插件插进 profile 插件树
234
266
  scripts/install.ps1 无 pnpm 的安装 / 卸载脚本
@@ -257,14 +289,16 @@ test/*.test.mjs node:test
257
289
  每个条目只能渲染自己声明过的子 slot,第三方无法直接把手伸进别人的 slot 重新排版。
258
290
 
259
291
  因此会话行右键只做一件事:在行组件的 fiber 子树里找到那个 `Menu`,触发它 anchor
260
- (省略号按钮)的点击,展开的自然是同一份 slot 内容。本插件自己的三个动作也通过
292
+ (省略号按钮)的点击,展开的自然是同一份 slot 内容。本插件自己的动作也通过
261
293
  `ctx.slots.inject` + `ctx.slots.register` 注册进去,所以:
262
294
 
263
295
  - 不依赖「分叉」「置顶」这些内置条目是否存在;
264
296
  - 内置或别的插件以后新增条目,右键菜单自动出现;
265
297
  - 不复制、不硬编码任何内置动作。
266
298
 
267
- 工作区行没有这样的 slot,所以工作区菜单仍由本插件自己组项。
299
+ 工作区行没有这样的 slot,所以工作区菜单仍由本插件自己组项。官方 `Menu` 的
300
+ `items` 只支持单层条目,无法表达子菜单,因此工作区菜单用 `MenuSurface` +
301
+ `MenuItemButton` 自绘:行、图标、危险色和分隔线都复用官方控件,交互与官方菜单一致。
268
302
 
269
303
  ### 为什么会话菜单能贴着鼠标
270
304
 
@@ -274,13 +308,13 @@ test/*.test.mjs node:test
274
308
  方法,不影响按钮菜单的默认位置。
275
309
 
276
310
  「…」按钮菜单与右键菜单共用同一个 `Menu` 实例和同一份 slot 内容,区别只在
277
- `rightClickMenuUntil` 窗口:本插件三条只在窗口内挂载,窗口随菜单关闭一并清零。
311
+ `rightClickMenuUntil` 窗口:本插件条目只在窗口内挂载,窗口随菜单关闭一并清零。
278
312
 
279
313
  ### 为什么菜单是命令式挂载
280
314
 
281
315
  右键事件不是 React 渲染流的一部分。工作区菜单按需创建一个 `0×0`、
282
- `z-index:2147483647` 的容器,`createRoot` 渲染官方 `Menu`(`portal` + 显式
283
- `getAnchorRect` 钉在鼠标位置),关闭时 `unmount()` 并移除容器。会话菜单不挂载任何
316
+ `z-index:2147483647` 的容器,`createRoot` 渲染自绘面板;面板挂载后量一次尺寸,
317
+ 再把左上角夹进视口,避免贴边时被裁掉。关闭时 `unmount()` 并移除容器。会话菜单不挂载任何
284
318
  新容器,只是打开行内已有的官方菜单。
285
319
 
286
320
  ### 宿主路由
@@ -296,6 +330,19 @@ test/*.test.mjs node:test
296
330
  都找不到时退回 `rundll32` 打开 `vscode://file/...`;
297
331
  - spawn 用 `detached + stdio:'ignore'`,不设 `windowsHide`(否则资源管理器窗口会被隐藏)。
298
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
+
299
346
  ## 兼容性
300
347
 
301
348
  按 DSH 客户端 `0.2.1-rc.5` 的 `ProjectRowItem` / `SessionNodeItem` / `Menu` 实现。
@@ -309,14 +356,16 @@ DSH 升级若改动行组件或菜单定位实现:
309
356
  - 依赖 DSH 内置行组件的 props 形状。DSH 升级若改了这两个组件,右键会静默不弹。
310
357
  - 会话右键依赖行内 `Menu` 组件仍在 fiber 子树里。找不到时退回点击行内操作区的
311
358
  省略号按钮,再找不到就放弃 —— 不会自建菜单,也不会误触行的打开动作。
312
- - 本插件不提供会话“删除”:DSH 官方只支持归档,归档后可恢复;强行删记录容易留下
313
- 孤儿数据。会话的归档 / 取消归档由内置菜单条目负责。
314
- - 会话行右键的 VS Code / 资源管理器目录来自 `sessions.list` 的 `cwd`,取不到时退回
359
+ - 永久删除只对**已归档**会话开放;未归档会话仍只能用内置的归档 / 取消归档。删除不会
360
+ 级联删除 fork 出来的子会话,需要时请分别删除。
361
+ - 删除操作直接作用于会话日志目录,宿主没有回收站;确认框里已明确提示不可恢复。
362
+ - 会话行「打开方式」的目录来自 `sessions.list` 的 `cwd`,取不到时退回
315
363
  所属工作区目录;未分组会话可能没有目录,此时会提示“没有可用的目录路径”。
316
364
 
317
365
  ## 许可与声明
318
366
 
319
367
  - 代码:[MIT](LICENSE)。
368
+ - 更新日志:[CHANGELOG.md](CHANGELOG.md)。
320
369
  - 第三方代码引用与许可证全文:[NOTICE.md](NOTICE.md) · [English](NOTICE.en.md)。
321
370
  - AI 使用与代码来源声明:[AI_USAGE.md](AI_USAGE.md) · [English](AI_USAGE.en.md)。
322
371