jsdw_ios/QuickLocation/Component/PhotoPicker/PhotoPickerVC.swift

122 lines
3.7 KiB
Swift

//
// PhotoPickerVC.swift
// QuickLocation
//
import UIKit
import Photos
final class PhotoPickerVC: BaseViewController {
override var isNavigationBarHidden: Bool { true }
override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent }
var onConfirm: (([UIImage]) -> Void)?
private let maxCount: Int
private let store = PhotoPickerStore()
private var rootView: PhotoPickerView!
private var selected: [PHAsset] = []
private var currentAlbumIndex = 0
private var isExporting = false
init(maxCount: Int = 9) {
self.maxCount = max(1, maxCount)
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .fullScreen
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
rootView = PhotoPickerView(store: store, maxCount: maxCount)
view = rootView
}
override func viewDidLoad() {
super.viewDidLoad()
rootView.bindAlbumStore(store)
bind()
store.requestAccess { [weak self] granted in
guard let self else { return }
guard granted else {
DLToast.show(text: "请在设置中开启相册权限")
self.dismiss(animated: true)
return
}
self.store.reloadAlbums()
self.currentAlbumIndex = 0
self.rootView.reloadAlbums(currentIndex: 0)
self.rootView.reloadGrid()
}
}
private func bind() {
rootView.onClose = { [weak self] in
self?.dismiss(animated: true)
}
rootView.onToggleAlbum = { [weak self] in
guard let self else { return }
self.rootView.isAlbumOpen.toggle()
}
rootView.onPickAlbum = { [weak self] index in
guard let self, self.store.albums.indices.contains(index) else { return }
self.currentAlbumIndex = index
self.store.loadAssets(in: self.store.albums[index])
self.rootView.reloadAlbums(currentIndex: index)
self.rootView.reloadGrid()
self.rootView.isAlbumOpen = false
}
rootView.onSelectAsset = { [weak self] index in
self?.toggleAsset(at: index)
}
rootView.onPreview = { [weak self] in
self?.showPreview()
}
rootView.onConfirm = { [weak self] in
self?.confirmSelection()
}
}
private func toggleAsset(at index: Int) {
guard store.assets.indices.contains(index) else { return }
let asset = store.assets[index]
if let idx = selected.firstIndex(where: { $0.localIdentifier == asset.localIdentifier }) {
selected.remove(at: idx)
} else {
if selected.count >= maxCount {
rootView.showLimitToast()
return
}
selected.append(asset)
}
rootView.applySelection(selected.map(\.localIdentifier))
}
private func showPreview() {
guard !selected.isEmpty else { return }
let vc = PhotoPickerPreviewVC(assets: selected, startIndex: 0, store: store)
present(vc, animated: true)
}
private func confirmSelection() {
guard !isExporting else { return }
guard !selected.isEmpty else {
dismiss(animated: true)
return
}
isExporting = true
DLToast.showLoading()
store.requestFullImages(for: selected) { [weak self] images in
DLToast.dismiss()
guard let self else { return }
self.isExporting = false
self.dismiss(animated: true) {
self.onConfirm?(images)
}
}
}
}