feat(offlinetiles): add download progress bar
Some checks failed
TrafficCue CI / check (push) Failing after 54s
TrafficCue CI / build (push) Successful in 50s

This commit is contained in:
2025-08-11 13:16:40 +02:00
parent f9d34d942e
commit d8b04ff756
7 changed files with 62 additions and 15 deletions

View File

@@ -1,8 +1,10 @@
<script>
<script lang="ts">
import { downloadPMTiles, getRemoteList } from "$lib/services/OfflineTiles";
import { DownloadCloudIcon } from "@lucide/svelte";
import SettingsButton from "./SettingsButton.svelte";
import SidebarHeader from "../SidebarHeader.svelte";
let progresses: {[key: string]: number} = $state({});
</script>
<SidebarHeader>
@@ -22,8 +24,10 @@
{/if}
{#each list as item, _index (item.file)}
<SettingsButton disabled={!window.__TAURI__} icon={DownloadCloudIcon} text={item.name} onclick={async () => {
await downloadPMTiles("https://trafficcue-tiles.picoscratch.de/" + item.file, item.name.includes("World") ? "world": "tiles");
<SettingsButton disabled={!window.__TAURI__} icon={DownloadCloudIcon} text={item.name} progress={progresses[item.file] ?? -1} onclick={async () => {
await downloadPMTiles("https://trafficcue-tiles.picoscratch.de/" + item.file, item.name.includes("World") ? "world": "tiles", (progress, total) => {
progresses[item.file] = (progress / total) * 100;
});
alert(`Downloaded ${item.name}`);
location.reload();
}} />

View File

@@ -3,8 +3,13 @@
import type { IconProps } from "@lucide/svelte";
import type { Component } from "svelte";
import { view } from "../../view.svelte";
import Progress from "$lib/components/ui/progress/progress.svelte";
const { icon: Icon, text, view: viewName, onclick, disabled }: { icon: Component<IconProps>, text: string, view?: string, onclick?: () => void, disabled?: boolean } = $props();
const {
icon: Icon, text, view: viewName, onclick, disabled, progress
}: {
icon: Component<IconProps>, text: string, view?: string, onclick?: () => void, disabled?: boolean, progress?: number
} = $props();
</script>
<Button variant="secondary" style="width: 100%; height: 40px;" {disabled} onclick={() => {
@@ -13,4 +18,9 @@
}}>
<Icon />
{text}
{#if progress == -1}
<div style="width: 100%;"></div>
{:else if progress}
<Progress value={progress} />
{/if}
</Button>

View File

@@ -0,0 +1,7 @@
import Root from "./progress.svelte";
export {
Root,
//
Root as Progress,
};

View File

@@ -0,0 +1,27 @@
<script lang="ts">
import { Progress as ProgressPrimitive } from "bits-ui";
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
max = 100,
value,
...restProps
}: WithoutChildrenOrChild<ProgressPrimitive.RootProps> = $props();
</script>
<ProgressPrimitive.Root
bind:ref
data-slot="progress"
class={cn("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className)}
{value}
{max}
{...restProps}
>
<div
data-slot="progress-indicator"
class="bg-primary h-full w-full flex-1 transition-all"
style="transform: translateX(-{100 - (100 * (value ?? 0)) / (max ?? 1)}%)"
></div>
</ProgressPrimitive.Root>

View File

@@ -3,7 +3,7 @@ import { BaseDirectory, exists, mkdir, open, remove, SeekMode } from "@tauri-app
import { download } from "@tauri-apps/plugin-upload";
import { PMTiles, TileType, type Source } from "pmtiles";
export async function downloadPMTiles(url: string, name: string): Promise<void> {
export async function downloadPMTiles(url: string, name: string, onprogress?: (progress: number, total: number) => any): Promise<void> {
// if(!window.__TAURI__) {
// throw new Error("Tauri environment is not available.");
// }
@@ -34,6 +34,7 @@ export async function downloadPMTiles(url: string, name: string): Promise<void>
await download(url, path, ({ progress, total }) => {
totalProgress += progress;
console.log(`Download progress: ${Math.round((totalProgress / total) * 100)}% (${totalProgress}\tof ${total} bytes)`);
if(onprogress) onprogress(totalProgress, total);
});
console.log(`Download completed: ${path}`);