use std::path::Path;
use std::sync::Mutex;
use tauri::State;
use serde::Serialize;
use crate::state::{VaultViewerState, Tab};
use crate::config::save_tabs;
#[derive(Debug, Clone, Serialize)]
pub struct TabInfo {
pub id: String,
pub path: String,
pub title: String,
pub is_dirty: bool,
pub tab_type: String,
}
impl From<crate::state::Tab> for TabInfo {
fn from(tab: Tab) -> Self {
TabInfo {
id: tab.id,
path: tab.path,
title: tab.title,
is_dirty: tab.is_dirty,
tab_type: tab.tab_type,
}
}
}
#[tauri::command]
pub async fn add_tab(
path: String,
title: String,
tab_type: String,
state: State<'_, Mutex<VaultViewerState>>,
) -> Result<String, String> {
let mut viewer_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
let tab_id = viewer_state.add_tab(path, title, tab_type);
if let Some(vault_root) = &viewer_state.vault_root {
let _ = save_tabs(
Path::new(vault_root),
&viewer_state.open_tabs,
&viewer_state.active_tab,
);
}
Ok(tab_id)
}
#[tauri::command]
pub async fn close_tab(
tab_id: String,
state: State<'_, Mutex<VaultViewerState>>,
) -> Result<(), String> {
let mut viewer_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
viewer_state.close_tab(&tab_id);
if let Some(vault_root) = &viewer_state.vault_root {
let _ = save_tabs(
Path::new(vault_root),
&viewer_state.open_tabs,
&viewer_state.active_tab,
);
}
Ok(())
}
#[tauri::command]
pub async fn set_active_tab(
tab_id: String,
state: State<'_, Mutex<VaultViewerState>>,
) -> Result<(), String> {
let mut viewer_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
viewer_state.set_active_tab(tab_id);
if let Some(vault_root) = &viewer_state.vault_root {
let _ = save_tabs(
Path::new(vault_root),
&viewer_state.open_tabs,
&viewer_state.active_tab,
);
}
Ok(())
}
#[tauri::command]
pub async fn back_button(
state: State<'_, Mutex<VaultViewerState>>,
) -> Result<(), String> {
let mut viewer_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
viewer_state.back();
Ok(())
}
#[tauri::command]
pub async fn get_tabs(
state: State<'_, Mutex<VaultViewerState>>,
) -> Result<GetTabsResponse, String> {
let viewer_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
let open_tabs = viewer_state
.open_tabs
.iter()
.map(|tab| TabInfo::from(tab.clone()))
.collect();
let active_tab = viewer_state.active_tab.clone();
Ok(GetTabsResponse {
open_tabs,
active_tab,
})
}
#[derive(Debug, Serialize)]
pub struct GetTabsResponse {
pub open_tabs: Vec<TabInfo>,
pub active_tab: Option<String>,
}
#[tauri::command]
pub async fn set_vault_root(
vault_root: String,
state: State<'_, Mutex<VaultViewerState>>,
) -> Result<(), String> {
let mut viewer_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
viewer_state.vault_root = Some(vault_root);
Ok(())
}
#[tauri::command]
pub async fn load_saved_tabs(
state: State<'_, Mutex<VaultViewerState>>,
) -> Result<Option<GetTabsResponse>, String> {
let mut viewer_state = state.lock().map_err(|e| format!("Failed to lock state: {}", e))?;
if !viewer_state.user_preferences.auto_restore_tabs {
return Ok(None);
}
let vault_root = match &viewer_state.vault_root {
Some(root) => root.clone(),
None => return Ok(None),
};
use crate::config::load_tabs;
match load_tabs(Path::new(&vault_root)) {
Ok(Some(tabs_state)) => {
viewer_state.open_tabs = tabs_state.open_tabs.clone();
viewer_state.active_tab = tabs_state.active_tab.clone();
let open_tabs = viewer_state
.open_tabs
.iter()
.map(|tab| TabInfo::from(tab.clone()))
.collect();
let active_tab = viewer_state.active_tab.clone();
Ok(Some(GetTabsResponse {
open_tabs,
active_tab,
}))
}
Ok(None) => Ok(None),
Err(e) => Err(e),
}
}