domain: primaryImageTag -> imageId end-to-end (phase 4a/4b)

Rust: PlayerMediaItem and MergedMediaItem gain image_id (dual-carry),
populated from primary_image_tag at every construction/conversion site.
Regenerated bindings.

Frontend: all catalog + player + merged readers now use imageId. The
NowPlayingItem->MediaItem bridge (player.ts) properly maps the remote
session's Jellyfin fields (Type, runTimeTicks, primaryImageTag) onto the
neutral kind/durationMs/imageId. Types that are genuinely out of scope
(Person, NowPlayingItem, PlayItemRequest) keep primaryImageTag.

Rust 456, frontend 644, check clean.
This commit is contained in:
2026-07-23 21:40:58 +02:00
parent 2b42b74912
commit 93d198ce21
33 changed files with 107 additions and 51 deletions
+2 -2
View File
@@ -143,7 +143,7 @@
<CachedImage
itemId={artworkItemId}
imageType="Primary"
tag={displayMedia?.primaryImageTag}
tag={displayMedia?.imageId}
maxWidth={800}
alt=""
class="w-full h-full object-cover blur-3xl opacity-30"
@@ -223,7 +223,7 @@
<CachedImage
itemId={artworkItemId}
imageType="Primary"
tag={displayMedia?.primaryImageTag}
tag={displayMedia?.imageId}
maxWidth={500}
alt={displayMedia?.name}
class="w-full h-full object-cover"
+1 -1
View File
@@ -326,7 +326,7 @@
<CachedImage
itemId={displayMedia.albumId || displayMedia.id}
imageType="Primary"
tag={displayMedia.primaryImageTag}
tag={displayMedia.imageId}
maxWidth={100}
alt={displayMedia?.name}
class="w-full h-full object-cover"
@@ -78,11 +78,11 @@
<div
class="relative flex-shrink-0 w-28 h-16 rounded-lg overflow-hidden bg-gray-800"
>
{#if imageId && $nextEpisodeItem.primaryImageTag}
{#if imageId && $nextEpisodeItem.imageId}
<CachedImage
itemId={imageId}
imageType="Primary"
tag={$nextEpisodeItem.primaryImageTag}
tag={$nextEpisodeItem.imageId}
maxHeight={200}
alt={$nextEpisodeItem.name}
class="w-full h-full object-cover"
+2 -2
View File
@@ -184,11 +184,11 @@
<!-- Artwork -->
<div class="w-10 h-10 rounded bg-gray-800 flex-shrink-0 overflow-hidden">
{#if item.primaryImageTag}
{#if item.imageId}
<CachedImage
itemId={item.id}
imageType="Primary"
tag={item.primaryImageTag}
tag={item.imageId}
maxWidth={80}
alt={item.name}
class="w-full h-full object-cover"
+3 -3
View File
@@ -1223,7 +1223,7 @@
needsTranscoding: false,
// Now-playing metadata so the lockscreen/miniplayer show the item.
artist: media.seriesName ?? null,
primaryImageTag: media.primaryImageTag ?? null,
primaryImageTag: media.imageId ?? null,
serverId: media.serverId ?? null,
// Real duration so the lockscreen scrubber has a range to draw.
durationSeconds: duration > 0 ? duration : null,
@@ -1626,11 +1626,11 @@
{#if !isMediaReady}
<div class="absolute inset-0 flex items-center justify-center bg-black">
<!-- Poster/Title Card -->
{#if media?.primaryImageTag}
{#if media?.imageId}
<CachedImage
itemId={media.id}
imageType="Primary"
tag={media.primaryImageTag}
tag={media.imageId}
maxHeight={1080}
alt={media?.name || "Video"}
class="max-w-full max-h-full object-contain"