268 lines
7.1 KiB
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> |