Implement clipboard and QR presentation

This commit is contained in:
Hermes Agent
2026-08-10 00:49:42 +00:00
parent b685a4864c
commit b8c614e141
17 changed files with 1368 additions and 18 deletions

View File

@@ -0,0 +1,85 @@
//! Safe native clipboard adapter selection.
//!
//! Desktop adapters are supplied by `arboard`, which owns the operating-system
//! integration. IronStorage performs no direct FFI and contains no unsafe code.
use super::{ClipboardBackend, ClipboardContent, ClipboardError};
use crate::repository::SecretBytes;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
pub struct NativeClipboardBackend {
clipboard: arboard::Clipboard,
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
impl NativeClipboardBackend {
pub fn new() -> Result<Self, ClipboardError> {
arboard::Clipboard::new()
.map(|clipboard| Self { clipboard })
.map_err(|_| ClipboardError::Unavailable)
}
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
impl ClipboardBackend for NativeClipboardBackend {
fn read(&mut self) -> Result<ClipboardContent, ClipboardError> {
match self.clipboard.get_text() {
Ok(value) => Ok(ClipboardContent::text(value.into_bytes())),
Err(arboard::Error::ContentNotAvailable) => Ok(ClipboardContent::EmptyOrNonText),
Err(arboard::Error::ClipboardNotSupported) => Err(ClipboardError::Unavailable),
Err(_) => Err(ClipboardError::ReadFailed),
}
}
fn write(&mut self, value: &SecretBytes) -> Result<(), ClipboardError> {
let text = std::str::from_utf8(value.expose()).map_err(|_| ClipboardError::NonUtf8)?;
set_text(&mut self.clipboard, text).map_err(|error| match error {
arboard::Error::ClipboardNotSupported => ClipboardError::Unavailable,
_ => ClipboardError::WriteFailed,
})
}
fn clear(&mut self) -> Result<(), ClipboardError> {
self.clipboard.clear().map_err(|error| match error {
arboard::Error::ClipboardNotSupported => ClipboardError::Unavailable,
_ => ClipboardError::WriteFailed,
})
}
}
#[cfg(target_os = "linux")]
fn set_text(clipboard: &mut arboard::Clipboard, text: &str) -> Result<(), arboard::Error> {
use arboard::SetExtLinux as _;
clipboard.set().exclude_from_history().text(text)
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
fn set_text(clipboard: &mut arboard::Clipboard, text: &str) -> Result<(), arboard::Error> {
clipboard.set_text(text)
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
pub struct NativeClipboardBackend;
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
impl NativeClipboardBackend {
pub fn new() -> Result<Self, ClipboardError> {
Err(ClipboardError::Unavailable)
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
impl ClipboardBackend for NativeClipboardBackend {
fn read(&mut self) -> Result<ClipboardContent, ClipboardError> {
Err(ClipboardError::Unavailable)
}
fn write(&mut self, _value: &SecretBytes) -> Result<(), ClipboardError> {
Err(ClipboardError::Unavailable)
}
fn clear(&mut self) -> Result<(), ClipboardError> {
Err(ClipboardError::Unavailable)
}
}