[fractal/fractal-next] room: Add source property to get the raw JSON of an Event



commit 8f64615dc9f37d112efe6a269d4db671715dedbb
Author: Kévin Commaille <zecakeh tedomum fr>
Date:   Fri May 28 11:18:56 2021 +0200

    room: Add source property to get the raw JSON of an Event

 src/session/room/event.rs    | 33 +++++++++++++++++++++++++++++++--
 src/session/room/room.rs     | 27 ++++++++++++++-------------
 src/session/room/timeline.rs | 29 +++++++++++++++++++++--------
 3 files changed, 66 insertions(+), 23 deletions(-)
---
diff --git a/src/session/room/event.rs b/src/session/room/event.rs
index 01a6cd70..e449b4f2 100644
--- a/src/session/room/event.rs
+++ b/src/session/room/event.rs
@@ -25,6 +25,7 @@ mod imp {
     #[derive(Debug, Default)]
     pub struct Event {
         pub event: OnceCell<RefCell<AnyRoomEvent>>,
+        pub source: RefCell<Option<String>>,
         pub relates_to: RefCell<Vec<super::Event>>,
         pub show_header: Cell<bool>,
         pub sender: OnceCell<User>,
@@ -55,6 +56,13 @@ mod imp {
                         BoxedAnyRoomEvent::static_type(),
                         glib::ParamFlags::WRITABLE | glib::ParamFlags::CONSTRUCT,
                     ),
+                    glib::ParamSpec::new_string(
+                        "source",
+                        "Source",
+                        "The source (JSON) of this Event",
+                        None,
+                        glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT | 
glib::ParamFlags::EXPLICIT_NOTIFY,
+                    ),
                     glib::ParamSpec::new_boolean(
                         "show-header",
                         "Show Header",
@@ -101,6 +109,10 @@ mod imp {
                     let event = value.get::<BoxedAnyRoomEvent>().unwrap();
                     obj.set_matrix_event(event.0);
                 }
+                "source" => {
+                    let source = value.get().unwrap();
+                    obj.set_source(source);
+                }
                 "show-header" => {
                     let show_header = value.get().unwrap();
                     let _ = obj.set_show_header(show_header);
@@ -117,6 +129,7 @@ mod imp {
 
         fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
             match pspec.name() {
+                "source" => obj.source().to_value(),
                 "sender" => self.sender.get().to_value(),
                 "show-header" => obj.show_header().to_value(),
                 "can-hide-header" => obj.can_hide_header().to_value(),
@@ -136,9 +149,9 @@ glib::wrapper! {
 
 /// This is the GObject represatation of a matrix room event
 impl Event {
-    pub fn new(event: &AnyRoomEvent, sender: &User) -> Self {
+    pub fn new(event: &AnyRoomEvent, source: &String, sender: &User) -> Self {
         let event = BoxedAnyRoomEvent(event.to_owned());
-        glib::Object::new(&[("event", &event), ("sender", &sender)])
+        glib::Object::new(&[("event", &event), ("source", source), ("sender", sender)])
             .expect("Failed to create Event")
     }
 
@@ -174,6 +187,22 @@ impl Event {
         fn_event!(event, event_id).clone()
     }
 
+    pub fn source(&self) -> String {
+        let priv_ = imp::Event::from_instance(&self);
+        priv_.source.borrow().clone().unwrap_or("".into())
+    }
+
+    pub fn set_source(&self, source: Option<String>) {
+        let priv_ = imp::Event::from_instance(&self);
+
+        if Some(self.source()) == source {
+            return;
+        }
+
+        priv_.source.replace(source);
+        self.notify("source");
+    }
+
     pub fn timestamp(&self) -> DateTime {
         let priv_ = imp::Event::from_instance(&self);
         let event = &*priv_.event.get().unwrap().borrow();
diff --git a/src/session/room/room.rs b/src/session/room/room.rs
index bcd86f31..c62b949e 100644
--- a/src/session/room/room.rs
+++ b/src/session/room/room.rs
@@ -5,6 +5,7 @@ use matrix_sdk::{
     api::r0::sync::sync_events::InvitedRoom,
     deserialized_responses::{JoinedRoom, LeftRoom},
     events::{
+        exports::serde::de::DeserializeOwned,
         room::{
             member::{MemberEventContent, MembershipState},
             message::{
@@ -18,7 +19,7 @@ use matrix_sdk::{
     identifiers::{EventId, RoomId, UserId},
     room::Room as MatrixRoom,
     uuid::Uuid,
-    MilliSecondsSinceUnixEpoch, RoomMember,
+    MilliSecondsSinceUnixEpoch, Raw, RoomMember,
 };
 use std::cell::RefCell;
 
@@ -433,13 +434,13 @@ impl Room {
     }
 
     /// Add new events to the timeline
-    pub fn append_events(&self, batch: Vec<AnyRoomEvent>) {
+    pub fn append_events<T: DeserializeOwned>(&self, batch: Vec<(AnyRoomEvent, Raw<T>)>) {
         let priv_ = imp::Room::from_instance(self);
 
         //FIXME: notify only when the count has changed
         self.notify_notification_count();
 
-        for event in batch.iter() {
+        for (event, _) in batch.iter() {
             match event {
                 AnyRoomEvent::State(AnyStateEvent::RoomMember(ref event)) => {
                     self.update_member_for_member_event(event)
@@ -649,15 +650,15 @@ impl Room {
                 .timeline
                 .events
                 .into_iter()
-                .filter_map(|event| {
-                    if let Ok(event) = event.event.deserialize() {
-                        Some(event)
+                .filter_map(|raw_event| {
+                    if let Ok(event) = raw_event.event.deserialize() {
+                        Some((event, raw_event.event))
                     } else {
-                        error!("Couldn't deserialize event: {:?}", event);
+                        error!("Couldn't deserialize event: {:?}", raw_event);
                         None
                     }
                 })
-                .map(|event| event_from_sync_event!(event, room_id))
+                .map(|(event, source)| (event_from_sync_event!(event, room_id), source))
                 .collect(),
         );
     }
@@ -681,15 +682,15 @@ impl Room {
                 .timeline
                 .events
                 .into_iter()
-                .filter_map(|event| {
-                    if let Ok(event) = event.event.deserialize() {
-                        Some(event)
+                .filter_map(|raw_event| {
+                    if let Ok(event) = raw_event.event.deserialize() {
+                        Some((event, raw_event.event))
                     } else {
-                        error!("Couldn't deserialize event: {:?}", event);
+                        error!("Couldn't deserialize event: {:?}", raw_event);
                         None
                     }
                 })
-                .map(|event| event_from_sync_event!(event, room_id))
+                .map(|(event, source)| (event_from_sync_event!(event, room_id), source))
                 .collect(),
         );
     }
diff --git a/src/session/room/timeline.rs b/src/session/room/timeline.rs
index 6a7a9228..3f148122 100644
--- a/src/session/room/timeline.rs
+++ b/src/session/room/timeline.rs
@@ -1,5 +1,10 @@
 use gtk::{gio, glib, prelude::*, subclass::prelude::*};
-use matrix_sdk::{events::AnyRoomEvent, identifiers::EventId};
+use matrix_sdk::{
+    events::{exports::serde::de::DeserializeOwned, AnyRoomEvent},
+    identifiers::EventId,
+    Raw,
+};
+use serde_json::{to_string_pretty as to_json_string_pretty, to_value as to_json_value};
 
 use crate::fn_event;
 use crate::session::room::{Event, Item, Room};
@@ -251,7 +256,7 @@ impl Timeline {
 
     /// Append the new events
     // TODO: This should be lazy, for isperation see: 
https://blogs.gnome.org/ebassi/documentation/lazy-loading/
-    pub fn append(&self, batch: Vec<AnyRoomEvent>) {
+    pub fn append<T: DeserializeOwned>(&self, batch: Vec<(AnyRoomEvent, Raw<T>)>) {
         let priv_ = imp::Timeline::from_instance(self);
 
         if batch.is_empty() {
@@ -269,18 +274,22 @@ impl Timeline {
 
             let mut pending_events = priv_.pending_events.borrow_mut();
 
-            for event in batch.into_iter() {
+            for (event, raw) in batch.into_iter() {
                 let event_id = fn_event!(event, event_id).clone();
                 let user = self.room().member_by_id(fn_event!(event, sender));
+                let source = to_json_value(raw.into_json())
+                    .and_then(|v| to_json_string_pretty(&v))
+                    .unwrap();
 
                 if let Some(pending_id) = pending_events.remove(&event_id) {
                     if let Some(event_obj) = priv_.event_map.borrow_mut().remove(&pending_id) {
                         event_obj.set_matrix_event(event);
+                        event_obj.set_source(Some(source));
                         priv_.event_map.borrow_mut().insert(event_id, event_obj);
                     }
                     added -= 1;
                 } else {
-                    let event = Event::new(&event, &user);
+                    let event = Event::new(&event, &source, &user);
 
                     priv_.event_map.borrow_mut().insert(event_id, event.clone());
                     if event.is_hidden_event() {
@@ -307,7 +316,8 @@ impl Timeline {
             let index = list.len();
 
             let user = self.room().member_by_id(fn_event!(event, sender));
-            let event = Event::new(&event, &user);
+            let source = to_json_string_pretty(&event).unwrap();
+            let event = Event::new(&event, &source, &user);
 
             if event.is_hidden_event() {
                 self.add_hidden_event(event);
@@ -341,7 +351,7 @@ impl Timeline {
 
     /// Prepends a batch of events
     // TODO: This should be lazy, see: https://blogs.gnome.org/ebassi/documentation/lazy-loading/
-    pub fn prepend(&self, batch: Vec<AnyRoomEvent>) {
+    pub fn prepend<T: DeserializeOwned>(&self, batch: Vec<(AnyRoomEvent, Raw<T>)>) {
         let priv_ = imp::Timeline::from_instance(self);
         let mut added = batch.len();
 
@@ -349,10 +359,13 @@ impl Timeline {
             // Extened the size of the list so that rust doesn't need to realocate memory multiple times
             priv_.list.borrow_mut().reserve(added);
 
-            for event in batch {
+            for (event, raw) in batch {
                 let user = self.room().member_by_id(fn_event!(event, sender));
                 let event_id = fn_event!(event, event_id).clone();
-                let event = Event::new(&event, &user);
+                let source = to_json_value(raw.into_json())
+                    .and_then(|v| to_json_string_pretty(&v))
+                    .unwrap();
+                let event = Event::new(&event, &source, &user);
 
                 priv_.event_map.borrow_mut().insert(event_id, event.clone());
 


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