From 4433343a2e2f14357e02af7ea1c0efec06bb886c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Moreno?= Date: Wed, 23 Aug 2017 11:17:55 +0200 Subject: [PATCH] Added date to messages --- Cargo.toml | 2 + src/app.rs | 150 ++++++++++++++++++++++++++++++++++++------------- src/backend.rs | 33 +++++++---- 3 files changed, 133 insertions(+), 52 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3e63467f..9f260a49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ authors = ["Daniel Garcia "] name = "guillotine" version = "0.1.0" [dependencies] +chrono = "0.4.0" gdk-pixbuf = "0.2.0" gio = "0.2.0" regex = "0.2.2" @@ -11,6 +12,7 @@ secret-service = "0.4.0" serde = "1.0.11" serde_derive = "1.0.11" serde_json = "1.0.2" +time = "0.1.38" url = "1.5.1" xdg = "2.1.0" diff --git a/src/app.rs b/src/app.rs index 2ace04b5..2b0c524f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,7 @@ extern crate gtk; extern crate gio; extern crate gdk_pixbuf; +extern crate chrono; extern crate secret_service; use self::secret_service::SecretService; @@ -16,6 +17,8 @@ use self::gio::ApplicationExt; use self::gdk_pixbuf::Pixbuf; use self::gtk::prelude::*; +use self::chrono::prelude::*; + use backend::Backend; use backend; @@ -287,29 +290,11 @@ impl AppOp { } } - pub fn add_room_message(&self, msg: backend::Message) { - let messages = self.gtk_builder - .get_object::("message_list") - .expect("Can't find message_list in ui file."); - - let body = msg.b; - let sender = msg.s; - - let mut msg = gtk::Box::new(gtk::Orientation::Horizontal, 5); - - let mut vert = gtk::Box::new(gtk::Orientation::Vertical, 0); - let mut label = gtk::Label::new(&body[..]); - label.set_line_wrap(true); - label.set_justify(gtk::Justification::Left); - label.set_halign(gtk::Align::Start); - label.set_alignment(0 as f32, 0 as f32); - - let mut fname = sender.clone(); - let mut avatar_url = String::new(); - if let Some(m) = self.members.get(&sender) { - fname = m.get_alias(); - avatar_url = m.avatar.clone(); - } + fn build_room_msg_avatar(&self, sender: &str) -> gtk::Image { + let avatar_url = match self.members.get(sender) { + Some(m) => m.avatar.clone(), + None => String::new() + }; let avatar = gtk::Image::new_from_icon_name("image-missing", 5); @@ -319,32 +304,117 @@ impl AppOp { let (tx, rx): (Sender, Receiver) = channel(); self.backend.get_media_async(avatar_url, tx).unwrap(); gtk::timeout_add(50, move || { - let recv = rx.try_recv(); - - if recv.is_err() { - return gtk::Continue(true); - } - - let fname = recv.unwrap(); - if let Ok(pixbuf) = Pixbuf::new_from_file_at_size(&fname, 32, 32) { - a.set_from_pixbuf(&pixbuf); + match rx.try_recv() { + Err(_) => gtk::Continue(true), + Ok(fname) => { + if let Ok(pixbuf) = Pixbuf::new_from_file_at_size(&fname, 32, 32) { + a.set_from_pixbuf(&pixbuf); + } + gtk::Continue(false) + } } - - gtk::Continue(false) }); } + avatar + } + + fn build_room_msg_username(&self, sender: &str) -> gtk::Label { + let uname = match self.members.get(sender) { + Some(m) => m.get_alias(), + None => String::from(sender) + }; + let mut username = gtk::Label::new(""); - username.set_markup(&format!("{}", fname)); + username.set_markup(&format!("{}", uname)); username.set_justify(gtk::Justification::Left); username.set_halign(gtk::Align::Start); - vert.pack_start(&username, false, false, 0); - vert.pack_start(&label, true, true, 0); + username + } + + fn build_room_msg_body(&self, body: &str) -> gtk::Label { + let mut msg = gtk::Label::new(body); + msg.set_line_wrap(true); + msg.set_justify(gtk::Justification::Left); + msg.set_halign(gtk::Align::Start); + msg.set_alignment(0 as f32, 0 as f32); + + msg + } + + fn build_room_msg_date(&self, dt: &DateTime) -> gtk::Label { + let d = dt.format("%d/%b/%y %H:%M").to_string(); + + let mut date = gtk::Label::new(""); + date.set_markup(&format!("{}", d)); + date.set_line_wrap(true); + date.set_justify(gtk::Justification::Right); + date.set_halign(gtk::Align::End); + date.set_alignment(1 as f32, 0 as f32); + + date + } + + fn build_room_msg_info(&self, msg: &backend::Message) -> gtk::Box { + // info + // +----------+------+ + // | username | date | + // +----------+------+ + let mut info = gtk::Box::new(gtk::Orientation::Horizontal, 0); + + let username = self.build_room_msg_username(&msg.sender); + let date = self.build_room_msg_date(&msg.date); + + info.pack_start(&username, true, true, 0); + info.pack_start(&date, false, false, 0); + + info + } + + fn build_room_msg_content(&self, msg: &backend::Message) -> gtk::Box { + // content + // +------+ + // | info | + // +------+ + // | body | + // +------+ + let mut content = gtk::Box::new(gtk::Orientation::Vertical, 0); + + let info = self.build_room_msg_info(msg); + let body = self.build_room_msg_body(&msg.body); + + content.pack_start(&info, false, false, 0); + content.pack_start(&body, true, true, 0); + + content + + } + + fn build_room_msg(&self, msg: backend::Message) -> gtk::Box { + let avatar = self.build_room_msg_avatar(&msg.sender); + + // msg + // +--------+---------+ + // | avatar | content | + // +--------+---------+ + let mut msg_widget = gtk::Box::new(gtk::Orientation::Horizontal, 5); + let content = self.build_room_msg_content(&msg); + + msg_widget.pack_start(&avatar, false, true, 5); + msg_widget.pack_start(&content, true, true, 0); + + msg_widget.show_all(); + + msg_widget + } + + pub fn add_room_message(&self, msg: backend::Message) { + let messages = self.gtk_builder + .get_object::("message_list") + .expect("Can't find message_list in ui file."); - msg.pack_start(&avatar, false, true, 5); - msg.pack_start(&vert, true, true, 0); - msg.show_all(); + let msg = self.build_room_msg(msg); messages.add(&msg); } diff --git a/src/backend.rs b/src/backend.rs index 44dc8515..142dcc8a 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -3,6 +3,8 @@ extern crate reqwest; extern crate regex; extern crate xdg; extern crate serde_json; +extern crate chrono; +extern crate time; use self::regex::Regex; @@ -19,6 +21,9 @@ use std::fs::File; use std::io::prelude::*; use std::io; +use self::chrono::prelude::*; +use self::time::Duration; + // TODO: send errors to the frontend macro_rules! get { @@ -142,14 +147,10 @@ pub enum BKResponse { #[derive(Debug)] pub struct Message { - /// the sender - pub s: String, - /// the message type - pub t: String, - /// the message body - pub b: String, - /// the message age - pub a: i64, + pub sender: String, + pub mtype: String, + pub body: String, + pub date: DateTime, } #[derive(Debug)] @@ -370,11 +371,13 @@ impl Backend { let mut ms: Vec = vec![]; for msg in r["chunk"].as_array().unwrap().iter().rev() { //println!("messages: {:#?}", msg); + let age = msg["age"].as_i64().unwrap_or(0); + let m = Message { - s: String::from(msg["sender"].as_str().unwrap()), - t: String::from(msg["content"]["msgtype"].as_str().unwrap()), - b: String::from(msg["content"]["body"].as_str().unwrap()), - a: msg["age"].as_i64().unwrap(), + sender: String::from(msg["sender"].as_str().unwrap()), + mtype: String::from(msg["content"]["msgtype"].as_str().unwrap()), + body: String::from(msg["content"]["body"].as_str().unwrap()), + date: age_to_datetime(age), }; ms.push(m); } @@ -524,3 +527,9 @@ fn dw_media(base: Url, url: &str, thumb: bool, dest: Option<&str>, w: i32, h: i3 Ok(fname) } + +fn age_to_datetime(age: i64) -> DateTime { + let now = Local::now(); + let diff = Duration::seconds(age / 1000); + now - diff +}