fix index

This commit is contained in:
anlicheng 2025-06-19 17:31:45 +08:00
parent c9bc301604
commit b95420ef74
2 changed files with 122 additions and 69 deletions

View File

@ -14,7 +14,7 @@ struct IndexMainView: View {
@AppStorage("userId") private var userId: String = Utils.defaultUserId() @AppStorage("userId") private var userId: String = Utils.defaultUserId()
@State var indexModel = IndexModel() @State var indexModel = IndexModel()
@State private var scrollID: Int? = 0 @State private var scrollID: IndexModel.ScrollTarget? = nil
// //
@State var showPrompt: Bool = false @State var showPrompt: Bool = false
@ -32,6 +32,8 @@ struct IndexMainView: View {
@State private var scrollOffset: CGFloat = 0 @State private var scrollOffset: CGFloat = 0
@State private var showFloatGroupLabel: Bool = false @State private var showFloatGroupLabel: Bool = false
@State private var scrollHeight: Double = 0
var body: some View { var body: some View {
VStack(alignment: .center) { VStack(alignment: .center) {
@ -77,22 +79,23 @@ struct IndexMainView: View {
// //
LazyVStack(alignment: .center, spacing: 10) { LazyVStack(alignment: .center, spacing: 10) {
ForEach(Array(indexModel.dramaGroupElements.enumerated()), id: \.offset) { idx, item in ForEach(indexModel.dramaGroupElements, id: \.id) { item in
switch item { switch item.data {
case .label(let groupId, let groupName, _): case .label(let groupId, let groupName, _):
DramaGroupLabelView(group_name: groupName) { DramaGroupLabelView(group_name: groupName) {
selectGroupId = groupId selectGroupId = groupId
indexModel.selectedDate = groupId indexModel.selectedDate = groupId
showDateNavPopover = true showDateNavPopover = true
} }
.id(item.id)
case .item(let groupId, let item, _): case .item(let groupId, let item, _):
DramaGroupItemView(groupId: groupId, item: item) DramaGroupItemView(groupId: groupId, item: item)
.id(idx) .id(item.id)
} }
} }
} }
.scrollTargetLayout() .scrollTargetLayout()
ProgressView() ProgressView()
} }
.frame(width: 370) .frame(width: 370)
@ -110,9 +113,10 @@ struct IndexMainView: View {
// //
self.headerRefreshing = true self.headerRefreshing = true
Task { Task {
await self.indexModel.loadMoreUpdateDramasTask(userId: self.userId, mode: .prev) await self.indexModel.loadPrevUpdateDramasTask(userId: self.userId) { anchorGroupElement in
DispatchQueue.main.async { DispatchQueue.main.async {
self.headerRefreshing = false self.headerRefreshing = false
}
} }
} }
} }

View File

@ -50,11 +50,22 @@ final class IndexModel {
let follow_num: Int let follow_num: Int
} }
enum GroupElement { // target
// groupId, groupName enum ScrollTarget: Hashable {
case label(String, String, Double) case group(id: String)
// groupId, UpdateDramaGroup.Item case item(id: Int)
case item(String, UpdateDramaGroup.Item, Double) }
struct GroupElement {
enum Data {
// groupId, groupName
case label(String, String, Double)
// groupId, UpdateDramaGroup.Item
case item(String, UpdateDramaGroup.Item, Double)
}
let id: ScrollTarget
let data: Data
} }
var selectedDate: String var selectedDate: String
@ -65,6 +76,10 @@ final class IndexModel {
// , 便 // , 便
var dramaGroupElements: [GroupElement] = [] var dramaGroupElements: [GroupElement] = []
// group
@ObservationIgnored
var dramaGroupMap: [Int:String] = [:]
var follow_num: String = "0" var follow_num: String = "0"
// group_name // group_name
@ -87,7 +102,7 @@ final class IndexModel {
// scrollID // scrollID
@ObservationIgnored @ObservationIgnored
var scrollIDPublisher = PassthroughSubject<(String, Int), Never>() var scrollIDPublisher = PassthroughSubject<(String, ScrollTarget), Never>()
@ObservationIgnored @ObservationIgnored
private var cancel: AnyCancellable? private var cancel: AnyCancellable?
@ -100,23 +115,42 @@ final class IndexModel {
self.selectedDate = "" self.selectedDate = ""
self.cancel = self.scrollIDPublisher self.cancel = self.scrollIDPublisher
.sink { userId, scrollID in .sink { userId, scrollTarget in
// grouplabel switch scrollTarget {
switch self.dramaGroupElements[scrollID] { case .group(id: let groupId):
case .label(_, _, _):
()
case .item(let groupId, _, _):
DispatchQueue.main.async { DispatchQueue.main.async {
self.setFixedDrameGroup(groupId: groupId) self.setFixedDrameGroup(groupId: groupId)
} }
case .item(id: let id):
// idgroup_id
if let groupId = self.dramaGroupMap[id] {
DispatchQueue.main.async {
self.setFixedDrameGroup(groupId: groupId)
}
}
}
// 6
let isCloseBottom = self.dramaGroupElements.suffix(6).contains { elem in
switch elem.data {
case .label(let groupId, _, _):
if case .group(id: let groupId0) = scrollTarget {
return groupId == groupId0
}
case .item(_, let item, _):
if case .item(id: let id) = scrollTarget {
return item.id == id
}
}
return false
} }
// //
let timeDistance = self.updateInterval.distance(to: Date()) let timeDistance = self.updateInterval.distance(to: Date())
// //
if timeDistance > 1.0 && self.dramaGroupElements.count - scrollID < 6 { if timeDistance > 1.0 && isCloseBottom {
Task { Task {
await self.loadMoreUpdateDramasTask(userId: userId, mode: .next) await self.loadMoreUpdateDramasTask(userId: userId)
} }
self.updateInterval = Date() self.updateInterval = Date()
} }
@ -130,7 +164,7 @@ final class IndexModel {
let (_, labelHeight, elementHeight) = self.elementHeight let (_, labelHeight, elementHeight) = self.elementHeight
self.dramaGroupElements.forEach { element in self.dramaGroupElements.forEach { element in
switch element { switch element.data {
case .label(let groupId, _, let y): case .label(let groupId, _, let y):
if offset + y >= -labelHeight && offset + y <= 0 { if offset + y >= -labelHeight && offset + y <= 0 {
rangeGroupId = groupId rangeGroupId = groupId
@ -186,13 +220,16 @@ final class IndexModel {
} }
func setFixedDrameGroup(groupId: String) { func setFixedDrameGroup(groupId: String) {
if let newFixedDramaGroup = self.updateDramaGroups.first(where: {$0.group_id == groupId}), if let newFixedDramaGroup = self.updateDramaGroups.first(where: {$0.group_id == groupId}) {
newFixedDramaGroup.group_id != self.fixedDramaGroup?.group_id { if let oldGroupId = self.fixedDramaGroup?.group_id, oldGroupId != newFixedDramaGroup.group_id {
self.fixedDramaGroup = newFixedDramaGroup self.fixedDramaGroup = newFixedDramaGroup
} else {
self.fixedDramaGroup = newFixedDramaGroup
}
} }
} }
func loadMoreUpdateDramasTask(userId: String, mode: API.LoadMode) async { func loadMoreUpdateDramasTask(userId: String) async {
guard !self.isMoreLoading else { guard !self.isMoreLoading else {
return return
} }
@ -200,51 +237,59 @@ final class IndexModel {
// id // id
let dramaIds = self.getDramaIds(self.updateDramaGroups) let dramaIds = self.getDramaIds(self.updateDramaGroups)
//print("current ids: \(dramaIds)") //print("current ids: \(dramaIds)")
if let lastId = dramaIds.last {
self.isMoreLoading = true
let response = await API.loadMoreUpdateDramas(userId: userId, mode: .next, id: lastId, as: [UpdateDramaGroup].self)
if case let .result(groups) = response {
if groups.count > 0 {
preloadGroupImages(groups: groups)
displayDramaGroups(self.updateDramaGroups, label: "before")
await MainActor.run {
self.updateDramaGroups = appendMergeDramaGroups(groups: self.updateDramaGroups, mergeGroups: groups)
self.fixedDramaGroup = self.updateDramaGroups.first
self.dramaGroupElements = transformUpdateDramaGroups(groups: self.updateDramaGroups)
}
displayDramaGroups(self.updateDramaGroups, label: "after")
}
}
self.isMoreLoading = false
}
}
func loadPrevUpdateDramasTask(userId: String, callback: (GroupElement?) -> Void) async {
guard !self.isMoreLoading else {
return
}
switch mode { let anchorGroupElement = dramaGroupElements.first
case .prev:
// id // id
if let firstId = dramaIds.first { let dramaIds = self.getDramaIds(self.updateDramaGroups)
self.isMoreLoading = true // id
let response = await API.loadMoreUpdateDramas(userId: userId, mode: mode, id: firstId, as: [UpdateDramaGroup].self) if let firstId = dramaIds.first {
if case let .result(groups) = response { self.isMoreLoading = true
if groups.count > 0 { let response = await API.loadMoreUpdateDramas(userId: userId, mode: .prev, id: firstId, as: [UpdateDramaGroup].self)
preloadGroupImages(groups: groups) if case let .result(groups) = response {
if groups.count > 0 {
preloadGroupImages(groups: groups)
displayDramaGroups(self.updateDramaGroups, label: "before")
await MainActor.run {
self.updateDramaGroups = preappendMergeDramaGroups(groups: self.updateDramaGroups, mergeGroups: groups)
self.fixedDramaGroup = self.updateDramaGroups.first
displayDramaGroups(self.updateDramaGroups, label: "before") self.dramaGroupElements = transformUpdateDramaGroups(groups: self.updateDramaGroups)
await MainActor.run { //
self.updateDramaGroups = preappendMergeDramaGroups(groups: self.updateDramaGroups, mergeGroups: groups) callback(anchorGroupElement)
self.fixedDramaGroup = self.updateDramaGroups.first
self.dramaGroupElements = transformUpdateDramaGroups(groups: self.updateDramaGroups)
}
displayDramaGroups(self.updateDramaGroups, label: "after")
} }
displayDramaGroups(self.updateDramaGroups, label: "after")
} }
self.isMoreLoading = false
}
case .next:
if let lastId = dramaIds.last {
self.isMoreLoading = true
let response = await API.loadMoreUpdateDramas(userId: userId, mode: mode, id: lastId, as: [UpdateDramaGroup].self)
if case let .result(groups) = response {
if groups.count > 0 {
preloadGroupImages(groups: groups)
displayDramaGroups(self.updateDramaGroups, label: "before")
await MainActor.run {
self.updateDramaGroups = appendMergeDramaGroups(groups: self.updateDramaGroups, mergeGroups: groups)
self.fixedDramaGroup = self.updateDramaGroups.first
self.dramaGroupElements = transformUpdateDramaGroups(groups: self.updateDramaGroups)
}
displayDramaGroups(self.updateDramaGroups, label: "after")
}
}
self.isMoreLoading = false
} }
self.isMoreLoading = false
} }
} }
@ -253,13 +298,17 @@ final class IndexModel {
var offset: Double = 0 var offset: Double = 0
let (spacing, labelHeight, elementHeight) = self.elementHeight let (spacing, labelHeight, elementHeight) = self.elementHeight
self.dramaGroupMap.removeAll()
var groupElements: [GroupElement] = [] var groupElements: [GroupElement] = []
for group in groups { for group in groups {
groupElements.append(.label(group.group_id, group.group_name, offset)) groupElements.append(GroupElement(id: .group(id: group.group_id), data: .label(group.group_id, group.group_name, offset)))
offset += labelHeight + spacing offset += labelHeight + spacing
for item in group.items { for item in group.items {
groupElements.append(.item(group.group_id, item, offset)) groupElements.append(GroupElement(id: .item(id: item.id), data: .item(group.group_id, item, offset)))
offset += elementHeight + spacing offset += elementHeight + spacing
self.dramaGroupMap[item.id] = group.group_id
} }
} }