239 lines
7.1 KiB
Swift
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)
|
|
}
|