Calculate directory sizes in background

This commit is contained in:
Mikei386
2026-06-23 09:17:32 +02:00
parent 74ba8d0984
commit 53e25c4641
7 changed files with 114 additions and 11 deletions
+57 -1
View File
@@ -15,6 +15,8 @@ const state = {
nextDebugId: 1,
jobs: new Map(),
jobRefresh: new Map(),
sizeJobs: new Map(),
sizeResults: new Map(),
nextWindowId: 1,
zIndex: 20
};
@@ -339,19 +341,23 @@ function renderProperties(body) {
return;
}
const sizeLabel = entry.type === 'directory' ? directorySizeLabel(entry) : formatBytes(entry.size);
body.classList.add('properties');
body.innerHTML = `
<dl>
<dt>Name</dt><dd>${escapeHtml(entry.name)}</dd>
<dt>Typ</dt><dd>${escapeHtml(entry.type)}</dd>
<dt>Pfad</dt><dd>${escapeHtml(entry.path)}</dd>
<dt>Größe</dt><dd>${formatBytes(entry.size)}</dd>
<dt>Größe</dt><dd>${escapeHtml(sizeLabel)}</dd>
<dt>Geändert</dt><dd>${new Date(entry.modifiedAt).toLocaleString()}</dd>
<dt>Besitzer</dt><dd>${escapeHtml(formatPrincipal(entry.owner, entry.ownerId))}</dd>
<dt>Gruppe</dt><dd>${escapeHtml(formatPrincipal(entry.group, entry.groupId))}</dd>
<dt>Rechte</dt><dd>${escapeHtml(entry.permissions ? `0${entry.permissions}`.slice(-4) : '-')}</dd>
</dl>
`;
if (entry.type === 'directory') {
ensureDirectorySize(entry);
}
}
function renderQueue(body) {
@@ -452,6 +458,24 @@ async function createJob(type, source, destination, refreshWindowIds = []) {
return job;
}
async function createSizeJob(entry) {
recordDebug('size.create.request', { source: entry.path });
const body = new URLSearchParams();
body.set('source', entry.path);
appendCsrf(body);
const job = await api(apiUrl('job.php?action=size'), {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body
});
recordDebug('size.create.response', job);
state.jobs.set(job.id, job);
state.sizeJobs.set(entry.path, job.id);
pollJob(job.id);
render();
return job;
}
async function reloadExplorerWindows(ids) {
const uniqueIds = new Set(ids);
const targets = state.windows.filter((win) => win.kind === 'explorer' && (uniqueIds.has(win.id) || !uniqueIds.size));
@@ -601,6 +625,8 @@ async function pollJob(id) {
render();
if (['queued', 'running', 'cancel_requested'].includes(job.status)) {
setTimeout(() => pollJob(id), 700);
} else if (job.type === 'size') {
finishSizeJob(job);
} else {
await refreshAfterJob(job);
}
@@ -610,6 +636,26 @@ async function pollJob(id) {
}
}
function ensureDirectorySize(entry) {
if (state.sizeResults.has(entry.path) || state.sizeJobs.has(entry.path)) {
return;
}
state.sizeJobs.set(entry.path, 'pending');
createSizeJob(entry).catch((error) => {
state.sizeJobs.delete(entry.path);
showError(error);
});
}
function finishSizeJob(job) {
state.sizeJobs.delete(job.source);
if (job.status === 'completed' && job.result) {
state.sizeResults.set(job.source, job.result);
}
recordDebug('size.finish', { id: job.id, source: job.source, status: job.status, result: job.result || null });
updatePropertiesWindows();
}
async function refreshAfterJob(job) {
const refresh = state.jobRefresh.get(job.id);
if (refresh?.done) {
@@ -961,6 +1007,16 @@ function formatBytes(bytes) {
return `${(value / 1024 / 1024 / 1024).toFixed(1)} GB`;
}
function directorySizeLabel(entry) {
const result = state.sizeResults.get(entry.path);
if (!result) {
return state.sizeJobs.has(entry.path) ? 'Berechne...' : 'Noch nicht berechnet';
}
const files = Number(result.files || 0);
const directories = Math.max(0, Number(result.directories || 0) - 1);
return `${formatBytes(result.size)} · ${files} Dateien · ${directories} Ordner`;
}
function formatPrincipal(name, id) {
if (name == null && id == null) return '-';
if (name == null || String(name) === String(id)) return String(id);