init: init proj

This commit is contained in:
2026-02-26 22:15:35 +08:00
commit 7ef5348f65
43 changed files with 3085 additions and 0 deletions

View 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()
}
}