This commit is contained in:
anlicheng 2025-02-20 23:09:16 +08:00
parent d2aeacd8b8
commit 6b477486c2
2 changed files with 112 additions and 59 deletions

View File

@ -5,7 +5,10 @@
// Created by on 2025/2/20. // Created by on 2025/2/20.
// //
// //
//
struct DateModel: Codable { struct DateModel: Codable {
struct Month: Codable { struct Month: Codable {
let name: String let name: String

View File

@ -7,10 +7,10 @@
import SwiftUI import SwiftUI
import SwiftData import SwiftData
import Observation
struct IndexView: View { @Observable
@Environment(\.modelContext) private var modelContext final class IndexModel {
@Query private var items: [Item]
struct DramaItem: Codable { struct DramaItem: Codable {
struct Episode: Codable { struct Episode: Codable {
@ -27,29 +27,88 @@ struct IndexView: View {
} }
} }
let id: Int32
let title: String let title: String
let episodes: [Episode] let episodes: [Episode]
} }
struct UpdateDramaItem: Codable { struct UpdateDramaItem: Codable {
let id: Int
let name: String let name: String
let thumb: String let thumb: String
let desc: String let desc: String
let datetime: String let datetime: String
} }
enum UpdateDramaShowItem {
case lable(String)
case item(UpdateDramaItem)
}
struct IndexResponse: Codable { struct IndexResponse: Codable {
let updateDramas: [UpdateDramaItem] let updateDramas: [UpdateDramaItem]
let dramas: [DramaItem] let dramas: [DramaItem]
} }
@State var dramas: [DramaItem] = [] struct UpdateDramaShowItem: Identifiable {
@State var showUpdateDramas: [UpdateDramaShowItem] = [] enum Element {
case lable(String)
case item(UpdateDramaItem)
}
let id = UUID()
let element: Element
init(element: Element) {
self.element = element
}
}
var dramas: [DramaItem]
var showUpdateDramas: [UpdateDramaShowItem]
init() {
self.dramas = []
self.showUpdateDramas = []
}
@MainActor
func loadData() async {
let response = await API.getIndexData(as: IndexResponse.self)
switch response {
case .error(let code, let message):
print(code)
print(message)
case .result(let result):
print(result)
self.dramas = result.dramas
self.showUpdateDramas = groupUpdateDramas(updateDramas: result.updateDramas)
}
}
@MainActor
func loadMoreUpdateDramas() async {
let response = await API.loadMoreUpdateDramas(as: [UpdateDramaItem].self)
if case let .result(items) = response {
let showItems = groupUpdateDramas(updateDramas: items)
self.showUpdateDramas.append(contentsOf: showItems)
}
}
private func groupUpdateDramas(updateDramas: [UpdateDramaItem]) -> [UpdateDramaShowItem] {
let groups = Dictionary(grouping: updateDramas) {$0.datetime}
var updateItems: [UpdateDramaShowItem] = []
groups.forEach { (key, items) in
updateItems.append(.init(element: .lable(key)))
items.forEach { item in
updateItems.append(.init(element: .item(item)))
}
}
return updateItems
}
}
struct IndexView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
@State var indexModel = IndexModel()
@State var isLoading: Bool = false @State var isLoading: Bool = false
// //
@ -72,16 +131,41 @@ struct IndexView: View {
.font(.system(size: 24)) .font(.system(size: 24))
} }
ForEach(dramas.indices, id: \.self) { id in ForEach(indexModel.dramas, id: \.id) { drama in
DramaCellView(dramaItem: dramas[id]) DramaCellView(dramaItem: drama)
} }
// //
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {
LazyVStack { LazyVStack {
ForEach(showUpdateDramas.indices, id: \.self) { index in ForEach(indexModel.showUpdateDramas, id: \.id) { drama in
UpdateDramaCellView(showItem: showUpdateDramas[index], showDateNavPopover: $showDateNavPopover) switch drama.element {
case .lable(let name):
Text(name)
.onTapGesture {
showDateNavPopover = true
}
case .item(let item):
VStack(alignment: .center) {
AsyncImage(url: URL(string: item.thumb)) { image in
image.resizable()
} placeholder: {
ProgressView()
}
.frame(width: 80, height: 80)
.overlay {
VStack(alignment: .leading) {
Text(item.name)
.lineLimit(1)
Text(item.desc)
.lineLimit(1)
}
}
}
.frame(width: 100, height: 120)
}
} }
} }
@ -95,7 +179,9 @@ struct IndexView: View {
if screenBounds.height - frame.minY > 50 && !isLoading { if screenBounds.height - frame.minY > 50 && !isLoading {
Task { Task {
await self.loadMoreUpdateDramas() self.isLoading = true
await self.indexModel.loadMoreUpdateDramas()
self.isLoading = false
} }
} }
} }
@ -110,35 +196,9 @@ struct IndexView: View {
} }
} }
.task { .task {
let response = await API.getIndexData(as: IndexResponse.self) await self.indexModel.loadData()
switch response {
case .error(let code, let message):
print(code)
print(message)
case .result(let result):
print(result)
self.dramas = result.dramas
self.showUpdateDramas = Self.yes(updateDramas: result.updateDramas)
} }
} }
}
@MainActor
private func loadMoreUpdateDramas() async {
guard !self.isLoading else {
return
}
self.isLoading = true
let response = await API.loadMoreUpdateDramas(as: [UpdateDramaItem].self)
if case let .result(items) = response {
let showItems = Self.yes(updateDramas: items)
self.showUpdateDramas.append(contentsOf: showItems)
}
self.isLoading = false
}
private func addItem() { private func addItem() {
withAnimation { withAnimation {
@ -155,24 +215,13 @@ struct IndexView: View {
} }
} }
private static func yes(updateDramas: [UpdateDramaItem]) -> [UpdateDramaShowItem] {
let groups = Dictionary(grouping: updateDramas) {$0.datetime}
var updateItems: [UpdateDramaShowItem] = []
groups.forEach { (key, items) in
updateItems.append(.lable(key))
items.forEach { item in
updateItems.append(.item(item))
}
}
return updateItems
}
} }
extension IndexView { extension IndexView {
// //
struct DramaCellView: View { struct DramaCellView: View {
let dramaItem: DramaItem let dramaItem: IndexModel.DramaItem
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
@ -207,14 +256,15 @@ extension IndexView {
} }
/*
extension IndexView { extension IndexView {
struct UpdateDramaCellView: View { struct UpdateDramaCellView: View {
let showItem: UpdateDramaShowItem let showItem: IndexModel.UpdateDramaShowItem
@Binding var showDateNavPopover: Bool @Binding var showDateNavPopover: Bool
var body: some View { var body: some View {
switch showItem { switch showItem.element {
case .lable(let name): case .lable(let name):
Text(name) Text(name)
.onTapGesture { .onTapGesture {
@ -243,7 +293,7 @@ extension IndexView {
} }
} }
} }*/
#Preview { #Preview {
IndexView() IndexView()