fix index view

This commit is contained in:
anlicheng 2025-04-13 17:16:52 +08:00
parent cfe9dd5c2e
commit f1790156f9
2 changed files with 62 additions and 36 deletions

View File

@ -28,9 +28,6 @@ struct IndexMainView: View {
@State private var footerRefreshing: Bool = false @State private var footerRefreshing: Bool = false
@State private var noMore: Bool = false @State private var noMore: Bool = false
// globalminY
@State private var footerOffset: Int = 0
var body: some View { var body: some View {
VStack(alignment: .center) { VStack(alignment: .center) {
@ -74,8 +71,9 @@ struct IndexMainView: View {
.contentShape(Rectangle()) .contentShape(Rectangle())
} }
} }
ProgressView() ProgressView()
.id(UUID())
.background(GeometryReader { geometry in .background(GeometryReader { geometry in
let minY = geometry.frame(in: .global).minY let minY = geometry.frame(in: .global).minY
Color.clear.preference(key: FooterOffsetPreferenceKey.self, value: Int(minY)) Color.clear.preference(key: FooterOffsetPreferenceKey.self, value: Int(minY))
@ -83,25 +81,12 @@ struct IndexMainView: View {
} }
.frame(width: 370) .frame(width: 370)
.coordinateSpace(name: "indexScrollView") .coordinateSpace(name: "indexScrollView")
.onScrollPhaseChange { oldPhase, newPhase in
guard !footerRefreshing && !showDateNavPopover else { .onPreferenceChange(FooterOffsetPreferenceKey.self) { offset in
return // state
DispatchQueue.main.async {
indexModel.loadMorePublisher.send((userId, offset))
} }
print("scroll old: \(oldPhase), new: \(newPhase), footer-offset: \(footerOffset)")
//
let height = Int(UIScreen.main.bounds.height)
let distance = height - footerOffset
if newPhase == .idle && (distance >= 0 && distance < 50) {
self.footerRefreshing = true
Task {
await self.indexModel.loadMoreUpdateDramas(userId: self.userId, mode: .next)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
self.footerRefreshing = false
}
}
}
} }
.refreshable { .refreshable {
guard !self.showDateNavPopover && !self.headerRefreshing else { guard !self.showDateNavPopover && !self.headerRefreshing else {
@ -110,8 +95,12 @@ struct IndexMainView: View {
// //
self.headerRefreshing = true self.headerRefreshing = true
await self.indexModel.loadMoreUpdateDramas(userId: self.userId, mode: .prev) Task {
self.headerRefreshing = false await self.indexModel.loadMoreUpdateDramasTask(userId: self.userId, mode: .prev)
DispatchQueue.main.async {
self.headerRefreshing = false
}
}
} }
.overlay(alignment: .topTrailing) { .overlay(alignment: .topTrailing) {
HStack(alignment: .center) { HStack(alignment: .center) {
@ -155,13 +144,9 @@ struct IndexMainView: View {
.onPreferenceChange(DramaGroupElementPreferenceKey.self) { frames in .onPreferenceChange(DramaGroupElementPreferenceKey.self) { frames in
let visibleFrames = frames.filter { $0.value >= 0} let visibleFrames = frames.filter { $0.value >= 0}
if let minFrame = visibleFrames.min(by: { $0.value <= $1.value}) { if let minFrame = visibleFrames.min(by: { $0.value <= $1.value}) {
indexModel.setFixedDrameGroup(groupId: minFrame.key) DispatchQueue.main.async {
} indexModel.setFixedDrameGroup(groupId: minFrame.key)
} }
.onPreferenceChange(FooterOffsetPreferenceKey.self) { offset in
// state
DispatchQueue.main.async {
self.footerOffset = offset
} }
} }
@ -268,10 +253,7 @@ extension IndexMainView {
static var defaultValue: Int = 0 static var defaultValue: Int = 0
static func reduce(value: inout Int, nextValue: () -> Int) { static func reduce(value: inout Int, nextValue: () -> Int) {
let newValue = nextValue() value += nextValue()
if newValue > 0 && abs(newValue - value) >= 50 {
value = newValue
}
} }
} }

View File

@ -7,6 +7,8 @@
import Foundation import Foundation
import Observation import Observation
import Combine
import SwiftUI
@Observable @Observable
final class IndexModel { final class IndexModel {
@ -60,12 +62,45 @@ final class IndexModel {
@ObservationIgnored @ObservationIgnored
private var isLoaded = false private var isLoaded = false
//
@ObservationIgnored
private var isMoreLoading = false
// debug // debug
@ObservationIgnored @ObservationIgnored
private var debug: Bool = false private var debug: Bool = false
//
@ObservationIgnored
private var updateInterval = Date()
// footeroffset
@ObservationIgnored
var loadMorePublisher = PassthroughSubject<(String, Int), Never>()
@ObservationIgnored
private var bag = Set<AnyCancellable>()
init() { init() {
self.selectedDate = "" self.selectedDate = ""
self.loadMorePublisher
.debounce(for: 0.2, scheduler: RunLoop.main)
.dropFirst()
.sink { (userId, offset) in
//
let timeDistance = self.updateInterval.distance(to: Date())
//
let height = Int(UIScreen.main.bounds.height)
let distance = height - offset
if timeDistance > 1.0 && (distance >= 0 && distance < 50) {
Task {
await self.loadMoreUpdateDramasTask(userId: userId, mode: .next)
}
self.updateInterval = Date()
}
}
.store(in: &bag)
} }
func loadData(userId: String) async { func loadData(userId: String) async {
@ -94,7 +129,11 @@ final class IndexModel {
} }
} }
func loadMoreUpdateDramas(userId: String, mode: API.LoadMode) async { func loadMoreUpdateDramasTask(userId: String, mode: API.LoadMode) async {
guard !self.isMoreLoading else {
return
}
// id // id
let dramaIds = self.getDramaIds(self.updateDramaGroups) let dramaIds = self.getDramaIds(self.updateDramaGroups)
print("current ids: \(dramaIds)") print("current ids: \(dramaIds)")
@ -103,6 +142,7 @@ final class IndexModel {
case .prev: case .prev:
// id // id
if let firstId = dramaIds.first { if let firstId = dramaIds.first {
self.isMoreLoading = true
let response = await API.loadMoreUpdateDramas(userId: userId, mode: mode, id: firstId, as: [UpdateDramaGroup].self) let response = await API.loadMoreUpdateDramas(userId: userId, mode: mode, id: firstId, as: [UpdateDramaGroup].self)
if case let .result(groups) = response { if case let .result(groups) = response {
if groups.count > 0 { if groups.count > 0 {
@ -114,9 +154,11 @@ final class IndexModel {
displayDramaGroups(self.updateDramaGroups, label: "after") displayDramaGroups(self.updateDramaGroups, label: "after")
} }
} }
self.isMoreLoading = false
} }
case .next: case .next:
if let lastId = dramaIds.last { if let lastId = dramaIds.last {
self.isMoreLoading = true
let response = await API.loadMoreUpdateDramas(userId: userId, mode: mode, id: lastId, as: [UpdateDramaGroup].self) let response = await API.loadMoreUpdateDramas(userId: userId, mode: mode, id: lastId, as: [UpdateDramaGroup].self)
if case let .result(groups) = response { if case let .result(groups) = response {
if groups.count > 0 { if groups.count > 0 {
@ -128,6 +170,8 @@ final class IndexModel {
displayDramaGroups(self.updateDramaGroups, label: "after") displayDramaGroups(self.updateDramaGroups, label: "after")
} }
} }
self.isMoreLoading = false
} }
} }
} }