Files
Vesktop/static/views/updater.html

268 lines
7.1 KiB
HTML

<head>
<title>Vesktop Updater</title>
<link rel="stylesheet" href="./style.css" type="text/css" />
<style>
html,
body {
height: 100%;
margin: 0;
box-sizing: border-box;
}
body {
padding: 2em;
display: flex;
flex-direction: column;
height: 100vh;
header,
footer {
flex: 0 0 auto;
}
main {
flex: 1 1 0%;
min-height: 0;
overflow: auto;
}
footer {
margin-top: 1em;
}
}
#versions {
display: inline-grid;
grid-template-columns: auto 1fr;
column-gap: 0.5em;
.label {
white-space: nowrap;
}
.value {
text-align: left;
}
#current-version {
color: #fc8f8a;
}
#new-version {
color: #71c07f;
}
}
#release-notes {
display: grid;
gap: 1em;
}
#buttons {
display: flex;
gap: 0.5em;
justify-content: end;
}
button {
cursor: pointer;
padding: 0.5rem 1rem;
font-size: 1.2em;
color: var(--fg);
border: none;
border-radius: 3px;
font-weight: bold;
transition: filter 0.2 ease-in-out;
}
button:hover,
button:active {
filter: brightness(0.9);
}
.green {
background-color: #248046;
}
.grey {
background-color: rgba(151, 151, 159, 0.12);
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0 0 0.5em 0;
}
h1 {
text-align: center;
}
h2 {
margin-bottom: 1em;
}
dialog {
width: 80%;
padding: 2em;
}
progress {
width: 100%;
height: 1.5em;
margin-top: 1em;
}
#error {
color: red;
font-weight: bold;
}
.spinner-wrapper {
display: flex;
justify-content: center;
align-items: center;
margin-top: 2em;
}
.spinner {
width: 48px;
height: 48px;
border: 5px solid var(--fg);
border-bottom-color: transparent;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
@keyframes rotation {
to {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<header>
<h1>An update is available!</h1>
</header>
<main>
<p id="versions">
<span class="label">Current version:</span> <span id="current-version" class="value"></span>
<span class="label">New version:</span> <span id="new-version" class="value"></span>
</p>
<h2>Release Notes</h2>
<div id="release-notes"></div>
</main>
<footer>
<section id="buttons">
<button id="update-button" class="green">Install update & restart</button>
<button id="later-button" class="grey">Remind me later</button>
<button id="ignore-button" class="grey">Ignore this update</button>
</section>
</footer>
<dialog id="update-dialog" closedby="none">
<h2>Downloading Update</h2>
<p>
Please wait while the update is being downloaded. Once the update finished downloading, it will
automatically install and Vesktop will restart.
</p>
<p id="linux-note" style="display: none">You will likely be prompted to enter your password. Do so to finish the
update.</p>
<progress id="download-progress" value="0" max="100"></progress>
<p id="error"></p>
</dialog>
<dialog id="installing-dialog" closedby="none">
<h2>Installing Update</h2>
<p>Please wait while the update is being installed. Vesktop will restart shortly.</p>
<div class="spinner-wrapper">
<div class="spinner"></div>
</div>
</dialog>
</body>
<script type="module">
const { update, version: currentVersion } = await VesktopUpdaterNative.getData();
document.getElementById("current-version").textContent = currentVersion;
document.getElementById("new-version").textContent = update.version;
document.getElementById("release-notes").innerHTML = update.releaseNotes
.map(({ version, note: html }) => `
<section>
<h3>Version ${version}</h3>
<div>${html.replace(/<\/?h([1-3])/g, (m, level) => m.replace(level, Number(level) + 3))}</div>
</section>
`)
.join("\n");
document.querySelectorAll("a").forEach((a) => {
a.target = "_blank";
});
// remove useless headings
document.querySelectorAll("h3, h4, h5, h6").forEach(h => {
if (h.textContent.trim().toLowerCase() === "what's changed") {
h.remove()
}
});
/** @type {HTMLDialogElement} */
const updateDialog = document.getElementById("update-dialog");
/** @type {HTMLDialogElement} */
const installingDialog = document.getElementById("installing-dialog");
/** @type {HTMLProgressElement} */
const downloadProgress = document.getElementById("download-progress");
/** @type {HTMLElement} */
const errorText = document.getElementById("error");
document.getElementById("update-button").addEventListener("click", () => {
downloadProgress.value = 0;
errorText.textContent = "";
if (navigator.platform.startsWith("Linux")) {
document.getElementById("linux-note").style.display = "initial";
}
updateDialog.showModal();
VesktopUpdaterNative.installUpdate().then(() => {
downloadProgress.value = 100
updateDialog.closedBy = "any";
installingDialog.showModal();
updateDialog.style.visibility = "hidden";
});
});
document.getElementById("later-button").addEventListener("click", () => VesktopUpdaterNative.snoozeUpdate());
document.getElementById("ignore-button").addEventListener("click", () => {
const confirmed = confirm("Are you sure you want to ignore this update? You will not be notified about this update again. Updates are important for security and stability.");
if (confirmed)
VesktopUpdaterNative.ignoreUpdate()
});
VesktopUpdaterNative.onProgress(percent => downloadProgress.value = percent);
VesktopUpdaterNative.onError(message => {
updateDialog.closedBy = "any";
errorText.textContent = `An error occurred while downloading the update: ${message}`;
installingDialog.close();
updateDialog.style.visibility = "initial";
});
</script>