Files
ddys-client/DDYSClient/ViewModels/DetailViewModel.swift
YANGJIANKUAN 1da412e637 fix: 修复详情页空白和海报图片错误
- DetailViewModel 添加 @MainActor 确保状态更新在主线程
- DetailView 消除空白初始状态,ProgressView 作为默认兜底
- 取消时保留加载状态避免页面闪回空白
- 使用 .task(id:) 确保切换条目时任务重新触发
- 海报优先从 JSON-LD image 字段获取,HTML fallback 改用正确选择器

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:33:22 +08:00

66 lines
1.9 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
@Observable @MainActor
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
do {
let html = try await APIClient.shared.fetchDetailPage(path: path)
let parsedDetail = try HTMLParser.parseContentDetail(html: html)
self.detail = parsedDetail
self.selectedSourceIndex = 0
self.selectedEpisodeIndex = 0
} catch is CancellationError {
// loading
return
} catch let error as URLError where error.code == .cancelled {
return
} catch {
self.error = error.localizedDescription
}
isLoading = false
}
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
}
}