Files
e-party-iOS/yana/Features/FeedFeature.swift
edwinQQQ 1f98ed534d feat: 更新Swift助手样式和动态视图组件
- 在swift-assistant-style.mdc中更新上下文信息,简化描述并保留关键信息。
- 在swift-swiftui-dev-rules.mdc中将alwaysApply设置为false,调整开发规则。
- 在Info.plist中移除冗余的CFBundleDisplayName和CFBundleName键,保持文件整洁。
- 在FeedFeature.swift中添加调试日志,增强API响应的可追踪性。
- 在HomeFeature.swift中新增Feed状态和相关actions,优化状态管理。
- 在FeedView.swift中直接使用store状态,提升组件性能和可读性。
- 在HomeView.swift中更新FeedView的store传递方式,确保状态一致性。
- 更新Xcode项目配置,调整代码签名和Swift版本,确保兼容性。
2025-07-14 14:50:15 +08:00

138 lines
5.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import ComposableArchitecture
@Reducer
struct FeedFeature {
@ObservableState
struct State: Equatable {
var moments: [MomentsInfo] = []
var isLoading = false
var hasMoreData = true
var error: String?
var nextDynamicId: Int = 0
//
var isInitialized = false
}
enum Action: Equatable {
case onAppear
case loadLatestMoments
case loadMoreMoments
case momentsResponse(TaskResult<MomentsLatestResponse>)
case clearError
case retryLoad
}
@Dependency(\.apiService) var apiService
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .onAppear:
//
guard !state.isInitialized else { return .none }
state.isInitialized = true
return .send(.loadLatestMoments)
case .loadLatestMoments:
//
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
//
debugInfo("📱 FeedFeature: API 响应成功")
debugInfo("📱 FeedFeature: response.code = \(response.code)")
debugInfo("📱 FeedFeature: response.message = \(response.message)")
debugInfo("📱 FeedFeature: response.data = \(response.data != nil ? "有数据" : "无数据")")
//
guard response.code == 200, let data = response.data else {
let errorMsg = response.message.isEmpty ? "获取动态失败" : response.message
state.error = errorMsg
debugError("❌ FeedFeature: API 响应失败 - code: \(response.code), message: \(errorMsg)")
return .none
}
//
debugInfo("📱 FeedFeature: data.dynamicList.count = \(data.dynamicList.count)")
debugInfo("📱 FeedFeature: data.nextDynamicId = \(data.nextDynamicId)")
//
let isRefresh = state.nextDynamicId == 0
debugInfo("📱 FeedFeature: isRefresh = \(isRefresh)")
if isRefresh {
//
state.moments = data.dynamicList
debugInfo(" FeedFeature: 刷新数据moments.count = \(state.moments.count)")
} else {
//
let oldCount = state.moments.count
state.moments.append(contentsOf: data.dynamicList)
debugInfo(" FeedFeature: 加载更多moments.count: \(oldCount) -> \(state.moments.count)")
}
//
state.nextDynamicId = data.nextDynamicId
state.hasMoreData = !data.dynamicList.isEmpty
debugInfo("📱 FeedFeature: 更新完成 - nextDynamicId: \(state.nextDynamicId), hasMoreData: \(state.hasMoreData)")
return .none
case let .momentsResponse(.failure(error)):
state.isLoading = false
state.error = error.localizedDescription
debugError("❌ FeedFeature: API 请求失败 - \(error.localizedDescription)")
return .none
case .clearError:
state.error = nil
return .none
case .retryLoad:
//
if state.moments.isEmpty {
return .send(.loadLatestMoments)
} else {
return .send(.loadMoreMoments)
}
}
}
}
}