Files
e-party-iOS/yana/Features/FeedFeature.swift
edwinQQQ ba991598be feat: 更新CreateFeed功能及相关视图组件
- 在CreateFeedFeature中新增isPresented依赖,确保在适当的上下文中执行视图关闭操作。
- 在FeedFeature中优化状态管理,简化CreateFeedView的呈现逻辑。
- 新增FeedListFeature和MainFeature,整合FeedListView和底部导航功能,提升用户体验。
- 更新HomeView和SplashView以集成MainView,确保应用结构一致性。
- 在多个视图中调整状态管理和导航逻辑,增强可维护性和用户体验。
2025-07-21 19:10:31 +08:00

112 lines
4.3 KiB
Swift

import Foundation
import ComposableArchitecture
@Reducer
struct FeedFeature {
@ObservableState
struct State: Equatable {
var moments: [MomentsInfo] = []
var isLoading = false
var isRefreshing = false
var hasMoreData = true
var error: String?
var nextDynamicId: Int = 0
// CreateFeedView
var createFeedState = CreateFeedFeature.State()
}
enum Action: Equatable {
case onAppear
case refresh
case loadLatestMoments
case loadMoreMoments
case momentsResponse(TaskResult<MomentsLatestResponse>)
case clearError
case retryLoad
// CreateFeedView Action
case createFeedCompleted
case createFeedDismissed
// CreateFeedFeature action
case createFeed(CreateFeedFeature.Action)
}
@Dependency(\.apiService) var apiService
var body: some ReducerOf<Self> {
Scope(state: \.createFeedState, action: \.createFeed) {
CreateFeedFeature()
}
Reduce { state, action in
switch action {
case .onAppear:
guard state.moments.isEmpty && !state.isLoading else { return .none }
return .send(.loadLatestMoments)
case .refresh:
guard !state.isRefreshing else { return .none }
state.isRefreshing = true
state.error = nil
let request = LatestDynamicsRequest(dynamicId: "", pageSize: 20, types: [.text, .picture])
return .run { send in
await send(.momentsResponse(TaskResult { try await apiService.request(request) }))
}
case .loadLatestMoments:
guard !state.isLoading else { return .none }
state.isLoading = true
state.error = nil
let request = LatestDynamicsRequest(dynamicId: "", pageSize: 20, types: [.text, .picture])
return .run { send in
await send(.momentsResponse(TaskResult { try await apiService.request(request) }))
}
case .loadMoreMoments:
guard !state.isLoading && state.hasMoreData else { return .none }
state.isLoading = true
state.error = nil
let request = LatestDynamicsRequest(dynamicId: state.nextDynamicId == 0 ? "" : String(state.nextDynamicId), pageSize: 20, types: [.text, .picture])
return .run { send in
await send(.momentsResponse(TaskResult { try await apiService.request(request) }))
}
case let .momentsResponse(.success(response)):
state.isLoading = false
state.isRefreshing = false
guard response.code == 200, let data = response.data else {
let errorMsg = response.message.isEmpty ? "获取动态失败" : response.message
state.error = errorMsg
return .none
}
let isRefresh = state.nextDynamicId == 0 || state.isRefreshing
if isRefresh {
state.moments = data.dynamicList
} else {
state.moments.append(contentsOf: data.dynamicList)
}
state.nextDynamicId = data.nextDynamicId
state.hasMoreData = !data.dynamicList.isEmpty
return .none
case let .momentsResponse(.failure(error)):
state.isLoading = false
state.isRefreshing = false
state.error = error.localizedDescription
return .none
case .clearError:
state.error = nil
return .none
case .retryLoad:
if state.moments.isEmpty {
return .send(.loadLatestMoments)
} else {
return .send(.loadMoreMoments)
}
case .createFeedCompleted:
return .send(.refresh)
case .createFeedDismissed:
return .none
case .createFeed(.dismissView):
return .send(.createFeedDismissed)
case .createFeed:
return .none
}
}
}
}