Many improvemtns and fixes related to decoupling of svelte and rust on android.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import type { MediaItem } from "$lib/api/types";
|
||||
import { auth } from "$lib/stores/auth";
|
||||
import CachedImage from "$lib/components/common/CachedImage.svelte";
|
||||
|
||||
interface Props {
|
||||
items: MediaItem[];
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
let currentIndex = $state(0);
|
||||
let intervalId: number | null = null;
|
||||
let heroImageUrl = $state<string>("");
|
||||
|
||||
// Touch/swipe state
|
||||
let touchStartX = $state(0);
|
||||
@@ -22,82 +21,45 @@
|
||||
|
||||
const currentItem = $derived(items[currentIndex] ?? null);
|
||||
|
||||
// Load hero image URL asynchronously based on item priority
|
||||
async function loadHeroImageUrl(): Promise<void> {
|
||||
if (!currentItem) {
|
||||
heroImageUrl = "";
|
||||
return;
|
||||
// Compute the best image source for the hero banner (no fetch, pure derivation)
|
||||
const heroImageSource = $derived.by(() => {
|
||||
if (!currentItem) return null;
|
||||
|
||||
// 1. Try backdrop image first (best for hero display)
|
||||
if (currentItem.backdropImageTags?.[0]) {
|
||||
return { itemId: currentItem.id, imageType: "Backdrop" as const, tag: currentItem.backdropImageTags[0] };
|
||||
}
|
||||
|
||||
try {
|
||||
const repo = auth.getRepository();
|
||||
|
||||
// 1. Try backdrop image first (best for hero display)
|
||||
if (currentItem.backdropImageTags?.[0]) {
|
||||
heroImageUrl = await repo.getImageUrl(currentItem.id, "Backdrop", {
|
||||
maxWidth: 1920,
|
||||
tag: currentItem.backdropImageTags[0],
|
||||
});
|
||||
return;
|
||||
// 2. For episodes, try series/season backdrops
|
||||
if (currentItem.type === "Episode") {
|
||||
if (currentItem.seriesId && currentItem.parentBackdropImageTags?.[0]) {
|
||||
return { itemId: currentItem.seriesId, imageType: "Backdrop" as const, tag: currentItem.parentBackdropImageTags[0] };
|
||||
}
|
||||
|
||||
// 2. For episodes, try to use series backdrop from parent
|
||||
if (currentItem.type === "Episode") {
|
||||
// First try parent backdrop tags (includes image tag for caching)
|
||||
if (currentItem.seriesId && currentItem.parentBackdropImageTags?.[0]) {
|
||||
heroImageUrl = await repo.getImageUrl(currentItem.seriesId, "Backdrop", {
|
||||
maxWidth: 1920,
|
||||
tag: currentItem.parentBackdropImageTags[0],
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Fallback: try series backdrop without tag (may not be cached optimally)
|
||||
if (currentItem.seriesId) {
|
||||
heroImageUrl = await repo.getImageUrl(currentItem.seriesId, "Backdrop", {
|
||||
maxWidth: 1920,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Last resort for episodes: try season backdrop
|
||||
if (currentItem.seasonId) {
|
||||
heroImageUrl = await repo.getImageUrl(currentItem.seasonId, "Backdrop", {
|
||||
maxWidth: 1920,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (currentItem.seriesId) {
|
||||
return { itemId: currentItem.seriesId, imageType: "Backdrop" as const, tag: undefined };
|
||||
}
|
||||
|
||||
// 3. For music tracks, try album backdrop first, then primary
|
||||
if (currentItem.type === "Audio" && currentItem.albumId) {
|
||||
// Try album backdrop first (more cinematic for hero)
|
||||
heroImageUrl = await repo.getImageUrl(currentItem.albumId, "Backdrop", {
|
||||
maxWidth: 1920,
|
||||
});
|
||||
return;
|
||||
if (currentItem.seasonId) {
|
||||
return { itemId: currentItem.seasonId, imageType: "Backdrop" as const, tag: undefined };
|
||||
}
|
||||
|
||||
// 4. Fall back to primary image (poster, album art, episode thumbnail)
|
||||
if (currentItem.primaryImageTag) {
|
||||
heroImageUrl = await repo.getImageUrl(currentItem.id, "Primary", {
|
||||
maxWidth: 1920,
|
||||
tag: currentItem.primaryImageTag,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. Last resort for audio: try album primary image
|
||||
if (currentItem.type === "Audio" && currentItem.albumId) {
|
||||
heroImageUrl = await repo.getImageUrl(currentItem.albumId, "Primary", {
|
||||
maxWidth: 1920,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
heroImageUrl = "";
|
||||
} catch {
|
||||
heroImageUrl = "";
|
||||
}
|
||||
}
|
||||
|
||||
// 3. For music tracks, try album backdrop
|
||||
if (currentItem.type === "Audio" && currentItem.albumId) {
|
||||
return { itemId: currentItem.albumId, imageType: "Backdrop" as const, tag: undefined };
|
||||
}
|
||||
|
||||
// 4. Fall back to primary image
|
||||
if (currentItem.primaryImageTag) {
|
||||
return { itemId: currentItem.id, imageType: "Primary" as const, tag: currentItem.primaryImageTag };
|
||||
}
|
||||
|
||||
// 5. Last resort for audio: album primary
|
||||
if (currentItem.type === "Audio" && currentItem.albumId) {
|
||||
return { itemId: currentItem.albumId, imageType: "Primary" as const, tag: undefined };
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
function next() {
|
||||
currentIndex = (currentIndex + 1) % items.length;
|
||||
@@ -143,11 +105,6 @@
|
||||
touchEndX = 0;
|
||||
}
|
||||
|
||||
// Load hero image whenever current item changes
|
||||
$effect(() => {
|
||||
loadHeroImageUrl();
|
||||
});
|
||||
|
||||
// Auto-rotate logic
|
||||
$effect(() => {
|
||||
if (autoRotate && items.length > 1) {
|
||||
@@ -166,10 +123,13 @@
|
||||
ontouchmove={handleTouchMove}
|
||||
ontouchend={handleTouchEnd}
|
||||
>
|
||||
{#if heroImageUrl}
|
||||
<img
|
||||
src={heroImageUrl}
|
||||
alt={currentItem?.name}
|
||||
{#if heroImageSource}
|
||||
<CachedImage
|
||||
itemId={heroImageSource.itemId}
|
||||
imageType={heroImageSource.imageType}
|
||||
tag={heroImageSource.tag}
|
||||
maxWidth={1920}
|
||||
alt={currentItem?.name ?? ""}
|
||||
class="absolute inset-0 w-full h-full object-cover"
|
||||
/>
|
||||
{:else}
|
||||
|
||||
Reference in New Issue
Block a user