[fractal/fractal-next] Use SyncRoomEvent instead of other types
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] Use SyncRoomEvent instead of other types
- Date: Tue, 20 Jul 2021 09:13:20 +0000 (UTC)
commit 5a3c22a4034d4b07d2746e8a68e70024a7f2c5ac
Author: Julian Sparber <julian sparber net>
Date: Tue Jul 20 09:13:19 2021 +0000
Use SyncRoomEvent instead of other types
src/session/content/item_row.rs | 116 +++++++------
src/session/content/message_row.rs | 42 +++--
src/session/content/state_row.rs | 4 +-
src/session/room/event.rs | 348 +++++++++++++++++++++----------------
src/session/room/item.rs | 8 +-
src/session/room/room.rs | 133 ++++++--------
src/session/room/timeline.rs | 65 +++----
src/session/user.rs | 4 +-
8 files changed, 377 insertions(+), 343 deletions(-)
---
diff --git a/src/session/content/item_row.rs b/src/session/content/item_row.rs
index 4ae02192..1c70d0c0 100644
--- a/src/session/content/item_row.rs
+++ b/src/session/content/item_row.rs
@@ -1,21 +1,23 @@
use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
-use gtk::{gio, glib, prelude::*, subclass::prelude::*};
+use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
use crate::components::{ContextMenuBin, ContextMenuBinExt, ContextMenuBinImpl};
use crate::session::content::{DividerRow, MessageRow, StateRow};
use crate::session::event_source_dialog::EventSourceDialog;
-use crate::session::room::{Item, ItemType};
-use matrix_sdk::ruma::events::AnyRoomEvent;
+use crate::session::room::{Event, Item, ItemType};
+use matrix_sdk::ruma::events::AnySyncRoomEvent;
mod imp {
use super::*;
+ use glib::signal::SignalHandlerId;
use std::cell::RefCell;
#[derive(Debug, Default)]
pub struct ItemRow {
pub item: RefCell<Option<Item>>,
pub menu_model: RefCell<Option<gio::MenuModel>>,
+ pub event_notify_handler: RefCell<Option<SignalHandlerId>>,
}
#[glib::object_subclass]
@@ -73,6 +75,16 @@ mod imp {
_ => unimplemented!(),
}
}
+
+ fn dispose(&self, _obj: &Self::Type) {
+ if let Some(ItemType::Event(event)) =
+ self.item.borrow().as_ref().map(|item| item.type_())
+ {
+ if let Some(handler) = self.event_notify_handler.borrow_mut().take() {
+ event.disconnect(handler);
+ }
+ }
+ }
}
impl WidgetImpl for ItemRow {}
@@ -113,6 +125,13 @@ impl ItemRow {
fn set_item(&self, item: Option<Item>) {
let priv_ = imp::ItemRow::from_instance(&self);
+ if let Some(ItemType::Event(event)) = priv_.item.borrow().as_ref().map(|item| item.type_())
+ {
+ if let Some(handler) = priv_.event_notify_handler.borrow_mut().take() {
+ event.disconnect(handler);
+ }
+ }
+
if let Some(ref item) = item {
match item.type_() {
ItemType::Event(event) => {
@@ -126,57 +145,19 @@ impl ItemRow {
self.enable_gactions();
}
- match event.matrix_event() {
- AnyRoomEvent::Message(_message) => {
- let child = if let Some(Ok(child)) =
- self.child().map(|w| w.downcast::<MessageRow>())
- {
- child
- } else {
- let child = MessageRow::new();
- self.set_child(Some(&child));
- child
- };
- child.set_event(event.clone());
- }
- AnyRoomEvent::State(state) => {
- let child = if let Some(Ok(child)) =
- self.child().map(|w| w.downcast::<StateRow>())
- {
- child
- } else {
- let child = StateRow::new();
- self.set_child(Some(&child));
- child
- };
-
- child.update(&state);
- }
- AnyRoomEvent::RedactedMessage(_) => {
- let child = if let Some(Ok(child)) =
- self.child().map(|w| w.downcast::<MessageRow>())
- {
- child
- } else {
- let child = MessageRow::new();
- self.set_child(Some(&child));
- child
- };
- child.set_event(event.clone());
- }
- AnyRoomEvent::RedactedState(_) => {
- let child = if let Some(Ok(child)) =
- self.child().map(|w| w.downcast::<MessageRow>())
- {
- child
- } else {
- let child = MessageRow::new();
- self.set_child(Some(&child));
- child
- };
- child.set_event(event.clone());
- }
- }
+ let event_notify_handler = event.connect_notify_local(
+ Some("event"),
+ clone!(@weak self as obj => move |event, _| {
+ obj.set_event_widget(event);
+ }),
+ );
+
+ priv_
+ .event_notify_handler
+ .borrow_mut()
+ .replace(event_notify_handler);
+
+ self.set_event_widget(event);
}
ItemType::DayDivider(date) => {
if self.context_menu().is_some() {
@@ -219,4 +200,31 @@ impl ItemRow {
}
priv_.item.replace(item);
}
+
+ fn set_event_widget(&self, event: &Event) {
+ match event.matrix_event() {
+ Some(AnySyncRoomEvent::State(state)) => {
+ let child = if let Some(Ok(child)) = self.child().map(|w| w.downcast::<StateRow>())
+ {
+ child
+ } else {
+ let child = StateRow::new();
+ self.set_child(Some(&child));
+ child
+ };
+ child.update(&state);
+ }
+ _ => {
+ let child =
+ if let Some(Ok(child)) = self.child().map(|w| w.downcast::<MessageRow>()) {
+ child
+ } else {
+ let child = MessageRow::new();
+ self.set_child(Some(&child));
+ child
+ };
+ child.set_event(event.clone());
+ }
+ }
+ }
}
diff --git a/src/session/content/message_row.rs b/src/session/content/message_row.rs
index c1fc0d60..996c3b17 100644
--- a/src/session/content/message_row.rs
+++ b/src/session/content/message_row.rs
@@ -1,5 +1,6 @@
use crate::components::Avatar;
use adw::{prelude::*, subclass::prelude::*};
+use gettextrs::gettext;
use gtk::{
gio, glib, glib::clone, glib::signal::SignalHandlerId, prelude::*, subclass::prelude::*,
CompositeTemplate,
@@ -12,7 +13,7 @@ use log::warn;
use matrix_sdk::ruma::events::{
room::message::{FormattedBody, MessageFormat, MessageType, Relation},
room::redaction::RedactionEventContent,
- AnyMessageEvent, AnyMessageEventContent, AnyRoomEvent,
+ AnyMessageEventContent, AnySyncMessageEvent, AnySyncRoomEvent,
};
use sourceview::prelude::*;
@@ -190,10 +191,10 @@ impl MessageRow {
if let Some(replacement_event) = event.relates_to().iter().rev().find(|event| {
let matrix_event = event.matrix_event();
match matrix_event {
- AnyRoomEvent::Message(AnyMessageEvent::RoomMessage(message)) => {
+ Some(AnySyncRoomEvent::Message(AnySyncMessageEvent::RoomMessage(message))) => {
message.content.relates_to.is_some()
}
- AnyRoomEvent::Message(AnyMessageEvent::RoomRedaction(_)) => true,
+ Some(AnySyncRoomEvent::Message(AnySyncMessageEvent::RoomRedaction(_))) => true,
_ => false,
}
}) {
@@ -207,24 +208,32 @@ impl MessageRow {
}
}
/// Find the content we need to display
- fn find_content(&self, event: &Event) -> AnyMessageEventContent {
+ fn find_content(&self, event: &Event) -> Option<AnyMessageEventContent> {
match self.find_last_event(event).matrix_event() {
- AnyRoomEvent::Message(message) => message.content(),
- AnyRoomEvent::RedactedMessage(message) => {
+ Some(AnySyncRoomEvent::Message(message)) => Some(message.content()),
+ Some(AnySyncRoomEvent::RedactedMessage(message)) => {
if let Some(ref redaction_event) = message.unsigned().redacted_because {
- AnyMessageEventContent::RoomRedaction(redaction_event.content.clone())
+ Some(AnyMessageEventContent::RoomRedaction(
+ redaction_event.content.clone(),
+ ))
} else {
- AnyMessageEventContent::RoomRedaction(RedactionEventContent::new())
+ Some(AnyMessageEventContent::RoomRedaction(
+ RedactionEventContent::new(),
+ ))
}
}
- AnyRoomEvent::RedactedState(state) => {
+ Some(AnySyncRoomEvent::RedactedState(state)) => {
if let Some(ref redaction_event) = state.unsigned().redacted_because {
- AnyMessageEventContent::RoomRedaction(redaction_event.content.clone())
+ Some(AnyMessageEventContent::RoomRedaction(
+ redaction_event.content.clone(),
+ ))
} else {
- AnyMessageEventContent::RoomRedaction(RedactionEventContent::new())
+ Some(AnyMessageEventContent::RoomRedaction(
+ RedactionEventContent::new(),
+ ))
}
}
- _ => panic!("This event isn’t a room message event or redacted event"),
+ _ => None,
}
}
@@ -234,8 +243,9 @@ impl MessageRow {
// TODO: create widgets for all event types
// TODO: display reaction events from event.relates_to()
+
match content {
- AnyMessageEventContent::RoomMessage(message) => {
+ Some(AnyMessageEventContent::RoomMessage(message)) => {
let msgtype = if let Some(Relation::Replacement(replacement)) = message.relates_to {
replacement.new_content.msgtype
} else {
@@ -300,10 +310,10 @@ impl MessageRow {
}
}
}
- AnyMessageEventContent::RoomRedaction(_) => {
- self.show_label_with_text("This message was removed.");
+ Some(AnyMessageEventContent::RoomRedaction(_)) => {
+ self.show_label_with_text(&gettext("This message was removed."))
}
- _ => warn!("Event not supported: {:?}", content),
+ _ => self.show_label_with_text(&gettext("Unsupported event")),
}
}
diff --git a/src/session/content/state_row.rs b/src/session/content/state_row.rs
index 4dd0f6c9..7f4b4aff 100644
--- a/src/session/content/state_row.rs
+++ b/src/session/content/state_row.rs
@@ -3,7 +3,7 @@ use gettextrs::gettext;
use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use log::warn;
use matrix_sdk::ruma::events::{
- room::member::MembershipState, AnyStateEvent, AnyStateEventContent,
+ room::member::MembershipState, AnyStateEventContent, AnySyncStateEvent,
};
mod imp {
@@ -51,7 +51,7 @@ impl StateRow {
glib::Object::new(&[]).expect("Failed to create StateRow")
}
- pub fn update(&self, state: &AnyStateEvent) {
+ pub fn update(&self, state: &AnySyncStateEvent) {
let _priv_ = imp::StateRow::from_instance(self);
// We may want to show more state events in the future
// For a full list of state events see:
diff --git a/src/session/room/event.rs b/src/session/room/event.rs
index 2ab260ef..4dcfb7a0 100644
--- a/src/session/room/event.rs
+++ b/src/session/room/event.rs
@@ -1,20 +1,23 @@
use gtk::{glib, glib::DateTime, prelude::*, subclass::prelude::*};
-use matrix_sdk::ruma::{
- events::{
- room::message::MessageType, room::message::Relation, AnyMessageEvent,
- AnyMessageEventContent, AnyRedactedMessageEvent, AnyRedactedStateEvent, AnyRoomEvent,
- AnyStateEvent,
+use matrix_sdk::{
+ deserialized_responses::SyncRoomEvent,
+ ruma::{
+ events::{
+ room::message::MessageType, room::message::Relation, AnyMessageEventContent,
+ AnyRedactedSyncMessageEvent, AnyRedactedSyncStateEvent, AnySyncMessageEvent,
+ AnySyncRoomEvent, AnySyncStateEvent,
+ },
+ identifiers::{EventId, UserId},
+ MilliSecondsSinceUnixEpoch,
},
- identifiers::{EventId, UserId},
};
-use crate::fn_event;
-use crate::session::User;
-use std::cell::RefCell;
+use crate::session::{Room, User};
+use log::warn;
#[derive(Clone, Debug, glib::GBoxed)]
-#[gboxed(type_name = "BoxedAnyRoomEvent")]
-pub struct BoxedAnyRoomEvent(AnyRoomEvent);
+#[gboxed(type_name = "BoxedSyncRoomEvent")]
+pub struct BoxedSyncRoomEvent(SyncRoomEvent);
mod imp {
use super::*;
@@ -24,11 +27,13 @@ mod imp {
#[derive(Debug, Default)]
pub struct Event {
- pub event: OnceCell<RefCell<AnyRoomEvent>>,
- pub source: RefCell<Option<String>>,
+ /// The deserialized matrix event
+ pub event: RefCell<Option<AnySyncRoomEvent>>,
+ /// The SDK event containing encryption information and the serialized event as `Raw`
+ pub pure_event: RefCell<Option<SyncRoomEvent>>,
pub relates_to: RefCell<Vec<super::Event>>,
pub show_header: Cell<bool>,
- pub sender: OnceCell<User>,
+ pub room: OnceCell<Room>,
}
#[glib::object_subclass]
@@ -53,15 +58,15 @@ mod imp {
"event",
"event",
"The matrix event of this Event",
- BoxedAnyRoomEvent::static_type(),
- glib::ParamFlags::WRITABLE | glib::ParamFlags::CONSTRUCT,
+ BoxedSyncRoomEvent::static_type(),
+ glib::ParamFlags::WRITABLE,
),
glib::ParamSpec::new_string(
"source",
"Source",
"The source (JSON) of this Event",
None,
- glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT |
glib::ParamFlags::EXPLICIT_NOTIFY,
+ glib::ParamFlags::READABLE | glib::ParamFlags::EXPLICIT_NOTIFY,
),
glib::ParamSpec::new_boolean(
"show-header",
@@ -82,6 +87,13 @@ mod imp {
"Sender",
"The sender of this matrix event",
User::static_type(),
+ glib::ParamFlags::READABLE,
+ ),
+ glib::ParamSpec::new_object(
+ "room",
+ "Room",
+ "The room containing this event",
+ Room::static_type(),
glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT_ONLY,
),
glib::ParamSpec::new_string(
@@ -106,22 +118,15 @@ mod imp {
) {
match pspec.name() {
"event" => {
- let event = value.get::<BoxedAnyRoomEvent>().unwrap();
- obj.set_matrix_event(event.0);
- }
- "source" => {
- let source = value.get().unwrap();
- obj.set_source(source);
+ let event = value.get::<BoxedSyncRoomEvent>().unwrap();
+ obj.set_matrix_pure_event(event.0);
}
"show-header" => {
let show_header = value.get().unwrap();
let _ = obj.set_show_header(show_header);
}
- "sender" => {
- let sender = value.get().unwrap();
- if let Some(sender) = sender {
- let _ = self.sender.set(sender).unwrap();
- }
+ "room" => {
+ let _ = self.room.set(value.get().unwrap());
}
_ => unimplemented!(),
}
@@ -130,7 +135,8 @@ 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(),
+ "sender" => obj.sender().to_value(),
+ "room" => self.room.get().unwrap().to_value(),
"show-header" => obj.show_header().to_value(),
"can-hide-header" => obj.can_hide_header().to_value(),
"time" => obj.time().to_value(),
@@ -149,68 +155,108 @@ glib::wrapper! {
/// This is the GObject representation of a matrix room event
impl Event {
- pub fn new(event: &AnyRoomEvent, source: &String, sender: &User) -> Self {
- let event = BoxedAnyRoomEvent(event.to_owned());
- glib::Object::new(&[("event", &event), ("source", source), ("sender", sender)])
- .expect("Failed to create Event")
+ pub fn new(event: SyncRoomEvent, room: &Room) -> Self {
+ let event = BoxedSyncRoomEvent(event);
+ glib::Object::new(&[("event", &event), ("room", room)]).expect("Failed to create Event")
}
- pub fn sender(&self) -> &User {
+ pub fn sender(&self) -> User {
let priv_ = imp::Event::from_instance(&self);
- priv_.sender.get().unwrap()
+ priv_
+ .room
+ .get()
+ .unwrap()
+ .member_by_id(&self.matrix_sender())
}
- pub fn matrix_event(&self) -> AnyRoomEvent {
+ /// Get the matrix event
+ ///
+ /// If the `SyncRoomEvent` couldn't be deserialized this is `None`
+ pub fn matrix_event(&self) -> Option<AnySyncRoomEvent> {
let priv_ = imp::Event::from_instance(&self);
- priv_.event.get().unwrap().borrow().clone()
+ priv_.event.borrow().clone()
}
- pub fn set_matrix_event(&self, event: AnyRoomEvent) {
+ pub fn matrix_pure_event(&self) -> SyncRoomEvent {
let priv_ = imp::Event::from_instance(&self);
- if let Some(value) = priv_.event.get() {
- value.replace(event);
+ priv_.pure_event.borrow().clone().unwrap()
+ }
+
+ pub fn set_matrix_pure_event(&self, event: SyncRoomEvent) {
+ let priv_ = imp::Event::from_instance(&self);
+
+ if let Ok(deserialized) = event.event.deserialize() {
+ priv_.event.replace(Some(deserialized));
} else {
- priv_.event.set(RefCell::new(event)).unwrap();
+ warn!("Failed to deserialize event: {:?}", event);
}
+
+ priv_.pure_event.replace(Some(event));
+
self.notify("event");
}
pub fn matrix_sender(&self) -> UserId {
let priv_ = imp::Event::from_instance(&self);
- let event = &*priv_.event.get().unwrap().borrow();
- fn_event!(event, sender).clone()
+
+ if let Some(event) = priv_.event.borrow().as_ref() {
+ event.sender().to_owned()
+ } else {
+ priv_
+ .pure_event
+ .borrow()
+ .as_ref()
+ .unwrap()
+ .event
+ .get_field::<UserId>("sender")
+ .unwrap()
+ .unwrap()
+ }
}
pub fn matrix_event_id(&self) -> EventId {
let priv_ = imp::Event::from_instance(&self);
- let event = &*priv_.event.get().unwrap().borrow();
- 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())
+ if let Some(event) = priv_.event.borrow().as_ref() {
+ event.event_id().to_owned()
+ } else {
+ priv_
+ .pure_event
+ .borrow()
+ .as_ref()
+ .unwrap()
+ .event
+ .get_field::<EventId>("event_id")
+ .unwrap()
+ .unwrap()
+ }
}
- pub fn set_source(&self, source: Option<String>) {
+ pub fn source(&self) -> String {
let priv_ = imp::Event::from_instance(&self);
-
- if Some(self.source()) == source {
- return;
- }
-
- priv_.source.replace(source);
- self.notify("source");
+ serde_json::to_string_pretty(priv_.pure_event.borrow().as_ref().unwrap().event.json())
+ .unwrap()
}
pub fn timestamp(&self) -> DateTime {
let priv_ = imp::Event::from_instance(&self);
- let event = &*priv_.event.get().unwrap().borrow();
-
- let ts = fn_event!(event, origin_server_ts).clone();
- // FIXME: we need to add `as_secs()` to `MilliSecondsSinceUnixEpoch`
- DateTime::from_unix_utc(i64::from(ts.0) / 1000)
+ let ts = if let Some(event) = priv_.event.borrow().as_ref() {
+ event.origin_server_ts().as_secs()
+ } else {
+ priv_
+ .pure_event
+ .borrow()
+ .as_ref()
+ .unwrap()
+ .event
+ .get_field::<MilliSecondsSinceUnixEpoch>("origin_server_ts")
+ .unwrap()
+ .unwrap()
+ .as_secs()
+ };
+
+ DateTime::from_unix_utc(ts.into())
.and_then(|t| t.to_local())
.unwrap()
}
@@ -234,9 +280,9 @@ impl Event {
pub fn related_matrix_event(&self) -> Option<EventId> {
let priv_ = imp::Event::from_instance(&self);
- match *priv_.event.get().unwrap().borrow() {
- AnyRoomEvent::Message(ref message) => match message {
- AnyMessageEvent::RoomRedaction(event) => Some(event.redacts.clone()),
+ match priv_.event.borrow().as_ref()? {
+ AnySyncRoomEvent::Message(ref message) => match message {
+ AnySyncMessageEvent::RoomRedaction(event) => Some(event.redacts.clone()),
_ => match message.content() {
AnyMessageEventContent::Reaction(event) => Some(event.relates_to.event_id),
AnyMessageEventContent::RoomMessage(event) => match event.relates_to {
@@ -265,75 +311,79 @@ impl Event {
return true;
}
- match &*priv_.event.get().unwrap().borrow() {
- AnyRoomEvent::Message(message) => match message {
- AnyMessageEvent::CallAnswer(_) => true,
- AnyMessageEvent::CallInvite(_) => true,
- AnyMessageEvent::CallHangup(_) => true,
- AnyMessageEvent::CallCandidates(_) => true,
- AnyMessageEvent::KeyVerificationReady(_) => true,
- AnyMessageEvent::KeyVerificationStart(_) => true,
- AnyMessageEvent::KeyVerificationCancel(_) => true,
- AnyMessageEvent::KeyVerificationAccept(_) => true,
- AnyMessageEvent::KeyVerificationKey(_) => true,
- AnyMessageEvent::KeyVerificationMac(_) => true,
- AnyMessageEvent::KeyVerificationDone(_) => true,
- AnyMessageEvent::RoomEncrypted(_) => true,
- AnyMessageEvent::RoomMessageFeedback(_) => true,
- AnyMessageEvent::RoomRedaction(_) => true,
- AnyMessageEvent::Sticker(_) => true,
- _ => false,
- },
- AnyRoomEvent::State(state) => match state {
- AnyStateEvent::PolicyRuleRoom(_) => true,
- AnyStateEvent::PolicyRuleServer(_) => true,
- AnyStateEvent::PolicyRuleUser(_) => true,
- AnyStateEvent::RoomAliases(_) => true,
- AnyStateEvent::RoomAvatar(_) => true,
- AnyStateEvent::RoomCanonicalAlias(_) => true,
- AnyStateEvent::RoomEncryption(_) => true,
- AnyStateEvent::RoomJoinRules(_) => true,
- AnyStateEvent::RoomName(_) => true,
- AnyStateEvent::RoomPinnedEvents(_) => true,
- AnyStateEvent::RoomPowerLevels(_) => true,
- AnyStateEvent::RoomServerAcl(_) => true,
- AnyStateEvent::RoomTopic(_) => true,
- _ => false,
- },
- AnyRoomEvent::RedactedMessage(message) => match message {
- AnyRedactedMessageEvent::CallAnswer(_) => true,
- AnyRedactedMessageEvent::CallInvite(_) => true,
- AnyRedactedMessageEvent::CallHangup(_) => true,
- AnyRedactedMessageEvent::CallCandidates(_) => true,
- AnyRedactedMessageEvent::KeyVerificationReady(_) => true,
- AnyRedactedMessageEvent::KeyVerificationStart(_) => true,
- AnyRedactedMessageEvent::KeyVerificationCancel(_) => true,
- AnyRedactedMessageEvent::KeyVerificationAccept(_) => true,
- AnyRedactedMessageEvent::KeyVerificationKey(_) => true,
- AnyRedactedMessageEvent::KeyVerificationMac(_) => true,
- AnyRedactedMessageEvent::KeyVerificationDone(_) => true,
- AnyRedactedMessageEvent::RoomEncrypted(_) => true,
- AnyRedactedMessageEvent::RoomMessageFeedback(_) => true,
- AnyRedactedMessageEvent::RoomRedaction(_) => true,
- AnyRedactedMessageEvent::Sticker(_) => true,
- _ => false,
- },
- AnyRoomEvent::RedactedState(state) => match state {
- AnyRedactedStateEvent::PolicyRuleRoom(_) => true,
- AnyRedactedStateEvent::PolicyRuleServer(_) => true,
- AnyRedactedStateEvent::PolicyRuleUser(_) => true,
- AnyRedactedStateEvent::RoomAliases(_) => true,
- AnyRedactedStateEvent::RoomAvatar(_) => true,
- AnyRedactedStateEvent::RoomCanonicalAlias(_) => true,
- AnyRedactedStateEvent::RoomEncryption(_) => true,
- AnyRedactedStateEvent::RoomJoinRules(_) => true,
- AnyRedactedStateEvent::RoomName(_) => true,
- AnyRedactedStateEvent::RoomPinnedEvents(_) => true,
- AnyRedactedStateEvent::RoomPowerLevels(_) => true,
- AnyRedactedStateEvent::RoomServerAcl(_) => true,
- AnyRedactedStateEvent::RoomTopic(_) => true,
- _ => false,
- },
+ if let Some(event) = priv_.event.borrow().as_ref() {
+ match event {
+ AnySyncRoomEvent::Message(message) => match message {
+ AnySyncMessageEvent::CallAnswer(_) => true,
+ AnySyncMessageEvent::CallInvite(_) => true,
+ AnySyncMessageEvent::CallHangup(_) => true,
+ AnySyncMessageEvent::CallCandidates(_) => true,
+ AnySyncMessageEvent::KeyVerificationReady(_) => true,
+ AnySyncMessageEvent::KeyVerificationStart(_) => true,
+ AnySyncMessageEvent::KeyVerificationCancel(_) => true,
+ AnySyncMessageEvent::KeyVerificationAccept(_) => true,
+ AnySyncMessageEvent::KeyVerificationKey(_) => true,
+ AnySyncMessageEvent::KeyVerificationMac(_) => true,
+ AnySyncMessageEvent::KeyVerificationDone(_) => true,
+ AnySyncMessageEvent::RoomEncrypted(_) => true,
+ AnySyncMessageEvent::RoomMessageFeedback(_) => true,
+ AnySyncMessageEvent::RoomRedaction(_) => true,
+ AnySyncMessageEvent::Sticker(_) => true,
+ _ => false,
+ },
+ AnySyncRoomEvent::State(state) => match state {
+ AnySyncStateEvent::PolicyRuleRoom(_) => true,
+ AnySyncStateEvent::PolicyRuleServer(_) => true,
+ AnySyncStateEvent::PolicyRuleUser(_) => true,
+ AnySyncStateEvent::RoomAliases(_) => true,
+ AnySyncStateEvent::RoomAvatar(_) => true,
+ AnySyncStateEvent::RoomCanonicalAlias(_) => true,
+ AnySyncStateEvent::RoomEncryption(_) => true,
+ AnySyncStateEvent::RoomJoinRules(_) => true,
+ AnySyncStateEvent::RoomName(_) => true,
+ AnySyncStateEvent::RoomPinnedEvents(_) => true,
+ AnySyncStateEvent::RoomPowerLevels(_) => true,
+ AnySyncStateEvent::RoomServerAcl(_) => true,
+ AnySyncStateEvent::RoomTopic(_) => true,
+ _ => false,
+ },
+ AnySyncRoomEvent::RedactedMessage(message) => match message {
+ AnyRedactedSyncMessageEvent::CallAnswer(_) => true,
+ AnyRedactedSyncMessageEvent::CallInvite(_) => true,
+ AnyRedactedSyncMessageEvent::CallHangup(_) => true,
+ AnyRedactedSyncMessageEvent::CallCandidates(_) => true,
+ AnyRedactedSyncMessageEvent::KeyVerificationReady(_) => true,
+ AnyRedactedSyncMessageEvent::KeyVerificationStart(_) => true,
+ AnyRedactedSyncMessageEvent::KeyVerificationCancel(_) => true,
+ AnyRedactedSyncMessageEvent::KeyVerificationAccept(_) => true,
+ AnyRedactedSyncMessageEvent::KeyVerificationKey(_) => true,
+ AnyRedactedSyncMessageEvent::KeyVerificationMac(_) => true,
+ AnyRedactedSyncMessageEvent::KeyVerificationDone(_) => true,
+ AnyRedactedSyncMessageEvent::RoomEncrypted(_) => true,
+ AnyRedactedSyncMessageEvent::RoomMessageFeedback(_) => true,
+ AnyRedactedSyncMessageEvent::RoomRedaction(_) => true,
+ AnyRedactedSyncMessageEvent::Sticker(_) => true,
+ _ => false,
+ },
+ AnySyncRoomEvent::RedactedState(state) => match state {
+ AnyRedactedSyncStateEvent::PolicyRuleRoom(_) => true,
+ AnyRedactedSyncStateEvent::PolicyRuleServer(_) => true,
+ AnyRedactedSyncStateEvent::PolicyRuleUser(_) => true,
+ AnyRedactedSyncStateEvent::RoomAliases(_) => true,
+ AnyRedactedSyncStateEvent::RoomAvatar(_) => true,
+ AnyRedactedSyncStateEvent::RoomCanonicalAlias(_) => true,
+ AnyRedactedSyncStateEvent::RoomEncryption(_) => true,
+ AnyRedactedSyncStateEvent::RoomJoinRules(_) => true,
+ AnyRedactedSyncStateEvent::RoomName(_) => true,
+ AnyRedactedSyncStateEvent::RoomPinnedEvents(_) => true,
+ AnyRedactedSyncStateEvent::RoomPowerLevels(_) => true,
+ AnyRedactedSyncStateEvent::RoomServerAcl(_) => true,
+ AnyRedactedSyncStateEvent::RoomTopic(_) => true,
+ _ => false,
+ },
+ }
+ } else {
+ false
}
}
@@ -353,23 +403,25 @@ impl Event {
}
pub fn can_hide_header(&self) -> bool {
- let priv_ = imp::Event::from_instance(&self);
-
- match &*priv_.event.get().unwrap().borrow() {
- AnyRoomEvent::Message(ref message) => match message.content() {
- AnyMessageEventContent::RoomMessage(message) => match message.msgtype {
- MessageType::Audio(_) => true,
- MessageType::File(_) => true,
- MessageType::Image(_) => true,
- MessageType::Location(_) => true,
- MessageType::Notice(_) => true,
- MessageType::Text(_) => true,
- MessageType::Video(_) => true,
+ if let Some(event) = self.matrix_event() {
+ match event {
+ AnySyncRoomEvent::Message(ref message) => match message.content() {
+ AnyMessageEventContent::RoomMessage(message) => match message.msgtype {
+ MessageType::Audio(_) => true,
+ MessageType::File(_) => true,
+ MessageType::Image(_) => true,
+ MessageType::Location(_) => true,
+ MessageType::Notice(_) => true,
+ MessageType::Text(_) => true,
+ MessageType::Video(_) => true,
+ _ => false,
+ },
_ => false,
},
_ => false,
- },
- _ => false,
+ }
+ } else {
+ false
}
}
diff --git a/src/session/room/item.rs b/src/session/room/item.rs
index 08b4d69b..dd695908 100644
--- a/src/session/room/item.rs
+++ b/src/session/room/item.rs
@@ -1,6 +1,6 @@
use gtk::{glib, glib::DateTime, prelude::*, subclass::prelude::*};
use matrix_sdk::ruma::{
- events::AnyRoomEvent,
+ events::AnySyncRoomEvent,
identifiers::{EventId, UserId},
};
@@ -115,7 +115,7 @@ glib::wrapper! {
}
/// This represents any row inside the room history.
-/// This can be AnyRoomEvent, a day divider or new message divider.
+/// This can be AnySyncRoomEvent, a day divider or new message divider.
impl Item {
pub fn for_event(event: Event) -> Self {
let type_ = BoxedItemType(ItemType::Event(event));
@@ -141,10 +141,10 @@ impl Item {
}
}
- pub fn matrix_event(&self) -> Option<AnyRoomEvent> {
+ pub fn matrix_event(&self) -> Option<AnySyncRoomEvent> {
let priv_ = imp::Item::from_instance(&self);
if let ItemType::Event(event) = priv_.type_.get().unwrap() {
- Some(event.matrix_event())
+ event.matrix_event()
} else {
None
}
diff --git a/src/session/room/room.rs b/src/session/room/room.rs
index 78e91b7c..638e14f9 100644
--- a/src/session/room/room.rs
+++ b/src/session/room/room.rs
@@ -7,7 +7,6 @@ use matrix_sdk::{
ruma::{
api::client::r0::sync::sync_events::InvitedRoom,
events::{
- exports::serde::de::DeserializeOwned,
room::{
member::{MemberEventContent, MembershipState},
message::{
@@ -16,8 +15,8 @@ use matrix_sdk::{
},
},
tag::TagName,
- AnyMessageEvent, AnyRoomAccountDataEvent, AnyRoomEvent, AnyStateEvent,
- AnyStrippedStateEvent, AnySyncRoomEvent, MessageEvent, StateEvent, Unsigned,
+ AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncMessageEvent, AnySyncRoomEvent,
+ AnySyncStateEvent, SyncMessageEvent, SyncStateEvent, Unsigned,
},
identifiers::{EventId, RoomId, UserId},
serde::Raw,
@@ -26,13 +25,13 @@ use matrix_sdk::{
uuid::Uuid,
RoomMember,
};
+use serde_json::value::RawValue;
use std::cell::RefCell;
use std::convert::TryFrom;
use crate::components::{LabelWithWidgets, Pill};
-use crate::event_from_sync_event;
use crate::session::{
- room::{HighlightFlags, RoomType, Timeline},
+ room::{Event, HighlightFlags, RoomType, Timeline},
Avatar, Session, User,
};
use crate::utils::do_async;
@@ -539,28 +538,30 @@ impl Room {
}
/// Add new events to the timeline
- pub fn append_events<T: DeserializeOwned>(&self, batch: Vec<(AnyRoomEvent, Raw<T>)>) {
+ pub fn append_events(&self, batch: Vec<Event>) {
let priv_ = imp::Room::from_instance(self);
//FIXME: notify only when the count has changed
self.notify_notification_count();
- for (event, _) in batch.iter() {
- match event {
- AnyRoomEvent::State(AnyStateEvent::RoomMember(ref event)) => {
- self.update_member_for_member_event(event)
- }
- AnyRoomEvent::State(AnyStateEvent::RoomAvatar(event)) => {
- self.avatar().set_url(event.content.url.to_owned());
- }
- AnyRoomEvent::State(AnyStateEvent::RoomName(_)) => {
- // FIXME: this doesn't take into account changes in the calculated name
- self.load_display_name()
- }
- AnyRoomEvent::State(AnyStateEvent::RoomTopic(_)) => {
- self.notify("topic");
+ for event in &batch {
+ if let Some(event) = event.matrix_event() {
+ match event {
+ AnySyncRoomEvent::State(AnySyncStateEvent::RoomMember(ref event)) => {
+ self.update_member_for_member_event(event)
+ }
+ AnySyncRoomEvent::State(AnySyncStateEvent::RoomAvatar(event)) => {
+ self.avatar().set_url(event.content.url.to_owned());
+ }
+ AnySyncRoomEvent::State(AnySyncStateEvent::RoomName(_)) => {
+ // FIXME: this doesn't take into account changes in the calculated name
+ self.load_display_name()
+ }
+ AnySyncRoomEvent::State(AnySyncStateEvent::RoomTopic(_)) => {
+ self.notify("topic");
+ }
+ _ => {}
}
- _ => {}
}
}
@@ -583,7 +584,7 @@ impl Room {
}
/// Updates a room member based on the room member state event
- fn update_member_for_member_event(&self, event: &StateEvent<MemberEventContent>) {
+ fn update_member_for_member_event(&self, event: &SyncStateEvent<MemberEventContent>) {
let priv_ = imp::Room::from_instance(self);
let mut room_members = priv_.room_members.borrow_mut();
let user_id = &event.sender;
@@ -636,49 +637,46 @@ impl Room {
}
pub fn send_text_message(&self, body: &str, markdown_enabled: bool) {
- if let MatrixRoom::Joined(matrix_room) = self.matrix_room() {
- let content = if let Some(body) = body.strip_prefix("/me ") {
- let emote = if markdown_enabled {
- EmoteMessageEventContent::markdown(body)
- } else {
- EmoteMessageEventContent::plain(body)
- };
- MessageEventContent::new(MessageType::Emote(emote))
+ let content = if let Some(body) = body.strip_prefix("/me ") {
+ let emote = if markdown_enabled {
+ EmoteMessageEventContent::markdown(body)
} else {
- let text = if markdown_enabled {
- TextMessageEventContent::markdown(body)
- } else {
- TextMessageEventContent::plain(body)
- };
- MessageEventContent::new(MessageType::Text(text))
+ EmoteMessageEventContent::plain(body)
+ };
+ MessageEventContent::new(MessageType::Emote(emote))
+ } else {
+ let text = if markdown_enabled {
+ TextMessageEventContent::markdown(body)
+ } else {
+ TextMessageEventContent::plain(body)
};
+ MessageEventContent::new(MessageType::Text(text))
+ };
- let txn_id = Uuid::new_v4();
+ let txn_id = Uuid::new_v4();
- let pending_event = AnyMessageEvent::RoomMessage(MessageEvent {
- content,
- event_id: EventId::try_from(format!("${}:fractal.gnome.org", txn_id)).unwrap(),
- sender: self.session().user().user_id().clone(),
- origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
- room_id: matrix_room.room_id().clone(),
- unsigned: Unsigned::default(),
- });
+ let pending_event = AnySyncMessageEvent::RoomMessage(SyncMessageEvent {
+ content,
+ event_id: EventId::try_from(format!("${}:fractal.gnome.org", txn_id)).unwrap(),
+ sender: self.session().user().user_id().clone(),
+ origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
+ unsigned: Unsigned::default(),
+ });
- self.send_message(txn_id, pending_event);
- }
+ self.send_message(txn_id, pending_event);
}
- pub fn send_message(&self, txn_id: Uuid, event: AnyMessageEvent) {
+ pub fn send_message(&self, txn_id: Uuid, event: AnySyncMessageEvent) {
let priv_ = imp::Room::from_instance(self);
let content = event.content();
if let MatrixRoom::Joined(matrix_room) = self.matrix_room() {
let pending_id = event.event_id().clone();
- priv_
- .timeline
- .get()
- .unwrap()
- .append_pending(AnyRoomEvent::Message(event));
+ let json = serde_json::to_string(&AnySyncRoomEvent::Message(event)).unwrap();
+ let raw_event: Raw<AnySyncRoomEvent> =
+ Raw::from_json(RawValue::from_string(json).unwrap());
+ let event = Event::new(raw_event.into(), self);
+ priv_.timeline.get().unwrap().append_pending(event);
do_async(
glib::PRIORITY_DEFAULT_IDLE,
@@ -686,10 +684,7 @@ impl Room {
clone!(@weak self as obj => move |result| async move {
// FIXME: We should retry the request if it fails
match result {
- Ok(result) => {
- let priv_ = imp::Room::from_instance(&obj);
- priv_.timeline.get().unwrap().set_event_id_for_pending(pending_id,
result.event_id)
- },
+ Ok(result) => obj.timeline().set_event_id_for_pending(pending_id,
result.event_id),
Err(error) => error!("Couldn’t send message: {}", error),
};
}),
@@ -760,22 +755,12 @@ impl Room {
pub fn handle_left_response(&self, response_room: LeftRoom) {
self.set_matrix_room(self.session().client().get_room(self.room_id()).unwrap());
- let room_id = self.room_id();
-
self.append_events(
response_room
.timeline
.events
.into_iter()
- .filter_map(|raw_event| {
- if let Ok(event) = raw_event.event.deserialize() {
- Some((event, raw_event.event))
- } else {
- error!("Couldn’t deserialize event: {:?}", raw_event);
- None
- }
- })
- .map(|(event, source)| (event_from_sync_event!(event, room_id), source))
+ .map(|event| Event::new(event, self))
.collect(),
);
}
@@ -792,22 +777,12 @@ impl Room {
self.load_category();
}
- let room_id = self.room_id();
-
self.append_events(
response_room
.timeline
.events
.into_iter()
- .filter_map(|raw_event| {
- if let Ok(event) = raw_event.event.deserialize() {
- Some((event, raw_event.event))
- } else {
- error!("Couldn’t deserialize event: {:?}", raw_event);
- None
- }
- })
- .map(|(event, source)| (event_from_sync_event!(event, room_id), source))
+ .map(|event| Event::new(event, self))
.collect(),
);
}
diff --git a/src/session/room/timeline.rs b/src/session/room/timeline.rs
index 9206dfea..43298ad8 100644
--- a/src/session/room/timeline.rs
+++ b/src/session/room/timeline.rs
@@ -1,12 +1,6 @@
use gtk::{gio, glib, prelude::*, subclass::prelude::*};
-use matrix_sdk::ruma::{
- events::{exports::serde::de::DeserializeOwned, AnyRoomEvent},
- identifiers::EventId,
- serde::Raw,
-};
-use serde_json::{to_string_pretty as to_json_string_pretty, to_value as to_json_value};
-
-use crate::fn_event;
+use matrix_sdk::ruma::identifiers::EventId;
+
use crate::session::room::{Event, Item, Room};
mod imp {
@@ -268,7 +262,7 @@ impl Timeline {
/// Append the new events
// TODO: This should be lazy, for inspiration see:
https://blogs.gnome.org/ebassi/documentation/lazy-loading/
- pub fn append<T: DeserializeOwned>(&self, batch: Vec<(AnyRoomEvent, Raw<T>)>) {
+ pub fn append(&self, batch: Vec<Event>) {
let priv_ = imp::Timeline::from_instance(self);
if batch.is_empty() {
@@ -286,24 +280,22 @@ impl Timeline {
let mut pending_events = priv_.pending_events.borrow_mut();
- 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();
+ for event in batch.into_iter() {
+ let event_id = event.matrix_event_id();
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);
- }
+ let mut event_map = priv_.event_map.borrow_mut();
+
+ if let Some(pending_event) = event_map.remove(&pending_id) {
+ pending_event.set_matrix_pure_event(event.matrix_pure_event());
+ event_map.insert(event_id, pending_event);
+ };
added -= 1;
} else {
- let event = Event::new(&event, &source, &user);
-
- priv_.event_map.borrow_mut().insert(event_id, event.clone());
+ priv_
+ .event_map
+ .borrow_mut()
+ .insert(event_id.to_owned(), event.clone());
if event.is_hidden_event() {
self.add_hidden_event(event);
added -= 1;
@@ -320,17 +312,18 @@ impl Timeline {
}
/// Append an event that wasn't yet fully sent and received via a sync
- pub fn append_pending(&self, event: AnyRoomEvent) {
+ pub fn append_pending(&self, event: Event) {
let priv_ = imp::Timeline::from_instance(self);
+ priv_
+ .event_map
+ .borrow_mut()
+ .insert(event.matrix_event_id(), event.clone());
+
let index = {
let mut list = priv_.list.borrow_mut();
let index = list.len();
- let user = self.room().member_by_id(fn_event!(event, sender));
- 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);
None
@@ -363,7 +356,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<T: DeserializeOwned>(&self, batch: Vec<(AnyRoomEvent, Raw<T>)>) {
+ pub fn prepend(&self, batch: Vec<Event>) {
let priv_ = imp::Timeline::from_instance(self);
let mut added = batch.len();
@@ -371,15 +364,11 @@ impl Timeline {
// Extend the size of the list so that rust doesn't need to reallocate memory multiple times
priv_.list.borrow_mut().reserve(added);
- 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 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());
+ for event in batch {
+ priv_
+ .event_map
+ .borrow_mut()
+ .insert(event.matrix_event_id(), event.clone());
if event.is_hidden_event() {
self.add_hidden_event(event);
diff --git a/src/session/user.rs b/src/session/user.rs
index 3e75d374..c5ecb3a8 100644
--- a/src/session/user.rs
+++ b/src/session/user.rs
@@ -3,7 +3,7 @@ use gtk::{glib, prelude::*, subclass::prelude::*};
use crate::session::Session;
use matrix_sdk::{
ruma::{
- events::{room::member::MemberEventContent, StateEvent, StrippedStateEvent},
+ events::{room::member::MemberEventContent, StrippedStateEvent, SyncStateEvent},
identifiers::UserId,
},
RoomMember,
@@ -181,7 +181,7 @@ impl User {
}
/// Update the user based on the the room member state event
- pub fn update_from_member_event(&self, event: &StateEvent<MemberEventContent>) {
+ pub fn update_from_member_event(&self, event: &SyncStateEvent<MemberEventContent>) {
let changed = {
let priv_ = imp::User::from_instance(&self);
let user_id = priv_.user_id.get().unwrap();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]