E frontend reconciliation (2/2): align consumers to generated bindings; svelte-check clean
Traceability Validation / Check Requirement Traces (push) Failing after 21s
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 13m21s
🏗️ Build and Test JellyTau / Build Android APK (push) Failing after 2m14s

Reconcile the ~50 frontend files that consumed the old hand-written types against
the stricter generated bindings (141 -> 0 svelte-check errors):

- Nullable strictness: null-coalesce/guard at consumer sites; widen shared helpers
  (CachedImage.tag, ticksToSeconds, formatDuration, getSessionIcon, session store
  send*/transferToRemote) to accept null.
- Field-name fixes exposed by codegen: userData.played -> isPlayed; remote
  NowPlayingItem uses album (not albumName); ArtistItem id/name.
- player.ts: normalize remote NowPlayingItem -> MediaItem in mergedMedia.
- ArtistItem now serializes camelCase (PascalCase alias retained for Jellyfin
  deserialize); update its serialize test.
- Update downloads.test.ts to the bundled { request } shape; complete the
  sessions.test.ts NowPlayingItem mock.

Frontend: svelte-check 0 errors, vitest 448 passing. Backend: 387 passing.
This commit is contained in:
2026-06-20 20:49:20 +02:00
parent 76c78e2edc
commit 14e9d7e03a
21 changed files with 85 additions and 68 deletions
+2 -2
View File
@@ -52,7 +52,7 @@
if (!showProgress || !("userData" in item) || !item.userData || !item.runTimeTicks) {
return 0;
}
return (item.userData.playbackPositionTicks / item.runTimeTicks) * 100;
return ((item.userData.playbackPositionTicks ?? 0) / item.runTimeTicks) * 100;
});
const subtitle = $derived(() => {
@@ -112,7 +112,7 @@
{/if}
<!-- Played indicator -->
{#if "userData" in item && item.userData?.played}
{#if "userData" in item && item.userData?.isPlayed}
<div class="absolute top-2 right-2">
<svg class="w-5 h-5 text-[var(--color-jellyfin)]" fill="currentColor" viewBox="0 0 24 24">
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>