Add resizable compact folder sidebar
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.r013"
|
VERSION="2026.07.14.r014"
|
||||||
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.
+37
-1
@@ -119,6 +119,7 @@ function openExplorer(initialPath = state.config?.roots?.[0]?.path) {
|
|||||||
selectionAnchorPath: null,
|
selectionAnchorPath: null,
|
||||||
view: 'icons',
|
view: 'icons',
|
||||||
treeVisible: true,
|
treeVisible: true,
|
||||||
|
treeWidth: 220,
|
||||||
treeExpanded: [],
|
treeExpanded: [],
|
||||||
treeChildren: {},
|
treeChildren: {},
|
||||||
treeLoading: [],
|
treeLoading: [],
|
||||||
@@ -317,8 +318,9 @@ function renderExplorer(body, win) {
|
|||||||
<button class="icon ${data.view === 'icons' ? 'active' : ''}" data-action="view-icons" title="Symbolansicht" aria-label="Symbolansicht">${iconSvg('grid')}</button>
|
<button class="icon ${data.view === 'icons' ? 'active' : ''}" data-action="view-icons" title="Symbolansicht" aria-label="Symbolansicht">${iconSvg('grid')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="explorer-layout ${data.treeVisible ? 'with-tree' : ''}">
|
<div class="explorer-layout ${data.treeVisible ? 'with-tree' : ''}" style="--tree-width:${Number(data.treeWidth) || 220}px">
|
||||||
${data.treeVisible ? renderFolderTree(win) : ''}
|
${data.treeVisible ? renderFolderTree(win) : ''}
|
||||||
|
${data.treeVisible ? '<div class="tree-resizer" data-action="resize-tree" role="separator" aria-label="Breite der Ordnerstruktur ändern" aria-orientation="vertical"></div>' : ''}
|
||||||
<div class="explorer-content">
|
<div class="explorer-content">
|
||||||
<div class="drop-zone ${data.dragOver ? 'drag-over' : ''}">
|
<div class="drop-zone ${data.dragOver ? 'drag-over' : ''}">
|
||||||
${data.error ? `<p class="muted explorer-message">${escapeHtml(data.error)}</p>` : ''}
|
${data.error ? `<p class="muted explorer-message">${escapeHtml(data.error)}</p>` : ''}
|
||||||
@@ -342,6 +344,7 @@ function renderExplorer(body, win) {
|
|||||||
body.querySelector('[data-action="upload-folder"]').addEventListener('click', () => body.querySelector('[data-upload="folder"]').click());
|
body.querySelector('[data-action="upload-folder"]').addEventListener('click', () => body.querySelector('[data-upload="folder"]').click());
|
||||||
body.querySelector('[data-action="delete-selected"]').addEventListener('click', () => deleteEntries(win));
|
body.querySelector('[data-action="delete-selected"]').addEventListener('click', () => deleteEntries(win));
|
||||||
bindFolderTree(body, win);
|
bindFolderTree(body, win);
|
||||||
|
body.querySelector('[data-action="resize-tree"]')?.addEventListener('pointerdown', (event) => startTreeResize(event, win, body));
|
||||||
for (const inputEl of body.querySelectorAll('.upload-input')) {
|
for (const inputEl of body.querySelectorAll('.upload-input')) {
|
||||||
inputEl.addEventListener('change', async () => {
|
inputEl.addEventListener('change', async () => {
|
||||||
try {
|
try {
|
||||||
@@ -491,6 +494,39 @@ function bindFolderTree(body, win) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startTreeResize(event, win, body) {
|
||||||
|
if (event.button !== 0) return;
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
const handle = event.currentTarget;
|
||||||
|
const layout = body.querySelector('.explorer-layout');
|
||||||
|
const startX = event.clientX;
|
||||||
|
const startWidth = Number(win.data.treeWidth) || body.querySelector('.folder-tree')?.getBoundingClientRect().width || 220;
|
||||||
|
const pointerId = event.pointerId;
|
||||||
|
handle.classList.add('active');
|
||||||
|
try {
|
||||||
|
handle.setPointerCapture(pointerId);
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
const move = (moveEvent) => {
|
||||||
|
const maxWidth = Math.max(180, Math.min(480, body.clientWidth - 240));
|
||||||
|
win.data.treeWidth = Math.round(clamp(startWidth + moveEvent.clientX - startX, 150, maxWidth));
|
||||||
|
layout?.style.setProperty('--tree-width', `${win.data.treeWidth}px`);
|
||||||
|
};
|
||||||
|
const up = () => {
|
||||||
|
handle.classList.remove('active');
|
||||||
|
handle.removeEventListener('pointermove', move);
|
||||||
|
handle.removeEventListener('pointerup', up);
|
||||||
|
handle.removeEventListener('pointercancel', up);
|
||||||
|
try {
|
||||||
|
handle.releasePointerCapture(pointerId);
|
||||||
|
} catch {}
|
||||||
|
};
|
||||||
|
handle.addEventListener('pointermove', move);
|
||||||
|
handle.addEventListener('pointerup', up);
|
||||||
|
handle.addEventListener('pointercancel', up);
|
||||||
|
}
|
||||||
|
|
||||||
function renderFileEntries(entries, view, selectedPaths = new Set()) {
|
function renderFileEntries(entries, view, selectedPaths = new Set()) {
|
||||||
if (!entries.length) {
|
if (!entries.length) {
|
||||||
return '<p class="muted">Dieser Ordner ist leer. Dateien können hier abgelegt werden.</p>';
|
return '<p class="muted">Dieser Ordner ist leer. Dateien können hier abgelegt werden.</p>';
|
||||||
|
|||||||
@@ -313,7 +313,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.u-nav .explorer-layout.with-tree {
|
.u-nav .explorer-layout.with-tree {
|
||||||
grid-template-columns: clamp(180px, 25%, 250px) minmax(0, 1fr);
|
grid-template-columns: clamp(150px, var(--tree-width, 220px), 55%) 6px minmax(0, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-nav .explorer-content {
|
.u-nav .explorer-content {
|
||||||
@@ -331,6 +331,32 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.u-nav .tree-resizer {
|
||||||
|
background: var(--surface);
|
||||||
|
border-left: 1px solid transparent;
|
||||||
|
border-right: 1px solid var(--line);
|
||||||
|
cursor: ew-resize;
|
||||||
|
min-height: 0;
|
||||||
|
position: relative;
|
||||||
|
touch-action: none;
|
||||||
|
width: 6px;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-nav .tree-resizer::after {
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 999px;
|
||||||
|
content: "";
|
||||||
|
inset: 8px 1px;
|
||||||
|
position: absolute;
|
||||||
|
transition: background-color 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-nav .tree-resizer:hover::after,
|
||||||
|
.u-nav .tree-resizer.active::after {
|
||||||
|
background: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
.u-nav .tree-heading {
|
.u-nav .tree-heading {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid var(--line);
|
border-bottom: 1px solid var(--line);
|
||||||
@@ -398,12 +424,17 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
gap: 7px;
|
gap: 5px !important;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start !important;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0 5px 0 2px;
|
padding: 0 5px 0 2px;
|
||||||
text-align: left;
|
text-align: left !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-nav .tree-label > * {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
margin-right: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.u-nav .tree-label:hover,
|
.u-nav .tree-label:hover,
|
||||||
|
|||||||
+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.r013">
|
<!ENTITY version "2026.07.14.r014">
|
||||||
<!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>eb8a765a5e07ff3a65b04b40b6f76fb5</MD5>
|
<MD5>b4fd1637ca533afc55dbff96903fc53a</MD5>
|
||||||
</FILE>
|
</FILE>
|
||||||
|
|
||||||
<FILE Run="/bin/bash">
|
<FILE Run="/bin/bash">
|
||||||
|
|||||||
Reference in New Issue
Block a user