decode: fallback to relaying current clipboard to stdout on failure

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I6a6a696451def3e367afa9e8b0dd6ae626906e53
This commit is contained in:
raf 2025-08-13 17:19:13 +03:00
commit 64c923480e
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
3 changed files with 56 additions and 9 deletions

View file

@ -3,6 +3,7 @@ use crate::db::{ClipboardDb, SqliteClipboardDb};
use std::io::{Read, Write}; use std::io::{Read, Write};
use crate::db::StashError; use crate::db::StashError;
use wl_clipboard_rs::paste::{ClipboardType, MimeType, Seat, get_contents};
pub trait DecodeCommand { pub trait DecodeCommand {
fn decode( fn decode(
@ -16,12 +17,59 @@ pub trait DecodeCommand {
impl DecodeCommand for SqliteClipboardDb { impl DecodeCommand for SqliteClipboardDb {
fn decode( fn decode(
&self, &self,
in_: impl Read, mut in_: impl Read,
out: impl Write, mut out: impl Write,
input: Option<String>, input: Option<String>,
) -> Result<(), StashError> { ) -> Result<(), StashError> {
self.decode_entry(in_, out, input)?; let input_str = if let Some(s) = input {
log::info!("Entry decoded"); s
} else {
let mut buf = String::new();
if let Err(e) = in_.read_to_string(&mut buf) {
log::error!("Failed to read stdin for decode: {e}");
}
buf
};
// If input is empty or whitespace, treat as error and trigger fallback
if input_str.trim().is_empty() {
log::info!("No input provided to decode; relaying clipboard to stdout");
if let Ok((mut reader, _mime)) =
get_contents(ClipboardType::Regular, Seat::Unspecified, MimeType::Any)
{
let mut buf = Vec::new();
if let Err(err) = reader.read_to_end(&mut buf) {
log::error!("Failed to read clipboard for relay: {err}");
} else {
let _ = out.write_all(&buf);
}
} else {
log::error!("Failed to get clipboard contents for relay");
}
return Ok(());
}
// Try decode as usual
match self.decode_entry(input_str.as_bytes(), &mut out, Some(input_str.clone())) {
Ok(()) => {
log::info!("Entry decoded");
}
Err(e) => {
log::error!("Failed to decode entry: {e}");
if let Ok((mut reader, _mime)) =
get_contents(ClipboardType::Regular, Seat::Unspecified, MimeType::Any)
{
let mut buf = Vec::new();
if let Err(err) = reader.read_to_end(&mut buf) {
log::error!("Failed to read clipboard for relay: {err}");
} else {
let _ = out.write_all(&buf);
}
} else {
log::error!("Failed to get clipboard contents for relay");
}
}
}
Ok(()) Ok(())
} }
} }

View file

@ -145,8 +145,7 @@ impl SqliteClipboardDb {
})); }));
} }
Ok(serde_json::to_string_pretty(&entries) serde_json::to_string_pretty(&entries).map_err(|e| StashError::ListDecode(e.to_string()))
.map_err(|e| StashError::ListDecode(e.to_string()))?)
} }
} }

View file

@ -148,15 +148,15 @@ fn main() {
// Implement JSON output // Implement JSON output
match db.list_json() { match db.list_json() {
Ok(json) => { Ok(json) => {
println!("{}", json); println!("{json}");
} }
Err(e) => { Err(e) => {
log::error!("Failed to list entries as JSON: {}", e); log::error!("Failed to list entries as JSON: {e}");
} }
} }
} }
_ => { _ => {
log::error!("Unsupported format: {}", format); log::error!("Unsupported format: {format}");
} }
} }
} }