[fractal] fractal-gtk: room_history: Set header for new messages



commit ba7ec7586821ac605d829f88684bd048574df1b1
Author: Alistair Francis <alistair alistair23 me>
Date:   Mon Aug 26 21:29:05 2019 -0700

    fractal-gtk: room_history: Set header for new messages
    
    If a user redacts the first message in a group they will cause the
    header to be deleted. This makes it impossible to tell who sent the rest
    of the messages in the group.
    
    Set the header as true for the next message if this is the case.
    
    In case other messages in the group have already been deleted we loop
    over the messages to find the next non-redacted one from our current
    sender.
    
    Signed-off-by: Alistair Francis <alistair alistair23 me>

 fractal-gtk/src/widgets/message.rs      | 24 +++++++++++++++++-
 fractal-gtk/src/widgets/room_history.rs | 43 ++++++++++++++++++++++++++++++---
 2 files changed, 62 insertions(+), 5 deletions(-)
---
diff --git a/fractal-gtk/src/widgets/message.rs b/fractal-gtk/src/widgets/message.rs
index b1428316..63c065e6 100644
--- a/fractal-gtk/src/widgets/message.rs
+++ b/fractal-gtk/src/widgets/message.rs
@@ -41,7 +41,7 @@ pub struct MessageBox {
     gesture: gtk::GestureLongPress,
     row: gtk::ListBoxRow,
     image: Option<gtk::DrawingArea>,
-    header: bool,
+    pub header: bool,
 }
 
 impl MessageBox {
@@ -105,6 +105,28 @@ impl MessageBox {
         Some(self)
     }
 
+    pub fn update_header(&mut self, msg: Message, has_header: bool) {
+        let w = if has_header && msg.mtype != RowType::Emote {
+            self.row.set_margin_top(12);
+            self.header = true;
+            self.widget(&msg)
+        } else {
+            if let RowType::Emote = msg.mtype {
+                self.row.set_margin_top(12);
+            }
+            self.header = false;
+            self.small_widget(&msg)
+        };
+        match self.eventbox.get_child() {
+            Some(eb) => {
+                eb.destroy(); // clean the eventbox
+            }
+            _ => {}
+        }
+        self.eventbox.add(&w);
+        self.row.show_all();
+    }
+
     fn widget(&mut self, msg: &Message) -> gtk::Box {
         // msg
         // +--------+---------+
diff --git a/fractal-gtk/src/widgets/room_history.rs b/fractal-gtk/src/widgets/room_history.rs
index 4a6beb4f..2ff289a6 100644
--- a/fractal-gtk/src/widgets/room_history.rs
+++ b/fractal-gtk/src/widgets/room_history.rs
@@ -269,15 +269,50 @@ impl RoomHistory {
 
     pub fn remove_message(&mut self, item: MessageContent) -> Option<()> {
         let mut rows = self.rows.borrow_mut();
-        let ref mut msg = rows.list.iter_mut().find_map(|e| match e {
-            Element::Message(ref mut itermessage) if itermessage.id == item.id => Some(itermessage),
-            _ => None,
-        })?;
+        let (i, ref mut msg) = rows
+            .list
+            .iter_mut()
+            .enumerate()
+            .find_map(|(i, e)| match e {
+                Element::Message(ref mut itermessage) if itermessage.id == item.id => {
+                    Some((i, itermessage))
+                }
+                _ => None,
+            })?;
 
         let msg_widget = msg.widget.clone()?;
+        let msg_sender = msg.sender.clone();
         msg.msg.redacted = true;
         rows.listbox.remove(msg_widget.get_listbox_row()?);
 
+        // If the redacted message was a header message let's set
+        // the header on the next non-redacted message instead.
+        if msg_widget.header {
+            let rows_list_len = rows.list.len();
+            if let Some((msg_next_cloned, msg_widget)) = rows
+                .list
+                .iter_mut()
+                .rev()
+                .skip(rows_list_len - i)
+                .filter_map(|message_next| match message_next {
+                    Element::Message(ref mut msg_next) => {
+                        let msg_next_cloned = msg_next.clone();
+                        msg_next
+                            .widget
+                            .as_mut()
+                            .filter(|_| !msg_next_cloned.msg.redacted)
+                            .map(|msg_widet| (msg_next_cloned, msg_widet))
+                    }
+                    _ => None,
+                })
+                .next()
+                .filter(|(msg_next_cloned, _)| {
+                    msg_next_cloned.redactable && msg_next_cloned.sender == msg_sender
+                })
+            {
+                msg_widget.update_header(msg_next_cloned, true);
+            }
+        }
         None
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]