Add resizable compact folder sidebar
This commit is contained in:
+37
-1
@@ -119,6 +119,7 @@ function openExplorer(initialPath = state.config?.roots?.[0]?.path) {
|
||||
selectionAnchorPath: null,
|
||||
view: 'icons',
|
||||
treeVisible: true,
|
||||
treeWidth: 220,
|
||||
treeExpanded: [],
|
||||
treeChildren: {},
|
||||
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>
|
||||
</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 ? '<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="drop-zone ${data.dragOver ? 'drag-over' : ''}">
|
||||
${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="delete-selected"]').addEventListener('click', () => deleteEntries(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')) {
|
||||
inputEl.addEventListener('change', async () => {
|
||||
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()) {
|
||||
if (!entries.length) {
|
||||
return '<p class="muted">Dieser Ordner ist leer. Dateien können hier abgelegt werden.</p>';
|
||||
|
||||
Reference in New Issue
Block a user