use rusqlite::Connection; use std::sync::Mutex; use std::path::PathBuf; use tauri::Manager; mod database; mod commands; mod os_detection; pub struct AppState { pub db: Mutex, } fn get_data_dir() -> PathBuf { let exe_path = std::env::current_exe().unwrap(); let data_dir = exe_path.parent().unwrap().join("data"); std::fs::create_dir_all(&data_dir).ok(); data_dir } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { env_logger::init(); let data_dir = get_data_dir(); let db_path = data_dir.join("timetracker.db"); let conn = Connection::open(&db_path).expect("Failed to open database"); database::init_db(&conn).expect("Failed to initialize database"); tauri::Builder::default() .plugin(tauri_plugin_window_state::Builder::new().build()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_notification::init()) .manage(AppState { db: Mutex::new(conn) }) .invoke_handler(tauri::generate_handler![ commands::get_clients, commands::create_client, commands::update_client, commands::delete_client, commands::get_projects, commands::create_project, commands::update_project, commands::delete_project, commands::get_tasks, commands::create_task, commands::delete_task, commands::get_time_entries, commands::create_time_entry, commands::update_time_entry, commands::delete_time_entry, commands::get_reports, commands::create_invoice, commands::get_invoices, commands::update_invoice, commands::delete_invoice, commands::get_settings, commands::update_settings, commands::export_data, commands::clear_all_data, commands::get_idle_seconds, commands::get_visible_windows, commands::get_running_processes, commands::get_tracked_apps, commands::add_tracked_app, commands::remove_tracked_app, commands::get_tags, commands::create_tag, commands::update_tag, commands::delete_tag, commands::get_entry_tags, commands::set_entry_tags, commands::get_project_budget_status, commands::get_favorites, commands::create_favorite, commands::delete_favorite, commands::reorder_favorites, ]) .setup(|app| { #[cfg(desktop)] { use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}; use tauri::menu::{Menu, MenuItem}; let quit = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?; let show = MenuItem::with_id(app, "show", "Show Window", true, None::<&str>)?; let menu = Menu::with_items(app, &[&show, &quit])?; let _tray = TrayIconBuilder::new() .menu(&menu) .show_menu_on_left_click(false) .on_menu_event(|app, event| { match event.id.as_ref() { "quit" => { app.exit(0); } "show" => { if let Some(window) = app.get_webview_window("main") { window.show().ok(); window.set_focus().ok(); } } _ => {} } }) .on_tray_icon_event(|tray, event| { if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { let app = tray.app_handle(); if let Some(window) = app.get_webview_window("main") { window.show().ok(); window.set_focus().ok(); } } }) .build(app)?; } Ok(()) }) .run(tauri::generate_context!()) .expect("error while running tauri application"); }