From 2c317fb0ec778409da935c143344e5cdd21c691a Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 1 May 2026 08:30:36 +0300 Subject: [PATCH] fix remaining build errors --- src/api/tmdb.ts | 22 +++++++++---- src/components/detail/DetailHero.tsx | 2 +- src/components/detail/DetailMainSections.tsx | 7 ++-- src/components/detail/VersionsSelector.tsx | 2 +- src/components/discover/DecadeStrip.tsx | 2 +- src/components/discover/Roulette.tsx | 2 +- src/components/discover/SpotlightHero.tsx | 1 + src/components/discover/TonightHero.tsx | 5 +-- src/components/layout/AppHeader.tsx | 4 +-- src/components/player/PlayerBottomBar.tsx | 2 +- src/components/player/PlayerOverlays.tsx | 2 +- src/components/request/RequestModal.tsx | 2 +- src/components/ui/PersonSpotlightRow.tsx | 2 +- src/components/ui/QuickLookModal.tsx | 2 +- src/hooks/use-prebuffer.ts | 2 +- src/lib/downloads.ts | 2 +- src/lib/trakt.ts | 8 +++-- src/pages/PersonPage.tsx | 9 ++++-- src/pages/PlayerPage.tsx | 5 +-- src/pages/TmdbDetailPage.tsx | 5 +-- src/pages/discover/rows.tsx | 3 +- .../settings/sections/ServerDashboard.tsx | 2 +- src/types/dom-extensions.d.ts | 32 +++++++++++++++++++ src/vite-env.d.ts | 29 ----------------- 24 files changed, 90 insertions(+), 64 deletions(-) create mode 100644 src/types/dom-extensions.d.ts diff --git a/src/api/tmdb.ts b/src/api/tmdb.ts index 6eb5d6b..36f2f19 100644 --- a/src/api/tmdb.ts +++ b/src/api/tmdb.ts @@ -461,12 +461,22 @@ export interface TmdbSearchMultiResult extends TmdbMovie { known_for?: any[] } -/** TMDB discover result - union of movie and tv with optional media_type. */ -export type TmdbDiscoverItem = - | TmdbMovie - | TmdbTvShow - | (TmdbMovie & { media_type: string }) - | (TmdbTvShow & { media_type: string }) +/** TMDB discover result - permissive interface for movie / tv / multi. */ +export interface TmdbDiscoverItem { + id: number + title?: string + name?: string + overview?: string + poster_path?: string | null + backdrop_path?: string | null + release_date?: string + first_air_date?: string + vote_average?: number + vote_count?: number + adult?: boolean + original_language?: string + media_type?: string +} /* ────────────────────────────────────────────────────────────── */ /* Fetcher */ diff --git a/src/components/detail/DetailHero.tsx b/src/components/detail/DetailHero.tsx index c0e6883..da38715 100644 --- a/src/components/detail/DetailHero.tsx +++ b/src/components/detail/DetailHero.tsx @@ -277,7 +277,7 @@ export default function DetailHero({ )} diff --git a/src/components/detail/DetailMainSections.tsx b/src/components/detail/DetailMainSections.tsx index aa2e0b6..2920be3 100644 --- a/src/components/detail/DetailMainSections.tsx +++ b/src/components/detail/DetailMainSections.tsx @@ -10,6 +10,7 @@ import type { TmdbKeyword, TmdbReview, TmdbVideo, + TmdbCastMember, } from '../../api/tmdb' import type { CinemetaMeta } from '../../api/cinemeta' import type { TvmazeShow } from '../../api/tvmaze' @@ -66,8 +67,8 @@ interface Props { wikiTitle: string | null region: string watchProviders: TmdbWatchProviders | null | undefined - cast: unknown[] - crew: unknown[] + cast: TmdbCastMember[] + crew: TmdbCastMember[] keywords: TmdbKeyword[] reviews: TmdbReview[] videos: TmdbVideo[] | undefined @@ -76,7 +77,7 @@ interface Props { libraryMap: Map | undefined overview: string overviewSource: string | null - sources: { Id?: string }[] + sources: { Id?: string | null }[] activeSourceId: string | null onSourceChange: (id: string | null) => void } diff --git a/src/components/detail/VersionsSelector.tsx b/src/components/detail/VersionsSelector.tsx index ee92bb2..fea7930 100644 --- a/src/components/detail/VersionsSelector.tsx +++ b/src/components/detail/VersionsSelector.tsx @@ -22,7 +22,7 @@ export default function VersionsSelector({ item, selectedSourceId, onChange }: P
{sources.map(src => { const summary = summarizeSource(src) - const id = src.Id || src.id || '' + const id = src.Id || '' const active = id === selectedSourceId return (
diff --git a/src/hooks/use-prebuffer.ts b/src/hooks/use-prebuffer.ts index be29e87..230e701 100644 --- a/src/hooks/use-prebuffer.ts +++ b/src/hooks/use-prebuffer.ts @@ -41,7 +41,7 @@ export function usePrebuffer(item: BaseItemDto | null | undefined, armed: boolea playbackInfoDto: { UserId: jellyfinClient.getAuthState()!.userId, MaxStreamingBitrate: 140_000_000, - DeviceProfile: browserDeviceProfile(), + DeviceProfile: browserDeviceProfile() as any, AutoOpenLiveStream: true, EnableDirectPlay: true, EnableDirectStream: true, diff --git a/src/lib/downloads.ts b/src/lib/downloads.ts index 570da87..026bc06 100644 --- a/src/lib/downloads.ts +++ b/src/lib/downloads.ts @@ -49,7 +49,7 @@ export async function startDownload(args: { } } - const blob = new Blob(chunks) + const blob = new Blob(chunks as BlobPart[]) const objectUrl = URL.createObjectURL(blob) store.update(dl.id, { status: 'done', diff --git a/src/lib/trakt.ts b/src/lib/trakt.ts index 44bb1ae..ecd4ccf 100644 --- a/src/lib/trakt.ts +++ b/src/lib/trakt.ts @@ -250,7 +250,9 @@ export async function addToTraktWatchlist(item: BaseItemDto): Promise { if (!token) return false const body = await buildScrobbleBody(item, 0) if (!body) return false - const payload = item.Type === 'Movie' ? { movies: [{ ids: body.movie.ids }] } : { shows: [{ ids: body.show.ids }] } + const payload = item.Type === 'Movie' + ? { movies: [{ ids: (body as { movie: { ids: Record } }).movie.ids }] } + : { shows: [{ ids: (body as { show: { ids: Record } }).show.ids }] } try { const res = await fetch(`${BASE}/sync/watchlist`, { method: 'POST', @@ -269,7 +271,9 @@ export async function removeFromTraktWatchlist(item: BaseItemDto): Promise } }).movie.ids }] } + : { shows: [{ ids: (body as { show: { ids: Record } }).show.ids }] } try { const res = await fetch(`${BASE}/sync/watchlist/remove`, { method: 'POST', diff --git a/src/pages/PersonPage.tsx b/src/pages/PersonPage.tsx index ec5c68e..3a7b822 100644 --- a/src/pages/PersonPage.tsx +++ b/src/pages/PersonPage.tsx @@ -28,7 +28,10 @@ export default function PersonPage() { const filmography = useMemo(() => { const cast = (person?.combined_credits?.cast || []).map(c => ({ ...c, _kind: 'cast' as const })) const crew = (person?.combined_credits?.crew || []).map(c => ({ ...c, _kind: 'crew' as const })) - let merged: ((TmdbCombinedCreditCast | TmdbCombinedCreditCrew) & { _kind: 'cast' | 'crew' })[] = [ + type MergedCredit = + | (TmdbCombinedCreditCast & { _kind: 'cast' }) + | (TmdbCombinedCreditCrew & { _kind: 'crew' }) + let merged: MergedCredit[] = [ ...cast, ...crew, ] @@ -37,7 +40,7 @@ export default function PersonPage() { if (filter === 'Acting') { merged = merged.filter(c => c._kind === 'cast') } else { - merged = merged.filter(c => c._kind === 'crew' && c.department === filter) + merged = merged.filter((c): c is MergedCredit & { _kind: 'crew' } => c._kind === 'crew' && c.department === filter) } } @@ -260,7 +263,7 @@ export default function PersonPage() { {title}

- {c.character ? c.character : c.job} + {c.character ? c.character : (c as TmdbCombinedCreditCrew).job} {year && ( <> · diff --git a/src/pages/PlayerPage.tsx b/src/pages/PlayerPage.tsx index 96c5984..e164416 100644 --- a/src/pages/PlayerPage.tsx +++ b/src/pages/PlayerPage.tsx @@ -345,7 +345,7 @@ export default function PlayerPage() { const fromQueue = searchParams.get('resume') === 'true' if (showResumePromptPref && !fromQueue && pos > threshold) { setResumePromptOpen(true) - resumePromptShownRef.current = item.Id + resumePromptShownRef.current = item.Id ?? null } }, [item?.Id, searchParams, showResumePromptPref]) @@ -986,7 +986,8 @@ export default function PlayerPage() { if (resolvedSource?.SupportsDirectPlay) { const el = (playerRef.current as { el?: HTMLElement } | null)?.el const video = el?.querySelector('video') as HTMLVideoElement | null - const native = video.audioTracks as { length: number; [i: number]: { enabled: boolean } } | undefined + if (!video) return + const native = video.audioTracks as { length: number; [i: number]: { enabled: boolean; language?: string } } | undefined if (native && native.length > 1) { const target = audioTracks.find(t => t.Index === jfIndex) const targetLang = (target?.Language || '').toLowerCase() diff --git a/src/pages/TmdbDetailPage.tsx b/src/pages/TmdbDetailPage.tsx index b5231a6..83b852b 100644 --- a/src/pages/TmdbDetailPage.tsx +++ b/src/pages/TmdbDetailPage.tsx @@ -8,6 +8,7 @@ import { useTmdbDetailEnrichment } from '../hooks/use-tmdb-detail' import { useLibraryByTmdbId } from '../hooks/use-jellyfin' import { useFanartMovie, useFanartTv } from '../hooks/use-external' import { getTmdbImageUrl, pickTmdbLogo } from '../api/tmdb' +import type { TmdbMovie, TmdbTvShow } from '../api/tmdb' import { pickBestFanartImage } from '../api/fanart' import { mapTmdbToJf } from '../lib/tmdb-mapping' import ContentRow from '../components/ui/ContentRow' @@ -262,7 +263,7 @@ export default function TmdbDetailPage({ tmdbId, kind }: Props) { )} - {kind === 'tv' && data.number_of_seasons > 0 && ( + {kind === 'tv' && (data.number_of_seasons ?? 0) > 0 && ( <> @@ -287,7 +288,7 @@ export default function TmdbDetailPage({ tmdbId, kind }: Props) { )}

- + {matchedLocal && (