From 14e9d7e03a010e3dfd2533ccf06527bdba9723e4 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sat, 20 Jun 2026 20:49:20 +0200 Subject: [PATCH] E frontend reconciliation (2/2): align consumers to generated bindings; svelte-check clean 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. --- src-tauri/src/repository/types.rs | 12 +++++++++--- src/lib/components/common/CachedImage.svelte | 2 +- src/lib/components/library/CastSection.svelte | 3 ++- src/lib/components/library/CrewLinks.svelte | 2 +- .../library/EpisodeFocusView.svelte | 8 ++++---- src/lib/components/library/EpisodeRow.svelte | 12 ++++++------ .../components/library/LibraryListView.svelte | 6 +++--- src/lib/components/library/MediaCard.svelte | 4 ++-- src/lib/components/library/TrackList.svelte | 2 +- src/lib/components/player/Queue.svelte | 2 +- .../components/sessions/RemoteControls.svelte | 12 ++++++------ .../components/sessions/SessionCard.svelte | 8 ++++---- .../sessions/SessionPickerModal.svelte | 4 ++-- .../components/sessions/SessionsList.svelte | 2 +- src/lib/stores/downloads.test.ts | 19 +++++++++++-------- src/lib/stores/playbackMode.ts | 6 +++--- src/lib/stores/sessions.test.ts | 11 +++++++++-- src/lib/stores/sessions.ts | 16 ++++++++-------- src/lib/utils/duration.ts | 2 +- src/lib/utils/playbackUnits.ts | 4 ++-- src/routes/library/[id]/+page.svelte | 16 ++++++++-------- 21 files changed, 85 insertions(+), 68 deletions(-) diff --git a/src-tauri/src/repository/types.rs b/src-tauri/src/repository/types.rs index 32c2a72..3f9a5f6 100644 --- a/src-tauri/src/repository/types.rs +++ b/src-tauri/src/repository/types.rs @@ -405,15 +405,21 @@ mod tests { #[test] fn test_artist_item_serialize() { - // Test that ArtistItem serializes to PascalCase for consistency + // ArtistItem serializes to camelCase for the frontend; it still accepts + // Jellyfin's PascalCase on deserialize via #[serde(alias = ...)]. let artist = ArtistItem { id: "test-id".to_string(), name: "Test Artist".to_string(), }; let json = serde_json::to_string(&artist).expect("Failed to serialize"); - assert!(json.contains(r#""Id":"test-id""#)); - assert!(json.contains(r#""Name":"Test Artist""#)); + assert!(json.contains(r#""id":"test-id""#)); + assert!(json.contains(r#""name":"Test Artist""#)); + + let from_pascal: ArtistItem = + serde_json::from_str(r#"{"Id":"x","Name":"Y"}"#).expect("Failed to deserialize"); + assert_eq!(from_pascal.id, "x"); + assert_eq!(from_pascal.name, "Y"); } #[test] diff --git a/src/lib/components/common/CachedImage.svelte b/src/lib/components/common/CachedImage.svelte index 55fc67e..98133e8 100644 --- a/src/lib/components/common/CachedImage.svelte +++ b/src/lib/components/common/CachedImage.svelte @@ -6,7 +6,7 @@ interface Props { itemId: string; imageType?: string; - tag?: string; + tag?: string | null; maxWidth?: number; maxHeight?: number; class?: string; diff --git a/src/lib/components/library/CastSection.svelte b/src/lib/components/library/CastSection.svelte index 0498b31..2948b43 100644 --- a/src/lib/components/library/CastSection.svelte +++ b/src/lib/components/library/CastSection.svelte @@ -28,6 +28,7 @@ continue; } const type = person.type; + if (!type) continue; if (type in groups) { groups[type].push(person); } else { @@ -84,7 +85,7 @@
{#each filteredPeople as person, index (person.id)}