pub mod ai_chat; pub mod frontmatter; pub mod git; pub mod github; pub mod menu; pub mod search; pub mod settings; pub mod vault; use std::path::Path; use ai_chat::{AiChatRequest, AiChatResponse}; use frontmatter::FrontmatterValue; use git::{GitCommit, GitPullResult, LastCommitInfo, ModifiedFile}; use github::{DeviceFlowPollResult, DeviceFlowStart, GitHubUser, GithubRepo}; use search::SearchResponse; use settings::Settings; use vault::{RenameResult, VaultEntry}; #[tauri::command] fn list_vault(path: String) -> Result, String> { vault::scan_vault_cached(Path::new(&path)) } #[tauri::command] fn get_note_content(path: String) -> Result { vault::get_note_content(Path::new(&path)) } #[tauri::command] fn save_note_content(path: String, content: String) -> Result<(), String> { vault::save_note_content(&path, &content) } #[tauri::command] fn update_frontmatter( path: String, key: String, value: FrontmatterValue, ) -> Result { frontmatter::update_frontmatter(&path, &key, value) } #[tauri::command] fn delete_frontmatter_property(path: String, key: String) -> Result { frontmatter::delete_frontmatter_property(&path, &key) } #[tauri::command] fn get_file_history(vault_path: String, path: String) -> Result, String> { git::get_file_history(&vault_path, &path) } #[tauri::command] fn get_modified_files(vault_path: String) -> Result, String> { git::get_modified_files(&vault_path) } #[tauri::command] fn get_file_diff(vault_path: String, path: String) -> Result { git::get_file_diff(&vault_path, &path) } #[tauri::command] fn get_file_diff_at_commit( vault_path: String, path: String, commit_hash: String, ) -> Result { git::get_file_diff_at_commit(&vault_path, &path, &commit_hash) } #[tauri::command] fn git_commit(vault_path: String, message: String) -> Result { git::git_commit(&vault_path, &message) } #[tauri::command] fn get_last_commit_info(vault_path: String) -> Result, String> { git::get_last_commit_info(&vault_path) } #[tauri::command] fn git_pull(vault_path: String) -> Result { git::git_pull(&vault_path) } #[tauri::command] fn git_push(vault_path: String) -> Result { git::git_push(&vault_path) } #[tauri::command] async fn ai_chat(request: AiChatRequest) -> Result { ai_chat::send_chat(request).await } #[tauri::command] fn save_image(vault_path: String, filename: String, data: String) -> Result { vault::save_image(&vault_path, &filename, &data) } #[tauri::command] fn rename_note( vault_path: String, old_path: String, new_title: String, ) -> Result { vault::rename_note(&vault_path, &old_path, &new_title) } #[tauri::command] fn purge_trash(vault_path: String) -> Result, String> { vault::purge_trash(&vault_path) } #[tauri::command] fn migrate_is_a_to_type(vault_path: String) -> Result { vault::migrate_is_a_to_type(&vault_path) } #[tauri::command] fn update_menu_state(app_handle: tauri::AppHandle, has_active_note: bool) -> Result<(), String> { menu::set_note_items_enabled(&app_handle, has_active_note); Ok(()) } #[tauri::command] fn get_settings() -> Result { settings::get_settings() } #[tauri::command] fn save_settings(settings: Settings) -> Result<(), String> { settings::save_settings(settings) } #[tauri::command] async fn github_list_repos(token: String) -> Result, String> { github::github_list_repos(&token).await } #[tauri::command] async fn github_create_repo( token: String, name: String, private: bool, ) -> Result { github::github_create_repo(&token, &name, private).await } #[tauri::command] fn clone_repo(url: String, token: String, local_path: String) -> Result { github::clone_repo(&url, &token, &local_path) } #[tauri::command] async fn github_device_flow_start() -> Result { github::github_device_flow_start().await } #[tauri::command] async fn github_device_flow_poll(device_code: String) -> Result { github::github_device_flow_poll(&device_code).await } #[tauri::command] async fn github_get_user(token: String) -> Result { github::github_get_user(&token).await } #[tauri::command] async fn search_vault( vault_path: String, query: String, mode: String, limit: Option, ) -> Result { let limit = limit.unwrap_or(20); tokio::task::spawn_blocking(move || search::search_vault(&vault_path, &query, &mode, limit)) .await .map_err(|e| format!("Search task failed: {}", e))? } fn log_startup_result(label: &str, result: Result) { match result { Ok(n) if n > 0 => log::info!("{}: {} files", label, n), Err(e) => log::warn!("{}: {}", label, e), _ => {} } } /// Run startup housekeeping on the default vault (purge old trash, migrate legacy frontmatter). fn run_startup_tasks() { let vault_path = dirs::home_dir() .map(|h| h.join("Laputa")) .unwrap_or_default(); if !vault_path.is_dir() { return; } let vp_str = vault_path.to_str().unwrap_or_default(); log_startup_result( "Purged trashed files on startup", vault::purge_trash(vp_str).map(|d| d.len()), ); log_startup_result( "Migrated is_a to type on startup", vault::migrate_is_a_to_type(vp_str), ); } #[cfg(test)] mod tests {} #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .setup(|app| { if cfg!(debug_assertions) { app.handle().plugin( tauri_plugin_log::Builder::default() .level(log::LevelFilter::Info) .build(), )?; // Open devtools automatically in debug builds use tauri::Manager; if let Some(window) = app.get_webview_window("main") { window.open_devtools(); } } app.handle().plugin(tauri_plugin_dialog::init())?; #[cfg(desktop)] { app.handle() .plugin(tauri_plugin_updater::Builder::new().build())?; app.handle().plugin(tauri_plugin_process::init())?; app.handle().plugin(tauri_plugin_opener::init())?; menu::setup_menu(app)?; } run_startup_tasks(); Ok(()) }) .invoke_handler(tauri::generate_handler![ list_vault, get_note_content, save_note_content, update_frontmatter, delete_frontmatter_property, rename_note, get_file_history, get_modified_files, get_file_diff, get_file_diff_at_commit, git_commit, get_last_commit_info, git_pull, git_push, ai_chat, save_image, purge_trash, migrate_is_a_to_type, get_settings, update_menu_state, save_settings, github_list_repos, github_create_repo, clone_repo, github_device_flow_start, github_device_flow_poll, github_get_user, search_vault ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }