[fractal/fractal-next] session: Add Supervisor aka EventHandler



commit b601f159ad1d26449c13ac62a5e0b8d21acf48a1
Author: Julian Sparber <julian sparber net>
Date:   Wed Mar 24 12:05:21 2021 +0100

    session: Add Supervisor aka EventHandler
    
    The Supervisor implements `matrix_sdk::EventHanlder` and forwards
    events to via channels so we can update the UI.

 src/meson.build           |  1 +
 src/session/content.rs    | 13 ++++++-
 src/session/mod.rs        |  9 +++++
 src/session/sidebar.rs    | 13 ++++++-
 src/session/supervisor.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 124 insertions(+), 2 deletions(-)
---
diff --git a/src/meson.build b/src/meson.build
index d03ab188..27d6c064 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -28,6 +28,7 @@ sources = files(
   'session/mod.rs',
   'session/content.rs',
   'session/sidebar.rs',
+  'session/supervisor.rs',
 )
 
 custom_target(
diff --git a/src/session/content.rs b/src/session/content.rs
index 112a3c48..eab6b0b9 100644
--- a/src/session/content.rs
+++ b/src/session/content.rs
@@ -2,7 +2,8 @@ use adw;
 use adw::subclass::prelude::BinImpl;
 use gtk::subclass::prelude::*;
 use gtk::{self, prelude::*};
-use gtk::{glib, CompositeTemplate};
+use gtk::{glib, glib::SyncSender, CompositeTemplate};
+use matrix_sdk::identifiers::RoomId;
 
 mod imp {
     use super::*;
@@ -102,4 +103,14 @@ impl FrctlContent {
     pub fn new() -> Self {
         glib::Object::new(&[]).expect("Failed to create FrctlContent")
     }
+
+    /// Sets up the required channel to recive async updates from the `Client`
+    pub fn setup_channel(&self) -> SyncSender<RoomId> {
+        let (sender, receiver) = glib::MainContext::sync_channel::<RoomId>(Default::default(), 100);
+        receiver.attach(None, move |_room_id| {
+            //TODO: actually do something: update the message GListModel
+            glib::Continue(true)
+        });
+        sender
+    }
 }
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 9f38105a..a131c9e8 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -1,8 +1,10 @@
 mod content;
 mod sidebar;
+mod supervisor;
 
 use self::content::FrctlContent;
 use self::sidebar::FrctlSidebar;
+use self::supervisor::Supervisor;
 
 use crate::secret;
 use crate::RUNTIME;
@@ -169,8 +171,15 @@ impl FrctlSession {
 
         let client = client.unwrap();
 
+        let sidebar_sender = priv_.sidebar.get().setup_channel();
+        let content_sender = priv_.content.get().setup_channel();
+
+        let handler = Supervisor::new(sidebar_sender, content_sender);
+
         RUNTIME.block_on(async {
             tokio::spawn(async move {
+                client.set_event_handler(Box::new(handler)).await;
+
                 let success = match method {
                     CreationMethod::SessionRestore(session) => {
                         let res = client.restore_login(session).await;
diff --git a/src/session/sidebar.rs b/src/session/sidebar.rs
index 10a9c4df..19396b39 100644
--- a/src/session/sidebar.rs
+++ b/src/session/sidebar.rs
@@ -2,7 +2,8 @@ use adw;
 use adw::subclass::prelude::BinImpl;
 use gtk::subclass::prelude::*;
 use gtk::{self, prelude::*};
-use gtk::{glib, CompositeTemplate};
+use gtk::{glib, glib::SyncSender, CompositeTemplate};
+use matrix_sdk::{identifiers::RoomId, Client};
 
 mod imp {
     use super::*;
@@ -102,4 +103,14 @@ impl FrctlSidebar {
     pub fn new() -> Self {
         glib::Object::new(&[]).expect("Failed to create FrctlSidebar")
     }
+
+    /// Sets up the required channel to recive async updates from the `Client`
+    pub fn setup_channel(&self) -> SyncSender<RoomId> {
+        let (sender, receiver) = glib::MainContext::sync_channel::<RoomId>(Default::default(), 100);
+        receiver.attach(None, move |_room_id| {
+            //TODO: actually do something: update the message GListModel
+            glib::Continue(true)
+        });
+        sender
+    }
 }
diff --git a/src/session/supervisor.rs b/src/session/supervisor.rs
new file mode 100644
index 00000000..70c4fcd6
--- /dev/null
+++ b/src/session/supervisor.rs
@@ -0,0 +1,90 @@
+use gtk::glib;
+use gtk_macros::send;
+use log::error;
+use matrix_sdk::{
+    self, async_trait,
+    events::{
+        room::{
+            aliases::AliasesEventContent, avatar::AvatarEventContent,
+            canonical_alias::CanonicalAliasEventContent, join_rules::JoinRulesEventContent,
+            message::MessageEventContent, name::NameEventContent, tombstone::TombstoneEventContent,
+        },
+        SyncMessageEvent, SyncStateEvent,
+    },
+    identifiers::RoomId,
+    room::Room,
+    CustomEvent, EventHandler,
+};
+use serde_json::value::RawValue as RawJsonValue;
+use std::sync::{Arc, RwLock};
+
+/// The `Supervisor` implements the `matrix_sdk::EventHandler`.
+///
+/// The idea is that the `Supervisor` sends a message to a `channel` when a matrix event is
+/// received.
+/// Every major UI component should provide a `glib::SyncSender<T>` where `T` is the message the UI
+/// compnent excpects to receive for a matrix event.
+///
+pub struct Supervisor {
+    sidebar: glib::SyncSender<RoomId>,
+    // TODO: figure out what infromation the content actually needs and should receive from an
+    // event
+    content: glib::SyncSender<RoomId>,
+    /// The ID of the room we want to receive updates for in the content, this is usually the
+    /// user visible room.
+    pub room_of_intressed: Arc<RwLock<Option<RoomId>>>,
+}
+
+impl Supervisor {
+    pub fn new(sidebar: glib::SyncSender<RoomId>, content: glib::SyncSender<RoomId>) -> Self {
+        Self {
+            sidebar,
+            content,
+            room_of_intressed: Arc::new(RwLock::new(None)),
+        }
+    }
+}
+
+#[async_trait]
+impl EventHandler for Supervisor {
+    async fn on_room_name(&self, room: Room, _: &SyncStateEvent<NameEventContent>) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+
+    async fn on_room_canonical_alias(
+        &self,
+        room: Room,
+        _: &SyncStateEvent<CanonicalAliasEventContent>,
+    ) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+
+    async fn on_room_aliases(&self, room: Room, _: &SyncStateEvent<AliasesEventContent>) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+
+    async fn on_room_avatar(&self, room: Room, _: &SyncStateEvent<AvatarEventContent>) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+
+    async fn on_room_message(&self, room: Room, _: &SyncMessageEvent<MessageEventContent>) {
+        // TODO: get the correct event for new notification count
+        send!(self.sidebar, room.room_id().clone());
+        send!(self.content, room.room_id().clone());
+    }
+    async fn on_room_join_rules(&self, room: Room, _: &SyncStateEvent<JoinRulesEventContent>) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+
+    async fn on_room_tombstone(&self, room: Room, _: &SyncStateEvent<TombstoneEventContent>) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+
+    async fn on_unrecognized_event(&self, room: Room, _: &RawJsonValue) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+
+    async fn on_custom_event(&self, room: Room, _: &CustomEvent<'_>) {
+        send!(self.sidebar, room.room_id().clone());
+    }
+}


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