@preconcurrency import ApplicationServices
|
import CoreGraphics
|
import Foundation
|
|
private let axTrustedCheckOptionPromptKey =
|
kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String
|
|
public enum PermissionKind: String, CaseIterable, Equatable, Sendable {
|
case accessibility
|
case screenRecording
|
}
|
|
public enum PermissionStatus: Equatable, Sendable {
|
case granted
|
case notGranted
|
}
|
|
public protocol SystemPermissionChecking {
|
func status(for kind: PermissionKind) -> PermissionStatus
|
}
|
|
public protocol SystemPermissionRequesting {
|
@discardableResult
|
func request(_ kind: PermissionKind) -> PermissionStatus
|
}
|
|
public protocol SystemPermissionManaging: SystemPermissionChecking, SystemPermissionRequesting {}
|
|
public struct SystemPermissionChecker: SystemPermissionManaging {
|
public init() {}
|
|
public func status(for kind: PermissionKind) -> PermissionStatus {
|
switch kind {
|
case .accessibility:
|
return AXIsProcessTrusted() ? .granted : .notGranted
|
case .screenRecording:
|
return CGPreflightScreenCaptureAccess() ? .granted : .notGranted
|
}
|
}
|
|
@discardableResult
|
public func request(_ kind: PermissionKind) -> PermissionStatus {
|
switch kind {
|
case .accessibility:
|
let options = [axTrustedCheckOptionPromptKey: true] as CFDictionary
|
return AXIsProcessTrustedWithOptions(options) ? .granted : .notGranted
|
case .screenRecording:
|
return CGRequestScreenCaptureAccess() ? .granted : .notGranted
|
}
|
}
|
}
|