|  |  |  | // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import UIKit | 
					
						
							|  |  |  | import Photos | 
					
						
							|  |  |  | import PhotosUI | 
					
						
							|  |  |  | import SessionUIKit | 
					
						
							|  |  |  | import SessionUtilitiesKit | 
					
						
							|  |  |  | import SessionMessagingKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public enum Permissions { | 
					
						
							|  |  |  |     @discardableResult public static func requestCameraPermissionIfNeeded( | 
					
						
							|  |  |  |         presentingViewController: UIViewController? = nil, | 
					
						
							|  |  |  |         onAuthorized: (() -> Void)? = nil | 
					
						
							|  |  |  |     ) -> Bool { | 
					
						
							|  |  |  |         switch AVCaptureDevice.authorizationStatus(for: .video) { | 
					
						
							|  |  |  |             case .authorized: | 
					
						
							|  |  |  |                 onAuthorized?() | 
					
						
							|  |  |  |                 return true | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             case .denied, .restricted: | 
					
						
							|  |  |  |                 guard let presentingViewController: UIViewController = (presentingViewController ?? CurrentAppContext().frontmostViewController()) else { return false } | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 let confirmationModal: ConfirmationModal = ConfirmationModal( | 
					
						
							|  |  |  |                     info: ConfirmationModal.Info( | 
					
						
							|  |  |  |                         title: "Session", | 
					
						
							|  |  |  |                         body: .text( | 
					
						
							|  |  |  |                             String( | 
					
						
							|  |  |  |                                 format: "modal_permission_explanation".localized(), | 
					
						
							|  |  |  |                                 "modal_permission_camera".localized() | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                         ), | 
					
						
							|  |  |  |                         confirmTitle: "modal_permission_settings_title".localized(), | 
					
						
							|  |  |  |                         dismissOnConfirm: false | 
					
						
							|  |  |  |                     ) { [weak presentingViewController] _ in | 
					
						
							|  |  |  |                         presentingViewController?.dismiss(animated: true, completion: { | 
					
						
							|  |  |  |                             UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!) | 
					
						
							|  |  |  |                         }) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 presentingViewController.present(confirmationModal, animated: true, completion: nil) | 
					
						
							|  |  |  |                 return false | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |             case .notDetermined: | 
					
						
							|  |  |  |                 AVCaptureDevice.requestAccess(for: .video, completionHandler: { _ in | 
					
						
							|  |  |  |                     onAuthorized?() | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |                 return false | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |             default: return false | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public static func requestMicrophonePermissionIfNeeded( | 
					
						
							|  |  |  |         presentingViewController: UIViewController? = nil, | 
					
						
							|  |  |  |         onNotGranted: (() -> Void)? = nil | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         switch AVAudioSession.sharedInstance().recordPermission { | 
					
						
							|  |  |  |             case .granted: break | 
					
						
							|  |  |  |             case .denied: | 
					
						
							|  |  |  |                 guard let presentingViewController: UIViewController = (presentingViewController ?? CurrentAppContext().frontmostViewController()) else { return } | 
					
						
							|  |  |  |                 onNotGranted?() | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 let confirmationModal: ConfirmationModal = ConfirmationModal( | 
					
						
							|  |  |  |                     info: ConfirmationModal.Info( | 
					
						
							|  |  |  |                         title: "Session", | 
					
						
							|  |  |  |                         body: .text( | 
					
						
							|  |  |  |                             String( | 
					
						
							|  |  |  |                                 format: "modal_permission_explanation".localized(), | 
					
						
							|  |  |  |                                 "modal_permission_microphone".localized() | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                         ), | 
					
						
							|  |  |  |                         confirmTitle: "modal_permission_settings_title".localized(), | 
					
						
							|  |  |  |                         dismissOnConfirm: false, | 
					
						
							|  |  |  |                         onConfirm: { [weak presentingViewController] _ in | 
					
						
							|  |  |  |                             presentingViewController?.dismiss(animated: true, completion: { | 
					
						
							|  |  |  |                                 UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!) | 
					
						
							|  |  |  |                             }) | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                         afterClosed: { onNotGranted?() } | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 presentingViewController.present(confirmationModal, animated: true, completion: nil) | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |             case .undetermined: | 
					
						
							|  |  |  |                 onNotGranted?() | 
					
						
							|  |  |  |                 AVAudioSession.sharedInstance().requestRecordPermission { _ in } | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |             default: break | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public static func requestLibraryPermissionIfNeeded( | 
					
						
							|  |  |  |         presentingViewController: UIViewController? = nil, | 
					
						
							|  |  |  |         onAuthorized: @escaping () -> Void | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         let authorizationStatus: PHAuthorizationStatus | 
					
						
							|  |  |  |         if #available(iOS 14, *) { | 
					
						
							|  |  |  |             authorizationStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite) | 
					
						
							|  |  |  |             if authorizationStatus == .notDetermined { | 
					
						
							|  |  |  |                 // When the user chooses to select photos (which is the .limit status), | 
					
						
							|  |  |  |                 // the PHPhotoUI will present the picker view on the top of the front view. | 
					
						
							|  |  |  |                 // Since we have the ScreenLockUI showing when we request premissions, | 
					
						
							|  |  |  |                 // the picker view will be presented on the top of the ScreenLockUI. | 
					
						
							|  |  |  |                 // However, the ScreenLockUI will dismiss with the permission request alert view, so | 
					
						
							|  |  |  |                 // the picker view then will dismiss, too. The selection process cannot be finished | 
					
						
							|  |  |  |                 // this way. So we add a flag (isRequestingPermission) to prevent the ScreenLockUI | 
					
						
							|  |  |  |                 // from showing when we request the photo library permission. | 
					
						
							|  |  |  |                 SessionEnvironment.shared?.isRequestingPermission = true | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in | 
					
						
							|  |  |  |                     SessionEnvironment.shared?.isRequestingPermission = false | 
					
						
							|  |  |  |                     if [ PHAuthorizationStatus.authorized, PHAuthorizationStatus.limited ].contains(status) { | 
					
						
							|  |  |  |                         onAuthorized() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             authorizationStatus = PHPhotoLibrary.authorizationStatus() | 
					
						
							|  |  |  |             if authorizationStatus == .notDetermined { | 
					
						
							|  |  |  |                 PHPhotoLibrary.requestAuthorization { status in | 
					
						
							|  |  |  |                     if status == .authorized { | 
					
						
							|  |  |  |                         onAuthorized() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         switch authorizationStatus { | 
					
						
							|  |  |  |             case .authorized, .limited: onAuthorized() | 
					
						
							|  |  |  |             case .denied, .restricted: | 
					
						
							|  |  |  |                 guard let presentingViewController: UIViewController = (presentingViewController ?? CurrentAppContext().frontmostViewController()) else { return } | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 let confirmationModal: ConfirmationModal = ConfirmationModal( | 
					
						
							|  |  |  |                     info: ConfirmationModal.Info( | 
					
						
							|  |  |  |                         title: "Session", | 
					
						
							|  |  |  |                         body: .text( | 
					
						
							|  |  |  |                             String( | 
					
						
							|  |  |  |                                 format: "modal_permission_explanation".localized(), | 
					
						
							|  |  |  |                                 "modal_permission_library".localized() | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                         ), | 
					
						
							|  |  |  |                         confirmTitle: "modal_permission_settings_title".localized(), | 
					
						
							|  |  |  |                         dismissOnConfirm: false | 
					
						
							|  |  |  |                     ) { [weak presentingViewController] _ in | 
					
						
							|  |  |  |                         presentingViewController?.dismiss(animated: true, completion: { | 
					
						
							|  |  |  |                             UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!) | 
					
						
							|  |  |  |                         }) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 presentingViewController.present(confirmationModal, animated: true, completion: nil) | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |             default: return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |