use crate::app::config::PakeConfig; use crate::util::get_data_dir; use std::{path::PathBuf, str::FromStr}; use tauri::{App, Config, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder}; #[cfg(target_os = "macos")] use tauri::{Theme, TitleBarStyle}; #[cfg(target_os = "windows")] fn build_proxy_browser_arg(url: &Url) -> Option { let host = url.host_str()?; let scheme = url.scheme(); let port = url.port().or_else(|| match scheme { "http" => Some(80), "socks5" => Some(1080), _ => None, })?; match scheme { "http" | "socks5" => Some(format!("--proxy-server={scheme}://{host}:{port}")), _ => None, } } pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) -> WebviewWindow { let package_name = tauri_config.clone().product_name.unwrap(); let _data_dir = get_data_dir(app.handle(), package_name); let window_config = config .windows .first() .expect("At least one window configuration is required"); let user_agent = config.user_agent.get(); let url = match window_config.url_type.as_str() { "web" => WebviewUrl::App(window_config.url.parse().unwrap()), "local" => WebviewUrl::App(PathBuf::from(&window_config.url)), _ => panic!("url type can only be web or local"), }; let config_script = format!( "window.pakeConfig = {}", serde_json::to_string(&window_config).unwrap() ); // Platform-specific title: macOS prefers empty, others fallback to product name let effective_title = window_config.title.as_deref().unwrap_or_else(|| { if cfg!(target_os = "macos") { "" } else { tauri_config.product_name.as_deref().unwrap_or("") } }); let mut window_builder = WebviewWindowBuilder::new(app, "pake", url) .title(effective_title) .visible(false) .user_agent(user_agent) .resizable(window_config.resizable) .fullscreen(window_config.fullscreen) .maximized(window_config.maximize) .inner_size(window_config.width, window_config.height) .always_on_top(window_config.always_on_top) .incognito(window_config.incognito); if window_config.min_width > 0.0 || window_config.min_height > 0.0 { let min_w = if window_config.min_width > 0.0 { window_config.min_width } else { window_config.width }; let min_h = if window_config.min_height > 0.0 { window_config.min_height } else { window_config.height }; window_builder = window_builder.min_inner_size(min_w, min_h); } if !window_config.enable_drag_drop { window_builder = window_builder.disable_drag_drop_handler(); } // Add initialization scripts window_builder = window_builder .initialization_script(&config_script) .initialization_script(include_str!("../inject/component.js")) .initialization_script(include_str!("../inject/event.js")) .initialization_script(include_str!("../inject/style.js")) .initialization_script(include_str!("../inject/custom.js")); #[cfg(target_os = "windows")] let mut windows_browser_args = String::from("--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection --disable-blink-features=AutomationControlled"); #[cfg(all(not(target_os = "windows"), not(target_os = "macos")))] let mut linux_browser_args = String::from("--disable-blink-features=AutomationControlled"); if window_config.ignore_certificate_errors { #[cfg(target_os = "windows")] { windows_browser_args.push_str(" --ignore-certificate-errors"); } #[cfg(all(not(target_os = "windows"), not(target_os = "macos")))] { linux_browser_args.push_str(" --ignore-certificate-errors"); } #[cfg(target_os = "macos")] { window_builder = window_builder.additional_browser_args("--ignore-certificate-errors"); } } if window_config.enable_wasm { #[cfg(target_os = "windows")] { windows_browser_args.push_str(" --enable-features=SharedArrayBuffer"); windows_browser_args.push_str(" --enable-unsafe-webgpu"); } #[cfg(all(not(target_os = "windows"), not(target_os = "macos")))] { linux_browser_args.push_str(" --enable-features=SharedArrayBuffer"); linux_browser_args.push_str(" --enable-unsafe-webgpu"); } #[cfg(target_os = "macos")] { window_builder = window_builder .additional_browser_args("--enable-features=SharedArrayBuffer") .additional_browser_args("--enable-unsafe-webgpu"); } } let mut parsed_proxy_url: Option = None; // Platform-specific configuration must be set before proxy on Windows/Linux #[cfg(target_os = "macos")] { let title_bar_style = if window_config.hide_title_bar { TitleBarStyle::Overlay } else { TitleBarStyle::Visible }; window_builder = window_builder.title_bar_style(title_bar_style); if window_config.dark_mode { window_builder = window_builder.theme(Some(Theme::Dark)); } } // Windows and Linux: set data_directory before proxy_url #[cfg(not(target_os = "macos"))] { window_builder = window_builder.data_directory(_data_dir).theme(None); if !config.proxy_url.is_empty() { if let Ok(proxy_url) = Url::from_str(&config.proxy_url) { parsed_proxy_url = Some(proxy_url.clone()); #[cfg(target_os = "windows")] { if let Some(arg) = build_proxy_browser_arg(&proxy_url) { windows_browser_args.push(' '); windows_browser_args.push_str(&arg); } } } } #[cfg(target_os = "windows")] { window_builder = window_builder.additional_browser_args(&windows_browser_args); } #[cfg(all(not(target_os = "windows"), not(target_os = "macos")))] { window_builder = window_builder.additional_browser_args(&linux_browser_args); } } // Set proxy after platform-specific configs (required for Windows/Linux) if parsed_proxy_url.is_none() && !config.proxy_url.is_empty() { if let Ok(proxy_url) = Url::from_str(&config.proxy_url) { parsed_proxy_url = Some(proxy_url); } } if let Some(proxy_url) = parsed_proxy_url { window_builder = window_builder.proxy_url(proxy_url); #[cfg(debug_assertions)] println!("Proxy configured: {}", config.proxy_url); } window_builder.build().expect("Failed to build window") }