//! Diagnostics commands (envelope `{ok, value}` / `{ok:false, error}` as in 0.1.0). use super::{envelope, main_core, text, CommandResult}; use crate::core::app::CoreSlot; use crate::core::error::{CoreError, CoreResult}; use crate::dialogs::{self, Filter}; use serde_json::{json, Value}; use tauri::{State, Webview}; use tauri_plugin_clipboard_manager::ClipboardExt; fn wrap(result: CoreResult) -> Value { envelope(result, "DIAGNOSTICS_ERROR", Some(400)) } #[tauri::command] pub async fn core_diagnostics_resolve(webview: Webview, slot: State<'_, CoreSlot>, payload: Option) -> CommandResult { let core = main_core(&webview, &slot)?; Ok(wrap(core.services.diagnostics.resolve(&super::payload(payload)).await.map_err(CoreError::from))) } #[tauri::command] pub async fn core_diagnostics_start(webview: Webview, slot: State<'_, CoreSlot>, payload: Option) -> CommandResult { let core = main_core(&webview, &slot)?; Ok(wrap(core.services.diagnostics.start(&super::payload(payload)).map_err(CoreError::from))) } #[tauri::command] pub async fn core_diagnostics_cancel(webview: Webview, slot: State<'_, CoreSlot>, payload: Option) -> CommandResult { let core = main_core(&webview, &slot)?; let payload = super::payload(payload); Ok(wrap(core.services.diagnostics.cancel(text(&payload, "id"), payload.get("tool").and_then(Value::as_str)).map_err(CoreError::from))) } #[tauri::command] pub async fn core_diagnostics_get(webview: Webview, slot: State<'_, CoreSlot>, payload: Option) -> CommandResult { let core = main_core(&webview, &slot)?; let payload = super::payload(payload); Ok(wrap(core.services.diagnostics.get(text(&payload, "id")).map_err(CoreError::from))) } #[tauri::command] pub async fn core_diagnostics_history(webview: Webview, slot: State<'_, CoreSlot>) -> CommandResult { let core = main_core(&webview, &slot)?; Ok(wrap(core.services.diagnostics.history.list().map_err(CoreError::from))) } #[tauri::command] pub async fn core_diagnostics_remove_history(webview: Webview, slot: State<'_, CoreSlot>, payload: Option) -> CommandResult { let core = main_core(&webview, &slot)?; let payload = super::payload(payload); Ok(wrap(core.services.diagnostics.history.remove(payload.get("id").and_then(Value::as_str)).map_err(CoreError::from))) } #[tauri::command] pub async fn core_diagnostics_copy(webview: Webview, slot: State<'_, CoreSlot>, payload: Option) -> CommandResult { let core = main_core(&webview, &slot)?; let payload = super::payload(payload); let format = payload.get("format").and_then(Value::as_str).filter(|f| !f.is_empty()).unwrap_or("txt"); let result = core .services .diagnostics .export(text(&payload, "id"), format) .map_err(CoreError::from) .and_then(|content| core.app.clipboard().write_text(content).map_err(|e| CoreError::plain(e.to_string()))) .map(|_| json!({ "copied": true })); Ok(wrap(result)) } #[tauri::command] pub async fn core_diagnostics_export(webview: Webview, slot: State<'_, CoreSlot>, payload: Option) -> CommandResult { let core = main_core(&webview, &slot)?; let payload = super::payload(payload); let result = async { let format = text(&payload, "format").to_string(); let content = core.services.diagnostics.export(text(&payload, "id"), &format).map_err(CoreError::from)?; let window = dialogs::main_window(&core.app); let upper = format.to_uppercase(); let Some(path) = dialogs::save_file(&core.app, window.as_ref(), None, &format!("diagnostics.{format}"), &[Filter { name: &upper, extensions: &[format.as_str()] }]).await else { return Ok(json!({ "canceled": true })); }; super::profiles::write_private(&path, content.as_bytes())?; Ok(json!({ "canceled": false })) } .await; Ok(wrap(result)) } #[tauri::command] pub async fn core_diagnostics_import(webview: Webview, slot: State<'_, CoreSlot>) -> CommandResult { let core = main_core(&webview, &slot)?; let result = async { let window = dialogs::main_window(&core.app); let Some(path) = dialogs::pick_file(&core.app, window.as_ref(), None, &[Filter { name: &core.t("native.diagnostics.importFilter"), extensions: &["json"] }]).await else { return Ok(json!({ "canceled": true })); }; let meta = std::fs::symlink_metadata(&path)?; if !meta.is_file() || meta.len() > 2 * 1024 * 1024 { return Err(CoreError::new("IMPORT_LIMIT", "IMPORT_LIMIT")); } let text = std::fs::read_to_string(&path)?; let id = core.services.diagnostics.history.import(&text).map_err(CoreError::from)?; Ok(json!({ "id": id })) } .await; Ok(wrap(result)) }