From b968a1c16f953924a1f75bd05ed611e317f36445 Mon Sep 17 00:00:00 2001 From: Mikei386 <44135113+Mikei386@users.noreply.github.com> Date: Tue, 14 Jul 2026 19:25:09 +0200 Subject: [PATCH] Add safe text editing to preview window --- build-plugin.sh | 2 +- packages/u-navigator-2026.07.14.r017.tgz | Bin 0 -> 42049 bytes .../plugins/u-navigator/api/preview.php | 77 +++++++++++++ server/public/app.js | 101 +++++++++++++++++- server/public/styles.css | 42 ++++++++ u-navigator.plg | 4 +- 6 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 packages/u-navigator-2026.07.14.r017.tgz diff --git a/build-plugin.sh b/build-plugin.sh index 373ce6a..66b5372 100755 --- a/build-plugin.sh +++ b/build-plugin.sh @@ -2,7 +2,7 @@ set -eu PLUGIN="u-navigator" -VERSION="2026.07.14.r016" +VERSION="2026.07.14.r017" PKG_DIR="packages" WORK_DIR=".plugin-build" PKG_NAME="${PLUGIN}-${VERSION}.tgz" diff --git a/packages/u-navigator-2026.07.14.r017.tgz b/packages/u-navigator-2026.07.14.r017.tgz new file mode 100644 index 0000000000000000000000000000000000000000..dffd0c1e94462d8c748cc228a131f303ff0ce3aa GIT binary patch literal 42049 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 literal 0 HcmV?d00001 diff --git a/plugin-root/usr/local/emhttp/plugins/u-navigator/api/preview.php b/plugin-root/usr/local/emhttp/plugins/u-navigator/api/preview.php index 1e8e10a..7a035d4 100644 --- a/plugin-root/usr/local/emhttp/plugins/u-navigator/api/preview.php +++ b/plugin-root/usr/local/emhttp/plugins/u-navigator/api/preview.php @@ -15,6 +15,68 @@ if ($type === null) { unav_error(415, 'Preview is not available for this file type'); } +$editable = in_array($type, ['text', 'markdown', 'csv'], true); +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + unav_assert_writable(); + if (!$editable) { + unav_error(415, 'Dieser Dateityp kann nicht bearbeitet werden'); + } + $data = unav_request_data(); + if (!array_key_exists('content', $data)) { + unav_error(400, 'Missing file content'); + } + $content = (string)$data['content']; + if (strlen($content) > UNAV_TEXT_PREVIEW_MAX_BYTES) { + unav_error(413, 'Die bearbeitete Datei ist größer als 1 MB'); + } + if (strpos($content, "\0") !== false) { + unav_error(415, 'Binärdaten können nicht im Texteditor gespeichert werden'); + } + $expectedRevision = trim((string)($data['revision'] ?? '')); + if ($expectedRevision === '') { + unav_error(400, 'Missing file revision'); + } + $handle = fopen($resolved['path'], 'r+b'); + if ($handle === false || !flock($handle, LOCK_EX)) { + if (is_resource($handle)) { + fclose($handle); + } + unav_error(500, 'Could not lock file for editing'); + } + rewind($handle); + $current = stream_get_contents($handle); + if ($current === false) { + flock($handle, LOCK_UN); + fclose($handle); + unav_error(500, 'Could not read file before saving'); + } + if (!hash_equals($expectedRevision, hash('sha256', $current))) { + flock($handle, LOCK_UN); + fclose($handle); + unav_error(409, 'Die Datei wurde außerhalb von U-Navigator geändert. Bitte vor dem Speichern neu laden.'); + } + rewind($handle); + if (!ftruncate($handle, 0) || !unav_write_all($handle, $content) || !fflush($handle)) { + flock($handle, LOCK_UN); + fclose($handle); + unav_error(500, 'Could not save file'); + } + flock($handle, LOCK_UN); + fclose($handle); + clearstatcache(true, $resolved['path']); + unav_json([ + 'path' => $resolved['path'], + 'size' => strlen($content), + 'modifiedAt' => gmdate('c', filemtime($resolved['path']) ?: time()), + 'revision' => hash('sha256', $content), + 'content' => $content, + ]); +} + +if ($_SERVER['REQUEST_METHOD'] !== 'GET') { + unav_error(405, 'Method not allowed'); +} + $size = filesize($resolved['path']); if ($size === false) { unav_error(500, 'Could not read file size'); @@ -35,6 +97,7 @@ $payload = [ 'size' => $size, 'extension' => $extension, 'type' => $type, + 'editable' => $editable, 'mime' => $mime, 'rawUrl' => 'preview.php?raw=1&path=' . rawurlencode($resolved['path']), ]; @@ -51,10 +114,24 @@ if (in_array($type, ['text', 'markdown', 'csv'], true)) { unav_error(415, 'Preview is not available for binary files'); } $payload['content'] = $content; + $payload['revision'] = hash('sha256', $content); } unav_json($payload); +function unav_write_all($handle, string $content): bool { + $length = strlen($content); + $offset = 0; + while ($offset < $length) { + $written = fwrite($handle, substr($content, $offset)); + if ($written === false || $written === 0) { + return false; + } + $offset += $written; + } + return true; +} + function unav_preview_type(string $extension, string $name): ?string { $base = strtolower($name); if (in_array($base, ['dockerfile', 'makefile'], true)) { diff --git a/server/public/app.js b/server/public/app.js index 1643bfd..99f67c7 100644 --- a/server/public/app.js +++ b/server/public/app.js @@ -68,6 +68,7 @@ const uiIcons = { move: '', preview: '', refresh: '', + save: '', shield: '', tree: '', upload: '' @@ -170,6 +171,10 @@ function openPreview(entry, sourceWindowId = state.focusedId) { existing.data.entry = entry; existing.data.sourceWindowId = sourceWindowId; existing.data.content = ''; + existing.data.editable = false; + existing.data.editing = false; + existing.data.draft = ''; + existing.data.revision = ''; existing.data.loading = true; existing.data.error = null; focusWindow(existing); @@ -187,6 +192,10 @@ function openPreview(entry, sourceWindowId = state.focusedId) { entry, sourceWindowId, content: '', + editable: false, + editing: false, + draft: '', + revision: '', loading: true, error: null } @@ -268,8 +277,17 @@ function renderWindow(win) { focusWindow(win); render(); }); - titlebar.querySelector('[data-action="close"]').addEventListener('click', (event) => { + titlebar.querySelector('[data-action="close"]').addEventListener('click', async (event) => { event.stopPropagation(); + if (win.kind === 'preview' && win.data.editing && win.data.draft !== win.data.content) { + const discard = await showConfirmDialog( + 'Ungespeicherte Änderungen', + 'Die Änderungen an dieser Datei wurden noch nicht gespeichert.', + '', + { confirmLabel: 'Verwerfen', danger: true } + ); + if (!discard) return; + } state.windows = state.windows.filter((item) => item.id !== win.id); state.focusedId = state.windows.at(-1)?.id || null; render(); @@ -635,22 +653,54 @@ function renderPreview(body, win) { } const entry = data.entry; const navigation = previewNavigation(data); + const canEdit = data.editable && !isReadOnly(); body.innerHTML = `
- - + +
${escapeHtml(entry?.name || data.name || 'Vorschau')} - ${escapeHtml(formatBytes(data.size || entry?.size || 0))} +
+ ${escapeHtml(formatBytes(data.size || entry?.size || 0))} + ${canEdit && !data.editing ? `` : ''} + ${data.editing ? `` : ''} +
${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)); + body.querySelector('[data-action="preview-edit"]')?.addEventListener('click', () => { + data.editing = true; + data.draft = data.content || ''; + render(); + }); + body.querySelector('[data-action="preview-cancel"]')?.addEventListener('click', () => { + data.editing = false; + data.draft = ''; + render(); + }); + const editor = body.querySelector('.preview-editor'); + if (editor) { + editor.addEventListener('input', () => { + data.draft = editor.value; + }); + editor.addEventListener('keydown', (event) => { + if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') { + event.preventDefault(); + savePreview(win, editor.value); + } + }); + requestAnimationFrame(() => editor.focus()); + } + body.querySelector('[data-action="preview-save"]')?.addEventListener('click', () => savePreview(win, editor?.value ?? data.draft ?? '')); } function renderPreviewContent(data) { + if (data.editing) { + return ``; + } if (data.type === 'markdown') { return `
${renderMarkdown(data.content || '')}
`; } @@ -702,6 +752,10 @@ async function loadPreview(win, entry) { win.data.extension = result.extension; win.data.rawUrl = result.rawUrl; win.data.content = result.content; + win.data.editable = Boolean(result.editable); + win.data.editing = false; + win.data.draft = ''; + win.data.revision = result.revision || ''; } catch (error) { win.data.error = error.message; } finally { @@ -710,6 +764,43 @@ async function loadPreview(win, entry) { } } +async function savePreview(win, content) { + if (win.data.saving || !win.data.editable || isReadOnly()) return; + win.data.saving = true; + render(); + const body = new URLSearchParams(); + body.set('content', content); + body.set('revision', win.data.revision || ''); + appendCsrf(body); + try { + const result = await api(apiUrl(`preview.php?path=${encodeURIComponent(win.data.entry.path)}`), { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, + body + }); + win.data.content = result.content; + win.data.draft = ''; + win.data.editing = false; + win.data.revision = result.revision; + win.data.size = result.size; + win.data.entry = { ...win.data.entry, size: result.size, modifiedAt: result.modifiedAt }; + const source = state.windows.find((item) => item.id === win.data.sourceWindowId && item.kind === 'explorer'); + const sourceEntry = source?.data.entries?.find((item) => item.path === result.path); + if (sourceEntry) { + sourceEntry.size = result.size; + sourceEntry.modifiedAt = result.modifiedAt; + } + if (state.selectedEntry?.path === result.path) { + state.selectedEntry = win.data.entry; + } + } catch (error) { + showError(error); + } finally { + win.data.saving = false; + render(); + } +} + function renderMarkdown(content) { const blocks = []; let listItems = []; @@ -2644,7 +2735,7 @@ function windowTitle(win) { return `Explorer · ${win.data.path || ''}`; } if (win.kind === 'preview') { - return `Vorschau · ${win.data.entry?.name || ''}`; + return `${win.data.editing ? 'Editor' : 'Vorschau'} · ${win.data.entry?.name || ''}`; } return win.title; } diff --git a/server/public/styles.css b/server/public/styles.css index 9603363..3667c9e 100644 --- a/server/public/styles.css +++ b/server/public/styles.css @@ -1264,6 +1264,27 @@ padding-bottom: 6px; } +.u-nav .preview-actions { + align-items: center; + display: flex; + gap: 6px; + justify-content: flex-end; + white-space: nowrap; +} + +.u-nav .preview-actions button { + align-items: center; + display: inline-flex; + font-size: 12px; + gap: 5px; + min-height: 28px; +} + +.u-nav .preview-actions .unav-icon { + height: 14px; + width: 14px; +} + .u-nav .preview-nav { display: inline-flex; gap: 4px; @@ -1295,6 +1316,27 @@ white-space: pre; } +.u-nav .preview-editor { + background: var(--surface-2); + border: 1px solid var(--accent); + border-radius: 7px; + color: var(--text); + font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + margin: 0; + min-height: 0; + outline: 0; + overflow: auto; + padding: 10px; + resize: none; + tab-size: 2; + white-space: pre; + width: 100%; +} + +.u-nav .preview-editor:focus { + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent); +} + .u-nav .preview-rendered, .u-nav .preview-table-wrap, .u-nav .preview-media, diff --git a/u-navigator.plg b/u-navigator.plg index 2f67859..6c07fcd 100644 --- a/u-navigator.plg +++ b/u-navigator.plg @@ -1,7 +1,7 @@ - + @@ -24,7 +24,7 @@ https://git.casaderoll.de/michael/Unraid-Navigator/raw/branch/main/packages/&package; -8c943cbf6a929bfb8e3249c901fb3869 +3fa2ea5659712c219ce073b7a16410c5