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.

200 lines
6.7 KiB

6 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 openPicker(mode: UIImagePickerController.CameraCaptureMode) {
  32. var presentationStyle: UIAlertController.Style = .actionSheet
  33. if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad) {
  34. presentationStyle = .alert
  35. }
  36. let alertController = UIAlertController(
  37. title: nil,
  38. message: "Gme would like to access your camera",
  39. preferredStyle: presentationStyle
  40. )
  41. let cameraAction = UIAlertAction(
  42. title: "camera_text".localized(),
  43. style: UIAlertAction.Style.default
  44. ) { (_) in
  45. self.openCamera(mode: .photo)
  46. }
  47. let galleryAction = UIAlertAction(
  48. title: "gallery_text".localized(),
  49. style: UIAlertAction.Style.default
  50. ) { (_) in
  51. self.showPhotoGallery(mode: mode)
  52. }
  53. let cancelAction = UIAlertAction(title: "cancel_text".localized(), style: .cancel, handler: nil)
  54. alertController.addAction(cameraAction)
  55. alertController.addAction(galleryAction)
  56. alertController.addAction(cancelAction)
  57. alertController.modalPresentationStyle = .overFullScreen
  58. self.presentViewController(viewController: alertController, animated: true, completion: nil)
  59. }
  60. private func presentViewController(
  61. viewController: UIViewController,
  62. animated: Bool,
  63. completion: (() -> Void)?
  64. ) {
  65. OperationQueue.main.addOperation {
  66. self.presenter?.presenting().present(viewController, animated: animated, completion: completion)
  67. }
  68. }
  69. func openCamera(mode: UIImagePickerController.CameraCaptureMode) {
  70. func openPicker() {
  71. self.imagePicker.sourceType = UIImagePickerController.SourceType.camera
  72. let mediaTypes = ["public.image"]
  73. self.imagePicker.mediaTypes = mediaTypes
  74. self.imagePicker.cameraCaptureMode = mode
  75. self.imagePicker.allowsEditing = false
  76. self.imagePicker.modalPresentationStyle = .overFullScreen
  77. self.presentViewController(viewController: self.imagePicker, animated: true, completion: nil)
  78. }
  79. PermissionHelper.isAllowedToRecordVideo { (isAllowed) in
  80. if isAllowed {
  81. openPicker()
  82. } else {
  83. self.presenter?.presenting().alert(message: "camera_access_denied_text", okAction: {
  84. UIApplication.tryURL(url: UIApplication.openSettingsURLString)
  85. })
  86. }
  87. }
  88. }
  89. private func showPhotoGallery(mode: UIImagePickerController.CameraCaptureMode) {
  90. PermissionHelper.isAllowedToShowGallary { (isAllowed) in
  91. DispatchQueue.main.async {
  92. if isAllowed {
  93. self.imagePicker.allowsEditing = false
  94. self.imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
  95. let mediaTypes = mode == .video ? ["public.image", "public.movie"] : ["public.image"]
  96. self.imagePicker.mediaTypes = mediaTypes
  97. self.imagePicker.modalPresentationStyle = .overFullScreen
  98. self.presentViewController(viewController: self.imagePicker, animated: true, completion: nil)
  99. } else {
  100. self.presenter?.presenting().alert(
  101. message: "galery_access_denied_text".localized(),
  102. okAction: {
  103. UIApplication.tryURL(url: UIApplication.openSettingsURLString)
  104. }
  105. )
  106. }
  107. }
  108. }
  109. }
  110. func resizeImage(image: UIImage, to targetSize: CGSize) -> UIImage? {
  111. // This is the rect that we've calculated out and this is what is actually used below
  112. let rect = CGRect(origin: CGPoint.zero, size: targetSize)
  113. // Actually do the resizing to the rect using the ImageContext stuff
  114. UIGraphicsBeginImageContextWithOptions(targetSize, false, 1.0)
  115. image.draw(in: rect)
  116. let newImage = UIGraphicsGetImageFromCurrentImageContext()
  117. UIGraphicsEndImageContext()
  118. return newImage
  119. }
  120. }
  121. extension MultiMediaManager: UIImagePickerControllerDelegate {
  122. func imagePickerController(
  123. _ picker: UIImagePickerController,
  124. didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
  125. ) {
  126. let info = Dictionary(uniqueKeysWithValues: info.map {key, value in (key.rawValue, value)})
  127. var completion: (() -> Void)?
  128. if let mediaType = info["UIImagePickerControllerMediaType"] as? String {
  129. if mediaType == "public.image" {
  130. if let picture = info[
  131. UIImagePickerController.InfoKey.originalImage.rawValue
  132. ] as? UIImage {
  133. if let cropsize = self.delegate?.cropSize?() {
  134. if picture.size.width < cropsize.width || picture.size.height < cropsize.height {
  135. let message = "Image size must be greater than \(cropsize.width) X \(cropsize.height)"
  136. self.delegate?.didFinishPickingWithError(error: message)
  137. } else {
  138. guard let resizedImage = self.resizeImage(image: picture, to: cropsize) else { return }
  139. completion = {
  140. self.delegate?.didFinishPickingWithImage?(image: resizedImage)
  141. }
  142. }
  143. } else {
  144. completion = {
  145. self.delegate?.didFinishPickingWithImage?(image: picture)
  146. }
  147. }
  148. }
  149. } else if mediaType == "public.movie" {
  150. // _ = info["UIImagePickerControllerMediaURL"] as! URL
  151. return
  152. }
  153. }
  154. picker.dismiss(animated: true) {
  155. completion?()
  156. }
  157. }
  158. }
  159. extension MultiMediaManager: UINavigationControllerDelegate {
  160. }
  161. struct PermissionHelper {
  162. static func isAllowedToRecordVideo(completion: @escaping (Bool) -> Void) {
  163. let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
  164. completion(status != .denied && status != .restricted)
  165. }
  166. static func isAllowedToRecordSound(completion: @escaping (Bool) -> Void) {
  167. AVAudioSession.sharedInstance().requestRecordPermission(completion)
  168. }
  169. static func isAllowedToShowGallary(completion: @escaping (Bool) -> Void) {
  170. PHPhotoLibrary.requestAuthorization { (status) in
  171. completion(status == .authorized)
  172. }
  173. }
  174. }