|
|
@@ -1,237 +0,0 @@
|
|
|
-//
|
|
|
-// LNPhotosPicker.swift
|
|
|
-// Lanu
|
|
|
-//
|
|
|
-// Created by OneeChan on 2025/11/26.
|
|
|
-//
|
|
|
-
|
|
|
-import Foundation
|
|
|
-import UIKit
|
|
|
-import Photos
|
|
|
-
|
|
|
-
|
|
|
-enum LNImagePickerType: CaseIterable {
|
|
|
- case camera
|
|
|
- case photo
|
|
|
-
|
|
|
- var title: String {
|
|
|
- switch self {
|
|
|
- case .camera: .init(key: "A00011")
|
|
|
- case .photo: .init(key: "A00012")
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-extension LNBottomSheetMenu {
|
|
|
- static func showImageSelectMenu(view: UIView? = nil,
|
|
|
- allowEdit: Bool = false,
|
|
|
- video: Bool = false,
|
|
|
- handler: @escaping LNMediaPickerHandler) {
|
|
|
- let panel = LNBottomSheetMenu()
|
|
|
- panel.update([
|
|
|
- LNImagePickerType.camera.title,
|
|
|
- LNImagePickerType.photo.title,
|
|
|
- .init(key: "A00003")
|
|
|
- ]) { index, _ in
|
|
|
- if index == 0 {
|
|
|
- LNMediaPicker.shared.takePictures(from: view, allowEdit: allowEdit, video: video, handler: handler)
|
|
|
- } else if index == 1 {
|
|
|
- LNMediaPicker.shared.selectPhoto(from: view, allowEdit: allowEdit, video: video, handler: handler)
|
|
|
- }
|
|
|
- }
|
|
|
- panel.popup()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-extension LNCommonAlertView {
|
|
|
- static func showPhotoLibraryPermissionAlert() {
|
|
|
- let alert = LNCommonAlertView()
|
|
|
- alert.titleLabel.text = .init(key: "A00287")
|
|
|
- alert.showConfirm(.init(key: "A00289")) {
|
|
|
- openAppSetting()
|
|
|
- }
|
|
|
- alert.showCancel()
|
|
|
- alert.popup()
|
|
|
- }
|
|
|
-
|
|
|
- static func showCameraPermissionAlert() {
|
|
|
- let alert = LNCommonAlertView()
|
|
|
- alert.titleLabel.text = .init(key: "A00288")
|
|
|
- alert.showConfirm(.init(key: "A00289")) {
|
|
|
- openAppSetting()
|
|
|
- }
|
|
|
- alert.showCancel()
|
|
|
- alert.popup()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-typealias LNMediaPickerHandler = (_ image: UIImage?, _ videoUrl: URL?) -> Void
|
|
|
-private class LNImagePickerController: UIImagePickerController {
|
|
|
- var handler: LNMediaPickerHandler?
|
|
|
-}
|
|
|
-
|
|
|
-class LNMediaPicker: NSObject {
|
|
|
- static let shared = LNMediaPicker()
|
|
|
-
|
|
|
- private override init() {
|
|
|
- super.init()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension LNMediaPicker {
|
|
|
- func selectPhoto(from view: UIView? = nil,
|
|
|
- allowEdit: Bool = false,
|
|
|
- video: Bool = false,
|
|
|
- handler: @escaping LNMediaPickerHandler) {
|
|
|
- // 2. 申请相册权限(iOS 10+ 需授权)
|
|
|
- PHPhotoLibrary.requestAuthorization { [weak self, weak view] status in
|
|
|
- guard let self, let view else { return }
|
|
|
- DispatchQueue.main.async { [weak self, weak view] in
|
|
|
- guard let self, let view else { return }
|
|
|
-
|
|
|
- switch status {
|
|
|
- case .authorized: // 已授权,打开相册
|
|
|
- self.openPhotoLibrary(view, allowEdit: allowEdit, video: video, handler: handler)
|
|
|
- case .denied, .restricted: // 拒绝授权或受限制
|
|
|
- LNCommonAlertView.showPhotoLibraryPermissionAlert()
|
|
|
- handler(nil, nil)
|
|
|
- break
|
|
|
- case .notDetermined: // 首次请求,系统会自动弹出授权框(无需额外处理)
|
|
|
- break
|
|
|
- case .limited:
|
|
|
- break
|
|
|
- @unknown default:
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func takePictures(from view: UIView? = nil,
|
|
|
- allowEdit: Bool = false,
|
|
|
- video: Bool = false,
|
|
|
- handler: @escaping LNMediaPickerHandler) {
|
|
|
- let status = AVCaptureDevice.authorizationStatus(for: .video)
|
|
|
-
|
|
|
- switch status {
|
|
|
- case .authorized: // 已授权
|
|
|
- self.openCamera(view, allowEdit: allowEdit, video: video, handler: handler)
|
|
|
- case .notDetermined: // 未决定,请求权限
|
|
|
- AVCaptureDevice.requestAccess(for: .video) { [weak self, weak view] granted in
|
|
|
- guard let self, let view else { return }
|
|
|
- DispatchQueue.main.async { [weak self, weak view] in
|
|
|
- guard let self, let view else { return }
|
|
|
- guard granted else {
|
|
|
- handler(nil, nil)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- self.openCamera(view, allowEdit: allowEdit, video: video, handler: handler)
|
|
|
- }
|
|
|
- }
|
|
|
- case .denied, .restricted: // 拒绝/受限
|
|
|
- LNCommonAlertView.showCameraPermissionAlert()
|
|
|
- handler(nil, nil)
|
|
|
- @unknown default:
|
|
|
- handler(nil, nil)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension LNMediaPicker {
|
|
|
- private func buildSelectPhotoPicker(
|
|
|
- allowEdit: Bool,
|
|
|
- video: Bool,
|
|
|
- handler: @escaping LNMediaPickerHandler
|
|
|
- ) -> UIImagePickerController {
|
|
|
- let vc = LNImagePickerController()
|
|
|
- vc.delegate = self
|
|
|
- vc.sourceType = .photoLibrary
|
|
|
- vc.allowsEditing = allowEdit
|
|
|
- if video {
|
|
|
- vc.mediaTypes = [UTType.image.identifier, UTType.movie.identifier]
|
|
|
- } else {
|
|
|
- vc.mediaTypes = [UTType.image.identifier]
|
|
|
- }
|
|
|
- vc.videoMaximumDuration = 60
|
|
|
- vc.handler = handler
|
|
|
-
|
|
|
- return vc
|
|
|
- }
|
|
|
-
|
|
|
- private func openPhotoLibrary(_ view: UIView?,
|
|
|
- allowEdit: Bool,
|
|
|
- video: Bool,
|
|
|
- handler: @escaping LNMediaPickerHandler) {
|
|
|
- let vc = view?.viewController ?? UIView.appKeyWindow?.rootViewController
|
|
|
- let picker = buildSelectPhotoPicker(allowEdit: allowEdit, video: video, handler: handler)
|
|
|
- vc?.present(picker, animated: true)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension LNMediaPicker {
|
|
|
- private func buildTakePicturesPicker(
|
|
|
- allowEdit: Bool,
|
|
|
- video: Bool,
|
|
|
- handler: @escaping LNMediaPickerHandler
|
|
|
- ) -> UIImagePickerController {
|
|
|
- let vc = LNImagePickerController()
|
|
|
- vc.delegate = self
|
|
|
- vc.sourceType = .camera
|
|
|
- vc.allowsEditing = allowEdit
|
|
|
- if video {
|
|
|
- vc.mediaTypes = [UTType.image.identifier, UTType.movie.identifier]
|
|
|
- } else {
|
|
|
- vc.mediaTypes = [UTType.image.identifier]
|
|
|
- }
|
|
|
- vc.videoMaximumDuration = 60
|
|
|
- vc.handler = handler
|
|
|
-
|
|
|
-
|
|
|
- return vc
|
|
|
- }
|
|
|
-
|
|
|
- private func openCamera(_ view: UIView?,
|
|
|
- allowEdit: Bool,
|
|
|
- video: Bool,
|
|
|
- handler: @escaping LNMediaPickerHandler) {
|
|
|
- let vc = view?.viewController ?? UIView.appKeyWindow?.rootViewController
|
|
|
- let picker = buildTakePicturesPicker(allowEdit: allowEdit, video: video, handler: handler)
|
|
|
- vc?.present(picker, animated: true)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension LNMediaPicker: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
|
|
|
- func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
|
|
|
- guard let vc = picker as? LNImagePickerController else { return }
|
|
|
- // 关闭相册
|
|
|
- picker.dismiss(animated: true)
|
|
|
-
|
|
|
- if let videoURL = info[.mediaURL] as? URL {
|
|
|
- vc.handler?(nil, videoURL)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 获取选择的图片(editedImage:编辑后的图片,originalImage:原始图片)
|
|
|
- let image: UIImage?
|
|
|
- if let editedImage = info[.editedImage] as? UIImage {
|
|
|
- image = editedImage
|
|
|
- } else if let originalImage = info[.originalImage] as? UIImage {
|
|
|
- image = originalImage
|
|
|
- } else {
|
|
|
- image = nil
|
|
|
- }
|
|
|
- vc.handler?(image, nil)
|
|
|
- }
|
|
|
-
|
|
|
- // 取消选择
|
|
|
- func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
|
|
- guard let vc = picker as? LNImagePickerController else { return }
|
|
|
-
|
|
|
- picker.dismiss(animated: true)
|
|
|
- vc.handler?(nil, nil)
|
|
|
- }
|
|
|
-}
|