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()
|
@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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
// 更新group的label的部分
|
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):
|
||||||
|
// 通过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())
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user