dsh-vscode-workbench 0.1.11 → 0.1.12
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 -2
- package/README.md +21 -2
- package/lib/client.js +293 -104
- package/lib/client.js.map +1 -1
- package/lib/index.js +93 -41
- package/lib/index.js.map +1 -1
- package/lib/types/client/Workbench.d.ts +3 -0
- package/lib/types/client/terminal.d.ts +1 -0
- package/lib/types/client/websocket.d.ts +15 -0
- package/lib/types/terminal.d.ts +5 -0
- package/package.json +1 -1
- package/src/client/DshConversationPanel.tsx +2 -0
- package/src/client/TerminalPanel.tsx +12 -5
- package/src/client/Workbench.tsx +140 -15
- package/src/client/styles.ts +9 -4
- package/src/client/terminal.ts +15 -4
- package/src/client/websocket.ts +50 -0
- package/src/host.ts +47 -14
- package/src/terminal.ts +27 -2
package/lib/client.js
CHANGED
|
@@ -7471,6 +7471,54 @@ window.__ModuleLoader__.load({
|
|
|
7471
7471
|
return "file";
|
|
7472
7472
|
}
|
|
7473
7473
|
//#endregion
|
|
7474
|
+
//#region src/client/websocket.ts
|
|
7475
|
+
const WEB_PAGE_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
7476
|
+
"http:",
|
|
7477
|
+
"https:",
|
|
7478
|
+
"blob:",
|
|
7479
|
+
"data:",
|
|
7480
|
+
"about:",
|
|
7481
|
+
"filesystem:"
|
|
7482
|
+
]);
|
|
7483
|
+
/** Parse a shell-published base only when it is a credential-free HTTP(S) origin. */
|
|
7484
|
+
function networkBase(value) {
|
|
7485
|
+
if (typeof value !== "string" || value === "") return void 0;
|
|
7486
|
+
let url;
|
|
7487
|
+
try {
|
|
7488
|
+
url = new URL(value);
|
|
7489
|
+
} catch {
|
|
7490
|
+
return;
|
|
7491
|
+
}
|
|
7492
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return void 0;
|
|
7493
|
+
if (url.username !== "" || url.password !== "" || url.host === "") return void 0;
|
|
7494
|
+
return {
|
|
7495
|
+
protocol: url.protocol,
|
|
7496
|
+
host: url.host
|
|
7497
|
+
};
|
|
7498
|
+
}
|
|
7499
|
+
/** Read the Host origin published by the DSH Desktop shell before application boot. */
|
|
7500
|
+
function transportStreamBaseUrl(globals = globalThis) {
|
|
7501
|
+
const transport = globals.__DSH_TRANSPORT__;
|
|
7502
|
+
return typeof transport?.streamBaseUrl === "string" ? transport.streamBaseUrl : void 0;
|
|
7503
|
+
}
|
|
7504
|
+
/**
|
|
7505
|
+
* Resolve an absolute workbench route to a WebSocket URL.
|
|
7506
|
+
*
|
|
7507
|
+
* Network pages keep their own origin. Application-delivered pages such as
|
|
7508
|
+
* `dsh-app://app/` have no WebSocket transport of their own, so they must use
|
|
7509
|
+
* the local Host origin published by the desktop shell.
|
|
7510
|
+
*/
|
|
7511
|
+
function websocketUrl(path, location = globalThis.location, streamBaseUrl = transportStreamBaseUrl()) {
|
|
7512
|
+
const route = path.startsWith("/") ? path : `/${path}`;
|
|
7513
|
+
if (WEB_PAGE_PROTOCOLS.has(location.protocol)) {
|
|
7514
|
+
if (location.host === "") return void 0;
|
|
7515
|
+
return `${location.protocol === "https:" ? "wss" : "ws"}://${location.host}${route}`;
|
|
7516
|
+
}
|
|
7517
|
+
const base = networkBase(streamBaseUrl);
|
|
7518
|
+
if (base === void 0) return void 0;
|
|
7519
|
+
return `${base.protocol === "https:" ? "wss" : "ws"}://${base.host}${route}`;
|
|
7520
|
+
}
|
|
7521
|
+
//#endregion
|
|
7474
7522
|
//#region src/client/terminal.ts
|
|
7475
7523
|
async function request(method, body) {
|
|
7476
7524
|
const response = await fetch(`/dsh-vscode-terminal/api/${method}`, {
|
|
@@ -7491,14 +7539,23 @@ window.__ModuleLoader__.load({
|
|
|
7491
7539
|
var SocketConnection = class {
|
|
7492
7540
|
socket;
|
|
7493
7541
|
listeners = /* @__PURE__ */ new Set();
|
|
7542
|
+
errorListeners = /* @__PURE__ */ new Set();
|
|
7543
|
+
closed = false;
|
|
7494
7544
|
queue = [];
|
|
7495
7545
|
constructor(sessionId, id) {
|
|
7496
|
-
const
|
|
7497
|
-
|
|
7546
|
+
const url = websocketUrl(`/dsh-vscode-terminal/ws?sessionId=${encodeURIComponent(sessionId)}&id=${encodeURIComponent(id)}`);
|
|
7547
|
+
if (url === void 0) throw new Error("无法连接终端:桌面端没有发布本地 Host 地址");
|
|
7548
|
+
this.socket = new WebSocket(url);
|
|
7498
7549
|
this.socket.onopen = () => {
|
|
7499
7550
|
for (const value of this.queue) this.socket.send(value);
|
|
7500
7551
|
this.queue = [];
|
|
7501
7552
|
};
|
|
7553
|
+
this.socket.onerror = () => {
|
|
7554
|
+
for (const listener of this.errorListeners) listener("终端 WebSocket 连接失败");
|
|
7555
|
+
};
|
|
7556
|
+
this.socket.onclose = () => {
|
|
7557
|
+
if (!this.closed) for (const listener of this.errorListeners) listener("终端 WebSocket 连接已断开");
|
|
7558
|
+
};
|
|
7502
7559
|
this.socket.onmessage = (event) => {
|
|
7503
7560
|
try {
|
|
7504
7561
|
const value = JSON.parse(String(event.data));
|
|
@@ -7530,12 +7587,17 @@ window.__ModuleLoader__.load({
|
|
|
7530
7587
|
});
|
|
7531
7588
|
}
|
|
7532
7589
|
close() {
|
|
7590
|
+
this.closed = true;
|
|
7533
7591
|
this.socket.close();
|
|
7534
7592
|
}
|
|
7535
7593
|
subscribe(listener) {
|
|
7536
7594
|
this.listeners.add(listener);
|
|
7537
7595
|
return () => this.listeners.delete(listener);
|
|
7538
7596
|
}
|
|
7597
|
+
subscribeError(listener) {
|
|
7598
|
+
this.errorListeners.add(listener);
|
|
7599
|
+
return () => this.errorListeners.delete(listener);
|
|
7600
|
+
}
|
|
7539
7601
|
};
|
|
7540
7602
|
/** Identify automatic terminal-emulator replies that must not be echoed during replay. */
|
|
7541
7603
|
function isTerminalProtocolReply(data) {
|
|
@@ -7572,12 +7634,21 @@ window.__ModuleLoader__.load({
|
|
|
7572
7634
|
}
|
|
7573
7635
|
}
|
|
7574
7636
|
async create(title) {
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7637
|
+
try {
|
|
7638
|
+
const terminal = await request("create", {
|
|
7639
|
+
sessionId: this.sessionId,
|
|
7640
|
+
...title === void 0 ? {} : { title }
|
|
7641
|
+
});
|
|
7642
|
+
await this.refresh();
|
|
7643
|
+
return terminal;
|
|
7644
|
+
} catch (error) {
|
|
7645
|
+
this.set({
|
|
7646
|
+
...this.snapshot,
|
|
7647
|
+
loading: false,
|
|
7648
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7649
|
+
});
|
|
7650
|
+
throw error;
|
|
7651
|
+
}
|
|
7581
7652
|
}
|
|
7582
7653
|
async close(id) {
|
|
7583
7654
|
await request("close", {
|
|
@@ -7643,7 +7714,14 @@ window.__ModuleLoader__.load({
|
|
|
7643
7714
|
const fit = new import_addon_fit.FitAddon();
|
|
7644
7715
|
terminal.loadAddon(fit);
|
|
7645
7716
|
terminal.open(root.current);
|
|
7646
|
-
|
|
7717
|
+
let connection;
|
|
7718
|
+
try {
|
|
7719
|
+
connection = workspace.connect(id);
|
|
7720
|
+
} catch (exception) {
|
|
7721
|
+
setError(exception instanceof Error ? exception.message : String(exception));
|
|
7722
|
+
terminal.dispose();
|
|
7723
|
+
return;
|
|
7724
|
+
}
|
|
7647
7725
|
const output = connection.subscribe((value) => {
|
|
7648
7726
|
if (value.replay) {
|
|
7649
7727
|
replaying.current = true;
|
|
@@ -7655,6 +7733,7 @@ window.__ModuleLoader__.load({
|
|
|
7655
7733
|
}, 250);
|
|
7656
7734
|
});
|
|
7657
7735
|
});
|
|
7736
|
+
const connectionError = connection.subscribeError(setError);
|
|
7658
7737
|
const input = terminal.onData((data) => {
|
|
7659
7738
|
if (!replaying.current || !isTerminalProtocolReply(data)) connection.write(data);
|
|
7660
7739
|
});
|
|
@@ -7675,6 +7754,7 @@ window.__ModuleLoader__.load({
|
|
|
7675
7754
|
terminalRef.current = void 0;
|
|
7676
7755
|
clearTimeout(replayGuard.current);
|
|
7677
7756
|
observer.disconnect();
|
|
7757
|
+
connectionError();
|
|
7678
7758
|
input.dispose();
|
|
7679
7759
|
resize.dispose();
|
|
7680
7760
|
output();
|
|
@@ -7712,8 +7792,8 @@ window.__ModuleLoader__.load({
|
|
|
7712
7792
|
workspace.refresh().then(() => {
|
|
7713
7793
|
if (!cancelled && workspace.getSnapshot().terminals.length === 0) workspace.create().then((value) => {
|
|
7714
7794
|
if (!cancelled) setActive(value.id);
|
|
7715
|
-
});
|
|
7716
|
-
});
|
|
7795
|
+
}).catch(() => void 0);
|
|
7796
|
+
}).catch(() => void 0);
|
|
7717
7797
|
return () => {
|
|
7718
7798
|
cancelled = true;
|
|
7719
7799
|
};
|
|
@@ -7723,7 +7803,7 @@ window.__ModuleLoader__.load({
|
|
|
7723
7803
|
}, [snapshot.terminals, active]);
|
|
7724
7804
|
(0, react.useEffect)(() => {
|
|
7725
7805
|
const create = () => {
|
|
7726
|
-
workspace.create().then((value) => setActive(value.id));
|
|
7806
|
+
workspace.create().then((value) => setActive(value.id)).catch(() => void 0);
|
|
7727
7807
|
};
|
|
7728
7808
|
window.addEventListener("dvw-terminal-new", create);
|
|
7729
7809
|
return () => window.removeEventListener("dvw-terminal-new", create);
|
|
@@ -7756,7 +7836,7 @@ window.__ModuleLoader__.load({
|
|
|
7756
7836
|
workspace.create().then((value) => {
|
|
7757
7837
|
setSplit((current) => [...current?.includes(first) ? current : [first], value.id]);
|
|
7758
7838
|
setActive(value.id);
|
|
7759
|
-
});
|
|
7839
|
+
}).catch(() => void 0);
|
|
7760
7840
|
};
|
|
7761
7841
|
const shown = (split ?? (active === void 0 ? [] : [active])).filter((id) => snapshot.terminals.some((value) => value.id === id));
|
|
7762
7842
|
const selectTerminal = (id) => {
|
|
@@ -12086,6 +12166,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
12086
12166
|
attached?.style.setProperty("--dvw-status-height", `${statusHeight}px`);
|
|
12087
12167
|
};
|
|
12088
12168
|
attach();
|
|
12169
|
+
document.body.setAttribute("data-dvw-conversation-active", "");
|
|
12089
12170
|
const observer = new MutationObserver(attach);
|
|
12090
12171
|
observer.observe(document.body, {
|
|
12091
12172
|
childList: true,
|
|
@@ -12093,6 +12174,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
12093
12174
|
});
|
|
12094
12175
|
return () => {
|
|
12095
12176
|
observer.disconnect();
|
|
12177
|
+
document.body.removeAttribute("data-dvw-conversation-active");
|
|
12096
12178
|
attached?.removeAttribute("data-dvw-conversation-panel");
|
|
12097
12179
|
attached?.style.removeProperty("--dvw-chat-width");
|
|
12098
12180
|
attached?.style.removeProperty("--dvw-status-height");
|
|
@@ -46216,6 +46298,11 @@ section.${c}>footer { z-index: 1; }
|
|
|
46216
46298
|
function resizedPanelWidth(startWidth, startX, nextX, direction, min, max) {
|
|
46217
46299
|
return Math.max(min, Math.min(max, Math.round(startWidth + (nextX - startX) * direction)));
|
|
46218
46300
|
}
|
|
46301
|
+
/** Retry a workspace lookup that raced the Host publishing its session after startup. */
|
|
46302
|
+
function workspaceRetryDelay(error, attempt) {
|
|
46303
|
+
if (!(error instanceof ApiError) || error.code !== "session-not-found" || attempt >= 10) return void 0;
|
|
46304
|
+
return Math.min(250 * (attempt + 1), 1e3);
|
|
46305
|
+
}
|
|
46219
46306
|
function PanelResizer({ className, label, width, min, max, defaultWidth, direction, onWidth }) {
|
|
46220
46307
|
const [dragging, setDragging] = (0, react.useState)(false);
|
|
46221
46308
|
const stopDragging = (0, react.useRef)(() => {});
|
|
@@ -46281,6 +46368,7 @@ section.${c}>footer { z-index: 1; }
|
|
|
46281
46368
|
}
|
|
46282
46369
|
function unloadedTab(path) {
|
|
46283
46370
|
return {
|
|
46371
|
+
instance: Symbol(path),
|
|
46284
46372
|
path,
|
|
46285
46373
|
content: "",
|
|
46286
46374
|
draft: "",
|
|
@@ -46293,6 +46381,12 @@ section.${c}>footer { z-index: 1; }
|
|
|
46293
46381
|
preview: /\.md$/i.test(path)
|
|
46294
46382
|
};
|
|
46295
46383
|
}
|
|
46384
|
+
function WorkbenchTitlebar({ name }) {
|
|
46385
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
46386
|
+
className: "dvw-titlebar",
|
|
46387
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "DSH Workbench" }), name !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: name })]
|
|
46388
|
+
});
|
|
46389
|
+
}
|
|
46296
46390
|
/** Restore tab headers without reading their file contents. */
|
|
46297
46391
|
function restoreTabPaths(paths) {
|
|
46298
46392
|
return [...new Set(paths)].map(unloadedTab);
|
|
@@ -46345,13 +46439,16 @@ section.${c}>footer { z-index: 1; }
|
|
|
46345
46439
|
api("fs.list", {
|
|
46346
46440
|
sessionId,
|
|
46347
46441
|
path
|
|
46348
|
-
}).then(
|
|
46442
|
+
}).then((value) => {
|
|
46443
|
+
setRows(value);
|
|
46444
|
+
setError(void 0);
|
|
46445
|
+
}).catch((error) => setError(String(error)));
|
|
46349
46446
|
}, [sessionId, path]);
|
|
46350
46447
|
(0, react.useEffect)(load, [load]);
|
|
46351
46448
|
(0, react.useEffect)(() => {
|
|
46352
46449
|
const handler = (event) => {
|
|
46353
46450
|
const paths = event.detail;
|
|
46354
|
-
if (paths
|
|
46451
|
+
if (!Array.isArray(paths) || directoryAffected(path, paths)) load();
|
|
46355
46452
|
};
|
|
46356
46453
|
window.addEventListener("dvw-files-changed", handler);
|
|
46357
46454
|
return () => window.removeEventListener("dvw-files-changed", handler);
|
|
@@ -47515,7 +47612,7 @@ section.${c}>footer { z-index: 1; }
|
|
|
47515
47612
|
const tabsRef = (0, react.useRef)(tabs);
|
|
47516
47613
|
tabsRef.current = tabs;
|
|
47517
47614
|
const workspaceRequests = (0, react.useRef)(new WorkspaceRequestScope());
|
|
47518
|
-
const loadingTabs = (0, react.useRef)(/* @__PURE__ */ new
|
|
47615
|
+
const loadingTabs = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
47519
47616
|
const dshDark = useDshDarkTheme();
|
|
47520
47617
|
const [theme, setTheme] = (0, react.useState)(() => {
|
|
47521
47618
|
const saved = localStorage.getItem("dvw:theme");
|
|
@@ -47528,6 +47625,11 @@ section.${c}>footer { z-index: 1; }
|
|
|
47528
47625
|
(0, react.useEffect)(() => localStorage.setItem("dvw:dsh-chat-width", String(Math.round(chatWidth))), [chatWidth]);
|
|
47529
47626
|
(0, react.useEffect)(() => localStorage.setItem("dvw:primary-side-visible", primarySideVisible ? "open" : "closed"), [primarySideVisible]);
|
|
47530
47627
|
(0, react.useEffect)(() => localStorage.setItem("dvw:status-visible", statusVisible ? "open" : "closed"), [statusVisible]);
|
|
47628
|
+
(0, react.useEffect)(() => {
|
|
47629
|
+
if (!snapshot.visible) return;
|
|
47630
|
+
document.body.setAttribute("data-dvw-workbench-active", "");
|
|
47631
|
+
return () => document.body.removeAttribute("data-dvw-workbench-active");
|
|
47632
|
+
}, [snapshot.visible]);
|
|
47531
47633
|
(0, react.useEffect)(() => {
|
|
47532
47634
|
if (!snapshot.visible) return;
|
|
47533
47635
|
const onKey = (event) => {
|
|
@@ -47552,7 +47654,7 @@ section.${c}>footer { z-index: 1; }
|
|
|
47552
47654
|
setActive(path);
|
|
47553
47655
|
};
|
|
47554
47656
|
(0, react.useEffect)(() => {
|
|
47555
|
-
if (
|
|
47657
|
+
if (sessionId === void 0) return;
|
|
47556
47658
|
const epoch = workspaceRequests.current.begin();
|
|
47557
47659
|
const cleared = resetWorkspaceDocuments();
|
|
47558
47660
|
loadingTabs.current.clear();
|
|
@@ -47562,113 +47664,177 @@ section.${c}>footer { z-index: 1; }
|
|
|
47562
47664
|
setActive(cleared.active);
|
|
47563
47665
|
setError(cleared.error);
|
|
47564
47666
|
const controller = new AbortController();
|
|
47565
|
-
|
|
47566
|
-
|
|
47567
|
-
|
|
47568
|
-
|
|
47569
|
-
|
|
47570
|
-
|
|
47571
|
-
|
|
47572
|
-
|
|
47573
|
-
|
|
47574
|
-
|
|
47667
|
+
const load = async () => {
|
|
47668
|
+
for (let attempt = 0;; attempt++) try {
|
|
47669
|
+
const value = await api("workspace", { sessionId }, controller.signal);
|
|
47670
|
+
if (!workspaceRequests.current.isCurrent(epoch)) return;
|
|
47671
|
+
setWorkspace(value);
|
|
47672
|
+
let restored = [];
|
|
47673
|
+
let selected;
|
|
47674
|
+
try {
|
|
47675
|
+
const parsed = JSON.parse(localStorage.getItem(`dvw:${value.cwd}`) ?? "{}");
|
|
47676
|
+
if (parsed.view && service.getSnapshot().visible) service.show(parsed.view);
|
|
47677
|
+
if (typeof parsed.panelHeight === "number") setPanelHeight(parsed.panelHeight);
|
|
47678
|
+
if (typeof parsed.sideWidth === "number") setSideWidth(Math.max(210, Math.min(640, Math.round(parsed.sideWidth))));
|
|
47679
|
+
restored = restoreTabPaths(parsed.paths ?? []);
|
|
47680
|
+
selected = parsed.active;
|
|
47681
|
+
const drafts = JSON.parse(localStorage.getItem(`dvw:drafts:${sessionId}:${value.cwd}`) ?? "[]");
|
|
47682
|
+
if (Array.isArray(drafts)) for (const draft of drafts) {
|
|
47683
|
+
if (!draft || typeof draft.path !== "string" || typeof draft.content !== "string" || typeof draft.draft !== "string" || typeof draft.revision !== "string" || draft.path.startsWith("diff:")) continue;
|
|
47684
|
+
const tab = {
|
|
47685
|
+
...unloadedTab(draft.path),
|
|
47686
|
+
content: draft.content,
|
|
47687
|
+
draft: draft.draft,
|
|
47688
|
+
revision: draft.revision,
|
|
47689
|
+
dirty: draft.draft !== draft.content,
|
|
47690
|
+
loaded: true
|
|
47691
|
+
};
|
|
47692
|
+
restored = [...restored.filter((row) => row.path !== tab.path), tab];
|
|
47693
|
+
}
|
|
47694
|
+
} catch {}
|
|
47575
47695
|
setTabs(restored);
|
|
47576
|
-
setActive(restored.some((tab) => tab.path ===
|
|
47577
|
-
|
|
47578
|
-
|
|
47579
|
-
|
|
47580
|
-
|
|
47696
|
+
setActive(restored.some((tab) => tab.path === selected) ? selected : restored.at(-1)?.path);
|
|
47697
|
+
return;
|
|
47698
|
+
} catch (error) {
|
|
47699
|
+
if (controller.signal.aborted || !workspaceRequests.current.isCurrent(epoch)) return;
|
|
47700
|
+
const delay = workspaceRetryDelay(error, attempt);
|
|
47701
|
+
if (delay === void 0) {
|
|
47702
|
+
setError(String(error));
|
|
47703
|
+
return;
|
|
47704
|
+
}
|
|
47705
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
47706
|
+
if (controller.signal.aborted || !workspaceRequests.current.isCurrent(epoch)) return;
|
|
47707
|
+
}
|
|
47708
|
+
};
|
|
47709
|
+
load();
|
|
47581
47710
|
return () => {
|
|
47582
47711
|
controller.abort();
|
|
47583
47712
|
loadingTabs.current.clear();
|
|
47584
47713
|
workspaceRequests.current.invalidate(epoch);
|
|
47585
47714
|
};
|
|
47586
|
-
}, [
|
|
47715
|
+
}, [sessionId, cwd]);
|
|
47587
47716
|
(0, react.useEffect)(() => {
|
|
47588
|
-
if (workspace)
|
|
47589
|
-
|
|
47590
|
-
|
|
47591
|
-
|
|
47592
|
-
|
|
47593
|
-
|
|
47594
|
-
|
|
47717
|
+
if (!workspace || sessionId === void 0) return;
|
|
47718
|
+
try {
|
|
47719
|
+
localStorage.setItem(`dvw:${workspace.cwd}`, JSON.stringify({
|
|
47720
|
+
view: snapshot.view,
|
|
47721
|
+
paths: tabs.filter((t) => !t.path.startsWith("diff:")).map((t) => t.path),
|
|
47722
|
+
active,
|
|
47723
|
+
panelHeight,
|
|
47724
|
+
sideWidth
|
|
47725
|
+
}));
|
|
47726
|
+
localStorage.setItem(`dvw:drafts:${sessionId}:${workspace.cwd}`, JSON.stringify(tabs.filter((tab) => tab.dirty).map(({ path, content, draft, revision }) => ({
|
|
47727
|
+
path,
|
|
47728
|
+
content,
|
|
47729
|
+
draft,
|
|
47730
|
+
revision
|
|
47731
|
+
}))));
|
|
47732
|
+
} catch {
|
|
47733
|
+
setError("无法保存工作区草稿,请在离开页面前保存文件。");
|
|
47734
|
+
}
|
|
47595
47735
|
}, [
|
|
47596
47736
|
workspace,
|
|
47737
|
+
sessionId,
|
|
47597
47738
|
snapshot.view,
|
|
47598
47739
|
tabs,
|
|
47599
47740
|
active,
|
|
47600
47741
|
panelHeight,
|
|
47601
47742
|
sideWidth
|
|
47602
47743
|
]);
|
|
47603
|
-
(0, react.
|
|
47604
|
-
if (
|
|
47605
|
-
const protocol = location.protocol === "https:" ? "wss" : "ws";
|
|
47606
|
-
const ws = new WebSocket(`${protocol}://${location.host}/dsh-vscode/ws/files?sessionId=${encodeURIComponent(sessionId)}`);
|
|
47607
|
-
ws.onmessage = (event) => {
|
|
47608
|
-
let paths = [];
|
|
47609
|
-
try {
|
|
47610
|
-
paths = JSON.parse(String(event.data)).paths ?? [];
|
|
47611
|
-
} catch {}
|
|
47612
|
-
window.dispatchEvent(new CustomEvent("dvw-files-changed", { detail: paths }));
|
|
47613
|
-
setTabs((current) => current.map((tab) => tab.dirty ? {
|
|
47614
|
-
...tab,
|
|
47615
|
-
external: true
|
|
47616
|
-
} : tab));
|
|
47617
|
-
};
|
|
47618
|
-
return () => ws.close();
|
|
47619
|
-
}, [snapshot.visible, sessionId]);
|
|
47620
|
-
(0, react.useEffect)(() => {
|
|
47621
|
-
if (sessionId === void 0 || active === void 0) return;
|
|
47622
|
-
const tab = tabsRef.current.find((row) => row.path === active);
|
|
47623
|
-
if (tab === void 0 || tab.loaded !== false || loadingTabs.current.has(active)) return;
|
|
47744
|
+
const loadTab = (0, react.useCallback)((path) => {
|
|
47745
|
+
if (sessionId === void 0) return;
|
|
47624
47746
|
const epoch = workspaceRequests.current.current();
|
|
47625
|
-
|
|
47626
|
-
|
|
47627
|
-
|
|
47628
|
-
|
|
47629
|
-
|
|
47747
|
+
const token = Symbol(path);
|
|
47748
|
+
loadingTabs.current.set(path, token);
|
|
47749
|
+
const current = () => workspaceRequests.current.isCurrent(epoch) && loadingTabs.current.get(path) === token;
|
|
47750
|
+
const documentPreview = documentPreviewKind(path);
|
|
47751
|
+
const image = /\.(?:avif|bmp|gif|ico|jpe?g|png|svg|webp)$/i.test(path);
|
|
47752
|
+
if (documentPreview !== void 0 || image) {
|
|
47753
|
+
const url = `/dsh-vscode/file?sessionId=${encodeURIComponent(sessionId)}&path=${encodeURIComponent(path)}&v=${Date.now()}`;
|
|
47754
|
+
setTabs((rows) => rows.map((row) => row.path === path ? {
|
|
47630
47755
|
...row,
|
|
47631
47756
|
loaded: true,
|
|
47632
|
-
|
|
47633
|
-
|
|
47634
|
-
|
|
47635
|
-
|
|
47636
|
-
return;
|
|
47637
|
-
}
|
|
47638
|
-
if (/\.(?:avif|bmp|gif|ico|jpe?g|png|svg|webp)$/i.test(active)) {
|
|
47639
|
-
const imageUrl = `/dsh-vscode/file?sessionId=${encodeURIComponent(sessionId)}&path=${encodeURIComponent(active)}`;
|
|
47640
|
-
setTabs((rows) => rows.map((row) => row.path === active ? {
|
|
47641
|
-
...row,
|
|
47642
|
-
loaded: true,
|
|
47643
|
-
imageUrl
|
|
47757
|
+
...image ? { imageUrl: url } : {
|
|
47758
|
+
documentPreview,
|
|
47759
|
+
documentUrl: url
|
|
47760
|
+
}
|
|
47644
47761
|
} : row));
|
|
47645
|
-
loadingTabs.current.delete(
|
|
47762
|
+
loadingTabs.current.delete(path);
|
|
47646
47763
|
return;
|
|
47647
47764
|
}
|
|
47648
47765
|
api("fs.read", {
|
|
47649
47766
|
sessionId,
|
|
47650
|
-
path
|
|
47767
|
+
path
|
|
47651
47768
|
}).then((doc) => {
|
|
47652
|
-
if (!
|
|
47769
|
+
if (!current()) return;
|
|
47653
47770
|
if (doc.binary || doc.tooLarge) {
|
|
47654
|
-
setTabs((rows) => rows.
|
|
47655
|
-
|
|
47656
|
-
|
|
47771
|
+
setTabs((rows) => rows.map((row) => row.path === path ? {
|
|
47772
|
+
...row,
|
|
47773
|
+
loaded: true,
|
|
47774
|
+
...row.dirty ? {} : {
|
|
47775
|
+
binary: doc.binary,
|
|
47776
|
+
tooLarge: doc.tooLarge
|
|
47777
|
+
},
|
|
47778
|
+
external: true
|
|
47779
|
+
} : row));
|
|
47657
47780
|
return;
|
|
47658
47781
|
}
|
|
47659
|
-
setTabs((rows) => rows.map((row) => row.path
|
|
47782
|
+
setTabs((rows) => rows.map((row) => row.path !== path ? row : row.dirty ? {
|
|
47783
|
+
...row,
|
|
47784
|
+
external: row.revision !== doc.revision
|
|
47785
|
+
} : {
|
|
47660
47786
|
...row,
|
|
47661
47787
|
...doc,
|
|
47662
47788
|
draft: doc.content,
|
|
47663
|
-
loaded: true
|
|
47664
|
-
|
|
47789
|
+
loaded: true,
|
|
47790
|
+
external: false
|
|
47791
|
+
}));
|
|
47665
47792
|
}).catch((error) => {
|
|
47666
|
-
if (
|
|
47667
|
-
}).finally(() =>
|
|
47793
|
+
if (current()) setError(String(error));
|
|
47794
|
+
}).finally(() => {
|
|
47795
|
+
if (current()) loadingTabs.current.delete(path);
|
|
47796
|
+
});
|
|
47797
|
+
}, [sessionId]);
|
|
47798
|
+
(0, react.useEffect)(() => {
|
|
47799
|
+
if (!snapshot.visible || sessionId === void 0 || workspace === void 0) return;
|
|
47800
|
+
const url = websocketUrl(`/dsh-vscode/ws/files?sessionId=${encodeURIComponent(sessionId)}`);
|
|
47801
|
+
if (url === void 0) return;
|
|
47802
|
+
const ws = new WebSocket(url);
|
|
47803
|
+
let closed = false;
|
|
47804
|
+
const refresh = (paths) => {
|
|
47805
|
+
if (closed) return;
|
|
47806
|
+
window.dispatchEvent(new CustomEvent("dvw-files-changed", { detail: paths }));
|
|
47807
|
+
for (const tab of tabsRef.current) {
|
|
47808
|
+
if (tab.path.startsWith("diff:") || tab.loaded === false) continue;
|
|
47809
|
+
if (paths === void 0 || paths.some((path) => tab.path === path || tab.path.startsWith(`${path}/`))) loadTab(tab.path);
|
|
47810
|
+
}
|
|
47811
|
+
};
|
|
47812
|
+
ws.onopen = () => refresh();
|
|
47813
|
+
ws.onmessage = (event) => {
|
|
47814
|
+
try {
|
|
47815
|
+
const value = JSON.parse(String(event.data));
|
|
47816
|
+
if (Array.isArray(value.paths) && value.paths.every((path) => typeof path === "string")) refresh(value.paths);
|
|
47817
|
+
} catch {}
|
|
47818
|
+
};
|
|
47819
|
+
return () => {
|
|
47820
|
+
closed = true;
|
|
47821
|
+
ws.close();
|
|
47822
|
+
};
|
|
47823
|
+
}, [
|
|
47824
|
+
snapshot.visible,
|
|
47825
|
+
sessionId,
|
|
47826
|
+
workspace,
|
|
47827
|
+
loadTab
|
|
47828
|
+
]);
|
|
47829
|
+
(0, react.useEffect)(() => {
|
|
47830
|
+
if (sessionId === void 0 || active === void 0 || workspace === void 0) return;
|
|
47831
|
+
if (tabsRef.current.find((row) => row.path === active)?.loaded === false && !loadingTabs.current.has(active)) loadTab(active);
|
|
47668
47832
|
}, [
|
|
47669
47833
|
active,
|
|
47670
47834
|
sessionId,
|
|
47671
|
-
|
|
47835
|
+
workspace,
|
|
47836
|
+
tabs,
|
|
47837
|
+
loadTab
|
|
47672
47838
|
]);
|
|
47673
47839
|
const open = (path, line, column) => {
|
|
47674
47840
|
if (sessionId !== void 0) openForWorkspace(path, line, column);
|
|
@@ -47678,8 +47844,12 @@ section.${c}>footer { z-index: 1; }
|
|
|
47678
47844
|
window.addEventListener("dvw-open-workspace-path", listener);
|
|
47679
47845
|
return () => window.removeEventListener("dvw-open-workspace-path", listener);
|
|
47680
47846
|
}, [sessionId, tabs]);
|
|
47847
|
+
const savingTabs = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
47681
47848
|
const save = async (tab) => {
|
|
47682
|
-
if (sessionId === void 0 || !tab.dirty) return;
|
|
47849
|
+
if (sessionId === void 0 || !tab.dirty || savingTabs.current.has(tab.path)) return;
|
|
47850
|
+
const epoch = workspaceRequests.current.current();
|
|
47851
|
+
savingTabs.current.add(tab.path);
|
|
47852
|
+
loadingTabs.current.delete(tab.path);
|
|
47683
47853
|
try {
|
|
47684
47854
|
const doc = await api("fs.save", {
|
|
47685
47855
|
sessionId,
|
|
@@ -47687,27 +47857,34 @@ section.${c}>footer { z-index: 1; }
|
|
|
47687
47857
|
content: tab.draft,
|
|
47688
47858
|
revision: tab.revision
|
|
47689
47859
|
});
|
|
47690
|
-
|
|
47860
|
+
if (!workspaceRequests.current.isCurrent(epoch)) return;
|
|
47861
|
+
loadingTabs.current.delete(tab.path);
|
|
47862
|
+
setTabs((rows) => rows.map((row) => row.path === tab.path && row.instance === tab.instance ? {
|
|
47691
47863
|
...row,
|
|
47692
47864
|
...doc,
|
|
47693
|
-
draft:
|
|
47694
|
-
dirty:
|
|
47865
|
+
draft: row.draft,
|
|
47866
|
+
dirty: row.draft !== doc.content,
|
|
47695
47867
|
external: false
|
|
47696
47868
|
} : row));
|
|
47697
47869
|
} catch (error) {
|
|
47698
|
-
setError(String(error));
|
|
47870
|
+
if (workspaceRequests.current.isCurrent(epoch)) setError(String(error));
|
|
47871
|
+
} finally {
|
|
47872
|
+
savingTabs.current.delete(tab.path);
|
|
47699
47873
|
}
|
|
47700
47874
|
};
|
|
47701
47875
|
const close = (tab) => {
|
|
47702
47876
|
if (tab.dirty && !confirm(`${tab.path} 有未保存更改,确定关闭?`)) return;
|
|
47877
|
+
loadingTabs.current.delete(tab.path);
|
|
47703
47878
|
setTabs((rows) => rows.filter((row) => row.path !== tab.path));
|
|
47704
47879
|
if (active === tab.path) setActive(tabs.filter((row) => row.path !== tab.path).at(-1)?.path);
|
|
47705
47880
|
};
|
|
47706
47881
|
const closeAll = () => {
|
|
47707
47882
|
const dirty = tabs.filter((tab) => tab.dirty);
|
|
47708
47883
|
if (dirty.length > 0 && !confirm(`有 ${dirty.length} 个文件包含未保存更改,确定全部关闭?`)) return;
|
|
47884
|
+
loadingTabs.current.clear();
|
|
47709
47885
|
setTabs([]);
|
|
47710
47886
|
setActive(void 0);
|
|
47887
|
+
setError(void 0);
|
|
47711
47888
|
};
|
|
47712
47889
|
const activeTab = tabs.find((tab) => tab.path === active);
|
|
47713
47890
|
const Panel = panels.find((panel) => panel.id === snapshot.bottomPanel)?.component;
|
|
@@ -47737,10 +47914,10 @@ section.${c}>footer { z-index: 1; }
|
|
|
47737
47914
|
}
|
|
47738
47915
|
};
|
|
47739
47916
|
if (!snapshot.visible) return null;
|
|
47740
|
-
if (sessionId === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
47917
|
+
if (sessionId === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47741
47918
|
className: "dvw-overlay",
|
|
47742
47919
|
"data-dvw-theme": theme === "dsh" ? void 0 : theme,
|
|
47743
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47920
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchTitlebar, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47744
47921
|
className: "dvw-empty",
|
|
47745
47922
|
style: { gridColumn: "1/4" },
|
|
47746
47923
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
@@ -47751,7 +47928,7 @@ section.${c}>footer { z-index: 1; }
|
|
|
47751
47928
|
children: "返回 DSH"
|
|
47752
47929
|
})
|
|
47753
47930
|
] })
|
|
47754
|
-
})
|
|
47931
|
+
})]
|
|
47755
47932
|
});
|
|
47756
47933
|
const markdown = activeTab !== void 0 && !activeTab.path.startsWith("diff:") && /\.md$/i.test(activeTab.path);
|
|
47757
47934
|
const diffMarkdown = activeTab?.diff !== void 0 && /\.md$/i.test(activeTab.diffSourcePath ?? "");
|
|
@@ -47773,6 +47950,7 @@ section.${c}>footer { z-index: 1; }
|
|
|
47773
47950
|
onDragOverCapture: suppressAttachmentDrop,
|
|
47774
47951
|
onDropCapture: suppressAttachmentDrop,
|
|
47775
47952
|
children: [
|
|
47953
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchTitlebar, { name: workspace?.name }),
|
|
47776
47954
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DshConversationPanel, {
|
|
47777
47955
|
visible: chatVisible && !settingsOpen,
|
|
47778
47956
|
width: chatWidth,
|
|
@@ -47961,9 +48139,9 @@ section.${c}>footer { z-index: 1; }
|
|
|
47961
48139
|
className: "dvw-side",
|
|
47962
48140
|
"data-side-width": sideWidth,
|
|
47963
48141
|
children: [
|
|
47964
|
-
snapshot.view === "explorer" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Explorer, {
|
|
48142
|
+
snapshot.view === "explorer" && workspace !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Explorer, {
|
|
47965
48143
|
sessionId,
|
|
47966
|
-
cwd: workspace
|
|
48144
|
+
cwd: workspace.cwd,
|
|
47967
48145
|
selected: active,
|
|
47968
48146
|
onOpen: (path) => void open(path)
|
|
47969
48147
|
}),
|
|
@@ -48164,6 +48342,12 @@ section.${c}>footer { z-index: 1; }
|
|
|
48164
48342
|
source: activeTab.draft,
|
|
48165
48343
|
sessionId,
|
|
48166
48344
|
path: activeTab.path
|
|
48345
|
+
}) : activeTab.binary || activeTab.tooLarge ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48346
|
+
className: "dvw-message",
|
|
48347
|
+
children: activeTab.binary ? "二进制文件不能在文本编辑器中打开" : `文件超过 5 MiB:${activeTab.path}`
|
|
48348
|
+
}) : activeTab.loaded === false ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48349
|
+
className: "dvw-message",
|
|
48350
|
+
children: "正在加载文件…"
|
|
48167
48351
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonacoEditor, {
|
|
48168
48352
|
uri: `${workspace?.cwd ?? ""}/${activeTab.path}`,
|
|
48169
48353
|
value: activeTab.draft,
|
|
@@ -48257,11 +48441,13 @@ section.${c}>footer { z-index: 1; }
|
|
|
48257
48441
|
//#region src/client/styles.ts
|
|
48258
48442
|
const CSS$1 = String.raw`
|
|
48259
48443
|
@font-face{font-family:codicon;font-display:block;src:url('/dsh-vscode/codicons/codicon.ttf') format('truetype')}
|
|
48444
|
+
:root{--dvw-titlebar-height:0px}html[data-platform=darwin]{--dvw-titlebar-height:var(--dsh-frame-top-clearance,48px)}
|
|
48260
48445
|
.codicon{display:inline-block;font:normal normal normal 16px/1 codicon;text-align:center;text-decoration:none;text-rendering:auto;-webkit-font-smoothing:antialiased;user-select:none}
|
|
48261
48446
|
.codicon-add:before{content:"\ea60"}.codicon-git-branch:before,.codicon-source-control:before{content:"\ea68"}.codicon-search:before{content:"\ea6d"}.codicon-edit:before{content:"\ea73"}.codicon-close:before{content:"\ea76"}.codicon-close-all:before{content:"\eac1"}.codicon-cloud-upload:before{content:"\eac3"}.codicon-file:before{content:"\ea7b"}.codicon-new-file:before{content:"\ea7f"}.codicon-new-folder:before{content:"\ea80"}.codicon-folder:before{content:"\ea83"}.codicon-trash:before{content:"\ea81"}.codicon-code:before{content:"\eac4"}.codicon-check:before{content:"\eab2"}.codicon-chevron-down:before{content:"\eab4"}.codicon-chevron-right:before{content:"\eab6"}.codicon-color-mode:before{content:"\eac6"}.codicon-diff:before,.codicon-diff-sidebyside:before{content:"\eae1"}.codicon-diff-single:before{content:"\ec22"}.codicon-discard:before{content:"\eae2"}.codicon-file-code:before{content:"\eae9"}.codicon-file-media:before{content:"\eaea"}.codicon-file-pdf:before{content:"\eaeb"}.codicon-file-zip:before{content:"\eaef"}.codicon-files:before{content:"\eaf0"}.codicon-folder-opened:before{content:"\eaf7"}.codicon-git-commit:before{content:"\eafc"}.codicon-graph:before{content:"\eb03"}.codicon-home:before{content:"\eb06"}.codicon-list-tree:before{content:"\eb86"}.codicon-preview:before{content:"\eb2f"}.codicon-refresh:before{content:"\eb37"}.codicon-remove:before{content:"\eb3b"}.codicon-check-all:before{content:"\ebb1"}
|
|
48262
48447
|
.codicon-layout-sidebar-right:before{content:"\ebf4"}.codicon-layout-sidebar-right-off:before{content:"\ec00"}.codicon-settings:before{content:"\eb51"}.codicon-sparkle:before{content:"\ec10"}.codicon-split-horizontal:before{content:"\eb56"}.codicon-terminal:before{content:"\ea85"}
|
|
48263
48448
|
.dvw-launch{display:flex;align-items:center;gap:10px;width:100%;height:36px;padding:0 9px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary,#aaa);cursor:pointer;font:inherit}.dvw-launch:hover{background:var(--dsw-alias-interactive-bg-hover,#292929);color:var(--dsw-alias-label-primary,#fff)}.dvw-launcher-mount{position:fixed;z-index:20;right:16px;bottom:16px}.dvw-launcher-mount .dvw-launch{width:auto;height:32px;padding:0 12px;justify-content:center;border:1px solid var(--dsw-alias-border-l3,#e5e7eb);border-radius:6px;background:var(--dsw-alias-bg-layer-1,#fff);box-shadow:0 1px 2px rgba(0,0,0,.06);color:var(--dsw-alias-label-primary,#333)}body[data-ds-dark-theme] .dvw-launcher-mount .dvw-launch{color:var(--dsw-alias-label-primary,#ddd)}@media(max-width:640px){.dvw-launcher-mount{right:8px;bottom:8px}.dvw-launcher-mount .dvw-launch{height:30px;padding:0 10px;font-size:12px}}
|
|
48264
|
-
.dvw-overlay{--dvw-side-width:210px;--dvw-base:var(--dsw-alias-bg-base,#181818);--dvw-surface-1:var(--dsw-alias-bg-layer-1,#1e1e1e);--dvw-surface-2:var(--dsw-alias-bg-layer-2,#252526);--dvw-surface-3:var(--dsw-alias-bg-layer-3,#2d2d30);--dvw-text:var(--dsw-alias-label-primary,#ccc);--dvw-text-2:var(--dsw-alias-label-secondary,#aaa);--dvw-text-3:var(--dsw-alias-label-tertiary,#858585);--dvw-border:var(--dsw-alias-border-l2,#333);--dvw-border-soft:var(--dsw-alias-border-l3,#292929);--dvw-hover:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.08));--dvw-active:var(--dsw-alias-interactive-bg-active,rgba(255,255,255,.14));--dvw-accent:var(--dsw-alias-state-business-primary,#3b82f6);--dvw-error:var(--dsw-alias-state-error-primary,#f48771);--dvw-success:var(--dsw-alias-state-success-primary,#73c991);--dvw-warn:var(--dsw-alias-state-warn-primary,#d7ba7d);position:absolute;inset:0;z-index:100;display:grid;grid-template-columns:48px var(--dvw-side-width) minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto 24px;background:var(--dvw-base);color:var(--dvw-text);pointer-events:auto;font:13px/1.4 var(--dsw-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif);overflow:hidden;color-scheme:light}
|
|
48449
|
+
.dvw-overlay{--dvw-side-width:210px;--dvw-base:var(--dsw-alias-bg-base,#181818);--dvw-surface-1:var(--dsw-alias-bg-layer-1,#1e1e1e);--dvw-surface-2:var(--dsw-alias-bg-layer-2,#252526);--dvw-surface-3:var(--dsw-alias-bg-layer-3,#2d2d30);--dvw-text:var(--dsw-alias-label-primary,#ccc);--dvw-text-2:var(--dsw-alias-label-secondary,#aaa);--dvw-text-3:var(--dsw-alias-label-tertiary,#858585);--dvw-border:var(--dsw-alias-border-l2,#333);--dvw-border-soft:var(--dsw-alias-border-l3,#292929);--dvw-hover:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.08));--dvw-active:var(--dsw-alias-interactive-bg-active,rgba(255,255,255,.14));--dvw-accent:var(--dsw-alias-state-business-primary,#3b82f6);--dvw-error:var(--dsw-alias-state-error-primary,#f48771);--dvw-success:var(--dsw-alias-state-success-primary,#73c991);--dvw-warn:var(--dsw-alias-state-warn-primary,#d7ba7d);position:absolute;inset:0;z-index:100;display:grid;grid-template-columns:48px var(--dvw-side-width) minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto 24px;box-sizing:border-box;padding-top:var(--dvw-titlebar-height);background:var(--dvw-base);color:var(--dvw-text);pointer-events:auto;font:13px/1.4 var(--dsw-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif);overflow:hidden;color-scheme:light}
|
|
48450
|
+
.dvw-titlebar{display:none}html[data-platform=darwin] .dvw-titlebar{position:absolute;top:0;right:0;left:0;z-index:6;display:flex;align-items:center;gap:8px;height:var(--dvw-titlebar-height);padding:0 12px 0 84px;border-bottom:1px solid var(--dvw-border-soft);background:var(--dvw-base);color:var(--dvw-text-3);font-size:12px;-webkit-app-region:drag;user-select:none}.dvw-titlebar strong{flex:none;font-weight:600;color:var(--dvw-text-2)}.dvw-titlebar span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
48265
48451
|
body[data-ds-dark-theme] .dvw-overlay,.dvw-overlay[data-dvw-theme=dark]{color-scheme:dark}
|
|
48266
48452
|
.dvw-overlay[data-dvw-theme=dark]{--dvw-base:#151517;--dvw-surface-1:#232324;--dvw-surface-2:#2c2c2e;--dvw-surface-3:#353638;--dvw-text:#f9fafb;--dvw-text-2:#cfd3d6;--dvw-text-3:#adb2b8;--dvw-border:#ffffff1f;--dvw-border-soft:#ffffff29;--dvw-hover:#ffffff14;--dvw-active:#ffffff24;--dvw-accent:#679efe;--dvw-error:#f25a5a;--dvw-success:#22c55e;--dvw-warn:#f59e0b}
|
|
48267
48453
|
.dvw-overlay[data-dvw-theme=light]{--dvw-base:#fff;--dvw-surface-1:#fff;--dvw-surface-2:#fff;--dvw-surface-3:#fff;--dvw-text:#0f1115;--dvw-text-2:#61666b;--dvw-text-3:#81858c;--dvw-border:#0000001a;--dvw-border-soft:#0000001f;--dvw-hover:#2631480f;--dvw-active:#2631481a;--dvw-accent:#4176e6;--dvw-error:#ec1313;--dvw-success:#22c55e;--dvw-warn:#f59e0b;color-scheme:light}
|
|
@@ -48285,11 +48471,11 @@ body[data-ds-dark-theme] .dvw-overlay,.dvw-overlay[data-dvw-theme=dark]{color-sc
|
|
|
48285
48471
|
.dvw-chat-head{height:36px;display:flex;align-items:center;justify-content:space-between;padding:0 6px 0 12px;border-bottom:1px solid var(--dvw-border);background:var(--dvw-base);font-weight:600}
|
|
48286
48472
|
.dvw-chat-head>span{display:flex;align-items:center;gap:7px}.dvw-chat-body{height:calc(100% - 36px);background:var(--dvw-base)}
|
|
48287
48473
|
.dvw-dsh-mark{display:block}
|
|
48288
|
-
.dvw-chat-resizer{position:fixed;top:
|
|
48474
|
+
.dvw-chat-resizer{position:fixed;top:var(--dvw-titlebar-height);right:calc(var(--dvw-chat-width) - 2px);bottom:0;width:4px;z-index:4;cursor:ew-resize;touch-action:none}
|
|
48289
48475
|
.dvw-chat-resizer:hover,.dvw-chat-resizer:focus-visible,.dvw-chat-resizer[data-dragging=true]{background:var(--dvw-accent)}
|
|
48290
48476
|
.dvw-side-resizer,.dvw-chat-resizer{width:10px;cursor:ew-resize;touch-action:none;background:transparent}
|
|
48291
48477
|
.dvw-side-resizer{position:relative;transform:translateX(5px);z-index:22}
|
|
48292
|
-
.dvw-chat-resizer{position:fixed;top:
|
|
48478
|
+
.dvw-chat-resizer{position:fixed;top:var(--dvw-titlebar-height);right:calc(var(--dvw-chat-width) - 5px);z-index:22}
|
|
48293
48479
|
.dvw-side-resizer::after,.dvw-chat-resizer::after{content:"";position:absolute;top:0;bottom:0;left:4px;width:2px;background:var(--dvw-border)}
|
|
48294
48480
|
.dvw-chat-resizer::after{left:1px;width:6px}
|
|
48295
48481
|
.dvw-side-resizer:hover,.dvw-side-resizer:focus-visible,.dvw-side-resizer[data-dragging=true],.dvw-chat-resizer:hover,.dvw-chat-resizer:focus-visible,.dvw-chat-resizer[data-dragging=true]{background:transparent}
|
|
@@ -48299,7 +48485,10 @@ body[data-ds-dark-theme] .dvw-overlay,.dvw-overlay[data-dvw-theme=dark]{color-sc
|
|
|
48299
48485
|
.dvw-side-resizer:hover::after,.dvw-side-resizer:focus-visible::after,.dvw-side-resizer[data-dragging=true]::after,.dvw-chat-resizer:hover::after,.dvw-chat-resizer:focus-visible::after,.dvw-chat-resizer[data-dragging=true]::after{background:var(--dvw-accent)}
|
|
48300
48486
|
.dvw-chat-toggle{position:absolute;z-index:5;top:6px;right:6px;border:1px solid var(--dvw-border);background:var(--dvw-base)}
|
|
48301
48487
|
.dvw-overlay:not([data-dvw-chat=true]) .dvw-tabs{padding-right:36px}
|
|
48302
|
-
[data-dvw-conversation-panel]{position:fixed!important;top:
|
|
48488
|
+
[data-dvw-conversation-panel]{position:fixed!important;top:var(--dvw-titlebar-height)!important;right:0!important;bottom:var(--dvw-status-height,24px)!important;left:auto!important;width:var(--dvw-chat-width)!important;height:auto!important;min-width:0!important;z-index:21!important;border-left:1px solid var(--dsw-alias-border-l2)!important;box-shadow:none!important}
|
|
48489
|
+
body[data-dvw-workbench-active] [data-sidebar-right-expand],body[data-dvw-conversation-active] [data-sidebar-right-expand]{display:none!important}
|
|
48490
|
+
body[data-dvw-workbench-active] [data-shell-leading]{display:none!important}
|
|
48491
|
+
body[data-dvw-workbench-active] [data-sidebar-toggle]{display:none!important}
|
|
48303
48492
|
.dvw-confirm-backdrop{position:fixed;z-index:50;inset:0;display:grid;place-items:center;padding:24px;background:rgba(0,0,0,.38)}.dvw-confirm{width:min(380px,calc(100vw - 48px));border:1px solid var(--dvw-border);border-radius:7px;background:var(--dvw-surface-1);box-shadow:0 12px 36px rgba(0,0,0,.34);padding:18px}.dvw-confirm h2{margin:0 0 12px;font-size:15px}.dvw-confirm p{margin:0;color:var(--dvw-text)}.dvw-confirm-note{margin-top:8px!important;color:var(--dvw-text-3)!important;font-size:12px}.dvw-confirm footer{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}.dvw-confirm footer button{height:28px;border:1px solid var(--dvw-border);border-radius:4px;background:var(--dvw-surface-2);color:var(--dvw-text);padding:0 12px;font:inherit;cursor:pointer}.dvw-confirm footer button:hover{background:var(--dvw-hover)}.dvw-confirm footer .dvw-danger-button{border-color:color-mix(in srgb,var(--dvw-error) 65%,var(--dvw-border));background:var(--dvw-error);color:#fff}.dvw-confirm footer .dvw-danger-button:hover{background:color-mix(in srgb,var(--dvw-error) 82%,#000)}
|
|
48304
48493
|
.dvw-tree[data-dvw-native-drop-target=true]{outline:1px dashed var(--dvw-accent);outline-offset:-3px}.dvw-tree-row[data-dvw-native-drop-target=true]{background:var(--dvw-active)}
|
|
48305
48494
|
.dvw-act:disabled{opacity:.4;cursor:not-allowed}
|