Files
e-party-iOS/yana/Views/Components/ImagePickerWithPreview/ImagePickerWithPreviewReducer.swift
edwinQQQ ac0d622c97 feat: 更新Info.plist和AppSettingView以支持相机和图片选择功能
- 在Info.plist中新增相机使用说明,确保应用能够访问相机功能。
- 在AppSettingFeature中新增showImagePicker状态和setShowImagePicker动作,支持图片选择弹窗的显示。
- 在AppSettingView中整合图片选择与预览功能,优化用户体验。
- 更新MainView以简化导航逻辑,提升代码可读性与维护性。
- 在ImagePickerWithPreview组件中实现相机和相册选择功能,增强交互性。
2025-07-25 18:47:11 +08:00

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
}
}
}
}
}