Skip to content

Commit

Permalink
Merge pull request #100 from r17x/main
Browse files Browse the repository at this point in the history
feat: only require screen capture and accessibility permissions
  • Loading branch information
richiemcilroy authored Oct 7, 2024
2 parents fa27761 + 6de08e6 commit 923d221
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 168 deletions.
14 changes: 10 additions & 4 deletions apps/desktop/src-tauri/src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,13 @@ pub fn get_input_devices() -> IndexMap<String, (Device, SupportedStreamConfig)>
let host = cpal::default_host();
let mut device_map = IndexMap::new();

let get_usable_device = |device: Device| {
let get_usable_microphone = |device: Device| {
if !device.default_input_config().is_ok() {
return None;
}

device
.supported_input_configs()
// .map_err(utils::log_debug_error)
.ok()
.and_then(|mut configs| {
configs.find(|c| match c.sample_format() {
Expand All @@ -225,17 +228,20 @@ pub fn get_input_devices() -> IndexMap<String, (Device, SupportedStreamConfig)>
device
.name()
.ok()
.filter(|name| !name.to_lowercase().contains("speaker"))
.map(|name| (name, device, config.with_max_sample_rate()))
})
};

if let Some((name, device, config)) = host.default_input_device().and_then(get_usable_device) {
if let Some((name, device, config)) =
host.default_input_device().and_then(get_usable_microphone)
{
device_map.insert(name, (device, config));
}

match host.input_devices() {
Ok(devices) => {
for (name, device, config) in devices.filter_map(get_usable_device) {
for (name, device, config) in devices.filter_map(get_usable_microphone) {
device_map.entry(name).or_insert((device, config));
}
}
Expand Down
50 changes: 47 additions & 3 deletions apps/desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,9 @@ async fn stop_recording(app: AppHandle, state: MutableState<'_, App>) -> Result<
serde_json::to_string_pretty(&json!(&config)).unwrap(),
)
.unwrap();

AppSounds::StopRecording.play();

if let Ok(Some(settings)) = GeneralSettingsStore::get(&app) {
if settings.open_editor_after_recording {
let recording_id = current_recording
Expand Down Expand Up @@ -1429,13 +1431,17 @@ async fn list_audio_devices() -> Result<Vec<String>, ()> {
#[tauri::command(async)]
#[specta::specta]
fn open_main_window(app: AppHandle) {
println!("Attempting to open main window");
if let Some(window) = app.get_webview_window("main") {
println!("Main window already exists, setting focus");
window.set_focus().ok();
return;
}

let permissions = permissions::do_permissions_check(false);
if !permissions.screen_recording.permitted() || !permissions.accessibility.permitted() {
return;
}

println!("Creating new main window");
let Some(window) = WebviewWindow::builder(&app, "main", tauri::WebviewUrl::App("/".into()))
.title("Cap")
Expand Down Expand Up @@ -2152,6 +2158,42 @@ async fn delete_auth_open_signin(app: AppHandle) -> Result<(), String> {
Ok(())
}

#[tauri::command]
#[specta::specta]
async fn reset_camera_permissions(app: AppHandle) -> Result<(), ()> {
#[cfg(debug_assertions)]
let bundle_id = "com.apple.Terminal";
#[cfg(not(debug_assertions))]
let bundle_id = "so.cap.desktop";

Command::new("tccutil")
.arg("reset")
.arg("Camera")
.arg(bundle_id)
.output()
.expect("Failed to reset camera permissions");

Ok(())
}

#[tauri::command]
#[specta::specta]
async fn reset_microphone_permissions(app: AppHandle) -> Result<(), ()> {
#[cfg(debug_assertions)]
let bundle_id = "com.apple.Terminal";
#[cfg(not(debug_assertions))]
let bundle_id = "so.cap.desktop";

Command::new("tccutil")
.arg("reset")
.arg("Microphone")
.arg(bundle_id)
.output()
.expect("Failed to reset microphone permissions");

Ok(())
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let specta_builder = tauri_specta::Builder::new()
Expand Down Expand Up @@ -2205,7 +2247,9 @@ pub fn run() {
open_external_link,
hotkeys::set_hotkey,
set_general_settings,
delete_auth_open_signin
delete_auth_open_signin,
reset_camera_permissions,
reset_microphone_permissions
])
.events(tauri_specta::collect_events![
RecordingOptionsChanged,
Expand Down Expand Up @@ -2270,7 +2314,7 @@ pub fn run() {
if permissions::do_permissions_check(true).necessary_granted() {
open_main_window(app_handle.clone());
} else {
permissions::open_permissions_window(app);
permissions::open_permissions_window(app_handle.clone());
}

app.manage(Arc::new(RwLock::new(App {
Expand Down
37 changes: 21 additions & 16 deletions apps/desktop/src-tauri/src/permissions.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use serde::{Deserialize, Serialize};
use tauri::{Manager, WebviewUrl, WebviewWindow, Wry};
use tauri::{AppHandle, Manager, WebviewUrl, WebviewWindow};
use tauri_plugin_decorum::WebviewWindowExt;

use core_foundation::boolean::CFBoolean;
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; // Import CFDictionaryRef
use core_foundation::string::CFString;
#[cfg(target_os = "macos")]
use nokhwa_bindings_macos::{AVAuthorizationStatus, AVMediaType};
use std::os::raw::c_void;

#[cfg(target_os = "macos")]
#[link(name = "ApplicationServices", kind = "framework")]
Expand Down Expand Up @@ -211,24 +211,29 @@ pub fn request_accessibility_permission() {
}
}

#[tauri::command(async)]
#[tauri::command]
#[specta::specta]
pub fn open_permissions_window(app: &impl Manager<Wry>) {
pub fn open_permissions_window(app: AppHandle) {
if let Some(window) = app.get_webview_window("permissions") {
window.set_focus().ok();
return;
}

WebviewWindow::builder(app, "permissions", WebviewUrl::App("/permissions".into()))
.title("Cap")
.inner_size(300.0, 256.0)
.resizable(false)
.maximized(false)
.shadow(true)
.accept_first_mouse(true)
.transparent(true)
.hidden_title(true)
.decorations(false)
.build()
.ok();
let window =
WebviewWindow::builder(&app, "permissions", WebviewUrl::App("/permissions".into()))
.title("Cap")
.inner_size(300.0, 350.0)
.resizable(false)
.maximized(false)
.shadow(true)
.accept_first_mouse(true)
.transparent(true)
.hidden_title(true)
.title_bar_style(tauri::TitleBarStyle::Overlay)
.build()
.unwrap();

window.create_overlay_titlebar().unwrap();
#[cfg(target_os = "macos")]
window.set_traffic_lights_inset(14.0, 22.0).unwrap();
}
Loading

1 comment on commit 923d221

@vercel
Copy link

@vercel vercel bot commented on 923d221 Oct 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.