session-ios/Session/Utilities/Permissions.swift

157 lines
7.1 KiB
Swift

// 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.
Environment.shared?.isRequestingPermission = true
PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
Environment.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
}
}
}