Redesign updater UI with manual version picker and status bar
This commit is contained in:
@@ -94,6 +94,60 @@
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.release-status-bar {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.release-advanced {
|
||||
border: 1px dashed var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 10px;
|
||||
margin-top: 8px;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
.release-advanced-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.release-list {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.release-card {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
padding: 8px 10px;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.release-card input[type="radio"] {
|
||||
accent-color: var(--accent);
|
||||
}
|
||||
|
||||
.release-card-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.release-card-tags {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-card .status-msg {
|
||||
overflow-wrap: anywhere;
|
||||
margin-top: 6px;
|
||||
|
||||
@@ -25,9 +25,14 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
||||
const releaseProgress = document.getElementById("releaseProgress");
|
||||
const releaseCheckBtn = document.getElementById("releaseCheckBtn");
|
||||
const releaseApplyBtn = document.getElementById("releaseApplyBtn");
|
||||
const releaseVersionSelect = document.getElementById("releaseVersionSelect");
|
||||
const releaseAdvancedToggle = document.getElementById("releaseAdvancedToggle");
|
||||
const releaseAdvanced = document.getElementById("releaseAdvanced");
|
||||
const releaseList = document.getElementById("releaseList");
|
||||
const releaseApplyVersionBtn = document.getElementById("releaseApplyVersionBtn");
|
||||
const releaseAutoCheck = document.getElementById("releaseAutoCheck");
|
||||
const releaseStatusChip = document.getElementById("releaseStatusChip");
|
||||
const releaseChannelChip = document.getElementById("releaseChannelChip");
|
||||
const releaseLastCheckChip = document.getElementById("releaseLastCheckChip");
|
||||
const releaseLog = document.getElementById("releaseLog");
|
||||
const releaseLogStatus = document.getElementById("releaseLogStatus");
|
||||
const releaseLogCopy = document.getElementById("releaseLogCopy");
|
||||
@@ -68,40 +73,70 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
||||
};
|
||||
|
||||
async function loadReleaseList() {
|
||||
if (!releaseVersionSelect) return;
|
||||
if (!releaseList) return;
|
||||
try {
|
||||
const data = await listReleases();
|
||||
releaseOptions = data.releases || [];
|
||||
releaseVersionSelect.innerHTML = "";
|
||||
if (!releaseOptions.length) {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = "";
|
||||
opt.textContent = "No releases found";
|
||||
releaseVersionSelect.appendChild(opt);
|
||||
releaseVersionSelect.disabled = true;
|
||||
releaseApplyVersionBtn && (releaseApplyVersionBtn.disabled = true);
|
||||
return;
|
||||
}
|
||||
releaseVersionSelect.disabled = false;
|
||||
releaseOptions.forEach((r) => {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = r.version;
|
||||
const tag = r.prerelease ? " (dev)" : "";
|
||||
opt.textContent = `${r.version}${tag}${r.published_at ? ` — ${fmtDate(r.published_at)}` : ""}`;
|
||||
releaseVersionSelect.appendChild(opt);
|
||||
});
|
||||
if (releaseApplyVersionBtn) releaseApplyVersionBtn.disabled = false;
|
||||
renderReleaseList();
|
||||
} catch (e) {
|
||||
releaseVersionSelect.innerHTML = "";
|
||||
const opt = document.createElement("option");
|
||||
opt.value = "";
|
||||
opt.textContent = "Failed to load releases";
|
||||
releaseVersionSelect.appendChild(opt);
|
||||
releaseVersionSelect.disabled = true;
|
||||
if (releaseApplyVersionBtn) releaseApplyVersionBtn.disabled = true;
|
||||
renderReleaseList(true);
|
||||
}
|
||||
}
|
||||
|
||||
function renderReleaseList(error = false) {
|
||||
if (!releaseList) return;
|
||||
releaseList.innerHTML = "";
|
||||
if (error) {
|
||||
releaseList.textContent = "Failed to load releases.";
|
||||
return;
|
||||
}
|
||||
if (!releaseOptions.length) {
|
||||
releaseList.textContent = "No releases found.";
|
||||
return;
|
||||
}
|
||||
releaseOptions.forEach((r, idx) => {
|
||||
const card = document.createElement("label");
|
||||
card.className = "release-card";
|
||||
card.setAttribute("role", "option");
|
||||
const input = document.createElement("input");
|
||||
input.type = "radio";
|
||||
input.name = "releaseVersion";
|
||||
input.value = r.version;
|
||||
if (idx === 0) input.checked = true;
|
||||
const meta = document.createElement("div");
|
||||
meta.className = "release-card-meta";
|
||||
const title = document.createElement("div");
|
||||
title.className = "release-card-title";
|
||||
title.textContent = r.version;
|
||||
const tags = document.createElement("div");
|
||||
tags.className = "release-card-tags";
|
||||
const chip = document.createElement("span");
|
||||
chip.className = "status-chip ghost";
|
||||
chip.textContent = r.prerelease ? "Dev" : "Stable";
|
||||
tags.appendChild(chip);
|
||||
if (r.published_at) {
|
||||
const date = document.createElement("span");
|
||||
date.className = "hint quiet";
|
||||
date.textContent = fmtDate(r.published_at);
|
||||
tags.appendChild(date);
|
||||
}
|
||||
meta.appendChild(title);
|
||||
meta.appendChild(tags);
|
||||
if (r.changelog_url) {
|
||||
const link = document.createElement("a");
|
||||
link.href = r.changelog_url;
|
||||
link.target = "_blank";
|
||||
link.className = "hint";
|
||||
link.textContent = "Changelog";
|
||||
meta.appendChild(link);
|
||||
}
|
||||
card.appendChild(input);
|
||||
card.appendChild(meta);
|
||||
releaseList.appendChild(card);
|
||||
});
|
||||
if (releaseApplyVersionBtn) releaseApplyVersionBtn.disabled = false;
|
||||
}
|
||||
|
||||
function setReleaseChip(state) {
|
||||
if (!releaseFlagTop) return;
|
||||
releaseFlagTop.textContent = "Pi-Kit: n/a";
|
||||
@@ -193,6 +228,7 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
||||
current_release_date = null,
|
||||
latest_release_date = null,
|
||||
changelog_url = null,
|
||||
last_check = null,
|
||||
} = data || {};
|
||||
releaseChannel = channel || "dev";
|
||||
if (releaseChannelToggle) releaseChannelToggle.checked = releaseChannel === "dev";
|
||||
@@ -214,6 +250,13 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
||||
if (releaseLatest) releaseLatest.textContent = latest_version;
|
||||
if (releaseCurrentDate) releaseCurrentDate.textContent = fmtDate(current_release_date);
|
||||
if (releaseLatestDate) releaseLatestDate.textContent = fmtDate(latest_release_date);
|
||||
if (releaseStatusChip) {
|
||||
releaseStatusChip.textContent = `Status: ${status.replaceAll("_", " ")}`;
|
||||
releaseStatusChip.classList.toggle("chip-warm", status === "update_available");
|
||||
releaseStatusChip.classList.toggle("chip-off", status === "error");
|
||||
}
|
||||
if (releaseChannelChip) releaseChannelChip.textContent = `Channel: ${releaseChannel}`;
|
||||
if (releaseLastCheckChip) releaseLastCheckChip.textContent = `Last check: ${last_check ? fmtDate(last_check) : "—"}`;
|
||||
if (releaseAutoCheck) releaseAutoCheck.checked = !!auto_check;
|
||||
if (releaseProgress) releaseProgress.textContent = "";
|
||||
if (status === "in_progress" && progress) {
|
||||
@@ -338,14 +381,22 @@ export function initReleaseUI({ showToast, showBusy, hideBusy, confirmAction, lo
|
||||
}
|
||||
});
|
||||
|
||||
releaseAdvancedToggle?.addEventListener("click", async () => {
|
||||
releaseAdvanced?.classList.toggle("hidden");
|
||||
if (!releaseAdvanced?.classList.contains("hidden")) {
|
||||
await loadReleaseList();
|
||||
}
|
||||
});
|
||||
|
||||
releaseApplyVersionBtn?.addEventListener("click", async () => {
|
||||
if (!releaseVersionSelect || !releaseVersionSelect.value) {
|
||||
const selected = releaseList?.querySelector("input[name='releaseVersion']:checked");
|
||||
if (!selected) {
|
||||
showToast("Select a version first", "error");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
lastReleaseToastKey = null;
|
||||
const ver = releaseVersionSelect.value;
|
||||
const ver = selected.value;
|
||||
logUi(`Install version ${ver} requested`);
|
||||
releaseBusyActive = true;
|
||||
showBusy(`Installing ${ver}…`, "Applying selected release. This can take up to a minute.");
|
||||
|
||||
Reference in New Issue
Block a user