init: init proj
This commit is contained in:
98
DDYSClient/ViewModels/BrowseViewModel.swift
Normal file
98
DDYSClient/ViewModels/BrowseViewModel.swift
Normal file
@@ -0,0 +1,98 @@
|
||||
import Foundation
|
||||
|
||||
@Observable
|
||||
final class BrowseViewModel {
|
||||
var items: [ContentItem] = []
|
||||
var category: ContentCategory = .movie
|
||||
var filter = FilterState()
|
||||
var currentPage = 1
|
||||
var totalPages = 1
|
||||
var isLoading = false
|
||||
var isLoadingMore = false
|
||||
var error: String?
|
||||
|
||||
private var cacheKey: String {
|
||||
"\(category.rawValue)_\(filter.sort)_\(filter.genre)_\(filter.region)_\(filter.year)"
|
||||
}
|
||||
|
||||
var hasData: Bool {
|
||||
!items.isEmpty
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func loadContentIfNeeded() async {
|
||||
if hasData && !ContentCache.shared.isExpired(key: cacheKey) {
|
||||
return
|
||||
}
|
||||
await loadContent()
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func loadContent() async {
|
||||
isLoading = true
|
||||
error = nil
|
||||
currentPage = 1
|
||||
totalPages = 1
|
||||
items = []
|
||||
|
||||
do {
|
||||
let html = try await APIClient.shared.fetchCategoryPage(
|
||||
category: category,
|
||||
page: 1,
|
||||
filter: filter
|
||||
)
|
||||
let newItems = try HTMLParser.parseContentList(html: html, defaultCategory: category)
|
||||
let pagination = try HTMLParser.parsePagination(html: html)
|
||||
|
||||
self.items = newItems
|
||||
self.currentPage = pagination.current
|
||||
self.totalPages = pagination.total
|
||||
|
||||
ContentCache.shared.markFresh(key: cacheKey)
|
||||
} catch is CancellationError {
|
||||
} catch let error as URLError where error.code == .cancelled {
|
||||
} catch {
|
||||
self.error = error.localizedDescription
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func loadMore() async {
|
||||
guard !isLoadingMore, !isLoading, currentPage < totalPages else { return }
|
||||
isLoadingMore = true
|
||||
|
||||
let nextPage = currentPage + 1
|
||||
do {
|
||||
let html = try await APIClient.shared.fetchCategoryPage(
|
||||
category: category,
|
||||
page: nextPage,
|
||||
filter: filter
|
||||
)
|
||||
let newItems = try HTMLParser.parseContentList(html: html, defaultCategory: category)
|
||||
let pagination = try HTMLParser.parsePagination(html: html)
|
||||
|
||||
self.items.append(contentsOf: newItems)
|
||||
self.currentPage = pagination.current
|
||||
self.totalPages = pagination.total
|
||||
} catch is CancellationError {
|
||||
} catch let error as URLError where error.code == .cancelled {
|
||||
} catch {
|
||||
// 加载更多失败不显示全局错误,允许重试
|
||||
}
|
||||
|
||||
isLoadingMore = false
|
||||
}
|
||||
|
||||
func changeCategory(_ newCategory: ContentCategory) async {
|
||||
category = newCategory
|
||||
filter = FilterState()
|
||||
await loadContentIfNeeded()
|
||||
}
|
||||
|
||||
func applyFilter(_ newFilter: FilterState) async {
|
||||
filter = newFilter
|
||||
await loadContent()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user