Skip to content

Commit

Permalink
feat: added download indicator to update modal
Browse files Browse the repository at this point in the history
  • Loading branch information
Tormak9970 committed Oct 8, 2024
1 parent 1cb14ac commit 8cff2f1
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 40 deletions.
1 change: 1 addition & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ tauri-plugin-single-instance = "2.0.0-rc.0"
tauri-plugin-updater = "2.0.0-rc.1"

panic-message = "0.3.0"
rayon = "1.10.0"
phf = { version = "0.11", features = ["macros"] }
chrono = "0.4.34"
image = "0.25.1"
Expand Down
34 changes: 34 additions & 0 deletions src/components/layout/ProgressIndicator.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
export let extraOptions: HTMLAttributes<HTMLDivElement> = {};
export let percent: number;
</script>

<div class="m3-container" role="progressbar" {...extraOptions}>
<div class="percent" style="width: {percent}%;" />
</div>

<style>
:root {
--m3-linear-progress-shape: 4px;
}
.m3-container {
display: inline-flex;
background-color: var(--foreground);
height: 0.5rem;
min-width: 8rem;
width: 100%;
overflow: hidden;
border-radius: var(--m3-linear-progress-shape);
}
.percent {
background-color: var(--highlight);
transition: all 200ms;
border-radius: var(--m3-linear-progress-shape);
}
.m3-container {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
</style>
1 change: 1 addition & 0 deletions src/components/layout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export { default as GridLoadingSkeleton } from "./GridLoadingSkeleton.svelte";

export { default as LoadingSpinner } from "./LoadingSpinner.svelte";
export { default as ProgressBar } from "./ProgressBar.svelte";
export { default as ProgressIndicator } from "./ProgressIndicator.svelte";
export { default as Table } from "./Table.svelte";
export { default as VirtualGrid } from "./VirtualGrid.svelte";
export { default as VirtualList } from "./VirtualList.svelte";
Expand Down
159 changes: 119 additions & 40 deletions src/components/modals/updates/UpdateModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
import { LogController, ToastController } from "@controllers";
import { scrollShadow } from "@directives";
import { Button } from "@interactables";
import { ProgressIndicator } from "@layout";
import type { DownloadEvent } from "@tauri-apps/plugin-updater";
import { onMount } from "svelte";
import { fade } from "svelte/transition";
import ModalBody from "../modal-utils/ModalBody.svelte";
import UpdateField from "./UpdateField.svelte";
Expand All @@ -17,20 +21,26 @@
html: true,
linkify: true
});
let step: "changelog" | "download" | "restart" = "changelog";
let formattedDate = "No date provided";
$: updateData = $updateManifest!;
const months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
$: title = step === "changelog" ? `Update v${$updateManifest?.version} is Available!` : (step === "download" ? `Downloading v${$updateManifest?.version}...` : "Download Complete!")
const dateParts = $updateManifest!.date!.split(" ");
const dateSegs = dateParts[0].split("-").map((seg) => parseInt(seg));
const cleanDate = `${months[dateSegs[1]-1]} ${dateSegs[2]}, ${dateSegs[0]}`
const stepHeight = {
changelog: 390,
download: 122,
restart: 125
}
let contentLength = 0;
let downloaded = 0;
/**
* Handles click events to redirect to the browser.
* @param e The click event.
*/
function clickListener(e: Event): void {
function linkClick(e: Event): void {
const origin = (e.target as Element).closest("a");
if (origin) {
Expand All @@ -41,53 +51,114 @@
}
/**
* Applies the update
* Ignores the update.
*/
async function update(): Promise<void> {
LogController.log(`Installing update v${updateData.version}, released on ${updateData.date}.`);
ToastController.showGenericToast("Installing update...");
async function ignoreUpdate(): Promise<void> {
LogController.log(`Skipping update v${$updateManifest!.version}.`);
open = false;
}
function downloadUpdate() {
LogController.log(`Downloading update v${$updateManifest!.version}, released on ${$updateManifest!.date}.`);
try {
$updateManifest!.download((event: DownloadEvent) => {
switch (event.event) {
case 'Started':
contentLength = event.data.contentLength!;
downloaded = 0;
step = "download";
break;
case 'Progress':
downloaded += event.data.chunkLength!;
break;
case 'Finished':
step = "restart";
break;
}
});
} catch (e: any) {
ToastController.showWarningToast("Failed to download update!");
}
}
async function installUpdate(): Promise<void> {
LogController.log(`Installing update v${$updateManifest!.version}, released on ${$updateManifest!.date}.`);
// Install the update. This will also restart the app on Windows!
await updateData.downloadAndInstall();
await $updateManifest!.install();
// On macOS and Linux you will need to restart the app manually.
// You could use this step to display another confirmation dialog.
await relaunch();
}
/**
* Ignores the update.
*/
async function ignoreUpdate(): Promise<void> {
LogController.log(`Skipping update v${updateData.version}.`);
$showUpdateModal = false;
}
onMount(() => {
let dateString = $updateManifest?.date;
if (dateString) {
let date = new Date(dateString);
if (isNaN(date.getTime())) {
dateString = dateString.replace(/(\+|-)(\d{2}):(\d{2}):(\d{2})$/, '$1$2:$3');
date = new Date(dateString);
}
const lang = "en-US";
const formatter = new Intl.DateTimeFormat(lang, {
year: 'numeric',
month: 'long',
day: 'numeric',
});
formattedDate = formatter.format(date);
}
});
</script>

<ModalBody title={`Update v${updateData.version} is Available!`} open={open} on:close={() => open = false} canClose={false}>
<div class="content">
<ModalBody title={title} open={open} on:close={() => open = false} on:closeEnd={() => $showUpdateModal = false } canClose={false}>
<div class="content" style:height="{stepHeight[step]}px">
<div class="info">
<!-- svelte-ignore missing-declaration -->
<UpdateField label="Your Version" value={APP_VERSION} />
<UpdateField label="Newest Version" value={updateData.version} />
<UpdateField label="Release Date" value={cleanDate} />
<UpdateField label="Release Date" value={formattedDate} />
<UpdateField label="Current Version" value={$updateManifest?.currentVersion ?? "Not Found"} />
<UpdateField label="New Version" value={$updateManifest?.version ?? "Not Found"} />
</div>
<div class="changelog">
<div class="header"><b>Changelog</b>:</div>
<div class="release-notes-container">
{#if step === "changelog"}
<div class="changelog">
<div class="scroll-container" use:scrollShadow={{ background: "--background-dark"}}>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="release-notes" on:click={clickListener}>
{@html mdIt.render(updateData.body ?? "No update details found")}
<div class="release-notes" on:click={linkClick}>
{@html mdIt.render($updateManifest?.body ?? "No update details found")}
</div>
</div>
</div>
</div>
{:else if step === "download"}
<div class="download-container" in:fade={{ duration: 300 }}>
<ProgressIndicator percent={downloaded / (contentLength || 1) * 100} />
</div>
{:else}
<div class="complete-message" in:fade={{ duration: 300 }}>
Steam Art Manager needs to restart. Would you like to restart now?
</div>
{/if}
</div>
<span slot="buttons" class="buttons">
<Button label="Update" onClick={update} width="47.5%" />
<Button label="Ignore" onClick={ignoreUpdate} width="47.5%" />
<div class="side">
{#if step === "changelog"}
<Button label="Skip" onClick={ignoreUpdate} width="100%" />
{:else if step === "restart"}
<Button label="No" onClick={() => { open = false }} width="100%" />
{/if}
</div>
<div class="side">
{#if step === "changelog"}
<Button label="Download" onClick={downloadUpdate} width="100%" />
{:else if step === "restart"}
<Button label="Yes" onClick={installUpdate} width="100%" />
{/if}
</div>
</span>
</ModalBody>

Expand All @@ -105,17 +176,12 @@
width: 100%;
}
.changelog > .header {
font-size: 14px;
margin-bottom: 5px;
}
.changelog > .release-notes-container {
.changelog {
border-radius: 4px;
background-color: var(--background-dark);
overflow: hidden;
height: 60vh;
height: calc(100% - 70px);
}
:global(.changelog .release-notes p) {
Expand All @@ -140,10 +206,23 @@
overflow: auto;
}
.download-container {
margin-top: 2rem;
width: 100%;
}
.complete-message {
margin-top: 1.5rem;
width: 100%;
}
.buttons {
width: 100%;
display: flex;
justify-content: space-around;
justify-content: space-between;
justify-self: flex-end;
}
.buttons > .side {
width: 48%;
}
</style>

0 comments on commit 8cff2f1

Please sign in to comment.