Compare commits

...

2 Commits

6 changed files with 738 additions and 628 deletions

View File

@ -11,28 +11,28 @@
},
"dependencies": {
"@heroicons/vue": "^2.2.0",
"@tauri-apps/api": "^2.5.0",
"@tauri-apps/plugin-dialog": "~2.2.2",
"@tauri-apps/plugin-fs": "~2.3.0",
"@tauri-apps/plugin-shell": "^2.2.1",
"@tauri-apps/plugin-sql": "~2.2.0",
"@tauri-apps/plugin-store": "~2.2.0",
"@tauri-apps/api": "~2.6.0",
"@tauri-apps/plugin-dialog": "~2.3.0",
"@tauri-apps/plugin-fs": "~2.4.0",
"@tauri-apps/plugin-shell": "~2.3.0",
"@tauri-apps/plugin-sql": "~2.3.0",
"@tauri-apps/plugin-store": "~2.3.0",
"clusterize.js": "^1.0.0",
"csv-parse": "^5.6.0",
"dayjs": "^1.11.13",
"vue": "^3.5.16",
"vue": "^3.5.17",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.10",
"@tauri-apps/cli": "^2.5.0",
"@tauri-apps/cli": "^2.6.2",
"@types/clusterize.js": "^0.18.3",
"@vitejs/plugin-vue": "^5.2.4",
"autoprefixer": "^10.4.21",
"postcss": "^8.5.4",
"postcss": "^8.5.6",
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^5.4.19",
"vue-tsc": "^2.2.10"
"vue-tsc": "^2.2.12"
}
}

660
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

631
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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"] }

View File

@ -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<AppState>>,
) -> Result<Option<String>, tauri_plugin_sql::Error> {
async fn get_open_filename(state: State<'_, Mutex<AppState>>) -> Result<Option<String>, ()> {
let state = state.lock().await;
Ok(state.db_filename.clone())
}
@ -46,7 +46,7 @@ async fn set_open_filename(
state: State<'_, Mutex<AppState>>,
app: AppHandle,
filename: Option<String>,
) -> 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::<EventBox>()
.expect("ApplicationWindow.titlebar not EventBox");
let header_bar = event_box
.child()
.expect("ApplicationWindow.titlebar has null child")
.downcast::<HeaderBar>()
.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,

View File

@ -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) {