fix index
This commit is contained in:
parent
c9bc301604
commit
b95420ef74
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
// 更新group的label的部分
|
||||
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):
|
||||
// 通过id查找对应的group_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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user