make counters animated with animejs

This commit is contained in:
maxid
2025-12-06 23:33:03 +01:00
parent 961c89e4e2
commit e117bed738
3 changed files with 68 additions and 12 deletions

View File

@@ -4,7 +4,7 @@
import client from '$lib/api';
import { isSemver, semverIsGreater } from '$lib/utils.ts';
import { env } from '$env/dynamic/public';
import { resolve } from '$app/paths';
import { animate } from 'animejs';
let moviesCount: string | null = $state(null);
let episodeCount: string | null = $state(null);
@@ -14,18 +14,55 @@
let releaseUrl: string | null = $state(null);
let newestVersion: string | null = $state(null);
// Elements to animate
let showEl: HTMLSpanElement;
let episodeEl: HTMLSpanElement;
let moviesEl: HTMLSpanElement;
let torrentEl: HTMLSpanElement;
function animateCounter(el: HTMLElement | undefined, target: number, pad = 3) {
if (!el) return;
const obj = { value: 0 };
animate(obj, {
value: target,
duration: 2000,
easing: 'easeInOutSine',
onUpdate: () => {
el.textContent = Math.floor(obj.value).toString().padStart(pad, '0');
}
});
}
onMount(async () => {
let tvShows = await client.GET('/api/v1/tv/shows');
if (!tvShows.error) showCount = tvShows.data.length.toString().padStart(3, '0');
if (!tvShows.error) {
const target = tvShows.data.length;
showCount = target.toString().padStart(3, '0');
animateCounter(showEl, target, 3);
}
let episodes = await client.GET('/api/v1/tv/episodes/count');
if (!episodes.error) episodeCount = episodes.data.toString().padStart(3, '0');
if (!episodes.error) {
const target = Number(episodes.data);
episodeCount = target.toString().padStart(3, '0');
animateCounter(episodeEl, target, 3);
}
let movies = await client.GET('/api/v1/movies');
if (!movies.error) moviesCount = movies.data.length.toString().padStart(3, '0');
if (!movies.error) {
const target = movies.data.length;
moviesCount = target.toString().padStart(3, '0');
animateCounter(moviesEl, target, 3);
}
let torrents = await client.GET('/api/v1/torrent');
if (!torrents.error) torrentCount = torrents.data.length.toString().padStart(3, '0');
if (!torrents.error) {
const target = torrents.data.length;
torrentCount = target.toString().padStart(3, '0');
animateCounter(torrentEl, target, 3);
}
let releases = await fetch('https://api.github.com/repos/maxdorninger/mediamanager/releases');
if (releases.ok) {
@@ -38,25 +75,32 @@
<div class="flex flex-wrap gap-2">
<div class="flex-auto">
<Card title="TV Shows" footer="Total count of downloaded episodes">{showCount ?? 'Error'}</Card>
<Card title="TV Shows" footer="Total count of downloaded episodes">
<span bind:this={showEl}>{showCount ?? 'Error'}</span>
</Card>
</div>
<div class="flex-auto">
<Card title="Episodes" footer="Total count of downloaded episodes"
>{episodeCount ?? 'Error'}</Card
>
<Card title="Episodes" footer="Total count of downloaded episodes">
<span bind:this={episodeEl}>{episodeCount ?? 'Error'}</span>
</Card>
</div>
<div class="flex-auto">
<Card title="Movies" footer="Total count of movies">{moviesCount ?? 'Error'}</Card>
<Card title="Movies" footer="Total count of movies">
<span bind:this={moviesEl}>{moviesCount ?? 'Error'}</span>
</Card>
</div>
<div class="flex-auto">
<Card title="Torrents" footer="Total count of torrents/NZBs">{torrentCount ?? 'Error'}</Card>
<Card title="Torrents" footer="Total count of torrents/NZBs">
<span bind:this={torrentEl}>{torrentCount ?? 'Error'}</span>
</Card>
</div>
<div class="flex-auto">
{#if semverIsGreater(newestVersion ?? '', installedVersion ?? '') || !isSemver(installedVersion ?? '')}
<Card title="New version available!" footer="A new version of MediaManager is available!">
<a
rel="external"
target="_blank"
href={resolve(releaseUrl ?? 'https://github.com/maxdorninger/MediaManager/releases')}
href={releaseUrl ?? 'https://github.com/maxdorninger/MediaManager/releases'}
class="underline"
>
{installedVersion} → v{newestVersion}