Window title working again

This commit is contained in:
Gregory Schier
2024-05-30 00:11:55 -07:00
parent 14b3abf76c
commit 2cef46b46a
8 changed files with 378 additions and 81 deletions

View File

@@ -2216,6 +2216,13 @@
"shell:allow-open" "shell:allow-open"
] ]
}, },
{
"description": "shell:allow-spawn -> Enables the spawn command without any pre-configured scope.",
"type": "string",
"enum": [
"shell:allow-spawn"
]
},
{ {
"description": "shell:allow-stdin-write -> Enables the stdin_write command without any pre-configured scope.", "description": "shell:allow-stdin-write -> Enables the stdin_write command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -2244,6 +2251,13 @@
"shell:deny-open" "shell:deny-open"
] ]
}, },
{
"description": "shell:deny-spawn -> Denies the spawn command without any pre-configured scope.",
"type": "string",
"enum": [
"shell:deny-spawn"
]
},
{ {
"description": "shell:deny-stdin-write -> Denies the stdin_write command without any pre-configured scope.", "description": "shell:deny-stdin-write -> Denies the stdin_write command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -2498,6 +2512,69 @@
"clipboard-manager:deny-write-text" "clipboard-manager:deny-write-text"
] ]
}, },
{
"description": "deep-link:default -> Allows reading the opened deep link via the get_current command",
"type": "string",
"enum": [
"deep-link:default"
]
},
{
"description": "deep-link:allow-get-current -> Enables the get_current command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:allow-get-current"
]
},
{
"description": "deep-link:allow-is-registered -> Enables the is_registered command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:allow-is-registered"
]
},
{
"description": "deep-link:allow-register -> Enables the register command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:allow-register"
]
},
{
"description": "deep-link:allow-unregister -> Enables the unregister command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:allow-unregister"
]
},
{
"description": "deep-link:deny-get-current -> Denies the get_current command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:deny-get-current"
]
},
{
"description": "deep-link:deny-is-registered -> Denies the is_registered command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:deny-is-registered"
]
},
{
"description": "deep-link:deny-register -> Denies the register command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:deny-register"
]
},
{
"description": "deep-link:deny-unregister -> Denies the unregister command without any pre-configured scope.",
"type": "string",
"enum": [
"deep-link:deny-unregister"
]
},
{ {
"type": "string", "type": "string",
"enum": [ "enum": [
@@ -5323,6 +5400,13 @@
"shell:allow-open" "shell:allow-open"
] ]
}, },
{
"description": "shell:allow-spawn -> Enables the spawn command without any pre-configured scope.",
"type": "string",
"enum": [
"shell:allow-spawn"
]
},
{ {
"description": "shell:allow-stdin-write -> Enables the stdin_write command without any pre-configured scope.", "description": "shell:allow-stdin-write -> Enables the stdin_write command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -5351,6 +5435,13 @@
"shell:deny-open" "shell:deny-open"
] ]
}, },
{
"description": "shell:deny-spawn -> Denies the spawn command without any pre-configured scope.",
"type": "string",
"enum": [
"shell:deny-spawn"
]
},
{ {
"description": "shell:deny-stdin-write -> Denies the stdin_write command without any pre-configured scope.", "description": "shell:deny-stdin-write -> Denies the stdin_write command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -5533,6 +5624,13 @@
"updater:allow-check" "updater:allow-check"
] ]
}, },
{
"description": "updater:allow-download -> Enables the download command without any pre-configured scope.",
"type": "string",
"enum": [
"updater:allow-download"
]
},
{ {
"description": "updater:allow-download-and-install -> Enables the download_and_install command without any pre-configured scope.", "description": "updater:allow-download-and-install -> Enables the download_and_install command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -5540,6 +5638,13 @@
"updater:allow-download-and-install" "updater:allow-download-and-install"
] ]
}, },
{
"description": "updater:allow-install -> Enables the install command without any pre-configured scope.",
"type": "string",
"enum": [
"updater:allow-install"
]
},
{ {
"description": "updater:deny-check -> Denies the check command without any pre-configured scope.", "description": "updater:deny-check -> Denies the check command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -5547,6 +5652,13 @@
"updater:deny-check" "updater:deny-check"
] ]
}, },
{
"description": "updater:deny-download -> Denies the download command without any pre-configured scope.",
"type": "string",
"enum": [
"updater:deny-download"
]
},
{ {
"description": "updater:deny-download-and-install -> Denies the download_and_install command without any pre-configured scope.", "description": "updater:deny-download-and-install -> Denies the download_and_install command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -5554,6 +5666,13 @@
"updater:deny-download-and-install" "updater:deny-download-and-install"
] ]
}, },
{
"description": "updater:deny-install -> Denies the install command without any pre-configured scope.",
"type": "string",
"enum": [
"updater:deny-install"
]
},
{ {
"description": "webview:default -> Default permissions for the plugin.", "description": "webview:default -> Default permissions for the plugin.",
"type": "string", "type": "string",
@@ -5897,6 +6016,13 @@
"window:allow-minimize" "window:allow-minimize"
] ]
}, },
{
"description": "window:allow-monitor-from-point -> Enables the monitor_from_point command without any pre-configured scope.",
"type": "string",
"enum": [
"window:allow-monitor-from-point"
]
},
{ {
"description": "window:allow-outer-position -> Enables the outer_position command without any pre-configured scope.", "description": "window:allow-outer-position -> Enables the outer_position command without any pre-configured scope.",
"type": "string", "type": "string",
@@ -6331,6 +6457,13 @@
"window:deny-minimize" "window:deny-minimize"
] ]
}, },
{
"description": "window:deny-monitor-from-point -> Denies the monitor_from_point command without any pre-configured scope.",
"type": "string",
"enum": [
"window:deny-monitor-from-point"
]
},
{ {
"description": "window:deny-outer-position -> Denies the outer_position command without any pre-configured scope.", "description": "window:deny-outer-position -> Denies the outer_position command without any pre-configured scope.",
"type": "string", "type": "string",

View File

@@ -69,7 +69,10 @@ mod plugin;
mod render; mod render;
mod updates; mod updates;
mod window_menu; mod window_menu;
mod tauri_plugin_traffic_light; #[cfg(target_os = "macos")]
mod tauri_plugin_mac_window;
#[cfg(target_os = "windows")]
mod tauri_plugin_windows_window;
async fn migrate_db(app_handle: &AppHandle, db: &Mutex<Pool<Sqlite>>) -> Result<(), String> { async fn migrate_db(app_handle: &AppHandle, db: &Mutex<Pool<Sqlite>>) -> Result<(), String> {
let pool = &*db.lock().await; let pool = &*db.lock().await;
@@ -1533,41 +1536,49 @@ async fn cmd_check_for_updates(
#[cfg_attr(mobile, tauri::mobile_entry_point)] #[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() { pub fn run() {
tauri::Builder::default() let mut builder = tauri::Builder::default()
.plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_window_state::Builder::default().with_denylist(&["settings"]).build()) .plugin(tauri_plugin_window_state::Builder::default().build())
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_fs::init());
.plugin(tauri_plugin_traffic_light::init())
.plugin( #[cfg(target_os = "windows")] {
tauri_plugin_log::Builder::default() builder = builder.plugin(tauri_plugin_windows_window::init());
.targets([ }
Target::new(TargetKind::Stdout),
Target::new(TargetKind::LogDir { file_name: None }), #[cfg(target_os = "macos")] {
Target::new(TargetKind::Webview), builder = builder.plugin(tauri_plugin_mac_window::init());
]) }
.level_for("cookie_store", log::LevelFilter::Info)
.level_for("h2", log::LevelFilter::Info) builder.plugin(
.level_for("hyper", log::LevelFilter::Info) tauri_plugin_log::Builder::default()
.level_for("hyper_rustls", log::LevelFilter::Info) .targets([
.level_for("reqwest", log::LevelFilter::Info) Target::new(TargetKind::Stdout),
.level_for("sqlx", log::LevelFilter::Warn) Target::new(TargetKind::LogDir { file_name: None }),
.level_for("tao", log::LevelFilter::Info) Target::new(TargetKind::Webview),
.level_for("tokio_util", log::LevelFilter::Info) ])
.level_for("tonic", log::LevelFilter::Info) .level_for("cookie_store", log::LevelFilter::Info)
.level_for("tower", log::LevelFilter::Info) .level_for("h2", log::LevelFilter::Info)
.level_for("tracing", log::LevelFilter::Info) .level_for("hyper", log::LevelFilter::Info)
.with_colors(ColoredLevelConfig::default()) .level_for("hyper_rustls", log::LevelFilter::Info)
.level(if is_dev() { .level_for("reqwest", log::LevelFilter::Info)
log::LevelFilter::Trace .level_for("sqlx", log::LevelFilter::Warn)
} else { .level_for("tao", log::LevelFilter::Info)
log::LevelFilter::Info .level_for("tokio_util", log::LevelFilter::Info)
}) .level_for("tonic", log::LevelFilter::Info)
.build(), .level_for("tower", log::LevelFilter::Info)
) .level_for("tracing", log::LevelFilter::Info)
.with_colors(ColoredLevelConfig::default())
.level(if is_dev() {
log::LevelFilter::Trace
} else {
log::LevelFilter::Info
})
.build(),
)
.setup(|app| { .setup(|app| {
let app_data_dir = app.path().app_data_dir().unwrap(); let app_data_dir = app.path().app_data_dir().unwrap();
let app_config_dir = app.path().app_config_dir().unwrap(); let app_config_dir = app.path().app_config_dir().unwrap();
@@ -1744,10 +1755,9 @@ fn is_dev() -> bool {
fn create_nested_window(window: &WebviewWindow, label: &str, url: &str, title: &str) -> WebviewWindow { fn create_nested_window(window: &WebviewWindow, label: &str, url: &str, title: &str) -> WebviewWindow {
info!("Create new nested window label={label}"); info!("Create new nested window label={label}");
let pos = window.outer_position().unwrap();
let mut win_builder = tauri::WebviewWindowBuilder::new( let mut win_builder = tauri::WebviewWindowBuilder::new(
window, window,
label, format!("nested_{}_{}", window.label(), label),
WebviewUrl::App(url.into()), WebviewUrl::App(url.into()),
) )
.resizable(true) .resizable(true)
@@ -1756,14 +1766,7 @@ fn create_nested_window(window: &WebviewWindow, label: &str, url: &str, title: &
.title(title) .title(title)
.parent(&window) .parent(&window)
.unwrap() .unwrap()
.position( .inner_size(700.0f64, 600.0f64);
(pos.x + 20) as f64,
(pos.y + 20) as f64,
)
.inner_size(
500.0f64,
300.0f64,
);
// Add macOS-only things // Add macOS-only things
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@@ -1827,7 +1830,7 @@ fn create_window(handle: &AppHandle, url: &str) -> WebviewWindow {
handle.set_menu(menu).expect("Failed to set app menu"); handle.set_menu(menu).expect("Failed to set app menu");
let window_num = handle.webview_windows().len(); let window_num = handle.webview_windows().len();
let label = format!("wnd_{}", window_num); let label = format!("main_{}", window_num);
info!("Create new window label={label}"); info!("Create new window label={label}");
let mut win_builder = tauri::WebviewWindowBuilder::new( let mut win_builder = tauri::WebviewWindowBuilder::new(
handle, handle,

View File

@@ -1,3 +1,4 @@
use hex_color::HexColor;
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use rand::{distributions::Alphanumeric, Rng}; use rand::{distributions::Alphanumeric, Rng};
use tauri::{Manager, plugin::{Builder, TauriPlugin}, Runtime, Window}; use tauri::{Manager, plugin::{Builder, TauriPlugin}, Runtime, Window};
@@ -6,23 +7,108 @@ const WINDOW_CONTROL_PAD_X: f64 = 13.0;
const WINDOW_CONTROL_PAD_Y: f64 = 18.0; const WINDOW_CONTROL_PAD_Y: f64 = 18.0;
struct UnsafeWindowHandle(*mut std::ffi::c_void); struct UnsafeWindowHandle(*mut std::ffi::c_void);
unsafe impl Send for UnsafeWindowHandle {} unsafe impl Send for UnsafeWindowHandle {}
unsafe impl Sync for UnsafeWindowHandle {} unsafe impl Sync for UnsafeWindowHandle {}
pub fn init<R: Runtime>() -> TauriPlugin<R> { pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("traffic_light_positioner") Builder::new("mac_window")
.on_window_ready(|window| { .on_window_ready(|window| {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")] {
setup_traffic_light_positioner(window); setup_traffic_light_positioner(&window);
let h = window.app_handle();
let window_for_theme = window.clone();
h.listen("yaak_bg_changed", move |ev| {
let payload = serde_json::from_str::<&str>(ev.payload())
.unwrap()
.trim();
let color = HexColor::parse_rgb(payload).unwrap();
update_window_theme(window_for_theme.clone(), color);
});
let window_for_title = window.clone();
h.listen("yaak_title_changed", move |ev| {
let payload = serde_json::from_str::<&str>(ev.payload())
.unwrap()
.trim();
update_window_title(window_for_title.clone(), payload.to_string());
});
}
return; return;
}) })
.build() .build()
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { fn update_window_title<R: Runtime>(window: Window<R>, title: String) {
use cocoa::{
appkit::NSWindow,
base::nil,
foundation::NSString,
};
unsafe {
let window_handle = UnsafeWindowHandle(window.ns_window().unwrap());
let window2 = window.clone();
let label = window.label().to_string();
let _ = window.run_on_main_thread(move || {
let win_title = NSString::alloc(nil).init_str(&title);
let handle = window_handle;
NSWindow::setTitle_(handle.0 as cocoa::base::id, win_title);
position_traffic_lights(
UnsafeWindowHandle(window2.ns_window().expect("Failed to create window handle")),
WINDOW_CONTROL_PAD_X,
WINDOW_CONTROL_PAD_Y,
label,
);
});
}}
#[cfg(target_os = "macos")]
fn update_window_theme<R: Runtime>(window: Window<R>, color: HexColor) {
use cocoa::appkit::{
NSAppearance, NSAppearanceNameVibrantDark, NSAppearanceNameVibrantLight, NSWindow,
};
let brightness = (color.r as u64 + color.g as u64 + color.b as u64) / 3;
let label = window.label().to_string();
unsafe {
let window_handle = UnsafeWindowHandle(window.ns_window().unwrap());
let window2 = window.clone();
let _ = window.run_on_main_thread(move || {
let handle = window_handle;
let selected_appearance = if brightness >= 128 {
NSAppearance(NSAppearanceNameVibrantLight)
} else {
NSAppearance(NSAppearanceNameVibrantDark)
};
NSWindow::setAppearance(handle.0 as cocoa::base::id, selected_appearance);
position_traffic_lights(
UnsafeWindowHandle(window2.ns_window().expect("Failed to create window handle")),
WINDOW_CONTROL_PAD_X,
WINDOW_CONTROL_PAD_Y,
label,
);
});
}
}
#[cfg(target_os = "macos")]
fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64, label: String) {
if label.starts_with("nested_") {
return;
}
use cocoa::appkit::{NSView, NSWindow, NSWindowButton}; use cocoa::appkit::{NSView, NSWindow, NSWindowButton};
use cocoa::foundation::NSRect; use cocoa::foundation::NSRect;
let ns_window = ns_window_handle.0 as cocoa::base::id; let ns_window = ns_window_handle.0 as cocoa::base::id;
unsafe { unsafe {
let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton);
@@ -59,7 +145,7 @@ struct WindowState<R: Runtime> {
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn setup_traffic_light_positioner<R: Runtime>(window: Window<R>) { pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
use cocoa::delegate; use cocoa::delegate;
use cocoa::appkit::NSWindow; use cocoa::appkit::NSWindow;
use cocoa::base::{BOOL, id}; use cocoa::base::{BOOL, id};
@@ -67,11 +153,11 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: Window<R>) {
use objc::runtime::{Object, Sel}; use objc::runtime::{Object, Sel};
use std::ffi::c_void; use std::ffi::c_void;
// Do the initial positioning
position_traffic_lights( position_traffic_lights(
UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")),
WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_X,
WINDOW_CONTROL_PAD_Y, WINDOW_CONTROL_PAD_Y,
window.label().to_string(),
); );
// Ensure they stay in place while resizing the window. // Ensure they stay in place while resizing the window.
@@ -86,6 +172,7 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: Window<R>) {
func(ptr); func(ptr);
} }
unsafe { unsafe {
let ns_win = window let ns_win = window
.ns_window() .ns_window()
@@ -115,11 +202,11 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: Window<R>) {
.expect("NS window should exist on state to handle resize") .expect("NS window should exist on state to handle resize")
as id; as id;
#[cfg(target_os = "macos")]
position_traffic_lights( position_traffic_lights(
UnsafeWindowHandle(id as *mut std::ffi::c_void), UnsafeWindowHandle(id as *mut c_void),
WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_X,
WINDOW_CONTROL_PAD_Y, WINDOW_CONTROL_PAD_Y,
state.window.label().to_string(),
); );
}); });
@@ -248,9 +335,10 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: Window<R>) {
let id = state.window.ns_window().expect("Failed to emit event") as id; let id = state.window.ns_window().expect("Failed to emit event") as id;
position_traffic_lights( position_traffic_lights(
UnsafeWindowHandle(id as *mut std::ffi::c_void), UnsafeWindowHandle(id as *mut c_void),
WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_X,
WINDOW_CONTROL_PAD_Y, WINDOW_CONTROL_PAD_Y,
state.window.label().to_string(),
); );
}); });
@@ -309,10 +397,10 @@ pub fn setup_traffic_light_positioner<R: Runtime>(window: Window<R>) {
} }
} }
// Are we deallocing this properly ? (I miss safe Rust :( ) // Are we de-allocing this properly ? (I miss safe Rust :( )
let window_label = window.label().to_string(); let window_label = window.label().to_string();
let app_state = WindowState { window }; let app_state = WindowState { window: window.clone() };
let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void; let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void;
let random_str: String = rand::thread_rng() let random_str: String = rand::thread_rng()
.sample_iter(&Alphanumeric) .sample_iter(&Alphanumeric)

View File

@@ -0,0 +1,89 @@
use hex_color::HexColor;
use tauri::{ Runtime, Window};
use std::mem::transmute;
use std::{ptr, ffi::c_void, mem::size_of};
use tauri::plugin::{Builder, TauriPlugin};
use windows::Win32::UI::Controls::{WTA_NONCLIENT, WTNCA_NODRAWICON, WTNCA_NOSYSMENU, WTNCA_NOMIRRORHELP};
use windows::Win32::UI::Controls::SetWindowThemeAttribute;
use windows::Win32::UI::Controls::WTNCA_NODRAWCAPTION;
use windows::Win32::Graphics::Dwm::DWMWA_CAPTION_COLOR;
use windows::Win32::Foundation::COLORREF;
use windows::Win32::Foundation::BOOL;
use windows::Win32::Graphics::Dwm::DwmSetWindowAttribute;
use windows::Win32::Foundation::HWND;
use windows::Win32::Graphics::Dwm::{DWMWA_USE_IMMERSIVE_DARK_MODE};
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("windows_window")
.on_window_ready(|window| {
#[cfg(target_os = "windows")]
setup_win_window(window);
return;
})
.build()
}
fn hex_color_to_colorref(color: HexColor) -> COLORREF {
// TODO: Remove this unsafe, This operation doesn't need to be unsafe!
unsafe {
COLORREF(transmute::<[u8; 4], u32>([color.r, color.g, color.b, 0]))
}
}
struct WinThemeAttribute {
flag: u32,
mask: u32
}
#[cfg(target_os = "windows")]
fn update_bg_color(hwnd: &HWND, bg_color: HexColor) {
let use_dark_mode = BOOL::from(true);
let final_color = hex_color_to_colorref(bg_color);
unsafe {
DwmSetWindowAttribute(
HWND(hwnd.0),
DWMWA_USE_IMMERSIVE_DARK_MODE,
ptr::addr_of!(use_dark_mode) as *const c_void,
size_of::<BOOL>().try_into().unwrap()
).unwrap();
DwmSetWindowAttribute(
HWND(hwnd.0),
DWMWA_CAPTION_COLOR,
ptr::addr_of!(final_color) as *const c_void,
size_of::<COLORREF>().try_into().unwrap()
).unwrap();
let flags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
let mask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON | WTNCA_NOSYSMENU | WTNCA_NOMIRRORHELP;
let options = WinThemeAttribute { flag: flags, mask };
SetWindowThemeAttribute(
HWND(hwnd.0),
WTA_NONCLIENT,
ptr::addr_of!(options) as *const c_void,
size_of::<WinThemeAttribute>().try_into().unwrap()
).unwrap();
}
}
#[cfg(target_os = "windows")]
pub fn setup_win_window<R: Runtime>(window: Window<R>) {
let win_handle = window.hwnd().unwrap();
let win_clone = win_handle.clone();
window.listen_global("yaak_bg_changed", move |ev| {
let payload = serde_json::from_str::<&str>(ev.payload().unwrap())
.unwrap()
.trim();
let color = HexColor::parse_rgb(payload).unwrap();
update_bg_color(&HWND(win_clone.0), color);
});
}

View File

@@ -32,7 +32,7 @@ export const SettingsDialog = ({ fullscreen }: Props) => {
{fullscreen && ( {fullscreen && (
<div <div
data-tauri-drag-region data-tauri-drag-region
className="h-[38px] bg-background-highlight-secondary flex items-center justify-center border-b border-background-highlight" className="h-[27px] bg-background-highlight-secondary flex items-center justify-center border-b border-background-highlight"
> >
Settings Settings
</div> </div>

View File

@@ -14,7 +14,6 @@ import { Icon } from './core/Icon';
import { IconButton } from './core/IconButton'; import { IconButton } from './core/IconButton';
import { useDialog } from './DialogContext'; import { useDialog } from './DialogContext';
import { KeyboardShortcutsDialog } from './KeyboardShortcutsDialog'; import { KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';
import { SettingsDialog } from './Settings/SettingsDialog';
export function SettingsDropdown() { export function SettingsDropdown() {
const importData = useImportData(); const importData = useImportData();
@@ -26,13 +25,12 @@ export function SettingsDropdown() {
const routes = useAppRoutes(); const routes = useAppRoutes();
const workspaceId = useActiveWorkspaceId(); const workspaceId = useActiveWorkspaceId();
const showSettings = () => { const showSettings = async () => {
dialog.show({ if (!workspaceId) return;
id: 'settings', await invoke('cmd_new_nested_window', {
size: 'dynamic', url: routes.paths.workspaceSettings({ workspaceId }),
noScroll: true, label: 'settings',
noPadding: true, title: 'Yaak Settings',
render: () => <SettingsDialog />,
}); });
}; };
@@ -63,20 +61,6 @@ export function SettingsDropdown() {
}); });
}, },
}, },
{
key: 'foo',
label: 'Foo',
hotKeyAction: 'hotkeys.showHelp',
leftSlot: <Icon icon="keyboard" />,
onSelect: async () => {
if (!workspaceId) return;
await invoke('cmd_new_nested_window', {
url: routes.paths.workspaceSettings({ workspaceId }),
label: 'settings',
title: 'Yaak Settings',
});
},
},
{ {
key: 'import-data', key: 'import-data',
label: 'Import Data', label: 'Import Data',

View File

@@ -40,7 +40,7 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
<div className="pointer-events-none"> <div className="pointer-events-none">
<RecentRequestsDropdown /> <RecentRequestsDropdown />
</div> </div>
<div className="flex-1 flex gap-1 items-center h-full justify-end pointer-events-none"> <div className="flex-1 flex gap-1 items-center h-full justify-end pointer-events-none pr-0.5">
<ImportCurlButton /> <ImportCurlButton />
<SettingsDropdown /> <SettingsDropdown />
{(osInfo?.osType === 'linux' || osInfo?.osType === 'windows') && ( {(osInfo?.osType === 'linux' || osInfo?.osType === 'windows') && (

View File

@@ -5,6 +5,7 @@ import { useActiveEnvironment } from './useActiveEnvironment';
import { useActiveRequest } from './useActiveRequest'; import { useActiveRequest } from './useActiveRequest';
import { useActiveWorkspace } from './useActiveWorkspace'; import { useActiveWorkspace } from './useActiveWorkspace';
import { useOsInfo } from './useOsInfo'; import { useOsInfo } from './useOsInfo';
import { emit } from '@tauri-apps/api/event';
export function useSyncWindowTitle() { export function useSyncWindowTitle() {
const activeRequest = useActiveRequest(); const activeRequest = useActiveRequest();
@@ -26,13 +27,12 @@ export function useSyncWindowTitle() {
newTitle += ` ${fallbackRequestName(activeRequest)}`; newTitle += ` ${fallbackRequestName(activeRequest)}`;
} }
// TODO: This resets the stoplight position so we can't use it on macOS yet. Perhaps // TODO: This resets the stoplight position so we can't use it on macOS yet. So we send
// we can // a custom command instead
if (osInfo?.osType !== 'macos') { if (osInfo?.osType !== 'macos') {
console.log('DO IT', osInfo?.osType);
getCurrent().setTitle(newTitle).catch(console.error); getCurrent().setTitle(newTitle).catch(console.error);
} else { } else {
// emit('yaak_title_changed', newTitle).catch(console.error); emit('yaak_title_changed', newTitle).catch(console.error);
} }
}, [activeEnvironment, activeRequest, activeWorkspace, osInfo?.osType]); }, [activeEnvironment, activeRequest, activeWorkspace, osInfo?.osType]);
} }