Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ tempfile = "3"
insta = "1.46.3"

[features]
default = ["postgres", "libsql", "html-to-markdown"]
default = ["postgres", "libsql", "html-to-markdown", "tui"]
Comment thread
henrypark133 marked this conversation as resolved.
postgres = [
"dep:deadpool-postgres",
"dep:tokio-postgres",
Expand Down
9 changes: 5 additions & 4 deletions crates/ironclaw_tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ license = "MIT OR Apache-2.0"
homepage = "https://github.com/nearai/ironclaw"
repository = "https://github.com/nearai/ironclaw"

[package.metadata.dist]
dist = false
[features]
default = ["clipboard"]
clipboard = ["dep:arboard", "dep:image"]

[dependencies]
ratatui = { version = "0.29", features = ["crossterm"] }
Expand All @@ -23,8 +24,8 @@ unicode-width = "0.2"
pulldown-cmark = { version = "0.12", default-features = false }
thiserror = "2"
tracing = "0.1"
arboard = "3"
image = { version = "0.25", default-features = false, features = ["png"] }
arboard = { version = "3", optional = true }
image = { version = "0.25", default-features = false, features = ["png"], optional = true }

[dev-dependencies]
tokio = { version = "1", features = ["full"] }
18 changes: 17 additions & 1 deletion crates/ironclaw_tui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1660,12 +1660,18 @@ fn copy_text_to_clipboard(text: &str) -> bool {
true
}

#[cfg(not(test))]
#[cfg(all(not(test), feature = "clipboard"))]
{
arboard::Clipboard::new()
.and_then(|mut clipboard| clipboard.set_text(text.to_string()))
.is_ok()
}

#[cfg(all(not(test), not(feature = "clipboard")))]
{
let _ = text;
false
}
}

async fn handle_mouse_click(
Expand Down Expand Up @@ -2442,6 +2448,7 @@ fn capture_screen_snapshot(frame: &mut ratatui::Frame<'_>, state: &mut AppState)
/// Try to read an image from the system clipboard and return it as a PNG-encoded
/// [`TuiAttachment`]. Returns `None` if the clipboard has no image data or if
/// encoding fails.
#[cfg(feature = "clipboard")]
fn try_paste_clipboard_image(state: &AppState) -> Option<TuiAttachment> {
let mut clipboard = arboard::Clipboard::new().ok()?;
let img_data = clipboard.get_image().ok()?;
Expand All @@ -2460,8 +2467,14 @@ fn try_paste_clipboard_image(state: &AppState) -> Option<TuiAttachment> {
})
}

#[cfg(not(feature = "clipboard"))]
fn try_paste_clipboard_image(_state: &AppState) -> Option<TuiAttachment> {
None
}

/// Encode raw RGBA pixel data to PNG. Returns `None` on invalid dimensions or
/// encoding failure.
#[cfg(feature = "clipboard")]
fn encode_rgba_to_png(rgba: &[u8], width: u32, height: u32) -> Option<Vec<u8>> {
let expected_len = (width as usize)
.checked_mul(height as usize)?
Expand Down Expand Up @@ -2526,6 +2539,7 @@ mod tests {
}
}

#[cfg(feature = "clipboard")]
#[test]
fn encode_rgba_to_png_valid() {
// 2x2 red image
Expand All @@ -2540,6 +2554,7 @@ mod tests {
assert_eq!(&bytes[..4], &[0x89, b'P', b'N', b'G']);
}

#[cfg(feature = "clipboard")]
#[test]
fn encode_rgba_to_png_bad_dimensions() {
let rgba = vec![0u8; 16]; // 4 pixels
Expand All @@ -2548,6 +2563,7 @@ mod tests {
assert!(png.is_none());
}

#[cfg(feature = "clipboard")]
#[test]
fn encode_rgba_to_png_zero_size() {
// 0x0 image: the image crate rejects zero-dimension buffers
Expand Down
Loading