Browse Source

Clean MessageContent

fix-filtering
Alejandro Domínguez 5 years ago
parent
commit
60e81c4a7b
  1. 63
      fractal-gtk/src/appop/message.rs
  2. 2
      fractal-gtk/src/appop/room.rs
  3. 8
      fractal-gtk/src/model/message.rs
  4. 17
      fractal-gtk/src/ui/mod.rs
  5. 47
      fractal-gtk/src/widgets/message.rs
  6. 34
      fractal-gtk/src/widgets/room_history.rs

63
fractal-gtk/src/appop/message.rs

@ -45,7 +45,7 @@ impl AppOp {
self.mark_last_message_as_read(Force(true));
}
pub fn add_room_message(&mut self, msg: &Message) -> Option<()> {
pub fn add_room_message(&mut self, msg: Message) -> Option<()> {
let session_client = self.login_data.as_ref()?.session_client.clone();
if let Some(ui_msg) = self.create_new_room_message(msg) {
if let Some(ref mut history) = self.ui.history {
@ -55,7 +55,7 @@ impl AppOp {
None
}
pub fn remove_room_message(&mut self, msg: &Message) {
pub fn remove_room_message(&mut self, msg: Message) {
let session_client =
unwrap_or_unit_return!(self.login_data.as_ref().map(|ld| ld.session_client.clone()));
if let Some(ui_msg) = self.create_new_room_message(msg) {
@ -68,7 +68,7 @@ impl AppOp {
pub fn add_tmp_room_message(&mut self, msg: Message) -> Option<()> {
let login_data = self.login_data.clone()?;
let messages = self.ui.history.as_ref()?.get_listbox();
if let Some(ui_msg) = self.create_new_room_message(&msg) {
if let Some(ui_msg) = self.create_new_room_message(msg.clone()) {
let mb = widgets::MessageBox::tmpwidget(
login_data.session_client.clone(),
self.user_info_cache.clone(),
@ -108,7 +108,7 @@ impl AppOp {
let r = self.rooms.get(self.active_room.as_ref()?)?;
let mut widgets = vec![];
for t in self.msg_queue.iter().rev().filter(|m| m.msg.room == r.id) {
if let Some(ui_msg) = self.create_new_room_message(&t.msg) {
if let Some(ui_msg) = self.create_new_room_message(t.msg.clone()) {
let mb = widgets::MessageBox::tmpwidget(
login_data.session_client.clone(),
self.user_info_cache.clone(),
@ -365,7 +365,7 @@ impl AppOp {
let uid = login_data.uid;
for msg in msgs.iter() {
if !msg.redacted && self.active_room.as_ref().map_or(false, |x| x == &msg.room) {
self.add_room_message(&msg);
self.add_room_message(msg.clone());
msg_in_active = true;
}
@ -415,7 +415,7 @@ impl AppOp {
for item in msgs.iter().rev() {
/* create a list of new messages to load to the history */
if active_room.map_or(false, |a_room| item.room == *a_room) && !item.redacted {
if let Some(ui_msg) = self.create_new_room_message(item) {
if let Some(ui_msg) = self.create_new_room_message(item.clone()) {
list.push(ui_msg);
}
}
@ -434,7 +434,7 @@ impl AppOp {
let message = self.get_message_by_id(&room_id, &id);
if let Some(msg) = message {
self.remove_room_message(&msg);
self.remove_room_message(msg.clone());
if let Some(ref mut room) = self.rooms.get_mut(&msg.room) {
if let Some(ref mut message) = room.messages.iter_mut().find(|e| e.id == msg.id) {
message.redacted = true;
@ -445,7 +445,7 @@ impl AppOp {
}
/* parese a backend Message into a Message for the UI */
pub fn create_new_room_message(&self, msg: &Message) -> Option<MessageContent> {
pub fn create_new_room_message(&self, msg: Message) -> Option<MessageContent> {
let login_data = self.login_data.clone()?;
let mut highlights = vec![];
lazy_static! {
@ -506,48 +506,15 @@ impl AppOp {
let redactable = admin != 0 || login_data.uid == msg.sender;
let is_last_viewed = msg.receipt.contains_key(&login_data.uid);
Some(create_ui_message(
msg.clone(),
name,
t,
Some(MessageContent {
msg,
sender_name: name,
mtype: t,
highlights,
redactable,
is_last_viewed,
))
}
}
/* FIXME: don't convert msg to ui messages here, we should later get a ui message from storage */
fn create_ui_message(
msg: Message,
name: Option<String>,
t: RowType,
highlights: Vec<String>,
redactable: bool,
last_viewed: bool,
) -> MessageContent {
MessageContent {
msg: msg.clone(),
id: msg.id,
sender: msg.sender,
sender_name: name,
mtype: t,
body: msg.body,
date: msg.date,
replace_date: if msg.replace.is_some() {
Some(msg.date)
} else {
None
},
thumb: msg.thumb,
url: msg.url,
local_path: msg.local_path,
formatted_body: msg.formatted_body,
format: msg.format,
last_viewed,
highlights,
redactable,
widget: None,
last_viewed: is_last_viewed,
widget: None,
})
}
}

2
fractal-gtk/src/appop/room.rs

@ -275,7 +275,7 @@ impl AppOp {
/* create the intitial list of messages to fill the new room history */
let mut messages = vec![];
if let Some(room) = self.rooms.get(&active_room) {
for msg in room.messages.iter() {
for msg in room.messages.iter().cloned() {
/* Make sure the message is from this room and not redacted */
if msg.room == active_room && !msg.redacted {
let row = self.create_new_room_message(msg);

8
fractal-gtk/src/model/message.rs

@ -400,6 +400,14 @@ impl Message {
}
}
pub const fn replace_date(&self) -> Option<&DateTime<Local>> {
if self.replace.is_some() {
Some(&self.date)
} else {
None
}
}
/// Generates an unique transaction id for this message
/// The txn_id is generated using the md5sum of a concatenation of the message room id, the
/// message body and the date.

17
fractal-gtk/src/ui/mod.rs

@ -2,11 +2,7 @@ use crate::actions::AppState;
use crate::model::{member::Member, message::Message};
use crate::util::i18n::i18n;
use crate::widgets::{self, SVEntry};
use chrono::prelude::{DateTime, Local};
use gtk::prelude::*;
use matrix_sdk::identifiers::{EventId, UserId};
use std::path::PathBuf;
use url::Url;
pub mod about;
pub mod account;
@ -171,20 +167,9 @@ impl UI {
* To-Do: this should be moved to a file collecting all structs used in the UI */
#[derive(Debug, Clone)]
pub struct MessageContent {
pub id: Option<EventId>,
pub sender: UserId,
pub msg: Message,
pub sender_name: Option<String>,
pub mtype: RowType,
pub body: String,
pub date: DateTime<Local>,
pub replace_date: Option<DateTime<Local>>,
pub thumb: Option<Url>,
pub url: Option<Url>,
pub local_path: Option<PathBuf>,
pub formatted_body: Option<String>,
pub format: Option<String>,
/* in some places we still need the backend message type (e.g. media viewer) */
pub msg: Message,
pub highlights: Vec<String>,
pub redactable: bool,
pub last_viewed: bool,

47
fractal-gtk/src/widgets/message.rs

@ -261,7 +261,7 @@ impl MessageBox {
body_bx.pack_start(&body, true, true, 0);
if let Some(replace_date) = msg.replace_date {
if let Some(replace_date) = msg.msg.replace_date() {
let edit_mark =
gtk::Image::from_icon_name(Some("document-edit-symbolic"), gtk::IconSize::Button);
edit_mark.get_style_context().add_class("edit-mark");
@ -290,7 +290,7 @@ impl MessageBox {
fn build_room_msg_body(&self, msg: &Message) -> gtk::Box {
let bx = gtk::Box::new(gtk::Orientation::Vertical, 6);
let msgs_by_kind_of_line = msg.body.lines().group_by(|&line| kind_of_line(line));
let msgs_by_kind_of_line = msg.msg.body.lines().group_by(|&line| kind_of_line(line));
let msg_parts = msgs_by_kind_of_line.into_iter().map(|(k, group)| {
let mut v: Vec<&str> = if k == MsgPartType::Quote {
group.map(trim_start_quote).collect()
@ -360,7 +360,7 @@ impl MessageBox {
self.eventbox.upcast_ref::<gtk::Widget>()
};
let id = msg.id.clone();
let id = msg.msg.id.clone();
widget.connect_button_press_event(move |w, e| {
if e.triggers_context_menu() {
let menu = MessageMenu::new(id.as_ref(), &mtype, &redactable, Some(w));
@ -372,7 +372,7 @@ impl MessageBox {
}
});
let id = msg.id.clone();
let id = msg.msg.id.clone();
self.gesture
.connect_pressed(clone!(@weak widget => move |_, x, y| {
let menu = MessageMenu::new(id.as_ref(), &mtype, &redactable, Some(&widget));
@ -382,7 +382,7 @@ impl MessageBox {
}
fn connect_media_viewer(&self, msg: &Message) -> Option<()> {
let evid = msg.id.as_ref()?.to_string();
let evid = msg.msg.id.as_ref()?.to_string();
let data = glib::Variant::from(evid);
self.root.set_action_name(Some("app.open-media-viewer"));
self.root.set_action_target_value(Some(&data));
@ -395,7 +395,7 @@ fn build_room_msg_avatar(
user_info_cache: UserInfoCache,
msg: &Message,
) -> widgets::Avatar {
let uid = msg.sender.clone();
let uid = msg.msg.sender.clone();
let alias = msg.sender_name.clone();
let avatar = widgets::Avatar::avatar_new(Some(globals::MSG_ICON_SIZE));
avatar.set_valign(gtk::Align::Start);
@ -420,11 +420,11 @@ fn build_room_msg_avatar(
fn build_room_msg_sticker(session_client: MatrixClient, msg: &Message) -> gtk::Box {
let bx = gtk::Box::new(gtk::Orientation::Horizontal, 0);
if let Some(url) = msg.url.clone() {
if let Some(url) = msg.msg.url.clone() {
let image = widgets::image::Image::new(Either::Left(url))
.size(Some(globals::MAX_STICKER_SIZE))
.build(session_client);
image.widget.set_tooltip_text(Some(&msg.body[..]));
image.widget.set_tooltip_text(Some(&msg.msg.body[..]));
bx.add(&image.widget);
}
@ -435,7 +435,7 @@ fn build_room_msg_sticker(session_client: MatrixClient, msg: &Message) -> gtk::B
fn build_room_audio_player(session_client: MatrixClient, msg: &Message) -> gtk::Box {
let bx = gtk::Box::new(gtk::Orientation::Horizontal, 6);
if let Some(url) = msg.url.clone() {
if let Some(url) = msg.msg.url.clone() {
let player = AudioPlayerWidget::new();
let start_playing = false;
PlayerExt::initialize_stream(
@ -456,6 +456,7 @@ fn build_room_audio_player(session_client: MatrixClient, msg: &Message) -> gtk::
download_btn.set_tooltip_text(Some(i18n("Save").as_str()));
let evid = msg
.msg
.id
.as_ref()
.map(|evid| evid.to_string())
@ -466,7 +467,7 @@ fn build_room_audio_player(session_client: MatrixClient, msg: &Message) -> gtk::
bx.pack_start(&download_btn, false, false, 3);
let outer_box = gtk::Box::new(gtk::Orientation::Vertical, 6);
let file_name = gtk::Label::new(Some(&format!("<b>{}</b>", msg.body)));
let file_name = gtk::Label::new(Some(&format!("<b>{}</b>", msg.msg.body)));
file_name.set_use_markup(true);
file_name.set_xalign(0.0);
file_name.set_line_wrap(true);
@ -481,7 +482,7 @@ fn build_room_msg_file(msg: &Message) -> gtk::Box {
let bx = gtk::Box::new(gtk::Orientation::Horizontal, 12);
let btn_bx = gtk::Box::new(gtk::Orientation::Horizontal, 0);
let name = msg.body.as_str();
let name = msg.msg.body.as_str();
let name_lbl = gtk::Label::new(Some(name));
name_lbl.set_tooltip_text(Some(name));
name_lbl.set_ellipsize(pango::EllipsizeMode::End);
@ -493,6 +494,7 @@ fn build_room_msg_file(msg: &Message) -> gtk::Box {
download_btn.set_tooltip_text(Some(i18n("Save").as_str()));
let evid = msg
.msg
.id
.as_ref()
.map(|evid| evid.to_string())
@ -527,12 +529,13 @@ fn build_room_msg_image(
// If the thumbnail is not a valid URL we use the msg.url
let img = msg
.msg
.thumb
.clone()
.filter(|m| m.scheme() == "mxc" || m.scheme().starts_with("http"))
.or_else(|| msg.url.clone())
.or_else(|| msg.msg.url.clone())
.map(Either::Left)
.or_else(|| Some(Either::Right(msg.local_path.clone()?)));
.or_else(|| Some(Either::Right(msg.msg.local_path.clone()?)));
let image = if let Some(img_path) = img {
let image = widgets::image::Image::new(img_path)
@ -558,7 +561,7 @@ fn build_room_video_player(
) -> (gtk::Box, Option<Rc<VideoPlayerWidget>>) {
let bx = gtk::Box::new(gtk::Orientation::Vertical, 6);
let player = if let Some(url) = msg.url.clone() {
let player = if let Some(url) = msg.msg.url.clone() {
let with_controls = false;
let player = VideoPlayerWidget::new(with_controls);
let start_playing = false;
@ -588,6 +591,7 @@ fn build_room_video_player(
play_button.get_style_context().add_class("play-icon");
play_button.get_style_context().add_class("flat");
let evid = msg
.msg
.id
.as_ref()
.map(|evid| evid.to_string())
@ -615,7 +619,7 @@ fn build_room_video_player(
});
overlay.add_overlay(&menu_button);
let evid = msg.id.as_ref();
let evid = msg.msg.id.as_ref();
let redactable = msg.redactable;
let menu = MessageMenu::new(evid, &RowType::Video, &redactable, None);
menu_button.set_popover(Some(&menu.get_popover()));
@ -639,9 +643,9 @@ fn build_room_msg_emote(msg: &Message) -> (gtk::Box, gtk::Label) {
let sname = msg
.sender_name
.clone()
.unwrap_or_else(|| msg.sender.to_string());
.unwrap_or_else(|| msg.msg.sender.to_string());
let msg_label = gtk::Label::new(None);
let markup = markup_text(&msg.body);
let markup = markup_text(&msg.msg.body);
msg_label.set_markup(&format!("<b>{}</b> {}", sname, markup));
set_label_styles(&msg_label);
@ -750,9 +754,12 @@ impl From<&Message> for MessageBoxInfoHeader {
// +----------+------+
let root = gtk::Box::new(gtk::Orientation::Horizontal, 0);
let username =
build_room_msg_username(msg.sender_name.as_deref().unwrap_or(msg.sender.as_str()));
let date = build_room_msg_date(&msg.date);
let username = build_room_msg_username(
msg.sender_name
.as_deref()
.unwrap_or(msg.msg.sender.as_str()),
);
let date = build_room_msg_date(&msg.msg.date);
let username_event_box = gtk::EventBox::new();
username_event_box.add(&username);

34
fractal-gtk/src/widgets/room_history.rs

@ -471,8 +471,11 @@ impl RoomHistory {
}
return Continue(true);
}
if let Some(pos) = edits.iter().position(|edit| item.id == edit.msg.replace) {
edits[pos].date = item.date;
if let Some(pos) = edits
.iter()
.position(|edit| item.msg.id == edit.msg.replace)
{
edits[pos].msg.date = item.msg.date;
item = edits.remove(pos).unwrap();
}
@ -482,17 +485,17 @@ impl RoomHistory {
if let Some(first) = rows.borrow().list.back() {
if let Element::Message(ref message) = first {
if item.date.day() != message.date.day() {
if item.msg.date.day() != message.msg.date.day() {
prev_day_divider =
Some(Element::DayDivider(create_day_divider(message.date)));
Some(Element::DayDivider(create_day_divider(message.msg.date)));
}
}
};
let has_header = {
if let Some(last) = last {
if item.date.day() != last.date.day() {
if item.msg.date.day() != last.msg.date.day() {
day_divider =
Some(Element::DayDivider(create_day_divider(item.date)));
Some(Element::DayDivider(create_day_divider(item.msg.date)));
}
last.mtype == RowType::Emote || !should_group_message(&item, &last)
} else {
@ -562,8 +565,9 @@ impl RoomHistory {
if let Some(last) = last {
match last {
Element::Message(ref message) => {
if item.date.day() != message.date.day() {
day_divider = Some(Element::DayDivider(create_day_divider(item.date)));
if item.msg.date.day() != message.msg.date.day() {
day_divider =
Some(Element::DayDivider(create_day_divider(item.msg.date)));
}
message.mtype == RowType::Emote || !should_group_message(&item, &message)
}
@ -610,14 +614,14 @@ impl RoomHistory {
.enumerate()
.find_map(|(i, e)| match e {
Element::Message(ref mut itermessage)
if itermessage.id == item.msg.replace
if itermessage.msg.id == item.msg.replace
|| itermessage.msg.replace == item.msg.replace =>
{
Some((i, itermessage))
}
_ => None,
})?;
item.date = msg.date;
item.msg.date = msg.msg.date;
let msg_widget = msg.widget.clone()?;
item.widget = Some(create_row(
@ -643,14 +647,14 @@ impl RoomHistory {
.iter_mut()
.enumerate()
.find_map(|(i, e)| match e {
Element::Message(ref mut itermessage) if itermessage.id == item.id => {
Element::Message(ref mut itermessage) if itermessage.msg.id == item.msg.id => {
Some((i, itermessage))
}
_ => None,
})?;
let msg_widget = msg.widget.clone()?;
let msg_sender = msg.sender.clone();
let msg_sender = msg.msg.sender.clone();
msg.msg.redacted = true;
rows.remove_item(i);
@ -676,7 +680,7 @@ impl RoomHistory {
})
.next()
.filter(|(msg_next_cloned, _)| {
msg_next_cloned.redactable && msg_next_cloned.sender == msg_sender
msg_next_cloned.redactable && msg_next_cloned.msg.sender == msg_sender
})
{
msg_widget.update_header(session_client, user_info_cache, msg_next_cloned, true);
@ -769,8 +773,8 @@ fn create_row(
/* returns if two messages should have only a single header or not */
fn should_group_message(msg: &MessageContent, prev: &MessageContent) -> bool {
if msg.sender == prev.sender && !prev.msg.redacted {
let diff = msg.date.signed_duration_since(prev.date);
if msg.msg.sender == prev.msg.sender && !prev.msg.redacted {
let diff = msg.msg.date.signed_duration_since(prev.msg.date);
let minutes = diff.num_minutes();
minutes < globals::MINUTES_TO_SPLIT_MSGS
} else {

Loading…
Cancel
Save