many changes
Traceability Validation / Check Requirement Traces (push) Failing after 1m18s
🏗️ Build and Test JellyTau / Build APK and Run Tests (push) Has been cancelled

This commit is contained in:
2026-02-14 00:09:47 +01:00
parent 6d1c618a3a
commit e3797f32ca
74 changed files with 6718 additions and 771 deletions
+21 -20
View File
@@ -2,7 +2,6 @@
import type { MediaItem, Library } from "$lib/api/types";
import { auth } from "$lib/stores/auth";
import { downloads } from "$lib/stores/downloads";
import { getImageUrlSync } from "$lib/services/imageCache";
interface Props {
item: MediaItem | Library;
@@ -14,6 +13,9 @@
let { item, size = "medium", showProgress = false, showDownloadStatus = true, onclick }: Props = $props();
// Image URL state - loaded asynchronously
let imageUrl = $state<string>("");
// Check if this item is downloaded
const downloadInfo = $derived(
Object.values($downloads.downloads).find((d) => d.itemId === item.id)
@@ -40,32 +42,35 @@
return "aspect-video";
});
function getImageUrl(): string {
// Load image URL asynchronously from backend
async function loadImageUrl(): Promise<void> {
try {
const repo = auth.getRepository();
const serverUrl = repo.serverUrl;
const id = item.id;
const tag = "primaryImageTag" in item ? item.primaryImageTag : ("imageTag" in item ? item.imageTag : undefined);
const maxWidth = size === "large" ? 400 : size === "medium" ? 300 : 200;
const tag = "primaryImageTag" in item ? item.primaryImageTag : ("imageTag" in item ? item.imageTag : undefined);
// Use the caching service - returns server URL immediately and triggers background caching
return getImageUrlSync(serverUrl, id, "Primary", {
imageUrl = await repo.getImageUrl(item.id, "Primary", {
maxWidth,
tag,
});
} catch {
return "";
imageUrl = "";
}
}
function getProgress(): number {
// Load image URL whenever item or size changes
$effect(() => {
loadImageUrl();
});
const progress = $derived(() => {
if (!showProgress || !("userData" in item) || !item.userData || !item.runTimeTicks) {
return 0;
}
return (item.userData.playbackPositionTicks / item.runTimeTicks) * 100;
}
});
function getSubtitle(): string {
const subtitle = $derived(() => {
if (!("type" in item)) return "";
switch (item.type) {
@@ -82,11 +87,7 @@
default:
return "";
}
}
const imageUrl = $derived(getImageUrl());
const progress = $derived(getProgress());
const subtitle = $derived(getSubtitle());
});
</script>
<button
@@ -122,11 +123,11 @@
</div>
<!-- Progress bar -->
{#if progress > 0}
{#if progress() > 0}
<div class="absolute bottom-0 left-0 right-0 h-1 bg-gray-800">
<div
class="h-full bg-[var(--color-jellyfin)]"
style="width: {progress}%"
style="width: {progress()}%"
></div>
</div>
{/if}
@@ -188,8 +189,8 @@
<p class="text-sm font-medium text-white truncate group-hover/card:text-[var(--color-jellyfin)] transition-colors">
{item.name}
</p>
{#if subtitle}
<p class="text-xs text-gray-400 truncate">{subtitle}</p>
{#if subtitle()}
<p class="text-xs text-gray-400 truncate">{subtitle()}</p>
{/if}
</div>
</button>