From 5550193861539af1cc629b38c6fda98c93803ab8 Mon Sep 17 00:00:00 2001 From: Iuliia Ivashko Date: Fri, 30 Jan 2026 01:44:33 +0200 Subject: [PATCH] feat(ui): adapt macOS header/vav bar height for legacy versions & fix traffic lights wobble --- packages/desktop/src-tauri/src/main.rs | 102 ------------------- packages/ui/src/components/layout/Header.tsx | 25 ++++- 2 files changed, 24 insertions(+), 103 deletions(-) diff --git a/packages/desktop/src-tauri/src/main.rs b/packages/desktop/src-tauri/src/main.rs index d1dc59b8..bd2c27f4 100644 --- a/packages/desktop/src-tauri/src/main.rs +++ b/packages/desktop/src-tauri/src/main.rs @@ -85,13 +85,6 @@ use tokio::{ use tower_http::cors::CorsLayer; use window_state::{load_window_state, persist_window_state, WindowStateManager}; -#[cfg(target_os = "macos")] -use std::sync::atomic::{AtomicBool, Ordering}; - - - -#[cfg(target_os = "macos")] -static NEEDS_TRAFFIC_LIGHT_FIX: AtomicBool = AtomicBool::new(false); const PROXY_BODY_LIMIT: usize = 50 * 1024 * 1024; // 50MB const CLIENT_RELOAD_DELAY_MS: u64 = 800; @@ -316,84 +309,6 @@ async fn desktop_open_devtools(window: WebviewWindow) -> Result<(), String> { Ok(()) } -#[cfg(target_os = "macos")] -fn get_macos_major_version() -> isize { - use objc2_foundation::NSProcessInfo; - let process_info = NSProcessInfo::processInfo(); - let version = process_info.operatingSystemVersion(); - version.majorVersion -} - -#[cfg(target_os = "macos")] -fn get_traffic_light_y(macos_version: isize) -> f64 { - if macos_version <= 15 { - 4.0 - } else { - 16.0 - } -} - -#[cfg(target_os = "macos")] -fn adjust_traffic_lights_position( - window: &tauri::WebviewWindow, - x: f64, - y: f64, -) { - use objc2::msg_send; - use objc2::runtime::AnyObject; - use objc2_foundation::{NSPoint, NSRect}; - - if let Ok(ns_window) = window.ns_window() { - unsafe { - let ns_window: *mut AnyObject = ns_window.cast(); - let close_button: *mut AnyObject = msg_send![ns_window, standardWindowButton: 0usize]; - - if !close_button.is_null() { - let superview: *mut AnyObject = msg_send![close_button, superview]; - if !superview.is_null() { - let frame: NSRect = msg_send![superview, frame]; - let new_frame = NSRect::new(NSPoint::new(x, y), frame.size); - let _: () = msg_send![superview, setFrame: new_frame]; - } - } - } - } -} - -#[cfg(target_os = "macos")] -fn adjust_traffic_lights_centered( - window: &tauri::WebviewWindow, - fallback_x: f64, - y: f64, -) { - use objc2::msg_send; - use objc2::runtime::AnyObject; - use objc2_foundation::{NSPoint, NSRect}; - - if let Ok(ns_window) = window.ns_window() { - unsafe { - let ns_window: *mut AnyObject = ns_window.cast(); - let close_button: *mut AnyObject = msg_send![ns_window, standardWindowButton: 0usize]; - - if !close_button.is_null() { - let superview: *mut AnyObject = msg_send![close_button, superview]; - if !superview.is_null() { - let frame: NSRect = msg_send![superview, frame]; - let parent: *mut AnyObject = msg_send![superview, superview]; - if !parent.is_null() { - let parent_frame: NSRect = msg_send![parent, frame]; - let new_x = (parent_frame.size.width - frame.size.width) / 2.0; - let new_frame = NSRect::new(NSPoint::new(new_x, y), frame.size); - let _: () = msg_send![superview, setFrame: new_frame]; - return; - } - } - } - } - } - - adjust_traffic_lights_position(window, fallback_x, y); -} #[cfg(target_os = "macos")] fn optimize_webview_layer(window: &tauri::WebviewWindow) { @@ -756,15 +671,6 @@ fn main() { if let Some(window) = app.get_webview_window("main") { #[cfg(target_os = "macos")] { - let macos_version = get_macos_major_version(); - info!("[macos] Detected macOS version: {}", macos_version); - - if macos_version <= 15 { - NEEDS_TRAFFIC_LIGHT_FIX.store(true, Ordering::SeqCst); - let traffic_light_y = get_traffic_light_y(macos_version); - adjust_traffic_lights_centered(&window, 17.0, traffic_light_y); - } - // Apply layer optimizations for smoother scrolling optimize_webview_layer(&window); } @@ -1129,14 +1035,6 @@ fn main() { size.height as f64, is_maximized, ); - #[cfg(target_os = "macos")] - if NEEDS_TRAFFIC_LIGHT_FIX.load(Ordering::SeqCst) { - if let Some(webview) = window.app_handle().get_webview_window("main") { - let macos_version = get_macos_major_version(); - let traffic_light_y = get_traffic_light_y(macos_version); - adjust_traffic_lights_centered(&webview, 17.0, traffic_light_y); - } - } } tauri::WindowEvent::CloseRequested { api, .. } => { api.prevent_close(); diff --git a/packages/ui/src/components/layout/Header.tsx b/packages/ui/src/components/layout/Header.tsx index 0b9ece79..0a583172 100644 --- a/packages/ui/src/components/layout/Header.tsx +++ b/packages/ui/src/components/layout/Header.tsx @@ -107,6 +107,18 @@ export const Header: React.FC = () => { return /Macintosh|Mac OS X/.test(navigator.userAgent || ''); }, []); + const macosMajorVersion = React.useMemo(() => { + if (typeof navigator === 'undefined') { + return null; + } + const match = (navigator.userAgent || '').match(/Mac OS X (\d+)[._]/); + if (!match) { + return null; + } + const parsed = Number.parseInt(match[1], 10); + return Number.isNaN(parsed) ? null : parsed; + }, []); + useEffect(() => { if (typeof window === 'undefined') { return; @@ -289,6 +301,16 @@ export const Header: React.FC = () => { return 'pl-3'; }, [isDesktopApp, isMacPlatform]); + const macosHeaderSizeClass = React.useMemo(() => { + if (!isDesktopApp || !isMacPlatform) { + return ''; + } + if (macosMajorVersion === null || macosMajorVersion > 15) { + return ''; + } + return 'h-14'; + }, [isDesktopApp, isMacPlatform, macosMajorVersion]); + const updateHeaderHeight = React.useCallback(() => { if (typeof document === 'undefined') { return; @@ -463,7 +485,8 @@ export const Header: React.FC = () => { onMouseDown={handleDragStart} className={cn( 'app-region-drag relative flex h-12 select-none items-center', - desktopPaddingClass + desktopPaddingClass, + macosHeaderSizeClass )} role="tablist" aria-label="Main navigation"