Files
ddys-client/DDYSClient/ViewModels/DetailViewModel.swift
2026-02-26 22:15:35 +08:00

67 lines
1.9 KiB
Swift

import Foundation
@Observable
final class DetailViewModel {
var detail: ContentDetail?
var selectedSourceIndex = 0
var selectedEpisodeIndex = 0
var isLoading = false
var error: String?
var currentSource: StreamSource? {
guard let detail, selectedSourceIndex < detail.sources.count else { return nil }
return detail.sources[selectedSourceIndex]
}
var currentEpisode: Episode? {
guard let source = currentSource,
selectedEpisodeIndex < source.episodes.count else { return nil }
return source.episodes[selectedEpisodeIndex]
}
var hasMultipleEpisodes: Bool {
guard let source = currentSource else { return false }
return source.episodes.count > 1
}
func loadDetail(path: String) async {
isLoading = true
error = nil
defer { isLoading = false }
do {
let html = try await APIClient.shared.fetchDetailPage(path: path)
let parsedDetail = try HTMLParser.parseContentDetail(html: html)
await MainActor.run {
self.detail = parsedDetail
self.selectedSourceIndex = 0
self.selectedEpisodeIndex = 0
}
} catch is CancellationError {
return
} catch let error as URLError where error.code == .cancelled {
return
} catch {
await MainActor.run { self.error = error.localizedDescription }
}
}
func selectSource(_ index: Int) {
selectedSourceIndex = index
selectedEpisodeIndex = 0
}
func selectEpisode(_ index: Int) {
selectedEpisodeIndex = index
}
func nextEpisode() -> Bool {
guard let source = currentSource else { return false }
if selectedEpisodeIndex + 1 < source.episodes.count {
selectedEpisodeIndex += 1
return true
}
return false
}
}