@tobycaimf/dsh-archived-sessions 1.0.1 → 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/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
- .archv-errretry:focus-visible,.archv-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
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;align-items:center;justify-content:space-between;gap:14px;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}
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-actions{display:flex;gap:8px;flex:none}
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:560px){.archv-card{flex-direction:column;align-items:stretch;gap:10px}.archv-actions{justify-content:flex-end}}
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,151 +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
- function ArchivedPanel() {
105
- const [items, setItems] = (0, import_react.useState)(null);
106
- const [busy, setBusy] = (0, import_react.useState)(null);
107
- const [confirmId, setConfirmId] = (0, import_react.useState)(null);
108
- const [error, setError] = (0, import_react.useState)(null);
109
- const [toast, setToast] = (0, import_react.useState)(null);
110
- const timer = (0, import_react.useRef)(null);
111
- const showToast = (msg) => {
112
- if (timer.current) clearTimeout(timer.current);
113
- setToast(msg);
114
- timer.current = setTimeout(() => setToast(null), 2400);
115
- };
116
- const refresh = () => {
117
- setError(null);
118
- postJSON("/archived-sessions/list", {}).then((r) => setItems(r.items || [])).catch((e) => setError(String(e && e.message || e)));
119
- };
120
- (0, import_react.useEffect)(() => {
121
- refresh();
122
- return () => {
123
- if (timer.current) clearTimeout(timer.current);
124
- };
125
- }, []);
126
- const act = (action, it) => {
127
- if (busy) return;
128
- if (action === "delete") {
129
- if (confirmId !== it.sessionId) {
130
- setConfirmId(it.sessionId);
131
- return;
132
- }
133
- setConfirmId(null);
134
- } else {
135
- setConfirmId(null);
136
- setError(null);
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");
137
150
  }
138
- setBusy(it.sessionId);
139
- postJSON("/archived-sessions/" + action, { sessionId: it.sessionId }).then(() => {
140
- setBusy(null);
141
- showToast(action === "restore" ? `\u5DF2\u6062\u590D\u300C${it.title || it.sessionId}\u300D` : `\u5DF2\u5220\u9664 ${it.title || it.sessionId}`);
142
- refresh();
143
- }).catch((e) => {
144
- setBusy(null);
145
- setConfirmId(null);
146
- setError(String(e && e.message || e));
147
- });
148
151
  };
149
- const workspaceTag = (it) => {
150
- if (it.hasWorkspace && it.workspaceGone) {
151
- 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: [
152
- "\u5DE5\u4F5C\u533A\u5DF2\u5220 \xB7 ",
153
- pathName(it.workspacePath) || "?"
154
- ] });
155
- }
156
- const wName = it.workspaceTitle || pathName(it.workspacePath);
157
- if (wName) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", title: it.workspacePath || "", children: wName });
158
- return null;
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
159
  };
160
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv", role: "region", "aria-label": "\u5F52\u6863\u4F1A\u8BDD", children: [
161
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: CSS }),
162
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-head", children: [
163
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "archv-title", children: "\u5F52\u6863\u4F1A\u8BDD" }),
164
- items !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-count", "aria-label": `${items.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD`, children: items.length })
165
- ] }),
166
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "archv-sub", children: "\u88AB\u5F52\u6863\uFF08\u4ECE\u4FA7\u680F\u9690\u85CF\uFF09\u7684\u4F1A\u8BDD\u90FD\u5728\u8FD9\u91CC\u3002\u6062\u590D\u4F1A\u628A\u4F1A\u8BDD\u653E\u56DE\u539F\u5206\u7EC4\uFF1B\u5220\u9664\u4F1A\u5F7B\u5E95\u79FB\u9664\u65E5\u5FD7\u6587\u4EF6\uFF0C\u4E0D\u53EF\u6062\u590D\u3002" }),
167
- error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-err", role: "alert", children: [
168
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: error }),
169
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-errretry", onClick: refresh, children: "\u91CD\u8BD5" })
170
- ] }),
171
- items === 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)) }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-empty", children: "\u76EE\u524D\u6CA1\u6709\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u4FA7\u680F\u4EFB\u4E00\u4F1A\u8BDD\u7684\u83DC\u5355\u91CC\u9009\u62E9\u300C\u5F52\u6863\u300D\u5373\u53EF\u6536\u7EB3\u8FDB\u6765\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-list", role: "list", children: items.map((it) => {
172
- const isConfirm = confirmId === it.sessionId;
173
- const date = fmtDate(it.createdAt);
174
- const wtag = workspaceTag(it);
175
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-card", role: "listitem", children: [
176
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-main", children: [
177
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-name", title: it.title || "", children: it.title || "(\u65E0\u6807\u9898)" }),
178
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-meta", children: [
179
- date && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-date", children: date }),
180
- date && wtag && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-dot", children: "\xB7" }),
181
- wtag,
182
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-id", children: it.sessionId })
183
- ] })
184
- ] }),
185
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-actions", children: [
186
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "archv-btn archv-restore", disabled: busy !== null, "aria-label": "\u6062\u590D " + (it.title || it.sessionId), onClick: () => act("restore", it), children: [
187
- busy === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-spin", "aria-hidden": "true" }),
188
- "\u6062\u590D"
189
- ] }),
190
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-btn archv-del", disabled: busy !== null, "aria-label": (isConfirm ? "\u786E\u8BA4\u5220\u9664 " : "\u5220\u9664 ") + (it.title || it.sessionId), onClick: () => act("delete", it), children: isConfirm ? "\u786E\u8BA4\u5220\u9664?" : "\u5220\u9664" })
191
- ] })
192
- ] }, it.sessionId);
193
- }) }),
194
- toast && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-status", role: "status", children: toast })
195
- ] });
196
160
  }
197
- var MOVE_CSS = `
198
- .mv{display:flex;flex-direction:column;gap:4px;max-width:800px;padding:8px 2px 28px}
199
- .mv-head{display:flex;align-items:center;gap:10px;margin:0 0 2px}
200
- .mv-title{font-size:16px;font-weight:650;color:var(--dsw-alias-label-primary);letter-spacing:-0.01em;margin:0}
201
- .mv-count{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:1px 8px;flex:none}
202
- .mv-sub{font-size:12px;line-height:1.55;color:var(--dsw-alias-label-tertiary);margin:0 0 12px;max-width:64ch}
203
- .mv-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}
204
- .mv-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}
205
- .mv-list{display:flex;flex-direction:column;gap:8px}
206
- .mv-card{display:flex;align-items:center;justify-content:space-between;gap:14px;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}
207
- .mv-card:hover{border-color:var(--dsw-alias-border-l4)}
208
- .mv-main{min-width:0;display:flex;flex-direction:column;gap:4px}
209
- .mv-name{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
210
- .mv-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0}
211
- .mv-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}
212
- .mv-archived{color:var(--dsw-alias-state-warning-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-warning-primary) 50%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-warning-primary) 8%,transparent)}
213
- .mv-date{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none}
214
- .mv-id{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;color:var(--dsw-alias-label-tertiary);flex:none}
215
- .mv-dot{color:var(--dsw-alias-border-l3);flex:none}
216
- .mv-actions{display:flex;gap:8px;flex:none}
217
- .mv-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}
218
- .mv-btn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
219
- .mv-btn:disabled{opacity:.5;cursor:default}
220
- .mv-go{color:var(--dsw-alias-state-business-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 45%,transparent)}
221
- .mv-go:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,transparent);color:var(--dsw-alias-state-business-primary)}
222
- .mv-sheet{display:flex;flex-direction:column;gap:10px;margin-top:10px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-fill-subtle)}
223
- .mv-sheet-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;color:var(--dsw-alias-label-secondary)}
224
- .mv-sheet-row input[type=radio]{accent-color:var(--dsw-alias-state-business-primary)}
225
- .mv-sheet select,.mv-sheet input[type=text]{appearance:none;min-height:32px;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}
226
- .mv-sheet input[type=text]{flex:1;min-width:220px}
227
- .mv-sheet select:focus-visible,.mv-sheet input[type=text]:focus-visible,.mv-go:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
228
- .mv-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}
229
- .mv-skel{display:flex;flex-direction:column;gap:8px}
230
- .mv-skel-card{height:58px;border-radius:12px;background:var(--dsw-alias-fill-subtle);position:relative;overflow:hidden}
231
- .mv-skel-card::after{content:'';position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--dsw-alias-fill-elevated) 75%,transparent),transparent);animation:mv-shimmer 1.4s infinite}
232
- @keyframes mv-shimmer{100%{transform:translateX(100%)}}
233
- @keyframes mv-pop{from{opacity:0;transform:translateX(-50%) translateY(10px)}}
234
- .mv-status{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:60;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);padding:9px 16px;border-radius:999px;font-size:12px;box-shadow:0 8px 24px rgb(0 0 0/.18);display:flex;align-items:center;gap:8px;animation:mv-pop .18s ease-out;max-width:min(90vw,420px)}
235
- .mv-spin{width:12px;height:12px;border:2px solid color-mix(in srgb,var(--dsw-alias-label-secondary) 35%,transparent);border-top-color:var(--dsw-alias-label-secondary);border-radius:50%;animation:archv-rot .8s linear infinite;flex:none}
236
- @media (prefers-reduced-motion:reduce){.mv-skel-card::after{animation:none}.mv-card,.mv-btn{transition:none}.mv-status,.mv-spin{animation:none}}
237
- @media (max-width:560px){.mv-card{flex-direction:column;align-items:stretch;gap:10px}.mv-actions{justify-content:flex-end}.mv-sheet input[type=text]{min-width:0}}
238
- `;
239
- function MovePanel() {
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 }) {
240
172
  const [sessions, setSessions] = (0, import_react.useState)(null);
241
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);
242
178
  const [busy, setBusy] = (0, import_react.useState)(null);
243
- const [open, setOpen] = (0, import_react.useState)(null);
244
- const [mode, setMode] = (0, import_react.useState)("existing");
179
+ const [openMove, setOpenMove] = (0, import_react.useState)(null);
180
+ const [moveMode, setMoveMode] = (0, import_react.useState)("existing");
245
181
  const [targetWs, setTargetWs] = (0, import_react.useState)("");
246
182
  const [newPath, setNewPath] = (0, import_react.useState)("");
247
183
  const [error, setError] = (0, import_react.useState)(null);
248
184
  const [toast, setToast] = (0, import_react.useState)(null);
185
+ const [picking, setPicking] = (0, import_react.useState)(false);
249
186
  const timer = (0, import_react.useRef)(null);
250
187
  const showToast = (msg) => {
251
188
  if (timer.current) clearTimeout(timer.current);
@@ -260,6 +197,9 @@ function MovePanel() {
260
197
  ]).then(([s, works]) => {
261
198
  setSessions(s.items || []);
262
199
  setWorkspaces(works.items || []);
200
+ setSelected({});
201
+ setConfirmDel(null);
202
+ setConfirmBatch(false);
263
203
  if (!targetWs && works.items && works.items.length) setTargetWs(works.items[0].workspaceId);
264
204
  }).catch((e) => setError(String(e && e.message || e)));
265
205
  };
@@ -273,8 +213,42 @@ function MovePanel() {
273
213
  const w = workspaces.find((x) => x.workspaceId === id);
274
214
  return w ? w.path : "";
275
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
+ };
229
+ const act = (action, it) => {
230
+ if (busy) return;
231
+ if (action === "delete") {
232
+ if (confirmDel !== it.sessionId) {
233
+ setConfirmDel(it.sessionId);
234
+ return;
235
+ }
236
+ setConfirmDel(null);
237
+ }
238
+ setBusy(it.sessionId);
239
+ postJSON("/archived-sessions/" + action, { sessionId: it.sessionId }).then(() => {
240
+ setBusy(null);
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}`);
243
+ refresh();
244
+ }).catch((e) => {
245
+ setBusy(null);
246
+ setConfirmDel(null);
247
+ setError(String(e && e.message || e));
248
+ });
249
+ };
276
250
  const doMove = (it) => {
277
- const targetPath = mode === "new" ? newPath.trim() : wsPath(targetWs);
251
+ const targetPath = moveMode === "new" ? newPath.trim() : wsPath(targetWs);
278
252
  if (!targetPath) {
279
253
  setError("\u8BF7\u9009\u62E9\u5DF2\u6709\u5DE5\u4F5C\u533A\u6216\u8F93\u5165\u65B0\u7684\u76EE\u6807\u76EE\u5F55\u8DEF\u5F84");
280
254
  return;
@@ -283,8 +257,8 @@ function MovePanel() {
283
257
  setError(null);
284
258
  postJSON("/archived-sessions/move", { sessionId: it.sessionId, targetPath }).then((r) => {
285
259
  setBusy(null);
286
- setOpen(null);
287
- setMode("existing");
260
+ setOpenMove(null);
261
+ setMoveMode("existing");
288
262
  setNewPath("");
289
263
  showToast(`\u5DF2\u628A\u300C${it.title || it.sessionId}\u300D\u79FB\u5230 ${r.workspaceTitle || targetPath}`);
290
264
  refresh();
@@ -293,169 +267,218 @@ function MovePanel() {
293
267
  setError(String(e && e.message || e));
294
268
  });
295
269
  };
296
- const wtag = (it) => {
297
- if (it.workspacePath) {
298
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-wtag", title: it.workspacePath, children: it.workspaceTitle || pathName(it.workspacePath) });
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
+ };
316
+ const workspaceTag = (it) => {
317
+ if (it.hasWorkspace && it.workspaceGone) {
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: [
319
+ "\u5DE5\u4F5C\u533A\u5DF2\u5220 \xB7 ",
320
+ pathName(it.workspacePath) || "?"
321
+ ] });
322
+ }
323
+ const wName = it.workspaceTitle || pathName(it.workspacePath);
324
+ if (wName) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "archv-wtag", title: it.workspacePath || "", children: wName });
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
+ ] });
299
334
  }
300
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-wtag", children: "\u672A\u5206\u7EC4" });
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
+ ] });
301
339
  };
302
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv", role: "region", "aria-label": "\u79FB\u52A8\u4F1A\u8BDD", children: [
303
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: MOVE_CSS }),
304
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-head", children: [
305
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "mv-title", children: "\u79FB\u52A8\u4F1A\u8BDD\u5230\u5DE5\u4F5C\u533A" }),
306
- sessions !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-count", "aria-label": `${sessions.length} \u4E2A\u4F1A\u8BDD`, children: sessions.length })
340
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv", role: "region", "aria-label": "\u4F1A\u8BDD\u7BA1\u7406", children: [
341
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: CSS }),
342
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-head", children: [
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 })
307
345
  ] }),
308
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mv-sub", children: "\u628A\u4EFB\u610F\u4F1A\u8BDD\u79FB\u52A8\u5230\u67D0\u4E2A\u5DE5\u4F5C\u533A\u76EE\u5F55\uFF08\u53EF\u9009\u7528\u73B0\u6709\u5DE5\u4F5C\u533A\u6216\u8F93\u5165\u65B0\u76EE\u5F55\uFF0C\u81EA\u52A8\u521B\u5EFA\uFF09\u3002\u79FB\u52A8\u4F1A\u6539\u5199\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u76EE\u5F55\u5E76\u628A\u65E5\u5FD7\u8FC1\u79FB\u8FC7\u53BB\uFF1B \u4F1A\u8BDD\u5F53\u524D\u5904\u4E8E\u6253\u5F00\u72B6\u6001\u65F6\u9700\u5148\u5728\u4FA7\u680F\u5207\u8D70\u624D\u80FD\u79FB\u52A8\u3002" }),
309
- error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-err", role: "alert", 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" }),
347
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "archv-err", role: "alert", children: [
310
348
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: error }),
311
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "mv-errretry", onClick: refresh, children: "\u91CD\u8BD5" })
349
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "archv-errretry", onClick: refresh, children: "\u91CD\u8BD5" })
312
350
  ] }),
313
- sessions === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-skel", "aria-label": "\u52A0\u8F7D\u4E2D", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-skel-card" }, i)) }) : sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-empty", children: "\u6682\u65E0\u53EF\u79FB\u52A8\u7684\u4F1A\u8BDD\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-list", role: "list", children: sessions.map((it) => {
314
- const date = fmtDate(it.createdAt);
315
- const expanded = open === it.sessionId;
316
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-card", role: "listitem", children: [
317
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-main", children: [
318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-name", title: it.title || "", children: it.title || "(\u65E0\u6807\u9898)" }),
319
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-meta", children: [
320
- it.archived && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-wtag mv-archived", children: "\u5DF2\u5F52\u6863" }),
321
- wtag(it),
322
- date && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
323
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-dot", children: "\xB7" }),
324
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-date", children: date })
325
- ] }),
326
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-id", children: it.sessionId })
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
+ ")"
361
+ ] }),
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" })
327
379
  ] }),
328
- expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet", children: [
329
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "mv-sheet-row", children: [
330
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "radio", name: "mv-target", checked: mode === "existing", onChange: () => setMode("existing") }),
331
- "\u5DF2\u6709\u5DE5\u4F5C\u533A"
332
- ] }),
333
- mode === "existing" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-sheet-row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: targetWs, onChange: (e) => setTargetWs(e.target.value), "aria-label": "\u76EE\u6807\u5DE5\u4F5C\u533A", children: [
334
- workspaces.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\uFF08\u6682\u65E0\u5DE5\u4F5C\u533A\uFF09" }),
335
- workspaces.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: w.workspaceId, children: [
336
- w.title,
337
- " \xB7 ",
338
- w.path
339
- ] }, w.workspaceId))
340
- ] }) }),
341
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "mv-sheet-row", children: [
342
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "radio", name: "mv-target", checked: mode === "new", onChange: () => setMode("new") }),
343
- "\u65B0\u5EFA\u5DE5\u4F5C\u533A\u76EE\u5F55"
344
- ] }),
345
- mode === "new" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-sheet-row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
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" })
382
+ ] })
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)(
346
390
  "input",
347
391
  {
348
- type: "text",
349
- value: newPath,
350
- onChange: (e) => setNewPath(e.target.value),
351
- placeholder: "\u4F8B\u5982 /Users/you/Projects/demo \u6216 ~/demo",
352
- "aria-label": "\u65B0\u5DE5\u4F5C\u533A\u76EE\u5F55\u8DEF\u5F84"
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)
353
397
  }
354
- ) }),
355
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mv-sheet-row", children: [
356
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: "mv-btn mv-go", disabled: busy !== null, onClick: () => doMove(it), children: [
357
- busy === it.sessionId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mv-spin", "aria-hidden": "true" }),
358
- "\u786E\u8BA4\u79FB\u52A8"
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
+ ] })
359
411
  ] }),
360
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "mv-btn", disabled: busy !== null, onClick: () => {
361
- setOpen(null);
362
- setMode("existing");
363
- setNewPath("");
364
- }, children: "\u53D6\u6D88" })
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
+ ] })
365
466
  ] })
366
467
  ] })
367
- ] }),
368
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
369
- "button",
370
- {
371
- type: "button",
372
- className: "mv-btn mv-go",
373
- disabled: busy !== null,
374
- "aria-label": "\u79FB\u52A8 " + (it.title || it.sessionId),
375
- onClick: () => {
376
- if (expanded) {
377
- setOpen(null);
378
- } else {
379
- setTargetWs(workspaces.length ? targetWs || workspaces[0].workspaceId : "");
380
- setMode("existing");
381
- setNewPath("");
382
- setOpen(it.sessionId);
383
- }
384
- },
385
- children: expanded ? "\u6536\u8D77" : "\u79FB\u52A8\u5230\u2026"
386
- }
387
- ) })
388
- ] }, it.sessionId);
389
- }) }),
390
- toast && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mv-status", role: "status", children: toast })
468
+ ] }, it.sessionId);
469
+ }) })
470
+ ] }),
471
+ toast && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "archv-status", role: "status", children: toast })
391
472
  ] });
392
473
  }
393
- var NAV_CSS = `
394
- [data-dsh-nav-archived] > svg:first-child,
395
- [data-dsh-nav-move] > svg:first-child { display: none; }
396
- [data-dsh-nav-archived]::before,
397
- [data-dsh-nav-move]::before {
398
- content: ''; flex: none; width: 16px; height: 16px; background: currentColor;
399
- -webkit-mask: center / contain no-repeat; mask: center / contain no-repeat;
400
- }
401
- [data-dsh-nav-archived]::before {
402
- -webkit-mask-image: 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");
403
- mask-image: 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");
404
- }
405
- [data-dsh-nav-move]::before {
406
- -webkit-mask-image: 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'M22%2019a2%202%200%200%201-2%202H4a2%202%200%200%201-2-2V5a2%202%200%200%201%202-2h5l2%203h9a2%202%200%200%201%202%202z'/%3E%3Cpath%20d%3D'M12%2010v6'/%3E%3Cpath%20d%3D'm15%2013-3%203-3-3'/%3E%3C/svg%3E");
407
- mask-image: 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'M22%2019a2%202%200%200%201-2%202H4a2%202%200%200%201-2-2V5a2%202%200%200%201%202-2h5l2%203h9a2%202%200%200%201%202%202z'/%3E%3Cpath%20d%3D'M12%2010v6'/%3E%3Cpath%20d%3D'm15%2013-3%203-3-3'/%3E%3C/svg%3E");
408
- }
409
- `;
410
- function markSettingsNav() {
411
- const ARCHIVED_LABEL = "\u5F52\u6863\u4F1A\u8BDD";
412
- const MOVE_LABEL = "\u79FB\u52A8\u4F1A\u8BDD";
413
- let disposed = false;
414
- const sync = () => {
415
- if (disposed) return;
416
- const buttons = document.querySelectorAll('[role="dialog"] nav button');
417
- for (const b of buttons) {
418
- const t = (b.textContent || "").trim();
419
- if (t === ARCHIVED_LABEL) b.setAttribute("data-dsh-nav-archived", "");
420
- else b.removeAttribute("data-dsh-nav-archived");
421
- if (t === MOVE_LABEL) b.setAttribute("data-dsh-nav-move", "");
422
- else b.removeAttribute("data-dsh-nav-move");
423
- }
424
- };
425
- sync();
426
- const obs = new MutationObserver(sync);
427
- obs.observe(document.body, { childList: true, subtree: true, characterData: true });
428
- return () => {
429
- disposed = true;
430
- obs.disconnect();
431
- document.querySelectorAll("[data-dsh-nav-archived]").forEach((e) => e.removeAttribute("data-dsh-nav-archived"));
432
- document.querySelectorAll("[data-dsh-nav-move]").forEach((e) => e.removeAttribute("data-dsh-nav-move"));
433
- };
434
- }
435
- function installSettingsNavIcons(ctx) {
436
- const styleEl = document.createElement("style");
437
- styleEl.textContent = NAV_CSS;
438
- document.head.appendChild(styleEl);
439
- const dispose = markSettingsNav();
440
- ctx.effect(() => () => {
441
- dispose();
442
- if (styleEl.parentNode) styleEl.parentNode.removeChild(styleEl);
443
- });
444
- }
445
474
  function apply(ctx) {
446
475
  installSettingsNavIcons(ctx);
476
+ const workspacesSvc = ctx.get("workspaces");
447
477
  ctx.slots.inject(
448
478
  "settings.section",
449
479
  () => ctx.slots.register(
450
- { name: "settings.section", id: "archived-sessions", order: 90, label: "\u5F52\u6863\u4F1A\u8BDD" },
451
- (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedPanel, { ...props })
452
- )
453
- );
454
- ctx.slots.inject(
455
- "settings.section",
456
- () => ctx.slots.register(
457
- { name: "settings.section", id: "move-sessions", order: 91, label: "\u79FB\u52A8\u4F1A\u8BDD" },
458
- (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MovePanel, { ...props })
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 })
459
482
  )
460
483
  );
461
484
  }