[fractal] Track relations in MessageList
- From: Alejandro Domínguez <aledomu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] Track relations in MessageList
- Date: Fri, 12 Feb 2021 11:43:41 +0000 (UTC)
commit 6b10fa3ecc99b99dcb93b07720e40d73a21102aa
Author: Kai A. Hiller <V02460 gmail com>
Date: Sat Jan 9 22:31:13 2021 +0100
Track relations in MessageList
fractal-gtk/src/model/message.rs | 9 +++++
fractal-gtk/src/model/message_list.rs | 65 +++++++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+)
---
diff --git a/fractal-gtk/src/model/message.rs b/fractal-gtk/src/model/message.rs
index 1bfa753b..b06e6468 100644
--- a/fractal-gtk/src/model/message.rs
+++ b/fractal-gtk/src/model/message.rs
@@ -433,6 +433,15 @@ impl Message {
}
}
+ /// Returns all event IDs this message relates to.
+ pub fn relations(&self) -> Vec<EventId> {
+ vec![self.in_reply_to.as_ref(), self.replace.as_ref()]
+ .into_iter()
+ .flat_map(|r| r.into_iter())
+ .cloned()
+ .collect()
+ }
+
/// 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.
diff --git a/fractal-gtk/src/model/message_list.rs b/fractal-gtk/src/model/message_list.rs
index ac476449..7f944324 100644
--- a/fractal-gtk/src/model/message_list.rs
+++ b/fractal-gtk/src/model/message_list.rs
@@ -1,5 +1,7 @@
use crate::model::message::Message;
use matrix_sdk::identifiers::EventId;
+use std::collections::{HashMap, HashSet};
+use std::iter;
use std::iter::FromIterator;
use std::slice::Iter;
@@ -7,6 +9,7 @@ use std::slice::Iter;
#[derive(Debug, Default, Clone)]
pub struct MessageList {
messages: Vec<Message>,
+ relating_messages: HashMap<EventId, HashSet<EventId>>,
}
impl MessageList {
@@ -34,6 +37,11 @@ impl MessageList {
/// Inserts the message at the correct position replacing its older version.
pub fn add(&mut self, msg: Message) {
assert!(msg.id.is_some());
+ let id = msg.id.clone().unwrap();
+
+ if msg.redacted {
+ self.remove_relations(&id);
+ }
// Deduplication only happens for messages with the same date, so we have
// to manually go through the message list and remove possible duplicates.
@@ -45,6 +53,10 @@ impl MessageList {
// brute-force-fix this by searching all messages for duplicates.
self.messages.retain(|m| m.id != msg.id);
+ if !msg.redacted {
+ self.populate_relations(&msg);
+ }
+
match self.messages.binary_search(&msg) {
Ok(idx) => self.messages[idx] = msg,
Err(idx) => self.messages.insert(idx, msg),
@@ -52,6 +64,59 @@ impl MessageList {
// TODO: Use is_sorted (https://github.com/rust-lang/rust/issues/53485)
// debug_assert!(self.messages.is_sorted());
}
+
+ /// Updates records of those relations the message is involved in.
+ ///
+ /// This updates both, relating and related, messages.
+ fn populate_relations(&mut self, msg: &Message) {
+ // Other messages relate to `msg`
+ let id = msg.id.as_ref().cloned().unwrap();
+ let relating = self.find_and_get_relating(&id);
+ self.relating_messages.insert(id.clone(), relating);
+
+ // `msg` relates to other messages
+ if let Some(replace_id) = &msg.replace {
+ self.update_relating(replace_id, iter::once(&id).cloned().collect());
+ }
+ }
+
+ /// Remove all outgoing relations for the given event.
+ fn remove_relations(&mut self, event_id: &EventId) {
+ let msg = unwrap_or_unit_return!(self.get(event_id));
+ let relations = msg.relations();
+
+ let event_sets = self.relating_messages.iter_mut().filter_map(|(id, rs)| {
+ if relations.contains(&id) {
+ Some(rs)
+ } else {
+ None
+ }
+ });
+
+ for set in event_sets {
+ set.retain(|id| id != event_id);
+ }
+ }
+
+ /// Records new messages relating to the message with the given id.
+ ///
+ /// This does not remove other messages relating to the given id.
+ fn update_relating(&mut self, id: &EventId, relating: HashSet<EventId>) {
+ let new_relating = match self.relating_messages.remove(id) {
+ Some(old_relating) => old_relating.union(&relating).cloned().collect(),
+ None => relating,
+ };
+ self.relating_messages.insert(id.clone(), new_relating);
+ }
+
+ /// Finds and returns all messages relating to the given one.
+ fn find_and_get_relating(&self, id: &EventId) -> HashSet<EventId> {
+ self.messages
+ .iter()
+ .filter(|m| m.replace.as_ref() == Some(id) || m.in_reply_to.as_ref() == Some(id))
+ .map(|m| m.id.clone().unwrap())
+ .collect()
+ }
}
impl FromIterator<Message> for MessageList {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]