diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 1e727c9b..c203bdf8 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -38,7 +38,7 @@ color-eyre = { workspace = true } number_prefix = { workspace = true } ctrlc = { workspace = true } qr2term = { workspace = true } -arboard = { workspace = true, features = [ +arboard = { optional = true, workspace = true, features = [ "wayland-data-control", ] } # Wayland by default, fallback to X11. tracing = { workspace = true, features = ["log", "log-always"] } @@ -48,6 +48,7 @@ tracing-subscriber = { workspace = true, features = ["env-filter"] } trycmd = { workspace = true } [features] +clipboard = ["dep:arboard"] # TLS implementations for websocket connections via async-tungstenite # required for optional wss connection to the mailbox server tls = ["magic-wormhole/tls"] @@ -56,5 +57,5 @@ native-tls = ["magic-wormhole/native-tls"] experimental-transfer-v2 = ["magic-wormhole/experimental-transfer-v2"] experimental = ["experimental-transfer-v2"] -default = ["magic-wormhole/default", "magic-wormhole/forwarding"] +default = ["clipboard", "magic-wormhole/default", "magic-wormhole/forwarding"] all = ["default", "magic-wormhole/native-tls"] diff --git a/cli/src/main.rs b/cli/src/main.rs index a79de164..35284632 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -6,7 +6,6 @@ use std::{ time::{Duration, Instant}, }; -use arboard::Clipboard; use async_std::sync::Arc; use clap::{Args, CommandFactory, Parser, Subcommand}; use color_eyre::{eyre, eyre::Context}; @@ -21,6 +20,9 @@ use magic_wormhole::{ use std::{io::Write, path::PathBuf}; use tracing_subscriber::EnvFilter; +#[cfg(feature = "clipboard")] +use arboard::Clipboard; + fn install_ctrlc_handler( ) -> eyre::Result futures::future::BoxFuture<'static, ()> + Clone> { use async_std::sync::{Condvar, Mutex}; @@ -282,12 +284,6 @@ async fn main() -> eyre::Result<()> { .init(); }; - let mut clipboard = Clipboard::new() - .map_err(|err| { - tracing::warn!("Failed to initialize clipboard support: {}", err); - }) - .ok(); - match app.command { WormholeCommand::Send { common, @@ -307,7 +303,6 @@ async fn main() -> eyre::Result<()> { true, transfer::APP_CONFIG, Some(&sender_print_code), - clipboard.as_mut(), )), ctrl_c(), ) @@ -345,7 +340,6 @@ async fn main() -> eyre::Result<()> { true, transfer::APP_CONFIG, Some(&sender_print_code), - clipboard.as_mut(), )); match futures::future::select(connect_fut, ctrl_c()).await { Either::Left((result, _)) => result?, @@ -385,7 +379,6 @@ async fn main() -> eyre::Result<()> { false, transfer::APP_CONFIG, None, - clipboard.as_mut(), )); match futures::future::select(connect_fut, ctrl_c()).await { Either::Left((result, _)) => result?, @@ -459,7 +452,6 @@ async fn main() -> eyre::Result<()> { true, app_config, Some(&server_print_code), - clipboard.as_mut(), )); let (wormhole, _code, relay_hints) = match futures::future::select(connect_fut, ctrl_c()).await { @@ -487,17 +479,8 @@ async fn main() -> eyre::Result<()> { tracing::warn!("This is an unstable feature. Make sure that your peer is running the exact same version of the program as you. Also, please report all bugs and crashes."); let mut app_config = forwarding::APP_CONFIG; app_config.app_version.transit_abilities = parse_transit_args(&common); - let (wormhole, _code, relay_hints) = parse_and_connect( - &mut term, - common, - code, - None, - false, - app_config, - None, - clipboard.as_mut(), - ) - .await?; + let (wormhole, _code, relay_hints) = + parse_and_connect(&mut term, common, code, None, false, app_config, None).await?; let offer = forwarding::connect( wormhole, @@ -581,7 +564,6 @@ async fn parse_and_connect( is_send: bool, mut app_config: magic_wormhole::AppConfig, print_code: Option<&PrintCodeFn>, - clipboard: Option<&mut Clipboard>, ) -> eyre::Result<(Wormhole, magic_wormhole::Code, Vec)> { // TODO handle relay servers with multiple endpoints better let mut relay_hints: Vec = common_args @@ -663,10 +645,19 @@ async fn parse_and_connect( /* Print code and also copy it to clipboard */ if is_send { - if let Some(clipboard) = clipboard { - match clipboard.set_text(mailbox_connection.code().to_string()) { - Ok(()) => tracing::info!("Code copied to clipboard"), - Err(err) => tracing::warn!("Failed to copy code to clipboard: {}", err), + #[cfg(feature = "clipboard")] + { + let clipboard = Clipboard::new() + .map_err(|err| { + tracing::warn!("Failed to initialize clipboard support: {}", err); + }) + .ok(); + + if let Some(mut clipboard) = clipboard { + match clipboard.set_text(mailbox_connection.code().to_string()) { + Ok(()) => tracing::info!("Code copied to clipboard"), + Err(err) => tracing::warn!("Failed to copy code to clipboard: {}", err), + } } } @@ -787,11 +778,17 @@ fn sender_print_code( is_leader: false, } .to_string(); - writeln!( - term, - "\nThis wormhole's code is: {} (it has been copied to your clipboard)", - style(&code).bold() - )?; + + if cfg!(feature = "clipboard") { + writeln!( + term, + "\nThis wormhole's code is: {} (it has been copied to your clipboard)", + style(&code).bold() + )?; + } else { + writeln!(term, "\nThis wormhole's code is: {}", style(&code).bold())?; + } + writeln!(term, "This is equivalent to the following link: \u{001B}]8;;{}\u{001B}\\{}\u{001B}]8;;\u{001B}\\", &uri, &uri)?; let qr = qr2term::generate_qr_string(&uri).context("Failed to generate QR code for send link")?; @@ -816,7 +813,16 @@ fn server_print_code( code: &magic_wormhole::Code, _: &Option, ) -> eyre::Result<()> { - writeln!(term, "\nThis wormhole's code is: {}", style(&code).bold())?; + if cfg!(feature = "clipboard") { + writeln!( + term, + "\nThis wormhole's code is: {} (it has been copied to your clipboard)", + style(&code).bold() + )?; + } else { + writeln!(term, "\nThis wormhole's code is: {}", style(&code).bold())?; + } + writeln!( term, "On the other side, enter that code into a Magic Wormhole client\n"