From 6b9c44bd7b2783527e1cfd881c9fa18604fbae71 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:05:48 +0330 Subject: [PATCH 01/48] bump tauri and tauri plugin versions --- Cargo.toml | 9 +++-- apps/desktop/src-tauri/Cargo.toml | 56 +++++++++++++++---------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0b35f66d45..86a7f011d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,11 @@ [workspace] resolver = "2" -members = ["apps/cli", "apps/desktop/src-tauri", "crates/*", "crates/workspace-hack"] +members = [ + "apps/cli", + "apps/desktop/src-tauri", + "crates/*", + "crates/workspace-hack", +] [workspace.dependencies] anyhow = { version = "1.0.86" } @@ -17,7 +22,7 @@ tokio = { version = "1.39.3", features = [ "rt-multi-thread", "time", ] } -tauri = { version = "2.5.0", features = ["specta"] } +tauri = { version = "2.8.5", features = ["specta"] } specta = { version = "=2.0.0-rc.20", features = [ "derive", "serde_json", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index a6cf8cfe17..ea73f63966 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -20,30 +20,30 @@ swift-rs = { version = "1.0.6", features = ["build"] } [dependencies] tauri = { workspace = true, features = [ - "macos-private-api", - "protocol-asset", - "tray-icon", - "image-png", - "devtools", + "macos-private-api", + "protocol-asset", + "tray-icon", + "image-png", + "devtools", ] } tauri-specta = { version = "=2.0.0-rc.20", features = ["derive", "typescript"] } -tauri-plugin-dialog = "2.2.0" -tauri-plugin-fs = "2.2.0" -tauri-plugin-global-shortcut = "2.2.0" -tauri-plugin-http = "2.2.0" -tauri-plugin-notification = "2.2.0" -tauri-plugin-os = "2.2.0" -tauri-plugin-process = "2.2.0" -tauri-plugin-shell = "2.2.0" -tauri-plugin-single-instance = { version = "2.2.0", features = ["deep-link"] } -tauri-plugin-store = "2.2.0" +tauri-plugin-dialog = "2.4.0" +tauri-plugin-fs = "2.4.2" +tauri-plugin-global-shortcut = "2.3.0" +tauri-plugin-http = "2.5.2" +tauri-plugin-notification = "2.3.1" +tauri-plugin-os = "2.3.1" +tauri-plugin-process = "2.3.0" +tauri-plugin-shell = "2.3.1" +tauri-plugin-single-instance = { version = "2.3.4", features = ["deep-link"] } +tauri-plugin-store = "2.4.0" tauri-plugin-updater = "2.9.0" tauri-plugin-oauth = { git = "https://github.com/FabianLars/tauri-plugin-oauth", branch = "v2" } -tauri-plugin-window-state = "2.2.0" -tauri-plugin-positioner = "2.2.0" -tauri-plugin-deep-link = "2.2.0" -tauri-plugin-clipboard-manager = "2.2.1" -tauri-plugin-opener = "2.2.6" +tauri-plugin-window-state = "2.4.0" +tauri-plugin-positioner = "2.3.0" +tauri-plugin-deep-link = "2.4.3" +tauri-plugin-clipboard-manager = "2.3.0" +tauri-plugin-opener = "2.5.0" serde = { workspace = true } serde_json = "1.0.111" @@ -109,7 +109,7 @@ async-stream = "0.3.6" tracing-futures = { version = "0.2.5", features = ["futures-03"] } tracing-opentelemetry = "0.32.0" opentelemetry = "0.31.0" -opentelemetry-otlp = "0.31.0" #{ version = , features = ["http-proto", "reqwest-client"] } +opentelemetry-otlp = "0.31.0" #{ version = , features = ["http-proto", "reqwest-client"] } opentelemetry_sdk = { version = "0.31.0", features = ["rt-tokio", "trace"] } posthog-rs = "0.3.7" workspace-hack = { version = "0.1", path = "../../../crates/workspace-hack" } @@ -119,9 +119,9 @@ workspace-hack = { version = "0.1", path = "../../../crates/workspace-hack" } core-graphics = "0.24.0" core-foundation = "0.10.0" objc2-app-kit = { version = "0.3.0", features = [ - "NSWindow", - "NSResponder", - "NSHapticFeedback", + "NSWindow", + "NSResponder", + "NSHapticFeedback", ] } cocoa = "0.26.0" objc = "0.2.7" @@ -131,10 +131,10 @@ cidre = { workspace = true } [target.'cfg(target_os= "windows")'.dependencies] windows = { workspace = true, features = [ - "Win32_Foundation", - "Win32_System", - "Win32_UI_WindowsAndMessaging", - "Win32_Graphics_Gdi", + "Win32_Foundation", + "Win32_System", + "Win32_UI_WindowsAndMessaging", + "Win32_Graphics_Gdi", ] } windows-sys = { workspace = true } From 40cf146d8092c81e1356c00f8ea7b64024df770a Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Tue, 11 Nov 2025 16:50:19 +0330 Subject: [PATCH 02/48] Remove macos/delegates.rs --- apps/desktop/src-tauri/src/lib.rs | 1 - .../src-tauri/src/platform/macos/delegates.rs | 358 ------------------ .../src-tauri/src/platform/macos/mod.rs | 1 - apps/desktop/src-tauri/src/windows.rs | 102 +---- 4 files changed, 3 insertions(+), 459 deletions(-) delete mode 100644 apps/desktop/src-tauri/src/platform/macos/delegates.rs diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index b2152ba350..3abe84784b 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -1917,7 +1917,6 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { reset_microphone_permissions, is_camera_window_open, seek_to, - windows::position_traffic_lights, windows::set_theme, global_message_dialog, show_window, diff --git a/apps/desktop/src-tauri/src/platform/macos/delegates.rs b/apps/desktop/src-tauri/src/platform/macos/delegates.rs deleted file mode 100644 index 7c9c97f020..0000000000 --- a/apps/desktop/src-tauri/src/platform/macos/delegates.rs +++ /dev/null @@ -1,358 +0,0 @@ -// TODO(Ilya): Re-write all macos code to use `objc2` crates n -/// -/// Credit to @haasal, @charrondev, Hoppscotch app, Electron, Zed Editor -/// -/// https://github.com/haasal -/// https://gist.github.com/charrondev -/// https://github.com/hoppscotch/hoppscotch -/// https://github.com/clearlysid/tauri-plugin-decorum/ -/// (Issue) https://github.com/tauri-apps/tauri/issues/4789 -/// (Gist) https://gist.github.com/charrondev/43150e940bd2771b1ea88256d491c7a9 -/// (Hoppscotch) https://github.com/hoppscotch/hoppscotch/blob/286fcd2bb08a84f027b10308d1e18da368f95ebf/packages/hoppscotch-selfhost-desktop/src-tauri/src/mac/window.rs -/// (Electron) https://github.com/electron/electron/blob/38512efd25a159ddc64a54c22ef9eb6dd60064ec/shell/browser/native_window_mac.mm#L1454 -/// -use objc::{msg_send, sel, sel_impl}; -use rand::{Rng, distributions::Alphanumeric}; -use tauri::{Emitter, LogicalPosition, Runtime, Window}; - -pub struct UnsafeWindowHandle(pub *mut std::ffi::c_void); -unsafe impl Send for UnsafeWindowHandle {} -unsafe impl Sync for UnsafeWindowHandle {} - -#[derive(Debug)] -struct WindowState { - window: Window, - controls_inset: LogicalPosition, -} - -// TODO: Respect RTL display language -// TODO: Update Height, consider supporting the scenario where the buttons are hidden by the system due to screen sharing of the window -// https://developer.apple.com/documentation/appkit/nsapplication/1428556-userinterfacelayoutdirection?language=objc -pub fn position_window_controls( - ns_window_handle: UnsafeWindowHandle, - inset: &LogicalPosition, -) { - use cocoa::{ - appkit::{NSView, NSWindow, NSWindowButton}, - base::id, - foundation::NSRect, - }; - - let ns_window = ns_window_handle.0 as id; - unsafe { - let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let minimize = ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let zoom = ns_window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - - let title_bar_container_view = close.superview().superview(); - - let close_rect: NSRect = msg_send![close, frame]; - let button_height = close_rect.size.height; - - let title_bar_frame_height = button_height + inset.y; - let mut title_bar_rect = NSView::frame(title_bar_container_view); - title_bar_rect.size.height = title_bar_frame_height; - title_bar_rect.origin.y = NSView::frame(ns_window).size.height - title_bar_frame_height; - let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; - - let window_buttons = vec![close, minimize, zoom]; - let space_between = NSView::frame(minimize).origin.x - NSView::frame(close).origin.x; - let vertical_offset = 4.0; // Adjust this value to push buttons down - - for (i, button) in window_buttons.into_iter().enumerate() { - let mut rect: NSRect = NSView::frame(button); - rect.origin.x = inset.x + (i as f64 * space_between); - rect.origin.y = ((title_bar_frame_height - button_height) / 2.0) - vertical_offset; - button.setFrameOrigin(rect.origin); - } - } -} - -pub fn setup(window: Window, controls_inset: LogicalPosition) { - use cocoa::appkit::NSWindow; - use cocoa::base::{BOOL, id}; - use cocoa::foundation::NSUInteger; - use objc::runtime::{Object, Sel}; - use std::ffi::c_void; - - let ns_win = window.ns_window().expect("Failed to create window handle"); - - // Do the initial positioning - position_window_controls(UnsafeWindowHandle(ns_win), &controls_inset); - - // Ensure they stay in place while resizing the window. - fn with_window_state) -> T, T>( - this: &Object, - func: F, - ) { - let ptr = unsafe { - let x: *mut c_void = *this.get_ivar("app_box"); - &mut *(x as *mut WindowState) - }; - func(ptr); - } - - unsafe { - let ns_win_id = ns_win as id; - let current_delegate: id = ns_win_id.delegate(); - - extern "C" fn on_window_should_close(this: &Object, _cmd: Sel, sender: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, windowShouldClose: sender] - } - } - extern "C" fn on_window_will_close(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillClose: notification]; - } - } - extern "C" fn on_window_did_resize(this: &Object, _cmd: Sel, notification: id) { - unsafe { - with_window_state(this, |state: &mut WindowState| { - position_window_controls( - UnsafeWindowHandle( - state - .window - .ns_window() - .expect("Failed to get handle to NSWindow"), - ), - &state.controls_inset, - ); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidResize: notification]; - } - } - extern "C" fn on_window_did_move(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidMove: notification]; - } - } - extern "C" fn on_window_did_change_backing_properties( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidChangeBackingProperties: notification]; - } - } - extern "C" fn on_window_did_become_key(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidBecomeKey: notification]; - } - } - extern "C" fn on_window_did_resign_key(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidResignKey: notification]; - } - } - extern "C" fn on_dragging_entered(this: &Object, _cmd: Sel, notification: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, draggingEntered: notification] - } - } - extern "C" fn on_prepare_for_drag_operation( - this: &Object, - _cmd: Sel, - notification: id, - ) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, prepareForDragOperation: notification] - } - } - extern "C" fn on_perform_drag_operation(this: &Object, _cmd: Sel, sender: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, performDragOperation: sender] - } - } - extern "C" fn on_conclude_drag_operation(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, concludeDragOperation: notification]; - } - } - extern "C" fn on_dragging_exited(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, draggingExited: notification]; - } - } - extern "C" fn on_window_will_use_full_screen_presentation_options( - this: &Object, - _cmd: Sel, - window: id, - proposed_options: NSUInteger, - ) -> NSUInteger { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, window: window willUseFullScreenPresentationOptions: proposed_options] - } - } - extern "C" fn on_window_did_enter_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(this, |state: &mut WindowState| { - state - .window - .emit("did-enter-fullscreen", ()) - .expect("Failed to emit event"); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidEnterFullScreen: notification]; - } - } - extern "C" fn on_window_will_enter_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(this, |state: &mut WindowState| { - state - .window - .emit("will-enter-fullscreen", ()) - .expect("Failed to emit event"); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillEnterFullScreen: notification]; - } - } - extern "C" fn on_window_did_exit_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(this, |state: &mut WindowState| { - state - .window - .emit("did-exit-fullscreen", ()) - .expect("Failed to emit event"); - - position_window_controls( - UnsafeWindowHandle( - state - .window - .ns_window() - .expect("Failed to get handle to NSWindow"), - ), - &state.controls_inset, - ); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidExitFullScreen: notification]; - } - } - extern "C" fn on_window_will_exit_full_screen( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - with_window_state(this, |state: &mut WindowState| { - state - .window - .emit("will-exit-fullscreen", ()) - .expect("Failed to emit event"); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillExitFullScreen: notification]; - } - } - extern "C" fn on_window_did_fail_to_enter_full_screen( - this: &Object, - _cmd: Sel, - window: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidFailToEnterFullScreen: window]; - } - } - extern "C" fn on_effective_appearance_did_change( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, effectiveAppearanceDidChange: notification]; - } - } - extern "C" fn on_effective_appearance_did_changed_on_main_thread( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![ - super_del, - effectiveAppearanceDidChangedOnMainThread: notification - ]; - } - } - - let window_label = window.label().to_string(); - - let app_state = WindowState { - window, - controls_inset, - }; - let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void; - let random_str: String = rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(20) - .map(char::from) - .collect(); - - // We need to ensure we have a unique delegate name, otherwise we will panic while trying to create a duplicate - // delegate with the same name. - let delegate_name = format!("windowDelegate_cap_{window_label}_{random_str}"); - - ns_win_id.setDelegate_(cocoa::delegate!(&delegate_name, { - window: id = ns_win_id, - app_box: *mut c_void = app_box, - toolbar: id = cocoa::base::nil, - super_delegate: id = current_delegate, - (windowShouldClose:) => on_window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL, - (windowWillClose:) => on_window_will_close as extern "C" fn(&Object, Sel, id), - (windowDidResize:) => on_window_did_resize:: as extern "C" fn(&Object, Sel, id), - (windowDidMove:) => on_window_did_move as extern "C" fn(&Object, Sel, id), - (windowDidChangeBackingProperties:) => on_window_did_change_backing_properties as extern "C" fn(&Object, Sel, id), - (windowDidBecomeKey:) => on_window_did_become_key as extern "C" fn(&Object, Sel, id), - (windowDidResignKey:) => on_window_did_resign_key as extern "C" fn(&Object, Sel, id), - (draggingEntered:) => on_dragging_entered as extern "C" fn(&Object, Sel, id) -> BOOL, - (prepareForDragOperation:) => on_prepare_for_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL, - (performDragOperation:) => on_perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL, - (concludeDragOperation:) => on_conclude_drag_operation as extern "C" fn(&Object, Sel, id), - (draggingExited:) => on_dragging_exited as extern "C" fn(&Object, Sel, id), - (window:willUseFullScreenPresentationOptions:) => on_window_will_use_full_screen_presentation_options as extern "C" fn(&Object, Sel, id, NSUInteger) -> NSUInteger, - (windowDidEnterFullScreen:) => on_window_did_enter_full_screen:: as extern "C" fn(&Object, Sel, id), - (windowWillEnterFullScreen:) => on_window_will_enter_full_screen:: as extern "C" fn(&Object, Sel, id), - (windowDidExitFullScreen:) => on_window_did_exit_full_screen:: as extern "C" fn(&Object, Sel, id), - (windowWillExitFullScreen:) => on_window_will_exit_full_screen:: as extern "C" fn(&Object, Sel, id), - (windowDidFailToEnterFullScreen:) => on_window_did_fail_to_enter_full_screen as extern "C" fn(&Object, Sel, id), - (effectiveAppearanceDidChange:) => on_effective_appearance_did_change as extern "C" fn(&Object, Sel, id), - (effectiveAppearanceDidChangedOnMainThread:) => on_effective_appearance_did_changed_on_main_thread as extern "C" fn(&Object, Sel, id) - })) - } -} diff --git a/apps/desktop/src-tauri/src/platform/macos/mod.rs b/apps/desktop/src-tauri/src/platform/macos/mod.rs index f6d5d47010..ad7ffee427 100644 --- a/apps/desktop/src-tauri/src/platform/macos/mod.rs +++ b/apps/desktop/src-tauri/src/platform/macos/mod.rs @@ -10,7 +10,6 @@ // }; // use objc::{class, msg_send, sel, sel_impl}; -pub mod delegates; mod sc_shareable_content; pub use sc_shareable_content::*; diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index ba6d5a71f6..263e4be231 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -30,7 +30,8 @@ use crate::{ }; #[cfg(target_os = "macos")] -const DEFAULT_TRAFFIC_LIGHTS_INSET: LogicalPosition = LogicalPosition::new(12.0, 12.0); +const DEFAULT_TRAFFIC_LIGHTS_INSET_WITH_TOOLBAR: LogicalPosition = + LogicalPosition::new(20.0, 30.0); #[derive(Clone, Deserialize, Type)] pub enum CapWindowId { @@ -150,20 +151,6 @@ impl CapWindowId { app.get_webview_window(&label) } - #[cfg(target_os = "macos")] - pub fn traffic_lights_position(&self) -> Option>> { - match self { - Self::Editor { .. } => Some(Some(LogicalPosition::new(20.0, 32.0))), - Self::RecordingControls => Some(Some(LogicalPosition::new(-100.0, -100.0))), - Self::Camera - | Self::WindowCaptureOccluder { .. } - | Self::CaptureArea - | Self::RecordingsOverlay - | Self::TargetSelectOverlay { .. } => None, - _ => Some(None), - } - } - pub fn min_size(&self) -> Option<(f64, f64)> { Some(match self { Self::Setup => (600.0, 600.0), @@ -719,12 +706,6 @@ impl ShowCapWindow { // removing this for now as it causes windows to just stay hidden sometimes -_- // window.hide().ok(); - - #[cfg(target_os = "macos")] - if let Some(position) = _id.traffic_lights_position() { - add_traffic_lights(&window, position); - } - Ok(window) } @@ -747,17 +728,6 @@ impl ShowCapWindow { .min_inner_size(min.0, min.1); } - #[cfg(target_os = "macos")] - { - if id.traffic_lights_position().is_some() { - builder = builder - .hidden_title(true) - .title_bar_style(tauri::TitleBarStyle::Overlay); - } else { - builder = builder.decorations(false) - } - } - #[cfg(windows)] { builder = builder.decorations(false); @@ -795,29 +765,6 @@ impl ShowCapWindow { } } -#[cfg(target_os = "macos")] -fn add_traffic_lights(window: &WebviewWindow, controls_inset: Option>) { - use crate::platform::delegates; - - let target_window = window.clone(); - window - .run_on_main_thread(move || { - delegates::setup( - target_window.as_ref().window(), - controls_inset.unwrap_or(DEFAULT_TRAFFIC_LIGHTS_INSET), - ); - - let c_win = target_window.clone(); - target_window.on_window_event(move |event| match event { - tauri::WindowEvent::ThemeChanged(..) | tauri::WindowEvent::Focused(..) => { - position_traffic_lights_impl(&c_win.as_ref().window(), controls_inset); - } - _ => {} - }); - }) - .ok(); -} - #[tauri::command] #[specta::specta] #[instrument(skip(window))] @@ -826,50 +773,7 @@ pub fn set_theme(window: tauri::Window, theme: AppTheme) { AppTheme::System => None, AppTheme::Light => Some(tauri::Theme::Light), AppTheme::Dark => Some(tauri::Theme::Dark), - }); - - #[cfg(target_os = "macos")] - match CapWindowId::from_str(window.label()) { - Ok(win) if win.traffic_lights_position().is_some() => position_traffic_lights(window, None), - Ok(_) | Err(_) => {} - } -} - -#[tauri::command] -#[specta::specta] -#[instrument(skip(_window))] -pub fn position_traffic_lights(_window: tauri::Window, _controls_inset: Option<(f64, f64)>) { - #[cfg(target_os = "macos")] - position_traffic_lights_impl( - &_window, - _controls_inset.map(LogicalPosition::from).or_else(|| { - // Attempt to get the default inset from the window's traffic lights position - CapWindowId::from_str(_window.label()) - .ok() - .and_then(|id| id.traffic_lights_position().flatten()) - }), - ); -} - -#[cfg(target_os = "macos")] -fn position_traffic_lights_impl( - window: &tauri::Window, - controls_inset: Option>, -) { - use crate::platform::delegates::{UnsafeWindowHandle, position_window_controls}; - let c_win = window.clone(); - window - .run_on_main_thread(move || { - let ns_window = match c_win.ns_window() { - Ok(handle) => handle, - Err(_) => return, - }; - position_window_controls( - UnsafeWindowHandle(ns_window), - &controls_inset.unwrap_or(DEFAULT_TRAFFIC_LIGHTS_INSET), - ); - }) - .ok(); + }) } fn should_protect_window(app: &AppHandle, window_title: &str) -> bool { From a681a881619da58e8bbf57b6296fe186f05909f7 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Fri, 14 Nov 2025 18:46:12 +0330 Subject: [PATCH 03/48] Rename CapWindowId -> CapWindowDef, ShowCapWindow -> CapWindow + Update serde version. --- Cargo.lock | 12 +- .../desktop/src-tauri/src/deeplink_actions.rs | 4 +- apps/desktop/src-tauri/src/hotkeys.rs | 4 +- apps/desktop/src-tauri/src/lib.rs | 98 ++++++------ apps/desktop/src-tauri/src/recording.rs | 36 ++--- .../src-tauri/src/target_select_overlay.rs | 10 +- apps/desktop/src-tauri/src/tray.rs | 6 +- apps/desktop/src-tauri/src/windows.rs | 150 ++++++++++-------- apps/desktop/src/utils/tauri.ts | 7 +- 9 files changed, 175 insertions(+), 152 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7074489506..4562529bac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8041,9 +8041,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -8063,18 +8063,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", diff --git a/apps/desktop/src-tauri/src/deeplink_actions.rs b/apps/desktop/src-tauri/src/deeplink_actions.rs index dbd90f667f..240205c982 100644 --- a/apps/desktop/src-tauri/src/deeplink_actions.rs +++ b/apps/desktop/src-tauri/src/deeplink_actions.rs @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf}; use tauri::{AppHandle, Manager, Url}; use tracing::trace; -use crate::{App, ArcLock, recording::StartRecordingInputs, windows::ShowCapWindow}; +use crate::{App, ArcLock, recording::StartRecordingInputs, windows::CapWindow}; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] @@ -150,7 +150,7 @@ impl DeepLinkAction { crate::open_project_from_path(Path::new(&project_path), app.clone()) } DeepLinkAction::OpenSettings { page } => { - crate::show_window(app.clone(), ShowCapWindow::Settings { page }).await + crate::show_window(app.clone(), CapWindow::Settings { page }).await } } } diff --git a/apps/desktop/src-tauri/src/hotkeys.rs b/apps/desktop/src-tauri/src/hotkeys.rs index 14bf3d38cd..d3f8142888 100644 --- a/apps/desktop/src-tauri/src/hotkeys.rs +++ b/apps/desktop/src-tauri/src/hotkeys.rs @@ -1,6 +1,6 @@ use crate::{ RequestOpenRecordingPicker, RequestStartRecording, recording, - recording_settings::RecordingTargetMode, windows::ShowCapWindow, + recording_settings::RecordingTargetMode, windows::CapWindow, }; use global_hotkey::HotKeyState; use serde::{Deserialize, Serialize}; @@ -96,7 +96,7 @@ pub fn init(app: &AppHandle) { if shortcut.key == Code::Comma && shortcut.mods == Modifiers::META { let app = app.clone(); tokio::spawn(async move { - let _ = ShowCapWindow::Settings { page: None }.show(&app).await; + let _ = CapWindow::Settings { page: None }.show(&app).await; }); } diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 3abe84784b..cf79d2a981 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -83,7 +83,7 @@ use tracing::*; use upload::{create_or_get_video, upload_image, upload_video}; use web_api::AuthedApiError; use web_api::ManagerExt as WebManagerExt; -use windows::{CapWindowId, EditorWindowIds, ShowCapWindow, set_window_transparent}; +use windows::{CapWindow, CapWindowDef, EditorWindowIds, set_window_transparent}; use crate::{ camera::CameraPreviewManager, @@ -290,7 +290,7 @@ async fn set_camera_input( .map_err(|e| e.to_string())?; } Some(id) => { - ShowCapWindow::Camera + CapWindow::Camera .show(&app_handle) .await .map_err(|err| error!("Failed to show camera preview window: {err}")) @@ -856,7 +856,7 @@ struct SerializedEditorInstance { #[specta::specta] #[instrument(skip(window))] async fn create_editor_instance(window: Window) -> Result { - let CapWindowId::Editor { id } = CapWindowId::from_str(window.label()).unwrap() else { + let CapWindowDef::Editor { id } = CapWindowDef::from_str(window.label()).unwrap() else { return Err("Invalid window".to_string()); }; @@ -1008,14 +1008,14 @@ fn close_recordings_overlay_window(app: AppHandle) { #[cfg(target_os = "macos")] { use tauri_nspanel::ManagerExt; - if let Ok(panel) = app.get_webview_panel(&CapWindowId::RecordingsOverlay.label()) { + if let Ok(panel) = app.get_webview_panel(&CapWindowDef::RecordingsOverlay.label()) { panel.released_when_closed(true); panel.close(); } } if !cfg!(target_os = "macos") - && let Some(window) = CapWindowId::RecordingsOverlay.get(&app) + && let Some(window) = CapWindowDef::RecordingsOverlay.get(&app) { let _ = window.close(); } @@ -1028,7 +1028,7 @@ fn focus_captures_panel(_app: AppHandle) { #[cfg(target_os = "macos")] { use tauri_nspanel::ManagerExt; - if let Ok(panel) = _app.get_webview_panel(&CapWindowId::RecordingsOverlay.label()) { + if let Ok(panel) = _app.get_webview_panel(&CapWindowDef::RecordingsOverlay.label()) { panel.make_key_window(); } } @@ -1253,7 +1253,7 @@ async fn upload_screenshot( }; if !auth.is_upgraded() { - ShowCapWindow::Upgrade.show(&app).await.ok(); + CapWindow::Upgrade.show(&app).await.ok(); return Ok(UploadResult::UpgradeRequired); } @@ -1638,7 +1638,7 @@ async fn reset_microphone_permissions(_app: AppHandle) -> Result<(), ()> { #[specta::specta] #[instrument(skip(app))] async fn is_camera_window_open(app: AppHandle) -> bool { - CapWindowId::Camera.get(&app).is_some() + CapWindowDef::Camera.get(&app).is_some() } #[tauri::command] @@ -1716,7 +1716,7 @@ async fn editor_delete_project( #[tauri::command] #[specta::specta] #[instrument(skip(app))] -async fn show_window(app: AppHandle, window: ShowCapWindow) -> Result<(), String> { +async fn show_window(app: AppHandle, window: CapWindow) -> Result<(), String> { let _ = window.show(&app).await; Ok(()) } @@ -2029,7 +2029,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { else { let app = app.clone(); tokio::spawn(async move { - ShowCapWindow::Main { + CapWindow::Main { init_target_mode: None, } .show(&app) @@ -2070,14 +2070,14 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { flags }) .with_denylist(&[ - CapWindowId::Setup.label().as_str(), + CapWindowDef::Setup.label().as_str(), "window-capture-occluder", "target-select-overlay", - CapWindowId::CaptureArea.label().as_str(), - CapWindowId::Camera.label().as_str(), - CapWindowId::RecordingsOverlay.label().as_str(), - CapWindowId::RecordingControls.label().as_str(), - CapWindowId::Upgrade.label().as_str(), + CapWindowDef::CaptureArea.label().as_str(), + CapWindowDef::Camera.label().as_str(), + CapWindowDef::RecordingsOverlay.label().as_str(), + CapWindowDef::RecordingControls.label().as_str(), + CapWindowDef::Upgrade.label().as_str(), ]) .map_label(|label| match label { label if label.starts_with("editor-") => "editor", @@ -2110,7 +2110,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { camera_feed .tell(feeds::camera::OnFeedDisconnect(Box::new({ move || { - if let Some(win) = CapWindowId::Camera.get(&app) { + if let Some(win) = CapWindowDef::Camera.get(&app) { win.close().ok(); } } @@ -2208,11 +2208,11 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { .map(|s| !s.has_completed_startup) .unwrap_or(false) { - let _ = ShowCapWindow::Setup.show(&app).await; + let _ = CapWindow::Setup.show(&app).await; } else { println!("Permissions granted, showing main window"); - let _ = ShowCapWindow::Main { + let _ = CapWindow::Main { init_target_mode: None, } .show(&app) @@ -2250,7 +2250,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { }); RequestOpenRecordingPicker::listen_any_spawn(&app, async |event, app| { - let _ = ShowCapWindow::Main { + let _ = CapWindow::Main { init_target_mode: event.target_mode, } .show(&app) @@ -2258,7 +2258,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { }); RequestOpenSettings::listen_any_spawn(&app, async |payload, app| { - let _ = ShowCapWindow::Settings { + let _ = CapWindow::Settings { page: Some(payload.page), } .show(&app) @@ -2284,14 +2284,14 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { match event { WindowEvent::Destroyed => { - if let Ok(window_id) = CapWindowId::from_str(label) { + if let Ok(window_id) = CapWindowDef::from_str(label) { match window_id { - CapWindowId::Main => { + CapWindowDef::Main => { let app = app.clone(); for (id, window) in app.webview_windows() { - if let Ok(CapWindowId::TargetSelectOverlay { .. }) = - CapWindowId::from_str(&id) + if let Ok(CapWindowDef::TargetSelectOverlay { .. }) = + CapWindowDef::from_str(&id) { let _ = window.close(); } @@ -2311,25 +2311,25 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { } }); } - CapWindowId::Editor { id } => { + CapWindowDef::Editor { id } => { let window_ids = EditorWindowIds::get(window.app_handle()); window_ids.ids.lock().unwrap().retain(|(_, _id)| *_id != id); tokio::spawn(EditorInstances::remove(window.clone())); #[cfg(target_os = "windows")] - if CapWindowId::Settings.get(&app).is_none() { + if CapWindowDef::Settings.get(&app).is_none() { reopen_main_window(&app); } } - CapWindowId::Settings => { + CapWindowDef::Settings => { for (label, window) in app.webview_windows() { - if let Ok(id) = CapWindowId::from_str(&label) + if let Ok(id) = CapWindowDef::from_str(&label) && matches!( id, - CapWindowId::TargetSelectOverlay { .. } - | CapWindowId::Main - | CapWindowId::Camera + CapWindowDef::TargetSelectOverlay { .. } + | CapWindowDef::Main + | CapWindowDef::Camera ) { let _ = window.show(); @@ -2343,14 +2343,14 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { return; } - CapWindowId::Upgrade | CapWindowId::ModeSelect => { + CapWindowDef::Upgrade | CapWindowDef::ModeSelect => { for (label, window) in app.webview_windows() { - if let Ok(id) = CapWindowId::from_str(&label) + if let Ok(id) = CapWindowDef::from_str(&label) && matches!( id, - CapWindowId::TargetSelectOverlay { .. } - | CapWindowId::Main - | CapWindowId::Camera + CapWindowDef::TargetSelectOverlay { .. } + | CapWindowDef::Main + | CapWindowDef::Camera ) { let _ = window.show(); @@ -2358,11 +2358,11 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { } return; } - CapWindowId::TargetSelectOverlay { display_id } => { + CapWindowDef::TargetSelectOverlay { display_id } => { app.state::() .destroy(&display_id, app.global_shortcut()); } - CapWindowId::Camera => { + CapWindowDef::Camera => { let app = app.clone(); tokio::spawn(async move { app.state::>() @@ -2381,7 +2381,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { && app .webview_windows() .keys() - .all(|label| !CapWindowId::from_str(label).unwrap().activates_dock()) + .all(|label| !CapWindowDef::from_str(label).unwrap().activates_dock()) { #[cfg(target_os = "macos")] app.set_activation_policy(tauri::ActivationPolicy::Accessory) @@ -2390,12 +2390,12 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { } #[cfg(target_os = "macos")] WindowEvent::Focused(focused) => { - let window_id = CapWindowId::from_str(label); + let window_id = CapWindowDef::from_str(label); - if matches!(window_id, Ok(CapWindowId::Upgrade)) { + if matches!(window_id, Ok(CapWindowDef::Upgrade)) { for (label, window) in app.webview_windows() { - if let Ok(id) = CapWindowId::from_str(&label) - && matches!(id, CapWindowId::TargetSelectOverlay { .. }) + if let Ok(id) = CapWindowDef::from_str(&label) + && matches!(id, CapWindowDef::TargetSelectOverlay { .. }) { let _ = window.hide(); } @@ -2445,7 +2445,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { } else { let handle = _handle.clone(); tokio::spawn(async move { - let _ = ShowCapWindow::Main { + let _ = CapWindow::Main { init_target_mode: None, } .show(&handle) @@ -2471,13 +2471,13 @@ fn has_open_editor_window(app: &AppHandle) -> bool { #[cfg(target_os = "windows")] fn reopen_main_window(app: &AppHandle) { - if let Some(main) = CapWindowId::Main.get(app) { + if let Some(main) = CapWindowDef::Main.get(app) { let _ = main.show(); let _ = main.set_focus(); } else { let handle = app.clone(); tokio::spawn(async move { - let _ = ShowCapWindow::Main { + let _ = CapWindow::Main { init_target_mode: None, } .show(&handle) @@ -2720,7 +2720,7 @@ fn open_project_from_path(path: &Path, app: AppHandle) -> Result<(), String> { } let project_path = path.to_path_buf(); - tokio::spawn(async move { ShowCapWindow::Editor { project_path }.show(&app).await }); + tokio::spawn(async move { CapWindow::Editor { project_path }.show(&app).await }); } RecordingMetaInner::Instant(_) => { let mp4_path = path.join("content/output.mp4"); @@ -2729,7 +2729,7 @@ fn open_project_from_path(path: &Path, app: AppHandle) -> Result<(), String> { let _ = app .opener() .open_path(mp4_path.to_str().unwrap_or_default(), None::); - if let Some(main_window) = CapWindowId::Main.get(&app) { + if let Some(main_window) = CapWindowDef::Main.get(&app) { main_window.close().ok(); } } diff --git a/apps/desktop/src-tauri/src/recording.rs b/apps/desktop/src-tauri/src/recording.rs index e999788c23..a2678ef120 100644 --- a/apps/desktop/src-tauri/src/recording.rs +++ b/apps/desktop/src-tauri/src/recording.rs @@ -57,7 +57,7 @@ use crate::{ InstantMultipartUpload, build_video_meta, compress_image, create_or_get_video, upload_video, }, web_api::ManagerExt, - windows::{CapWindowId, ShowCapWindow}, + windows::{CapWindowDef, CapWindow}, }; #[derive(Clone)] @@ -319,7 +319,7 @@ pub async fn start_recording( } }; - if let Some(window) = CapWindowId::Camera.get(&app) { + if let Some(window) = CapWindowDef::Camera.get(&app) { let _ = window.set_content_protected(matches!(inputs.mode, RecordingMode::Studio)); } @@ -410,13 +410,13 @@ pub async fn start_recording( if let Some(show) = inputs .capture_target .display() - .map(|d| ShowCapWindow::WindowCaptureOccluder { screen_id: d.id() }) + .map(|d| CapWindow::WindowCaptureOccluder { screen_id: d.id() }) { let _ = show.show(&app).await; } } ScreenCaptureTarget::Area { screen, .. } => { - let _ = ShowCapWindow::WindowCaptureOccluder { + let _ = CapWindow::WindowCaptureOccluder { screen_id: screen.clone(), } .show(&app) @@ -435,17 +435,17 @@ pub async fn start_recording( for (id, win) in app .webview_windows() .iter() - .filter_map(|(label, win)| CapWindowId::from_str(label).ok().map(|id| (id, win))) + .filter_map(|(label, win)| CapWindowDef::from_str(label).ok().map(|id| (id, win))) { - if matches!(id, CapWindowId::TargetSelectOverlay { .. }) { + if matches!(id, CapWindowDef::TargetSelectOverlay { .. }) { win.close().ok(); } } - let _ = ShowCapWindow::InProgressRecording { countdown } + let _ = CapWindow::InProgressRecording { countdown } .show(&app) .await; - if let Some(window) = CapWindowId::Main.get(&app) { + if let Some(window) = CapWindowDef::Main.get(&app) { let _ = general_settings .map(|v| v.main_window_recording_start_behaviour) .unwrap_or_default() @@ -689,7 +689,7 @@ pub async fn start_recording( ) .kind(tauri_plugin_dialog::MessageDialogKind::Error); - if let Some(window) = CapWindowId::RecordingControls.get(&app) { + if let Some(window) = CapWindowDef::RecordingControls.get(&app) { dialog = dialog.parent(&window); } @@ -753,7 +753,7 @@ async fn handle_spawn_failure( ) .kind(tauri_plugin_dialog::MessageDialogKind::Error); - if let Some(window) = CapWindowId::RecordingControls.get(app) { + if let Some(window) = CapWindowDef::RecordingControls.get(app) { dialog = dialog.parent(&window); } @@ -880,14 +880,14 @@ pub async fn delete_recording(app: AppHandle, state: MutableState<'_, App>) -> R .flatten() .unwrap_or_default(); - if let Some(window) = CapWindowId::RecordingControls.get(&app) { + if let Some(window) = CapWindowDef::RecordingControls.get(&app) { let _ = window.close(); } match settings.post_deletion_behaviour { PostDeletionBehaviour::DoNothing => {} PostDeletionBehaviour::ReopenRecordingWindow => { - let _ = ShowCapWindow::Main { + let _ = CapWindow::Main { init_target_mode: None, } .show(&app) @@ -944,19 +944,19 @@ async fn handle_recording_end( let _ = app.recording_logging_handle.reload(None); - if let Some(window) = CapWindowId::RecordingControls.get(&handle) { + if let Some(window) = CapWindowDef::RecordingControls.get(&handle) { let _ = window.close(); } - if let Some(window) = CapWindowId::Main.get(&handle) { + if let Some(window) = CapWindowDef::Main.get(&handle) { window.unminimize().ok(); } else { - if let Some(v) = CapWindowId::Camera.get(&handle) { + if let Some(v) = CapWindowDef::Camera.get(&handle) { let _ = v.close(); } let _ = app.mic_feed.ask(microphone::RemoveInput).await; let _ = app.camera_feed.ask(camera::RemoveInput).await; - if let Some(win) = CapWindowId::Camera.get(&handle) { + if let Some(win) = CapWindowDef::Camera.get(&handle) { win.close().ok(); } } @@ -1138,14 +1138,14 @@ async fn handle_recording_finish( .unwrap_or(PostStudioRecordingBehaviour::OpenEditor) { PostStudioRecordingBehaviour::OpenEditor => { - let _ = ShowCapWindow::Editor { + let _ = CapWindow::Editor { project_path: recording_dir, } .show(app) .await; } PostStudioRecordingBehaviour::ShowOverlay => { - let _ = ShowCapWindow::RecordingsOverlay.show(app).await; + let _ = CapWindow::RecordingsOverlay.show(app).await; let app = AppHandle::clone(app); tokio::spawn(async move { diff --git a/apps/desktop/src-tauri/src/target_select_overlay.rs b/apps/desktop/src-tauri/src/target_select_overlay.rs index d8ccf834d8..32166b29f2 100644 --- a/apps/desktop/src-tauri/src/target_select_overlay.rs +++ b/apps/desktop/src-tauri/src/target_select_overlay.rs @@ -8,7 +8,7 @@ use std::{ use base64::prelude::*; use cap_recording::screen_capture::ScreenCaptureTarget; -use crate::windows::{CapWindowId, ShowCapWindow}; +use crate::windows::{CapWindowDef, CapWindow}; use scap_targets::{ Display, DisplayId, Window, WindowId, bounds::{LogicalBounds, PhysicalSize}, @@ -54,7 +54,7 @@ pub async fn open_target_select_overlays( .map(|d| d.id()) .collect::>(); for display_id in displays { - let _ = ShowCapWindow::TargetSelectOverlay { display_id } + let _ = CapWindow::TargetSelectOverlay { display_id } .show(&app) .await; } @@ -115,7 +115,7 @@ pub async fn open_target_select_overlays( #[instrument(skip(app))] pub async fn close_target_select_overlays(app: AppHandle) -> Result<(), String> { for (id, window) in app.webview_windows() { - if let Ok(CapWindowId::TargetSelectOverlay { .. }) = CapWindowId::from_str(&id) { + if let Ok(CapWindowDef::TargetSelectOverlay { .. }) = CapWindowDef::from_str(&id) { let _ = window.close(); } } @@ -227,8 +227,8 @@ impl WindowFocusManager { tokio::spawn(async move { let app = window.app_handle(); loop { - let cap_main = CapWindowId::Main.get(app); - let cap_settings = CapWindowId::Settings.get(app); + let cap_main = CapWindowDef::Main.get(app); + let cap_settings = CapWindowDef::Settings.get(app); let has_cap_main = cap_main .as_ref() diff --git a/apps/desktop/src-tauri/src/tray.rs b/apps/desktop/src-tauri/src/tray.rs index d07632be35..10495466d7 100644 --- a/apps/desktop/src-tauri/src/tray.rs +++ b/apps/desktop/src-tauri/src/tray.rs @@ -1,4 +1,4 @@ -use crate::windows::ShowCapWindow; +use crate::windows::CapWindow; use crate::{RecordingStarted, RecordingStopped, RequestOpenSettings, recording}; use std::sync::{ @@ -102,7 +102,7 @@ pub fn create_tray(app: &AppHandle) -> tauri::Result<()> { Ok(TrayItem::OpenCap) => { let app = app.clone(); tokio::spawn(async move { - let _ = ShowCapWindow::Main { + let _ = CapWindow::Main { init_target_mode: None, } .show(&app) @@ -124,7 +124,7 @@ pub fn create_tray(app: &AppHandle) -> tauri::Result<()> { Ok(TrayItem::OpenSettings) => { let app = app.clone(); tokio::spawn( - async move { ShowCapWindow::Settings { page: None }.show(&app).await }, + async move { CapWindow::Settings { page: None }.show(&app).await }, ); } Ok(TrayItem::UploadLogs) => { diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 263e4be231..fa07c64bc4 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -34,7 +34,7 @@ const DEFAULT_TRAFFIC_LIGHTS_INSET_WITH_TOOLBAR: LogicalPosition = LogicalPosition::new(20.0, 30.0); #[derive(Clone, Deserialize, Type)] -pub enum CapWindowId { +pub enum CapWindowDef { // Contains onboarding + permissions Setup, Main, @@ -51,7 +51,7 @@ pub enum CapWindowId { Debug, } -impl FromStr for CapWindowId { +impl FromStr for CapWindowDef { type Err = String; fn from_str(s: &str) -> Result { @@ -90,7 +90,7 @@ impl FromStr for CapWindowId { } } -impl std::fmt::Display for CapWindowId { +impl std::fmt::Display for CapWindowDef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Setup => write!(f, "setup"), @@ -114,27 +114,27 @@ impl std::fmt::Display for CapWindowId { } } -impl CapWindowId { +impl CapWindowDef { pub fn label(&self) -> String { self.to_string() } - pub fn title(&self) -> String { + pub const fn title(&self) -> &str { match self { - Self::Setup => "Cap Setup".to_string(), - Self::Settings => "Cap Settings".to_string(), - Self::WindowCaptureOccluder { .. } => "Cap Window Capture Occluder".to_string(), - Self::CaptureArea => "Cap Capture Area".to_string(), - Self::RecordingControls => "Cap Recording Controls".to_string(), - Self::Editor { .. } => "Cap Editor".to_string(), - Self::ModeSelect => "Cap Mode Selection".to_string(), - Self::Camera => "Cap Camera".to_string(), - Self::RecordingsOverlay => "Cap Recordings Overlay".to_string(), - _ => "Cap".to_string(), + Self::Setup => "Cap Setup", + Self::Settings => "Cap Settings", + Self::WindowCaptureOccluder { .. } => "Cap Window Capture Occluder", + Self::CaptureArea => "Cap Capture Area", + Self::RecordingControls => "Cap Recording Controls", + Self::Editor { .. } => "Cap Editor", + Self::ModeSelect => "Cap Mode Selection", + Self::Camera => "Cap Camera", + Self::RecordingsOverlay => "Cap Recordings Overlay", + _ => "Cap", } } - pub fn activates_dock(&self) -> bool { + pub const fn activates_dock(&self) -> bool { matches!( self, Self::Setup @@ -151,7 +151,34 @@ impl CapWindowId { app.get_webview_window(&label) } - pub fn min_size(&self) -> Option<(f64, f64)> { + #[cfg(target_os = "macos")] + pub const fn has_toolbar(&self) -> bool { + matches!(self, Self::Editor { .. } | Self::Settings { .. }) + } + + #[cfg(target_os = "macos")] + pub const fn undecorated(&self) -> bool { + matches!( + self, + Self::Camera + | Self::WindowCaptureOccluder { .. } + | Self::CaptureArea + | Self::RecordingsOverlay + | Self::TargetSelectOverlay { .. } + ) + } + + #[cfg(target_os = "macos")] + pub const fn disables_window_buttons(&self) -> bool { + matches!(self, Self::RecordingControls) + } + + #[cfg(target_os = "macos")] + pub const fn disables_fullscreen(&self) -> bool { + matches!(self, Self::Settings) + } + + pub const fn min_size(&self) -> Option<(f64, f64)> { Some(match self { Self::Setup => (600.0, 600.0), Self::Main => (300.0, 360.0), @@ -166,7 +193,7 @@ impl CapWindowId { } #[derive(Debug, Clone, Type, Deserialize)] -pub enum ShowCapWindow { +pub enum CapWindow { Setup, Main { init_target_mode: Option, @@ -195,7 +222,7 @@ pub enum ShowCapWindow { ModeSelect, } -impl ShowCapWindow { +impl CapWindow { pub async fn show(&self, app: &AppHandle) -> tauri::Result { if let Self::Editor { project_path } = &self { let state = app.state::(); @@ -210,12 +237,11 @@ impl ShowCapWindow { } } - if let Some(window) = self.id(app).get(app) { + if let Some(window) = self.def(app).get(app) { window.set_focus().ok(); return Ok(window); } - let _id = self.id(app); let monitor = app.primary_monitor()?.unwrap(); let window = match self { @@ -239,7 +265,7 @@ impl ShowCapWindow { .map(|s| s.enable_new_recording_flow) .unwrap_or_default(); - let title = CapWindowId::Main.title(); + let title = CapWindowDef::Main.title(); let should_protect = should_protect_window(app, &title); let window = self @@ -291,10 +317,11 @@ impl ShowCapWindow { .map(|d| d.id()) == Some(display.id()); - let title = CapWindowId::TargetSelectOverlay { + let title = CapWindowDef::TargetSelectOverlay { display_id: display_id.clone(), } - .title(); + .title() + .to_string(); let should_protect = should_protect_window(app, &title); let mut window_builder = self @@ -366,12 +393,12 @@ impl ShowCapWindow { Self::Settings { page } => { // Hide main window and target select overlays when settings window opens for (label, window) in app.webview_windows() { - if let Ok(id) = CapWindowId::from_str(&label) + if let Ok(id) = CapWindowDef::from_str(&label) && matches!( id, - CapWindowId::TargetSelectOverlay { .. } - | CapWindowId::Main - | CapWindowId::Camera + CapWindowDef::TargetSelectOverlay { .. } + | CapWindowDef::Main + | CapWindowDef::Camera ) { let _ = window.hide(); @@ -388,7 +415,7 @@ impl ShowCapWindow { .build()? } Self::Editor { .. } => { - if let Some(main) = CapWindowId::Main.get(app) { + if let Some(main) = CapWindowDef::Main.get(app) { let _ = main.close(); }; @@ -400,7 +427,7 @@ impl ShowCapWindow { } Self::Upgrade => { // Hide main window when upgrade window opens - if let Some(main) = CapWindowId::Main.get(app) { + if let Some(main) = CapWindowDef::Main.get(app) { let _ = main.hide(); } @@ -417,7 +444,7 @@ impl ShowCapWindow { } Self::ModeSelect => { // Hide main window when mode select window opens - if let Some(main) = CapWindowId::Main.get(app) { + if let Some(main) = CapWindowDef::Main.get(app) { let _ = main.hide(); } @@ -448,7 +475,7 @@ impl ShowCapWindow { if enable_native_camera_preview && state.camera_preview.is_initialized() { error!("Unable to initialize camera preview as one already exists!"); - if let Some(window) = CapWindowId::Camera.get(app) { + if let Some(window) = CapWindowDef::Camera.get(app) { window.show().ok(); } return Err(anyhow!( @@ -517,10 +544,11 @@ impl ShowCapWindow { return Err(tauri::Error::WindowNotFound); }; - let title = CapWindowId::WindowCaptureOccluder { + let title = CapWindowDef::WindowCaptureOccluder { screen_id: screen_id.clone(), } - .title(); + .title() + .to_string(); let should_protect = should_protect_window(app, &title); #[cfg(target_os = "macos")] @@ -557,7 +585,7 @@ impl ShowCapWindow { window } Self::CaptureArea { screen_id } => { - let title = CapWindowId::CaptureArea.title(); + let title = CapWindowDef::CaptureArea.title(); let should_protect = should_protect_window(app, &title); let mut window_builder = self @@ -600,7 +628,7 @@ impl ShowCapWindow { ); // Hide the main window if the target monitor is the same - if let Some(main_window) = CapWindowId::Main.get(app) + if let Some(main_window) = CapWindowDef::Main.get(app) && let (Ok(outer_pos), Ok(outer_size)) = (main_window.outer_position(), main_window.outer_size()) && let Ok(scale_factor) = main_window.scale_factor() @@ -615,7 +643,7 @@ impl ShowCapWindow { let width = 250.0; let height = 40.0; - let title = CapWindowId::RecordingControls.title(); + let title = CapWindowDef::RecordingControls.title(); let should_protect = should_protect_window(app, &title); let window = self @@ -648,7 +676,7 @@ impl ShowCapWindow { window } Self::RecordingsOverlay => { - let title = CapWindowId::RecordingsOverlay.title(); + let title = CapWindowDef::RecordingsOverlay.title(); let should_protect = should_protect_window(app, &title); let window = self @@ -714,15 +742,15 @@ impl ShowCapWindow { app: &'a AppHandle, url: impl Into, ) -> WebviewWindowBuilder<'a, Wry, AppHandle> { - let id = self.id(app); + let def = self.def(app); - let mut builder = WebviewWindow::builder(app, id.label(), WebviewUrl::App(url.into())) - .title(id.title()) + let mut builder = WebviewWindow::builder(app, def.label(), WebviewUrl::App(url.into())) + .title(def.title()) .visible(false) .accept_first_mouse(true) .shadow(true); - if let Some(min) = id.min_size() { + if let Some(min) = def.min_size() { builder = builder .inner_size(min.0, min.1) .min_inner_size(min.0, min.1); @@ -736,31 +764,29 @@ impl ShowCapWindow { builder } - pub fn id(&self, app: &AppHandle) -> CapWindowId { + pub fn def(&self, app: &AppHandle) -> CapWindowDef { match self { - ShowCapWindow::Setup => CapWindowId::Setup, - ShowCapWindow::Main { .. } => CapWindowId::Main, - ShowCapWindow::Settings { .. } => CapWindowId::Settings, - ShowCapWindow::Editor { project_path } => { + CapWindow::Setup => CapWindowDef::Setup, + CapWindow::Main { .. } => CapWindowDef::Main, + CapWindow::Settings { .. } => CapWindowDef::Settings, + CapWindow::Editor { project_path } => { let state = app.state::(); let s = state.ids.lock().unwrap(); let id = s.iter().find(|(path, _)| path == project_path).unwrap().1; - CapWindowId::Editor { id } + CapWindowDef::Editor { id } } - ShowCapWindow::RecordingsOverlay => CapWindowId::RecordingsOverlay, - ShowCapWindow::TargetSelectOverlay { display_id } => CapWindowId::TargetSelectOverlay { + CapWindow::RecordingsOverlay => CapWindowDef::RecordingsOverlay, + CapWindow::TargetSelectOverlay { display_id } => CapWindowDef::TargetSelectOverlay { display_id: display_id.clone(), }, - ShowCapWindow::WindowCaptureOccluder { screen_id } => { - CapWindowId::WindowCaptureOccluder { - screen_id: screen_id.clone(), - } - } - ShowCapWindow::CaptureArea { .. } => CapWindowId::CaptureArea, - ShowCapWindow::Camera => CapWindowId::Camera, - ShowCapWindow::InProgressRecording { .. } => CapWindowId::RecordingControls, - ShowCapWindow::Upgrade => CapWindowId::Upgrade, - ShowCapWindow::ModeSelect => CapWindowId::ModeSelect, + CapWindow::WindowCaptureOccluder { screen_id } => CapWindowDef::WindowCaptureOccluder { + screen_id: screen_id.clone(), + }, + CapWindow::CaptureArea { .. } => CapWindowDef::CaptureArea, + CapWindow::Camera => CapWindowDef::Camera, + CapWindow::InProgressRecording { .. } => CapWindowDef::RecordingControls, + CapWindow::Upgrade => CapWindowDef::Upgrade, + CapWindow::ModeSelect => CapWindowDef::ModeSelect, } } } @@ -773,7 +799,7 @@ pub fn set_theme(window: tauri::Window, theme: AppTheme) { AppTheme::System => None, AppTheme::Light => Some(tauri::Theme::Light), AppTheme::Dark => Some(tauri::Theme::Dark), - }) + }); } fn should_protect_window(app: &AppHandle, window_title: &str) -> bool { @@ -794,7 +820,7 @@ fn should_protect_window(app: &AppHandle, window_title: &str) -> bool { #[instrument(skip(app))] pub fn refresh_window_content_protection(app: AppHandle) -> Result<(), String> { for (label, window) in app.webview_windows() { - if let Ok(id) = CapWindowId::from_str(&label) { + if let Ok(id) = CapWindowDef::from_str(&label) { let title = id.title(); window .set_content_protected(should_protect_window(&app, &title)) diff --git a/apps/desktop/src/utils/tauri.ts b/apps/desktop/src/utils/tauri.ts index 9f2c25ff4c..e382b70e67 100644 --- a/apps/desktop/src/utils/tauri.ts +++ b/apps/desktop/src/utils/tauri.ts @@ -164,16 +164,13 @@ async isCameraWindowOpen() : Promise { async seekTo(frameNumber: number) : Promise { return await TAURI_INVOKE("seek_to", { frameNumber }); }, -async positionTrafficLights(controlsInset: [number, number] | null) : Promise { - await TAURI_INVOKE("position_traffic_lights", { controlsInset }); -}, async setTheme(theme: AppTheme) : Promise { await TAURI_INVOKE("set_theme", { theme }); }, async globalMessageDialog(message: string) : Promise { await TAURI_INVOKE("global_message_dialog", { message }); }, -async showWindow(window: ShowCapWindow) : Promise { +async showWindow(window: CapWindow) : Promise { return await TAURI_INVOKE("show_window", { window }); }, async writeClipboardString(text: string) : Promise { @@ -370,6 +367,7 @@ export type CameraPreviewState = { size: CameraPreviewSize; shape: CameraPreview export type CameraShape = "square" | "source" export type CameraXPosition = "left" | "center" | "right" export type CameraYPosition = "top" | "bottom" +export type CapWindow = "Setup" | { Main: { init_target_mode: RecordingTargetMode | null } } | { Settings: { page: string | null } } | { Editor: { project_path: string } } | "RecordingsOverlay" | { WindowCaptureOccluder: { screen_id: DisplayId } } | { TargetSelectOverlay: { display_id: DisplayId } } | { CaptureArea: { screen_id: DisplayId } } | "Camera" | { InProgressRecording: { countdown: number | null } } | "Upgrade" | "ModeSelect" export type CaptionData = { segments: CaptionSegment[]; settings: CaptionSettings | null } export type CaptionSegment = { id: string; start: number; end: number; text: string } export type CaptionSettings = { enabled: boolean; font: string; size: number; color: string; backgroundColor: string; backgroundOpacity: number; position: string; bold: boolean; italic: boolean; outline: boolean; outlineColor: string; exportWithSubtitles: boolean } @@ -471,7 +469,6 @@ export type SerializedEditorInstance = { framesSocketUrl: string; recordingDurat export type SetCaptureAreaPending = boolean export type ShadowConfiguration = { size: number; opacity: number; blur: number } export type SharingMeta = { id: string; link: string } -export type ShowCapWindow = "Setup" | { Main: { init_target_mode: RecordingTargetMode | null } } | { Settings: { page: string | null } } | { Editor: { project_path: string } } | "RecordingsOverlay" | { WindowCaptureOccluder: { screen_id: DisplayId } } | { TargetSelectOverlay: { display_id: DisplayId } } | { CaptureArea: { screen_id: DisplayId } } | "Camera" | { InProgressRecording: { countdown: number | null } } | "Upgrade" | "ModeSelect" export type SingleSegment = { display: VideoMeta; camera?: VideoMeta | null; audio?: AudioMeta | null; cursor?: string | null } export type StartRecordingInputs = { capture_target: ScreenCaptureTarget; capture_system_audio?: boolean; mode: RecordingMode; organization_id?: string | null } export type StereoMode = "stereo" | "monoL" | "monoR" From 3df6657190933039b4ed02e3346be45fb2abc5f7 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Fri, 14 Nov 2025 18:59:18 +0330 Subject: [PATCH 04/48] Add `objc2-*` to desktop crates + use objc2_application_services in permissions.rs --- Cargo.lock | 176 +++++++++++++++------- Cargo.toml | 1 + apps/desktop/src-tauri/Cargo.toml | 14 +- apps/desktop/src-tauri/src/permissions.rs | 33 ++-- crates/cursor-info/Cargo.toml | 6 +- crates/scap-screencapturekit/Cargo.toml | 2 +- 6 files changed, 142 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4562529bac..223c3c3625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,7 +327,7 @@ dependencies = [ "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "parking_lot", "percent-encoding", "windows-sys 0.60.2", @@ -1178,6 +1178,7 @@ dependencies = [ "async-stream", "axum", "base64 0.22.1", + "block2 0.6.1", "bytemuck", "bytes", "cap-audio", @@ -1194,12 +1195,10 @@ dependencies = [ "chrono", "cidre", "clipboard-rs", - "cocoa", - "core-foundation 0.10.1", - "core-graphics 0.24.0", "cpal 0.15.3 (git+https://github.com/CapSoftware/cpal?rev=3cc779a7b4ca)", "device_query", "dirs", + "dispatch2", "dotenvy_macro", "ffmpeg-next", "flume", @@ -1213,8 +1212,12 @@ dependencies = [ "log", "md5", "nix 0.29.0", - "objc", + "objc2 0.6.2", "objc2-app-kit", + "objc2-application-services", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", "opentelemetry", "opentelemetry-otlp", "opentelemetry_sdk", @@ -1828,7 +1831,7 @@ dependencies = [ "image 0.25.8", "objc2 0.6.2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "windows 0.59.0", "x11rb", ] @@ -4122,7 +4125,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.0", "system-configuration 0.6.1", "tokio", "tower-service", @@ -4809,7 +4812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.3", ] [[package]] @@ -4942,7 +4945,7 @@ checksum = "119c8490084af61b44c9eda9d626475847a186737c0378c85e32d77c33a01cd4" dependencies = [ "cc", "objc2 0.6.2", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "time", ] @@ -5258,7 +5261,7 @@ dependencies = [ "objc2 0.6.2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "png 0.17.16", "serde", @@ -5612,9 +5615,9 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.9.4", "block2 0.6.1", @@ -5625,8 +5628,25 @@ dependencies = [ "objc2-core-foundation", "objc2-core-graphics", "objc2-core-image", - "objc2-foundation 0.3.1", - "objc2-quartz-core 0.3.1", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-application-services" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69282c2b5bc58fba07cb9de2113619532eb551e98efe3d8d695509ef45fbd53b" +dependencies = [ + "bitflags 2.9.4", + "libc", + "objc2 0.6.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-services", + "objc2-foundation 0.3.2", ] [[package]] @@ -5645,8 +5665,8 @@ dependencies = [ "objc2-core-image", "objc2-core-media", "objc2-core-video", - "objc2-foundation 0.3.1", - "objc2-quartz-core 0.3.1", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", ] [[package]] @@ -5656,18 +5676,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfc1d11521c211a7ebe17739fc806719da41f56c6b3f949d9861b459188ce910" dependencies = [ "objc2 0.6.2", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] name = "objc2-cloud-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] @@ -5694,47 +5714,52 @@ dependencies = [ [[package]] name = "objc2-core-data" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] name = "objc2-core-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.9.4", + "block2 0.6.1", "dispatch2", + "libc", "objc2 0.6.2", ] [[package]] name = "objc2-core-graphics" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.9.4", + "block2 0.6.1", "dispatch2", + "libc", "objc2 0.6.2", "objc2-core-foundation", "objc2-io-surface", + "objc2-metal 0.3.2", ] [[package]] name = "objc2-core-image" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" dependencies = [ "objc2 0.6.2", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] @@ -5752,11 +5777,35 @@ dependencies = [ "objc2-core-video", ] +[[package]] +name = "objc2-core-services" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583300ad934cba24ff5292aee751ecc070f7ca6b39a574cc21b7b5e588e06a0b" +dependencies = [ + "dispatch2", + "objc2 0.6.2", + "objc2-core-foundation", + "objc2-security", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.2", + "objc2-core-foundation", + "objc2-core-graphics", +] + [[package]] name = "objc2-core-video" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1989c3e76c7e978cab0ba9e6f4961cd00ed14ca21121444cc26877403bfb6303" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", @@ -5794,9 +5843,9 @@ dependencies = [ [[package]] name = "objc2-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.9.4", "block2 0.6.1", @@ -5807,9 +5856,9 @@ dependencies = [ [[package]] name = "objc2-io-surface" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", @@ -5838,6 +5887,17 @@ dependencies = [ "objc2-foundation 0.2.2", ] +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.2", + "objc2-foundation 0.3.2", +] + [[package]] name = "objc2-osa-kit" version = "0.3.1" @@ -5847,7 +5907,7 @@ dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] @@ -5860,25 +5920,25 @@ dependencies = [ "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", - "objc2-metal", + "objc2-metal 0.2.2", ] [[package]] name = "objc2-quartz-core" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] name = "objc2-security" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1f8e0ef3ab66b08c42644dcb34dba6ec0a574bbd8adbb8bdbdc7a2779731a44" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", @@ -5894,7 +5954,7 @@ dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] @@ -5908,7 +5968,7 @@ dependencies = [ "objc2 0.6.2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "objc2-javascript-core", "objc2-security", ] @@ -6193,7 +6253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b" dependencies = [ "objc2 0.6.2", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "objc2-osa-kit", "serde", "serde_json", @@ -6826,7 +6886,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls 0.23.31", - "socket2 0.5.10", + "socket2 0.6.0", "thiserror 2.0.16", "tokio", "tracing", @@ -6863,7 +6923,7 @@ dependencies = [ "cfg_aliases 0.2.1", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.0", "tracing", "windows-sys 0.60.2", ] @@ -7382,7 +7442,7 @@ dependencies = [ "objc2 0.6.2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "raw-window-handle", "wasm-bindgen", "wasm-bindgen-futures", @@ -7686,7 +7746,7 @@ dependencies = [ "inquire", "objc2 0.6.2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "scap-targets", "tokio", "tracing", @@ -8880,7 +8940,7 @@ dependencies = [ "ndk-sys 0.6.0+11769913", "objc2 0.6.2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "parking_lot", "raw-window-handle", @@ -8948,7 +9008,7 @@ dependencies = [ "muda", "objc2 0.6.2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "objc2-ui-kit", "objc2-web-kit", "percent-encoding", @@ -9230,7 +9290,7 @@ dependencies = [ "dunce", "glob", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "open", "schemars 0.8.22", "serde", @@ -9439,7 +9499,7 @@ dependencies = [ "log", "objc2 0.6.2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "percent-encoding", "raw-window-handle", @@ -10131,7 +10191,7 @@ dependencies = [ "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "png 0.17.16", "serde", @@ -11088,7 +11148,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.0", ] [[package]] @@ -11106,7 +11166,7 @@ dependencies = [ "objc2 0.6.2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "raw-window-handle", "windows-sys 0.59.0", "windows-version", @@ -11949,7 +12009,7 @@ dependencies = [ "objc2 0.6.2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "objc2-ui-kit", "objc2-web-kit", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 86a7f011d5..27da5cd08f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ cidre = { git = "https://github.com/CapSoftware/cidre", rev = "bf84b67079a8", fe "async", "dispatch", ], default-features = false } +objc2 = "0.6.1" windows = "0.60.0" windows-core = "0.60" diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index ea73f63966..e98745a867 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -116,16 +116,18 @@ workspace-hack = { version = "0.1", path = "../../../crates/workspace-hack" } [target.'cfg(target_os = "macos")'.dependencies] -core-graphics = "0.24.0" -core-foundation = "0.10.0" -objc2-app-kit = { version = "0.3.0", features = [ +objc2.workspace = true +dispatch2 = "0.3.0" +block2 = "0.6.1" +objc2-foundation = "0.3.2" +objc2-application-services = "0.3.2" +objc2-core-foundation = "0.3.2" +objc2-core-graphics = "0.3.2" +objc2-app-kit = { version = "0.3.2", features = [ "NSWindow", "NSResponder", "NSHapticFeedback", ] } -cocoa = "0.26.0" -objc = "0.2.7" -swift-rs = "1.0.6" tauri-nspanel = { git = "https://github.com/ahkohd/tauri-nspanel", branch = "v2" } cidre = { workspace = true } diff --git a/apps/desktop/src-tauri/src/permissions.rs b/apps/desktop/src-tauri/src/permissions.rs index 9e6ad00f20..22cd256d0f 100644 --- a/apps/desktop/src-tauri/src/permissions.rs +++ b/apps/desktop/src-tauri/src/permissions.rs @@ -4,14 +4,6 @@ use serde::{Deserialize, Serialize}; use cidre::av; use tracing::instrument; -#[cfg(target_os = "macos")] -#[link(name = "ApplicationServices", kind = "framework")] -unsafe extern "C" { - fn AXIsProcessTrusted() -> bool; - fn AXIsProcessTrustedWithOptions(options: core_foundation::dictionary::CFDictionaryRef) - -> bool; -} - #[derive(Debug, Serialize, Deserialize, specta::Type)] #[serde(rename_all = "camelCase")] pub enum OSPermission { @@ -91,20 +83,17 @@ pub async fn request_permission(_permission: OSPermission) { }); } OSPermission::Accessibility => { - use core_foundation::base::TCFType; - use core_foundation::dictionary::CFDictionary; // Import CFDictionaryRef - use core_foundation::string::CFString; - - let prompt_key = CFString::new("AXTrustedCheckOptionPrompt"); - let prompt_value = core_foundation::boolean::CFBoolean::true_value(); - - let options = CFDictionary::from_CFType_pairs(&[( - prompt_key.as_CFType(), - prompt_value.as_CFType(), - )]); - + let options = objc2_core_foundation::CFDictionary::from_slices( + &[&*objc2_core_foundation::CFString::from_static_str( + "AXTrustedCheckOptionPrompt", + )], + &[&*objc2_core_foundation::CFBoolean::new(true)], + ); + // SAFETY: The AXIsProcessTrustedWithOptions function is safe to call with a valid CFDictionaryRef. unsafe { - AXIsProcessTrustedWithOptions(options.as_concrete_TypeRef()); + objc2_application_services::AXIsProcessTrustedWithOptions(Some( + &*options.as_opaque(), + )); } } } @@ -173,7 +162,7 @@ pub fn do_permissions_check(_initial_check: bool) -> OSPermissionsCheck { }, microphone: check_av_permission(MediaType::audio()), camera: check_av_permission(MediaType::video()), - accessibility: if unsafe { AXIsProcessTrusted() } { + accessibility: if unsafe { objc2_application_services::AXIsProcessTrusted() } { OSPermissionStatus::Granted } else { OSPermissionStatus::Denied diff --git a/crates/cursor-info/Cargo.toml b/crates/cursor-info/Cargo.toml index e86871e9ec..6ee59a5863 100644 --- a/crates/cursor-info/Cargo.toml +++ b/crates/cursor-info/Cargo.toml @@ -12,8 +12,8 @@ workspace-hack = { version = "0.1", path = "../workspace-hack" } [target.'cfg(target_os= "windows")'.dependencies] windows = { workspace = true, features = [ - "Win32_Graphics_Gdi", - "Win32_UI_WindowsAndMessaging", + "Win32_Graphics_Gdi", + "Win32_UI_WindowsAndMessaging", ] } [dev-dependencies] @@ -21,7 +21,7 @@ hex = "0.4" sha2 = "0.10" [target.'cfg(target_os = "macos")'.dev-dependencies] -objc2 = "0.6" +objc2 = { workspace = true } objc2-app-kit = { version = "0.3.0", features = ["NSCursor", "NSApplication"] } diff --git a/crates/scap-screencapturekit/Cargo.toml b/crates/scap-screencapturekit/Cargo.toml index 8d71749275..4754e42083 100644 --- a/crates/scap-screencapturekit/Cargo.toml +++ b/crates/scap-screencapturekit/Cargo.toml @@ -11,7 +11,7 @@ workspace-hack = { version = "0.1", path = "../workspace-hack" } [target.'cfg(target_os = "macos")'.dependencies] cidre = { workspace = true } -objc2 = "0.6.1" +objc2 = { workspace = true } objc2-app-kit = "0.3.1" objc2-foundation = "0.3.1" From ab4fb114406a3c2136860ee6866e9353ebba4ee1 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:23:20 +0330 Subject: [PATCH 05/48] bump tauri version + cleanups in windows.rs New min width for settings window. --- Cargo.lock | 65 +++--- Cargo.toml | 2 +- apps/desktop/src-tauri/Cargo.toml | 2 +- .../src-tauri/src/platform/macos/mod.rs | 97 ++++---- apps/desktop/src-tauri/src/windows.rs | 219 ++++++++---------- 5 files changed, 188 insertions(+), 197 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 223c3c3625..8146881a22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -855,9 +855,9 @@ dependencies = [ [[package]] name = "block2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ "objc2 0.6.2", ] @@ -1178,7 +1178,7 @@ dependencies = [ "async-stream", "axum", "base64 0.22.1", - "block2 0.6.1", + "block2 0.6.2", "bytemuck", "bytes", "cap-audio", @@ -2604,7 +2604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "libc", "objc2 0.6.2", ] @@ -5620,7 +5620,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "libc", "objc2 0.6.2", "objc2-cloud-kit", @@ -5656,7 +5656,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e085a2e16c61dadbad7a808fc9d5b5f8472b1b825b53d529c9f64ccac78e722" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", "objc2 0.6.2", "objc2-avf-audio", @@ -5730,7 +5730,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", "libc", "objc2 0.6.2", @@ -5743,7 +5743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", "libc", "objc2 0.6.2", @@ -5848,7 +5848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "libc", "objc2 0.6.2", "objc2-core-foundation", @@ -5964,7 +5964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "objc2 0.6.2", "objc2-app-kit", "objc2-core-foundation", @@ -7432,7 +7432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" dependencies = [ "ashpd", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", "glib-sys", "gobject-sys", @@ -7849,7 +7849,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c62ae379564f834110c5b020cc731a7c14b8ec4879b4367579a467a0a704c21" dependencies = [ - "block2 0.6.1", + "block2 0.6.2", "core-foundation 0.10.1", "core-graphics 0.25.0", "core-media-rs", @@ -8916,12 +8916,12 @@ dependencies = [ [[package]] name = "tao" -version = "0.34.3" +version = "0.34.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "959469667dbcea91e5485fc48ba7dd6023face91bb0f1a14681a70f99847c3f7" +checksum = "f3a753bdc39c07b192151523a3f77cd0394aa75413802c883a0f6f6a0e5ee2e7" dependencies = [ "bitflags 2.9.4", - "block2 0.6.1", + "block2 0.6.2", "core-foundation 0.10.1", "core-graphics 0.24.0", "crossbeam-channel", @@ -8984,9 +8984,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.8.5" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d1d3b3dc4c101ac989fd7db77e045cc6d91a25349cd410455cb5c57d510c1c" +checksum = "9e492485dd390b35f7497401f67694f46161a2a00ffd800938d5dd3c898fb9d8" dependencies = [ "anyhow", "bytes", @@ -9030,7 +9030,6 @@ dependencies = [ "tokio", "tray-icon", "url", - "urlpattern", "webkit2gtk", "webview2-com", "window-vibrancy", @@ -9039,9 +9038,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.4.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c432ccc9ff661803dab74c6cd78de11026a578a9307610bbc39d3c55be7943f" +checksum = "87d6f8cafe6a75514ce5333f115b7b1866e8e68d9672bf4ca89fc0f35697ea9d" dependencies = [ "anyhow", "cargo_toml", @@ -9061,9 +9060,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab3a62cf2e6253936a8b267c2e95839674e7439f104fa96ad0025e149d54d8a" +checksum = "b7ef707148f0755110ca54377560ab891d722de4d53297595380a748026f139f" dependencies = [ "base64 0.22.1", "brotli", @@ -9088,9 +9087,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4368ea8094e7045217edb690f493b55b30caf9f3e61f79b4c24b6db91f07995e" +checksum = "71664fd715ee6e382c05345ad258d6d1d50f90cf1b58c0aa726638b33c2a075d" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -9464,9 +9463,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4cfc9ad45b487d3fded5a4731a567872a4812e9552e3964161b08edabf93846" +checksum = "9368f09358496f2229313fccb37682ad116b7f46fa76981efe116994a0628926" dependencies = [ "cookie", "dpi", @@ -9489,9 +9488,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.8.1" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fe9d48bd122ff002064e88cfcd7027090d789c4302714e68fcccba0f4b7807" +checksum = "929f5df216f5c02a9e894554401bcdab6eec3e39ec6a4a7731c7067fc8688a93" dependencies = [ "gtk", "http 1.3.1", @@ -9544,9 +9543,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a3852fdf9a4f8fbeaa63dc3e9a85284dd6ef7200751f0bd66ceee30c93f212" +checksum = "f6b8bbe426abdbf52d050e52ed693130dbd68375b9ad82a3fb17efb4c8d85673" dependencies = [ "anyhow", "brotli", @@ -11986,12 +11985,12 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "wry" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f0e9642a0d061f6236c54ccae64c2722a7879ad4ec7dff59bd376d446d8e90" +checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" dependencies = [ "base64 0.22.1", - "block2 0.6.1", + "block2 0.6.2", "cookie", "crossbeam-channel", "dirs", diff --git a/Cargo.toml b/Cargo.toml index 27da5cd08f..ecd080fa3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ tokio = { version = "1.39.3", features = [ "rt-multi-thread", "time", ] } -tauri = { version = "2.8.5", features = ["specta"] } +tauri = { version = "2.9.3", features = ["specta"] } specta = { version = "=2.0.0-rc.20", features = [ "derive", "serde_json", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index e98745a867..56f9c9fd7c 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -118,7 +118,7 @@ workspace-hack = { version = "0.1", path = "../../../crates/workspace-hack" } [target.'cfg(target_os = "macos")'.dependencies] objc2.workspace = true dispatch2 = "0.3.0" -block2 = "0.6.1" +block2 = "0.6.2" objc2-foundation = "0.3.2" objc2-application-services = "0.3.2" objc2-core-foundation = "0.3.2" diff --git a/apps/desktop/src-tauri/src/platform/macos/mod.rs b/apps/desktop/src-tauri/src/platform/macos/mod.rs index ad7ffee427..2d3e71ec14 100644 --- a/apps/desktop/src-tauri/src/platform/macos/mod.rs +++ b/apps/desktop/src-tauri/src/platform/macos/mod.rs @@ -1,52 +1,59 @@ -// use std::ffi::c_void; - -// use cocoa::{ -// base::{id, nil}, -// foundation::NSString, -// }; -// use core_graphics::{ -// base::boolean_t, -// display::{CFDictionaryRef, CGRect}, -// }; -// use objc::{class, msg_send, sel, sel_impl}; +use dispatch2::run_on_main; +use objc2::{MainThreadMarker, MainThreadOnly}; +use objc2_app_kit::{NSWindow, NSWindowButton, NSWindowCollectionBehavior, NSWindowLevel}; +use tauri::WebviewWindow; mod sc_shareable_content; pub use sc_shareable_content::*; -pub fn set_window_level(window: tauri::Window, level: objc2_app_kit::NSWindowLevel) { - let c_window = window.clone(); - _ = window.run_on_main_thread(move || unsafe { - let ns_win = c_window - .ns_window() - .expect("Failed to get native window handle") - as *const objc2_app_kit::NSWindow; - (*ns_win).setLevel(level); - }); +pub trait WebviewWindowExt { + fn objc2_nswindow(&self) -> &NSWindow; + + fn set_window_buttons_visible(&self, visible: bool); + + fn set_level(&self, level: NSWindowLevel); + + fn disable_fullscreen(&self); } -// pub fn get_ns_window_number(ns_window: *mut c_void) -> isize { -// let ns_window = ns_window as *const objc2_app_kit::NSWindow; - -// unsafe { (*ns_window).windowNumber() } -// } - -// #[link(name = "CoreGraphics", kind = "framework")] -// unsafe extern "C" { -// pub fn CGRectMakeWithDictionaryRepresentation( -// dict: CFDictionaryRef, -// rect: *mut CGRect, -// ) -> boolean_t; -// } - -// /// Makes the background of the WKWebView layer transparent. -// /// This differs from Tauri's implementation as it does not change the window background which causes performance performance issues and artifacts when shadows are enabled on the window. -// /// Use Tauri's implementation to make the window itself transparent. -// pub fn make_webview_transparent(target: &tauri::WebviewWindow) -> tauri::Result<()> { -// target.with_webview(|webview| unsafe { -// let wkwebview = webview.inner() as id; -// let no: id = msg_send![class!(NSNumber), numberWithBool:0]; -// // [https://developer.apple.com/documentation/webkit/webview/1408486-drawsbackground] -// let _: id = msg_send![wkwebview, setValue:no forKey: NSString::alloc(nil).init_str("drawsBackground")]; -// }) -// } +impl WebviewWindowExt for WebviewWindow { + #[inline] + fn objc2_nswindow(&self) -> &NSWindow { + // SAFETY: This cast is safe as the existence of the WebviewWindow means it's attached to an NSWindow + unsafe { + &*self + .ns_window() + .expect("WebviewWindow is always backed by NSWindow") + .cast() + } + } + + fn set_window_buttons_visible(&self, visible: bool) { + run_on_main(move |_| { + let nswindow = self.objc2_nswindow(); + for btn in [ + NSWindowButton::CloseButton, + NSWindowButton::MiniaturizeButton, + NSWindowButton::ZoomButton, + ] { + if let Some(btn) = nswindow.standardWindowButton(btn) { + btn.setHidden(!visible); + } + } + }); + } + + fn set_level(&self, level: NSWindowLevel) { + run_on_main(move |_| self.objc2_nswindow().setLevel(level)); + } + + fn disable_fullscreen(&self) { + run_on_main(move |_| { + let window = self.objc2_nswindow(); + window.setCollectionBehavior( + window.collectionBehavior() | NSWindowCollectionBehavior::FullScreenNone, + ); + }); + } +} diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index fa07c64bc4..fe60eb4c0a 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -7,6 +7,7 @@ use scap_targets::{Display, DisplayId}; use serde::Deserialize; use specta::Type; use std::{ + f64, ops::Deref, path::PathBuf, str::FromStr, @@ -29,6 +30,9 @@ use crate::{ window_exclusion::WindowExclusion, }; +#[cfg(target_os = "macos")] +use crate::platform::{self, WebviewWindowExt}; + #[cfg(target_os = "macos")] const DEFAULT_TRAFFIC_LIGHTS_INSET_WITH_TOOLBAR: LogicalPosition = LogicalPosition::new(20.0, 30.0); @@ -152,10 +156,6 @@ impl CapWindowDef { } #[cfg(target_os = "macos")] - pub const fn has_toolbar(&self) -> bool { - matches!(self, Self::Editor { .. } | Self::Settings { .. }) - } - #[cfg(target_os = "macos")] pub const fn undecorated(&self) -> bool { matches!( @@ -178,12 +178,27 @@ impl CapWindowDef { matches!(self, Self::Settings) } + #[cfg(target_os = "macos")] + pub const fn window_level(&self) -> Option { + use objc2_app_kit::{ + NSMainMenuWindowLevel, NSPopUpMenuWindowLevel, NSScreenSaverWindowLevel, + }; + + match self { + Self::RecordingControls => Some(NSMainMenuWindowLevel), + Self::TargetSelectOverlay { .. } | Self::CaptureArea => Some(NSPopUpMenuWindowLevel), + Self::RecordingsOverlay | Self::WindowCaptureOccluder { .. } => { + Some(NSScreenSaverWindowLevel) + } + _ => None, + } + } pub const fn min_size(&self) -> Option<(f64, f64)> { Some(match self { Self::Setup => (600.0, 600.0), Self::Main => (300.0, 360.0), Self::Editor { .. } => (1275.0, 800.0), - Self::Settings => (600.0, 450.0), + Self::Settings => (650.0, 450.0), Self::Camera => (200.0, 200.0), Self::Upgrade => (950.0, 850.0), Self::ModeSelect => (900.0, 500.0), @@ -224,6 +239,8 @@ pub enum CapWindow { impl CapWindow { pub async fn show(&self, app: &AppHandle) -> tauri::Result { + use std::fmt::Write; + if let Self::Editor { project_path } = &self { let state = app.state::(); let mut s = state.ids.lock().unwrap(); @@ -242,6 +259,9 @@ impl CapWindow { return Ok(window); } + #[cfg(target_os = "macos")] + let def = self.def(app); + let monitor = app.primary_monitor()?.unwrap(); let window = match self { @@ -265,9 +285,6 @@ impl CapWindow { .map(|s| s.enable_new_recording_flow) .unwrap_or_default(); - let title = CapWindowDef::Main.title(); - let should_protect = should_protect_window(app, &title); - let window = self .window_builder(app, if new_recording_flow { "/new-main" } else { "/" }) .resizable(false) @@ -276,7 +293,6 @@ impl CapWindow { .minimizable(false) .always_on_top(true) .visible_on_all_workspaces(true) - .content_protected(should_protect) .center() .initialization_script(format!( " @@ -288,13 +304,15 @@ impl CapWindow { )) .build()?; - if new_recording_flow { - #[cfg(target_os = "macos")] - crate::platform::set_window_level(window.as_ref().window(), 50); - } - #[cfg(target_os = "macos")] { + if new_recording_flow { + _ = window.run_on_main_thread({ + let window = window.clone(); + move || window.objc2_nswindow().setLevel(110) + }); + } + let app_handle = app.clone(); tauri::async_runtime::spawn(async move { let prewarmer = @@ -317,14 +335,7 @@ impl CapWindow { .map(|d| d.id()) == Some(display.id()); - let title = CapWindowDef::TargetSelectOverlay { - display_id: display_id.clone(), - } - .title() - .to_string(); - let should_protect = should_protect_window(app, &title); - - let mut window_builder = self + let mut builder = self .window_builder( app, format!("/target-select-overlay?displayId={display_id}&isHoveredDisplay={is_hovered_display}"), @@ -333,29 +344,27 @@ impl CapWindow { .resizable(false) .fullscreen(false) .shadow(false) - .content_protected(should_protect) .always_on_top(true) .visible_on_all_workspaces(true) .skip_taskbar(true) - .transparent(true) - .visible(false); + .transparent(true); #[cfg(target_os = "macos")] { let position = display.raw_handle().logical_position(); let size = display.logical_size().unwrap(); - window_builder = window_builder + builder = builder .inner_size(size.width(), size.height()) .position(position.x(), position.y()); } #[cfg(windows)] { - window_builder = window_builder.inner_size(100.0, 100.0).position(0.0, 0.0); + builder = window_builder.inner_size(100.0, 100.0).position(0.0, 0.0); } - let window = window_builder.build()?; + let window = builder.build()?; #[cfg(windows)] { @@ -383,11 +392,6 @@ impl CapWindow { app.state::() .spawn(display_id, window.clone()); - #[cfg(target_os = "macos")] - { - crate::platform::set_window_level(window.as_ref().window(), 45); - } - window } Self::Settings { page } => { @@ -405,16 +409,23 @@ impl CapWindow { } } - self.window_builder( - app, - format!("/settings/{}", page.clone().unwrap_or_default()), - ) - .resizable(true) - .maximized(false) - .center() - .build()? + let mut builder = self + .window_builder( + app, + format!("/settings/{}", page.clone().unwrap_or_default()), + ) + .resizable(true) + .maximized(false) + .center(); + + #[cfg(target_os = "macos")] + { + builder = builder.max_inner_size(650.0, f64::MAX); + } + + builder.build()? } - Self::Editor { .. } => { + Self::Editor { project_path } => { if let Some(main) = CapWindowDef::Main.get(app) { let _ = main.close(); }; @@ -431,16 +442,14 @@ impl CapWindow { let _ = main.hide(); } - let mut builder = self - .window_builder(app, "/upgrade") + self.window_builder(app, "/upgrade") .resizable(false) .focused(true) .always_on_top(true) .maximized(false) .shadow(true) - .center(); - - builder.build()? + .center() + .build()? } Self::ModeSelect => { // Hide main window when mode select window opens @@ -448,8 +457,7 @@ impl CapWindow { let _ = main.hide(); } - let mut builder = self - .window_builder(app, "/mode-select") + self.window_builder(app, "/mode-select") .inner_size(900.0, 500.0) .min_inner_size(900.0, 500.0) .resizable(true) @@ -457,9 +465,8 @@ impl CapWindow { .maximizable(false) .center() .focused(true) - .shadow(true); - - builder.build()? + .shadow(true) + .build()? } Self::Camera => { const WINDOW_SIZE: f64 = 230.0 * 2.0; @@ -484,7 +491,7 @@ impl CapWindow { .into()); } - let mut window_builder = self + let mut builder = self .window_builder(app, "/camera") .maximized(false) .resizable(false) @@ -509,7 +516,7 @@ impl CapWindow { .transparent(true) .visible(false); // We set this true in `CameraWindowState::init_window` - let window = window_builder.build()?; + let window = builder.build()?; if enable_native_camera_preview { let camera_feed = state.camera_feed.clone(); @@ -524,17 +531,13 @@ impl CapWindow { } #[cfg(target_os = "macos")] - { - _ = window.run_on_main_thread({ - let window = window.as_ref().window(); - move || unsafe { - let win = window.ns_window().unwrap() as *const objc2_app_kit::NSWindow; - (*win).setCollectionBehavior( - (*win).collectionBehavior() | objc2_app_kit::NSWindowCollectionBehavior::FullScreenAuxiliary, - ); - } - }); - } + dispatch2::run_on_main(|_| { + let nswindow = window.objc2_nswindow(); + nswindow.setCollectionBehavior( + nswindow.collectionBehavior() + | objc2_app_kit::NSWindowCollectionBehavior::FullScreenAuxiliary, + ); + }); window } @@ -544,13 +547,6 @@ impl CapWindow { return Err(tauri::Error::WindowNotFound); }; - let title = CapWindowDef::WindowCaptureOccluder { - screen_id: screen_id.clone(), - } - .title() - .to_string(); - let should_protect = should_protect_window(app, &title); - #[cfg(target_os = "macos")] let position = display.raw_handle().logical_position(); @@ -559,7 +555,7 @@ impl CapWindow { let bounds = display.physical_size().unwrap(); - let mut window_builder = self + let mut builder = self .window_builder(app, "/window-capture-occluder") .maximized(false) .resizable(false) @@ -567,35 +563,22 @@ impl CapWindow { .shadow(false) .always_on_top(true) .visible_on_all_workspaces(true) - .content_protected(should_protect) .skip_taskbar(true) .inner_size(bounds.width(), bounds.height()) .position(position.x(), position.y()) .transparent(true); - let window = window_builder.build()?; - + let window = builder.build()?; window.set_ignore_cursor_events(true).unwrap(); - - #[cfg(target_os = "macos")] - { - crate::platform::set_window_level(window.as_ref().window(), 900); - } - window } Self::CaptureArea { screen_id } => { - let title = CapWindowDef::CaptureArea.title(); - let should_protect = should_protect_window(app, &title); - - let mut window_builder = self + let mut builder = self .window_builder(app, "/capture-area") .maximized(false) .fullscreen(false) .shadow(false) - .resizable(false) .always_on_top(true) - .content_protected(should_protect) .skip_taskbar(true) .closable(true) .decorations(false) @@ -607,26 +590,18 @@ impl CapWindow { #[cfg(target_os = "macos")] if let Some(bounds) = display.raw_handle().logical_bounds() { - window_builder = window_builder + builder = builder .inner_size(bounds.size().width(), bounds.size().height()) .position(bounds.position().x(), bounds.position().y()); } #[cfg(windows)] if let Some(bounds) = display.raw_handle().physical_bounds() { - window_builder = window_builder + builder = builder .inner_size(bounds.size().width(), bounds.size().height()) .position(bounds.position().x(), bounds.position().y()); } - let window = window_builder.build()?; - - #[cfg(target_os = "macos")] - crate::platform::set_window_level( - window.as_ref().window(), - objc2_app_kit::NSPopUpMenuWindowLevel, - ); - // Hide the main window if the target monitor is the same if let Some(main_window) = CapWindowDef::Main.get(app) && let (Ok(outer_pos), Ok(outer_size)) = @@ -637,15 +612,12 @@ impl CapWindow { let _ = main_window.minimize(); }; - window + builder.build()? } Self::InProgressRecording { countdown } => { let width = 250.0; let height = 40.0; - let title = CapWindowDef::RecordingControls.title(); - let should_protect = should_protect_window(app, &title); - let window = self .window_builder(app, "/in-progress-recording") .maximized(false) @@ -655,7 +627,6 @@ impl CapWindow { .always_on_top(true) .transparent(true) .visible_on_all_workspaces(true) - .content_protected(should_protect) .inner_size(width, height) .position( ((monitor.size().width as f64) / monitor.scale_factor() - width) / 2.0, @@ -668,17 +639,9 @@ impl CapWindow { )) .build()?; - #[cfg(target_os = "macos")] - { - crate::platform::set_window_level(window.as_ref().window(), 1000); - } - window } Self::RecordingsOverlay => { - let title = CapWindowDef::RecordingsOverlay.title(); - let should_protect = should_protect_window(app, &title); - let window = self .window_builder(app, "/recordings-overlay") .maximized(false) @@ -688,7 +651,6 @@ impl CapWindow { .always_on_top(true) .visible_on_all_workspaces(true) .accept_first_mouse(true) - .content_protected(should_protect) .inner_size( (monitor.size().width as f64) / monitor.scale_factor(), (monitor.size().height as f64) / monitor.scale_factor(), @@ -708,7 +670,7 @@ impl CapWindow { let panel = window.to_panel().unwrap(); - panel.set_level(cocoa::appkit::NSMainMenuWindowLevel); + panel.set_level(objc2_app_kit::NSMainMenuWindowLevel as i32); panel.set_collection_behaviour( NSWindowCollectionBehavior::NSWindowCollectionBehaviorTransient @@ -732,8 +694,21 @@ impl CapWindow { } }; - // removing this for now as it causes windows to just stay hidden sometimes -_- - // window.hide().ok(); + #[cfg(target_os = "macos")] + { + if def.disables_window_buttons() { + window.set_window_buttons_visible(false); + } + + if def.disables_fullscreen() { + window.disable_fullscreen(); + } + + if let Some(level) = def.window_level() { + window.set_level(level); + } + } + Ok(window) } @@ -743,12 +718,14 @@ impl CapWindow { url: impl Into, ) -> WebviewWindowBuilder<'a, Wry, AppHandle> { let def = self.def(app); + let should_protect = should_protect_window(app, def.title()); let mut builder = WebviewWindow::builder(app, def.label(), WebviewUrl::App(url.into())) .title(def.title()) .visible(false) .accept_first_mouse(true) - .shadow(true); + .shadow(true) + .content_protected(should_protect); if let Some(min) = def.min_size() { builder = builder @@ -756,6 +733,15 @@ impl CapWindow { .min_inner_size(min.0, min.1); } + #[cfg(target_os = "macos")] + if def.undecorated() { + builder = builder.decorations(false); + } else { + builder = builder + .hidden_title(true) + .title_bar_style(tauri::TitleBarStyle::Overlay); + } + #[cfg(windows)] { builder = builder.decorations(false); @@ -900,7 +886,6 @@ impl MonitorExt for Display { #[specta::specta] #[tauri::command(async)] -#[instrument(skip(_window))] pub fn set_window_transparent(_window: tauri::Window, _value: bool) { #[cfg(target_os = "macos")] { From c0e57246e06f0ff64b588120ee9b134eb5f64f96 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Mon, 17 Nov 2025 02:36:19 +0330 Subject: [PATCH 06/48] Use tauri window dispatch for calling AppKit on main instead of dispatch --- .../src-tauri/src/platform/macos/mod.rs | 42 +++++-------------- apps/desktop/src-tauri/src/windows.rs | 39 ++++++++++++----- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/apps/desktop/src-tauri/src/platform/macos/mod.rs b/apps/desktop/src-tauri/src/platform/macos/mod.rs index 2d3e71ec14..b75905238d 100644 --- a/apps/desktop/src-tauri/src/platform/macos/mod.rs +++ b/apps/desktop/src-tauri/src/platform/macos/mod.rs @@ -1,5 +1,4 @@ use dispatch2::run_on_main; -use objc2::{MainThreadMarker, MainThreadOnly}; use objc2_app_kit::{NSWindow, NSWindowButton, NSWindowCollectionBehavior, NSWindowLevel}; use tauri::WebviewWindow; @@ -10,11 +9,7 @@ pub use sc_shareable_content::*; pub trait WebviewWindowExt { fn objc2_nswindow(&self) -> &NSWindow; - fn set_window_buttons_visible(&self, visible: bool); - - fn set_level(&self, level: NSWindowLevel); - - fn disable_fullscreen(&self); + fn set_traffic_lights_visible(&self, visible: bool); } impl WebviewWindowExt for WebviewWindow { @@ -29,31 +24,16 @@ impl WebviewWindowExt for WebviewWindow { } } - fn set_window_buttons_visible(&self, visible: bool) { - run_on_main(move |_| { - let nswindow = self.objc2_nswindow(); - for btn in [ - NSWindowButton::CloseButton, - NSWindowButton::MiniaturizeButton, - NSWindowButton::ZoomButton, - ] { - if let Some(btn) = nswindow.standardWindowButton(btn) { - btn.setHidden(!visible); - } + fn set_traffic_lights_visible(&self, visible: bool) { + let nswindow = self.objc2_nswindow(); + for btn in [ + NSWindowButton::CloseButton, + NSWindowButton::MiniaturizeButton, + NSWindowButton::ZoomButton, + ] { + if let Some(btn) = nswindow.standardWindowButton(btn) { + btn.setHidden(!visible); } - }); - } - - fn set_level(&self, level: NSWindowLevel) { - run_on_main(move |_| self.objc2_nswindow().setLevel(level)); - } - - fn disable_fullscreen(&self) { - run_on_main(move |_| { - let window = self.objc2_nswindow(); - window.setCollectionBehavior( - window.collectionBehavior() | NSWindowCollectionBehavior::FullScreenNone, - ); - }); + } } } diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index fe60eb4c0a..e2f65ea586 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -150,6 +150,14 @@ impl CapWindowDef { ) } + #[cfg(target_os = "macos")] + pub const fn pre_solarium_traffic_lights_position(&self) -> LogicalPosition { + match self { + Self::Editor { .. } => LogicalPosition::new(20.0, 32.0), + _ => LogicalPosition::new(12.0, 20.0), + } + } + pub fn get(&self, app: &AppHandle) -> Option { let label = self.label(); app.get_webview_window(&label) @@ -695,19 +703,27 @@ impl CapWindow { }; #[cfg(target_os = "macos")] - { - if def.disables_window_buttons() { - window.set_window_buttons_visible(false); - } + let _ = window.run_on_main_thread({ + let window = window.clone(); + move || { + if def.disables_window_buttons() { + window.set_traffic_lights_visible(false); + } - if def.disables_fullscreen() { - window.disable_fullscreen(); - } + let nswindow = window.objc2_nswindow(); + + if def.disables_fullscreen() { + nswindow.setCollectionBehavior( + nswindow.collectionBehavior() + | objc2_app_kit::NSWindowCollectionBehavior::FullScreenNone, + ); + } - if let Some(level) = def.window_level() { - window.set_level(level); + if let Some(level) = def.window_level() { + nswindow.setLevel(level) + } } - } + }); Ok(window) } @@ -739,7 +755,8 @@ impl CapWindow { } else { builder = builder .hidden_title(true) - .title_bar_style(tauri::TitleBarStyle::Overlay); + .title_bar_style(tauri::TitleBarStyle::Overlay) + .traffic_light_position(def.pre_solarium_traffic_lights_position()); } #[cfg(windows)] From 3639093f835117600e6a4af56bc2943e7ae357e3 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Mon, 17 Nov 2025 02:53:33 +0330 Subject: [PATCH 07/48] macOS: Note recent documents --- apps/desktop/src-tauri/src/platform/macos/mod.rs | 13 ++++++++++++- apps/desktop/src-tauri/src/platform/mod.rs | 4 +++- apps/desktop/src-tauri/src/windows.rs | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src-tauri/src/platform/macos/mod.rs b/apps/desktop/src-tauri/src/platform/macos/mod.rs index b75905238d..99b61d2533 100644 --- a/apps/desktop/src-tauri/src/platform/macos/mod.rs +++ b/apps/desktop/src-tauri/src/platform/macos/mod.rs @@ -1,5 +1,8 @@ +use std::path::Path; + use dispatch2::run_on_main; -use objc2_app_kit::{NSWindow, NSWindowButton, NSWindowCollectionBehavior, NSWindowLevel}; +use objc2_app_kit::{NSDocumentController, NSWindow, NSWindowButton}; +use objc2_foundation::NSURL; use tauri::WebviewWindow; mod sc_shareable_content; @@ -37,3 +40,11 @@ impl WebviewWindowExt for WebviewWindow { } } } + +pub fn add_recent_document>(path: P) { + if let Some(url) = NSURL::from_file_path(path) { + run_on_main(move |mtm| { + NSDocumentController::sharedDocumentController(mtm).noteNewRecentDocumentURL(&url) + }) + } +} diff --git a/apps/desktop/src-tauri/src/platform/mod.rs b/apps/desktop/src-tauri/src/platform/mod.rs index e51d3e709a..0a29cdc827 100644 --- a/apps/desktop/src-tauri/src/platform/mod.rs +++ b/apps/desktop/src-tauri/src/platform/mod.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use serde::{Deserialize, Serialize}; use specta::Type; #[cfg(target_os = "windows")] @@ -38,7 +40,7 @@ pub fn perform_haptic_feedback( _time: Option, ) -> Result<(), String> { #[cfg(target_os = "macos")] - unsafe { + { use objc2_app_kit::{ NSHapticFeedbackManager, NSHapticFeedbackPattern, NSHapticFeedbackPerformanceTime, NSHapticFeedbackPerformer, diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index e2f65ea586..c95a486ff6 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -438,6 +438,9 @@ impl CapWindow { let _ = main.close(); }; + #[cfg(target_os = "macos")] + platform::add_recent_document(project_path); + self.window_builder(app, "/editor") .maximizable(true) .inner_size(1240.0, 800.0) From 5ce30accac531e7ed27d12c4e8d982176a01e4db Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Mon, 17 Nov 2025 06:17:20 +0330 Subject: [PATCH 08/48] CapThumbnailProvider macOS Extension crate --- Cargo.lock | 30 ++++++++++++++- crates/cap-quicklook-thumbnailing/Cargo.toml | 13 +++++++ crates/cap-quicklook-thumbnailing/src/main.rs | 6 +++ .../src/provider.rs | 37 +++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 crates/cap-quicklook-thumbnailing/Cargo.toml create mode 100644 crates/cap-quicklook-thumbnailing/src/main.rs create mode 100644 crates/cap-quicklook-thumbnailing/src/provider.rs diff --git a/Cargo.lock b/Cargo.lock index 8146881a22..4252592608 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1473,6 +1473,16 @@ dependencies = [ "workspace-hack", ] +[[package]] +name = "cap-quicklook-thumbnailing" +version = "0.1.0" +dependencies = [ + "block2 0.6.2", + "objc2 0.6.2", + "objc2-foundation 0.3.2", + "objc2-quick-look-thumbnailing", +] + [[package]] name = "cap-recording" version = "0.1.0" @@ -5934,6 +5944,22 @@ dependencies = [ "objc2-foundation 0.3.2", ] +[[package]] +name = "objc2-quick-look-thumbnailing" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8e00da1ca87ffe3ea8d20981026f013df91072a140432f0f88da9a356d9b3c" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "objc2 0.6.2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "objc2-ui-kit", +] + [[package]] name = "objc2-security" version = "0.3.2" @@ -5947,9 +5973,9 @@ dependencies = [ [[package]] name = "objc2-ui-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", diff --git a/crates/cap-quicklook-thumbnailing/Cargo.toml b/crates/cap-quicklook-thumbnailing/Cargo.toml new file mode 100644 index 0000000000..1b00ad4410 --- /dev/null +++ b/crates/cap-quicklook-thumbnailing/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cap-quicklook-thumbnailing" +version = "0.1.0" +edition = "2024" + +[target.'cfg(target_os = "macos")'.dependencies] +objc2.workspace = true +block2 = "0.6.2" +objc2-foundation = "0.3.2" +objc2-quick-look-thumbnailing = "0.3.2" + +[lints] +workspace = true diff --git a/crates/cap-quicklook-thumbnailing/src/main.rs b/crates/cap-quicklook-thumbnailing/src/main.rs new file mode 100644 index 0000000000..f1821ef932 --- /dev/null +++ b/crates/cap-quicklook-thumbnailing/src/main.rs @@ -0,0 +1,6 @@ +#[cfg(target_os = "macos")] +mod provider; + +fn main() { + println!("") +} diff --git a/crates/cap-quicklook-thumbnailing/src/provider.rs b/crates/cap-quicklook-thumbnailing/src/provider.rs new file mode 100644 index 0000000000..212cf61aa7 --- /dev/null +++ b/crates/cap-quicklook-thumbnailing/src/provider.rs @@ -0,0 +1,37 @@ +use objc2::define_class; + +use objc2::rc::Retained; +use objc2_foundation::NSError; +use objc2_foundation::NSObjectProtocol; +use objc2_foundation::ns_string; +use objc2_quick_look_thumbnailing::{ + QLFileThumbnailRequest, QLThumbnailProvider, QLThumbnailReply, +}; + +define_class! { + #[unsafe(super(QLThumbnailProvider))] + struct CapThumbnailProvider; + + unsafe impl NSObjectProtocol for CapThumbnailProvider {} + + impl CapThumbnailProvider { + #[unsafe(method(provideThumbnailForFileRequest:completionHandler:))] + unsafe fn provide( + &self, + request: &QLFileThumbnailRequest, + handler: &block2::Block + ) { + let path = unsafe { request.fileURL() }.URLByAppendingPathComponent( + ns_string!("/screenshots/display.jpg") + ); + + if let Some(path) = path { + unsafe { + let reply = QLThumbnailReply::replyWithImageFileURL(&path); + reply.setExtensionBadge(ns_string!("Cap")); + handler.call((Retained::into_raw(reply), std::ptr::null_mut())); + } + } + } + } +} From cf7be04cae3ff1f445f56535d662bd8e75085af5 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Wed, 19 Nov 2025 23:23:46 +0330 Subject: [PATCH 09/48] Revert "CapThumbnailProvider macOS Extension crate" This reverts commit 5ce30accac531e7ed27d12c4e8d982176a01e4db. --- Cargo.lock | 30 +-------------- crates/cap-quicklook-thumbnailing/Cargo.toml | 13 ------- crates/cap-quicklook-thumbnailing/src/main.rs | 6 --- .../src/provider.rs | 37 ------------------- 4 files changed, 2 insertions(+), 84 deletions(-) delete mode 100644 crates/cap-quicklook-thumbnailing/Cargo.toml delete mode 100644 crates/cap-quicklook-thumbnailing/src/main.rs delete mode 100644 crates/cap-quicklook-thumbnailing/src/provider.rs diff --git a/Cargo.lock b/Cargo.lock index 0412382455..0d504f22f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1473,16 +1473,6 @@ dependencies = [ "workspace-hack", ] -[[package]] -name = "cap-quicklook-thumbnailing" -version = "0.1.0" -dependencies = [ - "block2 0.6.2", - "objc2 0.6.2", - "objc2-foundation 0.3.2", - "objc2-quick-look-thumbnailing", -] - [[package]] name = "cap-recording" version = "0.1.0" @@ -5944,22 +5934,6 @@ dependencies = [ "objc2-foundation 0.3.2", ] -[[package]] -name = "objc2-quick-look-thumbnailing" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8e00da1ca87ffe3ea8d20981026f013df91072a140432f0f88da9a356d9b3c" -dependencies = [ - "bitflags 2.9.4", - "block2 0.6.2", - "objc2 0.6.2", - "objc2-app-kit", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.2", - "objc2-ui-kit", -] - [[package]] name = "objc2-security" version = "0.3.2" @@ -5973,9 +5947,9 @@ dependencies = [ [[package]] name = "objc2-ui-kit" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" dependencies = [ "bitflags 2.9.4", "objc2 0.6.2", diff --git a/crates/cap-quicklook-thumbnailing/Cargo.toml b/crates/cap-quicklook-thumbnailing/Cargo.toml deleted file mode 100644 index 1b00ad4410..0000000000 --- a/crates/cap-quicklook-thumbnailing/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "cap-quicklook-thumbnailing" -version = "0.1.0" -edition = "2024" - -[target.'cfg(target_os = "macos")'.dependencies] -objc2.workspace = true -block2 = "0.6.2" -objc2-foundation = "0.3.2" -objc2-quick-look-thumbnailing = "0.3.2" - -[lints] -workspace = true diff --git a/crates/cap-quicklook-thumbnailing/src/main.rs b/crates/cap-quicklook-thumbnailing/src/main.rs deleted file mode 100644 index f1821ef932..0000000000 --- a/crates/cap-quicklook-thumbnailing/src/main.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[cfg(target_os = "macos")] -mod provider; - -fn main() { - println!("") -} diff --git a/crates/cap-quicklook-thumbnailing/src/provider.rs b/crates/cap-quicklook-thumbnailing/src/provider.rs deleted file mode 100644 index 212cf61aa7..0000000000 --- a/crates/cap-quicklook-thumbnailing/src/provider.rs +++ /dev/null @@ -1,37 +0,0 @@ -use objc2::define_class; - -use objc2::rc::Retained; -use objc2_foundation::NSError; -use objc2_foundation::NSObjectProtocol; -use objc2_foundation::ns_string; -use objc2_quick_look_thumbnailing::{ - QLFileThumbnailRequest, QLThumbnailProvider, QLThumbnailReply, -}; - -define_class! { - #[unsafe(super(QLThumbnailProvider))] - struct CapThumbnailProvider; - - unsafe impl NSObjectProtocol for CapThumbnailProvider {} - - impl CapThumbnailProvider { - #[unsafe(method(provideThumbnailForFileRequest:completionHandler:))] - unsafe fn provide( - &self, - request: &QLFileThumbnailRequest, - handler: &block2::Block - ) { - let path = unsafe { request.fileURL() }.URLByAppendingPathComponent( - ns_string!("/screenshots/display.jpg") - ); - - if let Some(path) = path { - unsafe { - let reply = QLThumbnailReply::replyWithImageFileURL(&path); - reply.setExtensionBadge(ns_string!("Cap")); - handler.call((Retained::into_raw(reply), std::ptr::null_mut())); - } - } - } - } -} From 3aa29054626f4c67ab3ff48b376d5929d278012c Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:28:10 +0330 Subject: [PATCH 10/48] Add more associated file info like UTTypeConformsTo and UTTypeIdentifier. --- apps/desktop/src-tauri/tauri.conf.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 5f2a676ebd..76d6e5a4a8 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -84,7 +84,13 @@ "ext": ["cap"], "name": "Cap Project", "mimeType": "application/x-cap-project", - "role": "Editor" + "role": "Editor", + "rank": "Owner", + "description": "Cap Project", + "exportedType": { + "identifier": "so.cap.desktop.project", + "conformsTo": ["com.apple.package"] + } } ] } From cd6e23ef2ad351f707df60a13e5864473d4f8ef1 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 20 Nov 2025 03:35:18 +0330 Subject: [PATCH 11/48] fix after branch update --- .../desktop/src-tauri/src/deeplink_actions.rs | 4 +- .../src-tauri/src/target_select_overlay.rs | 10 ++--- apps/desktop/src-tauri/src/tray.rs | 6 +-- apps/desktop/src-tauri/src/windows.rs | 42 ------------------- 4 files changed, 10 insertions(+), 52 deletions(-) diff --git a/apps/desktop/src-tauri/src/deeplink_actions.rs b/apps/desktop/src-tauri/src/deeplink_actions.rs index dbd90f667f..240205c982 100644 --- a/apps/desktop/src-tauri/src/deeplink_actions.rs +++ b/apps/desktop/src-tauri/src/deeplink_actions.rs @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf}; use tauri::{AppHandle, Manager, Url}; use tracing::trace; -use crate::{App, ArcLock, recording::StartRecordingInputs, windows::ShowCapWindow}; +use crate::{App, ArcLock, recording::StartRecordingInputs, windows::CapWindow}; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] @@ -150,7 +150,7 @@ impl DeepLinkAction { crate::open_project_from_path(Path::new(&project_path), app.clone()) } DeepLinkAction::OpenSettings { page } => { - crate::show_window(app.clone(), ShowCapWindow::Settings { page }).await + crate::show_window(app.clone(), CapWindow::Settings { page }).await } } } diff --git a/apps/desktop/src-tauri/src/target_select_overlay.rs b/apps/desktop/src-tauri/src/target_select_overlay.rs index d52424235e..cee6bb2787 100644 --- a/apps/desktop/src-tauri/src/target_select_overlay.rs +++ b/apps/desktop/src-tauri/src/target_select_overlay.rs @@ -11,7 +11,7 @@ use cap_recording::screen_capture::ScreenCaptureTarget; use crate::{ general_settings, window_exclusion::WindowExclusion, - windows::{CapWindowId, ShowCapWindow}, + windows::{CapWindow, CapWindowDef}, }; use scap_targets::{ Display, DisplayId, Window, WindowId, @@ -58,7 +58,7 @@ pub async fn open_target_select_overlays( .map(|d| d.id()) .collect::>(); for display_id in displays { - let _ = ShowCapWindow::TargetSelectOverlay { display_id } + let _ = CapWindow::TargetSelectOverlay { display_id } .show(&app) .await; } @@ -183,7 +183,7 @@ pub async fn update_camera_overlay_bounds( #[instrument(skip(app))] pub async fn close_target_select_overlays(app: AppHandle) -> Result<(), String> { for (id, window) in app.webview_windows() { - if let Ok(CapWindowId::TargetSelectOverlay { .. }) = CapWindowId::from_str(&id) { + if let Ok(CapWindowDef::TargetSelectOverlay { .. }) = CapWindowDef::from_str(&id) { let _ = window.close(); } } @@ -295,8 +295,8 @@ impl WindowFocusManager { tokio::spawn(async move { let app = window.app_handle(); loop { - let cap_main = CapWindowId::Main.get(app); - let cap_settings = CapWindowId::Settings.get(app); + let cap_main = CapWindowDef::Main.get(app); + let cap_settings = CapWindowDef::Settings.get(app); let main_window_available = cap_main.is_some(); let settings_window_available = cap_settings.is_some(); diff --git a/apps/desktop/src-tauri/src/tray.rs b/apps/desktop/src-tauri/src/tray.rs index c7268e5bb4..a8dc0f20bf 100644 --- a/apps/desktop/src-tauri/src/tray.rs +++ b/apps/desktop/src-tauri/src/tray.rs @@ -1,6 +1,6 @@ use crate::{ RecordingStarted, RecordingStopped, RequestOpenRecordingPicker, RequestOpenSettings, recording, - recording_settings::RecordingTargetMode, windows::ShowCapWindow, + recording_settings::RecordingTargetMode, windows::CapWindow, }; use std::sync::{ @@ -134,7 +134,7 @@ pub fn create_tray(app: &AppHandle) -> tauri::Result<()> { Ok(TrayItem::OpenCap) => { let app = app.clone(); tokio::spawn(async move { - let _ = ShowCapWindow::Main { + let _ = CapWindow::Main { init_target_mode: None, } .show(&app) @@ -174,7 +174,7 @@ pub fn create_tray(app: &AppHandle) -> tauri::Result<()> { Ok(TrayItem::OpenSettings) => { let app = app.clone(); tokio::spawn( - async move { ShowCapWindow::Settings { page: None }.show(&app).await }, + async move { CapWindow::Settings { page: None }.show(&app).await }, ); } Ok(TrayItem::UploadLogs) => { diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 73a90edb9a..67249452f0 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -806,48 +806,6 @@ impl CapWindow { } } -fn restore_recording_inputs_if_idle(app: &AppHandle) { - let settings = match RecordingSettingsStore::get(app) { - Ok(Some(settings)) => settings, - Ok(None) => return, - Err(err) => { - warn!(%err, "Failed to load recording settings while restoring inputs"); - return; - } - }; - - let mic_name = settings.mic_name.clone(); - let camera_id = settings.camera_id.clone(); - - if mic_name.is_none() && camera_id.is_none() { - return; - } - - let app_handle = app.clone(); - let state = app_handle.state::>(); - let app_state = state.inner().clone(); - - tauri::async_runtime::spawn(async move { - if app_state.read().await.is_recording_active_or_pending() { - return; - } - - if let Some(mic) = mic_name { - match apply_mic_input(app_handle.state(), Some(mic)).await { - Err(err) => warn!(%err, "Failed to restore microphone input"), - Ok(_) => {} - } - } - - if let Some(camera) = camera_id { - match apply_camera_input(app_handle.clone(), app_handle.state(), Some(camera)).await { - Err(err) => warn!(%err, "Failed to restore camera input"), - Ok(_) => {} - } - } - }); -} - #[tauri::command] #[specta::specta] #[instrument(skip(window))] From ff91c460f576293cc74e9336cc812970cad1a54c Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 20 Nov 2025 22:20:31 +0330 Subject: [PATCH 12/48] Add xcode project for plugins --- Cargo.toml | 11 +- apps/desktop/src-tauri/tauri.conf.json | 5 +- macos/.gitignore | 62 ++++ .../CapExtras.xcodeproj/project.pbxproj | 349 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 17443 bytes .../xcschemes/xcschememanagement.plist | 14 + .../Cap_QuickLook_Thumbnail_Provider.swift | 18 + .../CapQLThumbnailProvider/Info.plist | 22 ++ 9 files changed, 482 insertions(+), 6 deletions(-) create mode 100644 macos/.gitignore create mode 100644 macos/CapExtras/CapExtras.xcodeproj/project.pbxproj create mode 100644 macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/xcuserdata/ilya.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift create mode 100644 macos/CapExtras/CapQLThumbnailProvider/Info.plist diff --git a/Cargo.toml b/Cargo.toml index ecd080fa3c..bb6c92519c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,11 +88,12 @@ manual_clamp = "deny" # Optimize for smaller binary size [profile.release] -panic = "abort" # Strip expensive panic clean-up logic -codegen-units = 1 # Compile crates one after another so the compiler can optimize better -lto = true # Enables link to optimizations -opt-level = "s" # Optimize for binary size -debug = true +codegen-units = 8 # Compile crates one after another so the compiler can optimize better +# panic = "abort" # Strip expensive panic clean-up logic +# codegen-units = 1 # Compile crates one after another so the compiler can optimize better +# lto = true # Enables link to optimizations +# opt-level = "s" # Optimize for binary size +# debug = true [patch.crates-io] # screencapturekit = { git = "https://github.com/CapSoftware/screencapturekit-rs", rev = "7ff1e103742e56c8f6c2e940b5e52684ed0bed69" } # branch = "cap-main" diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 76d6e5a4a8..618e73e5e0 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -65,7 +65,10 @@ "y": 140 } }, - "frameworks": ["../../../target/native-deps/Spacedrive.framework"] + "frameworks": ["../../../target/native-deps/Spacedrive.framework"], + "files": { + "PlugIns/*": "../../../macos/build/PlugIns/" + } }, "windows": { "nsis": { diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000000..52fe2f7102 --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,62 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output diff --git a/macos/CapExtras/CapExtras.xcodeproj/project.pbxproj b/macos/CapExtras/CapExtras.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..892bdad48e --- /dev/null +++ b/macos/CapExtras/CapExtras.xcodeproj/project.pbxproj @@ -0,0 +1,349 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 092CA65A2ECE775100C695FA /* QuickLookThumbnailing.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 092CA6592ECE775100C695FA /* QuickLookThumbnailing.framework */; }; + 092CA65C2ECE775100C695FA /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 092CA65B2ECE775100C695FA /* Quartz.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 092CA6572ECE775100C695FA /* CapQLThumbnailProvider.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = CapQLThumbnailProvider.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 092CA6592ECE775100C695FA /* QuickLookThumbnailing.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLookThumbnailing.framework; path = System/Library/Frameworks/QuickLookThumbnailing.framework; sourceTree = SDKROOT; }; + 092CA65B2ECE775100C695FA /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 092CA65D2ECE775100C695FA /* CapQLThumbnailProvider */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = CapQLThumbnailProvider; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 092CA6542ECE775100C695FA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 092CA65A2ECE775100C695FA /* QuickLookThumbnailing.framework in Frameworks */, + 092CA65C2ECE775100C695FA /* Quartz.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 092CA6582ECE775100C695FA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 092CA6592ECE775100C695FA /* QuickLookThumbnailing.framework */, + 092CA65B2ECE775100C695FA /* Quartz.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 09E0880D2ECE5B440097252E = { + isa = PBXGroup; + children = ( + 092CA65D2ECE775100C695FA /* CapQLThumbnailProvider */, + 092CA6582ECE775100C695FA /* Frameworks */, + 09E088172ECE5B440097252E /* Products */, + ); + sourceTree = ""; + }; + 09E088172ECE5B440097252E /* Products */ = { + isa = PBXGroup; + children = ( + 092CA6572ECE775100C695FA /* CapQLThumbnailProvider.appex */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 092CA6562ECE775100C695FA /* CapQLThumbnailProvider */ = { + isa = PBXNativeTarget; + buildConfigurationList = 092CA6642ECE775100C695FA /* Build configuration list for PBXNativeTarget "CapQLThumbnailProvider" */; + buildPhases = ( + 092CA6532ECE775100C695FA /* Sources */, + 092CA6542ECE775100C695FA /* Frameworks */, + 092CA6552ECE775100C695FA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 092CA65D2ECE775100C695FA /* CapQLThumbnailProvider */, + ); + name = CapQLThumbnailProvider; + packageProductDependencies = ( + ); + productName = CapQLThumbnailProvider; + productReference = 092CA6572ECE775100C695FA /* CapQLThumbnailProvider.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 09E0880E2ECE5B440097252E /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 2610; + LastUpgradeCheck = 2610; + TargetAttributes = { + 092CA6562ECE775100C695FA = { + CreatedOnToolsVersion = 26.1.1; + }; + }; + }; + buildConfigurationList = 09E088112ECE5B440097252E /* Build configuration list for PBXProject "CapExtras" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 09E0880D2ECE5B440097252E; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 09E088172ECE5B440097252E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 092CA6562ECE775100C695FA /* CapQLThumbnailProvider */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 092CA6552ECE775100C695FA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 092CA6532ECE775100C695FA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 092CA6612ECE775100C695FA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = CapQLThumbnailProvider/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = CapQLThumbnailProvider; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = so.cap.desktop.CapQLThumbnailProvider; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 092CA6622ECE775100C695FA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + ENABLE_APP_SANDBOX = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = CapQLThumbnailProvider/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = CapQLThumbnailProvider; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = so.cap.desktop.CapQLThumbnailProvider; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 09E088182ECE5B440097252E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 26.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 09E088192ECE5B440097252E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 26.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 092CA6642ECE775100C695FA /* Build configuration list for PBXNativeTarget "CapQLThumbnailProvider" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 092CA6612ECE775100C695FA /* Debug */, + 092CA6622ECE775100C695FA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 09E088112ECE5B440097252E /* Build configuration list for PBXProject "CapExtras" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 09E088182ECE5B440097252E /* Debug */, + 09E088192ECE5B440097252E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 09E0880E2ECE5B440097252E /* Project object */; +} diff --git a/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..919434a625 --- /dev/null +++ b/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/xcuserdata/ilya.xcuserdatad/UserInterfaceState.xcuserstate b/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/xcuserdata/ilya.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..c7a384d3e3b98a7d0cba0b6b9b47a7dc20eea7ac GIT binary patch literal 17443 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%0DLHOaW*0@K5kh3RolHoPSSDpXQ%ClbAlwzre&a zTfkaTOn37;VWnR_eWjPBEqT)C87q5W!~+hL{n1n=D*USe``YQSxd&ZOo%>m3+5Nve zhdsZw=5v4zj`dA`Hyi6){2~G8f;{x_7bBP$B?N7nzX(9^mG}7%rA7ZhT=e{bi++|@ zKI0EV&m8|be}MmjKgfT{AL73fuwKAM0T&9`EMTjE?E)@d!yn;~^2hkE`EU4d`R@em z5b#g|4-@b?0v;~l5duDUu*>|Bxhnx1oQm-ajbO4_ENyg)2ErH=VA!f@Y<0EI?YmKE zFSgn%tY*8h%34`uv=vo2jAg~vGGnRTYA!K3%vHr@p&`}Br2wVMg`gx?e?M~XqYUql^AX1R)?|F zVKp0VrKQ#qh=0uvQ^f!(gh*5@|BOm0AhJVWrm>>Dve;-dmz5dIDs7d<@(OE7MG3Ul z6jc@vq%uUJV*6)QilMe=0gjFKa*B2f;C7fA|%8YHWM1|iZ&`rsQ`1X_XzLgbL#!8de7Klnxg zDI9#mLTu1iNI>~Yy9wxD8FVc`3dXirq;18&sR)DHCqu!!q8R9Sb_CfRK}JIA!tQmG zQUO=?8e&ob36BUF?4Ka#kuhKZNi{j2j27@H0iP$}>Xl?H8Al+5fZzf?>zKV|8Q*E; zFsZub7yCKwX98eVG1#7M9$YRf>ylm+-(xMyry(8;&jNiJZ!Kx`wKB_hN8*H~Nv9xM8G(ny-Xx3fme9?}TDU3|k$ zE)Y|eb$`ZP4Uj<|W|O%R4|5m~H9e%2vGHJ|*(6>&3G6b%;gR01K1oPcl1{QfY-p9P zp(-fS1DEnosRYM)5xE$|h%6RxeK)y8zzuA8|BPR88ZYae#`TpgfTeF5uOv64#C7B< zay7YzTuZJa*OME_jpQZ)Lu5Kdz_6|mmrfV(3<1v+uv5SntV20u3Cbq7k=w}~|&MaMgc>p*(_kUfM-GQp_%IOS3>JE>wbs2EtJV%;|dxCJWbGw>k2?2xeWwn z;O%N?@P@rX=of(o4(UN{#b~jIiS1Uz5B7xr!XkR9Y@sDF_c$xCFXfaeL= zCt&|d@(S5SHVZf);7%AL8yYh^gGVrkG&CG~ed3M->$mzFz%uB;sC7eIqjZ8G|L>tC z8sZL*W~3CwqX`+o71~4go{9PQ$v*OdfENgOp@6%nPIK;e(yL7KJ&+S6k5P%#r3HCS1Xe;D9z4l(Mb%TCqc{zM3H^gZyWAZeG6b zOy>c53H9Xb`_2IXtg&G5IRT>{Zko)X=>rA^4R)-{smB7%Cug`1C;4Jf3ZzQ;a9*z% zRl^y*32?e&CY+a;ivrNKel@xln#OO0lX%O~8aQ|ND0J#RiMBw;?hDXwy9dtPvF`P6 z;hf!ZEQ9VwHP%A=U?DES!=dMFEOeQ*;5pLp`+C`}y%N>?g~8ZDpD=71lLO?78GZhO zwTrBTTL;l1m;iPa6u?6SDx0f8dk&K$WG6XBz7}=pA_0RB@C*220bjD3e2b2d@5v9) zv3f*+E+DYWf`BiD##JX%tgOG+09KOyk3h@~!zRMtV`4zHfi7l_{sScIbrc~rBYRI1 zNbdc2$uEs)Irh>?@Jn8W0*)4VVToL*3uVA(06r~n$Ow*IW)z}Q1hE2Gpb#Y1iD8M8 zQ5G^FGeDdR%iDmaqnU6luY+FbI6jA z+d}RLxhv%Ekb6Uxg=`Gj6tX$wk&wqio(Op=WNXONA#a5o2>CfQA~Y@399j`NA#`f! z^w6217lby3&JAq~^@h$1^@nzb-WB>r=;xs)!f;qbm@G^lrU;7-Q-!65rH5sPX~MK& z=Y-XSdBQFayCrN%*sWo=hb;?R7xr-2vtc{JUJv^!?8mT^VZVm`5q2sZhpWT2;bq|! z;Z;N48?rwlJR&-xB;vk^)e+kwUWj-r;@yb75&I%OiTE_)^N24Z{)~)^92z++a%SY* z$c{)~WFWFD^1{f)k(WfSi98T_Eb^DgKV?Y9$--nqWRbEcS+Q)ItXbxkwa7YT3uTLC zSIVxET_al}>z1vRZI(SF+ar5dwpX@K_Mz-!*?!q)vIDY%vO}`pWq(GYC@zXbg+_%( zMMTM>dy`ly9bmqo3MdM@hSsFQM)TqiG5Ei zG9+w+uh#MVO7w3v=i(3%a6?b9W z;k7{KfG%$1jcF5&ug3iTFPfPy&}g5@Hh4 z5;79960#F=67mvs3B?JHgkcH86V6R2O(;*OOmHX6OSmZE+Jt2Z4<$UGup{B^g!dCZ zNcbq>lZ1l_hY}7a98LH-kxNWTG$#&C9G-Y?Vrk;6#7h%bCq9|@Ug9w&Qp%J%r9oMs zG$}1go3cn*q8zF`M_I3&q@1FhrktU4DqYGs$~L7}IZt`9k}5A%Uaq`BdAIUj9(Z%l9nfRC#_7nKWRQoJ?CeL=An)vv1G)pE5`ovqfYbJTfiySiFET|HCXqV}s7sxMbxslHYHp!y;8!|F%XkE@?l zZ&7bkKcn8ReqOyp{gV1+^#S!k^&#~U^)dA~>hIOZ)jz3!QU9(!mCB`()X>z-)Dfwp zQ+=s-r#_JSeCqzx<7p9T!_&s6%}Vp8ElRs6?cy|=c4^w>X;-G*ns$5IooP$cBhr=W z$?2-})O26^CFw%?W$9O>A4)%w{!{wN^j|X`%6K~C<&0e!uVuWE@m9v}jE^(+XMC1% zAmd=hR~bh#lQYXR7iVtF{4DdE%iQ6eb&;f6vQx9uvoo_NWYg?T+557OYlmoKwFz3KHd(9F8ngvk zlh&dgraezPRy$rhLEE66tevWzu5HrJ(NgVF?P~2B?ON@6?GxH<+Gn)ewJ&OSYIkX0 z)9%xLsQp;GKc^;VMvgPbmD7~-V$SZILpg_Yj^=!w^KH)eIVW;{&iOUxk6e_Skeig7 zlB>>5%gxNq&dtfq%hl%^a|?6F5l5Y(S5Hw zp&z1`>E(KbK31QgPtvF8)%tXOre32r=nM50y-hz{U!||skI|3UPt@1x8}v>3+4{Nq zcD-LeU*Dy_P`^ySRsXX7P5o~DyZZO_`}Lpe59+_tAJHE-AVZuX(U5L17|u168O9sx z43i8~4NgO&q1iCY&}q2TaFyX&!wrTdhT9Bx8kQQ?8Xhz3Fzht!GQ4hh%dp4ro?)Ni zE5lL4H-_&GCk#Iuel`4IIAxR>VmZe8w&m?j3|^9$_rx(n+iJ$eT9L-1%2Rd~4Y zXyM7iUkZOM{M|If6k&=qMVV4eDwEojX40DsCZnm)bdG7bX@qH{X{@QnRBLK5O)*U~ zc}$m@t~1?ey4keEwA|EVT4h>eT5o#5^qA>M(-zY<(<`R8OnXf4nf94JH61X0X*z5= zYL=NR%x&gH=1a_i`Ev6$=IhNjnQt+#H$P(DYTjYqX@1MR*Zh(Bp!pl~_vSw>yd}gE zZi%ueEOC|uOM#`>QfjHN_$?P%ZnWHPS!P*dS#Q~A`Oy_54t=Cy^u-%Yiy6&p0;hbyL~IT%`aM5Botj;bW73FlAe*hlc!$F=({Z)qVaHa-4#(?`w;abEzdQcu4Zu0+JEZqJ J7=}Ae{V&3wK6(HE literal 0 HcmV?d00001 diff --git a/macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist b/macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000000..be5345de09 --- /dev/null +++ b/macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + CapQLThumbnailProvider.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift b/macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift new file mode 100644 index 0000000000..30d47c4e37 --- /dev/null +++ b/macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift @@ -0,0 +1,18 @@ +// +// ThumbnailProvider.swift +// CapQLThumbnailProvider +// + +import QuickLookThumbnailing + +class Cap_QuickLook_Thumbnail_Provider: QLThumbnailProvider { + + override func provideThumbnail(for request: QLFileThumbnailRequest, _ handler: @escaping (QLThumbnailReply?, Error?) -> Void) { + let imageURL = request.fileURL + .appendingPathComponent("screenshots", isDirectory: true) + .appendingPathComponent("display.jpg", isDirectory: false) + + let reply = QLThumbnailReply(imageFileURL: imageURL) + handler(reply, nil) + } +} diff --git a/macos/CapExtras/CapQLThumbnailProvider/Info.plist b/macos/CapExtras/CapQLThumbnailProvider/Info.plist new file mode 100644 index 0000000000..0f1dd79de7 --- /dev/null +++ b/macos/CapExtras/CapQLThumbnailProvider/Info.plist @@ -0,0 +1,22 @@ + + + + + NSExtension + + NSExtensionAttributes + + QLSupportedContentTypes + + so.cap.desktop.project + + QLThumbnailMinimumDimension + 32 + + NSExtensionPointIdentifier + com.apple.quicklook.thumbnail + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).Cap_QuickLook_Thumbnail_Provider + + + From bb33158f6360e5413546653655478beeaac8f457 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 22 Nov 2025 04:37:42 +0330 Subject: [PATCH 13/48] Revert "Add xcode project for plugins" This reverts commit ff91c460f576293cc74e9336cc812970cad1a54c. --- Cargo.toml | 11 +- apps/desktop/src-tauri/tauri.conf.json | 5 +- macos/.gitignore | 62 ---- .../CapExtras.xcodeproj/project.pbxproj | 349 ------------------ .../contents.xcworkspacedata | 7 - .../UserInterfaceState.xcuserstate | Bin 17443 -> 0 bytes .../xcschemes/xcschememanagement.plist | 14 - .../Cap_QuickLook_Thumbnail_Provider.swift | 18 - .../CapQLThumbnailProvider/Info.plist | 22 -- 9 files changed, 6 insertions(+), 482 deletions(-) delete mode 100644 macos/.gitignore delete mode 100644 macos/CapExtras/CapExtras.xcodeproj/project.pbxproj delete mode 100644 macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/xcuserdata/ilya.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift delete mode 100644 macos/CapExtras/CapQLThumbnailProvider/Info.plist diff --git a/Cargo.toml b/Cargo.toml index bb6c92519c..ecd080fa3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,12 +88,11 @@ manual_clamp = "deny" # Optimize for smaller binary size [profile.release] -codegen-units = 8 # Compile crates one after another so the compiler can optimize better -# panic = "abort" # Strip expensive panic clean-up logic -# codegen-units = 1 # Compile crates one after another so the compiler can optimize better -# lto = true # Enables link to optimizations -# opt-level = "s" # Optimize for binary size -# debug = true +panic = "abort" # Strip expensive panic clean-up logic +codegen-units = 1 # Compile crates one after another so the compiler can optimize better +lto = true # Enables link to optimizations +opt-level = "s" # Optimize for binary size +debug = true [patch.crates-io] # screencapturekit = { git = "https://github.com/CapSoftware/screencapturekit-rs", rev = "7ff1e103742e56c8f6c2e940b5e52684ed0bed69" } # branch = "cap-main" diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 618e73e5e0..76d6e5a4a8 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -65,10 +65,7 @@ "y": 140 } }, - "frameworks": ["../../../target/native-deps/Spacedrive.framework"], - "files": { - "PlugIns/*": "../../../macos/build/PlugIns/" - } + "frameworks": ["../../../target/native-deps/Spacedrive.framework"] }, "windows": { "nsis": { diff --git a/macos/.gitignore b/macos/.gitignore deleted file mode 100644 index 52fe2f7102..0000000000 --- a/macos/.gitignore +++ /dev/null @@ -1,62 +0,0 @@ -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## User settings -xcuserdata/ - -## Obj-C/Swift specific -*.hmap - -## App packaging -*.ipa -*.dSYM.zip -*.dSYM - -## Playgrounds -timeline.xctimeline -playground.xcworkspace - -# Swift Package Manager -# -# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. -# Packages/ -# Package.pins -# Package.resolved -# *.xcodeproj -# -# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata -# hence it is not needed unless you have added a package configuration file to your project -# .swiftpm - -.build/ - -# CocoaPods -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control -# -# Pods/ -# -# Add this line if you want to avoid checking in source code from the Xcode workspace -# *.xcworkspace - -# Carthage -# -# Add this line if you want to avoid checking in source code from Carthage dependencies. -# Carthage/Checkouts - -Carthage/Build/ - -# fastlane -# -# It is recommended to not store the screenshots in the git repo. -# Instead, use fastlane to re-generate the screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/#source-control - -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots/**/*.png -fastlane/test_output diff --git a/macos/CapExtras/CapExtras.xcodeproj/project.pbxproj b/macos/CapExtras/CapExtras.xcodeproj/project.pbxproj deleted file mode 100644 index 892bdad48e..0000000000 --- a/macos/CapExtras/CapExtras.xcodeproj/project.pbxproj +++ /dev/null @@ -1,349 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 77; - objects = { - -/* Begin PBXBuildFile section */ - 092CA65A2ECE775100C695FA /* QuickLookThumbnailing.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 092CA6592ECE775100C695FA /* QuickLookThumbnailing.framework */; }; - 092CA65C2ECE775100C695FA /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 092CA65B2ECE775100C695FA /* Quartz.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 092CA6572ECE775100C695FA /* CapQLThumbnailProvider.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = CapQLThumbnailProvider.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - 092CA6592ECE775100C695FA /* QuickLookThumbnailing.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLookThumbnailing.framework; path = System/Library/Frameworks/QuickLookThumbnailing.framework; sourceTree = SDKROOT; }; - 092CA65B2ECE775100C695FA /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFileSystemSynchronizedRootGroup section */ - 092CA65D2ECE775100C695FA /* CapQLThumbnailProvider */ = { - isa = PBXFileSystemSynchronizedRootGroup; - path = CapQLThumbnailProvider; - sourceTree = ""; - }; -/* End PBXFileSystemSynchronizedRootGroup section */ - -/* Begin PBXFrameworksBuildPhase section */ - 092CA6542ECE775100C695FA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 092CA65A2ECE775100C695FA /* QuickLookThumbnailing.framework in Frameworks */, - 092CA65C2ECE775100C695FA /* Quartz.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 092CA6582ECE775100C695FA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 092CA6592ECE775100C695FA /* QuickLookThumbnailing.framework */, - 092CA65B2ECE775100C695FA /* Quartz.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 09E0880D2ECE5B440097252E = { - isa = PBXGroup; - children = ( - 092CA65D2ECE775100C695FA /* CapQLThumbnailProvider */, - 092CA6582ECE775100C695FA /* Frameworks */, - 09E088172ECE5B440097252E /* Products */, - ); - sourceTree = ""; - }; - 09E088172ECE5B440097252E /* Products */ = { - isa = PBXGroup; - children = ( - 092CA6572ECE775100C695FA /* CapQLThumbnailProvider.appex */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 092CA6562ECE775100C695FA /* CapQLThumbnailProvider */ = { - isa = PBXNativeTarget; - buildConfigurationList = 092CA6642ECE775100C695FA /* Build configuration list for PBXNativeTarget "CapQLThumbnailProvider" */; - buildPhases = ( - 092CA6532ECE775100C695FA /* Sources */, - 092CA6542ECE775100C695FA /* Frameworks */, - 092CA6552ECE775100C695FA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - fileSystemSynchronizedGroups = ( - 092CA65D2ECE775100C695FA /* CapQLThumbnailProvider */, - ); - name = CapQLThumbnailProvider; - packageProductDependencies = ( - ); - productName = CapQLThumbnailProvider; - productReference = 092CA6572ECE775100C695FA /* CapQLThumbnailProvider.appex */; - productType = "com.apple.product-type.app-extension"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 09E0880E2ECE5B440097252E /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 2610; - LastUpgradeCheck = 2610; - TargetAttributes = { - 092CA6562ECE775100C695FA = { - CreatedOnToolsVersion = 26.1.1; - }; - }; - }; - buildConfigurationList = 09E088112ECE5B440097252E /* Build configuration list for PBXProject "CapExtras" */; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 09E0880D2ECE5B440097252E; - minimizedProjectReferenceProxies = 1; - preferredProjectObjectVersion = 77; - productRefGroup = 09E088172ECE5B440097252E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 092CA6562ECE775100C695FA /* CapQLThumbnailProvider */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 092CA6552ECE775100C695FA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 092CA6532ECE775100C695FA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 092CA6612ECE775100C695FA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = YES; - ENABLE_USER_SELECTED_FILES = readonly; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = CapQLThumbnailProvider/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = CapQLThumbnailProvider; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 13.5; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = so.cap.desktop.CapQLThumbnailProvider; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - STRING_CATALOG_GENERATE_SYMBOLS = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; - SWIFT_APPROACHABLE_CONCURRENCY = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 092CA6622ECE775100C695FA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; - ENABLE_APP_SANDBOX = YES; - ENABLE_USER_SELECTED_FILES = readonly; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = CapQLThumbnailProvider/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = CapQLThumbnailProvider; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@executable_path/../../../../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 13.5; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = so.cap.desktop.CapQLThumbnailProvider; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - STRING_CATALOG_GENERATE_SYMBOLS = YES; - SWIFT_APPROACHABLE_CONCURRENCY = YES; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 09E088182ECE5B440097252E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 26.1; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - 09E088192ECE5B440097252E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 26.1; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = macosx; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 092CA6642ECE775100C695FA /* Build configuration list for PBXNativeTarget "CapQLThumbnailProvider" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 092CA6612ECE775100C695FA /* Debug */, - 092CA6622ECE775100C695FA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 09E088112ECE5B440097252E /* Build configuration list for PBXProject "CapExtras" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 09E088182ECE5B440097252E /* Debug */, - 09E088192ECE5B440097252E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 09E0880E2ECE5B440097252E /* Project object */; -} diff --git a/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a625..0000000000 --- a/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/xcuserdata/ilya.xcuserdatad/UserInterfaceState.xcuserstate b/macos/CapExtras/CapExtras.xcodeproj/project.xcworkspace/xcuserdata/ilya.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index c7a384d3e3b98a7d0cba0b6b9b47a7dc20eea7ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17443 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%0DLHOaW*0@K5kh3RolHoPSSDpXQ%ClbAlwzre&a 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 J7=}Ae{V&3wK6(HE diff --git a/macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist b/macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index be5345de09..0000000000 --- a/macos/CapExtras/CapExtras.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - CapQLThumbnailProvider.xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift b/macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift deleted file mode 100644 index 30d47c4e37..0000000000 --- a/macos/CapExtras/CapQLThumbnailProvider/Cap_QuickLook_Thumbnail_Provider.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// ThumbnailProvider.swift -// CapQLThumbnailProvider -// - -import QuickLookThumbnailing - -class Cap_QuickLook_Thumbnail_Provider: QLThumbnailProvider { - - override func provideThumbnail(for request: QLFileThumbnailRequest, _ handler: @escaping (QLThumbnailReply?, Error?) -> Void) { - let imageURL = request.fileURL - .appendingPathComponent("screenshots", isDirectory: true) - .appendingPathComponent("display.jpg", isDirectory: false) - - let reply = QLThumbnailReply(imageFileURL: imageURL) - handler(reply, nil) - } -} diff --git a/macos/CapExtras/CapQLThumbnailProvider/Info.plist b/macos/CapExtras/CapQLThumbnailProvider/Info.plist deleted file mode 100644 index 0f1dd79de7..0000000000 --- a/macos/CapExtras/CapQLThumbnailProvider/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - NSExtension - - NSExtensionAttributes - - QLSupportedContentTypes - - so.cap.desktop.project - - QLThumbnailMinimumDimension - 32 - - NSExtensionPointIdentifier - com.apple.quicklook.thumbnail - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).Cap_QuickLook_Thumbnail_Provider - - - From 10995727e12e5b3dff45013015d65efa9ed34ce3 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 22 Nov 2025 05:01:20 +0330 Subject: [PATCH 14/48] Remove unused + remove for now --- apps/desktop/src-tauri/src/platform/macos/mod.rs | 8 -------- apps/desktop/src-tauri/src/windows.rs | 7 ------- 2 files changed, 15 deletions(-) diff --git a/apps/desktop/src-tauri/src/platform/macos/mod.rs b/apps/desktop/src-tauri/src/platform/macos/mod.rs index 99b61d2533..e57e9436e2 100644 --- a/apps/desktop/src-tauri/src/platform/macos/mod.rs +++ b/apps/desktop/src-tauri/src/platform/macos/mod.rs @@ -40,11 +40,3 @@ impl WebviewWindowExt for WebviewWindow { } } } - -pub fn add_recent_document>(path: P) { - if let Some(url) = NSURL::from_file_path(path) { - run_on_main(move |mtm| { - NSDocumentController::sharedDocumentController(mtm).noteNewRecentDocumentURL(&url) - }) - } -} diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 67249452f0..32aec265b4 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -34,10 +34,6 @@ use cap_recording::feeds; #[cfg(target_os = "macos")] use crate::platform::{self, WebviewWindowExt}; -#[cfg(target_os = "macos")] -const DEFAULT_TRAFFIC_LIGHTS_INSET_WITH_TOOLBAR: LogicalPosition = - LogicalPosition::new(20.0, 30.0); - #[derive(Clone, Deserialize, Type)] pub enum CapWindowDef { // Contains onboarding + permissions @@ -440,9 +436,6 @@ impl CapWindow { let _ = main.close(); }; - #[cfg(target_os = "macos")] - platform::add_recent_document(project_path); - self.window_builder(app, "/editor") .maximizable(true) .inner_size(1240.0, 800.0) From 3465e159923b2968008112587ac533cbb08fcb16 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 22 Nov 2025 05:06:16 +0330 Subject: [PATCH 15/48] missed rename on windows specific fn --- apps/desktop/src-tauri/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 4444000e55..ac367761b2 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -2832,7 +2832,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { fn has_open_editor_window(app: &AppHandle) -> bool { app.webview_windows() .keys() - .any(|label| matches!(CapWindowId::from_str(label), Ok(CapWindowId::Editor { .. }))) + .any(|label| matches!(CapWindow::from_str(label), Ok(CapWindow::Editor { .. }))) } #[cfg(target_os = "windows")] From f80a754c4e2dd52b12832819040c238688473937 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 22 Nov 2025 05:23:55 +0330 Subject: [PATCH 16/48] Apply clippy suggestions --- apps/desktop/src-tauri/src/permissions.rs | 4 ++-- apps/desktop/src-tauri/src/platform/macos/mod.rs | 6 +----- apps/desktop/src-tauri/src/platform/mod.rs | 2 -- apps/desktop/src-tauri/src/target_select_overlay.rs | 8 ++------ 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/apps/desktop/src-tauri/src/permissions.rs b/apps/desktop/src-tauri/src/permissions.rs index 22cd256d0f..f1983de1d4 100644 --- a/apps/desktop/src-tauri/src/permissions.rs +++ b/apps/desktop/src-tauri/src/permissions.rs @@ -87,12 +87,12 @@ pub async fn request_permission(_permission: OSPermission) { &[&*objc2_core_foundation::CFString::from_static_str( "AXTrustedCheckOptionPrompt", )], - &[&*objc2_core_foundation::CFBoolean::new(true)], + &[objc2_core_foundation::CFBoolean::new(true)], ); // SAFETY: The AXIsProcessTrustedWithOptions function is safe to call with a valid CFDictionaryRef. unsafe { objc2_application_services::AXIsProcessTrustedWithOptions(Some( - &*options.as_opaque(), + options.as_opaque(), )); } } diff --git a/apps/desktop/src-tauri/src/platform/macos/mod.rs b/apps/desktop/src-tauri/src/platform/macos/mod.rs index e57e9436e2..f865e64a03 100644 --- a/apps/desktop/src-tauri/src/platform/macos/mod.rs +++ b/apps/desktop/src-tauri/src/platform/macos/mod.rs @@ -1,8 +1,4 @@ -use std::path::Path; - -use dispatch2::run_on_main; -use objc2_app_kit::{NSDocumentController, NSWindow, NSWindowButton}; -use objc2_foundation::NSURL; +use objc2_app_kit::{NSWindow, NSWindowButton}; use tauri::WebviewWindow; mod sc_shareable_content; diff --git a/apps/desktop/src-tauri/src/platform/mod.rs b/apps/desktop/src-tauri/src/platform/mod.rs index 0a29cdc827..48324c5b96 100644 --- a/apps/desktop/src-tauri/src/platform/mod.rs +++ b/apps/desktop/src-tauri/src/platform/mod.rs @@ -1,5 +1,3 @@ -use std::path::Path; - use serde::{Deserialize, Serialize}; use specta::Type; #[cfg(target_os = "windows")] diff --git a/apps/desktop/src-tauri/src/target_select_overlay.rs b/apps/desktop/src-tauri/src/target_select_overlay.rs index cee6bb2787..1ad1fc5458 100644 --- a/apps/desktop/src-tauri/src/target_select_overlay.rs +++ b/apps/desktop/src-tauri/src/target_select_overlay.rs @@ -236,12 +236,8 @@ pub async fn focus_window(window_id: WindowId) -> Result<(), String> { .owner_pid() .ok_or("Could not get window owner PID")?; - if let Some(app) = - unsafe { NSRunningApplication::runningApplicationWithProcessIdentifier(pid) } - { - unsafe { - app.activateWithOptions(NSApplicationActivationOptions::ActivateIgnoringOtherApps); - } + if let Some(app) = NSRunningApplication::runningApplicationWithProcessIdentifier(pid) { + app.activateWithOptions(NSApplicationActivationOptions::ActivateIgnoringOtherApps); } } From c9cd0e8bda706d3e1217d87a492fb1f762eb5c60 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 22 Nov 2025 05:29:34 +0330 Subject: [PATCH 17/48] Fix main window and target_select_overlay window levels using non-standard levels for now. --- apps/desktop/src-tauri/src/windows.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 32aec265b4..125d3c9733 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -191,7 +191,7 @@ impl CapWindowDef { match self { Self::RecordingControls => Some(NSMainMenuWindowLevel), - Self::TargetSelectOverlay { .. } | Self::CaptureArea => Some(NSPopUpMenuWindowLevel), + Self::TargetSelectOverlay { .. } | Self::CaptureArea => Some(45), Self::RecordingsOverlay | Self::WindowCaptureOccluder { .. } => { Some(NSScreenSaverWindowLevel) } @@ -315,7 +315,7 @@ impl CapWindow { if new_recording_flow { _ = window.run_on_main_thread({ let window = window.clone(); - move || window.objc2_nswindow().setLevel(110) + move || window.objc2_nswindow().setLevel(50) }); } @@ -431,7 +431,7 @@ impl CapWindow { builder.build()? } - Self::Editor { project_path } => { + Self::Editor { .. } => { if let Some(main) = CapWindowDef::Main.get(app) { let _ = main.close(); }; From f02714b51f8346c059c0797c125c696ed2a9ce9e Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 29 Nov 2025 12:48:11 +0330 Subject: [PATCH 18/48] cargo fmt --- apps/desktop/src-tauri/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index d1a86183da..21289b22de 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -92,7 +92,7 @@ use upload::{create_or_get_video, upload_image, upload_video}; use web_api::AuthedApiError; use web_api::ManagerExt as WebManagerExt; use windows::{ - CapWindowDef, EditorWindowIds, ScreenshotEditorWindowIds, CapWindow, set_window_transparent, + CapWindow, CapWindowDef, EditorWindowIds, ScreenshotEditorWindowIds, set_window_transparent, }; use crate::{ From dc2c4437aceaa3db3c966d643c0998f6249d6582 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 29 Nov 2025 12:54:35 +0330 Subject: [PATCH 19/48] Fix after updating from main --- apps/desktop/src-tauri/src/lib.rs | 8 ++++---- apps/desktop/src-tauri/src/screenshot_editor.rs | 6 +++--- apps/desktop/src-tauri/src/windows.rs | 6 +++--- apps/desktop/src/utils/tauri.ts | 7 ++----- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 21289b22de..e091759cea 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -2698,7 +2698,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { match event { WindowEvent::CloseRequested { .. } => { - if let Ok(CapWindowId::Camera) = CapWindowId::from_str(label) { + if let Ok(CapWindowDef::Camera) = CapWindowDef::from_str(label) { tokio::spawn(cleanup_camera_window(app.clone())); } } @@ -2745,7 +2745,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { reopen_main_window(&app); } } - CapWindowId::ScreenshotEditor { id } => { + CapWindowDef::ScreenshotEditor { id } => { let window_ids = ScreenshotEditorWindowIds::get(window.app_handle()); window_ids.ids.lock().unwrap().retain(|(_, _id)| *_id != id); @@ -2753,11 +2753,11 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) { tokio::spawn(ScreenshotEditorInstances::remove(window.clone())); #[cfg(target_os = "windows")] - if CapWindowId::Settings.get(&app).is_none() { + if CapWindowDef::Settings.get(&app).is_none() { reopen_main_window(&app); } } - CapWindowId::Settings => { + CapWindowDef::Settings => { for (label, window) in app.webview_windows() { if let Ok(id) = CapWindowDef::from_str(&label) && matches!( diff --git a/apps/desktop/src-tauri/src/screenshot_editor.rs b/apps/desktop/src-tauri/src/screenshot_editor.rs index 591b17a34c..23f939b7af 100644 --- a/apps/desktop/src-tauri/src/screenshot_editor.rs +++ b/apps/desktop/src-tauri/src/screenshot_editor.rs @@ -1,7 +1,7 @@ use crate::PendingScreenshots; use crate::frame_ws::{WSFrame, create_watch_frame_ws}; use crate::gpu_context; -use crate::windows::{CapWindowId, ScreenshotEditorWindowIds}; +use crate::windows::{CapWindowDef, ScreenshotEditorWindowIds}; use cap_project::{ ProjectConfiguration, RecordingMeta, RecordingMetaInner, SingleSegment, StudioRecordingMeta, VideoMeta, @@ -382,8 +382,8 @@ pub struct SerializedScreenshotEditorInstance { pub async fn create_screenshot_editor_instance( window: Window, ) -> Result { - let CapWindowId::ScreenshotEditor { id } = - CapWindowId::from_str(window.label()).map_err(|e| e.to_string())? + let CapWindowDef::ScreenshotEditor { id } = + CapWindowDef::from_str(window.label()).map_err(|e| e.to_string())? else { return Err("Invalid window".to_string()); }; diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 8c0f0002e6..0dcf1f048e 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -136,7 +136,7 @@ impl CapWindowDef { Self::CaptureArea => "Cap Capture Area", Self::RecordingControls => "Cap Recording Controls", Self::Editor { .. } => "Cap Editor", - Self::ScreenshotEditor { .. } => "Cap Screenshot Editor".to_string(), + Self::ScreenshotEditor { .. } => "Cap Screenshot Editor", Self::ModeSelect => "Cap Mode Selection", Self::Camera => "Cap Camera", Self::RecordingsOverlay => "Cap Recordings Overlay", @@ -456,7 +456,7 @@ impl CapWindow { .build()? } Self::ScreenshotEditor { path: _ } => { - if let Some(main) = CapWindowId::Main.get(app) { + if let Some(main) = CapWindowDef::Main.get(app) { let _ = main.close(); }; @@ -823,7 +823,7 @@ impl CapWindow { let state = app.state::(); let s = state.ids.lock().unwrap(); let id = s.iter().find(|(p, _)| p == path).unwrap().1; - CapWindowId::ScreenshotEditor { id } + CapWindowDef::ScreenshotEditor { id } } } } diff --git a/apps/desktop/src/utils/tauri.ts b/apps/desktop/src/utils/tauri.ts index e0e2b94359..61b4d0a734 100644 --- a/apps/desktop/src/utils/tauri.ts +++ b/apps/desktop/src/utils/tauri.ts @@ -176,16 +176,13 @@ async isCameraWindowOpen() : Promise { async seekTo(frameNumber: number) : Promise { return await TAURI_INVOKE("seek_to", { frameNumber }); }, -async positionTrafficLights(controlsInset: [number, number] | null) : Promise { - await TAURI_INVOKE("position_traffic_lights", { controlsInset }); -}, async setTheme(theme: AppTheme) : Promise { await TAURI_INVOKE("set_theme", { theme }); }, async globalMessageDialog(message: string) : Promise { await TAURI_INVOKE("global_message_dialog", { message }); }, -async showWindow(window: ShowCapWindow) : Promise { +async showWindow(window: CapWindow) : Promise { return await TAURI_INVOKE("show_window", { window }); }, async writeClipboardString(text: string) : Promise { @@ -386,6 +383,7 @@ export type CameraPreviewState = { size: number; shape: CameraPreviewShape; mirr export type CameraShape = "square" | "source" export type CameraXPosition = "left" | "center" | "right" export type CameraYPosition = "top" | "bottom" +export type CapWindow = "Setup" | { Main: { init_target_mode: RecordingTargetMode | null } } | { Settings: { page: string | null } } | { Editor: { project_path: string } } | "RecordingsOverlay" | { WindowCaptureOccluder: { screen_id: DisplayId } } | { TargetSelectOverlay: { display_id: DisplayId } } | { CaptureArea: { screen_id: DisplayId } } | "Camera" | { InProgressRecording: { countdown: number | null } } | "Upgrade" | "ModeSelect" | { ScreenshotEditor: { path: string } } export type CaptionData = { segments: CaptionSegment[]; settings: CaptionSettings | null } export type CaptionSegment = { id: string; start: number; end: number; text: string } export type CaptionSettings = { enabled: boolean; font: string; size: number; color: string; backgroundColor: string; backgroundOpacity: number; position: string; bold: boolean; italic: boolean; outline: boolean; outlineColor: string; exportWithSubtitles: boolean } @@ -491,7 +489,6 @@ export type SerializedScreenshotEditorInstance = { framesSocketUrl: string; path export type SetCaptureAreaPending = boolean export type ShadowConfiguration = { size: number; opacity: number; blur: number } export type SharingMeta = { id: string; link: string } -export type ShowCapWindow = "Setup" | { Main: { init_target_mode: RecordingTargetMode | null } } | { Settings: { page: string | null } } | { Editor: { project_path: string } } | "RecordingsOverlay" | { WindowCaptureOccluder: { screen_id: DisplayId } } | { TargetSelectOverlay: { display_id: DisplayId } } | { CaptureArea: { screen_id: DisplayId } } | "Camera" | { InProgressRecording: { countdown: number | null } } | "Upgrade" | "ModeSelect" | { ScreenshotEditor: { path: string } } export type SingleSegment = { display: VideoMeta; camera?: VideoMeta | null; audio?: AudioMeta | null; cursor?: string | null } export type StartRecordingInputs = { capture_target: ScreenCaptureTarget; capture_system_audio?: boolean; mode: RecordingMode; organization_id?: string | null } export type StereoMode = "stereo" | "monoL" | "monoR" From 2227fa7094e061d7da910bbab593a0332150802b Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 29 Nov 2025 21:51:05 +0330 Subject: [PATCH 20/48] Use tauri-cli ^2.9.4 --- apps/desktop/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index b5f4e3d96d..7d700caa8d 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -73,7 +73,7 @@ "devDependencies": { "@fontsource/geist-sans": "^5.0.3", "@iconify/json": "^2.2.239", - "@tauri-apps/cli": ">=2.1.0", + "@tauri-apps/cli": "^2.9.4", "@total-typescript/ts-reset": "^0.6.1", "@types/dom-webcodecs": "^0.1.11", "@types/uuid": "^9.0.8", From 3b48cc36de2182694a5a9804e9771fd7f84e70d4 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 29 Nov 2025 21:53:00 +0330 Subject: [PATCH 21/48] Update pnpm-lock.yaml --- pnpm-lock.yaml | 328 +++++++++++++++++++++++++++---------------------- 1 file changed, 181 insertions(+), 147 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32ff0ea39f..b472f738bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,7 +118,7 @@ importers: version: 0.14.10(solid-js@1.9.6) '@solidjs/start': specifier: ^1.1.3 - version: 1.1.3(@testing-library/jest-dom@6.5.0)(@types/node@22.15.17)(jiti@2.6.1)(solid-js@1.9.6)(terser@5.44.0)(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1) + version: 1.1.3(@testing-library/jest-dom@6.5.0)(@types/node@22.15.17)(jiti@2.6.1)(solid-js@1.9.6)(terser@5.44.0)(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1) '@tanstack/solid-query': specifier: ^5.51.21 version: 5.75.4(solid-js@1.9.6) @@ -205,7 +205,7 @@ importers: version: 9.0.1 vinxi: specifier: ^0.5.6 - version: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) + version: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) webcodecs: specifier: ^0.1.0 version: 0.1.0 @@ -220,8 +220,8 @@ importers: specifier: ^2.2.239 version: 2.2.336 '@tauri-apps/cli': - specifier: '>=2.1.0' - version: 2.5.0 + specifier: ^2.9.4 + version: 2.9.4 '@total-typescript/ts-reset': specifier: ^0.6.1 version: 0.6.1 @@ -4319,8 +4319,8 @@ packages: '@oxc-project/types@0.94.0': resolution: {integrity: sha512-+UgQT/4o59cZfH6Cp7G0hwmqEQ0wE+AdIwhikdwnhWI9Dp8CgSY081+Q3O67/wq3VJu8mgUEB93J9EHHn70fOw==} - '@oxc-project/types@0.97.0': - resolution: {integrity: sha512-lxmZK4xFrdvU0yZiDwgVQTCvh2gHWBJCBk5ALsrtsBWhs0uDIi+FTOnXRQeQfs304imdvTdaakT/lqwQ8hkOXQ==} + '@oxc-project/types@0.99.0': + resolution: {integrity: sha512-LLDEhXB7g1m5J+woRSgfKsFPS3LhR9xRhTeIoEBm5WrkwMxn6eZ0Ld0c0K5eHB57ChZX6I3uSmmLjZ8pcjlRcw==} '@panva/hkdf@1.2.1': resolution: {integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==} @@ -5261,8 +5261,8 @@ packages: cpu: [arm64] os: [android] - '@rolldown/binding-android-arm64@1.0.0-beta.50': - resolution: {integrity: sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag==} + '@rolldown/binding-android-arm64@1.0.0-beta.52': + resolution: {integrity: sha512-MBGIgysimZPqTDcLXI+i9VveijkP5C3EAncEogXhqfax6YXj1Tr2LY3DVuEOMIjWfMPMhtQSPup4fSTAmgjqIw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] @@ -5273,8 +5273,8 @@ packages: cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-arm64@1.0.0-beta.50': - resolution: {integrity: sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w==} + '@rolldown/binding-darwin-arm64@1.0.0-beta.52': + resolution: {integrity: sha512-MmKeoLnKu1d9j6r19K8B+prJnIZ7u+zQ+zGQ3YHXGnr41rzE3eqQLovlkvoZnRoxDGPA4ps0pGiwXy6YE3lJyg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] @@ -5285,8 +5285,8 @@ packages: cpu: [x64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-beta.50': - resolution: {integrity: sha512-fFXDjXnuX7/gQZQm/1FoivVtRcyAzdjSik7Eo+9iwPQ9EgtA5/nB2+jmbzaKtMGG3q+BnZbdKHCtOacmNrkIDA==} + '@rolldown/binding-darwin-x64@1.0.0-beta.52': + resolution: {integrity: sha512-qpHedvQBmIjT8zdnjN3nWPR2qjQyJttbXniCEKKdHeAbZG9HyNPBUzQF7AZZGwmS9coQKL+hWg9FhWzh2dZ2IA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] @@ -5297,8 +5297,8 @@ packages: cpu: [x64] os: [freebsd] - '@rolldown/binding-freebsd-x64@1.0.0-beta.50': - resolution: {integrity: sha512-F1b6vARy49tjmT/hbloplzgJS7GIvwWZqt+tAHEstCh0JIh9sa8FAMVqEmYxDviqKBaAI8iVvUREm/Kh/PD26Q==} + '@rolldown/binding-freebsd-x64@1.0.0-beta.52': + resolution: {integrity: sha512-dDp7WbPapj/NVW0LSiH/CLwMhmLwwKb3R7mh2kWX+QW85X1DGVnIEyKh9PmNJjB/+suG1dJygdtdNPVXK1hylg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] @@ -5309,8 +5309,8 @@ packages: cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50': - resolution: {integrity: sha512-U6cR76N8T8M6lHj7EZrQ3xunLPxSvYYxA8vJsBKZiFZkT8YV4kjgCO3KwMJL0NOjQCPGKyiXO07U+KmJzdPGRw==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.52': + resolution: {integrity: sha512-9e4l6vy5qNSliDPqNfR6CkBOAx6PH7iDV4OJiEJzajajGrVy8gc/IKKJUsoE52G8ud8MX6r3PMl97NfwgOzB7g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -5321,8 +5321,8 @@ packages: cpu: [arm64] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50': - resolution: {integrity: sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.52': + resolution: {integrity: sha512-V48oDR84feRU2KRuzpALp594Uqlx27+zFsT6+BgTcXOtu7dWy350J1G28ydoCwKB+oxwsRPx2e7aeQnmd3YJbQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -5333,8 +5333,8 @@ packages: cpu: [arm64] os: [linux] - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50': - resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==} + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.52': + resolution: {integrity: sha512-ENLmSQCWqSA/+YN45V2FqTIemg7QspaiTjlm327eUAMeOLdqmSOVVyrQexJGNTQ5M8sDYCgVAig2Kk01Ggmqaw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -5345,8 +5345,8 @@ packages: cpu: [x64] os: [linux] - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50': - resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==} + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.52': + resolution: {integrity: sha512-klahlb2EIFltSUubn/VLjuc3qxp1E7th8ukayPfdkcKvvYcQ5rJztgx8JsJSuAKVzKtNTqUGOhy4On71BuyV8g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -5357,8 +5357,8 @@ packages: cpu: [x64] os: [linux] - '@rolldown/binding-linux-x64-musl@1.0.0-beta.50': - resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==} + '@rolldown/binding-linux-x64-musl@1.0.0-beta.52': + resolution: {integrity: sha512-UuA+JqQIgqtkgGN2c/AQ5wi8M6mJHrahz/wciENPTeI6zEIbbLGoth5XN+sQe2pJDejEVofN9aOAp0kaazwnVg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -5369,8 +5369,8 @@ packages: cpu: [arm64] os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.0.0-beta.50': - resolution: {integrity: sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==} + '@rolldown/binding-openharmony-arm64@1.0.0-beta.52': + resolution: {integrity: sha512-1BNQW8u4ro8bsN1+tgKENJiqmvc+WfuaUhXzMImOVSMw28pkBKdfZtX2qJPADV3terx+vNJtlsgSGeb3+W6Jiw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] @@ -5380,8 +5380,8 @@ packages: engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-wasm32-wasi@1.0.0-beta.50': - resolution: {integrity: sha512-nmCN0nIdeUnmgeDXiQ+2HU6FT162o+rxnF7WMkBm4M5Ds8qTU7Dzv2Wrf22bo4ftnlrb2hKK6FSwAJSAe2FWLg==} + '@rolldown/binding-wasm32-wasi@1.0.0-beta.52': + resolution: {integrity: sha512-K/p7clhCqJOQpXGykrFaBX2Dp9AUVIDHGc+PtFGBwg7V+mvBTv/tsm3LC3aUmH02H2y3gz4y+nUTQ0MLpofEEg==} engines: {node: '>=14.0.0'} cpu: [wasm32] @@ -5391,8 +5391,8 @@ packages: cpu: [arm64] os: [win32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50': - resolution: {integrity: sha512-7kcNLi7Ua59JTTLvbe1dYb028QEPaJPJQHqkmSZ5q3tJueUeb6yjRtx8mw4uIqgWZcnQHAR3PrLN4XRJxvgIkA==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52': + resolution: {integrity: sha512-a4EkXBtnYYsKipjS7QOhEBM4bU5IlR9N1hU+JcVEVeuTiaslIyhWVKsvf7K2YkQHyVAJ+7/A9BtrGqORFcTgng==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] @@ -5403,8 +5403,8 @@ packages: cpu: [ia32] os: [win32] - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50': - resolution: {integrity: sha512-lL70VTNvSCdSZkDPPVMwWn/M2yQiYvSoXw9hTLgdIWdUfC3g72UaruezusR6ceRuwHCY1Ayu2LtKqXkBO5LIwg==} + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.52': + resolution: {integrity: sha512-5ZXcYyd4GxPA6QfbGrNcQjmjbuLGvfz6728pZMsQvGHI+06LT06M6TPtXvFvLgXtexc+OqvFe1yAIXJU1gob/w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] @@ -5415,8 +5415,8 @@ packages: cpu: [x64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50': - resolution: {integrity: sha512-4qU4x5DXWB4JPjyTne/wBNPqkbQU8J45bl21geERBKtEittleonioACBL1R0PsBu0Aq21SwMK5a9zdBkWSlQtQ==} + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.52': + resolution: {integrity: sha512-tzpnRQXJrSzb8Z9sm97UD3cY0toKOImx+xRKsDLX4zHaAlRXWh7jbaKBePJXEN7gNw7Nm03PBNwphdtA8KSUYQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -5424,8 +5424,8 @@ packages: '@rolldown/pluginutils@1.0.0-beta.42': resolution: {integrity: sha512-N7pQzk9CyE7q0bBN/q0J8s6Db279r5kUZc6d7/wWRe9/zXqC52HQovVyu6iXPIDY4BEzzgbVLhVFXrOuGJ22ZQ==} - '@rolldown/pluginutils@1.0.0-beta.50': - resolution: {integrity: sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==} + '@rolldown/pluginutils@1.0.0-beta.52': + resolution: {integrity: sha512-/L0htLJZbaZFL1g9OHOblTxbCYIGefErJjtYOwgl9ZqNx27P3L0SDfjhhHIss32gu5NWgnxuT2a2Hnnv6QGHKA==} '@rollup/plugin-alias@5.1.1': resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} @@ -6305,10 +6305,10 @@ packages: react-dom: optional: true - '@storybook/builder-vite@10.1.0-alpha.10': - resolution: {integrity: sha512-Sb/Kwucehq0I9e5sZb+ZchP4iGUa6LQ0RIi+uXBiyvmnYA6OYKZCnGsCG8VQARwiWcSDmeHd71ncnyMBwJSEDA==} + '@storybook/builder-vite@10.2.0-alpha.1': + resolution: {integrity: sha512-UjgUJTJHhjiXRoW3XqNhkdSAQU04a+Jwaw9+0w4HtnPlIKSJCE9pd4eImxB2Oi1r1P9yKcxYGftKVOKVyPSjcg==} peerDependencies: - storybook: ^10.1.0-alpha.10 + storybook: ^10.2.0-alpha.1 vite: ^5.0.0 || ^6.0.0 || ^7.0.0 '@storybook/core@8.6.12': @@ -6319,12 +6319,12 @@ packages: prettier: optional: true - '@storybook/csf-plugin@10.1.0-alpha.10': - resolution: {integrity: sha512-DLFzOaUwu6gPFZ3cMxRdhIOUROq2LSKXuDioXlTTS23lQu5F4SPZM8TeWXQ6Oy5bg1LUhxsGWohTO7jmsThLRA==} + '@storybook/csf-plugin@10.2.0-alpha.1': + resolution: {integrity: sha512-kOl063iJw8fw861aw+AicnukARi1IdoHfOUBLN/AZbnOenQvnUBxkCvZCd/8hBIfedXys/fZyHBaORQuM0BlmA==} peerDependencies: esbuild: '*' rollup: '*' - storybook: ^10.1.0-alpha.10 + storybook: ^10.2.0-alpha.1 vite: '*' webpack: '*' peerDependenciesMeta: @@ -6553,8 +6553,8 @@ packages: cpu: [arm64] os: [darwin] - '@tauri-apps/cli-darwin-arm64@2.5.0': - resolution: {integrity: sha512-VuVAeTFq86dfpoBDNYAdtQVLbP0+2EKCHIIhkaxjeoPARR0sLpFHz2zs0PcFU76e+KAaxtEtAJAXGNUc8E1PzQ==} + '@tauri-apps/cli-darwin-arm64@2.9.4': + resolution: {integrity: sha512-9rHkMVtbMhe0AliVbrGpzMahOBg3rwV46JYRELxR9SN6iu1dvPOaMaiC4cP6M/aD1424ziXnnMdYU06RAH8oIw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -6565,8 +6565,8 @@ packages: cpu: [x64] os: [darwin] - '@tauri-apps/cli-darwin-x64@2.5.0': - resolution: {integrity: sha512-hUF01sC06cZVa8+I0/VtsHOk9BbO75rd+YdtHJ48xTdcYaQ5QIwL4yZz9OR1AKBTaUYhBam8UX9Pvd5V2/4Dpw==} + '@tauri-apps/cli-darwin-x64@2.9.4': + resolution: {integrity: sha512-VT9ymNuT06f5TLjCZW2hfSxbVtZDhORk7CDUDYiq5TiSYQdxkl8MVBy0CCFFcOk4QAkUmqmVUA9r3YZ/N/vPRQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -6577,8 +6577,8 @@ packages: cpu: [arm] os: [linux] - '@tauri-apps/cli-linux-arm-gnueabihf@2.5.0': - resolution: {integrity: sha512-LQKqttsK252LlqYyX8R02MinUsfFcy3+NZiJwHFgi5Y3+ZUIAED9cSxJkyNtuY5KMnR4RlpgWyLv4P6akN1xhg==} + '@tauri-apps/cli-linux-arm-gnueabihf@2.9.4': + resolution: {integrity: sha512-tTWkEPig+2z3Rk0zqZYfjUYcgD+aSm72wdrIhdYobxbQZOBw0zfn50YtWv+av7bm0SHvv75f0l7JuwgZM1HFow==} engines: {node: '>= 10'} cpu: [arm] os: [linux] @@ -6589,8 +6589,8 @@ packages: cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-arm64-gnu@2.5.0': - resolution: {integrity: sha512-mTQufsPcpdHg5RW0zypazMo4L55EfeE5snTzrPqbLX4yCK2qalN7+rnP8O8GT06xhp6ElSP/Ku1M2MR297SByQ==} + '@tauri-apps/cli-linux-arm64-gnu@2.9.4': + resolution: {integrity: sha512-ql6vJ611qoqRYHxkKPnb2vHa27U+YRKRmIpLMMBeZnfFtZ938eao7402AQCH1mO2+/8ioUhbpy9R/ZcLTXVmkg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -6601,14 +6601,14 @@ packages: cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-arm64-musl@2.5.0': - resolution: {integrity: sha512-rQO1HhRUQqyEaal5dUVOQruTRda/TD36s9kv1hTxZiFuSq3558lsTjAcUEnMAtBcBkps20sbyTJNMT0AwYIk8Q==} + '@tauri-apps/cli-linux-arm64-musl@2.9.4': + resolution: {integrity: sha512-vg7yNn7ICTi6hRrcA/6ff2UpZQP7un3xe3SEld5QM0prgridbKAiXGaCKr3BnUBx/rGXegQlD/wiLcWdiiraSw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tauri-apps/cli-linux-riscv64-gnu@2.5.0': - resolution: {integrity: sha512-7oS18FN46yDxyw1zX/AxhLAd7T3GrLj3Ai6s8hZKd9qFVzrAn36ESL7d3G05s8wEtsJf26qjXnVF4qleS3dYsA==} + '@tauri-apps/cli-linux-riscv64-gnu@2.9.4': + resolution: {integrity: sha512-l8L+3VxNk6yv5T/Z/gv5ysngmIpsai40B9p6NQQyqYqxImqYX37pqREoEBl1YwG7szGnDibpWhidPrWKR59OJA==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] @@ -6619,8 +6619,8 @@ packages: cpu: [x64] os: [linux] - '@tauri-apps/cli-linux-x64-gnu@2.5.0': - resolution: {integrity: sha512-SG5sFNL7VMmDBdIg3nO3EzNRT306HsiEQ0N90ILe3ZABYAVoPDO/ttpCO37ApLInTzrq/DLN+gOlC/mgZvLw1w==} + '@tauri-apps/cli-linux-x64-gnu@2.9.4': + resolution: {integrity: sha512-PepPhCXc/xVvE3foykNho46OmCyx47E/aG676vKTVp+mqin5d+IBqDL6wDKiGNT5OTTxKEyNlCQ81Xs2BQhhqA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -6631,8 +6631,8 @@ packages: cpu: [x64] os: [linux] - '@tauri-apps/cli-linux-x64-musl@2.5.0': - resolution: {integrity: sha512-QXDM8zp/6v05PNWju5ELsVwF0VH1n6b5pk2E6W/jFbbiwz80Vs1lACl9pv5kEHkrxBj+aWU/03JzGuIj2g3SkQ==} + '@tauri-apps/cli-linux-x64-musl@2.9.4': + resolution: {integrity: sha512-zcd1QVffh5tZs1u1SCKUV/V7RRynebgYUNWHuV0FsIF1MjnULUChEXhAhug7usCDq4GZReMJOoXa6rukEozWIw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -6643,8 +6643,8 @@ packages: cpu: [arm64] os: [win32] - '@tauri-apps/cli-win32-arm64-msvc@2.5.0': - resolution: {integrity: sha512-pFSHFK6b+o9y4Un8w0gGLwVyFTZaC3P0kQ7umRt/BLDkzD5RnQ4vBM7CF8BCU5nkwmEBUCZd7Wt3TWZxe41o6Q==} + '@tauri-apps/cli-win32-arm64-msvc@2.9.4': + resolution: {integrity: sha512-/7ZhnP6PY04bEob23q8MH/EoDISdmR1wuNm0k9d5HV7TDMd2GGCDa8dPXA4vJuglJKXIfXqxFmZ4L+J+MO42+w==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -6655,8 +6655,8 @@ packages: cpu: [ia32] os: [win32] - '@tauri-apps/cli-win32-ia32-msvc@2.5.0': - resolution: {integrity: sha512-EArv1IaRlogdLAQyGlKmEqZqm5RfHCUMhJoedWu7GtdbOMUfSAz6FMX2boE1PtEmNO4An+g188flLeVErrxEKg==} + '@tauri-apps/cli-win32-ia32-msvc@2.9.4': + resolution: {integrity: sha512-1LmAfaC4Cq+3O1Ir1ksdhczhdtFSTIV51tbAGtbV/mr348O+M52A/xwCCXQank0OcdBxy5BctqkMtuZnQvA8uQ==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -6667,8 +6667,8 @@ packages: cpu: [x64] os: [win32] - '@tauri-apps/cli-win32-x64-msvc@2.5.0': - resolution: {integrity: sha512-lj43EFYbnAta8pd9JnUq87o+xRUR0odz+4rixBtTUwUgdRdwQ2V9CzFtsMu6FQKpFQ6mujRK6P1IEwhL6ADRsQ==} + '@tauri-apps/cli-win32-x64-msvc@2.9.4': + resolution: {integrity: sha512-EdYd4c9wGvtPB95kqtEyY+bUR+k4kRw3IA30mAQ1jPH6z57AftT8q84qwv0RDp6kkEqOBKxeInKfqi4BESYuqg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -6678,8 +6678,8 @@ packages: engines: {node: '>= 10'} hasBin: true - '@tauri-apps/cli@2.5.0': - resolution: {integrity: sha512-rAtHqG0Gh/IWLjN2zTf3nZqYqbo81oMbqop56rGTjrlWk9pTTAjkqOjSL9XQLIMZ3RbeVjveCqqCA0s8RnLdMg==} + '@tauri-apps/cli@2.9.4': + resolution: {integrity: sha512-pvylWC9QckrOS9ATWXIXcgu7g2hKK5xTL5ZQyZU/U0n9l88SEFGcWgLQNa8WZmd+wWIOWhkxOFcOl3i6ubDNNw==} engines: {node: '>= 10'} hasBin: true @@ -7354,6 +7354,17 @@ packages: vite: optional: true + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/pretty-format@2.0.5': resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} @@ -7372,6 +7383,9 @@ packages: '@vitest/spy@2.1.9': resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + '@vitest/utils@2.0.5': resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} @@ -12395,8 +12409,8 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rolldown@1.0.0-beta.50: - resolution: {integrity: sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A==} + rolldown@1.0.0-beta.52: + resolution: {integrity: sha512-Hbnpljue+JhMJrlOjQ1ixp9me7sUec7OjFvS+A1Qm8k8Xyxmw3ZhxFu7LlSXW1s9AX3POE9W9o2oqCEeR5uDmg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -13174,6 +13188,10 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} @@ -17972,7 +17990,7 @@ snapshots: '@oxc-project/types@0.94.0': {} - '@oxc-project/types@0.97.0': {} + '@oxc-project/types@0.99.0': {} '@panva/hkdf@1.2.1': {} @@ -18945,61 +18963,61 @@ snapshots: '@rolldown/binding-android-arm64@1.0.0-beta.42': optional: true - '@rolldown/binding-android-arm64@1.0.0-beta.50': + '@rolldown/binding-android-arm64@1.0.0-beta.52': optional: true '@rolldown/binding-darwin-arm64@1.0.0-beta.42': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-beta.50': + '@rolldown/binding-darwin-arm64@1.0.0-beta.52': optional: true '@rolldown/binding-darwin-x64@1.0.0-beta.42': optional: true - '@rolldown/binding-darwin-x64@1.0.0-beta.50': + '@rolldown/binding-darwin-x64@1.0.0-beta.52': optional: true '@rolldown/binding-freebsd-x64@1.0.0-beta.42': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-beta.50': + '@rolldown/binding-freebsd-x64@1.0.0-beta.52': optional: true '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.42': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.52': optional: true '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.42': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50': + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.52': optional: true '@rolldown/binding-linux-arm64-musl@1.0.0-beta.42': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50': + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.52': optional: true '@rolldown/binding-linux-x64-gnu@1.0.0-beta.42': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50': + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.52': optional: true '@rolldown/binding-linux-x64-musl@1.0.0-beta.42': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-beta.50': + '@rolldown/binding-linux-x64-musl@1.0.0-beta.52': optional: true '@rolldown/binding-openharmony-arm64@1.0.0-beta.42': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-beta.50': + '@rolldown/binding-openharmony-arm64@1.0.0-beta.52': optional: true '@rolldown/binding-wasm32-wasi@1.0.0-beta.42': @@ -19007,7 +19025,7 @@ snapshots: '@napi-rs/wasm-runtime': 1.0.6 optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-beta.50': + '@rolldown/binding-wasm32-wasi@1.0.0-beta.52': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true @@ -19015,24 +19033,24 @@ snapshots: '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.42': optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50': + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52': optional: true '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.42': optional: true - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50': + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.52': optional: true '@rolldown/binding-win32-x64-msvc@1.0.0-beta.42': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50': + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.52': optional: true '@rolldown/pluginutils@1.0.0-beta.42': {} - '@rolldown/pluginutils@1.0.0-beta.50': {} + '@rolldown/pluginutils@1.0.0-beta.52': {} '@rollup/plugin-alias@5.1.1(rollup@4.40.2)': optionalDependencies: @@ -20011,11 +20029,11 @@ snapshots: dependencies: solid-js: 1.9.6 - '@solidjs/start@1.1.3(@testing-library/jest-dom@6.5.0)(@types/node@22.15.17)(jiti@2.6.1)(solid-js@1.9.6)(terser@5.44.0)(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)': + '@solidjs/start@1.1.3(@testing-library/jest-dom@6.5.0)(@types/node@22.15.17)(jiti@2.6.1)(solid-js@1.9.6)(terser@5.44.0)(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)': dependencies: '@tanstack/server-functions-plugin': 1.119.2(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) - '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1)) - '@vinxi/server-components': 0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1)) + '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1)) + '@vinxi/server-components': 0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1)) defu: 6.1.4 error-stack-parser: 2.1.4 html-to-image: 1.11.13 @@ -20026,7 +20044,7 @@ snapshots: source-map-js: 1.2.1 terracotta: 1.0.6(solid-js@1.9.6) tinyglobby: 0.2.13 - vinxi: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) + vinxi: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) vite-plugin-solid: 2.11.6(@testing-library/jest-dom@6.5.0)(solid-js@1.9.6)(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1)) transitivePeerDependencies: - '@testing-library/jest-dom' @@ -20156,14 +20174,16 @@ snapshots: react: 19.1.1 react-dom: 19.1.1(react@19.1.1) - '@storybook/builder-vite@10.1.0-alpha.10(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5))': + '@storybook/builder-vite@10.2.0-alpha.1(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5))': dependencies: - '@storybook/csf-plugin': 10.1.0-alpha.10(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5)) + '@storybook/csf-plugin': 10.2.0-alpha.1(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1)) storybook: 8.6.12(prettier@3.5.3) ts-dedent: 2.2.0 vite: 6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - esbuild + - msw - rollup - webpack @@ -20188,7 +20208,7 @@ snapshots: - supports-color - utf-8-validate - '@storybook/csf-plugin@10.1.0-alpha.10(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5))': + '@storybook/csf-plugin@10.2.0-alpha.1(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5))': dependencies: storybook: 8.6.12(prettier@3.5.3) unplugin: 2.3.10 @@ -20466,64 +20486,64 @@ snapshots: '@tauri-apps/cli-darwin-arm64@1.6.3': optional: true - '@tauri-apps/cli-darwin-arm64@2.5.0': + '@tauri-apps/cli-darwin-arm64@2.9.4': optional: true '@tauri-apps/cli-darwin-x64@1.6.3': optional: true - '@tauri-apps/cli-darwin-x64@2.5.0': + '@tauri-apps/cli-darwin-x64@2.9.4': optional: true '@tauri-apps/cli-linux-arm-gnueabihf@1.6.3': optional: true - '@tauri-apps/cli-linux-arm-gnueabihf@2.5.0': + '@tauri-apps/cli-linux-arm-gnueabihf@2.9.4': optional: true '@tauri-apps/cli-linux-arm64-gnu@1.6.3': optional: true - '@tauri-apps/cli-linux-arm64-gnu@2.5.0': + '@tauri-apps/cli-linux-arm64-gnu@2.9.4': optional: true '@tauri-apps/cli-linux-arm64-musl@1.6.3': optional: true - '@tauri-apps/cli-linux-arm64-musl@2.5.0': + '@tauri-apps/cli-linux-arm64-musl@2.9.4': optional: true - '@tauri-apps/cli-linux-riscv64-gnu@2.5.0': + '@tauri-apps/cli-linux-riscv64-gnu@2.9.4': optional: true '@tauri-apps/cli-linux-x64-gnu@1.6.3': optional: true - '@tauri-apps/cli-linux-x64-gnu@2.5.0': + '@tauri-apps/cli-linux-x64-gnu@2.9.4': optional: true '@tauri-apps/cli-linux-x64-musl@1.6.3': optional: true - '@tauri-apps/cli-linux-x64-musl@2.5.0': + '@tauri-apps/cli-linux-x64-musl@2.9.4': optional: true '@tauri-apps/cli-win32-arm64-msvc@1.6.3': optional: true - '@tauri-apps/cli-win32-arm64-msvc@2.5.0': + '@tauri-apps/cli-win32-arm64-msvc@2.9.4': optional: true '@tauri-apps/cli-win32-ia32-msvc@1.6.3': optional: true - '@tauri-apps/cli-win32-ia32-msvc@2.5.0': + '@tauri-apps/cli-win32-ia32-msvc@2.9.4': optional: true '@tauri-apps/cli-win32-x64-msvc@1.6.3': optional: true - '@tauri-apps/cli-win32-x64-msvc@2.5.0': + '@tauri-apps/cli-win32-x64-msvc@2.9.4': optional: true '@tauri-apps/cli@1.6.3': @@ -20541,19 +20561,19 @@ snapshots: '@tauri-apps/cli-win32-ia32-msvc': 1.6.3 '@tauri-apps/cli-win32-x64-msvc': 1.6.3 - '@tauri-apps/cli@2.5.0': + '@tauri-apps/cli@2.9.4': optionalDependencies: - '@tauri-apps/cli-darwin-arm64': 2.5.0 - '@tauri-apps/cli-darwin-x64': 2.5.0 - '@tauri-apps/cli-linux-arm-gnueabihf': 2.5.0 - '@tauri-apps/cli-linux-arm64-gnu': 2.5.0 - '@tauri-apps/cli-linux-arm64-musl': 2.5.0 - '@tauri-apps/cli-linux-riscv64-gnu': 2.5.0 - '@tauri-apps/cli-linux-x64-gnu': 2.5.0 - '@tauri-apps/cli-linux-x64-musl': 2.5.0 - '@tauri-apps/cli-win32-arm64-msvc': 2.5.0 - '@tauri-apps/cli-win32-ia32-msvc': 2.5.0 - '@tauri-apps/cli-win32-x64-msvc': 2.5.0 + '@tauri-apps/cli-darwin-arm64': 2.9.4 + '@tauri-apps/cli-darwin-x64': 2.9.4 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.9.4 + '@tauri-apps/cli-linux-arm64-gnu': 2.9.4 + '@tauri-apps/cli-linux-arm64-musl': 2.9.4 + '@tauri-apps/cli-linux-riscv64-gnu': 2.9.4 + '@tauri-apps/cli-linux-x64-gnu': 2.9.4 + '@tauri-apps/cli-linux-x64-musl': 2.9.4 + '@tauri-apps/cli-win32-arm64-msvc': 2.9.4 + '@tauri-apps/cli-win32-ia32-msvc': 2.9.4 + '@tauri-apps/cli-win32-x64-msvc': 2.9.4 '@tauri-apps/plugin-clipboard-manager@2.3.0': dependencies: @@ -21294,7 +21314,7 @@ snapshots: untun: 0.1.3 uqr: 0.1.2 - '@vinxi/plugin-directives@0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))': + '@vinxi/plugin-directives@0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))': dependencies: '@babel/parser': 7.27.2 acorn: 8.14.1 @@ -21305,18 +21325,18 @@ snapshots: magicast: 0.2.11 recast: 0.23.11 tslib: 2.8.1 - vinxi: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) + vinxi: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) - '@vinxi/server-components@0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))': + '@vinxi/server-components@0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1))': dependencies: - '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1)) + '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1)) acorn: 8.14.1 acorn-loose: 8.5.0 acorn-typescript: 1.4.13(acorn@8.14.1) astring: 1.9.0 magicast: 0.2.11 recast: 0.23.11 - vinxi: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) + vinxi: 0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1) '@virtual-grid/core@2.0.1': {} @@ -21367,6 +21387,14 @@ snapshots: optionalDependencies: vite: 5.4.19(@types/node@22.15.17)(terser@5.44.0) + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.19 + optionalDependencies: + vite: 6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) + '@vitest/pretty-format@2.0.5': dependencies: tinyrainbow: 1.2.0 @@ -21394,6 +21422,10 @@ snapshots: dependencies: tinyspy: 3.0.2 + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + '@vitest/utils@2.0.5': dependencies: '@vitest/pretty-format': 2.0.5 @@ -25999,7 +26031,7 @@ snapshots: cors: 2.8.5 next: 15.5.4(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - nitropack@2.11.11(@planetscale/database@1.19.0)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(xml2js@0.6.2): + nitropack@2.11.11(@planetscale/database@1.19.0)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(mysql2@3.15.2)(xml2js@0.6.2): dependencies: '@cloudflare/kv-asset-handler': 0.4.0 '@netlify/functions': 3.1.5(encoding@0.1.13)(rollup@4.40.2) @@ -26053,7 +26085,7 @@ snapshots: pretty-bytes: 6.1.1 radix3: 1.1.2 rollup: 4.40.2 - rollup-plugin-visualizer: 5.14.0(rolldown@1.0.0-beta.50)(rollup@4.40.2) + rollup-plugin-visualizer: 5.14.0(rollup@4.40.2) scule: 1.3.0 semver: 7.7.2 serve-placeholder: 2.0.2 @@ -27360,7 +27392,7 @@ snapshots: dependencies: glob: 7.2.3 - rolldown-plugin-dts@0.16.11(rolldown@1.0.0-beta.50)(typescript@5.8.3): + rolldown-plugin-dts@0.16.11(rolldown@1.0.0-beta.52)(typescript@5.8.3): dependencies: '@babel/generator': 7.28.3 '@babel/parser': 7.28.4 @@ -27371,7 +27403,7 @@ snapshots: dts-resolver: 2.1.2 get-tsconfig: 4.11.0 magic-string: 0.30.19 - rolldown: 1.0.0-beta.50 + rolldown: 1.0.0-beta.52 optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: @@ -27399,25 +27431,25 @@ snapshots: '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.42 '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.42 - rolldown@1.0.0-beta.50: + rolldown@1.0.0-beta.52: dependencies: - '@oxc-project/types': 0.97.0 - '@rolldown/pluginutils': 1.0.0-beta.50 + '@oxc-project/types': 0.99.0 + '@rolldown/pluginutils': 1.0.0-beta.52 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.50 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.50 - '@rolldown/binding-darwin-x64': 1.0.0-beta.50 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.50 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.50 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.50 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.50 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.50 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.50 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.50 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.50 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.50 - '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.50 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.50 + '@rolldown/binding-android-arm64': 1.0.0-beta.52 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.52 + '@rolldown/binding-darwin-x64': 1.0.0-beta.52 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.52 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.52 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.52 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.52 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.52 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.52 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.52 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.52 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.52 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.52 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.52 rollup-plugin-inject@3.0.2: dependencies: @@ -27429,14 +27461,13 @@ snapshots: dependencies: rollup-plugin-inject: 3.0.2 - rollup-plugin-visualizer@5.14.0(rolldown@1.0.0-beta.50)(rollup@4.40.2): + rollup-plugin-visualizer@5.14.0(rollup@4.40.2): dependencies: open: 8.4.2 picomatch: 4.0.3 source-map: 0.7.4 yargs: 17.7.2 optionalDependencies: - rolldown: 1.0.0-beta.50 rollup: 4.40.2 rollup-pluginutils@2.8.2: @@ -28019,7 +28050,7 @@ snapshots: storybook-solidjs-vite@1.0.0-beta.7(@storybook/test@8.6.12(storybook@8.6.12(prettier@3.5.3)))(esbuild@0.25.5)(rollup@4.40.2)(solid-js@1.9.6)(storybook@8.6.12(prettier@3.5.3))(vite-plugin-solid@2.11.6(@testing-library/jest-dom@6.5.0)(solid-js@1.9.6)(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1)))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5)): dependencies: - '@storybook/builder-vite': 10.1.0-alpha.10(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5)) + '@storybook/builder-vite': 10.2.0-alpha.1(esbuild@0.25.5)(rollup@4.40.2)(storybook@8.6.12(prettier@3.5.3))(vite@6.3.5(@types/node@22.15.17)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))(webpack@5.101.3(esbuild@0.25.5)) '@storybook/types': 9.0.0-alpha.1(storybook@8.6.12(prettier@3.5.3)) magic-string: 0.30.17 solid-js: 1.9.6 @@ -28030,6 +28061,7 @@ snapshots: transitivePeerDependencies: - '@storybook/test' - esbuild + - msw - rollup - webpack @@ -28431,6 +28463,8 @@ snapshots: tinyspy@3.0.2: {} + tinyspy@4.0.4: {} + tldts-core@6.1.86: {} tldts-core@7.0.11: {} @@ -28565,8 +28599,8 @@ snapshots: diff: 8.0.2 empathic: 2.0.0 hookable: 5.5.3 - rolldown: 1.0.0-beta.50 - rolldown-plugin-dts: 0.16.11(rolldown@1.0.0-beta.50)(typescript@5.8.3) + rolldown: 1.0.0-beta.52 + rolldown-plugin-dts: 0.16.11(rolldown@1.0.0-beta.52)(typescript@5.8.3) semver: 7.7.2 tinyexec: 1.0.1 tinyglobby: 0.2.15 @@ -29159,7 +29193,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1): + vinxi@0.5.6(@planetscale/database@1.19.0)(@types/node@22.15.17)(db0@0.3.2(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(mysql2@3.15.2))(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(ioredis@5.6.1)(jiti@2.6.1)(mysql2@3.15.2)(terser@5.44.0)(xml2js@0.6.2)(yaml@2.8.1): dependencies: '@babel/core': 7.27.1 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.1) @@ -29181,7 +29215,7 @@ snapshots: hookable: 5.5.3 http-proxy: 1.18.1 micromatch: 4.0.8 - nitropack: 2.11.11(@planetscale/database@1.19.0)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(mysql2@3.15.2)(rolldown@1.0.0-beta.50)(xml2js@0.6.2) + nitropack: 2.11.11(@planetscale/database@1.19.0)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20250507.0)(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(mysql2@3.15.2))(encoding@0.1.13)(mysql2@3.15.2)(xml2js@0.6.2) node-fetch-native: 1.6.6 path-to-regexp: 6.3.0 pathe: 1.1.2 From 821645f5839d0b56991595a399ea0081246a8571 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:01:13 +0330 Subject: [PATCH 22/48] fix double cfg --- apps/desktop/src-tauri/src/windows.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 0dcf1f048e..ddfece3629 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -170,7 +170,6 @@ impl CapWindowDef { app.get_webview_window(&label) } - #[cfg(target_os = "macos")] #[cfg(target_os = "macos")] pub const fn undecorated(&self) -> bool { matches!( From 5914222ecf342ee47afe812f299cedf1eaf4b3a9 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:03:42 +0330 Subject: [PATCH 23/48] Remove previously added min inner size limit for Settings window on macOS --- apps/desktop/src-tauri/src/windows.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index ddfece3629..8270bfda22 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -436,11 +436,6 @@ impl CapWindow { .maximized(false) .center(); - #[cfg(target_os = "macos")] - { - builder = builder.max_inner_size(650.0, f64::MAX); - } - builder.build()? } Self::Editor { .. } => { From 17e6ecb44bb13d8b002f4ef262c94912464a1f07 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Thu, 4 Dec 2025 12:16:11 +0400 Subject: [PATCH 24/48] fmt --- apps/desktop/src/routes/editor/Editor.tsx | 1164 ++++++++--------- .../src/routes/editor/Timeline/ZoomTrack.tsx | 374 +++--- 2 files changed, 770 insertions(+), 768 deletions(-) diff --git a/apps/desktop/src/routes/editor/Editor.tsx b/apps/desktop/src/routes/editor/Editor.tsx index 2d64a3385a..4f9444228f 100644 --- a/apps/desktop/src/routes/editor/Editor.tsx +++ b/apps/desktop/src/routes/editor/Editor.tsx @@ -9,23 +9,23 @@ import { convertFileSrc } from "@tauri-apps/api/core"; import { LogicalPosition } from "@tauri-apps/api/dpi"; import { Menu } from "@tauri-apps/api/menu"; import { - createEffect, - createMemo, - createSignal, - Match, - on, - Show, - Switch, + createEffect, + createMemo, + createSignal, + Match, + on, + Show, + Switch, } from "solid-js"; import { createStore } from "solid-js/store"; import { Transition } from "solid-transition-group"; import { - CROP_ZERO, - type CropBounds, - Cropper, - type CropperRef, - createCropOptionsMenuItems, - type Ratio, + CROP_ZERO, + type CropBounds, + Cropper, + type CropperRef, + createCropOptionsMenuItems, + type Ratio, } from "~/components/Cropper"; import { Toggle } from "~/components/Toggle"; import { composeEventHandlers } from "~/utils/composeEventHandlers"; @@ -33,12 +33,12 @@ import { createTauriEventListener } from "~/utils/createEventListener"; import { commands, events } from "~/utils/tauri"; import { ConfigSidebar } from "./ConfigSidebar"; import { - EditorContextProvider, - EditorInstanceContextProvider, - FPS, - serializeProjectConfiguration, - useEditorContext, - useEditorInstanceContext, + EditorContextProvider, + EditorInstanceContextProvider, + FPS, + serializeProjectConfiguration, + useEditorContext, + useEditorInstanceContext, } from "./context"; import { ExportDialog } from "./ExportDialog"; import { Header } from "./Header"; @@ -53,573 +53,573 @@ const RESIZE_HANDLE_HEIGHT = 8; const MIN_PLAYER_HEIGHT = MIN_PLAYER_CONTENT_HEIGHT + RESIZE_HANDLE_HEIGHT; export function Editor() { - return ( - - { - const ctx = useEditorInstanceContext(); - const editorInstance = ctx.editorInstance(); - - if (!editorInstance || !ctx.metaQuery.data) return; - - return { - editorInstance, - meta() { - const d = ctx.metaQuery.data; - if (!d) - throw new Error( - "metaQuery.data is undefined - how did this happen?" - ); - return d; - }, - refetchMeta: async () => { - await ctx.metaQuery.refetch(); - }, - }; - })()} - > - {(values) => ( - - - - )} - - - ); + return ( + + { + const ctx = useEditorInstanceContext(); + const editorInstance = ctx.editorInstance(); + + if (!editorInstance || !ctx.metaQuery.data) return; + + return { + editorInstance, + meta() { + const d = ctx.metaQuery.data; + if (!d) + throw new Error( + "metaQuery.data is undefined - how did this happen?", + ); + return d; + }, + refetchMeta: async () => { + await ctx.metaQuery.refetch(); + }, + }; + })()} + > + {(values) => ( + + + + )} + + + ); } function Inner() { - const { project, editorState, setEditorState, previewResolutionBase } = - useEditorContext(); - - const [layoutRef, setLayoutRef] = createSignal(); - const layoutBounds = createElementBounds(layoutRef); - const [storedTimelineHeight, setStoredTimelineHeight] = makePersisted( - createSignal(DEFAULT_TIMELINE_HEIGHT), - { name: "editorTimelineHeight" } - ); - const [isResizingTimeline, setIsResizingTimeline] = createSignal(false); - - const clampTimelineHeight = (value: number) => { - const available = layoutBounds.height ?? 0; - const maxHeight = - available > 0 - ? Math.max(MIN_TIMELINE_HEIGHT, available - MIN_PLAYER_HEIGHT) - : Number.POSITIVE_INFINITY; - const upperBound = Number.isFinite(maxHeight) - ? maxHeight - : Math.max(value, MIN_TIMELINE_HEIGHT); - return Math.min(Math.max(value, MIN_TIMELINE_HEIGHT), upperBound); - }; - - const timelineHeight = createMemo(() => - Math.round(clampTimelineHeight(storedTimelineHeight())) - ); - - const handleTimelineResizeStart = (event: MouseEvent) => { - if (event.button !== 0) return; - event.preventDefault(); - const startY = event.clientY; - const startHeight = timelineHeight(); - setIsResizingTimeline(true); - - const handleMove = (moveEvent: MouseEvent) => { - const delta = moveEvent.clientY - startY; - setStoredTimelineHeight(clampTimelineHeight(startHeight - delta)); - }; - - const handleUp = () => { - setIsResizingTimeline(false); - window.removeEventListener("mousemove", handleMove); - window.removeEventListener("mouseup", handleUp); - }; - - window.addEventListener("mousemove", handleMove); - window.addEventListener("mouseup", handleUp); - }; - - createEffect(() => { - const available = layoutBounds.height; - if (!available) return; - setStoredTimelineHeight((height) => clampTimelineHeight(height)); - }); - - createTauriEventListener(events.editorStateChanged, (payload) => { - throttledRenderFrame.clear(); - trailingRenderFrame.clear(); - setEditorState("playbackTime", payload.playhead_position / FPS); - }); - - const emitRenderFrame = (time: number) => { - if (!editorState.playing) { - events.renderFrameEvent.emit({ - frame_number: Math.max(Math.floor(time * FPS), 0), - fps: FPS, - resolution_base: previewResolutionBase(), - }); - } - }; - - const throttledRenderFrame = throttle(emitRenderFrame, 1000 / FPS); - - const trailingRenderFrame = debounce(emitRenderFrame, 1000 / FPS + 16); - - const renderFrame = (time: number) => { - throttledRenderFrame(time); - trailingRenderFrame(time); - }; - - const frameNumberToRender = createMemo(() => { - const preview = editorState.previewTime; - if (preview !== null) return preview; - return editorState.playbackTime; - }); - - createEffect( - on( - () => [frameNumberToRender(), previewResolutionBase()], - ([number]) => { - if (editorState.playing) return; - renderFrame(number as number); - } - ) - ); - - const updateConfigAndRender = throttle(async (time: number) => { - const config = serializeProjectConfiguration(project); - await commands.updateProjectConfigInMemory(config); - renderFrame(time); - }, 1000 / FPS); - createEffect( - on( - () => trackDeep(project), - () => { - updateConfigAndRender(editorState.playbackTime); - } - ) - ); - - return ( - <> -
-
-
-
-
- - - -
-
-
- -
-
-
- -
- - ); + const { project, editorState, setEditorState, previewResolutionBase } = + useEditorContext(); + + const [layoutRef, setLayoutRef] = createSignal(); + const layoutBounds = createElementBounds(layoutRef); + const [storedTimelineHeight, setStoredTimelineHeight] = makePersisted( + createSignal(DEFAULT_TIMELINE_HEIGHT), + { name: "editorTimelineHeight" }, + ); + const [isResizingTimeline, setIsResizingTimeline] = createSignal(false); + + const clampTimelineHeight = (value: number) => { + const available = layoutBounds.height ?? 0; + const maxHeight = + available > 0 + ? Math.max(MIN_TIMELINE_HEIGHT, available - MIN_PLAYER_HEIGHT) + : Number.POSITIVE_INFINITY; + const upperBound = Number.isFinite(maxHeight) + ? maxHeight + : Math.max(value, MIN_TIMELINE_HEIGHT); + return Math.min(Math.max(value, MIN_TIMELINE_HEIGHT), upperBound); + }; + + const timelineHeight = createMemo(() => + Math.round(clampTimelineHeight(storedTimelineHeight())), + ); + + const handleTimelineResizeStart = (event: MouseEvent) => { + if (event.button !== 0) return; + event.preventDefault(); + const startY = event.clientY; + const startHeight = timelineHeight(); + setIsResizingTimeline(true); + + const handleMove = (moveEvent: MouseEvent) => { + const delta = moveEvent.clientY - startY; + setStoredTimelineHeight(clampTimelineHeight(startHeight - delta)); + }; + + const handleUp = () => { + setIsResizingTimeline(false); + window.removeEventListener("mousemove", handleMove); + window.removeEventListener("mouseup", handleUp); + }; + + window.addEventListener("mousemove", handleMove); + window.addEventListener("mouseup", handleUp); + }; + + createEffect(() => { + const available = layoutBounds.height; + if (!available) return; + setStoredTimelineHeight((height) => clampTimelineHeight(height)); + }); + + createTauriEventListener(events.editorStateChanged, (payload) => { + throttledRenderFrame.clear(); + trailingRenderFrame.clear(); + setEditorState("playbackTime", payload.playhead_position / FPS); + }); + + const emitRenderFrame = (time: number) => { + if (!editorState.playing) { + events.renderFrameEvent.emit({ + frame_number: Math.max(Math.floor(time * FPS), 0), + fps: FPS, + resolution_base: previewResolutionBase(), + }); + } + }; + + const throttledRenderFrame = throttle(emitRenderFrame, 1000 / FPS); + + const trailingRenderFrame = debounce(emitRenderFrame, 1000 / FPS + 16); + + const renderFrame = (time: number) => { + throttledRenderFrame(time); + trailingRenderFrame(time); + }; + + const frameNumberToRender = createMemo(() => { + const preview = editorState.previewTime; + if (preview !== null) return preview; + return editorState.playbackTime; + }); + + createEffect( + on( + () => [frameNumberToRender(), previewResolutionBase()], + ([number]) => { + if (editorState.playing) return; + renderFrame(number as number); + }, + ), + ); + + const updateConfigAndRender = throttle(async (time: number) => { + const config = serializeProjectConfiguration(project); + await commands.updateProjectConfigInMemory(config); + renderFrame(time); + }, 1000 / FPS); + createEffect( + on( + () => trackDeep(project), + () => { + updateConfigAndRender(editorState.playbackTime); + }, + ), + ); + + return ( + <> +
+
+
+
+
+ + + +
+
+
+ +
+
+
+ +
+ + ); } function Dialogs() { - const { dialog, setDialog, presets, project } = useEditorContext(); - - return ( - { - const d = dialog(); - if ("type" in d && d.type === "crop") return "lg"; - return "sm"; - })()} - contentClass={(() => { - const d = dialog(); - if ("type" in d && d.type === "export") return "max-w-[740px]"; - return ""; - })()} - open={dialog().open} - onOpenChange={(o) => { - if (!o) setDialog((d) => ({ ...d, open: false })); - }} - > - { - const d = dialog(); - if ("type" in d) return d; - })()} - > - {(dialog) => ( - - - - - - {(_) => { - const [form, setForm] = createStore({ - name: "", - default: false, - }); - - const createPreset = createMutation(() => ({ - mutationFn: async () => { - await presets.createPreset({ ...form, config: project }); - }, - onSuccess: () => { - setDialog((d) => ({ ...d, open: false })); - }, - })); - - return ( - createPreset.mutate()} - > - Create - - } - > - - setForm("name", e.currentTarget.value)} - /> - - setForm("default", checked)} - /> - - - ); - }} - - { - const d = dialog(); - if (d.type === "renamePreset") return d; - })()} - > - {(dialog) => { - const [name, setName] = createSignal( - presets.query.data?.presets[dialog().presetIndex].name! - ); - - const renamePreset = createMutation(() => ({ - mutationFn: async () => - presets.renamePreset(dialog().presetIndex, name()), - onSuccess: () => { - setDialog((d) => ({ ...d, open: false })); - }, - })); - - return ( - renamePreset.mutate()} - > - Rename - - } - > - - setName(e.currentTarget.value)} - /> - - ); - }} - - { - const d = dialog(); - if (d.type === "deletePreset") return d; - })()} - > - {(dialog) => { - const deletePreset = createMutation(() => ({ - mutationFn: async () => { - await presets.deletePreset(dialog().presetIndex); - await presets.query.refetch(); - }, - onSuccess: () => { - setDialog((d) => ({ ...d, open: false })); - }, - })); - - return ( - deletePreset.mutate()} - disabled={deletePreset.isPending} - > - Delete - - } - > -

- Are you sure you want to delete this preset? -

-
- ); - }} -
- { - const d = dialog(); - if (d.type === "crop") return d; - })()} - > - {(dialog) => { - const { setProject: setState, editorInstance } = - useEditorContext(); - const display = editorInstance.recordings.segments[0].display; - - let cropperRef: CropperRef | undefined; - const [crop, setCrop] = createSignal(CROP_ZERO); - const [aspect, setAspect] = createSignal(null); - - const initialBounds = { - x: dialog().position.x, - y: dialog().position.y, - width: dialog().size.x, - height: dialog().size.y, - }; - - const [snapToRatio, setSnapToRatioEnabled] = makePersisted( - createSignal(true), - { name: "editorCropSnapToRatio" } - ); - - async function showCropOptionsMenu( - e: UIEvent, - positionAtCursor = false - ) { - e.preventDefault(); - const items = createCropOptionsMenuItems({ - aspect: aspect(), - snapToRatioEnabled: snapToRatio(), - onAspectSet: setAspect, - onSnapToRatioSet: setSnapToRatioEnabled, - }); - const menu = await Menu.new({ items }); - let pos: LogicalPosition | undefined; - if (!positionAtCursor) { - const rect = ( - e.target as HTMLDivElement - ).getBoundingClientRect(); - pos = new LogicalPosition(rect.x, rect.y + 40); - } - await menu.popup(pos); - await menu.close(); - } - - function BoundInput(props: { - field: keyof CropBounds; - min?: number; - max?: number; - }) { - return ( - { - cropperRef?.setCropProperty(props.field, v); - }} - changeOnWheel={true} - format={false} - > - ([ - (e) => e.stopPropagation(), - ])} - /> - - ); - } - - return ( - <> - -
-
- Size -
- -
- × -
- -
-
-
- Position -
- -
- × -
- -
-
-
-
-
- - - - } - onClick={() => cropperRef?.fill()} - disabled={ - crop().width === display.width && - crop().height === display.height - } - > - Full - - } - onClick={() => { - cropperRef?.reset(); - setAspect(null); - }} - disabled={ - crop().x === dialog().position.x && - crop().y === dialog().position.y && - crop().width === dialog().size.x && - crop().height === dialog().size.y - } - > - Reset - -
-
- -
-
- showCropOptionsMenu(e, true)} - > - screenshot - -
-
-
- - - - - ); - }} -
-
- )} -
-
- ); + const { dialog, setDialog, presets, project } = useEditorContext(); + + return ( + { + const d = dialog(); + if ("type" in d && d.type === "crop") return "lg"; + return "sm"; + })()} + contentClass={(() => { + const d = dialog(); + if ("type" in d && d.type === "export") return "max-w-[740px]"; + return ""; + })()} + open={dialog().open} + onOpenChange={(o) => { + if (!o) setDialog((d) => ({ ...d, open: false })); + }} + > + { + const d = dialog(); + if ("type" in d) return d; + })()} + > + {(dialog) => ( + + + + + + {(_) => { + const [form, setForm] = createStore({ + name: "", + default: false, + }); + + const createPreset = createMutation(() => ({ + mutationFn: async () => { + await presets.createPreset({ ...form, config: project }); + }, + onSuccess: () => { + setDialog((d) => ({ ...d, open: false })); + }, + })); + + return ( + createPreset.mutate()} + > + Create + + } + > + + setForm("name", e.currentTarget.value)} + /> + + setForm("default", checked)} + /> + + + ); + }} + + { + const d = dialog(); + if (d.type === "renamePreset") return d; + })()} + > + {(dialog) => { + const [name, setName] = createSignal( + presets.query.data?.presets[dialog().presetIndex].name!, + ); + + const renamePreset = createMutation(() => ({ + mutationFn: async () => + presets.renamePreset(dialog().presetIndex, name()), + onSuccess: () => { + setDialog((d) => ({ ...d, open: false })); + }, + })); + + return ( + renamePreset.mutate()} + > + Rename + + } + > + + setName(e.currentTarget.value)} + /> + + ); + }} + + { + const d = dialog(); + if (d.type === "deletePreset") return d; + })()} + > + {(dialog) => { + const deletePreset = createMutation(() => ({ + mutationFn: async () => { + await presets.deletePreset(dialog().presetIndex); + await presets.query.refetch(); + }, + onSuccess: () => { + setDialog((d) => ({ ...d, open: false })); + }, + })); + + return ( + deletePreset.mutate()} + disabled={deletePreset.isPending} + > + Delete + + } + > +

+ Are you sure you want to delete this preset? +

+
+ ); + }} +
+ { + const d = dialog(); + if (d.type === "crop") return d; + })()} + > + {(dialog) => { + const { setProject: setState, editorInstance } = + useEditorContext(); + const display = editorInstance.recordings.segments[0].display; + + let cropperRef: CropperRef | undefined; + const [crop, setCrop] = createSignal(CROP_ZERO); + const [aspect, setAspect] = createSignal(null); + + const initialBounds = { + x: dialog().position.x, + y: dialog().position.y, + width: dialog().size.x, + height: dialog().size.y, + }; + + const [snapToRatio, setSnapToRatioEnabled] = makePersisted( + createSignal(true), + { name: "editorCropSnapToRatio" }, + ); + + async function showCropOptionsMenu( + e: UIEvent, + positionAtCursor = false, + ) { + e.preventDefault(); + const items = createCropOptionsMenuItems({ + aspect: aspect(), + snapToRatioEnabled: snapToRatio(), + onAspectSet: setAspect, + onSnapToRatioSet: setSnapToRatioEnabled, + }); + const menu = await Menu.new({ items }); + let pos: LogicalPosition | undefined; + if (!positionAtCursor) { + const rect = ( + e.target as HTMLDivElement + ).getBoundingClientRect(); + pos = new LogicalPosition(rect.x, rect.y + 40); + } + await menu.popup(pos); + await menu.close(); + } + + function BoundInput(props: { + field: keyof CropBounds; + min?: number; + max?: number; + }) { + return ( + { + cropperRef?.setCropProperty(props.field, v); + }} + changeOnWheel={true} + format={false} + > + ([ + (e) => e.stopPropagation(), + ])} + /> + + ); + } + + return ( + <> + +
+
+ Size +
+ +
+ × +
+ +
+
+
+ Position +
+ +
+ × +
+ +
+
+
+
+
+ + + + } + onClick={() => cropperRef?.fill()} + disabled={ + crop().width === display.width && + crop().height === display.height + } + > + Full + + } + onClick={() => { + cropperRef?.reset(); + setAspect(null); + }} + disabled={ + crop().x === dialog().position.x && + crop().y === dialog().position.y && + crop().width === dialog().size.x && + crop().height === dialog().size.y + } + > + Reset + +
+
+ +
+
+ showCropOptionsMenu(e, true)} + > + screenshot + +
+
+
+ + + + + ); + }} +
+
+ )} +
+
+ ); } diff --git a/apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx b/apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx index b0e8665ff7..4625510d7c 100644 --- a/apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx +++ b/apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx @@ -281,7 +281,7 @@ export function ZoomTrack(props: { const { setTrackState } = useTrackContext(); const zoomPercentage = () => { - const amount = segment.amount; + const amount = segment().amount; return `${amount.toFixed(1)}x`; }; @@ -313,12 +313,11 @@ export function ZoomTrack(props: { e.stopPropagation(); const currentSelection = editorState.timeline.selection; - const segmentIndex = i(); + const segmentIndex = i; const isMultiSelect = e.ctrlKey || e.metaKey; const isRangeSelect = e.shiftKey; if (isRangeSelect && currentSelection?.type === "zoom") { - // Range selection: select from last selected to current const existingIndices = currentSelection.indices; const lastIndex = existingIndices[existingIndices.length - 1]; @@ -334,7 +333,6 @@ export function ZoomTrack(props: { indices: rangeIndices, }); } else if (isMultiSelect) { - // Handle multi-selection with Ctrl/Cmd+click if (currentSelection?.type === "zoom") { const baseIndices = currentSelection.indices; const exists = baseIndices.includes(segmentIndex); @@ -351,14 +349,12 @@ export function ZoomTrack(props: { setEditorState("timeline", "selection", null); } } else { - // Start new multi-selection setEditorState("timeline", "selection", { type: "zoom", indices: [segmentIndex], }); } } else { - // Normal single selection setEditorState("timeline", "selection", { type: "zoom", indices: [segmentIndex], @@ -405,200 +401,206 @@ export function ZoomTrack(props: { const selection = editorState.timeline.selection; if (!selection || selection.type !== "zoom") return false; - const segmentIndex = project.timeline?.zoomSegments?.findIndex( - (s) => s.start === segment.start && s.end === segment.end, - ); + const seg = segment(); + const segmentIndex = project.timeline?.zoomSegments?.findIndex( + (s) => s.start === seg.start && s.end === seg.end, + ); - if (segmentIndex === undefined || segmentIndex === -1) return false; + if (segmentIndex === undefined || segmentIndex === -1) return false; - return selection.indices.includes(segmentIndex); - }); + return selection.indices.includes(segmentIndex); + }); - return ( - { - e.stopPropagation(); - - if (editorState.timeline.interactMode === "split") { - const rect = e.currentTarget.getBoundingClientRect(); - const fraction = (e.clientX - rect.left) / rect.width; - - const splitTime = fraction * (segment.end - segment.start); - - projectActions.splitZoomSegment(i(), splitTime); - } - }} - > - { - const start = segment.start; + return ( + { + e.stopPropagation(); - let minValue = 0; + if (editorState.timeline.interactMode === "split") { + const rect = e.currentTarget.getBoundingClientRect(); + const fraction = (e.clientX - rect.left) / rect.width; + const seg = segment(); - const maxValue = segment.end - 1; + const splitTime = fraction * (seg.end - seg.start); - for (let i = zoomSegments().length - 1; i >= 0; i--) { - const segment = zoomSegments()[i]!; - if (segment.end <= start) { - minValue = segment.end; - break; + projectActions.splitZoomSegment(i, splitTime); + } + }} + > + { + const seg = segment(); + const start = seg.start; + + let minValue = 0; + + const maxValue = seg.end - 1; + + for (let idx = zoomSegments().length - 1; idx >= 0; idx--) { + const zs = zoomSegments()[idx]; + if (zs && zs.end <= start) { + minValue = zs.end; + break; + } } - } - return { start, minValue, maxValue }; - }, - (e, value, initialMouseX) => { - const newStart = - value.start + - (e.clientX - initialMouseX) * secsPerPixel(); - - setProject( - "timeline", - "zoomSegments", - i(), - "start", - Math.min( - value.maxValue, - Math.max(value.minValue, newStart), - ), - ); - - setProject( - "timeline", - "zoomSegments", - produce((s) => { - s.sort((a, b) => a.start - b.start); - }), - ); - }, - )} - /> - { - const original = { ...segment }; - - const prevSegment = zoomSegments()[i() - 1]; - const nextSegment = zoomSegments()[i() + 1]; - - const minStart = prevSegment?.end ?? 0; - const maxEnd = nextSegment?.start ?? duration(); - - return { - original, - minStart, - maxEnd, - }; - }, - (e, value, initialMouseX) => { - const rawDelta = - (e.clientX - initialMouseX) * secsPerPixel(); - - const newStart = value.original.start + rawDelta; - const newEnd = value.original.end + rawDelta; - - let delta = rawDelta; - - if (newStart < value.minStart) - delta = value.minStart - value.original.start; - else if (newEnd > value.maxEnd) - delta = value.maxEnd - value.original.end; - - setProject("timeline", "zoomSegments", i(), { - start: value.original.start + delta, - end: value.original.end + delta, - }); - }, - )} - > - {(() => { - const ctx = useSegmentContext(); - - return ( - - -
- -
-
- -
- - {zoomPercentage()} -
-
- -
- Zoom -
- - {zoomPercentage()} -
-
-
-
- ); - })()} -
- { - const end = segment.end; + return { start, minValue, maxValue }; + }, + (e, value, initialMouseX) => { + const newStart = + value.start + + (e.clientX - initialMouseX) * secsPerPixel(); + + setProject( + "timeline", + "zoomSegments", + i, + "start", + Math.min( + value.maxValue, + Math.max(value.minValue, newStart), + ), + ); + + setProject( + "timeline", + "zoomSegments", + produce((s) => { + s.sort((a, b) => a.start - b.start); + }), + ); + }, + )} + /> + { + const seg = segment(); + const original = { ...seg }; + const currentIndex = i; + + const prevSegment = zoomSegments()[currentIndex - 1]; + const nextSegment = zoomSegments()[currentIndex + 1]; + + const minStart = prevSegment?.end ?? 0; + const maxEnd = nextSegment?.start ?? duration(); + + return { + original, + minStart, + maxEnd, + }; + }, + (e, value, initialMouseX) => { + const rawDelta = + (e.clientX - initialMouseX) * secsPerPixel(); - const minValue = segment.start + 1; + const newStart = value.original.start + rawDelta; + const newEnd = value.original.end + rawDelta; - let maxValue = duration(); + let delta = rawDelta; - for (let i = 0; i < zoomSegments().length; i++) { - const segment = zoomSegments()[i]!; - if (segment.start > end) { - maxValue = segment.start; - break; - } - } + if (newStart < value.minStart) + delta = value.minStart - value.original.start; + else if (newEnd > value.maxEnd) + delta = value.maxEnd - value.original.end; - return { end, minValue, maxValue }; - }, - (e, value, initialMouseX) => { - const newEnd = - value.end + (e.clientX - initialMouseX) * secsPerPixel(); - - setProject( - "timeline", - "zoomSegments", - i(), - "end", - Math.min( - value.maxValue, - Math.max(value.minValue, newEnd), - ), + setProject("timeline", "zoomSegments", i, { + start: value.original.start + delta, + end: value.original.end + delta, + }); + }, + )} + > + {(() => { + const ctx = useSegmentContext(); + + return ( + + +
+ +
+
+ +
+ + {zoomPercentage()} +
+
+ +
+ Zoom +
+ + {zoomPercentage()} +
+
+
+
); + })()} +
+ { + const seg = segment(); + const end = seg.end; + + const minValue = seg.start + 1; + + let maxValue = duration(); + + for (let idx = 0; idx < zoomSegments().length; idx++) { + const zs = zoomSegments()[idx]; + if (zs && zs.start > end) { + maxValue = zs.start; + break; + } + } - setProject( - "timeline", - "zoomSegments", - produce((s) => { - s.sort((a, b) => a.start - b.start); - }), - ); - }, - )} - /> -
- ); - }} - + return { end, minValue, maxValue }; + }, + (e, value, initialMouseX) => { + const newEnd = + value.end + (e.clientX - initialMouseX) * secsPerPixel(); + + setProject( + "timeline", + "zoomSegments", + i, + "end", + Math.min( + value.maxValue, + Math.max(value.minValue, newEnd), + ), + ); + + setProject( + "timeline", + "zoomSegments", + produce((s) => { + s.sort((a, b) => a.start - b.start); + }), + ); + }, + )} + /> +
+ ); + }} + Date: Thu, 4 Dec 2025 12:22:09 +0400 Subject: [PATCH 25/48] fix --- apps/desktop/src-tauri/src/windows.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index ba1b3b80ac..5a2adf0468 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -276,7 +276,7 @@ impl CapWindow { } }; - let window_label = CapWindowId::Editor { id: window_id }.label(); + let window_label = CapWindowDef::Editor { id: window_id }.label(); PendingEditorInstances::start_prewarm(app, window_label, project_path.clone()).await; } From 51b78b0e198515cc77f7ef6d4cae8abc2a94e1ce Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 4 Dec 2025 12:30:36 +0330 Subject: [PATCH 26/48] oops (fix thing getting removed when resolving merge conflict) --- apps/desktop/src-tauri/src/windows.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 5a2adf0468..39cd6c3dac 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -280,6 +280,19 @@ impl CapWindow { PendingEditorInstances::start_prewarm(app, window_label, project_path.clone()).await; } + if let Self::ScreenshotEditor { path } = &self { + let state = app.state::(); + let mut s = state.ids.lock().unwrap(); + if !s.iter().any(|(p, _)| p == path) { + s.push(( + path.clone(), + state + .counter + .fetch_add(1, std::sync::atomic::Ordering::SeqCst), + )); + } + } + let def = self.def(app); if let Some(window) = def.get(app) { window.show().ok(); From b16cd8cd9147a29e71626ef487203b72fc409577 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 4 Dec 2025 12:54:37 +0330 Subject: [PATCH 27/48] ScreenshotEditor traffic lights pos --- apps/desktop/src-tauri/src/windows.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 39cd6c3dac..8caff29efa 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -162,7 +162,7 @@ impl CapWindowDef { #[cfg(target_os = "macos")] pub const fn pre_solarium_traffic_lights_position(&self) -> LogicalPosition { match self { - Self::Editor { .. } => LogicalPosition::new(20.0, 32.0), + Self::Editor { .. } | Self::ScreenshotEditor { .. } => LogicalPosition::new(20.0, 32.0), _ => LogicalPosition::new(12.0, 20.0), } } From e285de72c1f117a4ff4fdde3f84406ad546855eb Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 4 Dec 2025 13:07:26 +0330 Subject: [PATCH 28/48] Fix Cropper visual in screenshot editor --- apps/desktop/src/routes/screenshot-editor/Editor.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/routes/screenshot-editor/Editor.tsx b/apps/desktop/src/routes/screenshot-editor/Editor.tsx index 2785ae3d12..d8d82a6383 100644 --- a/apps/desktop/src/routes/screenshot-editor/Editor.tsx +++ b/apps/desktop/src/routes/screenshot-editor/Editor.tsx @@ -347,7 +347,7 @@ function Dialogs() {
{ const srcW = cropDialog().size.x; @@ -383,7 +383,7 @@ function Dialogs() { }} initialCrop={initialBounds} snapToRatioEnabled={snapToRatio()} - showBounds={true} + showBounds={false} allowLightMode={true} onContextMenu={(e) => showCropOptionsMenu(e, true)} > From eca16fd0e3da04f7d0792a572e0910765f5a781c Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 4 Dec 2025 13:16:45 +0330 Subject: [PATCH 29/48] Update windows.rs --- apps/desktop/src-tauri/src/windows.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src-tauri/src/windows.rs b/apps/desktop/src-tauri/src/windows.rs index 8caff29efa..c8a929fb78 100644 --- a/apps/desktop/src-tauri/src/windows.rs +++ b/apps/desktop/src-tauri/src/windows.rs @@ -162,8 +162,8 @@ impl CapWindowDef { #[cfg(target_os = "macos")] pub const fn pre_solarium_traffic_lights_position(&self) -> LogicalPosition { match self { - Self::Editor { .. } | Self::ScreenshotEditor { .. } => LogicalPosition::new(20.0, 32.0), - _ => LogicalPosition::new(12.0, 20.0), + Self::Editor { .. } | Self::ScreenshotEditor { .. } => LogicalPosition::new(20.0, 25.0), + _ => LogicalPosition::new(12.0, 16.0), } } From 96d33d9b3f8d668307bea54cf809c25b51e153af Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:13:38 +0330 Subject: [PATCH 30/48] Update package.json --- apps/desktop/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 7d700caa8d..ba000a42a2 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -73,7 +73,7 @@ "devDependencies": { "@fontsource/geist-sans": "^5.0.3", "@iconify/json": "^2.2.239", - "@tauri-apps/cli": "^2.9.4", + "@tauri-apps/cli": "^2.9.5", "@total-typescript/ts-reset": "^0.6.1", "@types/dom-webcodecs": "^0.1.11", "@types/uuid": "^9.0.8", From 18d966f2d35147ec6333fa6eebef065184e95885 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Fri, 5 Dec 2025 03:17:24 +0330 Subject: [PATCH 31/48] macOS Hard minimum system version set to 13.1 --- apps/desktop/src-tauri/tauri.conf.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 76d6e5a4a8..5b7777b1b7 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -54,6 +54,7 @@ "../src/assets/rive/*.riv": "assets/rive/" }, "macOS": { + "minimumSystemVersion": "13.1", "dmg": { "background": "assets/dmg-background.png", "appPosition": { From 9226231c5cff96b2200eff3f29de96900d7217ce Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 6 Dec 2025 23:17:32 +0330 Subject: [PATCH 32/48] Tailwind 4 auto update + tw config changes --- .../src/components/CapErrorBoundary.tsx | 4 +- apps/desktop/src/components/Loader.tsx | 2 +- apps/desktop/src/components/SignInButton.tsx | 2 +- apps/desktop/src/components/Toggle.tsx | 12 +- .../src/components/titlebar/Titlebar.tsx | 6 +- apps/desktop/src/entry-server.tsx | 2 +- apps/desktop/src/routes/(window-chrome).tsx | 2 +- .../src/routes/(window-chrome)/(main).tsx | 32 +- .../(window-chrome)/new-main/CameraSelect.tsx | 2 +- .../new-main/MicrophoneSelect.tsx | 2 +- .../(window-chrome)/new-main/TargetCard.tsx | 8 +- .../new-main/TargetDropdownButton.tsx | 2 +- .../routes/(window-chrome)/new-main/index.tsx | 6 +- .../src/routes/(window-chrome)/settings.tsx | 8 +- .../(window-chrome)/settings/changelog.tsx | 12 +- .../(window-chrome)/settings/hotkeys.tsx | 2 +- .../settings/integrations/s3-config.tsx | 4 +- .../(window-chrome)/settings/license.tsx | 8 +- .../(window-chrome)/settings/recordings.tsx | 8 +- .../(window-chrome)/settings/screenshots.tsx | 6 +- .../src/routes/(window-chrome)/setup.tsx | 18 +- .../src/routes/(window-chrome)/update.tsx | 10 +- .../src/routes/(window-chrome)/upgrade.tsx | 14 +- apps/desktop/src/routes/camera.tsx | 4 +- apps/desktop/src/routes/capture-area.tsx | 10 +- apps/desktop/src/routes/debug.tsx | 2 +- .../src/routes/editor/AspectRatioSelect.tsx | 2 +- .../desktop/src/routes/editor/CaptionsTab.tsx | 10 +- .../src/routes/editor/ConfigSidebar.tsx | 46 +- apps/desktop/src/routes/editor/Editor.tsx | 22 +- .../src/routes/editor/ExportDialog.tsx | 4 +- apps/desktop/src/routes/editor/Header.tsx | 2 +- .../src/routes/editor/PresetsDropdown.tsx | 2 +- .../desktop/src/routes/editor/ShareButton.tsx | 6 +- .../src/routes/editor/Timeline/ClipTrack.tsx | 12 +- .../src/routes/editor/Timeline/MaskTrack.tsx | 6 +- .../src/routes/editor/Timeline/SceneTrack.tsx | 8 +- .../src/routes/editor/Timeline/TextTrack.tsx | 8 +- .../src/routes/editor/Timeline/Track.tsx | 4 +- .../routes/editor/Timeline/TrackManager.tsx | 4 +- .../src/routes/editor/Timeline/ZoomTrack.tsx | 8 +- .../src/routes/editor/Timeline/index.tsx | 8 +- apps/desktop/src/routes/editor/ui.tsx | 24 +- .../src/routes/in-progress-recording.tsx | 10 +- .../desktop/src/routes/recordings-overlay.tsx | 18 +- .../screenshot-editor/AnnotationConfig.tsx | 2 +- .../screenshot-editor/AnnotationTools.tsx | 2 +- .../routes/screenshot-editor/ColorPicker.tsx | 8 +- .../src/routes/screenshot-editor/Editor.tsx | 22 +- .../popovers/AspectRatioSelect.tsx | 2 +- .../popovers/BackgroundSettingsPopover.tsx | 4 +- .../popovers/RoundingPopover.tsx | 4 +- .../src/routes/screenshot-editor/ui.tsx | 24 +- .../src/routes/target-select-overlay.tsx | 10 +- packages/ui-solid/package.json | 11 +- packages/ui-solid/src/Button.tsx | 10 +- packages/ui-solid/src/SwitchTab.tsx | 2 +- packages/ui-solid/src/main.css | 181 ++++++- pnpm-lock.yaml | 459 +++++++++--------- 59 files changed, 645 insertions(+), 488 deletions(-) diff --git a/apps/desktop/src/components/CapErrorBoundary.tsx b/apps/desktop/src/components/CapErrorBoundary.tsx index 5bf7fc132e..2dca68d1d4 100644 --- a/apps/desktop/src/components/CapErrorBoundary.tsx +++ b/apps/desktop/src/components/CapErrorBoundary.tsx @@ -9,9 +9,9 @@ export function CapErrorBoundary(props: ParentProps) { fallback={(e: Error) => { console.error(e); return ( -
+
-

+

An Error Occured

diff --git a/apps/desktop/src/components/Loader.tsx b/apps/desktop/src/components/Loader.tsx index f88661a0e0..b8da544d80 100644 --- a/apps/desktop/src/components/Loader.tsx +++ b/apps/desktop/src/components/Loader.tsx @@ -2,7 +2,7 @@ export function AbsoluteInsetLoader() { return (

- +
); diff --git a/apps/desktop/src/components/SignInButton.tsx b/apps/desktop/src/components/SignInButton.tsx index 08fc3f12a9..2c9f0b834e 100644 --- a/apps/desktop/src/components/SignInButton.tsx +++ b/apps/desktop/src/components/SignInButton.tsx @@ -11,7 +11,7 @@ export function SignInButton( return (
diff --git a/apps/desktop/src/entry-server.tsx b/apps/desktop/src/entry-server.tsx index f9f4ae475f..dc1213d272 100644 --- a/apps/desktop/src/entry-server.tsx +++ b/apps/desktop/src/entry-server.tsx @@ -19,7 +19,7 @@ export default createHandler(() => ( {assets} -
+
{children}
{scripts} diff --git a/apps/desktop/src/routes/(window-chrome).tsx b/apps/desktop/src/routes/(window-chrome).tsx index 6483767acb..42804c7f6f 100644 --- a/apps/desktop/src/routes/(window-chrome).tsx +++ b/apps/desktop/src/routes/(window-chrome).tsx @@ -86,7 +86,7 @@ function Header() { data-tauri-drag-region > {ctx.state()?.items} - {isWindows && } + {isWindows && }
); } diff --git a/apps/desktop/src/routes/(window-chrome)/(main).tsx b/apps/desktop/src/routes/(window-chrome)/(main).tsx index 3f1be75165..0252f22ea4 100644 --- a/apps/desktop/src/routes/(window-chrome)/(main).tsx +++ b/apps/desktop/src/routes/(window-chrome)/(main).tsx @@ -260,7 +260,7 @@ function Page() { }); return ( -
+
-
+
@@ -383,7 +383,7 @@ function Page() { />
toggleRecording.mutate({ mode: rawOptions.mode })} - class="flex flex-grow justify-center items-center" + class="flex grow justify-center items-center" > {isRecording() ? ( "Stop Recording" @@ -712,9 +712,9 @@ function AreaSelectButton(props: { disabled={!targetScreenOrArea} onClick={handleAreaSelectButtonClick} class={cx( - "flex items-center justify-center flex-shrink-0 w-full h-full rounded-[0.5rem] transition-all duration-200", + "flex items-center justify-center shrink-0 w-full h-full rounded-lg transition-all duration-200", "hover:bg-gray-3 disabled:bg-gray-2 disabled:text-gray-11", - "focus-visible:outline font-[200] text-[0.875rem]", + "focus-visible:outline font-extralight text-[0.875rem]", props.targetVariant === "area" ? "bg-gray-2 text-blue-9 border border-blue-200" : "bg-gray-2 text-gray-11", @@ -722,7 +722,7 @@ function AreaSelectButton(props: { > ); } @@ -760,9 +760,9 @@ function MicrophoneSelect(props: { return ( ); @@ -771,10 +771,10 @@ function MicrophoneSelect(props: { function SystemAudio() { return ( +
} @@ -850,7 +850,7 @@ function InfoPill( {...props} type="button" class={cx( - "px-[0.375rem] rounded-full text-[0.75rem]", + "px-1.5 rounded-full text-[0.75rem]", props.variant === "blue" ? "bg-blue-3 text-blue-9" : "bg-red-3 text-red-9", diff --git a/apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx b/apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx index ab95e90f45..8c74a979a9 100644 --- a/apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx +++ b/apps/desktop/src/routes/(window-chrome)/new-main/CameraSelect.tsx @@ -58,7 +58,7 @@ export function CameraSelectBase(props: { }; return ( -
+
-
+
Commercial License -

+

For commercial use

@@ -261,7 +261,7 @@ function CommercialLicensePurchase() { onClick={() => openCommercialCheckout.mutate()} disabled={openCommercialCheckout.isPending} variant="dark" - class="w-full !rounded-full mt-10 !h-[48px] text-lg font-medium" + class="w-full rounded-full! mt-10 h-[48px]! text-lg font-medium" size="lg" > {openCommercialCheckout.isPending @@ -281,9 +281,9 @@ function CommercialLicensePurchase() { ].map((feature) => (
  • - +
    - + {feature}
  • diff --git a/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx b/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx index 3c694f45d3..2229d7bac9 100644 --- a/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx +++ b/apps/desktop/src/routes/(window-chrome)/settings/recordings.tsx @@ -150,7 +150,7 @@ export default function Recordings() { 0} fallback={ -

    +

    No recordings found

    } @@ -176,11 +176,11 @@ export default function Recordings() {
    -

    +

    No {activeTab()} recordings

    -
      +
        {(recording) => ( 0} fallback={ -

        +

        No screenshots found

        } @@ -131,7 +131,7 @@ export default function Screenshots() {
    -
      +
        {(screenshot) => (
        +
        {showStartup() && ( { @@ -102,7 +102,7 @@ export default function () {
        -

        +

        Permissions Required

        Cap needs permissions to run properly.

        @@ -116,11 +116,11 @@ export default function () { return (
      • -
        - +
        + {permission.name} Permission - + {permission.description}
        @@ -162,7 +162,7 @@ export default function () {
        -

        +

        Select Recording Mode

        @@ -304,7 +304,7 @@ function Startup(props: { onClose: () => void }) { >

        void }) { }`} > Cloud One @@ -447,7 +447,7 @@ function Startup(props: { onClose: () => void }) { }`} > Cloud Two diff --git a/apps/desktop/src/routes/(window-chrome)/update.tsx b/apps/desktop/src/routes/(window-chrome)/update.tsx index 2dddd8a402..7c694ad2aa 100644 --- a/apps/desktop/src/routes/(window-chrome)/update.tsx +++ b/apps/desktop/src/routes/(window-chrome)/update.tsx @@ -16,11 +16,11 @@ export default function () { }); return ( -
        +
        No update available + No update available } keyed > @@ -69,12 +69,12 @@ export default function () {
        + } >
        -

        +

        Update has been installed. Restart Cap to finish updating.

        @@ -93,7 +93,7 @@ export default function () { > {(status) => ( <> -

        +

        Installing Update

        diff --git a/apps/desktop/src/routes/(window-chrome)/upgrade.tsx b/apps/desktop/src/routes/(window-chrome)/upgrade.tsx index bf160cde30..2de6e359f1 100644 --- a/apps/desktop/src/routes/(window-chrome)/upgrade.tsx +++ b/apps/desktop/src/routes/(window-chrome)/upgrade.tsx @@ -328,7 +328,7 @@ export default function Page() { ) : ( <>
        -

        +

        Early Adopter Pricing

        @@ -361,7 +361,7 @@ export default function Page() {

        Commercial License

        -

        +

        For commercial use

        @@ -402,9 +402,9 @@ export default function Page() { ].map((feature) => (
      • - +
        - + {feature}
      • @@ -421,7 +421,7 @@ export default function Page() { onClick={() => openCommercialCheckout.mutate()} disabled={openCommercialCheckout.isPending} variant="dark" - class="w-full !rounded-full !h-[48px] text-lg font-medium" + class="w-full rounded-full! h-[48px]! text-lg font-medium" size="lg" > {openCommercialCheckout.isPending @@ -457,7 +457,7 @@ export default function Page() { riveInstance.play("items-coming-in"); } }} - class="flex-grow p-3 h-[700px] flex-1 bg-gray-12 rounded-2xl border shadow-sm text-card-foreground md:p-3" + class="grow p-3 h-[700px] flex-1 bg-gray-12 rounded-2xl border shadow-sm text-card-foreground md:p-3" >
        @@ -512,7 +512,7 @@ export default function Page() {
        -
        +
        -
        +