[fractal/fractal-next] timeline: Don't display redacted events



commit dfabd1cba4f0b52e09978fd7cd44f41f269a3c73
Author: Kévin Commaille <zecakeh tedomum fr>
Date:   Wed Jan 26 19:45:59 2022 +0100

    timeline: Don't display redacted events

 src/session/room/event.rs    | 68 +++------------------------------
 src/session/room/timeline.rs | 91 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 94 insertions(+), 65 deletions(-)
---
diff --git a/src/session/room/event.rs b/src/session/room/event.rs
index 466c7d3d..1def5242 100644
--- a/src/session/room/event.rs
+++ b/src/session/room/event.rs
@@ -12,12 +12,9 @@ use matrix_sdk::{
     media::MediaEventContent,
     ruma::{
         events::{
-            room::{
-                message::{MessageType, Relation},
-                redaction::RoomRedactionEventContent,
-            },
-            AnyMessageEventContent, AnyRedactedSyncMessageEvent, AnyRedactedSyncStateEvent,
-            AnySyncMessageEvent, AnySyncRoomEvent, AnySyncStateEvent, Unsigned,
+            room::message::{MessageType, Relation},
+            AnyMessageEventContent, AnySyncMessageEvent, AnySyncRoomEvent, AnySyncStateEvent,
+            Unsigned,
         },
         identifiers::{EventId, UserId},
         MilliSecondsSinceUnixEpoch,
@@ -416,41 +413,8 @@ impl Event {
                     | AnySyncStateEvent::SpaceParent(_)
                     | AnySyncStateEvent::SpaceChild(_)
             ),
-            Some(AnySyncRoomEvent::RedactedMessage(message)) => matches!(
-                message,
-                AnyRedactedSyncMessageEvent::CallAnswer(_)
-                    | AnyRedactedSyncMessageEvent::CallInvite(_)
-                    | AnyRedactedSyncMessageEvent::CallHangup(_)
-                    | AnyRedactedSyncMessageEvent::CallCandidates(_)
-                    | AnyRedactedSyncMessageEvent::KeyVerificationReady(_)
-                    | AnyRedactedSyncMessageEvent::KeyVerificationStart(_)
-                    | AnyRedactedSyncMessageEvent::KeyVerificationCancel(_)
-                    | AnyRedactedSyncMessageEvent::KeyVerificationAccept(_)
-                    | AnyRedactedSyncMessageEvent::KeyVerificationKey(_)
-                    | AnyRedactedSyncMessageEvent::KeyVerificationMac(_)
-                    | AnyRedactedSyncMessageEvent::KeyVerificationDone(_)
-                    | AnyRedactedSyncMessageEvent::RoomMessageFeedback(_)
-                    | AnyRedactedSyncMessageEvent::RoomRedaction(_)
-                    | AnyRedactedSyncMessageEvent::Sticker(_)
-            ),
-            Some(AnySyncRoomEvent::RedactedState(state)) => matches!(
-                state,
-                AnyRedactedSyncStateEvent::PolicyRuleRoom(_)
-                    | AnyRedactedSyncStateEvent::PolicyRuleServer(_)
-                    | AnyRedactedSyncStateEvent::PolicyRuleUser(_)
-                    | AnyRedactedSyncStateEvent::RoomAliases(_)
-                    | AnyRedactedSyncStateEvent::RoomAvatar(_)
-                    | AnyRedactedSyncStateEvent::RoomCanonicalAlias(_)
-                    | AnyRedactedSyncStateEvent::RoomEncryption(_)
-                    | AnyRedactedSyncStateEvent::RoomJoinRules(_)
-                    | AnyRedactedSyncStateEvent::RoomName(_)
-                    | AnyRedactedSyncStateEvent::RoomPinnedEvents(_)
-                    | AnyRedactedSyncStateEvent::RoomPowerLevels(_)
-                    | AnyRedactedSyncStateEvent::RoomServerAcl(_)
-                    | AnyRedactedSyncStateEvent::RoomTopic(_)
-                    | AnyRedactedSyncStateEvent::SpaceParent(_)
-                    | AnyRedactedSyncStateEvent::SpaceChild(_)
-            ),
+            Some(AnySyncRoomEvent::RedactedMessage(_)) => true,
+            Some(AnySyncRoomEvent::RedactedState(_)) => true,
             _ => false,
         }
     }
@@ -601,28 +565,6 @@ impl Event {
     pub fn original_content(&self) -> Option<AnyMessageEventContent> {
         match self.matrix_event()? {
             AnySyncRoomEvent::Message(message) => Some(message.content()),
-            AnySyncRoomEvent::RedactedMessage(message) => {
-                if let Some(ref redaction_event) = message.unsigned().redacted_because {
-                    Some(AnyMessageEventContent::RoomRedaction(
-                        redaction_event.content.clone(),
-                    ))
-                } else {
-                    Some(AnyMessageEventContent::RoomRedaction(
-                        RoomRedactionEventContent::new(),
-                    ))
-                }
-            }
-            AnySyncRoomEvent::RedactedState(state) => {
-                if let Some(ref redaction_event) = state.unsigned().redacted_because {
-                    Some(AnyMessageEventContent::RoomRedaction(
-                        redaction_event.content.clone(),
-                    ))
-                } else {
-                    Some(AnyMessageEventContent::RoomRedaction(
-                        RoomRedactionEventContent::new(),
-                    ))
-                }
-            }
             _ => None,
         }
     }
diff --git a/src/session/room/timeline.rs b/src/session/room/timeline.rs
index 8f0acfc5..197051b1 100644
--- a/src/session/room/timeline.rs
+++ b/src/session/room/timeline.rs
@@ -26,7 +26,7 @@ use crate::{
 mod imp {
     use std::{
         cell::{Cell, RefCell},
-        collections::VecDeque,
+        collections::{HashSet, VecDeque},
     };
 
     use glib::object::WeakRef;
@@ -46,6 +46,8 @@ mod imp {
         /// Maps the temporary `EventId` of the pending Event to the real
         /// `EventId`
         pub pending_events: RefCell<HashMap<String, Box<EventId>>>,
+        /// A Hashset of `EventId`s that where just redacted.
+        pub redacted_events: RefCell<HashSet<Box<EventId>>>,
         pub loading: Cell<bool>,
         pub complete: Cell<bool>,
         pub oldest_event: RefCell<Option<Box<EventId>>>,
@@ -285,6 +287,7 @@ impl Timeline {
         {
             let list = priv_.list.borrow();
             let mut relates_to_events = priv_.relates_to_events.borrow_mut();
+            let mut redacted_events = priv_.redacted_events.borrow_mut();
 
             for event in list
                 .range(position as usize..(position + added) as usize)
@@ -312,6 +315,10 @@ impl Timeline {
                         event.prepend_replacing_events(replacing_events);
                     }
                     event.add_reactions(reactions);
+
+                    if event.redacted() {
+                        redacted_events.insert(event.matrix_event_id());
+                    }
                 }
             }
         }
@@ -320,10 +327,85 @@ impl Timeline {
 
         self.upcast_ref::<gio::ListModel>()
             .items_changed(position, removed, added);
+
+        self.remove_redacted_events();
+    }
+
+    fn remove_redacted_events(&self) {
+        let priv_ = self.imp();
+        let mut redacted_events_pos = Vec::with_capacity(priv_.redacted_events.borrow().len());
+
+        // Find redacted events in the list
+        {
+            let mut redacted_events = priv_.redacted_events.borrow_mut();
+            let list = priv_.list.borrow();
+            let mut i = list.len();
+            let mut list = list.iter();
+
+            while let Some(item) = list.next_back() {
+                if let ItemType::Event(event) = item.type_() {
+                    if redacted_events.remove(&event.matrix_event_id()) {
+                        redacted_events_pos.push(i - 1);
+                    }
+                    if redacted_events.is_empty() {
+                        break;
+                    }
+                }
+                i -= 1;
+            }
+        }
+
+        let mut redacted_events_pos = &mut redacted_events_pos[..];
+        // Sort positions to start from the end so positions are still valid
+        // and to group calls to `items_changed`.
+        redacted_events_pos.sort_unstable_by(|a, b| b.partial_cmp(a).unwrap());
+        while let Some(pos) = redacted_events_pos.first() {
+            let mut pos = pos.to_owned();
+            let mut removed = 1;
+
+            {
+                let mut list = priv_.list.borrow_mut();
+                list.remove(pos);
+
+                // Remove all consecutive previous redacted events.
+                while let Some(next_pos) = redacted_events_pos.get(removed) {
+                    if next_pos == &(pos - 1) {
+                        pos -= 1;
+                        removed += 1;
+                        list.remove(pos);
+                    } else {
+                        break;
+                    }
+                }
+                redacted_events_pos = &mut redacted_events_pos[removed..];
+
+                // Remove the day divider before this event if it's not useful anymore.
+                let day_divider_before = pos >= 1
+                    && matches!(
+                        list.get(pos - 1).map(|item| item.type_()),
+                        Some(ItemType::DayDivider(_))
+                    );
+                let after = pos == list.len()
+                    || matches!(
+                        list.get(pos).map(|item| item.type_()),
+                        Some(ItemType::DayDivider(_))
+                    );
+
+                if day_divider_before && after {
+                    pos -= 1;
+                    removed += 1;
+                    list.remove(pos);
+                }
+            }
+
+            self.upcast_ref::<gio::ListModel>()
+                .items_changed(pos as u32, removed as u32, 0);
+        }
     }
 
     fn add_hidden_events(&self, events: Vec<Event>, at_front: bool) {
-        let mut relates_to_events = self.imp().relates_to_events.borrow_mut();
+        let priv_ = self.imp();
+        let mut relates_to_events = priv_.relates_to_events.borrow_mut();
 
         // Group events by related event
         let mut new_relations: HashMap<Box<EventId>, Vec<Event>> = HashMap::new();
@@ -359,6 +441,7 @@ impl Timeline {
         }
 
         // Handle new relations
+        let mut redacted_events = priv_.redacted_events.borrow_mut();
         for (relates_to_event_id, new_relations) in new_relations {
             if let Some(relates_to_event) = self.event_by_id(&relates_to_event_id) {
                 // Get the relations in relates_to_event otherwise they will be added in
@@ -396,6 +479,10 @@ impl Timeline {
                     relates_to_event.prepend_replacing_events(replacing_events);
                 }
                 relates_to_event.add_reactions(reactions);
+
+                if relates_to_event.redacted() {
+                    redacted_events.insert(relates_to_event.matrix_event_id());
+                }
             } else {
                 // Store the new event if the `related_to` event isn't known, we will update the
                 // `relates_to` once the `related_to` event is added to the list


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