diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1912766..471b8c6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -796,6 +796,7 @@ name = "drcr" version = "0.1.0" dependencies = [ "chrono", + "gtk", "indexmap 2.10.0", "libdrcr", "serde", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 84bf0df..8695ab1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,6 +19,7 @@ tauri-build = { version = "2", features = [] } [dependencies] chrono = "0.4.41" +gtk = "0.18.2" indexmap = { version = "2", features = ["serde"] } libdrcr = { path = "../libdrcr" } serde = { version = "1", features = ["derive"] } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 35fd784..3f84458 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,5 +1,5 @@ /* - DrCr: Web-based double-entry bookkeeping framework + DrCr: Double-entry bookkeeping framework Copyright (C) 2022-2025 Lee Yingtong Li (RunasSudo) This program is free software: you can redistribute it and/or modify @@ -20,6 +20,8 @@ mod libdrcr_austax; mod libdrcr_bridge; mod sql; +use gtk::prelude::{BinExt, Cast, GtkWindowExt, HeaderBarExt}; +use gtk::{EventBox, HeaderBar}; use tauri::{AppHandle, Builder, Manager, State}; use tauri_plugin_store::StoreExt; use tokio::sync::Mutex; @@ -34,9 +36,7 @@ struct AppState { // Filename state #[tauri::command] -async fn get_open_filename( - state: State<'_, Mutex>, -) -> Result, tauri_plugin_sql::Error> { +async fn get_open_filename(state: State<'_, Mutex>) -> Result, ()> { let state = state.lock().await; Ok(state.db_filename.clone()) } @@ -46,7 +46,7 @@ async fn set_open_filename( state: State<'_, Mutex>, app: AppHandle, filename: Option, -) -> Result<(), tauri_plugin_sql::Error> { +) -> Result<(), ()> { let mut state = state.lock().await; state.db_filename = filename.clone(); @@ -57,6 +57,34 @@ async fn set_open_filename( Ok(()) } +#[tauri::command] +async fn set_window_title(app: AppHandle, label: &str, title: &str) -> Result<(), ()> { + // First call Tauri + let tauri_window = app.get_webview_window(label).unwrap(); + tauri_window.set_title(title).unwrap(); + + // Then work around https://github.com/tauri-apps/tauri/issues/13749 + let gtk_window = tauri_window.gtk_window().unwrap(); + match gtk_window.titlebar() { + Some(titlebar) => { + let event_box = titlebar + .downcast::() + .expect("ApplicationWindow.titlebar not EventBox"); + + let header_bar = event_box + .child() + .expect("ApplicationWindow.titlebar has null child") + .downcast::() + .expect("ApplicationWindow.titlebar.child not HeaderBar"); + + header_bar.set_title(Some(title)); + } + None => (), + } + + Ok(()) +} + // Main method #[cfg_attr(mobile, tauri::mobile_entry_point)] @@ -75,7 +103,10 @@ pub fn run() { None } } - _ => panic!("Unexpected db_filename in store: {:?}", store.get("db_filename")), + _ => panic!( + "Unexpected db_filename in store: {:?}", + store.get("db_filename") + ), }; app.manage(Mutex::new(AppState { @@ -93,6 +124,7 @@ pub fn run() { .invoke_handler(tauri::generate_handler![ get_open_filename, set_open_filename, + set_window_title, libdrcr_austax::get_tax_summary, libdrcr_bridge::get_all_transactions_except_earnings_to_equity, libdrcr_bridge::get_all_transactions_except_earnings_to_equity_for_account, diff --git a/src/db.ts b/src/db.ts index 240d3fc..de752a5 100644 --- a/src/db.ts +++ b/src/db.ts @@ -49,9 +49,15 @@ export const db = reactive({ await invoke('set_open_filename', { 'filename': filename }); if (filename !== null) { - await getCurrentWindow().setTitle('DrCr – ' + filename?.replaceAll('\\', '/').split('/').at(-1)); + await invoke('set_window_title', { + 'label': await getCurrentWindow().label, + 'title': 'DrCr – ' + filename?.replaceAll('\\', '/').split('/').at(-1) + }); } else { - await getCurrentWindow().setTitle('DrCr'); + await invoke('set_window_title', { + 'label': await getCurrentWindow().label, + 'title': 'DrCr' + }); } if (filename !== null) {