use tauri::{command, AppHandle, Runtime};
#[cfg(target_os = "macos")]
use {
macos_accessibility_client::accessibility::{
application_is_trusted, application_is_trusted_with_prompt,
},
objc2::{class, msg_send, runtime::Bool},
objc2_foundation::NSString,
std::{fs::read_dir, process::Command},
tauri::Manager,
};
#[cfg(target_os = "macos")]
#[link(name = "CoreGraphics", kind = "framework")]
extern "C" {
fn CGPreflightScreenCaptureAccess() -> bool;
fn CGRequestScreenCaptureAccess() -> bool;
}
#[cfg(target_os = "macos")]
#[link(name = "IOKit", kind = "framework")]
extern "C" {
fn IOHIDCheckAccess(request: u32) -> u32;
}
#[command]
pub async fn check_accessibility_permission() -> bool {
#[cfg(target_os = "macos")]
return application_is_trusted();
#[cfg(not(target_os = "macos"))]
return true;
}
#[command]
pub async fn request_accessibility_permission() {
#[cfg(target_os = "macos")]
application_is_trusted_with_prompt();
}
#[command]
pub async fn check_full_disk_access_permission<R: Runtime>(app_handle: AppHandle<R>) -> bool {
#[cfg(target_os = "macos")]
{
let check_dirs = vec!["Library/Containers/com.apple.stocks", "Library/Safari"];
if let Ok(home_dir) = app_handle.path().home_dir() {
for check_dir in check_dirs.iter() {
if read_dir(&home_dir.join(check_dir)).is_ok() {
return true;
}
}
}
false
}
#[cfg(not(target_os = "macos"))]
{
let _ = app_handle;
true
}
}
#[command]
pub async fn request_full_disk_access_permission() -> Result<(), String> {
#[cfg(target_os = "macos")]
{
Command::new("open")
.arg("x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles")
.output()
.map_err(|error| error.to_string())?;
}
Ok(())
}
#[command]
pub async fn check_screen_recording_permission() -> bool {
#[cfg(target_os = "macos")]
unsafe {
CGPreflightScreenCaptureAccess()
}
#[cfg(not(target_os = "macos"))]
return true;
}
#[command]
pub async fn request_screen_recording_permission() {
#[cfg(target_os = "macos")]
unsafe {
CGRequestScreenCaptureAccess();
}
}
#[command]
pub async fn check_microphone_permission() -> bool {
#[cfg(target_os = "macos")]
unsafe {
let av_media_type = NSString::from_str("soun");
let status: i32 = msg_send![
class!(AVCaptureDevice),
authorizationStatusForMediaType: &*av_media_type
];
status == 3
}
#[cfg(not(target_os = "macos"))]
return true;
}
#[command]
pub async fn request_microphone_permission() -> Result<(), String> {
#[cfg(target_os = "macos")]
unsafe {
let av_media_type = NSString::from_str("soun");
type CompletionBlock = Option<extern "C" fn(Bool)>;
let completion_block: CompletionBlock = None;
let _: () = msg_send![
class!(AVCaptureDevice),
requestAccessForMediaType: &*av_media_type,
completionHandler: completion_block
];
}
Ok(())
}
#[command]
pub async fn check_camera_permission() -> bool {
#[cfg(target_os = "macos")]
unsafe {
let av_media_type = NSString::from_str("vide");
let status: i32 = msg_send![
class!(AVCaptureDevice),
authorizationStatusForMediaType: &*av_media_type
];
status == 3
}
#[cfg(not(target_os = "macos"))]
return true;
}
#[command]
pub async fn request_camera_permission() -> Result<(), String> {
#[cfg(target_os = "macos")]
unsafe {
let av_media_type = NSString::from_str("vide");
type CompletionBlock = Option<extern "C" fn(Bool)>;
let completion_block: CompletionBlock = None;
let _: () = msg_send![
class!(AVCaptureDevice),
requestAccessForMediaType: &*av_media_type,
completionHandler: completion_block
];
}
Ok(())
}
#[command]
pub async fn check_input_monitoring_permission() -> bool {
#[cfg(target_os = "macos")]
unsafe {
let status = IOHIDCheckAccess(1);
status == 0
}
#[cfg(not(target_os = "macos"))]
return true;
}
#[command]
pub async fn request_input_monitoring_permission() -> Result<(), String> {
#[cfg(target_os = "macos")]
{
Command::new("open")
.arg("x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent")
.output()
.map_err(|error| error.to_string())?;
}
Ok(())
}