[fractal] sidebar: Add category people



commit 311ffd55c364d78d89d657d314e6801efff2309f
Author: Julian Sparber <julian sparber net>
Date:   Fri Dec 17 00:12:39 2021 +0100

    sidebar: Add category people
    
    Part-of: <https://gitlab.gnome.org/GNOME/fractal/-/merge_requests/931>

 data/resources/ui/sidebar.ui         |  5 +++
 src/session/mod.rs                   | 40 +++++++++++++++++++++--
 src/session/room/mod.rs              | 63 +++++++++++++++++++++++++++++++++++-
 src/session/room/room_type.rs        | 33 +++++++++++++++----
 src/session/sidebar/category_type.rs |  3 ++
 src/session/sidebar/item_list.rs     |  5 +--
 src/session/sidebar/room_row.rs      | 34 +++++++++++++++++--
 7 files changed, 170 insertions(+), 13 deletions(-)
---
diff --git a/data/resources/ui/sidebar.ui b/data/resources/ui/sidebar.ui
index 2464c9620..5680ba597 100644
--- a/data/resources/ui/sidebar.ui
+++ b/data/resources/ui/sidebar.ui
@@ -46,6 +46,11 @@
         <attribute name="action">room-row.set-normal</attribute>
         <attribute name="hidden-when">action-disabled</attribute>
       </item>
+      <item>
+        <attribute name="label" translatable="yes">Move to _People</attribute>
+        <attribute name="action">room-row.set-direct</attribute>
+        <attribute name="hidden-when">action-disabled</attribute>
+      </item>
       <item>
         <attribute name="label" translatable="yes">Move to Low _Priority</attribute>
         <attribute name="action">room-row.set-lowpriority</attribute>
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 02ec32b73..5a686e76a 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -10,7 +10,7 @@ mod sidebar;
 mod user;
 pub mod verification;
 
-use std::{convert::TryFrom, fs, path::Path, time::Duration};
+use std::{collections::HashSet, convert::TryFrom, fs, path::Path, time::Duration};
 
 use adw::subclass::prelude::BinImpl;
 use futures::StreamExt;
@@ -35,7 +35,9 @@ use matrix_sdk::{
             },
             error::{FromHttpResponseError, ServerError},
         },
-        assign, RoomId,
+        assign,
+        events::{direct::DirectEventContent, GlobalAccountDataEvent},
+        RoomId,
     },
     store::{make_store_config, OpenStoreError},
     Client, ClientBuildError, Error, HttpError,
@@ -473,6 +475,7 @@ impl Session {
                 priv_.info.set(session).unwrap();
 
                 self.room_list().load();
+                self.setup_direct_room_handler();
 
                 self.sync();
 
@@ -845,6 +848,39 @@ impl Session {
         .await
         .unwrap()
     }
+
+    fn setup_direct_room_handler(&self) {
+        spawn!(
+            glib::PRIORITY_DEFAULT_IDLE,
+            clone!(@weak self as obj => async move {
+                let obj_weak = glib::SendWeakRef::from(obj.downgrade());
+                    obj.client().register_event_handler(
+                        move |event: GlobalAccountDataEvent<DirectEventContent>| {
+                            let obj_weak = obj_weak.clone();
+                            async move {
+                                let ctx = glib::MainContext::default();
+                                ctx.spawn(async move {
+                                    spawn!(async move {
+                                        if let Some(session) = obj_weak.upgrade() {
+                                            let room_ids = event.content.iter().fold(HashSet::new(), |mut 
acc, (_, rooms)| {
+                                                acc.extend(&*rooms);
+                                                acc
+                                            });
+                                            for room_id in room_ids {
+                                                if let Some(room) = session.room_list().get(room_id) {
+                                                    room.load_category();
+                                                }
+                                            }
+                                        }
+                                    });
+                                });
+                            }
+                        },
+                    )
+                    .await;
+            })
+        );
+    }
 }
 
 impl Default for Session {
diff --git a/src/session/room/mod.rs b/src/session/room/mod.rs
index c13f59f57..c0d586900 100644
--- a/src/session/room/mod.rs
+++ b/src/session/room/mod.rs
@@ -377,6 +377,16 @@ impl Room {
         self.imp().room_id.get().unwrap()
     }
 
+    /// Whether this room is a DM
+    pub fn is_direct(&self) -> bool {
+        self.imp()
+            .matrix_room
+            .borrow()
+            .as_ref()
+            .unwrap()
+            .is_direct()
+    }
+
     fn matrix_room(&self) -> MatrixRoom {
         self.imp().matrix_room.borrow().as_ref().unwrap().clone()
     }
@@ -518,6 +528,15 @@ impl Room {
                     RoomType::Left => room.reject_invitation().await,
                     RoomType::Outdated => unimplemented!(),
                     RoomType::Space => unimplemented!(),
+                    RoomType::Direct => {
+                        if !room.is_direct() {
+                            // TODO: mark as direct by adding it to account data
+                        }
+
+                        room.accept_invitation().await?;
+
+                        Ok(())
+                    }
                 },
                 MatrixRoom::Joined(room) => match category {
                     RoomType::Invited => Ok(()),
@@ -529,6 +548,10 @@ impl Room {
                         Ok(())
                     }
                     RoomType::Normal => {
+                        if room.is_direct() {
+                            // TODO: remove the room from the list of direct
+                            // rooms via the account data
+                        }
                         match previous_category {
                             RoomType::Favorite => {
                                 room.remove_tag(TagName::Favorite).await?;
@@ -550,6 +573,22 @@ impl Room {
                     RoomType::Left => room.leave().await,
                     RoomType::Outdated => unimplemented!(),
                     RoomType::Space => unimplemented!(),
+                    RoomType::Direct => {
+                        if !room.is_direct() {
+                            // TODO: Mark as direct by adding it to account data
+                        }
+
+                        if let Some(tags) = room.tags().await? {
+                            if tags.contains_key(&TagName::LowPriority) {
+                                room.remove_tag(TagName::LowPriority).await?;
+                            }
+                            if tags.contains_key(&TagName::Favorite) {
+                                room.remove_tag(TagName::Favorite).await?;
+                            }
+                        }
+
+                        Ok(())
+                    }
                 },
                 MatrixRoom::Left(room) => match category {
                     RoomType::Invited => Ok(()),
@@ -568,6 +607,23 @@ impl Room {
                     RoomType::Left => Ok(()),
                     RoomType::Outdated => unimplemented!(),
                     RoomType::Space => unimplemented!(),
+                    RoomType::Direct => {
+                        if !room.is_direct() {
+                            // TODO: Mark as direct by adding it to account data
+                        }
+
+                        if let Some(tags) = room.tags().await? {
+                            if tags.contains_key(&TagName::LowPriority) {
+                                room.remove_tag(TagName::LowPriority).await?;
+                            }
+                            if tags.contains_key(&TagName::Favorite) {
+                                room.remove_tag(TagName::Favorite).await?;
+                            }
+                        }
+
+                        room.join().await?;
+                        Ok(())
+                    }
                 },
             }
         });
@@ -617,12 +673,17 @@ impl Room {
                 if matrix_room.is_space() {
                     self.set_category_internal(RoomType::Space);
                 } else {
+                    let is_direct = matrix_room.is_direct();
                     let handle = spawn_tokio!(async move { matrix_room.tags().await });
 
                     spawn!(
                         glib::PRIORITY_DEFAULT_IDLE,
                         clone!(@weak self as obj => async move {
-                            let mut category = RoomType::Normal;
+                            let mut category = if is_direct {
+                                        RoomType::Direct
+                                    } else {
+                                        RoomType::Normal
+                                    };
 
                             if let Ok(Some(tags)) = handle.await.unwrap() {
                                 if tags.get(&TagName::Favorite).is_some() {
diff --git a/src/session/room/room_type.rs b/src/session/room/room_type.rs
index bdcdf5893..1dc3ab9b3 100644
--- a/src/session/room/room_type.rs
+++ b/src/session/room/room_type.rs
@@ -5,7 +5,8 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
 
 use crate::session::sidebar::CategoryType;
 
-// TODO: do we also want the category `People` and a custom category support?
+// TODO: do we also want custom tags support?
+// See https://spec.matrix.org/v1.2/client-server-api/#room-tagging
 #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, glib::Enum, IntoPrimitive, TryFromPrimitive)]
 #[repr(u32)]
 #[enum_type(name = "RoomType")]
@@ -17,6 +18,7 @@ pub enum RoomType {
     Left = 4,
     Outdated = 5,
     Space = 6,
+    Direct = 7,
 }
 
 impl RoomType {
@@ -26,23 +28,41 @@ impl RoomType {
             Self::Invited => {
                 matches!(
                     category,
-                    Self::Favorite | Self::Normal | Self::LowPriority | Self::Left
+                    Self::Favorite | Self::Normal | Self::Direct | Self::LowPriority | Self::Left
                 )
             }
             Self::Favorite => {
-                matches!(category, Self::Normal | Self::LowPriority | Self::Left)
+                matches!(
+                    category,
+                    Self::Normal | Self::Direct | Self::LowPriority | Self::Left
+                )
             }
             Self::Normal => {
-                matches!(category, Self::Favorite | Self::LowPriority | Self::Left)
+                matches!(
+                    category,
+                    Self::Favorite | Self::Direct | Self::LowPriority | Self::Left
+                )
             }
             Self::LowPriority => {
-                matches!(category, Self::Favorite | Self::Normal | Self::Left)
+                matches!(
+                    category,
+                    Self::Favorite | Self::Direct | Self::Normal | Self::Left
+                )
             }
             Self::Left => {
-                matches!(category, Self::Favorite | Self::Normal | Self::LowPriority)
+                matches!(
+                    category,
+                    Self::Favorite | Self::Direct | Self::Normal | Self::LowPriority
+                )
             }
             Self::Outdated => false,
             Self::Space => false,
+            Self::Direct => {
+                matches!(
+                    category,
+                    Self::Favorite | Self::Normal | Self::LowPriority | Self::Left
+                )
+            }
         }
     }
 }
@@ -83,6 +103,7 @@ impl TryFrom<&CategoryType> for RoomType {
                 Err("CategoryType::VerificationRequest cannot be a RoomType")
             }
             CategoryType::Space => Ok(Self::Space),
+            CategoryType::Direct => Ok(Self::Direct),
         }
     }
 }
diff --git a/src/session/sidebar/category_type.rs b/src/session/sidebar/category_type.rs
index 4de7cc579..00cadc16c 100644
--- a/src/session/sidebar/category_type.rs
+++ b/src/session/sidebar/category_type.rs
@@ -16,6 +16,7 @@ pub enum CategoryType {
     Left = 5,
     Outdated = 6,
     Space = 7,
+    Direct = 8,
 }
 
 impl Default for CategoryType {
@@ -37,6 +38,7 @@ impl ToString for CategoryType {
             // Translators: This shouldn't ever be visible to the user,
             CategoryType::Outdated => gettext("Outdated"),
             CategoryType::Space => gettext("Spaces"),
+            CategoryType::Direct => gettext("People"),
         }
     }
 }
@@ -57,6 +59,7 @@ impl From<&RoomType> for CategoryType {
             RoomType::Left => Self::Left,
             RoomType::Outdated => Self::Outdated,
             RoomType::Space => Self::Space,
+            RoomType::Direct => Self::Direct,
         }
     }
 }
diff --git a/src/session/sidebar/item_list.rs b/src/session/sidebar/item_list.rs
index ffb7b3354..4b7a26002 100644
--- a/src/session/sidebar/item_list.rs
+++ b/src/session/sidebar/item_list.rs
@@ -12,7 +12,7 @@ mod imp {
 
     #[derive(Debug, Default)]
     pub struct ItemList {
-        pub list: OnceCell<[SidebarItem; 8]>,
+        pub list: OnceCell<[SidebarItem; 9]>,
         pub room_list: OnceCell<RoomList>,
         pub verification_list: OnceCell<VerificationList>,
         /// The `CategoryType` to show all compatible categories for.
@@ -90,11 +90,12 @@ mod imp {
             let room_list = obj.room_list();
             let verification_list = obj.verification_list();
 
-            let list: [SidebarItem; 8] = [
+            let list: [SidebarItem; 9] = [
                 Entry::new(EntryType::Explore).upcast(),
                 Category::new(CategoryType::VerificationRequest, verification_list).upcast(),
                 Category::new(CategoryType::Invited, room_list).upcast(),
                 Category::new(CategoryType::Favorite, room_list).upcast(),
+                Category::new(CategoryType::Direct, room_list).upcast(),
                 Category::new(CategoryType::Normal, room_list).upcast(),
                 Category::new(CategoryType::LowPriority, room_list).upcast(),
                 Category::new(CategoryType::Left, room_list).upcast(),
diff --git a/src/session/sidebar/room_row.rs b/src/session/sidebar/room_row.rs
index 80b27143d..13a97a46f 100644
--- a/src/session/sidebar/room_row.rs
+++ b/src/session/sidebar/room_row.rs
@@ -39,7 +39,7 @@ mod imp {
             klass.set_accessible_role(gtk::AccessibleRole::Group);
 
             klass.install_action("room-row.accept-invite", None, move |widget, _, _| {
-                widget.room().unwrap().set_category(RoomType::Normal)
+                widget.set_room_as_normal_or_direct();
             });
             klass.install_action("room-row.reject-invite", None, move |widget, _, _| {
                 widget.room().unwrap().set_category(RoomType::Left)
@@ -54,12 +54,15 @@ mod imp {
             klass.install_action("room-row.set-lowpriority", None, move |widget, _, _| {
                 widget.room().unwrap().set_category(RoomType::LowPriority);
             });
+            klass.install_action("room-row.set-direct", None, move |widget, _, _| {
+                widget.room().unwrap().set_category(RoomType::Direct);
+            });
 
             klass.install_action("room-row.leave", None, move |widget, _, _| {
                 widget.room().unwrap().set_category(RoomType::Left);
             });
             klass.install_action("room-row.join", None, move |widget, _, _| {
-                widget.room().unwrap().set_category(RoomType::Normal)
+                widget.set_room_as_normal_or_direct();
             });
             klass.install_action("room-row.forget", None, move |widget, _, _| {
                 widget.room().unwrap().forget();
@@ -250,6 +253,7 @@ impl RoomRow {
                     self.action_set_enabled("room-row.leave", false);
                     self.action_set_enabled("room-row.join", false);
                     self.action_set_enabled("room-row.forget", false);
+                    self.action_set_enabled("room-row.set-direct", false);
                     return;
                 }
                 RoomType::Favorite => {
@@ -261,6 +265,7 @@ impl RoomRow {
                     self.action_set_enabled("room-row.leave", true);
                     self.action_set_enabled("room-row.join", false);
                     self.action_set_enabled("room-row.forget", false);
+                    self.action_set_enabled("room-row.set-direct", true);
                     return;
                 }
                 RoomType::Normal => {
@@ -272,6 +277,7 @@ impl RoomRow {
                     self.action_set_enabled("room-row.leave", true);
                     self.action_set_enabled("room-row.join", false);
                     self.action_set_enabled("room-row.forget", false);
+                    self.action_set_enabled("room-row.set-direct", true);
                     return;
                 }
                 RoomType::LowPriority => {
@@ -283,6 +289,7 @@ impl RoomRow {
                     self.action_set_enabled("room-row.leave", true);
                     self.action_set_enabled("room-row.join", false);
                     self.action_set_enabled("room-row.forget", false);
+                    self.action_set_enabled("room-row.set-direct", true);
                     return;
                 }
                 RoomType::Left => {
@@ -294,10 +301,23 @@ impl RoomRow {
                     self.action_set_enabled("room-row.leave", false);
                     self.action_set_enabled("room-row.join", true);
                     self.action_set_enabled("room-row.forget", true);
+                    self.action_set_enabled("room-row.set-direct", false);
                     return;
                 }
                 RoomType::Outdated => {}
                 RoomType::Space => {}
+                RoomType::Direct => {
+                    self.action_set_enabled("room-row.accept-invite", false);
+                    self.action_set_enabled("room-row.reject-invite", false);
+                    self.action_set_enabled("room-row.set-favorite", true);
+                    self.action_set_enabled("room-row.set-normal", true);
+                    self.action_set_enabled("room-row.set-lowpriority", true);
+                    self.action_set_enabled("room-row.leave", true);
+                    self.action_set_enabled("room-row.join", false);
+                    self.action_set_enabled("room-row.forget", false);
+                    self.action_set_enabled("room-row.set-direct", false);
+                    return;
+                }
             }
         }
 
@@ -309,6 +329,7 @@ impl RoomRow {
         self.action_set_enabled("room-row.leave", false);
         self.action_set_enabled("room-row.join", false);
         self.action_set_enabled("room-row.forget", false);
+        self.action_set_enabled("room-row.set-direct", false);
     }
 
     fn drag_prepare(&self, drag: &gtk::DragSource, x: f64, y: f64) -> Option<gdk::ContentProvider> {
@@ -332,6 +353,15 @@ impl RoomRow {
             .unwrap();
         self.parent().unwrap().remove_css_class("drag");
     }
+
+    fn set_room_as_normal_or_direct(&self) {
+        let room = self.room().unwrap();
+        if room.is_direct() {
+            room.set_category(RoomType::Direct);
+        } else {
+            room.set_category(RoomType::Normal);
+        }
+    }
 }
 
 impl Default for RoomRow {


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