diff --git a/build-plugin.sh b/build-plugin.sh index 60228e6..bc6e6e7 100755 --- a/build-plugin.sh +++ b/build-plugin.sh @@ -2,7 +2,7 @@ set -eu PLUGIN="u-navigator" -VERSION="2026.06.23.r031" +VERSION="2026.06.23.r032" PKG_DIR="packages" WORK_DIR=".plugin-build" PKG_NAME="${PLUGIN}-${VERSION}.tgz" diff --git a/packages/u-navigator-2026.06.23.r031.tgz b/packages/u-navigator-2026.06.23.r031.tgz deleted file mode 100644 index 341071b..0000000 Binary files a/packages/u-navigator-2026.06.23.r031.tgz and /dev/null differ diff --git a/packages/u-navigator-2026.06.23.r032.tgz b/packages/u-navigator-2026.06.23.r032.tgz new file mode 100644 index 0000000..44386b9 Binary files /dev/null and b/packages/u-navigator-2026.06.23.r032.tgz differ diff --git a/server/public/app.js b/server/public/app.js index cde2149..a99d841 100644 --- a/server/public/app.js +++ b/server/public/app.js @@ -120,7 +120,7 @@ function openProperties(entry = state.selectedEntry) { }); } -function openPreview(entry) { +function openPreview(entry, sourceWindowId = state.focusedId) { if (!entry || !isPreviewable(entry)) { showError(new Error('Für diesen Dateityp ist keine Vorschau verfügbar.')); return null; @@ -129,6 +129,7 @@ function openPreview(entry) { const existing = state.windows.find((item) => item.kind === 'preview'); if (existing) { existing.data.entry = entry; + existing.data.sourceWindowId = sourceWindowId; existing.data.content = ''; existing.data.loading = true; existing.data.error = null; @@ -145,6 +146,7 @@ function openPreview(entry) { y: 110, data: { entry, + sourceWindowId, content: '', loading: true, error: null @@ -333,7 +335,7 @@ function renderExplorer(body, win) { if (entry.type === 'directory') { loadExplorer(win, entry.path); } else if (isPreviewable(entry)) { - openPreview(entry); + openPreview(entry, win.id); } }); row.addEventListener('contextmenu', (event) => { @@ -425,13 +427,20 @@ function renderPreview(body, win) { return; } const entry = data.entry; + const navigation = previewNavigation(data); body.innerHTML = `
${renderPreviewContent(data)} `; + body.querySelector('[data-action="preview-prev"]')?.addEventListener('click', () => openPreview(navigation.previous, data.sourceWindowId)); + body.querySelector('[data-action="preview-next"]')?.addEventListener('click', () => openPreview(navigation.next, data.sourceWindowId)); } function renderPreviewContent(data) { @@ -456,6 +465,22 @@ function renderPreviewContent(data) { return `${escapeHtml(data.content || '')}`;
}
+function previewNavigation(data) {
+ const source = state.windows.find((win) => win.id === data.sourceWindowId && win.kind === 'explorer');
+ const entries = (source?.data.entries || []).filter(isPreviewable);
+ if (entries.length < 2) {
+ return { previous: null, next: null };
+ }
+ const index = entries.findIndex((entry) => entry.path === data.entry?.path);
+ if (index < 0) {
+ return { previous: null, next: null };
+ }
+ return {
+ previous: entries[(index - 1 + entries.length) % entries.length],
+ next: entries[(index + 1) % entries.length]
+ };
+}
+
async function loadPreview(win, entry) {
win.data.loading = true;
win.data.error = null;
@@ -463,6 +488,7 @@ async function loadPreview(win, entry) {
try {
const result = await api(apiUrl(`preview.php?path=${encodeURIComponent(entry.path)}`));
win.data.entry = entry;
+ win.data.sourceWindowId = win.data.sourceWindowId || state.focusedId;
win.data.name = result.name;
win.data.size = result.size;
win.data.type = result.type;
@@ -1000,7 +1026,7 @@ function renderContextMenu() {
if (entry.type === 'directory') {
actions.push(['Öffnen', () => loadExplorer(win, entry.path)]);
} else if (isPreviewable(entry)) {
- actions.push(['Vorschau', () => openPreview(entry)]);
+ actions.push(['Vorschau', () => openPreview(entry, win.id)]);
}
actions.push(['Eigenschaften', () => showPropertiesForEntry(win, entry)]);
if (!isReadOnly()) {
diff --git a/server/public/styles.css b/server/public/styles.css
index dc26a00..46ea6d0 100644
--- a/server/public/styles.css
+++ b/server/public/styles.css
@@ -704,12 +704,22 @@
align-items: center;
border-bottom: 1px solid var(--line);
color: var(--muted);
- display: flex;
+ display: grid;
gap: 10px;
- justify-content: space-between;
+ grid-template-columns: auto minmax(0, 1fr) auto;
padding-bottom: 8px;
}
+.u-nav .preview-nav {
+ display: inline-flex;
+ gap: 4px;
+}
+
+.u-nav .preview-nav button:disabled {
+ cursor: default;
+ opacity: 0.42;
+}
+
.u-nav .preview-meta strong {
color: var(--text);
min-width: 0;
diff --git a/u-navigator.plg b/u-navigator.plg
index ab2a009..8c4e878 100644
--- a/u-navigator.plg
+++ b/u-navigator.plg
@@ -1,7 +1,7 @@
-
+
@@ -24,7 +24,7 @@