// // TVShowView.swift // // Copyright 2026 Brendan Szymanski // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // SPDX-License-Identifier: GPL-3.0-or-later // import Adwaita import Foundation import LuminateCore struct TVShowView: View { var item: Components.Schemas.BaseItemDto var client: JellyfinClient var userId: String @State private var seasons: [Components.Schemas.BaseItemDto] = [] @State private var selectedSeasonId: String? @State private var backdropData: Data? var view: Body { ScrollView { VStack { if let data = backdropData { Picture() .data(data) .frame(minHeight: 300) .frame(maxHeight: 300) .hexpand(true) } HStack { PosterCell(item: item, client: client) .frame(minWidth: 200) .frame(maxWidth: 200) VStack { Text(item.name ?? "") .title1() .halign(.start) if let status = item.status { Text(status) .caption() .halign(.start) } if let overview = item.overview { Text(overview) .body() .halign(.start) .padding(10, .vertical) } } .hexpand(true) } .padding() if !seasons.isEmpty { VStack { Text("Season") .caption() .halign(.start) HStack { ForEach(seasons) { season in Button(season.name ?? "?") { selectedSeasonId = season.id } .suggested(selectedSeasonId == season.id) .flat(selectedSeasonId != season.id) } } } .padding(10, .horizontal) } if let seasonId = selectedSeasonId { EpisodeList( seriesId: item.id ?? "", seasonId: seasonId, client: client, userId: userId ) } } } .onAppear { loadSeasons() loadBackdrop() } } private func loadBackdrop() { guard let tag = item.backdropImageTag, let itemId = item.id else { return } Task { guard let url = await client.imageURL( itemId: itemId, imageType: .backdrop, tag: tag, maxWidth: 1920 ) else { return } let service = ImageService() backdropData = try? await service.loadImage(url: url) } } private func loadSeasons() { Task { let result = try? await client.getSeasons(seriesId: item.id ?? "", userId: userId) await MainActor.run { seasons = result?.items ?? [] selectedSeasonId = seasons.first?.id } } } }