Fix native titlebar. Get menu ready for native Mac menus

This commit is contained in:
Gregory Schier
2025-12-05 15:14:13 -08:00
parent 6534b3f622
commit 7b78fac24e
5 changed files with 31 additions and 29 deletions

View File

@@ -25,13 +25,13 @@ use tauri_plugin_deep_link::DeepLinkExt;
use tauri_plugin_log::fern::colors::ColoredLevelConfig; use tauri_plugin_log::fern::colors::ColoredLevelConfig;
use tauri_plugin_log::{Builder, Target, TargetKind, log}; use tauri_plugin_log::{Builder, Target, TargetKind, log};
use tauri_plugin_window_state::{AppHandleExt, StateFlags}; use tauri_plugin_window_state::{AppHandleExt, StateFlags};
use yaak_mac_window::AppHandleMacWindowExt;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tokio::task::block_in_place; use tokio::task::block_in_place;
use tokio::time; use tokio::time;
use yaak_common::window::WorkspaceWindowTrait; use yaak_common::window::WorkspaceWindowTrait;
use yaak_grpc::manager::GrpcHandle; use yaak_grpc::manager::GrpcHandle;
use yaak_grpc::{Code, ServiceDefinition, serialize_message}; use yaak_grpc::{Code, ServiceDefinition, serialize_message};
use yaak_mac_window::AppHandleMacWindowExt;
use yaak_models::models::{ use yaak_models::models::{
AnyModel, CookieJar, Environment, GrpcConnection, GrpcConnectionState, GrpcEvent, AnyModel, CookieJar, Environment, GrpcConnection, GrpcConnectionState, GrpcEvent,
GrpcEventType, GrpcRequest, HttpRequest, HttpResponse, HttpResponseState, Plugin, Workspace, GrpcEventType, GrpcRequest, HttpRequest, HttpResponse, HttpResponseState, Plugin, Workspace,
@@ -1322,7 +1322,13 @@ pub fn run() {
})) }))
.plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_window_state::Builder::default().build()) // Don't restore StateFlags::DECORATIONS because we want to be able to toggle them on/off on a restart
// We could* make this work if we toggled them in the frontend before the window closes, but, this is nicer.
.plugin(
tauri_plugin_window_state::Builder::new()
.with_state_flags(StateFlags::all() - StateFlags::DECORATIONS)
.build(),
)
.plugin(tauri_plugin_deep_link::init()) .plugin(tauri_plugin_deep_link::init())
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_dialog::init())

View File

@@ -1,11 +1,10 @@
use std::time::SystemTime;
use crate::error::Result; use crate::error::Result;
use crate::history::get_or_upsert_launch_info; use crate::history::get_or_upsert_launch_info;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use log::{debug, info}; use log::{debug, info};
use reqwest::Method; use reqwest::Method;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Instant;
use tauri::{AppHandle, Emitter, Manager, Runtime, WebviewWindow}; use tauri::{AppHandle, Emitter, Manager, Runtime, WebviewWindow};
use ts_rs::TS; use ts_rs::TS;
use yaak_common::api_client::yaak_api_client; use yaak_common::api_client::yaak_api_client;
@@ -21,7 +20,7 @@ const KV_KEY: &str = "seen";
// Create updater struct // Create updater struct
pub struct YaakNotifier { pub struct YaakNotifier {
last_check: SystemTime, last_check: Option<Instant>,
} }
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)] #[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
@@ -47,9 +46,7 @@ pub struct YaakNotificationAction {
impl YaakNotifier { impl YaakNotifier {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self { last_check: None }
last_check: SystemTime::UNIX_EPOCH,
}
} }
pub async fn seen<R: Runtime>(&mut self, window: &WebviewWindow<R>, id: &str) -> Result<()> { pub async fn seen<R: Runtime>(&mut self, window: &WebviewWindow<R>, id: &str) -> Result<()> {
@@ -69,13 +66,13 @@ impl YaakNotifier {
pub async fn maybe_check<R: Runtime>(&mut self, window: &WebviewWindow<R>) -> Result<()> { pub async fn maybe_check<R: Runtime>(&mut self, window: &WebviewWindow<R>) -> Result<()> {
let app_handle = window.app_handle(); let app_handle = window.app_handle();
let ignore_check = self.last_check.elapsed().unwrap().as_secs() < MAX_UPDATE_CHECK_SECONDS; if let Some(i) = self.last_check
&& i.elapsed().as_secs() < MAX_UPDATE_CHECK_SECONDS
if ignore_check { {
return Ok(()); return Ok(());
} }
self.last_check = SystemTime::now(); self.last_check = Some(Instant::now());
if !app_handle.db().get_settings().check_notifications { if !app_handle.db().get_settings().check_notifications {
info!("Notifications are disabled. Skipping check."); info!("Notifications are disabled. Skipping check.");

View File

@@ -1,6 +1,6 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::path::PathBuf; use std::path::PathBuf;
use std::time::{Duration, SystemTime}; use std::time::{Duration, Instant};
use crate::error::Result; use crate::error::Result;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
@@ -24,7 +24,7 @@ const MAX_UPDATE_CHECK_HOURS_ALPHA: u64 = 1;
// Create updater struct // Create updater struct
pub struct YaakUpdater { pub struct YaakUpdater {
last_update_check: SystemTime, last_check: Option<Instant>,
} }
pub enum UpdateMode { pub enum UpdateMode {
@@ -62,9 +62,7 @@ pub enum UpdateTrigger {
impl YaakUpdater { impl YaakUpdater {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self { last_check: None }
last_update_check: SystemTime::UNIX_EPOCH,
}
} }
pub async fn check_now<R: Runtime>( pub async fn check_now<R: Runtime>(
@@ -84,7 +82,7 @@ impl YaakUpdater {
let settings = window.db().get_settings(); let settings = window.db().get_settings();
let update_key = format!("{:x}", md5::compute(settings.id)); let update_key = format!("{:x}", md5::compute(settings.id));
self.last_update_check = SystemTime::now(); self.last_check = Some(Instant::now());
info!("Checking for updates mode={} autodl={}", mode, auto_download); info!("Checking for updates mode={} autodl={}", mode, auto_download);
@@ -176,9 +174,10 @@ impl YaakUpdater {
UpdateMode::Beta => MAX_UPDATE_CHECK_HOURS_BETA, UpdateMode::Beta => MAX_UPDATE_CHECK_HOURS_BETA,
UpdateMode::Alpha => MAX_UPDATE_CHECK_HOURS_ALPHA, UpdateMode::Alpha => MAX_UPDATE_CHECK_HOURS_ALPHA,
} * (60 * 60); } * (60 * 60);
let seconds_since_last_check = self.last_update_check.elapsed().unwrap().as_secs();
let ignore_check = seconds_since_last_check < update_period_seconds; if let Some(i) = self.last_check
if ignore_check { && i.elapsed().as_secs() < update_period_seconds
{
return Ok(false); return Ok(false);
} }

View File

@@ -95,12 +95,6 @@ pub(crate) fn create_window<R: Runtime>(
}); });
} }
#[cfg(not(target_os = "macos"))]
{
println!("ENABLING DECORATIONS FOR WINDOW");
win_builder = win_builder.decorations(true);
}
let settings = handle.db().get_settings(); let settings = handle.db().get_settings();
if config.hide_titlebar && !settings.use_native_titlebar { if config.hide_titlebar && !settings.use_native_titlebar {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@@ -110,8 +104,6 @@ pub(crate) fn create_window<R: Runtime>(
} }
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
{ {
// Doesn't seem to work from Rust, here, so we do it in main.tsx
println!("DISABLING DECORATIONS FOR WINDOW");
win_builder = win_builder.decorations(false); win_builder = win_builder.decorations(false);
} }
} }

View File

@@ -30,6 +30,10 @@ pub fn app_menu<R: Runtime>(app_handle: &AppHandle<R>) -> tauri::Result<Menu<R>>
], ],
)?; )?;
#[cfg(target_os = "macos")] {
window_menu.set_as_windows_menu_for_nsapp()?;
}
let help_menu = Submenu::with_id_and_items( let help_menu = Submenu::with_id_and_items(
app_handle, app_handle,
HELP_SUBMENU_ID, HELP_SUBMENU_ID,
@@ -44,6 +48,10 @@ pub fn app_menu<R: Runtime>(app_handle: &AppHandle<R>) -> tauri::Result<Menu<R>>
], ],
)?; )?;
#[cfg(target_os = "macos")] {
help_menu.set_as_windows_menu_for_nsapp()?;
}
let menu = Menu::with_items( let menu = Menu::with_items(
app_handle, app_handle,
&[ &[