Files
tolaria/src-tauri/src/lib.rs
Luca Rossi 465a80d3e1 style: cargo fmt (#135)
* ci: re-enable macOS code signing and notarization

Uncomment the Apple credential env vars in the release workflow
so Tauri's build step signs and notarizes the .app bundle.
This reverses the temporary disable from ee42731.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: cargo fmt

---------

Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 13:33:09 +01:00

326 lines
9.0 KiB
Rust

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<Vec<VaultEntry>, String> {
vault::scan_vault_cached(Path::new(&path))
}
#[tauri::command]
fn get_note_content(path: String) -> Result<String, String> {
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<String, String> {
frontmatter::update_frontmatter(&path, &key, value)
}
#[tauri::command]
fn delete_frontmatter_property(path: String, key: String) -> Result<String, String> {
frontmatter::delete_frontmatter_property(&path, &key)
}
#[tauri::command]
fn get_file_history(vault_path: String, path: String) -> Result<Vec<GitCommit>, String> {
git::get_file_history(&vault_path, &path)
}
#[tauri::command]
fn get_modified_files(vault_path: String) -> Result<Vec<ModifiedFile>, String> {
git::get_modified_files(&vault_path)
}
#[tauri::command]
fn get_file_diff(vault_path: String, path: String) -> Result<String, String> {
git::get_file_diff(&vault_path, &path)
}
#[tauri::command]
fn get_file_diff_at_commit(
vault_path: String,
path: String,
commit_hash: String,
) -> Result<String, String> {
git::get_file_diff_at_commit(&vault_path, &path, &commit_hash)
}
#[tauri::command]
fn git_commit(vault_path: String, message: String) -> Result<String, String> {
git::git_commit(&vault_path, &message)
}
#[tauri::command]
fn get_last_commit_info(vault_path: String) -> Result<Option<LastCommitInfo>, String> {
git::get_last_commit_info(&vault_path)
}
#[tauri::command]
fn git_pull(vault_path: String) -> Result<GitPullResult, String> {
git::git_pull(&vault_path)
}
#[tauri::command]
fn git_push(vault_path: String) -> Result<String, String> {
git::git_push(&vault_path)
}
#[tauri::command]
async fn ai_chat(request: AiChatRequest) -> Result<AiChatResponse, String> {
ai_chat::send_chat(request).await
}
#[tauri::command]
fn save_image(vault_path: String, filename: String, data: String) -> Result<String, String> {
vault::save_image(&vault_path, &filename, &data)
}
#[tauri::command]
fn rename_note(
vault_path: String,
old_path: String,
new_title: String,
) -> Result<RenameResult, String> {
vault::rename_note(&vault_path, &old_path, &new_title)
}
#[tauri::command]
fn purge_trash(vault_path: String) -> Result<Vec<String>, String> {
vault::purge_trash(&vault_path)
}
#[tauri::command]
fn migrate_is_a_to_type(vault_path: String) -> Result<usize, String> {
vault::migrate_is_a_to_type(&vault_path)
}
#[tauri::command]
fn create_getting_started_vault(target_path: Option<String>) -> Result<String, String> {
let path = match target_path {
Some(p) if !p.is_empty() => p,
_ => vault::default_vault_path()?.to_string_lossy().to_string(),
};
vault::create_getting_started_vault(&path)
}
#[tauri::command]
fn check_vault_exists(path: String) -> bool {
vault::vault_exists(&path)
}
#[tauri::command]
fn get_default_vault_path() -> Result<String, String> {
vault::default_vault_path().map(|p| p.to_string_lossy().to_string())
}
#[tauri::command]
fn batch_archive_notes(paths: Vec<String>) -> Result<usize, String> {
let mut count = 0;
for path in &paths {
frontmatter::update_frontmatter(path, "Archived", FrontmatterValue::Bool(true))?;
count += 1;
}
Ok(count)
}
#[tauri::command]
fn batch_trash_notes(paths: Vec<String>) -> Result<usize, String> {
let now = chrono::Utc::now().format("%Y-%m-%dT%H:%M:%SZ").to_string();
let mut count = 0;
for path in &paths {
frontmatter::update_frontmatter(path, "Trashed", FrontmatterValue::Bool(true))?;
frontmatter::update_frontmatter(path, "Trashed at", FrontmatterValue::String(now.clone()))?;
count += 1;
}
Ok(count)
}
#[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, String> {
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<Vec<GithubRepo>, String> {
github::github_list_repos(&token).await
}
#[tauri::command]
async fn github_create_repo(
token: String,
name: String,
private: bool,
) -> Result<GithubRepo, String> {
github::github_create_repo(&token, &name, private).await
}
#[tauri::command]
fn clone_repo(url: String, token: String, local_path: String) -> Result<String, String> {
github::clone_repo(&url, &token, &local_path)
}
#[tauri::command]
async fn github_device_flow_start() -> Result<DeviceFlowStart, String> {
github::github_device_flow_start().await
}
#[tauri::command]
async fn github_device_flow_poll(device_code: String) -> Result<DeviceFlowPollResult, String> {
github::github_device_flow_poll(&device_code).await
}
#[tauri::command]
async fn github_get_user(token: String) -> Result<GitHubUser, String> {
github::github_get_user(&token).await
}
#[tauri::command]
async fn search_vault(
vault_path: String,
query: String,
mode: String,
limit: Option<usize>,
) -> Result<SearchResponse, String> {
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<usize, String>) {
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,
batch_archive_notes,
batch_trash_notes,
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,
create_getting_started_vault,
check_vault_exists,
get_default_vault_path
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}