Commit 36a8e47c authored by Daniel García Moreno's avatar Daniel García Moreno

Fix attach file with the current message queue flow

I've moved the image/attach message creation from the backend to the
frontend so now we need to create the message with the file path in the
url field to attach a file. This simplifies the backend and allow us
more control over the temp message that we're showing because we can
render the temp message with the image
parent 5c0316cb
Pipeline #15033 passed with stage
in 12 minutes and 53 seconds
......@@ -137,6 +137,8 @@ row.msg-mention {
row.msg-tmp {
color: alpha(@theme_fg_color, 0.4);
background-color: #eee;
border-radius: 3px;
}
row.msg-emote {
......
......@@ -25,6 +25,7 @@ pub enum InternalCommand {
RemoveInv(String),
AppendTmpMessages,
ForceDequeueMessage,
AttachMessage(String),
#[allow(dead_code)]
SendSticker(Sticker),
#[allow(dead_code)]
......@@ -71,6 +72,9 @@ pub fn appop_loop(rx: Receiver<InternalCommand>) {
Ok(InternalCommand::ForceDequeueMessage) => {
APPOP!(force_dequeue_message);
}
Ok(InternalCommand::AttachMessage(file)) => {
APPOP!(attach_message, (file));
}
Ok(InternalCommand::SendSticker(sticker)) => {
APPOP!(send_sticker, (sticker));
}
......
......@@ -180,7 +180,7 @@ pub fn backend_loop(rx: Receiver<BKResponse>) {
.expect("failed to execute process");
}
Ok(BKResponse::AttachedFile(msg)) => {
APPOP!(add_tmp_room_message, (msg));
APPOP!(attached_file, (msg));
}
Ok(BKResponse::SearchEnd) => {
APPOP!(search_end);
......@@ -242,6 +242,10 @@ pub fn backend_loop(rx: Receiver<BKResponse>) {
APPOP!(show_error, (error));
APPOP!(set_state, (st));
},
Ok(BKResponse::AttachFileError(err)) => {
println!("ERROR attaching {:?}: retrying send", err);
APPOP!(retry_send);
}
Ok(BKResponse::SendMsgError(err)) => {
match err {
Error::SendMsgError(txid) => {
......
extern crate glib;
extern crate gdk;
extern crate gdk_pixbuf;
extern crate gtk;
extern crate gettextrs;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
use failure::Error;
use failure::err_msg;
use self::gtk::prelude::*;
use self::gettextrs::gettext;
use appop::AppOp;
use backend::BKCommand;
use app::InternalCommand;
use self::gdk_pixbuf::Pixbuf;
use self::gdk_pixbuf::PixbufExt;
......@@ -75,11 +83,10 @@ impl AppOp {
closebtn.connect_clicked(clone!(dialog => move |_| {
dialog.destroy();
}));
let room = self.active_room.clone().unwrap_or_default();
let bk = self.backend.clone();
let internal = self.internal.clone();
okbtn.connect_clicked(clone!(pixb, dialog => move |_| {
if let Ok(data) = get_pixbuf_data(&pixb) {
bk.send(BKCommand::AttachImage(room.clone(), data)).unwrap();
if let Ok(file) = store_pixbuf(&pixb) {
internal.send(InternalCommand::AttachMessage(file)).unwrap();
}
dialog.destroy();
}));
......@@ -89,3 +96,15 @@ impl AppOp {
}
}
}
fn store_pixbuf(pixb: &Pixbuf) -> Result<String, Error> {
let data = get_pixbuf_data(pixb)?;
let mut path = glib::get_tmp_dir().unwrap_or(PathBuf::from("/tmp"));
path.push("fractal-pasted-image");
let file = path.into_os_string().into_string().map_err(|_| err_msg("bad string"))?;
let mut f = File::create(file.clone())?;
f.write_all(&data)?;
f.sync_data()?;
Ok(file)
}
......@@ -2,6 +2,9 @@ extern crate gtk;
extern crate comrak;
extern crate chrono;
extern crate gettextrs;
extern crate tree_magic;
use std::path::Path;
use self::gtk::prelude::*;
use self::chrono::prelude::*;
......@@ -279,7 +282,14 @@ impl AppOp {
self.sending_message = true;
if let Some(next) = self.msg_queue.last() {
let msg = next.msg.clone();
self.backend.send(BKCommand::SendMsg(msg)).unwrap();
match &next.msg.mtype[..] {
"m.image" | "m.file" => {
self.backend.send(BKCommand::AttachFile(msg)).unwrap();
}
_ => {
self.backend.send(BKCommand::SendMsg(msg)).unwrap();
}
}
} else {
self.sending_message = false;
}
......@@ -343,6 +353,56 @@ impl AppOp {
self.dequeue_message();
}
pub fn attach_message(&mut self, file: String) -> Message {
/* reenable autoscroll to jump to new message in history */
self.autoscroll = true;
let now = Local::now();
let room = self.active_room.clone();
let f = file.clone();
let p: &Path = Path::new(&f);
let mime = tree_magic::from_filepath(p);
let mtype = match mime.as_ref() {
"image/gif" => "m.image",
"image/png" => "m.image",
"image/jpeg" => "m.image",
"image/jpg" => "m.image",
_ => "m.file"
};
let body = strn!(file.split("/").last().unwrap_or(&file));
let mut m = Message {
sender: self.uid.clone().unwrap_or_default(),
mtype: mtype.to_string(),
body: body,
room: room.unwrap_or_default(),
date: now,
thumb: None,
url: Some(file),
id: None,
formatted_body: None,
format: None,
};
m.id = Some(m.get_txn_id());
self.add_tmp_room_message(m.clone());
self.dequeue_message();
m
}
/// This method is called when a tmp message with an attach is sent correctly
/// to the matrix media server and we've the real url to use so we can
/// replace the tmp message with the same id with this new one
pub fn attached_file(&mut self, msg: Message) {
let p = self.msg_queue.iter().position(|m| m.msg == msg);
if let Some(i) = p {
let w = self.msg_queue.remove(i);
w.widget.map(|w| w.destroy());
}
self.add_tmp_room_message(msg);
}
pub fn attach_file(&mut self) {
let window: gtk::ApplicationWindow = self.ui.builder
.get_object("main_window")
......@@ -354,24 +414,22 @@ impl AppOp {
let btn = dialog.add_button(gettext("Select").as_str(), 1);
btn.get_style_context().unwrap().add_class("suggested-action");
let backend = self.backend.clone();
let room = self.active_room.clone().unwrap_or_default();
let internal = self.internal.clone();
dialog.connect_response(move |dialog, resp| {
if resp == 1 {
if let Some(fname) = dialog.get_filename() {
let f = strn!(fname.to_str().unwrap_or(""));
backend.send(BKCommand::AttachFile(room.clone(), f)).unwrap();
internal.send(InternalCommand::AttachMessage(f)).unwrap();
}
}
dialog.destroy();
});
let backend = self.backend.clone();
let room = self.active_room.clone().unwrap_or_default();
let internal = self.internal.clone();
dialog.connect_file_activated(move |dialog| {
if let Some(fname) = dialog.get_filename() {
let f = strn!(fname.to_str().unwrap_or(""));
backend.send(BKCommand::AttachFile(room.clone(), f)).unwrap();
internal.send(InternalCommand::AttachMessage(f)).unwrap();
}
dialog.destroy();
});
......
......@@ -266,7 +266,11 @@ impl<'a> MessageBox<'a> {
let url = msg.url.clone().unwrap_or_default();
let backend = self.op.backend.clone();
let image = widgets::image::Image::new(&backend, &msg.thumb.clone().unwrap_or_default(),
let img_path = match msg.thumb {
Some(ref m) => m.clone(),
None => msg.url.clone().unwrap_or_default(),
};
let image = widgets::image::Image::new(&backend, &img_path,
(600, 400), widgets::image::Thumb(false),
widgets::image::Circle(false), widgets::image::Fixed(false));
......
......@@ -269,12 +269,8 @@ impl Backend {
let r = room::set_room_avatar(self, roomid, fname);
bkerror!(r, tx, BKResponse::SetRoomAvatarError);
}
Ok(BKCommand::AttachFile(roomid, fname)) => {
let r = room::attach_file(self, roomid, fname);
bkerror!(r, tx, BKResponse::AttachFileError);
}
Ok(BKCommand::AttachImage(roomid, image)) => {
let r = room::attach_image(self, roomid, image);
Ok(BKCommand::AttachFile(msg)) => {
let r = room::attach_file(self, msg);
bkerror!(r, tx, BKResponse::AttachFileError);
}
Ok(BKCommand::NewRoom(name, privacy, internalid)) => {
......
extern crate serde_json;
extern crate tree_magic;
extern crate chrono;
extern crate url;
extern crate urlencoding;
use self::chrono::prelude::*;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::sync::mpsc::Sender;
use self::url::Url;
......@@ -346,52 +342,23 @@ pub fn set_room_avatar(bk: &Backend, roomid: String, avatar: String) -> Result<(
Ok(())
}
pub fn attach_image(bk: &Backend, roomid: String, image: Vec<u8>) -> Result<(), Error> {
attach_send(bk, roomid, strn!("Screenshot"), image, "m.image")
}
pub fn attach_file(bk: &Backend, msg: Message) -> Result<(), Error> {
let fname = msg.url.clone().unwrap_or_default();
if fname.starts_with("mxc://") {
return send_msg(bk, msg);
}
pub fn attach_file(bk: &Backend, roomid: String, path: String) -> Result<(), Error> {
let mut file = File::open(&path)?;
let mut file = File::open(&fname)?;
let mut contents: Vec<u8> = vec![];
file.read_to_end(&mut contents)?;
let p: &Path = Path::new(&path);
let mime = tree_magic::from_filepath(p);
let mtype = match mime.as_ref() {
"image/gif" => "m.image",
"image/png" => "m.image",
"image/jpeg" => "m.image",
"image/jpg" => "m.image",
_ => "m.file"
};
let body = strn!(path.split("/").last().unwrap_or(&path));
attach_send(bk, roomid, body, contents, mtype)
}
pub fn attach_send(bk: &Backend, roomid: String, body: String, contents: Vec<u8>, mtype: &str) -> Result<(), Error> {
let baseu = bk.get_base_url()?;
let tk = bk.data.lock().unwrap().access_token.clone();
let params = vec![("access_token", tk.clone())];
let mediaurl = media_url!(&baseu, "upload", params)?;
let now = Local::now();
let userid = bk.data.lock().unwrap().user_id.clone();
let mut m = Message {
sender: userid,
mtype: strn!(mtype),
body: body,
room: roomid.clone(),
date: now,
thumb: None,
url: None,
id: None,
formatted_body: None,
format: None,
};
let mut m = msg.clone();
let tx = bk.tx.clone();
let itx = bk.internal_tx.clone();
thread::spawn(
......@@ -402,7 +369,7 @@ pub fn attach_send(bk: &Backend, roomid: String, body: String, contents: Vec<u8>
}
Ok(js) => {
let uri = js["content_uri"].as_str().unwrap_or("");
m.url = Some(strn!(uri));
m.url = Some(uri.to_string());
if let Some(t) = itx {
t.send(BKCommand::SendMsg(m.clone())).unwrap();
}
......
......@@ -59,8 +59,7 @@ pub enum BKCommand {
SetRoomName(String, String),
SetRoomTopic(String, String),
SetRoomAvatar(String, String),
AttachFile(String, String),
AttachImage(String, Vec<u8>),
AttachFile(Message),
Search(String, Option<String>),
NewRoom(String, RoomType, String),
DirectChat(Member, String),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment