@dong-victor/dsh-better-sidebar-starter 0.1.8 → 0.1.10
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 +53 -77
- package/lib/client.js.map +1 -1
- package/lib/index.js +48 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -108,6 +108,14 @@ window.__ModuleLoader__.load({
|
|
|
108
108
|
function FolderIcon({ size }) {
|
|
109
109
|
return svg(size, `<path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" fill="currentColor" opacity="0.7"/>`);
|
|
110
110
|
}
|
|
111
|
+
/** 👁 Eye — hidden entries are shown (Material visibility). */
|
|
112
|
+
function EyeIcon({ size }) {
|
|
113
|
+
return svg(size, `<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="currentColor"/>`);
|
|
114
|
+
}
|
|
115
|
+
/** 🙈 Eye off — hidden entries are concealed (Material visibility_off). */
|
|
116
|
+
function EyeOffIcon({ size }) {
|
|
117
|
+
return svg(size, `<path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z" fill="currentColor"/>`);
|
|
118
|
+
}
|
|
111
119
|
/** 📋 Clipboard — bulk paste env. */
|
|
112
120
|
function ClipboardIcon({ size }) {
|
|
113
121
|
return svg(size, `<path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z" fill="currentColor"/>`);
|
|
@@ -1089,29 +1097,34 @@ window.__ModuleLoader__.load({
|
|
|
1089
1097
|
//#endregion
|
|
1090
1098
|
//#region src/client/DirChooser.tsx
|
|
1091
1099
|
/**
|
|
1092
|
-
* Shared directory chooser: a filesystem folder tree (backed by the
|
|
1093
|
-
*
|
|
1094
|
-
*
|
|
1095
|
-
*
|
|
1096
|
-
*
|
|
1100
|
+
* Shared directory chooser: a filesystem folder tree (backed by the starter
|
|
1101
|
+
* plugin's own fs-dirs host route) plus a browse button that opens a modal
|
|
1102
|
+
* popup. Browsing starts at the user's home directory and can navigate up to
|
|
1103
|
+
* any drive/root, so runtime tool paths (JDK/Maven/...) that live outside the
|
|
1104
|
+
* workspace can be selected. The sidebar fs.tree API cannot be used here — it
|
|
1105
|
+
* is workspace-confined since dsh-better-sidebar 0.16 (403 outside the
|
|
1106
|
+
* session workspace).
|
|
1097
1107
|
* @module dsh-better-sidebar-starter/client/DirChooser
|
|
1098
1108
|
*/
|
|
1099
|
-
/** Call the
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
};
|
|
1105
|
-
if (scope.cwd !== void 0 && scope.cwd !== "") payload.cwd = scope.cwd;
|
|
1106
|
-
const resp = await fetch("/sidebar/api/fs.tree", {
|
|
1109
|
+
/** Call the starter fs-dirs host route via fetch. Returns directories only,
|
|
1110
|
+
* INCLUDING hidden ones (flagged via `hidden`) — visibility is decided at
|
|
1111
|
+
* render time so the show-hidden toggle works without refetching. */
|
|
1112
|
+
async function fsTree(scope, path) {
|
|
1113
|
+
const resp = await fetch("/api/dsh-better-sidebar-starter/fs-dirs", {
|
|
1107
1114
|
method: "POST",
|
|
1108
1115
|
headers: { "content-type": "application/json" },
|
|
1109
|
-
body: JSON.stringify(
|
|
1116
|
+
body: JSON.stringify({
|
|
1117
|
+
sessionId: scope.sessionId,
|
|
1118
|
+
path
|
|
1119
|
+
})
|
|
1110
1120
|
});
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1121
|
+
const parsed = await resp.json().catch(() => void 0);
|
|
1122
|
+
if (!resp.ok) throw new Error(`fs-dirs ${path}: ${parsed?.error ?? resp.status}`);
|
|
1123
|
+
return (parsed?.entries ?? []).filter((e) => e.isDir);
|
|
1124
|
+
}
|
|
1125
|
+
/** Render-time hidden-entry filter shared by the tree components. */
|
|
1126
|
+
function visibleDirs(entries, showHidden) {
|
|
1127
|
+
return showHidden ? entries : entries.filter((e) => !e.hidden);
|
|
1115
1128
|
}
|
|
1116
1129
|
/** Fetch the user's home directory from the host. Falls back to cwd. */
|
|
1117
1130
|
async function fetchHomeDefault(scope) {
|
|
@@ -1139,6 +1152,7 @@ window.__ModuleLoader__.load({
|
|
|
1139
1152
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
1140
1153
|
const [error, setError] = (0, react.useState)(null);
|
|
1141
1154
|
const [expanded, setExpanded] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
1155
|
+
const [showHidden, setShowHidden] = (0, react.useState)(false);
|
|
1142
1156
|
const scopeRef = (0, react.useRef)(scope);
|
|
1143
1157
|
const initDoneRef = (0, react.useRef)(false);
|
|
1144
1158
|
const initialValueRef = (0, react.useRef)(selectedPath);
|
|
@@ -1163,7 +1177,7 @@ window.__ModuleLoader__.load({
|
|
|
1163
1177
|
const loadDir = (s, path) => {
|
|
1164
1178
|
setLoading(true);
|
|
1165
1179
|
setError(null);
|
|
1166
|
-
fsTree
|
|
1180
|
+
fsTree(s, path).then((dirs) => {
|
|
1167
1181
|
setEntries(dirs);
|
|
1168
1182
|
setLoading(false);
|
|
1169
1183
|
}).catch((err) => {
|
|
@@ -1200,7 +1214,15 @@ window.__ModuleLoader__.load({
|
|
|
1200
1214
|
className: "sts-dirtree-home",
|
|
1201
1215
|
onClick: () => loadDir(scopeRef.current, cur),
|
|
1202
1216
|
title: "刷新"
|
|
1203
|
-
}, "↻"), (0, react.createElement)("
|
|
1217
|
+
}, "↻"), (0, react.createElement)("button", {
|
|
1218
|
+
className: "sts-dirtree-home",
|
|
1219
|
+
onClick: () => setShowHidden(!showHidden),
|
|
1220
|
+
title: showHidden ? "隐藏隐藏目录" : "显示隐藏目录",
|
|
1221
|
+
style: showHidden ? {
|
|
1222
|
+
color: "#61afef",
|
|
1223
|
+
opacity: 1
|
|
1224
|
+
} : { opacity: .6 }
|
|
1225
|
+
}, (0, react.createElement)(showHidden ? EyeIcon : EyeOffIcon, { size: 13 })), (0, react.createElement)("span", {
|
|
1204
1226
|
className: "sts-dirtree-cur",
|
|
1205
1227
|
title: cur
|
|
1206
1228
|
}, cur || "(.)")), (0, react.createElement)("div", {
|
|
@@ -1213,13 +1235,14 @@ window.__ModuleLoader__.load({
|
|
|
1213
1235
|
}, "加载中...") : error !== null ? (0, react.createElement)("div", {
|
|
1214
1236
|
className: "sts-tree-error",
|
|
1215
1237
|
style: { paddingLeft: "16px" }
|
|
1216
|
-
}, error) : entries !== null && entries.length > 0 ? (0, react.createElement)("div", { className: "sts-dirtree-sub" }, ...entries.map((entry) => (0, react.createElement)(DirRow, {
|
|
1238
|
+
}, error) : entries !== null && visibleDirs(entries, showHidden).length > 0 ? (0, react.createElement)("div", { className: "sts-dirtree-sub" }, ...visibleDirs(entries, showHidden).map((entry) => (0, react.createElement)(DirRow, {
|
|
1217
1239
|
key: entry.path,
|
|
1218
1240
|
scope,
|
|
1219
1241
|
entry,
|
|
1220
1242
|
depth: 1,
|
|
1221
1243
|
selectedPath,
|
|
1222
1244
|
expanded,
|
|
1245
|
+
showHidden,
|
|
1223
1246
|
onToggleExpand: toggleExpand,
|
|
1224
1247
|
onPick,
|
|
1225
1248
|
onNavigate: navigateInto
|
|
@@ -1230,7 +1253,7 @@ window.__ModuleLoader__.load({
|
|
|
1230
1253
|
}
|
|
1231
1254
|
/** One directory row with recursive expansion + click into. */
|
|
1232
1255
|
function DirRow(props) {
|
|
1233
|
-
const { scope, entry, depth, selectedPath, expanded, onToggleExpand, onPick, onNavigate } = props;
|
|
1256
|
+
const { scope, entry, depth, selectedPath, expanded, showHidden, onToggleExpand, onPick, onNavigate } = props;
|
|
1234
1257
|
const [children, setChildren] = (0, react.useState)(null);
|
|
1235
1258
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
1236
1259
|
const isExpanded = expanded.has(entry.path);
|
|
@@ -1244,7 +1267,7 @@ window.__ModuleLoader__.load({
|
|
|
1244
1267
|
onToggleExpand(entry.path);
|
|
1245
1268
|
if (children === null) {
|
|
1246
1269
|
setLoading(true);
|
|
1247
|
-
fsTree
|
|
1270
|
+
fsTree(scope, entry.path).then((dirs) => {
|
|
1248
1271
|
setChildren(dirs);
|
|
1249
1272
|
setLoading(false);
|
|
1250
1273
|
}).catch(() => {
|
|
@@ -1260,13 +1283,14 @@ window.__ModuleLoader__.load({
|
|
|
1260
1283
|
}, (0, react.createElement)("span", { className: `sts-tree-chevron${isExpanded ? " expanded" : ""}` }, (0, react.createElement)(isExpanded ? ChevronDownIcon : ChevronRightIcon, { size: 12 })), (0, react.createElement)("span", { className: "sts-tree-icon" }, (0, react.createElement)(FolderIcon, { size: 14 })), (0, react.createElement)("span", { className: "sts-tree-label" }, entry.name)), isExpanded ? loading ? (0, react.createElement)("div", {
|
|
1261
1284
|
className: "sts-tree-loading",
|
|
1262
1285
|
style: { paddingLeft: `${(depth + 1) * 16 + 8}px` }
|
|
1263
|
-
}, "加载中...") : children !== null && children.length > 0 ? (0, react.createElement)("div", null, ...children.map((child) => (0, react.createElement)(DirRow, {
|
|
1286
|
+
}, "加载中...") : children !== null && visibleDirs(children, showHidden).length > 0 ? (0, react.createElement)("div", null, ...visibleDirs(children, showHidden).map((child) => (0, react.createElement)(DirRow, {
|
|
1264
1287
|
key: child.path,
|
|
1265
1288
|
scope,
|
|
1266
1289
|
entry: child,
|
|
1267
1290
|
depth: depth + 1,
|
|
1268
1291
|
selectedPath,
|
|
1269
1292
|
expanded,
|
|
1293
|
+
showHidden,
|
|
1270
1294
|
onToggleExpand,
|
|
1271
1295
|
onPick,
|
|
1272
1296
|
onNavigate: props.onNavigate
|
|
@@ -1356,23 +1380,6 @@ window.__ModuleLoader__.load({
|
|
|
1356
1380
|
* and environment variables.
|
|
1357
1381
|
* @module dsh-better-sidebar-starter/client/ConfigEditorModal
|
|
1358
1382
|
*/
|
|
1359
|
-
/** Call the sidebar fs.tree API directly via fetch. Returns directories only.
|
|
1360
|
-
* If path is omitted, the server uses the session cwd (root listing).
|
|
1361
|
-
* The sidebar API wraps responses in { ok: true, value: ... } envelope. */
|
|
1362
|
-
async function fsTree(scope, path) {
|
|
1363
|
-
const payload = { sessionId: scope.sessionId };
|
|
1364
|
-
if (scope.cwd !== void 0 && scope.cwd !== "") payload.cwd = scope.cwd;
|
|
1365
|
-
if (path !== void 0) payload.path = path;
|
|
1366
|
-
const resp = await fetch("/sidebar/api/fs.tree", {
|
|
1367
|
-
method: "POST",
|
|
1368
|
-
headers: { "content-type": "application/json" },
|
|
1369
|
-
body: JSON.stringify(payload)
|
|
1370
|
-
});
|
|
1371
|
-
if (!resp.ok) throw new Error(`fs.tree ${path ?? "(root)"}: ${resp.status}`);
|
|
1372
|
-
const parsed = await resp.json();
|
|
1373
|
-
if (!parsed.ok || parsed.value === void 0) throw new Error(`fs.tree ${path ?? "(root)"}: ${parsed.error?.message ?? "unknown error"}`);
|
|
1374
|
-
return parsed.value.entries.filter((e) => e.isDir && !e.hidden);
|
|
1375
|
-
}
|
|
1376
1383
|
/** Recursive tree node: loads its own children on expand. */
|
|
1377
1384
|
function TreeNode(props) {
|
|
1378
1385
|
const { scope, entry, depth, selectedPath, onSelect } = props;
|
|
@@ -1383,7 +1390,7 @@ window.__ModuleLoader__.load({
|
|
|
1383
1390
|
if (!expanded && children === null) {
|
|
1384
1391
|
setLoading(true);
|
|
1385
1392
|
fsTree(scope, entry.path).then((dirs) => {
|
|
1386
|
-
setChildren(dirs);
|
|
1393
|
+
setChildren(dirs.filter((d) => !d.hidden));
|
|
1387
1394
|
setLoading(false);
|
|
1388
1395
|
}).catch(() => {
|
|
1389
1396
|
setChildren([]);
|
|
@@ -1426,8 +1433,9 @@ window.__ModuleLoader__.load({
|
|
|
1426
1433
|
if (!expanded && children === null) {
|
|
1427
1434
|
setLoading(true);
|
|
1428
1435
|
setError(null);
|
|
1429
|
-
|
|
1430
|
-
|
|
1436
|
+
const root = scope.cwd ?? "";
|
|
1437
|
+
(root === "" ? Promise.reject(/* @__PURE__ */ new Error("fs-dirs: 会话工作目录不可用")) : fsTree(scope, root)).then((dirs) => {
|
|
1438
|
+
setChildren(dirs.filter((d) => !d.hidden));
|
|
1431
1439
|
setLoading(false);
|
|
1432
1440
|
}).catch((err) => {
|
|
1433
1441
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -3104,39 +3112,7 @@ window.__ModuleLoader__.load({
|
|
|
3104
3112
|
icon: (size) => (0, react.createElement)(RocketIcon, { size }),
|
|
3105
3113
|
order: 50,
|
|
3106
3114
|
single: true,
|
|
3107
|
-
settings: {
|
|
3108
|
-
pluginToggles: [
|
|
3109
|
-
{
|
|
3110
|
-
key: "autoSelectOnStart",
|
|
3111
|
-
type: "switch",
|
|
3112
|
-
title: "启动后自动选中日志"
|
|
3113
|
-
},
|
|
3114
|
-
{
|
|
3115
|
-
key: "autoScroll",
|
|
3116
|
-
type: "switch",
|
|
3117
|
-
title: "自动滚动到最新日志"
|
|
3118
|
-
},
|
|
3119
|
-
{
|
|
3120
|
-
key: "javaHome",
|
|
3121
|
-
type: "text",
|
|
3122
|
-
title: "Java 主目录 (JAVA_HOME)",
|
|
3123
|
-
desc: "Spring Boot 用的 JDK 路径,留空则自动查找"
|
|
3124
|
-
},
|
|
3125
|
-
{
|
|
3126
|
-
key: "nodePath",
|
|
3127
|
-
type: "text",
|
|
3128
|
-
title: "Node.js 路径",
|
|
3129
|
-
desc: "npm 命令用的 Node 路径,留空则用系统默认"
|
|
3130
|
-
},
|
|
3131
|
-
{
|
|
3132
|
-
key: "pythonPath",
|
|
3133
|
-
type: "text",
|
|
3134
|
-
title: "Python 路径",
|
|
3135
|
-
desc: "Python 命令用的解释器路径,留空则用系统默认"
|
|
3136
|
-
}
|
|
3137
|
-
],
|
|
3138
|
-
render: (props) => (0, react.createElement)(SettingsPanel, props)
|
|
3139
|
-
},
|
|
3115
|
+
settings: { render: (props) => (0, react.createElement)(SettingsPanel, props) },
|
|
3140
3116
|
component: (props) => (0, react.createElement)(ServicesTab, props)
|
|
3141
3117
|
}), "dsh-better-sidebar-starter: services tab");
|
|
3142
3118
|
}
|