dimensionhub/dimensionhub/Views/IndexView.swift
2025-02-19 22:23:07 +08:00

239 lines
7.1 KiB
Swift

//
// ContentView.swift
// dimensionhub
//
// Created by on 2025/2/18.
//
import SwiftUI
import SwiftData
struct IndexView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
struct DramaItem: Codable {
struct Episode: Codable {
let id: Int32
let name: String
let thumb: String
let numName: String
enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
case thumb = "thumb"
case numName = "num_name"
}
}
let title: String
let episodes: [Episode]
}
struct UpdateDramaItem: Codable {
let name: String
let thumb: String
let desc: String
let datetime: String
}
enum UpdateDramaShowItem {
case lable(String)
case item(UpdateDramaItem)
}
struct IndexResponse: Codable {
let updateDramas: [UpdateDramaItem]
let dramas: [DramaItem]
}
@State var dramas: [DramaItem] = []
@State var showUpdateDramas: [UpdateDramaShowItem] = []
@State var isLoading: Bool = false
var body: some View {
VStack(alignment: .center) {
HStack(alignment: .center) {
Spacer()
Text("亚次元")
.padding(.top, 5)
.padding(.bottom, 5)
Spacer()
}
.background(Color.red)
HStack(alignment: .center) {
Spacer()
Text("番剧补完计划")
.font(.system(size: 24))
}
ForEach(dramas.indices, id: \.self) { id in
DramaCellView(dramaItem: dramas[id])
}
//
ScrollView(.vertical, showsIndicators: false) {
LazyVStack {
ForEach(showUpdateDramas.indices, id: \.self) { index in
UpdateDramaCellView(showItem: showUpdateDramas[index])
}
}
.background(GeometryReader { geometry in
Color.clear.onChange(of: geometry.frame(in: .global).minY) {_, offset in
let contentHeight = geometry.size.height
let scrollViewHeight = UIScreen.main.bounds.height
//
if offset + contentHeight > scrollViewHeight - 50 {
print("call me here11")
Task {
await self.loadMoreUpdateDramas()
}
}
}
})
}
}
.task {
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 = Self.yes(updateDramas: result.updateDramas)
}
}
}
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() {
withAnimation {
let newItem = Item(timestamp: Date())
modelContext.insert(newItem)
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
for index in offsets {
modelContext.delete(items[index])
}
}
}
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 {
//
struct DramaCellView: View {
let dramaItem: DramaItem
var body: some View {
VStack(alignment: .leading) {
Text(dramaItem.title)
.font(.system(size: 20))
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .center, spacing: 10) {
ForEach(dramaItem.episodes, id: \.id) { item in
VStack(alignment: .center) {
AsyncImage(url: URL(string: item.thumb)) { image in
image.resizable()
} placeholder: {
ProgressView()
}
.frame(width: 80, height: 80)
.overlay {
Text(item.numName)
}
Text(item.name)
.lineLimit(1)
}
.frame(width: 100, height: 120)
}
}
.border(Color.red)
}
}
}
}
}
extension IndexView {
struct UpdateDramaCellView: View {
let showItem: UpdateDramaShowItem
var body: some View {
switch showItem {
case .lable(let name):
Text(name)
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)
}
}
}
}
#Preview {
IndexView()
.modelContainer(for: Item.self, inMemory: true)
}