dsh-vscode-workbench 0.1.4 → 0.1.6
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 +229 -89
- package/lib/client.js.map +1 -1
- package/lib/index.js +16 -7
- package/lib/index.js.map +1 -1
- package/lib/types/client/DshMark.d.ts +0 -1
- package/lib/types/client/Workbench.d.ts +7 -0
- package/lib/types/client/api.d.ts +4 -0
- package/lib/types/types.d.ts +2 -2
- package/package.json +1 -1
- package/src/client/DshMark.tsx +8 -13
- package/src/client/Workbench.tsx +42 -18
- package/src/client/api.ts +6 -2
- package/src/client/styles.ts +2 -2
- package/src/host.ts +6 -3
- package/src/index.ts +5 -2
- package/src/types.ts +1 -1
package/lib/client.js
CHANGED
|
@@ -115,6 +115,13 @@ window.__ModuleLoader__.load({
|
|
|
115
115
|
};
|
|
116
116
|
//#endregion
|
|
117
117
|
//#region src/client/api.ts
|
|
118
|
+
var ApiError = class extends Error {
|
|
119
|
+
code;
|
|
120
|
+
constructor(code, message) {
|
|
121
|
+
super(message);
|
|
122
|
+
this.code = code;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
118
125
|
async function api(method, body, signal) {
|
|
119
126
|
const response = await fetch(`/dsh-vscode/api/${method}`, {
|
|
120
127
|
method: "POST",
|
|
@@ -123,7 +130,7 @@ window.__ModuleLoader__.load({
|
|
|
123
130
|
signal
|
|
124
131
|
});
|
|
125
132
|
const answer = await response.json();
|
|
126
|
-
if (!response.ok || !answer.ok) throw new
|
|
133
|
+
if (!response.ok || !answer.ok) throw new ApiError(answer.error?.code ?? "request-failed", answer.error?.message ?? `request failed (${response.status})`);
|
|
127
134
|
return answer.value;
|
|
128
135
|
}
|
|
129
136
|
//#endregion
|
|
@@ -4418,22 +4425,21 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4418
4425
|
}
|
|
4419
4426
|
//#endregion
|
|
4420
4427
|
//#region src/client/DshMark.tsx
|
|
4421
|
-
/**
|
|
4428
|
+
/** Bundled DSH fish logo — self-contained, no dependence on host DOM. */
|
|
4429
|
+
const WHALE_VIEWBOX = "0 0 23.16 17.04";
|
|
4430
|
+
const WHALE_PATH = "M22.9168 1.43018C22.6713 1.31018 22.5658 1.53918 22.4223 1.65519C22.3733 1.69269 22.3318 1.74169 22.2903 1.78669C21.9317 2.1697 21.5127 2.42121 20.9657 2.39121C20.1657 2.34621 19.4827 2.59771 18.8787 3.20973C18.7502 2.45521 18.3236 2.0047 17.6746 1.71569C17.3351 1.56568 16.9916 1.41518 16.7536 1.08867C16.5876 0.856163 16.5421 0.597155 16.4591 0.341647C16.4061 0.187643 16.3536 0.0301382 16.1761 0.00363739C15.9836 -0.0263635 15.9081 0.135141 15.8326 0.270145C15.5306 0.822162 15.4136 1.43018 15.4251 2.0462C15.4516 3.43174 16.0366 4.53527 17.1991 5.3203C17.3311 5.4103 17.3651 5.5003 17.3236 5.63181C17.2441 5.90231 17.1501 6.16482 17.0671 6.43533C17.0141 6.60784 16.9351 6.64584 16.7501 6.57033C16.1121 6.30383 15.5611 5.90931 15.074 5.4328C14.2475 4.63328 13.5 3.75075 12.568 3.05973C12.349 2.89822 12.13 2.74822 11.9034 2.60522C10.9524 1.68169 12.028 0.923165 12.277 0.833162C12.5375 0.739159 12.3675 0.41615 11.5259 0.42015C10.6844 0.42365 9.91439 0.705658 8.93286 1.08117C8.78935 1.13767 8.63835 1.17867 8.48384 1.21267C7.59332 1.04367 6.66829 1.00617 5.70226 1.11517C3.88321 1.31768 2.43016 2.1777 1.36213 3.64575C0.0790928 5.4103 -0.222916 7.41536 0.146595 9.50642C0.535106 11.7105 1.66014 13.535 3.38869 14.9616C5.18125 16.4406 7.24581 17.1657 9.60138 17.0266C11.0319 16.9441 12.6245 16.7526 14.421 15.2321C14.874 15.4576 15.3496 15.5476 16.1381 15.6151C16.7456 15.6716 17.3306 15.5851 17.7836 15.4911C18.4931 15.3411 18.4441 14.6841 18.1876 14.5636C16.1081 13.595 16.5646 13.9891 16.1496 13.67C17.2061 12.42 18.8202 10.1979 19.3182 7.17235C19.3672 6.83834 19.4297 6.36783 19.4222 6.09732C19.4182 5.93231 19.4562 5.86831 19.6447 5.84931C20.1657 5.78931 20.6712 5.64681 21.1357 5.3913C22.4833 4.65528 23.0268 3.44624 23.1548 1.9972C23.1738 1.77569 23.1508 1.54668 22.9168 1.43018ZM11.1749 14.4736C9.15936 12.889 8.18184 12.3675 7.77832 12.39C7.40081 12.4125 7.46881 12.8445 7.55182 13.126C7.63882 13.404 7.75182 13.5955 7.91033 13.8396C8.01983 14.0011 8.09533 14.2411 7.80083 14.4216C7.15181 14.8231 6.02327 14.2866 5.97027 14.2601C4.65673 13.4865 3.5587 12.4655 2.78467 11.069C2.03715 9.72493 1.60314 8.28289 1.53164 6.74384C1.51264 6.37233 1.62214 6.24082 1.99215 6.17332C2.47916 6.08332 2.98118 6.06432 3.46769 6.13582C5.52476 6.43633 7.27581 7.35586 8.74385 8.8129C9.58188 9.64243 10.2159 10.634 10.8689 11.6025C11.5634 12.631 12.3105 13.611 13.262 14.4146C13.598 14.6961 13.866 14.9101 14.1225 15.0681C13.349 15.1546 12.058 15.1731 11.1749 14.4746L11.1749 14.4736ZM12.141 8.25988C12.141 8.09488 12.273 7.96338 12.439 7.96338C12.4765 7.96338 12.5105 7.97088 12.541 7.98188C12.5825 7.99688 12.6205 8.01938 12.6505 8.05338C12.7035 8.10588 12.7335 8.18088 12.7335 8.25988C12.7335 8.42489 12.6015 8.55639 12.4355 8.55639C12.2695 8.55639 12.141 8.42489 12.141 8.25988ZM15.1415 9.79893C14.949 9.87793 14.7565 9.94544 14.5715 9.95294C14.2845 9.96794 13.9715 9.85143 13.8015 9.70893C13.5375 9.48742 13.3485 9.36342 13.2695 8.97691C13.2355 8.8119 13.2545 8.55639 13.2845 8.40989C13.3525 8.09438 13.277 7.89187 13.0545 7.70787C12.8735 7.55786 12.643 7.51636 12.39 7.51636C12.2955 7.51636 12.209 7.47486 12.1445 7.44136C12.039 7.38886 11.9519 7.25735 12.035 7.09585C12.0615 7.04335 12.19 6.91584 12.22 6.89334C12.5635 6.69784 12.9595 6.76184 13.326 6.90834C13.6655 7.04735 13.9225 7.30236 14.292 7.66287C14.6695 8.09838 14.7375 8.21838 14.9525 8.54539C15.1225 8.8009 15.277 9.06341 15.3831 9.36392C15.4471 9.55142 15.3641 9.70493 15.1415 9.79893Z";
|
|
4422
4431
|
function DshMark({ size = 18 }) {
|
|
4423
|
-
|
|
4424
|
-
(0, react.useLayoutEffect)(() => {
|
|
4425
|
-
const source = [...document.querySelectorAll("svg")].find((svg) => svg.getAttribute("viewBox") === "0 0 23.16 17.04" && !mount.current?.contains(svg));
|
|
4426
|
-
if (source === void 0 || mount.current === null) return;
|
|
4427
|
-
const logo = source.cloneNode(true);
|
|
4428
|
-
logo.setAttribute("width", String(size));
|
|
4429
|
-
logo.setAttribute("height", String(size * 17.04 / 23.16));
|
|
4430
|
-
mount.current.replaceChildren(logo);
|
|
4431
|
-
}, [size]);
|
|
4432
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4432
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
4433
4433
|
className: "dvw-dsh-mark",
|
|
4434
|
-
|
|
4434
|
+
width: size,
|
|
4435
|
+
height: size * 17.04 / 23.16,
|
|
4436
|
+
viewBox: WHALE_VIEWBOX,
|
|
4437
|
+
fill: "none",
|
|
4435
4438
|
"aria-hidden": "true",
|
|
4436
|
-
children: "
|
|
4439
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4440
|
+
d: WHALE_PATH,
|
|
4441
|
+
fill: "currentColor"
|
|
4442
|
+
})
|
|
4437
4443
|
});
|
|
4438
4444
|
}
|
|
4439
4445
|
//#endregion
|
|
@@ -4469,11 +4475,48 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4469
4475
|
};
|
|
4470
4476
|
//#endregion
|
|
4471
4477
|
//#region src/client/Workbench.tsx
|
|
4478
|
+
function unloadedTab(path) {
|
|
4479
|
+
return {
|
|
4480
|
+
path,
|
|
4481
|
+
content: "",
|
|
4482
|
+
draft: "",
|
|
4483
|
+
revision: "",
|
|
4484
|
+
size: 0,
|
|
4485
|
+
binary: false,
|
|
4486
|
+
tooLarge: false,
|
|
4487
|
+
dirty: false,
|
|
4488
|
+
loaded: false,
|
|
4489
|
+
preview: /\.md$/i.test(path)
|
|
4490
|
+
};
|
|
4491
|
+
}
|
|
4492
|
+
/** Restore tab headers without reading their file contents. */
|
|
4493
|
+
function restoreTabPaths(paths) {
|
|
4494
|
+
return [...new Set(paths)].map(unloadedTab);
|
|
4495
|
+
}
|
|
4496
|
+
/** Return whether file changes require reloading one visible directory. */
|
|
4497
|
+
function directoryAffected(directory, changedPaths) {
|
|
4498
|
+
return changedPaths.some((changed) => {
|
|
4499
|
+
const normalized = changed.replace(/\\/g, "/");
|
|
4500
|
+
const parent = normalized.includes("/") ? normalized.slice(0, normalized.lastIndexOf("/")) : "";
|
|
4501
|
+
return normalized === directory || parent === directory;
|
|
4502
|
+
});
|
|
4503
|
+
}
|
|
4472
4504
|
/** Return the basename shown in a tab while preserving its full internal path. */
|
|
4473
4505
|
function tabLabel(tab) {
|
|
4474
4506
|
const path = tab.title ?? tab.diffSourcePath ?? tab.path.replace(/^diff:/, "");
|
|
4475
4507
|
return path.split(/[\\/]/).at(-1) ?? path;
|
|
4476
4508
|
}
|
|
4509
|
+
/** Invoke `fn` at most once per `ms` after the latest call, always running the freshest callback. */
|
|
4510
|
+
function useDebouncedCallback(fn, ms) {
|
|
4511
|
+
const fnRef = (0, react.useRef)(fn);
|
|
4512
|
+
fnRef.current = fn;
|
|
4513
|
+
const timer = (0, react.useRef)();
|
|
4514
|
+
(0, react.useEffect)(() => () => clearTimeout(timer.current), []);
|
|
4515
|
+
return (0, react.useCallback)(() => {
|
|
4516
|
+
clearTimeout(timer.current);
|
|
4517
|
+
timer.current = setTimeout(() => fnRef.current(), ms);
|
|
4518
|
+
}, [ms]);
|
|
4519
|
+
}
|
|
4477
4520
|
function useDshDarkTheme() {
|
|
4478
4521
|
const read = () => document.body.hasAttribute("data-ds-dark-theme");
|
|
4479
4522
|
const [dark, setDark] = (0, react.useState)(read);
|
|
@@ -4487,7 +4530,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4487
4530
|
}, []);
|
|
4488
4531
|
return dark;
|
|
4489
4532
|
}
|
|
4490
|
-
function Tree({ sessionId, path, depth, expanded, selected, selectedDirectory, statuses, onToggle, onSelectDirectory, onOpen, onChange, onUpload }) {
|
|
4533
|
+
function Tree({ sessionId, path, depth, expanded, selected, selectedDirectory, statuses, onToggle, onSelectDirectory, onOpen, onChange, onUpload, creating, onCreatingChange, onCreatingCancel, onCreatingSubmit }) {
|
|
4491
4534
|
const [rows, setRows] = (0, react.useState)([]);
|
|
4492
4535
|
const [error, setError] = (0, react.useState)();
|
|
4493
4536
|
const [dropTarget, setDropTarget] = (0, react.useState)(false);
|
|
@@ -4502,7 +4545,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4502
4545
|
}, [sessionId, path]);
|
|
4503
4546
|
(0, react.useEffect)(load, [load]);
|
|
4504
4547
|
(0, react.useEffect)(() => {
|
|
4505
|
-
const handler = () =>
|
|
4548
|
+
const handler = (event) => {
|
|
4549
|
+
const paths = event.detail;
|
|
4550
|
+
if (paths === void 0 || directoryAffected(path, paths)) load();
|
|
4551
|
+
};
|
|
4506
4552
|
window.addEventListener("dvw-files-changed", handler);
|
|
4507
4553
|
return () => window.removeEventListener("dvw-files-changed", handler);
|
|
4508
4554
|
}, [load]);
|
|
@@ -4569,6 +4615,41 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4569
4615
|
className: "dvw-error",
|
|
4570
4616
|
children: error
|
|
4571
4617
|
}),
|
|
4618
|
+
creating?.directory === path && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4619
|
+
className: "dvw-tree-row dvw-tree-create-row",
|
|
4620
|
+
style: { paddingLeft: 6 + depth * 13 },
|
|
4621
|
+
children: [
|
|
4622
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "dvw-chevron" }),
|
|
4623
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
4624
|
+
name: creating.kind === "directory" ? "folder" : "new-file",
|
|
4625
|
+
className: `dvw-file-icon ${creating.kind === "directory" ? "folder" : ""}`
|
|
4626
|
+
}),
|
|
4627
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4628
|
+
className: "dvw-tree-create-input",
|
|
4629
|
+
value: creating.value,
|
|
4630
|
+
autoFocus: true,
|
|
4631
|
+
"aria-label": creating.kind === "directory" ? "新建文件夹名称" : "新建文件名称",
|
|
4632
|
+
"aria-invalid": creating.error !== void 0,
|
|
4633
|
+
placeholder: creating.kind === "directory" ? "文件夹名称" : "文件名称",
|
|
4634
|
+
onChange: (event) => onCreatingChange(event.target.value),
|
|
4635
|
+
onKeyDown: (event) => {
|
|
4636
|
+
if (event.key === "Enter") {
|
|
4637
|
+
event.preventDefault();
|
|
4638
|
+
onCreatingSubmit();
|
|
4639
|
+
}
|
|
4640
|
+
if (event.key === "Escape") {
|
|
4641
|
+
event.preventDefault();
|
|
4642
|
+
onCreatingCancel();
|
|
4643
|
+
}
|
|
4644
|
+
},
|
|
4645
|
+
onBlur: onCreatingCancel
|
|
4646
|
+
})
|
|
4647
|
+
]
|
|
4648
|
+
}), creating.error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4649
|
+
className: "dvw-tree-create-error",
|
|
4650
|
+
style: { paddingLeft: 42 + depth * 13 },
|
|
4651
|
+
children: creating.error
|
|
4652
|
+
})] }),
|
|
4572
4653
|
rows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4573
4654
|
className: "dvw-tree-row",
|
|
4574
4655
|
"data-dvw-upload-directory": row.kind === "directory" ? row.path : void 0,
|
|
@@ -4646,7 +4727,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4646
4727
|
onSelectDirectory,
|
|
4647
4728
|
onOpen,
|
|
4648
4729
|
onChange,
|
|
4649
|
-
onUpload
|
|
4730
|
+
onUpload,
|
|
4731
|
+
creating,
|
|
4732
|
+
onCreatingChange,
|
|
4733
|
+
onCreatingCancel,
|
|
4734
|
+
onCreatingSubmit
|
|
4650
4735
|
})] }, row.path)),
|
|
4651
4736
|
context && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4652
4737
|
className: "dvw-context-menu",
|
|
@@ -4722,6 +4807,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4722
4807
|
const [statuses, setStatuses] = (0, react.useState)(/* @__PURE__ */ new Map());
|
|
4723
4808
|
const [dropTarget, setDropTarget] = (0, react.useState)(false);
|
|
4724
4809
|
const [selectedDirectory, setSelectedDirectory] = (0, react.useState)("");
|
|
4810
|
+
const [creating, setCreating] = (0, react.useState)();
|
|
4725
4811
|
const picker = (0, react.useRef)(null);
|
|
4726
4812
|
(0, react.useEffect)(() => {
|
|
4727
4813
|
if (props.cwd) try {
|
|
@@ -4736,25 +4822,49 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4736
4822
|
const refreshStatus = (0, react.useCallback)(() => {
|
|
4737
4823
|
api("git.status", { sessionId: props.sessionId }).then((status) => setStatuses(new Map(status.changes.map((change) => [change.path, gitStatusCode(change)])))).catch(() => setStatuses(/* @__PURE__ */ new Map()));
|
|
4738
4824
|
}, [props.sessionId]);
|
|
4825
|
+
const refreshStatusDebounced = useDebouncedCallback(refreshStatus, 500);
|
|
4739
4826
|
(0, react.useEffect)(() => {
|
|
4740
4827
|
refreshStatus();
|
|
4741
|
-
const handler = () =>
|
|
4828
|
+
const handler = () => refreshStatusDebounced();
|
|
4742
4829
|
window.addEventListener("dvw-files-changed", handler);
|
|
4743
4830
|
return () => window.removeEventListener("dvw-files-changed", handler);
|
|
4744
|
-
}, [refreshStatus]);
|
|
4745
|
-
const
|
|
4746
|
-
const
|
|
4747
|
-
if (
|
|
4831
|
+
}, [refreshStatus, refreshStatusDebounced]);
|
|
4832
|
+
const startCreating = (kind) => {
|
|
4833
|
+
const directory = selectedDirectory;
|
|
4834
|
+
if (directory) setExpanded((current) => new Set(current).add(directory));
|
|
4835
|
+
setCreating({
|
|
4836
|
+
kind,
|
|
4837
|
+
directory,
|
|
4838
|
+
value: ""
|
|
4839
|
+
});
|
|
4840
|
+
};
|
|
4841
|
+
const submitCreating = async () => {
|
|
4842
|
+
if (creating === void 0) return;
|
|
4843
|
+
const value = creating.value.trim();
|
|
4844
|
+
if (value === "") {
|
|
4845
|
+
setCreating((current) => current && {
|
|
4846
|
+
...current,
|
|
4847
|
+
error: "请输入名称"
|
|
4848
|
+
});
|
|
4849
|
+
return;
|
|
4850
|
+
}
|
|
4851
|
+
const path = createdEntryPath(creating.directory, value);
|
|
4748
4852
|
try {
|
|
4749
4853
|
await api("fs.create", {
|
|
4750
4854
|
sessionId: props.sessionId,
|
|
4751
4855
|
path,
|
|
4752
|
-
kind
|
|
4856
|
+
kind: creating.kind
|
|
4753
4857
|
});
|
|
4858
|
+
const created = path;
|
|
4859
|
+
setCreating(void 0);
|
|
4860
|
+
setSelectedDirectory(creating.kind === "directory" ? created : creating.directory);
|
|
4754
4861
|
setRevision((x) => x + 1);
|
|
4755
4862
|
window.dispatchEvent(new Event("dvw-files-changed"));
|
|
4756
4863
|
} catch (error) {
|
|
4757
|
-
|
|
4864
|
+
setCreating((current) => current && {
|
|
4865
|
+
...current,
|
|
4866
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4867
|
+
});
|
|
4758
4868
|
}
|
|
4759
4869
|
};
|
|
4760
4870
|
const upload = (0, react.useCallback)(async (directory, files) => {
|
|
@@ -4865,13 +4975,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4865
4975
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4866
4976
|
className: "dvw-icon",
|
|
4867
4977
|
title: "新建文件",
|
|
4868
|
-
onClick: () =>
|
|
4978
|
+
onClick: () => startCreating("file"),
|
|
4869
4979
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "new-file" })
|
|
4870
4980
|
}),
|
|
4871
4981
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4872
4982
|
className: "dvw-icon",
|
|
4873
|
-
title: "
|
|
4874
|
-
onClick: () =>
|
|
4983
|
+
title: "新建文件夹",
|
|
4984
|
+
onClick: () => startCreating("directory"),
|
|
4875
4985
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "new-folder" })
|
|
4876
4986
|
}),
|
|
4877
4987
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -4909,7 +5019,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4909
5019
|
onSelectDirectory: setSelectedDirectory,
|
|
4910
5020
|
onOpen: props.onOpen,
|
|
4911
5021
|
onChange: () => setRevision((x) => x + 1),
|
|
4912
|
-
onUpload: (directory, files) => void upload(directory, files)
|
|
5022
|
+
onUpload: (directory, files) => void upload(directory, files),
|
|
5023
|
+
creating,
|
|
5024
|
+
onCreatingChange: (value) => setCreating((current) => current && {
|
|
5025
|
+
...current,
|
|
5026
|
+
value,
|
|
5027
|
+
error: void 0
|
|
5028
|
+
}),
|
|
5029
|
+
onCreatingCancel: () => setCreating(void 0),
|
|
5030
|
+
onCreatingSubmit: () => void submitCreating()
|
|
4913
5031
|
})
|
|
4914
5032
|
}, revision)] });
|
|
4915
5033
|
}
|
|
@@ -4917,6 +5035,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
4917
5035
|
function uploadDestination(selectedDirectory) {
|
|
4918
5036
|
return selectedDirectory ?? "";
|
|
4919
5037
|
}
|
|
5038
|
+
/** Join an inline-created entry name to the currently selected Explorer directory. */
|
|
5039
|
+
function createdEntryPath(directory, name) {
|
|
5040
|
+
return directory ? `${directory}/${name}` : name;
|
|
5041
|
+
}
|
|
4920
5042
|
/** Replace the final path component while preserving its workspace-relative directory. */
|
|
4921
5043
|
function renamedPath(path, name) {
|
|
4922
5044
|
return [...path.split("/").slice(0, -1), name].filter(Boolean).join("/");
|
|
@@ -5318,14 +5440,19 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5318
5440
|
setStatus(nextStatus);
|
|
5319
5441
|
setCommits(nextCommits);
|
|
5320
5442
|
setError(void 0);
|
|
5321
|
-
}).catch((error) =>
|
|
5443
|
+
}).catch((error) => {
|
|
5444
|
+
setStatus(void 0);
|
|
5445
|
+
setCommits([]);
|
|
5446
|
+
setError(error instanceof ApiError && error.code === "not-repository" ? void 0 : String(error));
|
|
5447
|
+
});
|
|
5322
5448
|
}, [props.sessionId]);
|
|
5449
|
+
const refreshDebounced = useDebouncedCallback(refresh, 500);
|
|
5323
5450
|
(0, react.useEffect)(refresh, [refresh]);
|
|
5324
5451
|
(0, react.useEffect)(() => {
|
|
5325
|
-
const fn = () =>
|
|
5452
|
+
const fn = () => refreshDebounced();
|
|
5326
5453
|
window.addEventListener("dvw-files-changed", fn);
|
|
5327
5454
|
return () => window.removeEventListener("dvw-files-changed", fn);
|
|
5328
|
-
}, [
|
|
5455
|
+
}, [refreshDebounced]);
|
|
5329
5456
|
const action = async (name, path, value) => {
|
|
5330
5457
|
setBusy(true);
|
|
5331
5458
|
try {
|
|
@@ -5586,6 +5713,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5586
5713
|
const tabsRef = (0, react.useRef)(tabs);
|
|
5587
5714
|
tabsRef.current = tabs;
|
|
5588
5715
|
const workspaceRequests = (0, react.useRef)(new WorkspaceRequestScope());
|
|
5716
|
+
const loadingTabs = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
5589
5717
|
const dshDark = useDshDarkTheme();
|
|
5590
5718
|
const [theme, setTheme] = (0, react.useState)(() => {
|
|
5591
5719
|
const saved = localStorage.getItem("dvw:theme");
|
|
@@ -5608,61 +5736,24 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5608
5736
|
window.addEventListener("keydown", onKey, true);
|
|
5609
5737
|
return () => window.removeEventListener("keydown", onKey, true);
|
|
5610
5738
|
}, [snapshot.visible]);
|
|
5611
|
-
const openForWorkspace =
|
|
5612
|
-
if (
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
}
|
|
5622
|
-
|
|
5623
|
-
const imageUrl = `/dsh-vscode/file?sessionId=${encodeURIComponent(targetSessionId)}&path=${encodeURIComponent(path)}`;
|
|
5624
|
-
if (!workspaceRequests.current.isCurrent(epoch)) return;
|
|
5625
|
-
setTabs((rows) => workspaceRequests.current.isCurrent(epoch) ? [...rows.filter((tab) => tab.path !== path), {
|
|
5626
|
-
path,
|
|
5627
|
-
content: "",
|
|
5628
|
-
draft: "",
|
|
5629
|
-
revision: "",
|
|
5630
|
-
size: 0,
|
|
5631
|
-
binary: false,
|
|
5632
|
-
tooLarge: false,
|
|
5633
|
-
dirty: false,
|
|
5634
|
-
imageUrl
|
|
5635
|
-
}] : rows);
|
|
5636
|
-
setActive(path);
|
|
5637
|
-
return;
|
|
5638
|
-
}
|
|
5639
|
-
try {
|
|
5640
|
-
const doc = await api("fs.read", {
|
|
5641
|
-
sessionId: targetSessionId,
|
|
5642
|
-
path
|
|
5643
|
-
});
|
|
5644
|
-
if (!workspaceRequests.current.isCurrent(epoch)) return;
|
|
5645
|
-
if (doc.binary || doc.tooLarge) {
|
|
5646
|
-
setError(doc.binary ? "二进制文件不能在文本编辑器中打开" : `文件超过 5 MiB:${path}`);
|
|
5647
|
-
return;
|
|
5648
|
-
}
|
|
5649
|
-
setTabs((rows) => workspaceRequests.current.isCurrent(epoch) ? [...rows.filter((tab) => tab.path !== path), {
|
|
5650
|
-
...doc,
|
|
5651
|
-
draft: doc.content,
|
|
5652
|
-
dirty: false,
|
|
5653
|
-
line,
|
|
5654
|
-
column,
|
|
5655
|
-
preview: /\.md$/i.test(path)
|
|
5656
|
-
}] : rows);
|
|
5657
|
-
setActive(path);
|
|
5658
|
-
} catch (error) {
|
|
5659
|
-
if (workspaceRequests.current.isCurrent(epoch)) setError(String(error));
|
|
5660
|
-
}
|
|
5739
|
+
const openForWorkspace = (path, line, column) => {
|
|
5740
|
+
if (tabsRef.current.find((tab) => tab.path === path)) setTabs((rows) => rows.map((tab) => tab.path === path ? {
|
|
5741
|
+
...tab,
|
|
5742
|
+
line,
|
|
5743
|
+
column
|
|
5744
|
+
} : tab));
|
|
5745
|
+
else setTabs((rows) => [...rows, {
|
|
5746
|
+
...unloadedTab(path),
|
|
5747
|
+
line,
|
|
5748
|
+
column
|
|
5749
|
+
}]);
|
|
5750
|
+
setActive(path);
|
|
5661
5751
|
};
|
|
5662
5752
|
(0, react.useEffect)(() => {
|
|
5663
5753
|
if (!snapshot.visible || sessionId === void 0) return;
|
|
5664
5754
|
const epoch = workspaceRequests.current.begin();
|
|
5665
5755
|
const cleared = resetWorkspaceDocuments();
|
|
5756
|
+
loadingTabs.current.clear();
|
|
5666
5757
|
setWorkspace(void 0);
|
|
5667
5758
|
setTabs(cleared.tabs);
|
|
5668
5759
|
tabsRef.current = cleared.tabs;
|
|
@@ -5678,13 +5769,16 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5678
5769
|
if (parsed.view) service.show(parsed.view);
|
|
5679
5770
|
if (typeof parsed.panelHeight === "number") setPanelHeight(parsed.panelHeight);
|
|
5680
5771
|
if (typeof parsed.sideWidth === "number") setSideWidth(Math.max(210, Math.min(640, Math.round(parsed.sideWidth))));
|
|
5681
|
-
|
|
5772
|
+
const restored = restoreTabPaths(parsed.paths ?? []);
|
|
5773
|
+
setTabs(restored);
|
|
5774
|
+
setActive(restored.some((tab) => tab.path === parsed.active) ? parsed.active : restored.at(-1)?.path);
|
|
5682
5775
|
} catch {}
|
|
5683
5776
|
}).catch((error) => {
|
|
5684
5777
|
if (!controller.signal.aborted && workspaceRequests.current.isCurrent(epoch)) setError(String(error));
|
|
5685
5778
|
});
|
|
5686
5779
|
return () => {
|
|
5687
5780
|
controller.abort();
|
|
5781
|
+
loadingTabs.current.clear();
|
|
5688
5782
|
workspaceRequests.current.invalidate(epoch);
|
|
5689
5783
|
};
|
|
5690
5784
|
}, [snapshot.visible, sessionId]);
|
|
@@ -5692,6 +5786,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5692
5786
|
if (workspace) localStorage.setItem(`dvw:${workspace.cwd}`, JSON.stringify({
|
|
5693
5787
|
view: snapshot.view,
|
|
5694
5788
|
paths: tabs.filter((t) => !t.path.startsWith("diff:")).map((t) => t.path),
|
|
5789
|
+
active,
|
|
5695
5790
|
panelHeight,
|
|
5696
5791
|
sideWidth
|
|
5697
5792
|
}));
|
|
@@ -5699,6 +5794,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5699
5794
|
workspace,
|
|
5700
5795
|
snapshot.view,
|
|
5701
5796
|
tabs,
|
|
5797
|
+
active,
|
|
5702
5798
|
panelHeight,
|
|
5703
5799
|
sideWidth
|
|
5704
5800
|
]);
|
|
@@ -5706,8 +5802,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5706
5802
|
if (!snapshot.visible || sessionId === void 0) return;
|
|
5707
5803
|
const protocol = location.protocol === "https:" ? "wss" : "ws";
|
|
5708
5804
|
const ws = new WebSocket(`${protocol}://${location.host}/dsh-vscode/ws/files?sessionId=${encodeURIComponent(sessionId)}`);
|
|
5709
|
-
ws.onmessage = () => {
|
|
5710
|
-
|
|
5805
|
+
ws.onmessage = (event) => {
|
|
5806
|
+
let paths = [];
|
|
5807
|
+
try {
|
|
5808
|
+
paths = JSON.parse(String(event.data)).paths ?? [];
|
|
5809
|
+
} catch {}
|
|
5810
|
+
window.dispatchEvent(new CustomEvent("dvw-files-changed", { detail: paths }));
|
|
5711
5811
|
setTabs((current) => current.map((tab) => tab.dirty ? {
|
|
5712
5812
|
...tab,
|
|
5713
5813
|
external: true
|
|
@@ -5715,9 +5815,49 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
5715
5815
|
};
|
|
5716
5816
|
return () => ws.close();
|
|
5717
5817
|
}, [snapshot.visible, sessionId]);
|
|
5718
|
-
|
|
5719
|
-
if (sessionId === void 0) return;
|
|
5720
|
-
|
|
5818
|
+
(0, react.useEffect)(() => {
|
|
5819
|
+
if (sessionId === void 0 || active === void 0) return;
|
|
5820
|
+
const tab = tabsRef.current.find((row) => row.path === active);
|
|
5821
|
+
if (tab === void 0 || tab.loaded !== false || loadingTabs.current.has(active)) return;
|
|
5822
|
+
const epoch = workspaceRequests.current.current();
|
|
5823
|
+
loadingTabs.current.add(active);
|
|
5824
|
+
if (/\.(?:avif|bmp|gif|ico|jpe?g|png|svg|webp)$/i.test(active)) {
|
|
5825
|
+
const imageUrl = `/dsh-vscode/file?sessionId=${encodeURIComponent(sessionId)}&path=${encodeURIComponent(active)}`;
|
|
5826
|
+
setTabs((rows) => rows.map((row) => row.path === active ? {
|
|
5827
|
+
...row,
|
|
5828
|
+
loaded: true,
|
|
5829
|
+
imageUrl
|
|
5830
|
+
} : row));
|
|
5831
|
+
loadingTabs.current.delete(active);
|
|
5832
|
+
return;
|
|
5833
|
+
}
|
|
5834
|
+
api("fs.read", {
|
|
5835
|
+
sessionId,
|
|
5836
|
+
path: active
|
|
5837
|
+
}).then((doc) => {
|
|
5838
|
+
if (!workspaceRequests.current.isCurrent(epoch)) return;
|
|
5839
|
+
if (doc.binary || doc.tooLarge) {
|
|
5840
|
+
setTabs((rows) => rows.filter((row) => row.path !== active));
|
|
5841
|
+
setActive((current) => current === active ? void 0 : current);
|
|
5842
|
+
setError(doc.binary ? "二进制文件不能在文本编辑器中打开" : `文件超过 5 MiB:${active}`);
|
|
5843
|
+
return;
|
|
5844
|
+
}
|
|
5845
|
+
setTabs((rows) => rows.map((row) => row.path === active ? {
|
|
5846
|
+
...row,
|
|
5847
|
+
...doc,
|
|
5848
|
+
draft: doc.content,
|
|
5849
|
+
loaded: true
|
|
5850
|
+
} : row));
|
|
5851
|
+
}).catch((error) => {
|
|
5852
|
+
if (workspaceRequests.current.isCurrent(epoch)) setError(String(error));
|
|
5853
|
+
}).finally(() => loadingTabs.current.delete(active));
|
|
5854
|
+
}, [
|
|
5855
|
+
active,
|
|
5856
|
+
sessionId,
|
|
5857
|
+
tabs
|
|
5858
|
+
]);
|
|
5859
|
+
const open = (path, line, column) => {
|
|
5860
|
+
if (sessionId !== void 0) openForWorkspace(path, line, column);
|
|
5721
5861
|
};
|
|
5722
5862
|
(0, react.useEffect)(() => {
|
|
5723
5863
|
const listener = (event) => void open(event.detail);
|
|
@@ -6301,7 +6441,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
6301
6441
|
body[data-ds-dark-theme] .dvw-overlay,.dvw-overlay[data-dvw-theme=dark]{color-scheme:dark}
|
|
6302
6442
|
.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}
|
|
6303
6443
|
.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}
|
|
6304
|
-
.dvw-overlay *{box-sizing:border-box}.dvw-activity{grid-row:1/3;background:var(--dvw-base);border-right:1px solid var(--dvw-border-soft);display:flex;flex-direction:column;align-items:center}.dvw-act{width:48px;height:48px;border:0;border-left:2px solid transparent;background:transparent;color:var(--dvw-text-3);font-size:22px;cursor:pointer}.dvw-act:hover,.dvw-act[data-active=true]{color:var(--dvw-text)}.dvw-act[data-active=true]{border-left-color:var(--dvw-accent)}.dvw-act.dsh{margin-top:auto}.dvw-side{grid-column:2;grid-row:1/3;min-width:0;width:100%;background:var(--dvw-surface-1);border-right:1px solid var(--dvw-border);display:flex;flex-direction:column}.dvw-side-resizer{grid-column:2;grid-row:1/3;justify-self:end;width:7px;height:100%;z-index:4;cursor:ew-resize;transform:translateX(3px);touch-action:none}.dvw-side-resizer:hover,.dvw-side-resizer:active{background:var(--dvw-accent)}.dvw-side-head{height:36px;display:flex;align-items:center;padding:0 12px;text-transform:uppercase;font-size:11px;letter-spacing:.4px}.dvw-toolbar{margin-left:auto;display:flex;gap:2px}.dvw-icon{border:0;background:transparent;color:var(--dvw-text-2);border-radius:4px;min-width:24px;height:24px;display:inline-grid;place-items:center;cursor:pointer}.dvw-icon:hover{background:var(--dvw-hover);color:var(--dvw-text)}.dvw-icon:disabled{opacity:.45;cursor:default}.dvw-file-picker{display:none}.dvw-tree,.dvw-results,.dvw-git{overflow:auto;flex:1}.dvw-tree[data-drop-target=true]{outline:1px dashed var(--dvw-accent);outline-offset:-3px}.dvw-tree-row{display:flex;align-items:center;height:24px;padding-right:6px;cursor:pointer;white-space:nowrap}.dvw-tree-row:hover{background:var(--dvw-hover)}.dvw-tree-row[data-selected=true],.dvw-tree-row[data-drop-target=true]{background:var(--dvw-active)}.dvw-chevron{width:16px;text-align:center;color:var(--dvw-text-3)}.dvw-file-icon{width:18px;color:var(--dvw-text-2)}.dvw-file-icon.folder{color:var(--dvw-accent)}.dvw-tree-name{overflow:hidden;text-overflow:ellipsis}.dvw-tree-rename{min-width:0;flex:1;height:20px;border:1px solid var(--dvw-accent);background:var(--dvw-surface-1);color:var(--dvw-text);font:inherit;outline:0}.dvw-tree-status{margin-left:auto;padding-left:6px;font-size:11px;font-weight:600;color:var(--dvw-warn)}.dvw-tree-status[data-status=M]{color:var(--dvw-warn)}.dvw-tree-status[data-status=A]{color:var(--dvw-success)}.dvw-tree-status[data-status=D]{color:var(--dvw-error)}.dvw-context-menu{position:fixed;z-index:40;min-width:148px;padding:4px;border:1px solid var(--dvw-border);border-radius:5px;background:var(--dvw-surface-3);box-shadow:0 6px 20px rgba(0,0,0,.3)}.dvw-context-menu button{width:100%;height:28px;border:0;border-radius:3px;background:transparent;color:var(--dvw-text);display:flex;align-items:center;gap:8px;padding:0 8px;text-align:left;font:inherit;cursor:pointer}.dvw-context-menu button:hover{background:var(--dvw-hover)}.dvw-context-menu .dvw-context-delete{color:var(--dvw-error)}
|
|
6444
|
+
.dvw-overlay *{box-sizing:border-box}.dvw-activity{grid-row:1/3;background:var(--dvw-base);border-right:1px solid var(--dvw-border-soft);display:flex;flex-direction:column;align-items:center}.dvw-act{width:48px;height:48px;border:0;border-left:2px solid transparent;background:transparent;color:var(--dvw-text-3);font-size:22px;cursor:pointer}.dvw-act:hover,.dvw-act[data-active=true]{color:var(--dvw-text)}.dvw-act[data-active=true]{border-left-color:var(--dvw-accent)}.dvw-act.dsh{margin-top:auto}.dvw-side{grid-column:2;grid-row:1/3;min-width:0;width:100%;background:var(--dvw-surface-1);border-right:1px solid var(--dvw-border);display:flex;flex-direction:column}.dvw-side-resizer{grid-column:2;grid-row:1/3;justify-self:end;width:7px;height:100%;z-index:4;cursor:ew-resize;transform:translateX(3px);touch-action:none}.dvw-side-resizer:hover,.dvw-side-resizer:active{background:var(--dvw-accent)}.dvw-side-head{height:36px;display:flex;align-items:center;padding:0 12px;text-transform:uppercase;font-size:11px;letter-spacing:.4px}.dvw-toolbar{margin-left:auto;display:flex;gap:2px}.dvw-icon{border:0;background:transparent;color:var(--dvw-text-2);border-radius:4px;min-width:24px;height:24px;display:inline-grid;place-items:center;cursor:pointer}.dvw-icon:hover{background:var(--dvw-hover);color:var(--dvw-text)}.dvw-icon:disabled{opacity:.45;cursor:default}.dvw-file-picker{display:none}.dvw-tree,.dvw-results,.dvw-git{overflow:auto;flex:1}.dvw-tree[data-drop-target=true]{outline:1px dashed var(--dvw-accent);outline-offset:-3px}.dvw-tree-row{display:flex;align-items:center;height:24px;padding-right:6px;cursor:pointer;white-space:nowrap}.dvw-tree-row:hover{background:var(--dvw-hover)}.dvw-tree-row[data-selected=true],.dvw-tree-row[data-drop-target=true]{background:var(--dvw-active)}.dvw-chevron{width:16px;flex:none;text-align:center;color:var(--dvw-text-3)}.dvw-file-icon{width:18px;flex:none;color:var(--dvw-text-2)}.dvw-file-icon.folder{color:var(--dvw-accent)}.dvw-tree-name{overflow:hidden;text-overflow:ellipsis}.dvw-tree-rename,.dvw-tree-create-input{min-width:0;flex:1;height:20px;border:1px solid var(--dvw-accent);border-radius:0;background:var(--dvw-surface-1);color:var(--dvw-text);padding:0 3px;font:inherit;letter-spacing:0;outline:0}.dvw-tree-create-row{cursor:text}.dvw-tree-create-row:hover{background:transparent}.dvw-tree-create-input::placeholder{color:var(--dvw-text-3)}.dvw-tree-create-input[aria-invalid=true]{border-color:var(--dvw-error)}.dvw-tree-create-error{min-height:20px;padding-top:2px;padding-right:6px;padding-bottom:3px;color:var(--dvw-error);font-size:11px;line-height:15px;white-space:normal;overflow-wrap:anywhere}.dvw-tree-status{margin-left:auto;padding-left:6px;font-size:11px;font-weight:600;color:var(--dvw-warn)}.dvw-tree-status[data-status=M]{color:var(--dvw-warn)}.dvw-tree-status[data-status=A]{color:var(--dvw-success)}.dvw-tree-status[data-status=D]{color:var(--dvw-error)}.dvw-context-menu{position:fixed;z-index:40;min-width:148px;padding:4px;border:1px solid var(--dvw-border);border-radius:5px;background:var(--dvw-surface-3);box-shadow:0 6px 20px rgba(0,0,0,.3)}.dvw-context-menu button{width:100%;height:28px;border:0;border-radius:3px;background:transparent;color:var(--dvw-text);display:flex;align-items:center;gap:8px;padding:0 8px;text-align:left;font:inherit;cursor:pointer}.dvw-context-menu button:hover{background:var(--dvw-hover)}.dvw-context-menu .dvw-context-delete{color:var(--dvw-error)}
|
|
6305
6445
|
.dvw-main{grid-column:3;grid-row:1;display:flex;min-width:0;min-height:0;flex-direction:column;background:var(--dvw-surface-1)}.dvw-tabs{height:36px;background:var(--dvw-base);display:flex;overflow-x:auto}.dvw-tab{height:36px;min-width:110px;max-width:260px;border:0;border-right:1px solid var(--dvw-border-soft);background:var(--dvw-base);color:var(--dvw-text-2);padding:0 8px 0 12px;display:flex;align-items:center;gap:8px;cursor:pointer}.dvw-tab[data-active=true]{background:var(--dvw-surface-1);color:var(--dvw-text);border-top:1px solid var(--dvw-accent)}.dvw-tab-name{overflow:hidden;text-overflow:ellipsis;flex:1;text-align:left}.dvw-editor{position:relative;flex:1;min-height:0}.dvw-editor-toolbar{position:absolute;z-index:3;top:0;right:0;left:0;height:36px;display:flex;align-items:center;justify-content:flex-end;gap:4px;padding:0 10px;border-bottom:1px solid var(--dvw-border-soft);background:var(--dvw-surface-1)}.dvw-editor-body{position:absolute;inset:0;min-height:0}.dvw-editor-body[data-toolbar=true]{top:36px}.dvw-mode-button{height:27px;padding:0 10px;display:flex;align-items:center;gap:6px;border:1px solid transparent;border-radius:5px;background:transparent;color:var(--dvw-text-2);cursor:pointer}.dvw-mode-button:hover{background:var(--dvw-hover)}.dvw-mode-button[data-active=true]{border-color:var(--dvw-border);background:var(--dvw-active);color:var(--dvw-text)}.dvw-empty{height:100%;display:grid;place-items:center;color:var(--dvw-text-3);text-align:center}.dvw-empty strong{font-size:24px;color:var(--dvw-text-2)}.dvw-message{padding:12px;color:var(--dvw-warn)}
|
|
6306
6446
|
.dvw-bottom{grid-column:3;grid-row:2;height:260px;min-height:120px;border-top:1px solid var(--dvw-border);background:var(--dvw-base);display:flex;flex-direction:column}.dvw-bottom-head{height:35px;display:flex;align-items:center;gap:14px;padding:0 12px}.dvw-bottom-title{border:0;border-bottom:1px solid var(--dvw-text);background:transparent;color:var(--dvw-text);height:35px}.dvw-bottom-body{flex:1;min-height:0}.dvw-status{grid-column:1/4;grid-row:3;background:var(--dvw-accent);color:#fff;display:flex;align-items:center;padding:0 8px;gap:18px;font-size:12px}.dvw-theme-control{position:relative;margin-left:auto}.dvw-theme-trigger{height:22px;min-width:112px;display:flex;align-items:center;gap:7px;padding:0 8px;border:0;border-radius:5px;background:color-mix(in srgb,#000 17%,transparent);color:#fff;cursor:pointer}.dvw-theme-trigger:hover{background:color-mix(in srgb,#000 27%,transparent)}.dvw-theme-orb{width:13px;height:13px;border:2px solid #fff;border-radius:50%;background:linear-gradient(90deg,#17181c 50%,#fff 50%)}.dvw-theme-orb.dark{background:#17181c}.dvw-theme-orb.light{background:#fff}.dvw-theme-menu{position:absolute;right:0;bottom:29px;width:224px;padding:6px;border:1px solid var(--dvw-border);border-radius:10px;background:var(--dvw-surface-3);box-shadow:0 10px 35px rgba(0,0,0,.28);color:var(--dvw-text)}.dvw-theme-menu button{width:100%;min-height:48px;border:0;border-radius:7px;background:transparent;color:inherit;display:grid;grid-template-columns:30px 1fr 20px;align-items:center;text-align:left;padding:6px;cursor:pointer}.dvw-theme-menu button:hover,.dvw-theme-menu button[aria-checked=true]{background:var(--dvw-hover)}.dvw-theme-menu strong,.dvw-theme-menu small{display:block}.dvw-theme-menu small{color:var(--dvw-text-3);margin-top:2px}.dvw-theme-swatch{width:22px;height:22px;border-radius:6px;border:1px solid var(--dvw-border);background:linear-gradient(135deg,#17181c 0 50%,#fff 50%)}.dvw-theme-swatch.dark{background:#17181c}.dvw-theme-swatch.light{background:#fff}
|
|
6307
6447
|
.dvw-search-form{padding:8px;display:grid;gap:6px}.dvw-input,.dvw-textarea,.dvw-select{width:100%;border:1px solid var(--dvw-border);background:var(--dvw-surface-2);color:var(--dvw-text);padding:5px 7px;outline:none}.dvw-input:focus,.dvw-textarea:focus,.dvw-select:focus{border-color:var(--dvw-accent)}.dvw-options{display:flex;align-items:center;gap:8px;font-size:11px}.dvw-result-file{padding:5px 8px;font-weight:600}.dvw-result{padding:4px 8px 4px 20px;cursor:pointer;display:flex;gap:8px}.dvw-result:hover{background:var(--dvw-hover)}.dvw-line{color:var(--dvw-text-3);min-width:30px;text-align:right}.dvw-preview{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
@@ -6319,7 +6459,7 @@ body[data-ds-dark-theme] .dvw-overlay,.dvw-overlay[data-dvw-theme=dark]{color-sc
|
|
|
6319
6459
|
.dvw-chat{grid-column:4;grid-row:1/3;min-width:0;background:var(--dvw-base);border-left:1px solid var(--dvw-border);position:relative}
|
|
6320
6460
|
.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}
|
|
6321
6461
|
.dvw-chat-head>span{display:flex;align-items:center;gap:7px}.dvw-chat-body{height:calc(100% - 36px);background:var(--dvw-base)}
|
|
6322
|
-
.dvw-dsh-mark{
|
|
6462
|
+
.dvw-dsh-mark{display:block}
|
|
6323
6463
|
.dvw-chat-resizer{position:fixed;top:0;right:calc(var(--dvw-chat-width) - 4px);bottom:0;width:8px;z-index:4;cursor:ew-resize;touch-action:none}
|
|
6324
6464
|
.dvw-chat-resizer:hover,.dvw-chat-resizer:active{background:var(--dvw-accent)}
|
|
6325
6465
|
.dvw-chat-toggle{position:absolute;z-index:5;top:6px;right:6px;border:1px solid var(--dvw-border);background:var(--dvw-base)}
|