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

View File

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