Skip to content

Commit

Permalink
Support uploading image attachments from clipboard (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjajaja authored and ulyssa committed May 20, 2023
1 parent ad8b4a6 commit 2899d4f
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 1 deletion.
149 changes: 148 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ categories = ["command-line-utilities"]
rust-version = "1.66"

[dependencies]
arboard = "3.2.0"
bitflags = "1.3.2"
chrono = "0.4"
clap = {version = "4.0", features = ["derive"]}
Expand All @@ -23,6 +24,7 @@ dirs = "4.0.0"
emojis = "~0.5.2"
gethostname = "0.4.1"
html5ever = "0.26.0"
image = "0.24.5"
markup5ever_rcdom = "0.2.0"
mime = "^0.3.16"
mime_guess = "^2.0.4"
Expand Down
7 changes: 7 additions & 0 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ pub enum RoomAction {
pub enum SendAction {
Submit,
Upload(String),
UploadImage(usize, usize, Cow<'static, [u8]>),
}

#[derive(Clone, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -360,6 +361,12 @@ pub enum IambError {

#[error("Verification request error: {0}")]
VerificationRequestError(#[from] matrix_sdk::encryption::identities::RequestVerificationError),

#[error("Image error: {0}")]
Image(#[from] image::ImageError),

#[error("Could not use system clipboard data")]
Clipboard,
}

impl From<IambError> for UIError<IambInfo> {
Expand Down
40 changes: 40 additions & 0 deletions src/windows/room/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::fs;
use std::ops::Deref;
use std::path::{Path, PathBuf};

use modalkit::editing::store::RegisterError;
use tokio;

use matrix_sdk::{
Expand Down Expand Up @@ -471,6 +472,36 @@ impl ChatState {
let msg = MessageType::Text(msg);
let msg = RoomMessageEventContent::new(msg);

(resp.event_id, msg)
},
SendAction::UploadImage(width, height, bytes) => {
// Convert to png because arboard does not give us the mime type.
let bytes =
image::ImageBuffer::from_raw(width as _, height as _, bytes.into_owned())
.ok_or(IambError::Clipboard)
.and_then(|imagebuf| {
let dynimage = image::DynamicImage::ImageRgba8(imagebuf);
let bytes = Vec::<u8>::new();
let mut buff = std::io::Cursor::new(bytes);
dynimage.write_to(&mut buff, image::ImageOutputFormat::Png)?;
Ok(buff.into_inner())
})
.map_err(IambError::from)?;
let mime = mime::IMAGE_PNG;

let name = Cow::from(format!("Clipboard.png"));
let config = AttachmentConfig::new();

let resp = room
.send_attachment(name.as_ref(), &mime, bytes.as_ref(), config)
.await
.map_err(IambError::from)?;

// Mock up the local echo message for the scrollback.
let msg = TextMessageEventContent::plain(format!("[Attached File: {name}]"));
let msg = MessageType::Text(msg);
let msg = RoomMessageEventContent::new(msg);

(resp.event_id, msg)
},
};
Expand Down Expand Up @@ -617,6 +648,15 @@ impl Editable<ProgramContext, ProgramStore, IambInfo> for ChatState {
// Run command again.
delegate!(self, w => w.editor_command(act, ctx, store))
},
Err(EditError::Register(RegisterError::ClipboardImage(data))) => {
let msg = "Do you really want to upload the image from your system clipboard?";
let send =
IambAction::Send(SendAction::UploadImage(data.width, data.height, data.bytes));
let prompt = PromptYesNo::new(msg, vec![Action::from(send)]);
let prompt = Box::new(prompt);

Err(EditError::NeedConfirm(prompt))
},
res @ Err(_) => res,
}
}
Expand Down

0 comments on commit 2899d4f

Please sign in to comment.