
- 在Info.plist中新增相机使用说明,确保应用能够访问相机功能。 - 在AppSettingFeature中新增showImagePicker状态和setShowImagePicker动作,支持图片选择弹窗的显示。 - 在AppSettingView中整合图片选择与预览功能,优化用户体验。 - 更新MainView以简化导航逻辑,提升代码可读性与维护性。 - 在ImagePickerWithPreview组件中实现相机和相册选择功能,增强交互性。
140 lines
5.2 KiB
Swift
140 lines
5.2 KiB
Swift
import Foundation
|
|
import ComposableArchitecture
|
|
import SwiftUI
|
|
import PhotosUI
|
|
|
|
public enum ImagePickerSelectionMode: Equatable {
|
|
case single
|
|
case multiple(max: Int)
|
|
}
|
|
|
|
public struct ImagePickerWithPreviewState: Equatable {
|
|
public var selectionMode: ImagePickerSelectionMode = .single
|
|
public var showActionSheet: Bool = false
|
|
public var showPhotoPicker: Bool = false
|
|
public var showCamera: Bool = false
|
|
public var showPreview: Bool = false
|
|
public var isLoading: Bool = false
|
|
public var errorMessage: String? = nil
|
|
public var selectedPhotoItems: [PhotosPickerItem] = []
|
|
public var selectedImages: [UIImage] = []
|
|
public var cameraImage: UIImage? = nil
|
|
public var previewIndex: Int = 0 // 多选时预览当前索引
|
|
|
|
public init(selectionMode: ImagePickerSelectionMode = .single) {
|
|
self.selectionMode = selectionMode
|
|
}
|
|
}
|
|
|
|
public enum ImagePickerWithPreviewAction: Equatable {
|
|
case showActionSheet(Bool)
|
|
case selectSource(ImageSource)
|
|
case photoPickerItemsChanged([PhotosPickerItem])
|
|
case cameraImagePicked(UIImage?)
|
|
case previewConfirm
|
|
case previewCancel
|
|
case uploadStart
|
|
case uploadSuccess
|
|
case uploadFailure(String)
|
|
case setLoading(Bool)
|
|
case setError(String?)
|
|
case setPreviewIndex(Int)
|
|
case setShowCamera(Bool)
|
|
case setShowPhotoPicker(Bool)
|
|
case reset
|
|
}
|
|
|
|
public enum ImageSource: Equatable {
|
|
case camera
|
|
case photoLibrary
|
|
}
|
|
|
|
public struct ImagePickerWithPreviewReducer: Reducer {
|
|
public init() {}
|
|
public struct State: Equatable {
|
|
public var inner: ImagePickerWithPreviewState
|
|
public init(inner: ImagePickerWithPreviewState) { self.inner = inner }
|
|
}
|
|
public enum Action: Equatable {
|
|
case inner(ImagePickerWithPreviewAction)
|
|
}
|
|
public var body: some ReducerOf<Self> {
|
|
Reduce { state, action in
|
|
switch action {
|
|
case .inner(let action):
|
|
switch action {
|
|
case .showActionSheet(let show):
|
|
state.inner.showActionSheet = show
|
|
return .none
|
|
case .selectSource(let source):
|
|
state.inner.showActionSheet = false
|
|
switch source {
|
|
case .camera:
|
|
state.inner.showCamera = true
|
|
state.inner.showPhotoPicker = false
|
|
case .photoLibrary:
|
|
state.inner.showPhotoPicker = true
|
|
state.inner.showCamera = false
|
|
}
|
|
return .none
|
|
case .photoPickerItemsChanged(let items):
|
|
state.inner.selectedPhotoItems = items
|
|
// 选完后进入预览
|
|
state.inner.showPreview = !items.isEmpty
|
|
state.inner.previewIndex = 0
|
|
return .none
|
|
case .cameraImagePicked(let image):
|
|
state.inner.cameraImage = image
|
|
state.inner.selectedImages = image.map { [$0] } ?? []
|
|
state.inner.showPreview = image != nil
|
|
state.inner.previewIndex = 0
|
|
return .none
|
|
case .previewConfirm:
|
|
state.inner.showPreview = false
|
|
state.inner.isLoading = true
|
|
state.inner.errorMessage = nil
|
|
return .none // 上传逻辑由外部Effect注入
|
|
case .previewCancel:
|
|
state.inner.showPreview = false
|
|
state.inner.selectedPhotoItems = []
|
|
state.inner.selectedImages = []
|
|
state.inner.cameraImage = nil
|
|
return .none
|
|
case .uploadStart:
|
|
state.inner.isLoading = true
|
|
state.inner.errorMessage = nil
|
|
return .none
|
|
case .uploadSuccess:
|
|
state.inner.isLoading = false
|
|
state.inner.selectedPhotoItems = []
|
|
state.inner.selectedImages = []
|
|
state.inner.cameraImage = nil
|
|
return .none
|
|
case .uploadFailure(let msg):
|
|
state.inner.isLoading = false
|
|
state.inner.errorMessage = msg
|
|
return .none
|
|
case .setLoading(let loading):
|
|
state.inner.isLoading = loading
|
|
return .none
|
|
case .setError(let msg):
|
|
state.inner.errorMessage = msg
|
|
return .none
|
|
case .setPreviewIndex(let idx):
|
|
state.inner.previewIndex = idx
|
|
return .none
|
|
case .setShowCamera(let show):
|
|
state.inner.showCamera = show
|
|
return .none
|
|
case .setShowPhotoPicker(let show):
|
|
state.inner.showPhotoPicker = show
|
|
return .none
|
|
case .reset:
|
|
let mode = state.inner.selectionMode
|
|
state.inner = ImagePickerWithPreviewState(selectionMode: mode)
|
|
return .none
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |