diff --git a/build-plugin.sh b/build-plugin.sh
index bff287b..783970d 100755
--- a/build-plugin.sh
+++ b/build-plugin.sh
@@ -2,7 +2,7 @@
set -eu
PLUGIN="u-navigator"
-VERSION="2026.06.23.r036"
+VERSION="2026.06.23.r037"
PKG_DIR="packages"
WORK_DIR=".plugin-build"
PKG_NAME="${PLUGIN}-${VERSION}.tgz"
diff --git a/packages/u-navigator-2026.06.23.r036.tgz b/packages/u-navigator-2026.06.23.r036.tgz
deleted file mode 100644
index 2103495..0000000
Binary files a/packages/u-navigator-2026.06.23.r036.tgz and /dev/null differ
diff --git a/packages/u-navigator-2026.06.23.r037.tgz b/packages/u-navigator-2026.06.23.r037.tgz
new file mode 100644
index 0000000..07f3ed5
Binary files /dev/null and b/packages/u-navigator-2026.06.23.r037.tgz differ
diff --git a/server/public/app.js b/server/public/app.js
index a99d841..ffda5de 100644
--- a/server/public/app.js
+++ b/server/public/app.js
@@ -90,6 +90,8 @@ function openExplorer(initialPath = state.config?.roots?.[0]?.path) {
path: initialPath,
entries: [],
selectedPath: null,
+ selectedPaths: [],
+ selectionAnchorPath: null,
view: 'icons',
loading: false,
error: null
@@ -271,7 +273,7 @@ function renderExplorer(body, win) {
${data.error ? `
${escapeHtml(data.error)}
` : ''}
- ${data.loading ? '
Lade...
' : renderFileEntries(data.entries || [], data.view || 'list')}
+ ${data.loading ? '
Lade...
' : renderFileEntries(data.entries || [], data.view || 'list', selectedPathSet(win))}
`;
@@ -326,9 +328,9 @@ function renderExplorer(body, win) {
lockExplorerScroll(win, body);
startItemPointerDrag(event, win, entry);
});
- row.addEventListener('click', () => {
+ row.addEventListener('click', (event) => {
if (shouldSuppressItemActivation()) return;
- selectEntry(win, entry, body);
+ selectEntry(win, entry, body, event);
});
row.addEventListener('dblclick', () => {
if (shouldSuppressItemActivation()) return;
@@ -341,22 +343,22 @@ function renderExplorer(body, win) {
row.addEventListener('contextmenu', (event) => {
event.preventDefault();
event.stopPropagation();
- selectEntry(win, entry);
+ selectEntry(win, entry, null, event);
showContextMenu(event, win, entry);
});
}
}
-function renderFileEntries(entries, view) {
+function renderFileEntries(entries, view, selectedPaths = new Set()) {
if (!entries.length) {
return 'Dieser Ordner ist leer. Dateien können hier abgelegt werden.
';
}
- return view === 'icons' ? renderFileIcons(entries) : renderFileTable(entries);
+ return view === 'icons' ? renderFileIcons(entries, selectedPaths) : renderFileTable(entries, selectedPaths);
}
-function renderFileTable(entries) {
+function renderFileTable(entries, selectedPaths) {
const rows = entries.map((entry) => `
-
+
| ${icons[entry.type] || 'Item'}${escapeHtml(entry.name)} |
${entry.type} |
${entry.type === 'file' ? formatBytes(entry.size) : ''} |
@@ -372,9 +374,9 @@ function renderFileTable(entries) {
`;
}
-function renderFileIcons(entries) {
+function renderFileIcons(entries, selectedPaths) {
const items = entries.map((entry) => `
-