Add Jellyfin handoff progress job

This commit is contained in:
Dymas
2026-06-14 13:09:46 +02:00
parent 6403c98b7d
commit 332ec670fc
8 changed files with 475 additions and 35 deletions
+54 -2
View File
@@ -591,6 +591,7 @@ CONFIG_HTML = r"""<!doctype html>
</label>
</div>
<div class="field-hint">TV entries move only after the show is marked `Finished` and at least one downloaded language covers the expected episode count. Movie entries move after they are downloaded. The manual trigger scans the current watchlist and moves anything already eligible.</div>
<div class="muted" id="jellyfinSyncStatus">No recent Jellyfin handoff job.</div>
</section>
<section class="settings settings-main">
@@ -683,7 +684,9 @@ CONFIG_HTML = r"""<!doctype html>
path: "",
parent_path: "",
home_path: ""
}
},
jellyfinSyncRunning: false,
jellyfinSyncJobId: null
};
const $ = (id) => document.getElementById(id);
@@ -700,6 +703,26 @@ CONFIG_HTML = r"""<!doctype html>
$("notice").textContent = text || "";
}
function setJellyfinSyncButton(running) {
$("runJellyfinSyncBtn").disabled = !!running;
$("runJellyfinSyncBtn").textContent = running ? "Running..." : "Run now";
}
function setJellyfinSyncStatus(job) {
const el = $("jellyfinSyncStatus");
if (!job) {
el.textContent = "No recent Jellyfin handoff job.";
return;
}
if (job.status === "running") {
const title = job.current_title ? ` · ${job.current_title}` : "";
const file = job.current_file ? ` · ${job.current_file}` : "";
el.textContent = `${job.completed || 0}/${job.total || 0} processed · ${job.moved || 0} moved · ${job.moved_files || 0} files${title}${file}`;
return;
}
el.textContent = job.message || "Jellyfin handoff idle.";
}
function selectedWebhookEvents() {
return [...document.querySelectorAll(".webhook-event:checked")].map((input) => input.value);
}
@@ -772,13 +795,38 @@ CONFIG_HTML = r"""<!doctype html>
}
}
async function pollJellyfinSyncStatus(notifyOnComplete = true) {
try {
const data = await api("/api/config/jellyfin/sync-status");
const job = data.job || null;
const running = !!data.running && !!job;
const wasRunning = state.jellyfinSyncRunning;
state.jellyfinSyncRunning = running;
state.jellyfinSyncJobId = job ? job.id : null;
setJellyfinSyncButton(running);
setJellyfinSyncStatus(job);
if (running) {
setNotice(job.message || "Jellyfin handoff running...");
} else if (job && wasRunning && notifyOnComplete) {
setNotice(job.message || "Jellyfin handoff completed.");
}
} catch (error) {
setNotice(error.message);
}
}
async function runJellyfinSync() {
try {
const data = await api("/api/config/jellyfin/sync", {
method: "POST",
body: JSON.stringify(formConfigPayload())
});
setNotice(data.message || "Jellyfin handoff completed.");
const job = data.job || null;
state.jellyfinSyncRunning = !!job && (job.status === "pending" || job.status === "running");
state.jellyfinSyncJobId = job ? job.id : null;
setJellyfinSyncButton(state.jellyfinSyncRunning);
setJellyfinSyncStatus(job);
setNotice(data.message || "Jellyfin handoff started.");
} catch (error) {
setNotice(error.message);
}
@@ -961,8 +1009,12 @@ CONFIG_HTML = r"""<!doctype html>
(async function init() {
try {
await loadConfig();
await pollJellyfinSyncStatus(false);
await loadDeps();
await loadVersion();
window.setInterval(() => {
pollJellyfinSyncStatus();
}, 2500);
} catch (error) {
setNotice(error.message);
}