Modernize file context menu
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
PLUGIN="u-navigator"
|
PLUGIN="u-navigator"
|
||||||
VERSION="2026.07.14.r015"
|
VERSION="2026.07.14.r016"
|
||||||
PKG_DIR="packages"
|
PKG_DIR="packages"
|
||||||
WORK_DIR=".plugin-build"
|
WORK_DIR=".plugin-build"
|
||||||
PKG_NAME="${PLUGIN}-${VERSION}.tgz"
|
PKG_NAME="${PLUGIN}-${VERSION}.tgz"
|
||||||
|
|||||||
Binary file not shown.
+28
-14
@@ -51,7 +51,10 @@ const uiIcons = {
|
|||||||
chevronDown: '<path d="m6 9 6 6 6-6"></path>',
|
chevronDown: '<path d="m6 9 6 6 6-6"></path>',
|
||||||
chevronRight: '<path d="m9 18 6-6-6-6"></path>',
|
chevronRight: '<path d="m9 18 6-6-6-6"></path>',
|
||||||
close: '<path d="M18 6 6 18"></path><path d="m6 6 12 12"></path>',
|
close: '<path d="M18 6 6 18"></path><path d="m6 6 12 12"></path>',
|
||||||
|
copy: '<rect x="9" y="9" width="11" height="11" rx="2"></rect><path d="M15 9V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3"></path>',
|
||||||
delete: '<path d="M4 7h16"></path><path d="M10 11v6"></path><path d="M14 11v6"></path><path d="M6 7l1 14h10l1-14"></path><path d="M9 7V4h6v3"></path>',
|
delete: '<path d="M4 7h16"></path><path d="M10 11v6"></path><path d="M14 11v6"></path><path d="M6 7l1 14h10l1-14"></path><path d="M9 7V4h6v3"></path>',
|
||||||
|
download: '<path d="M12 3v12"></path><path d="m7 10 5 5 5-5"></path><path d="M5 21h14"></path>',
|
||||||
|
edit: '<path d="M12 20h9"></path><path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L8 18l-4 1 1-4Z"></path>',
|
||||||
enter: '<path d="M7 8 3 12l4 4"></path><path d="M3 12h12a4 4 0 0 0 4-4V5"></path>',
|
enter: '<path d="M7 8 3 12l4 4"></path><path d="M3 12h12a4 4 0 0 0 4-4V5"></path>',
|
||||||
file: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"></path><path d="M14 2v6h6"></path>',
|
file: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"></path><path d="M14 2v6h6"></path>',
|
||||||
folder: '<path d="M3 7a2 2 0 0 1 2-2h5l2 2h7a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"></path>',
|
folder: '<path d="M3 7a2 2 0 0 1 2-2h5l2 2h7a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"></path>',
|
||||||
@@ -59,9 +62,13 @@ const uiIcons = {
|
|||||||
grid: '<rect x="4" y="4" width="6" height="6" rx="1"></rect><rect x="14" y="4" width="6" height="6" rx="1"></rect><rect x="4" y="14" width="6" height="6" rx="1"></rect><rect x="14" y="14" width="6" height="6" rx="1"></rect>',
|
grid: '<rect x="4" y="4" width="6" height="6" rx="1"></rect><rect x="14" y="4" width="6" height="6" rx="1"></rect><rect x="4" y="14" width="6" height="6" rx="1"></rect><rect x="14" y="14" width="6" height="6" rx="1"></rect>',
|
||||||
list: '<path d="M9 6h11"></path><path d="M9 12h11"></path><path d="M9 18h11"></path><path d="M4 6h.01"></path><path d="M4 12h.01"></path><path d="M4 18h.01"></path>',
|
list: '<path d="M9 6h11"></path><path d="M9 12h11"></path><path d="M9 18h11"></path><path d="M4 6h.01"></path><path d="M4 12h.01"></path><path d="M4 18h.01"></path>',
|
||||||
link: '<path d="M10 13a5 5 0 0 0 7.5.5l2-2a5 5 0 0 0-7-7l-1.1 1.1"></path><path d="M14 11a5 5 0 0 0-7.5-.5l-2 2a5 5 0 0 0 7 7l1.1-1.1"></path>',
|
link: '<path d="M10 13a5 5 0 0 0 7.5.5l2-2a5 5 0 0 0-7-7l-1.1 1.1"></path><path d="M14 11a5 5 0 0 0-7.5-.5l-2 2a5 5 0 0 0 7 7l1.1-1.1"></path>',
|
||||||
|
info: '<circle cx="12" cy="12" r="9"></circle><path d="M12 11v5"></path><path d="M12 8h.01"></path>',
|
||||||
maximize: '<rect x="5" y="5" width="14" height="14" rx="2"></rect>',
|
maximize: '<rect x="5" y="5" width="14" height="14" rx="2"></rect>',
|
||||||
minimize: '<path d="M8 4h12v12"></path><path d="M4 8h12v12H4Z"></path>',
|
minimize: '<path d="M8 4h12v12"></path><path d="M4 8h12v12H4Z"></path>',
|
||||||
|
move: '<path d="M5 12h14"></path><path d="m14 7 5 5-5 5"></path><path d="M5 7v10"></path>',
|
||||||
|
preview: '<path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12Z"></path><circle cx="12" cy="12" r="2.5"></circle>',
|
||||||
refresh: '<path d="M20 6v5h-5"></path><path d="M4 18v-5h5"></path><path d="M19 11a7 7 0 0 0-12-4.9L4 9"></path><path d="M5 13a7 7 0 0 0 12 4.9l3-2.9"></path>',
|
refresh: '<path d="M20 6v5h-5"></path><path d="M4 18v-5h5"></path><path d="M19 11a7 7 0 0 0-12-4.9L4 9"></path><path d="M5 13a7 7 0 0 0 12 4.9l3-2.9"></path>',
|
||||||
|
shield: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"></path><path d="m9 12 2 2 4-4"></path>',
|
||||||
tree: '<path d="M4 5h6"></path><path d="M4 12h10"></path><path d="M4 19h14"></path><path d="M4 5v14"></path><circle cx="4" cy="5" r="1.5"></circle><circle cx="4" cy="12" r="1.5"></circle><circle cx="4" cy="19" r="1.5"></circle>',
|
tree: '<path d="M4 5h6"></path><path d="M4 12h10"></path><path d="M4 19h14"></path><path d="M4 5v14"></path><circle cx="4" cy="5" r="1.5"></circle><circle cx="4" cy="12" r="1.5"></circle><circle cx="4" cy="19" r="1.5"></circle>',
|
||||||
upload: '<path d="M12 16V5"></path><path d="m8 9 4-4 4 4"></path><path d="M5 16v3h14v-3"></path>'
|
upload: '<path d="M12 16V5"></path><path d="m8 9 4-4 4 4"></path><path d="M5 16v3h14v-3"></path>'
|
||||||
};
|
};
|
||||||
@@ -1995,33 +2002,40 @@ function renderContextMenu() {
|
|||||||
|
|
||||||
if (entry) {
|
if (entry) {
|
||||||
if (entry.type === 'directory') {
|
if (entry.type === 'directory') {
|
||||||
actions.push(['Öffnen', () => loadExplorer(win, entry.path)]);
|
actions.push({ label: 'Öffnen', icon: 'folder', action: () => loadExplorer(win, entry.path) });
|
||||||
} else if (isPreviewable(entry)) {
|
} else if (isPreviewable(entry)) {
|
||||||
actions.push(['Vorschau', () => openPreview(entry, win.id)]);
|
actions.push({ label: 'Vorschau', icon: 'preview', action: () => openPreview(entry, win.id) });
|
||||||
}
|
}
|
||||||
actions.push(['Eigenschaften', () => showPropertiesForEntry(win, entry)]);
|
actions.push({ label: 'Eigenschaften', icon: 'info', action: () => showPropertiesForEntry(win, entry) });
|
||||||
actions.push(['Herunterladen', () => downloadEntries(win, entry)]);
|
actions.push({ label: 'Herunterladen', icon: 'download', action: () => downloadEntries(win, entry) });
|
||||||
if (!isReadOnly()) {
|
if (!isReadOnly()) {
|
||||||
actions.push(['Umbenennen', () => renameEntry(win, entry)]);
|
actions.push({ label: 'Umbenennen', icon: 'edit', separator: true, action: () => renameEntry(win, entry) });
|
||||||
actions.push(['Berechtigungen...', () => openPermissionsDialog(win, entry)]);
|
actions.push({ label: 'Berechtigungen…', icon: 'shield', action: () => openPermissionsDialog(win, entry) });
|
||||||
actions.push(['Kopieren nach...', () => promptTransfer(win, entry, 'copy')]);
|
actions.push({ label: 'Kopieren nach…', icon: 'copy', action: () => promptTransfer(win, entry, 'copy') });
|
||||||
actions.push(['Verschieben nach...', () => promptTransfer(win, entry, 'move')]);
|
actions.push({ label: 'Verschieben nach…', icon: 'move', action: () => promptTransfer(win, entry, 'move') });
|
||||||
actions.push(['Löschen', () => deleteEntries(win, entry)]);
|
actions.push({ label: 'Löschen', icon: 'delete', danger: true, separator: true, action: () => deleteEntries(win, entry) });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
actions.push(['Aktuellen Ordner herunterladen', () => downloadEntries(win, null)]);
|
actions.push({ label: 'Aktuellen Ordner herunterladen', icon: 'download', action: () => downloadEntries(win, null) });
|
||||||
actions.push(['Neu laden', () => loadExplorer(win, win.data.path)]);
|
actions.push({ label: 'Neu laden', icon: 'refresh', action: () => loadExplorer(win, win.data.path) });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [label, action] of actions) {
|
for (const item of actions) {
|
||||||
|
if (item.separator) {
|
||||||
|
const separator = document.createElement('div');
|
||||||
|
separator.className = 'context-separator';
|
||||||
|
separator.setAttribute('role', 'separator');
|
||||||
|
menu.appendChild(separator);
|
||||||
|
}
|
||||||
const button = document.createElement('button');
|
const button = document.createElement('button');
|
||||||
button.type = 'button';
|
button.type = 'button';
|
||||||
button.textContent = label;
|
button.className = `context-action ${item.danger ? 'danger' : ''}`;
|
||||||
|
button.innerHTML = `<span class="context-icon">${iconSvg(item.icon)}</span><span>${escapeHtml(item.label)}</span>`;
|
||||||
button.addEventListener('click', async () => {
|
button.addEventListener('click', async () => {
|
||||||
state.contextMenu = null;
|
state.contextMenu = null;
|
||||||
render();
|
render();
|
||||||
try {
|
try {
|
||||||
await action();
|
await item.action();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showError(error);
|
showError(error);
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-10
@@ -792,25 +792,62 @@
|
|||||||
.u-nav .context-menu {
|
.u-nav .context-menu {
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
display: grid;
|
display: grid;
|
||||||
min-width: 170px;
|
min-width: 205px;
|
||||||
padding: 5px;
|
padding: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 100000;
|
z-index: 100000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-nav .context-menu button {
|
.u-nav .context-menu .context-action {
|
||||||
border-color: transparent;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
background: transparent;
|
||||||
text-align: left;
|
border: 0;
|
||||||
|
border-radius: 7px;
|
||||||
|
box-shadow: none;
|
||||||
|
display: grid;
|
||||||
|
font: 500 12px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important;
|
||||||
|
gap: 7px;
|
||||||
|
grid-template-columns: 18px minmax(0, 1fr);
|
||||||
|
justify-content: stretch !important;
|
||||||
|
letter-spacing: normal !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
min-height: 30px;
|
||||||
|
padding: 0 8px !important;
|
||||||
|
text-align: left !important;
|
||||||
|
text-transform: none !important;
|
||||||
|
white-space: nowrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-nav .context-menu button:hover {
|
.u-nav .context-menu .context-action:hover,
|
||||||
background: var(--surface-2);
|
.u-nav .context-menu .context-action:focus-visible {
|
||||||
border-color: var(--line);
|
background: var(--accent-soft);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-nav .context-menu .context-action.danger {
|
||||||
|
color: #c4382d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-nav .context-icon {
|
||||||
|
align-items: center;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-nav .context-icon .unav-icon {
|
||||||
|
height: 15px;
|
||||||
|
stroke-width: 1.9;
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-nav .context-separator {
|
||||||
|
border-top: 1px solid var(--line);
|
||||||
|
height: 1px;
|
||||||
|
margin: 4px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-nav .modal-overlay {
|
.u-nav .modal-overlay {
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE PLUGIN [
|
<!DOCTYPE PLUGIN [
|
||||||
<!ENTITY name "u-navigator">
|
<!ENTITY name "u-navigator">
|
||||||
<!ENTITY author "Michael Roll">
|
<!ENTITY author "Michael Roll">
|
||||||
<!ENTITY version "2026.07.14.r015">
|
<!ENTITY version "2026.07.14.r016">
|
||||||
<!ENTITY package "&name;-&version;.tgz">
|
<!ENTITY package "&name;-&version;.tgz">
|
||||||
<!ENTITY pluginURL "https://git.casaderoll.de/michael/Unraid-Navigator/raw/branch/main/u-navigator.plg">
|
<!ENTITY pluginURL "https://git.casaderoll.de/michael/Unraid-Navigator/raw/branch/main/u-navigator.plg">
|
||||||
<!ENTITY support "https://git.casaderoll.de/michael/Unraid-Navigator">
|
<!ENTITY support "https://git.casaderoll.de/michael/Unraid-Navigator">
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
<FILE Name="/boot/config/plugins/&name;/&package;">
|
<FILE Name="/boot/config/plugins/&name;/&package;">
|
||||||
<URL>https://git.casaderoll.de/michael/Unraid-Navigator/raw/branch/main/packages/&package;</URL>
|
<URL>https://git.casaderoll.de/michael/Unraid-Navigator/raw/branch/main/packages/&package;</URL>
|
||||||
<MD5>e7bd64a4dda7a5915d9ef73657dec517</MD5>
|
<MD5>8c943cbf6a929bfb8e3249c901fb3869</MD5>
|
||||||
</FILE>
|
</FILE>
|
||||||
|
|
||||||
<FILE Run="/bin/bash">
|
<FILE Run="/bin/bash">
|
||||||
|
|||||||
Reference in New Issue
Block a user