feat: 实现动态内容的分页加载与刷新功能
- 在FeedListFeature中新增分页相关状态管理,支持上拉加载更多和下拉刷新功能,提升用户体验。 - 在FeedListView中实现上拉加载更多的触发逻辑和加载指示器,优化动态内容展示。
This commit is contained in:
@@ -13,12 +13,17 @@ struct FeedListFeature {
|
||||
var moments: [MomentsInfo] = []
|
||||
// 新增:只加载一次标志
|
||||
var isLoaded: Bool = false
|
||||
// 分页相关
|
||||
var currentPage: Int = 1
|
||||
var hasMore: Bool = true
|
||||
var isLoadingMore: Bool = false
|
||||
}
|
||||
|
||||
enum Action: Equatable {
|
||||
case onAppear
|
||||
case reload
|
||||
case loadMore
|
||||
case loadMoreResponse(TaskResult<MomentsLatestResponse>)
|
||||
case editFeedButtonTapped // 新增:点击 add 按钮
|
||||
case editFeedDismissed // 新增:关闭编辑页
|
||||
// 新增:动态内容相关
|
||||
@@ -34,6 +39,57 @@ struct FeedListFeature {
|
||||
guard !state.isLoaded else { return .none }
|
||||
state.isLoaded = true
|
||||
return .send(.fetchFeeds)
|
||||
case .reload:
|
||||
// 下拉刷新,重置状态并请求第一页
|
||||
state.isLoading = true
|
||||
state.error = nil
|
||||
state.currentPage = 1
|
||||
state.hasMore = true
|
||||
state.isLoaded = true
|
||||
return .run { [apiService] send in
|
||||
await send(.fetchFeedsResponse(TaskResult {
|
||||
let request = LatestDynamicsRequest(dynamicId: "", pageSize: 20, types: [.text, .picture])
|
||||
return try await apiService.request(request)
|
||||
}))
|
||||
}
|
||||
case .loadMore:
|
||||
// 上拉加载更多
|
||||
guard state.hasMore, !state.isLoadingMore, !state.isLoading else { return .none }
|
||||
state.isLoadingMore = true
|
||||
let lastDynamicId: String = {
|
||||
if let last = state.moments.last {
|
||||
return String(last.dynamicId)
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}()
|
||||
return .run { [apiService] send in
|
||||
await send(.loadMoreResponse(TaskResult {
|
||||
let request = LatestDynamicsRequest(dynamicId: lastDynamicId, pageSize: 20, types: [.text, .picture])
|
||||
return try await apiService.request(request)
|
||||
}))
|
||||
}
|
||||
case let .loadMoreResponse(.success(response)):
|
||||
state.isLoadingMore = false
|
||||
if let list = response.data?.dynamicList {
|
||||
if list.isEmpty {
|
||||
state.hasMore = false
|
||||
} else {
|
||||
state.moments.append(contentsOf: list)
|
||||
state.currentPage += 1
|
||||
state.hasMore = (list.count >= 20)
|
||||
}
|
||||
state.error = nil
|
||||
} else {
|
||||
state.hasMore = false
|
||||
state.error = response.message
|
||||
}
|
||||
return .none
|
||||
case let .loadMoreResponse(.failure(error)):
|
||||
state.isLoadingMore = false
|
||||
state.hasMore = false
|
||||
state.error = error.localizedDescription
|
||||
return .none
|
||||
case .fetchFeeds:
|
||||
state.isLoading = true
|
||||
state.error = nil
|
||||
@@ -49,21 +105,19 @@ struct FeedListFeature {
|
||||
if let list = response.data?.dynamicList {
|
||||
state.moments = list
|
||||
state.error = nil
|
||||
state.currentPage = 1
|
||||
state.hasMore = (list.count >= 20)
|
||||
} else {
|
||||
state.moments = []
|
||||
state.error = response.message
|
||||
state.hasMore = false
|
||||
}
|
||||
return .none
|
||||
case let .fetchFeedsResponse(.failure(error)):
|
||||
state.isLoading = false
|
||||
state.moments = []
|
||||
state.error = error.localizedDescription
|
||||
return .none
|
||||
case .reload:
|
||||
// 预留刷新逻辑
|
||||
return .none
|
||||
case .loadMore:
|
||||
// 预留分页加载逻辑
|
||||
state.hasMore = false
|
||||
return .none
|
||||
case .editFeedButtonTapped:
|
||||
state.isEditFeedPresented = true
|
||||
|
@@ -69,12 +69,29 @@ struct FeedListView: View {
|
||||
LazyVStack(spacing: 16) {
|
||||
ForEach(Array(viewStore.moments.enumerated()), id: \ .element.dynamicId) { index, moment in
|
||||
OptimizedDynamicCardView(moment: moment, allMoments: viewStore.moments, currentIndex: index)
|
||||
// 上拉加载更多触发点
|
||||
if index == viewStore.moments.count - 1, viewStore.hasMore, !viewStore.isLoadingMore {
|
||||
Color.clear
|
||||
.frame(height: 1)
|
||||
.onAppear {
|
||||
viewStore.send(.loadMore)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 加载更多指示器
|
||||
if viewStore.isLoadingMore {
|
||||
ProgressView()
|
||||
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.top, 10)
|
||||
.padding(.bottom, 20)
|
||||
}
|
||||
.refreshable {
|
||||
viewStore.send(.reload)
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
|
Reference in New Issue
Block a user