import Foundation import ComposableArchitecture import SwiftUI import PhotosUI // 修正:导入PhotosUI @Reducer struct EditFeedFeature { @ObservableState struct State: Equatable { var content: String = "" var isLoading: Bool = false var errorMessage: String? = nil var shouldDismiss: Bool = false var selectedImages: [PhotosPickerItem] = [] var processedImages: [UIImage] = [] var canAddMoreImages: Bool { processedImages.count < 9 } var canPublish: Bool { !content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !isLoading } // 手动实现Equatable,selectedImages只比较数量(PhotosPickerItem不支持Equatable) static func == (lhs: State, rhs: State) -> Bool { lhs.content == rhs.content && lhs.isLoading == rhs.isLoading && lhs.errorMessage == rhs.errorMessage && lhs.shouldDismiss == rhs.shouldDismiss && lhs.processedImages == rhs.processedImages && lhs.selectedImages.count == rhs.selectedImages.count } } enum Action { case contentChanged(String) case publishButtonTapped case publishResponse(Result) case clearError case dismissView case clearDismissFlag // 新增图片相关Action case photosPickerItemsChanged([PhotosPickerItem]) case processPhotosPickerItems([PhotosPickerItem]) case updateProcessedImages([UIImage]) case removeImage(Int) } @Dependency(\.apiService) var apiService @Dependency(\.dismiss) var dismiss @Dependency(\.isPresented) var isPresented var body: some ReducerOf { Reduce { state, action in switch action { case .contentChanged(let newContent): state.content = newContent return .none case .publishButtonTapped: guard state.canPublish else { state.errorMessage = "请输入内容" return .none } state.isLoading = true state.errorMessage = nil return .run { [content = state.content] send in let userId = await UserInfoManager.getCurrentUserId() ?? "" let request = await PublishFeedRequest.make( content: content.trimmingCharacters(in: .whitespacesAndNewlines), uid: userId, type: "0" ) do { let response = try await apiService.request(request) await send(.publishResponse(.success(response))) } catch { await send(.publishResponse(.failure(error))) } } case .publishResponse(.success(let response)): state.isLoading = false if response.code == 200 { return .send(.dismissView) } else { state.errorMessage = response.message.isEmpty ? "发布失败" : response.message return .none } case .publishResponse(.failure(let error)): state.isLoading = false state.errorMessage = error.localizedDescription return .none case .clearError: state.errorMessage = nil return .none case .dismissView: state.shouldDismiss = true return .none case .clearDismissFlag: state.shouldDismiss = false return .none case .photosPickerItemsChanged(let items): state.selectedImages = items return .run { send in await send(.processPhotosPickerItems(items)) } case .processPhotosPickerItems(let items): let currentImages = state.processedImages return .run { send in var newImages = currentImages for item in items { guard let data = try? await item.loadTransferable(type: Data.self), let image = UIImage(data: data) else { continue } if newImages.count < 9 { newImages.append(image) } } await MainActor.run { send(.updateProcessedImages(newImages)) } } case .updateProcessedImages(let images): state.processedImages = images return .none case .removeImage(let index): guard index < state.processedImages.count else { return .none } state.processedImages.remove(at: index) if index < state.selectedImages.count { state.selectedImages.remove(at: index) } return .none } } } }