
- 在Package.swift中更新依赖路径,确保项目结构清晰。 - 在AppSettingFeature中新增初始化方法,支持用户信息、头像和昵称的设置。 - 更新FeedListFeature和MainFeature,新增测试按钮和导航功能,提升用户交互体验。 - 在MeFeature中优化用户信息加载逻辑,增强错误处理能力。 - 新增TestView以支持测试功能,验证导航跳转的有效性。 - 更新多个视图以整合新功能,提升代码可读性与维护性。
144 lines
5.2 KiB
Swift
144 lines
5.2 KiB
Swift
import Foundation
|
||
import ComposableArchitecture
|
||
|
||
@Reducer
|
||
struct FeedListFeature {
|
||
@Dependency(\.apiService) var apiService
|
||
struct State: Equatable {
|
||
var isFirstLoad: Bool = true
|
||
var feeds: [Feed] = [] // 预留 feed 内容
|
||
var isLoading: Bool = false
|
||
var error: String? = nil
|
||
var isEditFeedPresented: Bool = false // 新增:控制 EditFeedView 弹窗
|
||
// 新增:动态内容
|
||
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 // 新增:关闭编辑页
|
||
case testButtonTapped // 新增:点击测试按钮
|
||
// 新增:动态内容相关
|
||
case fetchFeeds
|
||
case fetchFeedsResponse(TaskResult<MomentsLatestResponse>)
|
||
// 预留后续 Action
|
||
}
|
||
|
||
func reduce(into state: inout State, action: Action) -> Effect<Action> {
|
||
switch action {
|
||
case .onAppear:
|
||
guard state.isFirstLoad else { return .none }
|
||
state.isFirstLoad = false
|
||
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
|
||
// 发起 API 请求
|
||
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 let .fetchFeedsResponse(.success(response)):
|
||
state.isLoading = false
|
||
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
|
||
state.hasMore = false
|
||
return .none
|
||
case .editFeedButtonTapped:
|
||
state.isEditFeedPresented = true
|
||
return .none
|
||
case .editFeedDismissed:
|
||
state.isEditFeedPresented = false
|
||
return .none
|
||
case .testButtonTapped:
|
||
debugInfoSync("[LOG] FeedListFeature testButtonTapped")
|
||
return .none
|
||
}
|
||
}
|
||
}
|
||
|
||
// Feed 数据模型占位,后续可替换为真实模型
|
||
enum Feed: Equatable, Identifiable {
|
||
case placeholder(id: UUID = UUID())
|
||
var id: UUID {
|
||
switch self {
|
||
case .placeholder(let id): return id
|
||
}
|
||
}
|
||
} |