@tobycaimf/dsh-archived-sessions 1.0.0 → 1.0.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/README.en.md +21 -8
- package/README.md +21 -8
- package/assets/screenshot-archived-sessions.png +0 -0
- package/assets/screenshot-batch-mode.png +0 -0
- package/lib/client.js +323 -44
- package/lib/client.js.map +2 -2
- package/lib/index.js +231 -1
- package/lib/index.js.map +2 -2
- package/package.json +2 -2
- package/src/client/index.jsx +333 -63
- package/src/index.js +236 -6
package/README.en.md
CHANGED
|
@@ -2,18 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
> English | [中文](./README.md)
|
|
4
4
|
|
|
5
|
-
> Manage your
|
|
6
|
-
> Archive
|
|
5
|
+
> Manage **all your sessions** in DSH from one place — **Session Manager**.
|
|
6
|
+
> Archive / restore / permanently delete / move to another workspace, with workspace tags and session dates, plus batch actions.
|
|
7
|
+
> Target directories can be an **existing workspace** or a **new path** (auto-created); the new-path mode also supports the **native OS directory picker**, and the settings nav gets a dedicated archive-box icon.
|
|
7
8
|
|
|
8
|
-
A persistent DSH plugin (host + browser halves).
|
|
9
|
+
A persistent DSH plugin (host + browser halves). Under **Settings → 会话管理 (Session Manager)** unify all conversations: archive (hide from sidebar), restore, permanently delete, and relocate between workspaces.
|
|
9
10
|
|
|
10
11
|
## Features
|
|
11
12
|
|
|
12
|
-
- **
|
|
13
|
-
- **Restore**:
|
|
13
|
+
- **Unified panel**: a single Session Manager entry with an **All / Archived** filter; each row shows the title (falls back to the first user message), **archive status** (active / archived), the **session date**, and a **workspace tag** (title or directory name; a dashed "原工作区已删除 / workspace deleted" tag when the original workspace is gone).
|
|
14
|
+
- **Archive / Restore**: archive hides a session from the sidebar; restore unarchives and puts it back into its group.
|
|
14
15
|
- **Permanently delete**: physically removes the session log file + detaches workspace accounting — **irreversible** (asks for confirmation first).
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
16
|
+
- **Move to a workspace**: pick an **existing workspace**, or enter a **new directory path** (auto-created); the new-path mode also lets you open the **native OS directory picker** with a **「浏览…」** button. The session's working directory and log are migrated, and it moves into the corresponding workspace group. Sessions that are currently open must be switched away from first.
|
|
17
|
+
- **Batch multi-select**: select-all / archive selected / restore selected / delete selected (single confirmation for batch delete).
|
|
18
|
+
- **Adaptive UI**: follows the theme tokens (light/dark), stacks vertically on narrow screens; loading / empty / error / busy states, keyboard focus and `prefers-reduced-motion` support; dedicated archive-box nav icon.
|
|
19
|
+
|
|
20
|
+
## Screenshots
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+

|
|
17
25
|
|
|
18
26
|
## Install
|
|
19
27
|
|
|
@@ -29,7 +37,7 @@ git clone https://github.com/TOBYCAI/dsh-archived-sessions.git
|
|
|
29
37
|
dsh plugin --profile desktop add link:/path/to/dsh-archived-sessions
|
|
30
38
|
```
|
|
31
39
|
|
|
32
|
-
> After installing, **restart DSH** (or refresh the page to reload the bundle). Then Settings →
|
|
40
|
+
> After installing, **restart DSH** (or refresh the page to reload the bundle). Then Settings → 会话管理 (Session Manager) becomes available.
|
|
33
41
|
|
|
34
42
|
## Uninstall
|
|
35
43
|
|
|
@@ -57,10 +65,15 @@ lib/client.js pre-built client (ModuleLoader CJS handshake)
|
|
|
57
65
|
| Method | Path | Description |
|
|
58
66
|
|---|---|---|
|
|
59
67
|
| POST | `/archived-sessions/list` | List archived sessions (skips deleted / non-existent ones) |
|
|
68
|
+
| POST | `/archived-sessions/archive` | Archive (hide) a single session |
|
|
69
|
+
| POST | `/archived-sessions/archive-many` | Archive many |
|
|
60
70
|
| POST | `/archived-sessions/restore` | Unarchive a single session |
|
|
61
71
|
| POST | `/archived-sessions/restore-many` | Unarchive many |
|
|
62
72
|
| POST | `/archived-sessions/delete` | Permanently delete a single session (physically removes log, keeps hidden) |
|
|
63
73
|
| POST | `/archived-sessions/delete-many` | Permanently delete many |
|
|
74
|
+
| POST | `/archived-sessions/sessions` | List all sessions (with archived flag) for the Session Manager panel |
|
|
75
|
+
| POST | `/archived-sessions/workspaces` | List available target workspaces |
|
|
76
|
+
| POST | `/archived-sessions/move` | Move a session to a target workspace `{ sessionId, targetPath }` |
|
|
64
77
|
|
|
65
78
|
> On delete the session **stays archived** (is not unarchived), so it won't pop back into the sidebar / "ungrouped"; entries whose log is already gone are skipped.
|
|
66
79
|
> DSH has no official session-delete API; this plugin implements "physically remove log + detach ownership + keep hidden".
|
package/README.md
CHANGED
|
@@ -2,18 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
> [English](./README.en.md) | 中文
|
|
4
4
|
|
|
5
|
-
> DSH
|
|
6
|
-
>
|
|
5
|
+
> DSH 设置面板**「会话管理」**:一个入口统一管理全部会话。
|
|
6
|
+
> 归档 / 恢复 / 彻底删除 / 移动到其他工作区,带工作区标签与会话日期,支持批量。
|
|
7
|
+
> 工作区目录可选「已有」或「新建」,新建支持**系统目录选择**;设置导航带专属归档盒图标。
|
|
7
8
|
|
|
8
|
-
一个 DSH 持久化插件(host + browser 双半)。在 **设置 →
|
|
9
|
+
一个 DSH 持久化插件(host + browser 双半)。在 **设置 → 会话管理** 里统一管理所有会话:归档(从侧栏隐藏)、恢复、彻底删除、移动到其他工作区。
|
|
9
10
|
|
|
10
11
|
## 功能
|
|
11
12
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
13
|
+
- **统一面板**:单一「会话管理」入口,顶部「全部 / 已归档」筛选;每行显示标题(缺失时回退首条用户消息)、**归档状态**(活动 / 已归档)、**会话日期**、**所属工作区标签**(标题或目录名;原工作区已删除时显示「工作区已删 · 目录名」)。
|
|
14
|
+
- **归档 / 恢复**:归档把会话从侧栏隐藏;恢复取消归档放回原分组。
|
|
14
15
|
- **彻底删除**:物理删除会话日志文件 + 解除工作区归属,**不可恢复**(删除前有二次确认)。
|
|
15
|
-
-
|
|
16
|
-
-
|
|
16
|
+
- **移动到工作区**:任选**已有工作区**或**新建目录路径**(自动创建);新建目录支持直接输入路径或点击 **「浏览…」调用系统目录选择窗口**。会话的工作目录与日志会一起迁移,随后滑入对应工作区分组;处于打开状态的会话需先切走。
|
|
17
|
+
- **批量多选**:全选 / 批量归档 / 恢复所选 / 删除所选(批量删除一次二次确认)。
|
|
18
|
+
- **自适应 UI**:深浅色跟随主题 token,窄屏自动纵向堆叠;加载/空/错误/操作中状态齐全;支持键盘焦点、`prefers-reduced-motion`;设置导航左侧为归档盒专属图标。
|
|
19
|
+
|
|
20
|
+
## 截图
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+

|
|
17
25
|
|
|
18
26
|
## 安装
|
|
19
27
|
|
|
@@ -29,7 +37,7 @@ git clone https://github.com/TOBYCAI/dsh-archived-sessions.git
|
|
|
29
37
|
dsh plugin --profile desktop add link:/path/to/dsh-archived-sessions
|
|
30
38
|
```
|
|
31
39
|
|
|
32
|
-
> 装完**重启 DSH**(或刷新页面重新加载 bundle)后,设置 →
|
|
40
|
+
> 装完**重启 DSH**(或刷新页面重新加载 bundle)后,设置 → 会话管理 即可用。
|
|
33
41
|
|
|
34
42
|
## 卸载
|
|
35
43
|
|
|
@@ -57,10 +65,15 @@ lib/client.js 预构建 client(ModuleLoader CJS handshake)
|
|
|
57
65
|
| 方法 | 路径 | 说明 |
|
|
58
66
|
|---|---|---|
|
|
59
67
|
| POST | `/archived-sessions/list` | 列出归档会话(跳过已删除/不存在者) |
|
|
68
|
+
| POST | `/archived-sessions/archive` | 归档(隐藏)单个会话 |
|
|
69
|
+
| POST | `/archived-sessions/archive-many` | 批量归档 |
|
|
60
70
|
| POST | `/archived-sessions/restore` | 取消归档单个 |
|
|
61
71
|
| POST | `/archived-sessions/restore-many` | 批量取消归档 |
|
|
62
72
|
| POST | `/archived-sessions/delete` | 彻底删除单个(物理删日志,保持隐藏) |
|
|
63
73
|
| POST | `/archived-sessions/delete-many` | 批量彻底删除 |
|
|
74
|
+
| POST | `/archived-sessions/sessions` | 列出全部会话(含已归档标记),供「会话管理」面板 |
|
|
75
|
+
| POST | `/archived-sessions/workspaces` | 列出可选目标工作区 |
|
|
76
|
+
| POST | `/archived-sessions/move` | 把会话移动到目标工作区 `{ sessionId, targetPath }` |
|
|
64
77
|
|
|
65
78
|
> 删除时会**保留归档位**(不取消归档),从而不会把会话放回侧栏/未分组;并跳过日志已不存在的条目。
|
|
66
79
|
> DSH 本身没有官方 session 删除接口,本插件是「物理删日志 + 解除归属 + 保持隐藏」的实现。
|
|
Binary file
|
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -45,25 +45,36 @@ var CSS = `
|
|
|
45
45
|
.archv-sub{font-size:12px;line-height:1.55;color:var(--dsw-alias-label-tertiary);margin:0 0 12px;max-width:64ch}
|
|
46
46
|
.archv-err{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);border-radius:10px;color:var(--dsw-alias-state-error-primary);font-size:12px;margin-bottom:10px}
|
|
47
47
|
.archv-errretry{appearance:none;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);background:transparent;color:inherit;border-radius:8px;padding:4px 10px;font-size:11px;cursor:pointer;flex:none}
|
|
48
|
-
.
|
|
48
|
+
.sess-filter{display:flex;align-items:center;gap:6px;margin:0 0 12px}
|
|
49
|
+
.sess-fbtn{appearance:none;min-height:30px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:999px;font-size:12px;font-weight:500;cursor:pointer}
|
|
50
|
+
.sess-fbtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
51
|
+
.sess-fbtn-on{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3)}
|
|
52
|
+
.sess-batch{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 2px 4px;margin-bottom:4px}
|
|
53
|
+
.sess-btntext{font-size:12px;color:var(--dsw-alias-label-tertiary);flex:none}
|
|
49
54
|
.archv-list{display:flex;flex-direction:column;gap:8px}
|
|
50
|
-
.archv-card{display:flex;
|
|
55
|
+
.archv-card{display:flex;flex-direction:column;align-items:stretch;gap:0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-fill-elevated);transition:border-color .15s ease,background-color .15s ease}
|
|
51
56
|
.archv-card:hover{border-color:var(--dsw-alias-border-l4)}
|
|
57
|
+
.archv-card-exp{border-color:var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-1)}
|
|
58
|
+
.archv-row{display:flex;align-items:center;gap:14px;width:100%;min-width:0}
|
|
52
59
|
.archv-main{min-width:0;display:flex;flex-direction:column;gap:4px}
|
|
53
60
|
.archv-name{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
54
61
|
.archv-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0}
|
|
55
62
|
.archv-wtag{display:inline-flex;align-items:center;gap:4px;max-width:100%;font-size:11px;font-weight:500;line-height:1;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:3px 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
56
63
|
.archv-wgone{border-style:dashed;color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 55%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 7%,transparent)}
|
|
64
|
+
.archv-active{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 45%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 8%,transparent)}
|
|
57
65
|
.archv-date{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none}
|
|
58
66
|
.archv-id{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;color:var(--dsw-alias-label-tertiary);flex:none}
|
|
59
67
|
.archv-dot{color:var(--dsw-alias-border-l3);flex:none}
|
|
60
|
-
.archv-
|
|
68
|
+
.archv-check{width:15px;height:15px;accent-color:var(--dsw-alias-state-business-primary);flex:none;cursor:pointer}
|
|
69
|
+
.archv-body{flex:1;min-width:0;display:flex;align-items:center;gap:12px}
|
|
70
|
+
.archv-actions{display:flex;gap:8px;flex:none;flex-wrap:wrap;justify-content:flex-end}
|
|
61
71
|
.archv-btn{appearance:none;min-height:32px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:9px;font-size:12px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:background-color .15s ease,border-color .15s ease,color .15s ease}
|
|
62
72
|
.archv-btn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
63
73
|
.archv-btn:disabled{opacity:.5;cursor:default}
|
|
64
|
-
.archv-restore{min-width:62px;justify-content:center}
|
|
65
74
|
.archv-del{color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent)}
|
|
66
75
|
.archv-del:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary)}
|
|
76
|
+
.archv-go{color:var(--dsw-alias-state-business-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 45%,transparent)}
|
|
77
|
+
.archv-go:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,transparent);color:var(--dsw-alias-state-business-primary)}
|
|
67
78
|
.archv-empty{display:flex;align-items:center;gap:10px;padding:20px 14px;border:1px dashed var(--dsw-alias-border-l3);border-radius:12px;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}
|
|
68
79
|
.archv-skel{display:flex;flex-direction:column;gap:8px}
|
|
69
80
|
.archv-skel-card{height:58px;border-radius:12px;background:var(--dsw-alias-fill-subtle);position:relative;overflow:hidden}
|
|
@@ -74,7 +85,24 @@ var CSS = `
|
|
|
74
85
|
@keyframes archv-rot{to{transform:rotate(360deg)}}
|
|
75
86
|
@keyframes archv-pop{from{opacity:0;transform:translateX(-50%) translateY(10px)}}
|
|
76
87
|
@media (prefers-reduced-motion:reduce){.archv-skel-card::after{animation:none}.archv-card,.archv-btn{transition:none}.archv-status,.archv-spin{animation:none}}
|
|
77
|
-
@media (max-width:
|
|
88
|
+
@media (max-width:640px){.archv-card{flex-direction:column;align-items:stretch;gap:10px}.archv-actions{justify-content:flex-end}}
|
|
89
|
+
.mv-sheet{width:100%;box-sizing:border-box;display:flex;flex-direction:column;gap:12px;margin-top:12px;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-left:3px solid var(--dsw-alias-state-business-primary);border-radius:10px;background:var(--dsw-alias-fill-subtle)}
|
|
90
|
+
.mv-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
|
|
91
|
+
.mv-sheet-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);margin:0}
|
|
92
|
+
.mv-sheet-close{appearance:none;width:26px;height:26px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:7px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1}
|
|
93
|
+
.mv-sheet-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
94
|
+
.mv-seg{display:flex;gap:2px;padding:2px;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;width:100%}
|
|
95
|
+
.mv-segbtn{appearance:none;flex:1;min-height:30px;padding:0 12px;border:none;background:transparent;color:var(--dsw-alias-label-secondary);border-radius:8px;font-size:12px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px}
|
|
96
|
+
.mv-segbtn:hover:not(:disabled){color:var(--dsw-alias-label-primary)}
|
|
97
|
+
.mv-segbtn-on{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);box-shadow:0 1px 2px rgb(0 0 0/.08)}
|
|
98
|
+
.mv-field{display:flex;flex-direction:column;gap:6px}
|
|
99
|
+
.mv-field label.mv-field-label{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}
|
|
100
|
+
.mv-field select,.mv-field input[type=text]{box-sizing:border-box;appearance:none;width:100%;min-height:34px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);font-size:12px;font-family:inherit}
|
|
101
|
+
.mv-field select:focus-visible,.mv-field input[type=text]:focus-visible,.mv-sheet-close:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}
|
|
102
|
+
.mv-browse-row{display:flex;align-items:center;gap:8px}
|
|
103
|
+
.mv-browse-row input[type=text]{flex:1;min-width:0}
|
|
104
|
+
.mv-foot{display:flex;justify-content:flex-end;align-items:center;gap:8px;margin-top:2px}
|
|
105
|
+
@media (max-width:640px){.archv-row{flex-wrap:wrap}.mv-sheet{padding:12px}}
|
|
78
106
|
`;
|
|
79
107
|
function fmtDate(iso) {
|
|
80
108
|
if (!iso) return null;
|
|
@@ -101,12 +129,60 @@ async function postJSON(path, body) {
|
|
|
101
129
|
if (!res.ok || !data) throw new Error(data && (data.error || data.message) || `request failed (${res.status})`);
|
|
102
130
|
return data;
|
|
103
131
|
}
|
|
104
|
-
|
|
105
|
-
|
|
132
|
+
var NAV_CSS = `
|
|
133
|
+
[data-dsh-nav-sessions] > svg:first-child { display: none; }
|
|
134
|
+
[data-dsh-nav-sessions]::before {
|
|
135
|
+
content: ''; flex: none; width: 16px; height: 16px; background: currentColor;
|
|
136
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http://www.w3.org/2000/svg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'2'%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3Cpath%20d%3D'M21%208v13H3V8'/%3E%3Cpath%20d%3D'M1%203h22v5H1z'/%3E%3Cpath%20d%3D'M10%2012h4'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
137
|
+
mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http://www.w3.org/2000/svg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'2'%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3Cpath%20d%3D'M21%208v13H3V8'/%3E%3Cpath%20d%3D'M1%203h22v5H1z'/%3E%3Cpath%20d%3D'M10%2012h4'/%3E%3C/svg%3E") center / contain no-repeat;
|
|
138
|
+
}
|
|
139
|
+
`;
|
|
140
|
+
function markSettingsNav() {
|
|
141
|
+
const LABEL = "\u4F1A\u8BDD\u7BA1\u7406";
|
|
142
|
+
let disposed = false;
|
|
143
|
+
const sync = () => {
|
|
144
|
+
if (disposed) return;
|
|
145
|
+
const buttons = document.querySelectorAll('[role="dialog"] nav button');
|
|
146
|
+
for (const b of buttons) {
|
|
147
|
+
const t = (b.textContent || "").trim();
|
|
148
|
+
if (t === LABEL) b.setAttribute("data-dsh-nav-sessions", "");
|
|
149
|
+
else b.removeAttribute("data-dsh-nav-sessions");
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
sync();
|
|
153
|
+
const obs = new MutationObserver(sync);
|
|
154
|
+
obs.observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
155
|
+
return () => {
|
|
156
|
+
disposed = true;
|
|
157
|
+
obs.disconnect();
|
|
158
|
+
document.querySelectorAll("[data-dsh-nav-sessions]").forEach((e) => e.removeAttribute("data-dsh-nav-sessions"));
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function installSettingsNavIcons(ctx) {
|
|
162
|
+
const styleEl = document.createElement("style");
|
|
163
|
+
styleEl.textContent = NAV_CSS;
|
|
164
|
+
document.head.appendChild(styleEl);
|
|
165
|
+
const dispose = markSettingsNav();
|
|
166
|
+
ctx.effect(() => () => {
|
|
167
|
+
dispose();
|
|
168
|
+
if (styleEl.parentNode) styleEl.parentNode.removeChild(styleEl);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function SessionPanel({ workspacesSvc }) {
|
|
172
|
+
const [sessions, setSessions] = (0, import_react.useState)(null);
|
|
173
|
+
const [workspaces, setWorkspaces] = (0, import_react.useState)([]);
|
|
174
|
+
const [filter, setFilter] = (0, import_react.useState)("all");
|
|
175
|
+
const [selected, setSelected] = (0, import_react.useState)({});
|
|
176
|
+
const [confirmDel, setConfirmDel] = (0, import_react.useState)(null);
|
|
177
|
+
const [confirmBatch, setConfirmBatch] = (0, import_react.useState)(false);
|
|
106
178
|
const [busy, setBusy] = (0, import_react.useState)(null);
|
|
107
|
-
const [
|
|
179
|
+
const [openMove, setOpenMove] = (0, import_react.useState)(null);
|
|
180
|
+
const [moveMode, setMoveMode] = (0, import_react.useState)("existing");
|
|
181
|
+
const [targetWs, setTargetWs] = (0, import_react.useState)("");
|
|
182
|
+
const [newPath, setNewPath] = (0, import_react.useState)("");
|
|
108
183
|
const [error, setError] = (0, import_react.useState)(null);
|
|
109
184
|
const [toast, setToast] = (0, import_react.useState)(null);
|
|
185
|
+
const [picking, setPicking] = (0, import_react.useState)(false);
|
|
110
186
|
const timer = (0, import_react.useRef)(null);
|
|
111
187
|
const showToast = (msg) => {
|
|
112
188
|
if (timer.current) clearTimeout(timer.current);
|
|
@@ -115,7 +191,17 @@ function ArchivedPanel() {
|
|
|
115
191
|
};
|
|
116
192
|
const refresh = () => {
|
|
117
193
|
setError(null);
|
|
118
|
-
|
|
194
|
+
Promise.all([
|
|
195
|
+
postJSON("/archived-sessions/sessions", {}),
|
|
196
|
+
postJSON("/archived-sessions/workspaces", {})
|
|
197
|
+
]).then(([s, works]) => {
|
|
198
|
+
setSessions(s.items || []);
|
|
199
|
+
setWorkspaces(works.items || []);
|
|
200
|
+
setSelected({});
|
|
201
|
+
setConfirmDel(null);
|
|
202
|
+
setConfirmBatch(false);
|
|
203
|
+
if (!targetWs && works.items && works.items.length) setTargetWs(works.items[0].workspaceId);
|
|
204
|
+
}).catch((e) => setError(String(e && e.message || e)));
|
|
119
205
|
};
|
|
120
206
|
(0, import_react.useEffect)(() => {
|
|
121
207
|
refresh();
|
|
@@ -123,29 +209,110 @@ function ArchivedPanel() {
|
|
|
123
209
|
if (timer.current) clearTimeout(timer.current);
|
|
124
210
|
};
|
|
125
211
|
}, []);
|
|
212
|
+
const wsPath = (id) => {
|
|
213
|
+
const w = workspaces.find((x) => x.workspaceId === id);
|
|
214
|
+
return w ? w.path : "";
|
|
215
|
+
};
|
|
216
|
+
const archivedList = sessions ? sessions.filter((x) => x.archived) : [];
|
|
217
|
+
const activeList = sessions ? sessions.filter((x) => !x.archived) : [];
|
|
218
|
+
const list = filter === "archived" ? archivedList : sessions || [];
|
|
219
|
+
const selIds = Object.keys(selected).filter((k) => selected[k]);
|
|
220
|
+
const toggle = (id) => setSelected((s) => ({ ...s, [id]: !s[id] }));
|
|
221
|
+
const clearSel = () => setSelected({});
|
|
222
|
+
const selectAll = () => {
|
|
223
|
+
const o = {};
|
|
224
|
+
list.forEach((x) => {
|
|
225
|
+
o[x.sessionId] = true;
|
|
226
|
+
});
|
|
227
|
+
setSelected(o);
|
|
228
|
+
};
|
|
126
229
|
const act = (action, it) => {
|
|
127
230
|
if (busy) return;
|
|
128
231
|
if (action === "delete") {
|
|
129
|
-
if (
|
|
130
|
-
|
|
232
|
+
if (confirmDel !== it.sessionId) {
|
|
233
|
+
setConfirmDel(it.sessionId);
|
|
131
234
|
return;
|
|
132
235
|
}
|
|
133
|
-
|
|
134
|
-
} else {
|
|
135
|
-
setConfirmId(null);
|
|
136
|
-
setError(null);
|
|
236
|
+
setConfirmDel(null);
|
|
137
237
|
}
|
|
138
238
|
setBusy(it.sessionId);
|
|
139
239
|
postJSON("/archived-sessions/" + action, { sessionId: it.sessionId }).then(() => {
|
|
140
240
|
setBusy(null);
|
|
141
|
-
|
|
241
|
+
const n = it.title || it.sessionId;
|
|
242
|
+
showToast(action === "archive" ? `\u5DF2\u5F52\u6863\u300C${n}\u300D` : action === "restore" ? `\u5DF2\u6062\u590D\u300C${n}\u300D` : `\u5DF2\u5220\u9664 ${n}`);
|
|
142
243
|
refresh();
|
|
143
244
|
}).catch((e) => {
|
|
144
245
|
setBusy(null);
|
|
145
|
-
|
|
246
|
+
setConfirmDel(null);
|
|
146
247
|
setError(String(e && e.message || e));
|
|
147
248
|
});
|
|
148
249
|
};
|
|
250
|
+
const doMove = (it) => {
|
|
251
|
+
const targetPath = moveMode === "new" ? newPath.trim() : wsPath(targetWs);
|
|
252
|
+
if (!targetPath) {
|
|
253
|
+
setError("\u8BF7\u9009\u62E9\u5DF2\u6709\u5DE5\u4F5C\u533A\u6216\u8F93\u5165\u65B0\u7684\u76EE\u6807\u76EE\u5F55\u8DEF\u5F84");
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
setBusy(it.sessionId);
|
|
257
|
+
setError(null);
|
|
258
|
+
postJSON("/archived-sessions/move", { sessionId: it.sessionId, targetPath }).then((r) => {
|
|
259
|
+
setBusy(null);
|
|
260
|
+
setOpenMove(null);
|
|
261
|
+
setMoveMode("existing");
|
|
262
|
+
setNewPath("");
|
|
263
|
+
showToast(`\u5DF2\u628A\u300C${it.title || it.sessionId}\u300D\u79FB\u5230 ${r.workspaceTitle || targetPath}`);
|
|
264
|
+
refresh();
|
|
265
|
+
}).catch((e) => {
|
|
266
|
+
setBusy(null);
|
|
267
|
+
setError(String(e && e.message || e));
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
const doBatch = (action) => {
|
|
271
|
+
if (!selIds.length || busy) return;
|
|
272
|
+
if (action === "delete-many") {
|
|
273
|
+
if (!confirmBatch) {
|
|
274
|
+
setConfirmBatch(true);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
setConfirmBatch(false);
|
|
278
|
+
}
|
|
279
|
+
setBusy("__batch__");
|
|
280
|
+
postJSON("/archived-sessions/" + action, { sessionIds: selIds }).then((r) => {
|
|
281
|
+
setBusy(null);
|
|
282
|
+
const n = r && (r.archived || r.restored || r.deleted) || selIds.length;
|
|
283
|
+
showToast(`\u5DF2\u5904\u7406 ${n} \u4E2A\u4F1A\u8BDD`);
|
|
284
|
+
refresh();
|
|
285
|
+
}).catch((e) => {
|
|
286
|
+
setBusy(null);
|
|
287
|
+
setConfirmBatch(false);
|
|
288
|
+
setError(String(e && e.message || e));
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
const openMoveFor = (it) => {
|
|
292
|
+
if (openMove === it.sessionId) {
|
|
293
|
+
setOpenMove(null);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
setTargetWs(workspaces.length ? targetWs || workspaces[0].workspaceId : "");
|
|
297
|
+
setMoveMode("existing");
|
|
298
|
+
setNewPath("");
|
|
299
|
+
setOpenMove(it.sessionId);
|
|
300
|
+
};
|
|
301
|
+
const pickDirectory = async () => {
|
|
302
|
+
if (!workspacesSvc || picking) return;
|
|
303
|
+
setPicking(true);
|
|
304
|
+
try {
|
|
305
|
+
const p = await workspacesSvc.pickDirectory();
|
|
306
|
+
if (p) {
|
|
307
|
+
setNewPath(p);
|
|
308
|
+
setMoveMode("new");
|
|
309
|
+
}
|
|
310
|
+
} catch (e) {
|
|
311
|
+
setError(String(e && e.message || e));
|
|
312
|
+
} finally {
|
|
313
|
+
setPicking(false);
|
|
314
|
+
}
|
|
315
|
+
};
|
|
149
316
|
const workspaceTag = (it) => {
|
|
150
317
|
if (it.hasWorkspace && it.workspaceGone) {
|
|
151
318
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "archv-wtag archv-wgone", title: (it.workspacePath || "") + "\uFF08\u539F\u5DE5\u4F5C\u533A\u5DF2\u5220\u9664\uFF09", children: [
|
|
@@ -155,51 +322,163 @@ function ArchivedPanel() {
|
|
|
155
322
|
}
|
|
156
323
|
const wName = it.workspaceTitle || pathName(it.workspacePath);
|
|
157
324
|
if (wName) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", title: it.workspacePath || "", children: wName });
|
|
158
|
-
return
|
|
325
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", children: "\u672A\u5206\u7EC4" });
|
|
326
|
+
};
|
|
327
|
+
const rowActions = (it) => {
|
|
328
|
+
if (it.archived) {
|
|
329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-actions", children: [
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-go", disabled: busy !== null, onClick: () => act("restore", it), children: "\u6062\u590D" }),
|
|
331
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-go", disabled: busy !== null, onClick: () => openMoveFor(it), children: openMove === it.sessionId ? "\u6536\u8D77" : "\u79FB\u52A8\u2026" }),
|
|
332
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: busy !== null, onClick: () => act("delete", it), children: confirmDel === it.sessionId ? "\u786E\u8BA4\u5220\u9664?" : "\u5220\u9664" })
|
|
333
|
+
] });
|
|
334
|
+
}
|
|
335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-actions", children: [
|
|
336
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, onClick: () => act("archive", it), children: "\u5F52\u6863" }),
|
|
337
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-go", disabled: busy !== null, onClick: () => openMoveFor(it), children: openMove === it.sessionId ? "\u6536\u8D77" : "\u79FB\u52A8\u2026" })
|
|
338
|
+
] });
|
|
159
339
|
};
|
|
160
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv", role: "region", "aria-label": "\
|
|
340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv", role: "region", "aria-label": "\u4F1A\u8BDD\u7BA1\u7406", children: [
|
|
161
341
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: CSS }),
|
|
162
342
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-head", children: [
|
|
163
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "archv-title", children: "\
|
|
164
|
-
|
|
343
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "archv-title", children: "\u4F1A\u8BDD\u7BA1\u7406" }),
|
|
344
|
+
sessions !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-count", "aria-label": `${sessions.length} \u4E2A\u4F1A\u8BDD`, children: sessions.length })
|
|
165
345
|
] }),
|
|
166
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "archv-sub", children: "\
|
|
346
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "archv-sub", children: "\u7EDF\u4E00\u7BA1\u7406\u5168\u90E8\u4F1A\u8BDD\uFF1A\u5F52\u6863 / \u6062\u590D / \u5F7B\u5E95\u5220\u9664 / \u79FB\u52A8\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A\uFF0C\u652F\u6301\u6279\u91CF\u3002\u5F52\u6863\u4F1A\u4ECE\u4FA7\u680F\u9690\u85CF\uFF1B\u5220\u9664\u4F1A\u5F7B\u5E95\u79FB\u9664\u65E5\u5FD7\uFF0C\u4E0D\u53EF\u6062\u590D\u3002" }),
|
|
167
347
|
error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-err", role: "alert", children: [
|
|
168
348
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: error }),
|
|
169
349
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-errretry", onClick: refresh, children: "\u91CD\u8BD5" })
|
|
170
350
|
] }),
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
wtag,
|
|
182
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-id", children: it.sessionId })
|
|
183
|
-
] })
|
|
351
|
+
sessions === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-skel", "aria-label": "\u52A0\u8F7D\u4E2D", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-skel-card" }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
352
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-filter", role: "tablist", "aria-label": "\u4F1A\u8BDD\u7B5B\u9009", children: [
|
|
353
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "sess-fbtn" + (filter === "all" ? " sess-fbtn-on" : ""), onClick: () => {
|
|
354
|
+
setFilter("all");
|
|
355
|
+
clearSel();
|
|
356
|
+
setConfirmBatch(false);
|
|
357
|
+
}, children: [
|
|
358
|
+
"\u5168\u90E8 (",
|
|
359
|
+
sessions.length,
|
|
360
|
+
")"
|
|
184
361
|
] }),
|
|
185
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
362
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "sess-fbtn" + (filter === "archived" ? " sess-fbtn-on" : ""), onClick: () => {
|
|
363
|
+
setFilter("archived");
|
|
364
|
+
clearSel();
|
|
365
|
+
setConfirmBatch(false);
|
|
366
|
+
}, children: [
|
|
367
|
+
"\u5DF2\u5F52\u6863 (",
|
|
368
|
+
archivedList.length,
|
|
369
|
+
")"
|
|
370
|
+
] })
|
|
371
|
+
] }),
|
|
372
|
+
list.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sess-batch", children: [
|
|
373
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sess-btntext", children: selIds.length ? `\u5DF2\u9009 ${selIds.length} \u9879` : filter === "archived" ? `\u5171 ${archivedList.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD` : `\u5171 ${sessions.length} \u4E2A\u4F1A\u8BDD\uFF08\u6D3B\u52A8 ${activeList.length} / \u5DF2\u5F52\u6863 ${archivedList.length}\uFF09` }),
|
|
374
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: list.length === 0, onClick: selectAll, children: "\u5168\u9009" }),
|
|
375
|
+
selIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
376
|
+
filter === "archived" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
377
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, onClick: () => doBatch("restore-many"), children: "\u6062\u590D\u6240\u9009" }),
|
|
378
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: busy !== null, onClick: () => doBatch("delete-many"), children: confirmBatch ? "\u786E\u8BA4\u5220\u9664\u6240\u9009?" : "\u5220\u9664\u6240\u9009" })
|
|
189
379
|
] }),
|
|
190
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn
|
|
380
|
+
filter === "all" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", disabled: busy !== null, onClick: () => doBatch("archive-many"), children: "\u5F52\u6863\u6240\u9009" }),
|
|
381
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", onClick: clearSel, children: "\u53D6\u6D88\u9009\u62E9" })
|
|
191
382
|
] })
|
|
192
|
-
] },
|
|
193
|
-
|
|
383
|
+
] }),
|
|
384
|
+
list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-empty", children: filter === "archived" ? "\u76EE\u524D\u6CA1\u6709\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u201C\u5168\u90E8\u201D\u91CC\u9009\u4E2D\u4F1A\u8BDD\u70B9\u201C\u5F52\u6863\u201D\u5373\u53EF\u6536\u7EB3\u8FDB\u6765\u3002" : "\u6682\u65E0\u53EF\u7BA1\u7406\u7684\u4F1A\u8BDD\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-list", role: "list", children: list.map((it) => {
|
|
385
|
+
const date = fmtDate(it.createdAt);
|
|
386
|
+
const expanded = openMove === it.sessionId;
|
|
387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-card" + (expanded ? " archv-card-exp" : ""), role: "listitem", children: [
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-row", children: [
|
|
389
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
390
|
+
"input",
|
|
391
|
+
{
|
|
392
|
+
type: "checkbox",
|
|
393
|
+
className: "archv-check",
|
|
394
|
+
checked: !!selected[it.sessionId],
|
|
395
|
+
onChange: () => toggle(it.sessionId),
|
|
396
|
+
"aria-label": "\u9009\u62E9 " + (it.title || it.sessionId)
|
|
397
|
+
}
|
|
398
|
+
),
|
|
399
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-body", children: [
|
|
400
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-main", children: [
|
|
401
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-name", title: it.title || "", children: it.title || "(\u65E0\u6807\u9898)" }),
|
|
402
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-meta", children: [
|
|
403
|
+
it.archived ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag archv-wgone", children: "\u5DF2\u5F52\u6863" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag archv-active", children: "\u6D3B\u52A8" }),
|
|
404
|
+
workspaceTag(it),
|
|
405
|
+
date && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
406
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-dot", children: "\xB7" }),
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-date", children: date })
|
|
408
|
+
] }),
|
|
409
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-id", children: it.sessionId })
|
|
410
|
+
] })
|
|
411
|
+
] }),
|
|
412
|
+
rowActions(it)
|
|
413
|
+
] })
|
|
414
|
+
] }),
|
|
415
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", role: "region", "aria-label": "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A", children: [
|
|
416
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet-head", children: [
|
|
417
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mv-sheet-title", children: "\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A" }),
|
|
418
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "mv-sheet-close", "aria-label": "\u5173\u95ED", onClick: () => setOpenMove(null), children: "\xD7" })
|
|
419
|
+
] }),
|
|
420
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-seg", role: "tablist", children: [
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", role: "tab", "aria-selected": moveMode === "existing", className: "mv-segbtn" + (moveMode === "existing" ? " mv-segbtn-on" : ""), onClick: () => setMoveMode("existing"), children: "\u5DF2\u6709\u5DE5\u4F5C\u533A" }),
|
|
422
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", role: "tab", "aria-selected": moveMode === "new", className: "mv-segbtn" + (moveMode === "new" ? " mv-segbtn-on" : ""), onClick: () => setMoveMode("new"), children: "\u65B0\u5EFA\u76EE\u5F55" })
|
|
423
|
+
] }),
|
|
424
|
+
moveMode === "existing" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-field", children: [
|
|
425
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "mv-field-label", htmlFor: "mv-target-ws", children: "\u76EE\u6807\u5DE5\u4F5C\u533A" }),
|
|
426
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { id: "mv-target-ws", value: targetWs, onChange: (e) => setTargetWs(e.target.value), children: [
|
|
427
|
+
workspaces.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\uFF08\u6682\u65E0\u5DE5\u4F5C\u533A\uFF09" }),
|
|
428
|
+
workspaces.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: w.workspaceId, children: [
|
|
429
|
+
w.title,
|
|
430
|
+
" \xB7 ",
|
|
431
|
+
w.path
|
|
432
|
+
] }, w.workspaceId))
|
|
433
|
+
] })
|
|
434
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-field", children: [
|
|
435
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "mv-field-label", htmlFor: "mv-new-path", children: "\u65B0\u5DE5\u4F5C\u533A\u76EE\u5F55\u8DEF\u5F84" }),
|
|
436
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-browse-row", children: [
|
|
437
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
438
|
+
"input",
|
|
439
|
+
{
|
|
440
|
+
id: "mv-new-path",
|
|
441
|
+
type: "text",
|
|
442
|
+
value: newPath,
|
|
443
|
+
onChange: (e) => setNewPath(e.target.value),
|
|
444
|
+
placeholder: "\u4F8B\u5982 /Users/you/Projects/demo \u6216 ~/demo"
|
|
445
|
+
}
|
|
446
|
+
),
|
|
447
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
448
|
+
"button",
|
|
449
|
+
{
|
|
450
|
+
type: "button",
|
|
451
|
+
className: "archv-btn",
|
|
452
|
+
onClick: pickDirectory,
|
|
453
|
+
disabled: busy !== null || picking || !workspacesSvc,
|
|
454
|
+
title: !workspacesSvc ? "\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u4E0D\u652F\u6301\u7CFB\u7EDF\u76EE\u5F55\u9009\u62E9" : "\u6253\u5F00\u7CFB\u7EDF\u76EE\u5F55\u9009\u62E9\u7A97\u53E3",
|
|
455
|
+
children: picking ? "\u9009\u62E9\u4E2D\u2026" : "\u6D4F\u89C8\u2026"
|
|
456
|
+
}
|
|
457
|
+
)
|
|
458
|
+
] })
|
|
459
|
+
] }),
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-foot", children: [
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn", onClick: () => setOpenMove(null), children: "\u53D6\u6D88" }),
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "archv-btn archv-go", disabled: busy !== null, onClick: () => doMove(it), children: [
|
|
463
|
+
busy === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-spin", "aria-hidden": "true" }),
|
|
464
|
+
"\u786E\u8BA4\u79FB\u52A8"
|
|
465
|
+
] })
|
|
466
|
+
] })
|
|
467
|
+
] })
|
|
468
|
+
] }, it.sessionId);
|
|
469
|
+
}) })
|
|
470
|
+
] }),
|
|
194
471
|
toast && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-status", role: "status", children: toast })
|
|
195
472
|
] });
|
|
196
473
|
}
|
|
197
474
|
function apply(ctx) {
|
|
475
|
+
installSettingsNavIcons(ctx);
|
|
476
|
+
const workspacesSvc = ctx.get("workspaces");
|
|
198
477
|
ctx.slots.inject(
|
|
199
478
|
"settings.section",
|
|
200
479
|
() => ctx.slots.register(
|
|
201
|
-
{ name: "settings.section", id: "
|
|
202
|
-
(props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
480
|
+
{ name: "settings.section", id: "session-manager", order: 90, label: "\u4F1A\u8BDD\u7BA1\u7406" },
|
|
481
|
+
(props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionPanel, { ...props, workspacesSvc })
|
|
203
482
|
)
|
|
204
483
|
);
|
|
205
484
|
}
|