download taken zichtbaar gemaakt
This commit is contained in:
+150
-9
@@ -101,6 +101,8 @@ let folderUploadPickerInput = null;
|
||||
let settingsState = {
|
||||
activeTab: "general",
|
||||
logsLoaded: false,
|
||||
tasksLoaded: false,
|
||||
logsPollTimer: null,
|
||||
showThumbnails: false,
|
||||
preferredStartupPathLeft: null,
|
||||
preferredStartupPathRight: null,
|
||||
@@ -903,6 +905,7 @@ function settingsElements() {
|
||||
downloadScanTimeout: document.getElementById("settings-download-scan-timeout"),
|
||||
downloadSymlinkPolicy: document.getElementById("settings-download-symlink-policy"),
|
||||
logsPanel: document.getElementById("settings-logs-panel"),
|
||||
tasksList: document.getElementById("settings-tasks-list"),
|
||||
logsList: document.getElementById("settings-logs-list"),
|
||||
logsError: document.getElementById("settings-logs-error"),
|
||||
};
|
||||
@@ -3726,6 +3729,68 @@ function formatHistoryLine(item) {
|
||||
};
|
||||
}
|
||||
|
||||
function formatTaskStatusLabel(task) {
|
||||
if (task.operation === "download") {
|
||||
switch (task.status) {
|
||||
case "requested":
|
||||
return "Requested";
|
||||
case "preparing":
|
||||
return "Preparing";
|
||||
case "ready":
|
||||
return "Ready for download";
|
||||
case "failed":
|
||||
return "Failed";
|
||||
case "cancelled":
|
||||
return "Cancelled";
|
||||
default:
|
||||
return task.status;
|
||||
}
|
||||
}
|
||||
switch (task.status) {
|
||||
case "queued":
|
||||
return "Queued";
|
||||
case "running":
|
||||
return "Running";
|
||||
case "completed":
|
||||
return "Completed";
|
||||
case "failed":
|
||||
return "Failed";
|
||||
default:
|
||||
return task.status;
|
||||
}
|
||||
}
|
||||
|
||||
function inferDownloadTaskContext(task) {
|
||||
if (task.operation !== "download") {
|
||||
return null;
|
||||
}
|
||||
if (typeof task.destination === "string" && /^kodidownload-\d{8}-\d{6}\.zip$/.test(task.destination)) {
|
||||
return "Multi-item ZIP";
|
||||
}
|
||||
return "Directory ZIP";
|
||||
}
|
||||
|
||||
function formatTaskLine(task) {
|
||||
const when = formatModified(task.finished_at || task.created_at || "");
|
||||
const details = [];
|
||||
const downloadContext = inferDownloadTaskContext(task);
|
||||
if (downloadContext) {
|
||||
details.push(downloadContext);
|
||||
}
|
||||
if (typeof task.done_items === "number" && typeof task.total_items === "number") {
|
||||
details.push(`${task.done_items}/${task.total_items} items`);
|
||||
}
|
||||
if (task.current_item) {
|
||||
details.push(`Current: ${task.current_item}`);
|
||||
}
|
||||
return {
|
||||
title: `${task.operation} · ${formatTaskStatusLabel(task)}`,
|
||||
path: task.destination ? `${task.destination} · ${task.source}` : task.source || "-",
|
||||
meta: [when, ...details].filter(Boolean).join(" · "),
|
||||
error: task.status === "failed" ? (task.error_message || task.error_code || "") : "",
|
||||
};
|
||||
}
|
||||
|
||||
function renderHistoryItems(items) {
|
||||
const elements = settingsElements();
|
||||
elements.logsList.innerHTML = "";
|
||||
@@ -3760,20 +3825,84 @@ function renderHistoryItems(items) {
|
||||
}
|
||||
}
|
||||
|
||||
function renderTaskItems(items) {
|
||||
const elements = settingsElements();
|
||||
elements.tasksList.innerHTML = "";
|
||||
if (!Array.isArray(items) || items.length === 0) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "popup-meta";
|
||||
empty.textContent = "No tasks yet.";
|
||||
elements.tasksList.append(empty);
|
||||
return;
|
||||
}
|
||||
for (const task of items) {
|
||||
const line = formatTaskLine(task);
|
||||
const row = document.createElement("div");
|
||||
row.className = `settings-log-item status-${task.status}`;
|
||||
const title = document.createElement("div");
|
||||
title.className = "settings-log-title";
|
||||
title.textContent = line.title;
|
||||
const path = document.createElement("div");
|
||||
path.className = "settings-log-path";
|
||||
path.textContent = line.path;
|
||||
const meta = document.createElement("div");
|
||||
meta.className = "settings-log-meta";
|
||||
meta.textContent = line.meta;
|
||||
row.append(title, path, meta);
|
||||
if (line.error) {
|
||||
const error = document.createElement("div");
|
||||
error.className = "settings-log-error";
|
||||
error.textContent = line.error;
|
||||
row.append(error);
|
||||
}
|
||||
elements.tasksList.append(row);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadHistoryForSettings() {
|
||||
const data = await apiRequest("GET", "/api/history");
|
||||
renderHistoryItems(data.items || []);
|
||||
settingsState.logsLoaded = true;
|
||||
}
|
||||
|
||||
async function loadTasksForSettings() {
|
||||
const data = await apiRequest("GET", "/api/tasks");
|
||||
renderTaskItems(data.items || []);
|
||||
settingsState.tasksLoaded = true;
|
||||
}
|
||||
|
||||
async function loadLogsAndTasksForSettings() {
|
||||
const elements = settingsElements();
|
||||
elements.logsError.textContent = "";
|
||||
elements.tasksList.innerHTML = '<div class="popup-meta">Loading...</div>';
|
||||
elements.logsList.innerHTML = '<div class="popup-meta">Loading...</div>';
|
||||
try {
|
||||
const data = await apiRequest("GET", "/api/history");
|
||||
renderHistoryItems(data.items || []);
|
||||
settingsState.logsLoaded = true;
|
||||
await Promise.all([loadTasksForSettings(), loadHistoryForSettings()]);
|
||||
} catch (err) {
|
||||
elements.tasksList.innerHTML = "";
|
||||
elements.logsList.innerHTML = "";
|
||||
elements.logsError.textContent = err.message;
|
||||
}
|
||||
}
|
||||
|
||||
function stopSettingsLogsPolling() {
|
||||
if (settingsState.logsPollTimer) {
|
||||
window.clearTimeout(settingsState.logsPollTimer);
|
||||
settingsState.logsPollTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleSettingsLogsPolling() {
|
||||
stopSettingsLogsPolling();
|
||||
if (settingsState.activeTab !== "logs" || settingsElements().overlay.classList.contains("hidden")) {
|
||||
return;
|
||||
}
|
||||
settingsState.logsPollTimer = window.setTimeout(async () => {
|
||||
await loadLogsAndTasksForSettings();
|
||||
scheduleSettingsLogsPolling();
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
async function handleShowThumbnailsChange(event) {
|
||||
const input = event.target;
|
||||
try {
|
||||
@@ -3814,6 +3943,7 @@ async function handleInterfaceSave() {
|
||||
}
|
||||
|
||||
function closeSettings() {
|
||||
stopSettingsLogsPolling();
|
||||
settingsElements().overlay.classList.add("hidden");
|
||||
}
|
||||
|
||||
@@ -3823,7 +3953,10 @@ async function openSettings(tab = "general") {
|
||||
elements.generalError.textContent = "";
|
||||
setSettingsTab(tab);
|
||||
if (settingsState.activeTab === "logs") {
|
||||
await loadHistoryForSettings();
|
||||
await loadLogsAndTasksForSettings();
|
||||
scheduleSettingsLogsPolling();
|
||||
} else {
|
||||
stopSettingsLogsPolling();
|
||||
}
|
||||
(settingsState.activeTab === "logs"
|
||||
? elements.logsTab
|
||||
@@ -4520,12 +4653,20 @@ function setupEvents() {
|
||||
|
||||
const settings = settingsElements();
|
||||
settings.closeButton.onclick = closeSettings;
|
||||
settings.generalTab.onclick = () => setSettingsTab("general");
|
||||
settings.interfaceTab.onclick = () => setSettingsTab("interface");
|
||||
settings.downloadsTab.onclick = () => setSettingsTab("downloads");
|
||||
settings.generalTab.onclick = () => {
|
||||
stopSettingsLogsPolling();
|
||||
setSettingsTab("general");
|
||||
};
|
||||
settings.interfaceTab.onclick = () => {
|
||||
stopSettingsLogsPolling();
|
||||
setSettingsTab("interface");
|
||||
};
|
||||
settings.downloadsTab.onclick = () => {
|
||||
stopSettingsLogsPolling();
|
||||
setSettingsTab("downloads");
|
||||
};
|
||||
settings.logsTab.onclick = async () => {
|
||||
setSettingsTab("logs");
|
||||
await loadHistoryForSettings();
|
||||
await openSettings("logs");
|
||||
};
|
||||
settings.showThumbnailsInput.onchange = handleShowThumbnailsChange;
|
||||
settings.generalSaveButton.onclick = handlePreferredStartupPathSave;
|
||||
|
||||
Reference in New Issue
Block a user