[fractal] Initial support for being kicked



commit 250376a7bd953d480d0d50eabb39ed0e891f9d84
Author: Isaac Curtis <iicurtis outlook com>
Date:   Sat Mar 9 13:58:18 2019 -0700

    Initial support for being kicked
    
    Remove translatable from kicked dialog

 fractal-gtk/res/resources.xml            |  1 +
 fractal-gtk/res/ui/kicked_room.ui        | 55 +++++++++++++++++++++
 fractal-gtk/src/appop/room.rs            | 23 ++++++++-
 fractal-gtk/src/widgets/kicked_dialog.rs | 82 ++++++++++++++++++++++++++++++++
 fractal-gtk/src/widgets/mod.rs           |  2 +
 fractal-matrix-api/src/model/room.rs     | 43 ++++++++++++++---
 fractal-matrix-api/src/types.rs          |  1 +
 7 files changed, 199 insertions(+), 8 deletions(-)
---
diff --git a/fractal-gtk/res/resources.xml b/fractal-gtk/res/resources.xml
index ae63d0d0..9ff8b1a3 100644
--- a/fractal-gtk/res/resources.xml
+++ b/fractal-gtk/res/resources.xml
@@ -14,6 +14,7 @@
       <file preprocess="xml-stripblanks">ui/invite_user.ui</file>
       <file preprocess="xml-stripblanks">ui/join_room.ui</file>
       <file preprocess="xml-stripblanks">ui/leave_room.ui</file>
+      <file preprocess="xml-stripblanks">ui/kicked_room.ui</file>
       <file preprocess="xml-stripblanks">ui/login_flow.ui</file>
       <file preprocess="xml-stripblanks">ui/main_window.ui</file>
       <file preprocess="xml-stripblanks">ui/scroll_widget.ui</file>
diff --git a/fractal-gtk/res/ui/kicked_room.ui b/fractal-gtk/res/ui/kicked_room.ui
new file mode 100644
index 00000000..5a5a336d
--- /dev/null
+++ b/fractal-gtk/res/ui/kicked_room.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkMessageDialog" id="kicked_room_dialog">
+    <property name="can_focus">False</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="urgency_hint">True</property>
+    <property name="deletable">False</property>
+    <property name="gravity">center</property>
+    <property name="message_type">warning</property>
+    <property name="text">You have been kicked from ROOM</property>
+    <property name="secondary_text">Reason: Unknown</property>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="homogeneous">True</property>
+            <property name="layout_style">expand</property>
+            <child>
+              <object class="GtkButton" id="kicked_room_confirm">
+                <property name="label" translatable="yes">Close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <style>
+      <class name="kicked-room"/>
+    </style>
+  </object>
+</interface>
+
diff --git a/fractal-gtk/src/appop/room.rs b/fractal-gtk/src/appop/room.rs
index 418d413d..cab2daf2 100644
--- a/fractal-gtk/src/appop/room.rs
+++ b/fractal-gtk/src/appop/room.rs
@@ -18,7 +18,7 @@ use crate::actions::AppState;
 use crate::cache;
 use crate::widgets;
 
-use crate::types::{Member, Room, RoomMembership, RoomTag};
+use crate::types::{Member, Reason, Room, RoomMembership, RoomTag};
 
 use crate::util::markup_text;
 
@@ -44,6 +44,14 @@ impl AppOp {
         while let Some(room) = rooms.pop() {
             if room.membership.is_left() {
                 // removing left rooms
+                if let RoomMembership::Left(kicked) = room.membership.clone() {
+                    if let Reason::Kicked(reason, kicker) = kicked {
+                        if let Some(r) = self.rooms.get(&room.id) {
+                            let room_name = r.name.clone().unwrap_or_default();
+                            self.kicked_room(room_name, reason, kicker.alias.unwrap_or_default());
+                        }
+                    }
+                }
                 if self.active_room.as_ref().map_or(false, |x| x == &room.id) {
                     self.really_leave_active_room();
                 } else {
@@ -234,6 +242,19 @@ impl AppOp {
         }
     }
 
+    pub fn kicked_room(&self, roomid: String, reason: String, kicker: String) {
+        let parent: gtk::Window = self
+            .ui
+            .builder
+            .get_object("main_window")
+            .expect("Can't find main_window in ui file.");
+        let parent_weak = parent.downgrade();
+        let parent = upgrade_weak!(parent_weak);
+        let viewer = widgets::KickedDialog::new();
+        viewer.set_parent_window(&parent);
+        viewer.show(&roomid, &reason, &kicker);
+    }
+
     pub fn create_new_room(&mut self) {
         let name = self
             .ui
diff --git a/fractal-gtk/src/widgets/kicked_dialog.rs b/fractal-gtk/src/widgets/kicked_dialog.rs
new file mode 100644
index 00000000..910a7401
--- /dev/null
+++ b/fractal-gtk/src/widgets/kicked_dialog.rs
@@ -0,0 +1,82 @@
+use crate::i18n::i18n_f;
+use gtk;
+use gtk::prelude::*;
+
+struct Widgets {
+    msg_kicked_window: gtk::MessageDialog,
+    confirm_kicked_button: gtk::Button,
+}
+
+impl Widgets {
+    pub fn new() -> Widgets {
+        let builder = gtk::Builder::new();
+        builder
+            .add_from_resource("/org/gnome/Fractal/ui/kicked_room.ui")
+            .expect("Can't load ui file: kicked_room.ui OH NO");
+
+        let msg_kicked_window: gtk::MessageDialog = builder
+            .get_object("kicked_room_dialog")
+            .expect("Can't find kicked_room_dialog in ui file.");
+
+        let confirm_kicked_button: gtk::Button = builder
+            .get_object("kicked_room_confirm")
+            .expect("Can't find kicked_room_confirm in ui file.");
+
+        Widgets {
+            msg_kicked_window,
+            confirm_kicked_button,
+        }
+    }
+}
+
+pub struct KickedDialog {
+    widgets: Widgets,
+}
+
+impl KickedDialog {
+    pub fn new() -> KickedDialog {
+        let viewer = KickedDialog {
+            widgets: Widgets::new(),
+        };
+        viewer.connect();
+        viewer
+    }
+
+    pub fn show(&self, room_name: &str, reason: &str, kicker: &str) {
+        let text = i18n_f("You have been kicked from {}", &[room_name]);
+        self.widgets
+            .msg_kicked_window
+            .set_property_text(Some(&text));
+        let secondary_text = i18n_f("Kicked by: {}\n \"{}\"", &[kicker, reason]);
+        self.widgets
+            .msg_kicked_window
+            .set_property_secondary_text(Some(&secondary_text));
+
+        self.widgets.msg_kicked_window.show();
+    }
+
+    /* This sets the transient_for parent */
+    pub fn set_parent_window(&self, parent: &gtk::Window) {
+        self.widgets.msg_kicked_window.set_transient_for(parent);
+    }
+
+    fn connect(&self) {
+        let msg_kicked_window = self.widgets.msg_kicked_window.downgrade();
+        self.widgets
+            .confirm_kicked_button
+            .connect_clicked(move |_| {
+                upgrade_weak!(msg_kicked_window).close();
+            });
+
+        /* Close the window when the user preses ESC */
+        self.widgets
+            .msg_kicked_window
+            .connect_key_press_event(|w, k| {
+                if k.get_keyval() == gdk::enums::key::Escape {
+                    w.close();
+                }
+
+                Inhibit(true)
+            });
+    }
+}
diff --git a/fractal-gtk/src/widgets/mod.rs b/fractal-gtk/src/widgets/mod.rs
index 7cca372b..6572c7ce 100644
--- a/fractal-gtk/src/widgets/mod.rs
+++ b/fractal-gtk/src/widgets/mod.rs
@@ -6,6 +6,7 @@ pub mod error_dialog;
 pub mod file_dialog;
 pub mod image;
 mod inline_player;
+mod kicked_dialog;
 mod login;
 pub mod media_viewer;
 mod member;
@@ -32,6 +33,7 @@ pub use self::divider::NewMessageDivider;
 pub use self::error_dialog as ErrorDialog;
 pub use self::file_dialog as FileDialog;
 pub use self::inline_player::AudioPlayerWidget;
+pub use self::kicked_dialog::KickedDialog;
 pub use self::login::LoginWidget;
 pub use self::media_viewer::MediaViewer;
 pub use self::member::MemberBox;
diff --git a/fractal-matrix-api/src/model/room.rs b/fractal-matrix-api/src/model/room.rs
index c3f2151c..c23eaa9a 100644
--- a/fractal-matrix-api/src/model/room.rs
+++ b/fractal-matrix-api/src/model/room.rs
@@ -18,7 +18,7 @@ pub enum RoomMembership {
     Joined(RoomTag),
     // An invite is send by some other user
     Invited(Member),
-    Left,
+    Left(Reason),
 }
 
 impl RoomMembership {
@@ -39,7 +39,11 @@ impl RoomMembership {
     }
 
     pub fn is_left(&self) -> bool {
-        self == &RoomMembership::Left
+        if let RoomMembership::Left(_) = self {
+            true
+        } else {
+            false
+        }
     }
 
     pub fn match_joined_tag(&self, tag: RoomTag) -> bool {
@@ -57,6 +61,12 @@ impl Default for RoomMembership {
     }
 }
 
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
+pub enum Reason {
+    None,
+    Kicked(String, Member),
+}
+
 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
 pub enum RoomTag {
     None,
@@ -159,11 +169,30 @@ impl Room {
             r
         });
 
-        let left_rooms = response
-            .rooms
-            .leave
-            .keys()
-            .map(|k| Self::new(k.clone(), RoomMembership::Left));
+        let left_rooms = response.rooms.leave.iter().map(|(k, room)| {
+            let leave_id = &room.timeline.events.last().unwrap()["sender"];
+            if leave_id != userid {
+                let kick_reason = &room.timeline.events.last().unwrap()["content"]["reason"];
+                if let Some((kicker_alias, kicker_avatar)) =
+                    get_user_avatar(baseu, leave_id.as_str().unwrap_or_default()).ok()
+                {
+                    let kicker = Member {
+                        alias: Some(kicker_alias),
+                        avatar: Some(kicker_avatar),
+                        uid: String::from(leave_id.as_str().unwrap_or_default()),
+                    };
+                    let reason = Reason::Kicked(
+                        String::from(kick_reason.as_str().unwrap_or_default()),
+                        kicker,
+                    );
+                    Self::new(k.clone(), RoomMembership::Left(reason))
+                } else {
+                    Self::new(k.clone(), RoomMembership::Left(Reason::None))
+                }
+            } else {
+                Self::new(k.clone(), RoomMembership::Left(Reason::None))
+            }
+        });
 
         let invited_rooms = response.rooms.invite.iter().filter_map(|(k, room)| {
             let stevents = &room.invite_state.events;
diff --git a/fractal-matrix-api/src/types.rs b/fractal-matrix-api/src/types.rs
index 482a7b9f..eb451f2c 100644
--- a/fractal-matrix-api/src/types.rs
+++ b/fractal-matrix-api/src/types.rs
@@ -14,6 +14,7 @@ pub use crate::model::register::*;
 pub use crate::model::room::PublicRoomsFilter;
 pub use crate::model::room::PublicRoomsRequest;
 pub use crate::model::room::PublicRoomsResponse;
+pub use crate::model::room::Reason;
 pub use crate::model::room::Room;
 pub use crate::model::room::RoomList;
 pub use crate::model::room::RoomMembership;


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