Files
e-party-iOS/yana/Features/MeFeature.swift
edwinQQQ 25fec8a2e6 feat: 增强FeedListFeature和MeFeature的首次加载逻辑
- 在FeedListFeature和MeFeature中新增isFirstLoad状态,确保仅在首次加载时请求数据。
- 更新MainView以简化视图切换逻辑,使用isHidden修饰符控制视图显示。
- 新增View+isHidden扩展,提供视图隐藏功能,提升代码可读性和复用性。
2025-07-24 10:20:12 +08:00

113 lines
4.1 KiB
Swift

import Foundation
import ComposableArchitecture
@Reducer
struct MeFeature {
@Dependency(\.apiService) var apiService
struct State: Equatable {
var isFirstLoad: Bool = true
var userInfo: UserInfo?
var isLoadingUserInfo: Bool = false
var userInfoError: String?
var moments: [MomentsInfo] = []
var isLoadingMoments: Bool = false
var momentsError: String?
var hasMore: Bool = true
var isLoadingMore: Bool = false
var isRefreshing: Bool = false
var page: Int = 1
var pageSize: Int = 20
var uid: Int = 0
}
enum Action: Equatable {
case onAppear
case refresh
case loadMore
case userInfoResponse(Result<UserInfo, APIError>)
case momentsResponse(Result<MyMomentsResponse, APIError>)
//
case settingButtonTapped
}
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(.refresh)
case .refresh:
guard state.uid > 0 else { return .none }
state.isRefreshing = true
state.page = 1
state.hasMore = true
return .merge(
fetchUserInfo(uid: state.uid),
fetchMoments(uid: state.uid, page: 1, pageSize: state.pageSize)
)
case .loadMore:
guard state.uid > 0, state.hasMore, !state.isLoadingMore else { return .none }
state.isLoadingMore = true
return fetchMoments(uid: state.uid, page: state.page + 1, pageSize: state.pageSize)
case let .userInfoResponse(result):
state.isLoadingUserInfo = false
state.isRefreshing = false
switch result {
case let .success(userInfo):
state.userInfo = userInfo
state.userInfoError = nil
case let .failure(error):
state.userInfoError = error.localizedDescription
}
return .none
case let .momentsResponse(result):
state.isLoadingMoments = false
state.isLoadingMore = false
state.isRefreshing = false
switch result {
case let .success(resp):
let newMoments = resp.data ?? []
if state.page == 1 {
state.moments = newMoments
} else {
state.moments += newMoments
}
state.hasMore = newMoments.count == state.pageSize
if state.hasMore { state.page += 1 }
state.momentsError = nil
case let .failure(error):
state.momentsError = error.localizedDescription
}
return .none
case .settingButtonTapped:
// MainFeature
return .none
}
}
private func fetchUserInfo(uid: Int) -> Effect<Action> {
.run { send in
do {
if let userInfo = try await UserInfoManager.fetchUserInfoFromServer(uid: String(uid), apiService: apiService) {
await send(.userInfoResponse(.success(userInfo)))
} else {
await send(.userInfoResponse(.failure(.noData)))
}
} catch {
await send(.userInfoResponse(.failure(error as? APIError ?? .unknown(error.localizedDescription))))
}
}
}
private func fetchMoments(uid: Int, page: Int, pageSize: Int) -> Effect<Action> {
.run { send in
do {
let req = GetMyDynamicRequest(fromUid: uid, uid: uid, page: page, pageSize: pageSize)
let resp = try await apiService.request(req)
await send(.momentsResponse(.success(resp)))
} catch {
await send(.momentsResponse(.failure(error as? APIError ?? .unknown(error.localizedDescription))))
}
}
}
}