You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
8.5 KiB

6 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
5 years ago
  1. //
  2. // MultiMediaManager.swift
  3. //
  4. //
  5. // Created by shishir sapkota
  6. //
  7. import UIKit
  8. import Foundation
  9. import AVFoundation
  10. import Photos
  11. //import RSKImageCropper
  12. @objc protocol MultiMediaManagerDelegate {
  13. @objc optional func cropSize() -> CGSize
  14. @objc optional func didFinishPickingWithImage(image: UIImage)
  15. func didFinishPickingWithError(error: String)
  16. @objc optional func didFinishPickingVideo(url: URL)
  17. }
  18. @objc protocol MultimediaPresenterProtocol {
  19. func presenting() -> UIViewController
  20. }
  21. class MultiMediaManager: NSObject {
  22. private let imagePicker = UIImagePickerController()
  23. private weak var presenter: MultimediaPresenterProtocol?
  24. weak var delegate: MultiMediaManagerDelegate?
  25. init(presenter: MultimediaPresenterProtocol) {
  26. self.presenter = presenter
  27. super.init()
  28. imagePicker.delegate = self
  29. imagePicker.allowsEditing = true
  30. }
  31. func openCameraPicker() {
  32. self.openCamera(mode: .photo)
  33. }
  34. func openPicker(mode: UIImagePickerController.CameraCaptureMode) {
  35. var presentationStyle: UIAlertController.Style = .actionSheet
  36. if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad) {
  37. presentationStyle = .alert
  38. }
  39. let alertController = UIAlertController(
  40. title: nil,
  41. message: "JME would like to access your camera",
  42. preferredStyle: presentationStyle
  43. )
  44. let cameraAction = UIAlertAction(
  45. title: "camera_text".localized(),
  46. style: UIAlertAction.Style.default
  47. ) { (_) in
  48. self.openCamera(mode: .photo)
  49. }
  50. let galleryAction = UIAlertAction(
  51. title: "gallery_text".localized(),
  52. style: UIAlertAction.Style.default
  53. ) { (_) in
  54. self.showPhotoGallery(mode: mode)
  55. }
  56. let cancelAction = UIAlertAction(title: "cancel_text".localized(), style: .cancel, handler: nil)
  57. alertController.addAction(cameraAction)
  58. // if DevicePlatform.isSimulator {
  59. alertController.addAction(galleryAction)
  60. // }
  61. alertController.addAction(cancelAction)
  62. alertController.modalPresentationStyle = .overFullScreen
  63. self.presentViewController(viewController: alertController, animated: true, completion: nil)
  64. }
  65. private func presentViewController(
  66. viewController: UIViewController,
  67. animated: Bool,
  68. completion: (() -> Void)?
  69. ) {
  70. OperationQueue.main.addOperation {
  71. self.presenter?.presenting().present(viewController, animated: animated, completion: completion)
  72. }
  73. }
  74. func openCamera(mode: UIImagePickerController.CameraCaptureMode) {
  75. func openPicker() {
  76. self.imagePicker.sourceType = UIImagePickerController.SourceType.camera
  77. let mediaTypes = ["public.image"]
  78. self.imagePicker.mediaTypes = mediaTypes
  79. self.imagePicker.cameraCaptureMode = mode
  80. self.imagePicker.allowsEditing = false
  81. self.imagePicker.modalPresentationStyle = .overFullScreen
  82. // let overlay = createOverlay(view: imagePicker.cameraOverlayView!)
  83. // imagePicker.view.addSubview(overlay)
  84. self.presentViewController(viewController: self.imagePicker, animated: true, completion: nil)
  85. }
  86. PermissionHelper.isAllowedToRecordVideo { (isAllowed) in
  87. if isAllowed {
  88. openPicker()
  89. } else {
  90. self.presenter?.presenting().alert(message: "camera_access_denied_text", okAction: {
  91. UIApplication.tryURL(url: UIApplication.openSettingsURLString)
  92. })
  93. }
  94. }
  95. }
  96. func createOverlay(view: UIView) -> UIView {
  97. let overlayView = UIView()
  98. overlayView.frame = CGRect(x: 100, y: 100, width: view.frame.width, height: view.frame.height - 200)
  99. overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.7)
  100. let path = CGMutablePath()
  101. let w = UIScreen.main.bounds.width
  102. let h = UIScreen.main.bounds.height
  103. path.addRoundedRect(in: CGRect(x: 30, y: 200, width: overlayView.frame.width-60, height: overlayView.frame.width - 150), cornerWidth: 5, cornerHeight: 5)
  104. path.closeSubpath()
  105. let shape = CAShapeLayer()
  106. shape.path = path
  107. shape.lineWidth = 5.0
  108. shape.strokeColor = UIColor.white.cgColor
  109. shape.fillColor = UIColor.white.cgColor
  110. overlayView.layer.addSublayer(shape)
  111. path.addRect(CGRect(origin: .zero, size: overlayView.frame.size))
  112. let maskLayer = CAShapeLayer()
  113. maskLayer.backgroundColor = UIColor.black.cgColor
  114. maskLayer.path = path
  115. maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
  116. overlayView.layer.mask = maskLayer
  117. overlayView.clipsToBounds = true
  118. return overlayView
  119. }
  120. private func showPhotoGallery(mode: UIImagePickerController.CameraCaptureMode) {
  121. PermissionHelper.isAllowedToShowGallary { (isAllowed) in
  122. DispatchQueue.main.async {
  123. if isAllowed {
  124. self.imagePicker.allowsEditing = false
  125. self.imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
  126. let mediaTypes = mode == .video ? ["public.image", "public.movie"] : ["public.image"]
  127. self.imagePicker.mediaTypes = mediaTypes
  128. self.imagePicker.modalPresentationStyle = .overFullScreen
  129. self.presentViewController(viewController: self.imagePicker, animated: true, completion: nil)
  130. } else {
  131. self.presenter?.presenting().alert(
  132. message: "galery_access_denied_text".localized(),
  133. okAction: {
  134. UIApplication.tryURL(url: UIApplication.openSettingsURLString)
  135. }
  136. )
  137. }
  138. }
  139. }
  140. }
  141. func resizeImage(image: UIImage, to targetSize: CGSize) -> UIImage? {
  142. // This is the rect that we've calculated out and this is what is actually used below
  143. let rect = CGRect(origin: CGPoint.zero, size: targetSize)
  144. // Actually do the resizing to the rect using the ImageContext stuff
  145. UIGraphicsBeginImageContextWithOptions(targetSize, false, 1.0)
  146. image.draw(in: rect)
  147. let newImage = UIGraphicsGetImageFromCurrentImageContext()
  148. UIGraphicsEndImageContext()
  149. return newImage
  150. }
  151. }
  152. extension MultiMediaManager: UIImagePickerControllerDelegate {
  153. func imagePickerController(
  154. _ picker: UIImagePickerController,
  155. didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
  156. ) {
  157. let info = Dictionary(uniqueKeysWithValues: info.map {key, value in (key.rawValue, value)})
  158. var completion: (() -> Void)?
  159. if let mediaType = info["UIImagePickerControllerMediaType"] as? String {
  160. if mediaType == "public.image" {
  161. if let picture = info[
  162. UIImagePickerController.InfoKey.originalImage.rawValue
  163. ] as? UIImage {
  164. if let cropsize = self.delegate?.cropSize?() {
  165. if picture.size.width < cropsize.width || picture.size.height < cropsize.height {
  166. let message = "Image size must be greater than \(cropsize.width) X \(cropsize.height)"
  167. self.delegate?.didFinishPickingWithError(error: message)
  168. } else {
  169. guard let resizedImage = self.resizeImage(image: picture, to: cropsize) else { return }
  170. completion = {
  171. self.delegate?.didFinishPickingWithImage?(image: resizedImage)
  172. }
  173. }
  174. } else {
  175. completion = {
  176. self.delegate?.didFinishPickingWithImage?(image: picture)
  177. }
  178. }
  179. }
  180. } else if mediaType == "public.movie" {
  181. // _ = info["UIImagePickerControllerMediaURL"] as! URL
  182. return
  183. }
  184. }
  185. picker.dismiss(animated: true) {
  186. completion?()
  187. }
  188. }
  189. }
  190. extension MultiMediaManager: UINavigationControllerDelegate {
  191. }
  192. struct PermissionHelper {
  193. static func isAllowedToRecordVideo(completion: @escaping (Bool) -> Void) {
  194. let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
  195. completion(status != .denied && status != .restricted)
  196. }
  197. static func isAllowedToRecordSound(completion: @escaping (Bool) -> Void) {
  198. AVAudioSession.sharedInstance().requestRecordPermission(completion)
  199. }
  200. static func isAllowedToShowGallary(completion: @escaping (Bool) -> Void) {
  201. PHPhotoLibrary.requestAuthorization { (status) in
  202. completion(status == .authorized)
  203. }
  204. }
  205. }
  206. struct DevicePlatform {
  207. static var isSimulator: Bool {
  208. #if targetEnvironment(simulator)
  209. // We're on the simulator
  210. return true
  211. #else
  212. // We're on a device
  213. return false
  214. #endif
  215. }
  216. }