From c9d3536f360304e6abc19b44c47493cecfbf2b35 Mon Sep 17 00:00:00 2001 From: Mohan <86064887+binarybaron@users.noreply.github.com> Date: Wed, 22 Jan 2025 16:29:11 +0100 Subject: [PATCH] fix(gui): Button to open data directory (#256) --- CHANGELOG.md | 1 + Cargo.lock | 144 +++++++++++++++++- src-gui/package.json | 1 + .../pages/help/DaemonControlBox.tsx | 12 +- src-gui/src/renderer/rpc.ts | 8 + src-gui/yarn.lock | 7 + src-tauri/Cargo.toml | 1 + src-tauri/capabilities/default.json | 3 +- src-tauri/src/lib.rs | 26 ++-- swap/src/cli/api.rs | 2 +- swap/src/cli/api/request.rs | 6 + 11 files changed, 187 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3514a11ac..555acba2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Docs: Added a dedicated page for makers. - Docs: Improved the refund and punish page. - ASB: Fixed an issue where the ASB would silently fail if the publication of the Monero refund transaction failed. +- GUI: Add a button to open the data directory for troubleshooting purposes. ## [1.0.0-rc.12] - 2025-01-14 diff --git a/Cargo.lock b/Cargo.lock index 5a30fc7e1..9a590e664 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9345,6 +9345,28 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "tauri-plugin-opener" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "635ed7c580dc3cdc61c94097d38ef517d749ffc0141c806d904e68e4b0cf1c2a" +dependencies = [ + "dunce", + "glob", + "objc2-app-kit", + "objc2-foundation", + "open", + "schemars", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.4", + "url", + "windows 0.58.0", + "zbus 5.3.0", +] + [[package]] name = "tauri-plugin-process" version = "2.0.1" @@ -9388,7 +9410,7 @@ dependencies = [ "thiserror 2.0.4", "tracing", "windows-sys 0.59.0", - "zbus", + "zbus 4.4.0", ] [[package]] @@ -11346,6 +11368,7 @@ dependencies = [ "tauri-build", "tauri-plugin-cli", "tauri-plugin-clipboard-manager", + "tauri-plugin-opener", "tauri-plugin-process", "tauri-plugin-shell", "tauri-plugin-single-instance", @@ -12593,9 +12616,45 @@ dependencies = [ "uds_windows", "windows-sys 0.52.0", "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", + "zbus_macros 4.4.0", + "zbus_names 3.0.0", + "zvariant 4.2.0", +] + +[[package]] +name = "zbus" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "192a0d989036cd60a1e91a54c9851fb9ad5bd96125d41803eed79d2e2ef74bd7" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock 3.4.0", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener 5.3.1", + "futures-core", + "futures-util", + "hex", + "nix 0.29.0", + "ordered-stream", + "serde", + "serde_repr", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.59.0", + "winnow 0.6.20", + "xdg-home", + "zbus_macros 5.3.0", + "zbus_names 4.1.1", + "zvariant 5.2.0", ] [[package]] @@ -12608,7 +12667,22 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.90", - "zvariant_utils", + "zvariant_utils 2.1.0", +] + +[[package]] +name = "zbus_macros" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3685b5c81fce630efc3e143a4ded235b107f1b1cdf186c3f115529e5e5ae4265" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", + "zbus_names 4.1.1", + "zvariant 5.2.0", + "zvariant_utils 3.1.0", ] [[package]] @@ -12619,7 +12693,19 @@ checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" dependencies = [ "serde", "static_assertions", - "zvariant", + "zvariant 4.2.0", +] + +[[package]] +name = "zbus_names" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "519629a3f80976d89c575895b05677cbc45eaf9f70d62a364d819ba646409cc8" +dependencies = [ + "serde", + "static_assertions", + "winnow 0.6.20", + "zvariant 5.2.0", ] [[package]] @@ -12745,7 +12831,22 @@ dependencies = [ "enumflags2", "serde", "static_assertions", - "zvariant_derive", + "zvariant_derive 4.2.0", +] + +[[package]] +name = "zvariant" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55e6b9b5f1361de2d5e7d9fd1ee5f6f7fcb6060618a1f82f3472f58f2b8d4be9" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "winnow 0.6.20", + "zvariant_derive 5.2.0", + "zvariant_utils 3.1.0", ] [[package]] @@ -12758,7 +12859,20 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.90", - "zvariant_utils", + "zvariant_utils 2.1.0", +] + +[[package]] +name = "zvariant_derive" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "573a8dd76961957108b10f7a45bac6ab1ea3e9b7fe01aff88325dc57bb8f5c8b" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.90", + "zvariant_utils 3.1.0", ] [[package]] @@ -12771,3 +12885,17 @@ dependencies = [ "quote", "syn 2.0.90", ] + +[[package]] +name = "zvariant_utils" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd46446ea2a1f353bfda53e35f17633afa79f4fe290a611c94645c69fe96a50" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "static_assertions", + "syn 2.0.90", + "winnow 0.6.20", +] diff --git a/src-gui/package.json b/src-gui/package.json index 56f413e17..d24a82a6d 100644 --- a/src-gui/package.json +++ b/src-gui/package.json @@ -23,6 +23,7 @@ "@tauri-apps/api": "^2.0.0", "@tauri-apps/plugin-cli": "^2.0.0", "@tauri-apps/plugin-clipboard-manager": "^2.0.0", + "@tauri-apps/plugin-opener": "^2.2.5", "@tauri-apps/plugin-process": "^2.0.0", "@tauri-apps/plugin-shell": "^2.0.0", "@tauri-apps/plugin-store": "^2.0.0", diff --git a/src-gui/src/renderer/components/pages/help/DaemonControlBox.tsx b/src-gui/src/renderer/components/pages/help/DaemonControlBox.tsx index 7d5bcb42e..169d2372e 100644 --- a/src-gui/src/renderer/components/pages/help/DaemonControlBox.tsx +++ b/src-gui/src/renderer/components/pages/help/DaemonControlBox.tsx @@ -5,9 +5,10 @@ import PromiseInvokeButton from "renderer/components/PromiseInvokeButton"; import { useAppSelector } from "store/hooks"; import InfoBox from "../../modal/swap/InfoBox"; import CliLogsBox from "../../other/RenderedCliLog"; -import { initializeContext } from "renderer/rpc"; +import { getDataDir, initializeContext } from "renderer/rpc"; import { relaunch } from "@tauri-apps/plugin-process"; import RotateLeftIcon from "@material-ui/icons/RotateLeft"; +import { revealItemInDir } from "@tauri-apps/plugin-opener"; const useStyles = makeStyles((theme) => ({ actionsOuter: { @@ -66,11 +67,12 @@ export default function DaemonControlBox() { } isIconButton + requiresContext={false} size="small" - tooltipTitle="Open the data directory of the Swap Daemon in your file explorer" - onInvoke={() => { - // TODO: Implement this - throw new Error("Not implemented"); + tooltipTitle="Open the data directory in your file explorer" + onInvoke={async () => { + const dataDir = await getDataDir(); + await revealItemInDir(dataDir); }} /> diff --git a/src-gui/src/renderer/rpc.ts b/src-gui/src/renderer/rpc.ts index 870c5ba0c..ba374ee08 100644 --- a/src-gui/src/renderer/rpc.ts +++ b/src-gui/src/renderer/rpc.ts @@ -29,6 +29,7 @@ import { CheckElectrumNodeResponse, GetMoneroAddressesResponse, TauriBackgroundRefundEvent, + GetDataDirArgs, } from "models/tauriModel"; import { contextStatusEventReceived, @@ -277,3 +278,10 @@ export async function updateAllNodeStatuses() { export async function getMoneroAddresses(): Promise { return await invokeNoArgs("get_monero_addresses"); } + +export async function getDataDir(): Promise { + const testnet = isTestnet(); + return await invoke("get_data_dir", { + is_testnet: testnet, + }); +} diff --git a/src-gui/yarn.lock b/src-gui/yarn.lock index c0d2b4d31..e2cc58076 100644 --- a/src-gui/yarn.lock +++ b/src-gui/yarn.lock @@ -792,6 +792,13 @@ dependencies: "@tauri-apps/api" "^2.0.0" +"@tauri-apps/plugin-opener@^2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-opener/-/plugin-opener-2.2.5.tgz#928b917d28d3e8b5bafb90f5f91fb0ed20c27fd4" + integrity sha512-hHsJ9RPWpZvZEPVFaL+d25gABMUMOf/A6ESXnvf/ii9guTukj58WXsAE/SOysXRIhej7kseRCxnOnIMpSCdUsQ== + dependencies: + "@tauri-apps/api" "^2.0.0" + "@tauri-apps/plugin-process@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-process/-/plugin-process-2.0.0.tgz#002fd73f0d7b1ae2a5aacf442aa657e83dc2960b" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ff1ae6620..8f6bd7a59 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -22,6 +22,7 @@ swap = { path = "../swap", features = [ "tauri" ] } sysinfo = "=0.32.1" tauri = { version = "^2.0.0", features = [ "config-json5" ] } tauri-plugin-clipboard-manager = "^2.0.0" +tauri-plugin-opener = "2.2.5" tauri-plugin-process = "^2.0.0" tauri-plugin-shell = "^2.0.0" tauri-plugin-store = "^2.0.0" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 7b2c9f336..637cf2524 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -12,6 +12,7 @@ "process:default", "cli:allow-cli-matches", "updater:default", - "process:allow-restart" + "process:allow-restart", + "opener:default" ] } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index f4b9ce5e0..fbd84741d 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -3,15 +3,9 @@ use std::result::Result; use std::sync::Arc; use swap::cli::{ api::{ - request::{ - BalanceArgs, BuyXmrArgs, CancelAndRefundArgs, CheckElectrumNodeArgs, - CheckElectrumNodeResponse, CheckMoneroNodeArgs, CheckMoneroNodeResponse, - ExportBitcoinWalletArgs, GetHistoryArgs, GetLogsArgs, GetMoneroAddressesArgs, - GetSwapInfoArgs, GetSwapInfosAllArgs, ListSellersArgs, MoneroRecoveryArgs, - ResumeSwapArgs, SuspendCurrentSwapArgs, WithdrawBtcArgs, - }, - tauri_bindings::{TauriContextStatusEvent, TauriEmitter, TauriHandle, TauriSettings}, - Context, ContextBuilder, + data, request::{ + BalanceArgs, BuyXmrArgs, CancelAndRefundArgs, CheckElectrumNodeArgs, CheckElectrumNodeResponse, CheckMoneroNodeArgs, CheckMoneroNodeResponse, ExportBitcoinWalletArgs, GetDataDirArgs, GetHistoryArgs, GetLogsArgs, GetMoneroAddressesArgs, GetSwapInfoArgs, GetSwapInfosAllArgs, ListSellersArgs, MoneroRecoveryArgs, ResumeSwapArgs, SuspendCurrentSwapArgs, WithdrawBtcArgs + }, tauri_bindings::{TauriContextStatusEvent, TauriEmitter, TauriHandle, TauriSettings}, Context, ContextBuilder }, command::{Bitcoin, Monero}, }; @@ -162,6 +156,7 @@ pub fn run() { .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_opener::init()) .invoke_handler(tauri::generate_handler![ get_balance, get_monero_addresses, @@ -181,6 +176,7 @@ pub fn run() { check_monero_node, check_electrum_node, get_wallet_descriptor, + get_data_dir ]) .setup(setup) .build(tauri::generate_context!()) @@ -221,6 +217,7 @@ tauri_command!(monero_recovery, MoneroRecoveryArgs); tauri_command!(get_logs, GetLogsArgs); tauri_command!(list_sellers, ListSellersArgs); tauri_command!(cancel_and_refund, CancelAndRefundArgs); + // These commands require no arguments tauri_command!(get_wallet_descriptor, ExportBitcoinWalletArgs, no_args); tauri_command!(suspend_current_swap, SuspendCurrentSwapArgs, no_args); @@ -252,6 +249,17 @@ async fn check_electrum_node( args.request().await.to_string_result() } +// Returns the data directory +// This is independent of the context to ensure the user can open the directory even if the context cannot +// be initialized (for troubleshooting purposes) +#[tauri::command] +async fn get_data_dir( + args: GetDataDirArgs, + _: tauri::State<'_, RwLock>, +) -> Result { + Ok(data::data_dir_from(None, args.is_testnet).to_string_result()?.to_string_lossy().to_string()) +} + /// Tauri command to initialize the Context #[tauri::command] async fn initialize_context( diff --git a/swap/src/cli/api.rs b/swap/src/cli/api.rs index bd2bbefcc..9794b6ae2 100644 --- a/swap/src/cli/api.rs +++ b/swap/src/cli/api.rs @@ -577,7 +577,7 @@ async fn init_monero_wallet( Ok((monero_wallet, monero_wallet_rpc_process)) } -mod data { +pub mod data { use super::*; pub fn data_dir_from(arg_dir: Option, testnet: bool) -> Result { diff --git a/swap/src/cli/api/request.rs b/swap/src/cli/api/request.rs index 5e913fc32..f45cd7650 100644 --- a/swap/src/cli/api/request.rs +++ b/swap/src/cli/api/request.rs @@ -1308,6 +1308,12 @@ pub struct CheckMoneroNodeResponse { pub available: bool, } +#[typeshare] +#[derive(Deserialize, Serialize)] +pub struct GetDataDirArgs { + pub is_testnet: bool, +} + #[derive(Error, Debug)] #[error("this is not one of the known monero networks")] struct UnknownMoneroNetwork(String);