[fractal] Assimilate room context menus



commit 8ec00cfc9fa04f98dc55a363b837fb6afdf52665
Author: Sonja Heinze <sonjaleaheinze gmail com>
Date:   Thu Feb 20 17:47:54 2020 +0100

    Assimilate room context menus
    
    Before, the three dot context menu button in the media viewer only provided
    the option "Save as". Now, it provides the same popover, right click on
    the corresponding media widget in the room history does. That is the
    same popover as the one the three dot context menu button of videos in
    the room history provides.

 fractal-gtk/res/resources.xml                      |   1 -
 fractal-gtk/res/ui/media_viewer.ui                 |   1 -
 fractal-gtk/res/ui/media_viewer_menu.ui            |  39 -------
 fractal-gtk/res/ui/message_menu.ui                 |  16 +--
 fractal-gtk/src/actions/global.rs                  |   3 +-
 .../src/actions/{room_history.rs => message.rs}    |  44 +++++++-
 fractal-gtk/src/actions/mod.rs                     |   4 +-
 fractal-gtk/src/appop/media_viewer.rs              |  19 ++++
 fractal-gtk/src/appop/room.rs                      |   4 +-
 fractal-gtk/src/meson.build                        |   2 +-
 fractal-gtk/src/widgets/media_viewer.rs            | 116 +++++++++------------
 fractal-gtk/src/widgets/message.rs                 |  18 ++--
 fractal-gtk/src/widgets/message_menu.rs            |  12 ++-
 fractal-gtk/src/widgets/room_history.rs            |   2 +-
 14 files changed, 140 insertions(+), 141 deletions(-)
---
diff --git a/fractal-gtk/res/resources.xml b/fractal-gtk/res/resources.xml
index 9ff8b1a3..b835a9af 100644
--- a/fractal-gtk/res/resources.xml
+++ b/fractal-gtk/res/resources.xml
@@ -28,7 +28,6 @@
       <file preprocess="xml-stripblanks">ui/password_dialog.ui</file>
       <file preprocess="xml-stripblanks">ui/markdown_popover.ui</file>
       <file preprocess="xml-stripblanks">ui/media_viewer.ui</file>
-      <file preprocess="xml-stripblanks">ui/media_viewer_menu.ui</file>
       <file preprocess="xml-stripblanks">ui/server_chooser_menu.ui</file>
       <file preprocess="xml-stripblanks">ui/msg_src_window.ui</file>
   </gresource>
diff --git a/fractal-gtk/res/ui/media_viewer.ui b/fractal-gtk/res/ui/media_viewer.ui
index b59ef33a..96a2599f 100644
--- a/fractal-gtk/res/ui/media_viewer.ui
+++ b/fractal-gtk/res/ui/media_viewer.ui
@@ -255,7 +255,6 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
-            <property name="popover">media_viewer_popover</property>
             <child>
               <object class="GtkImage">
                 <property name="visible">True</property>
diff --git a/fractal-gtk/res/ui/message_menu.ui b/fractal-gtk/res/ui/message_menu.ui
index 5dda5fd7..a64616a3 100644
--- a/fractal-gtk/res/ui/message_menu.ui
+++ b/fractal-gtk/res/ui/message_menu.ui
@@ -18,7 +18,7 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
-            <property name="action_name">room_history.reply</property>
+            <property name="action_name">message.reply</property>
             <property name="text" translatable="yes">Reply</property>
           </object>
           <packing>
@@ -32,7 +32,7 @@
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
             <property name="text" translatable="yes">Open With…</property>
-            <property name="action_name">room_history.open_with</property>
+            <property name="action_name">message.open_with</property>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -45,7 +45,7 @@
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
             <property name="text" translatable="yes">Save Image As…</property>
-            <property name="action_name">room_history.save_as</property>
+            <property name="action_name">message.save_as</property>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -58,7 +58,7 @@
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
             <property name="text" translatable="yes">Save Video As…</property>
-            <property name="action_name">room_history.save_as</property>
+            <property name="action_name">message.save_as</property>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -71,7 +71,7 @@
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
             <property name="text" translatable="yes">Copy Image</property>
-            <property name="action_name">room_history.copy_image</property>
+            <property name="action_name">message.copy_image</property>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -97,7 +97,7 @@
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
             <property name="text" translatable="yes">Copy Text</property>
-            <property name="action_name">room_history.copy_text</property>
+            <property name="action_name">message.copy_text</property>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -110,7 +110,7 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
-            <property name="action_name">room_history.show_source</property>
+            <property name="action_name">message.show_source</property>
             <property name="text" translatable="yes">View Source</property>
           </object>
           <packing>
@@ -135,7 +135,7 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
-            <property name="action_name">room_history.delete</property>
+            <property name="action_name">message.delete</property>
             <property name="text" translatable="yes">Delete Message</property>
           </object>
           <packing>
diff --git a/fractal-gtk/src/actions/global.rs b/fractal-gtk/src/actions/global.rs
index 09280f94..06187cfc 100644
--- a/fractal-gtk/src/actions/global.rs
+++ b/fractal-gtk/src/actions/global.rs
@@ -1,6 +1,5 @@
 use fractal_api::clone;
 use log::{debug, info};
-use std::cell::RefCell;
 use std::convert::TryInto;
 use std::rc::Rc;
 use std::sync::{Arc, Mutex};
@@ -89,7 +88,7 @@ pub fn new(app: &gtk::Application, op: &Arc<Mutex<AppOp>>) {
     let directory = SimpleAction::new("directory", None);
     //TODO: use roomid as value
     let room_settings = SimpleAction::new("open-room-settings", None);
-    // TODO: send file should be a room_history action
+    // TODO: send file should be a message action
     let send_file = SimpleAction::new("send-file", None);
 
     let previous_room = SimpleAction::new("previous-room", None);
diff --git a/fractal-gtk/src/actions/room_history.rs b/fractal-gtk/src/actions/message.rs
similarity index 84%
rename from fractal-gtk/src/actions/room_history.rs
rename to fractal-gtk/src/actions/message.rs
index 27c5a79b..26d61cda 100644
--- a/fractal-gtk/src/actions/room_history.rs
+++ b/fractal-gtk/src/actions/message.rs
@@ -2,12 +2,15 @@ use fractal_api::clone;
 use fractal_api::identifiers::RoomId;
 use fractal_api::r0::AccessToken;
 use log::error;
+use std::cell::RefCell;
 use std::convert::TryFrom;
 use std::fs;
+use std::rc::Rc;
 use std::sync::mpsc::channel;
 use std::sync::mpsc::TryRecvError;
 use std::sync::mpsc::{Receiver, Sender};
 
+use crate::actions::AppState;
 use crate::backend::BKCommand;
 use crate::error::Error;
 use crate::i18n::i18n;
@@ -15,6 +18,7 @@ use crate::types::Message;
 use crate::uibuilder::UI;
 use crate::App;
 use fractal_api::url::Url;
+use gio::ActionGroupExt;
 use gio::ActionMapExt;
 use gio::SimpleAction;
 use gio::SimpleActionGroup;
@@ -32,6 +36,7 @@ pub fn new(
     server_url: Url,
     access_token: AccessToken,
     ui: UI,
+    back_history: Rc<RefCell<Vec<AppState>>>,
 ) -> gio::SimpleActionGroup {
     let actions = SimpleActionGroup::new();
     /* Action for each message */
@@ -74,7 +79,26 @@ pub fn new(
     });
 
     let msg_entry = ui.sventry.view.downgrade();
+    let back_weak = Rc::downgrade(&back_history);
+    let window_weak = ui
+        .builder
+        .get_object::<gtk::ApplicationWindow>("main_window")
+        .expect("Couldn't find main_window in ui file.")
+        .downgrade();
     reply.connect_activate(move |_, data| {
+        let back_history = upgrade_weak!(back_weak);
+        let state = back_history.borrow().last().map(|state| state.clone());
+        match state {
+            Some(AppState::MediaViewer) => {
+                let window = upgrade_weak!(window_weak);
+                if let Some(action_group) = window.get_action_group("app") {
+                    action_group.activate_action("back", None);
+                } else {
+                    error!("The action group app is not attached to the main window.");
+                }
+            }
+            _ => {}
+        };
         let msg_entry = upgrade_weak!(msg_entry);
         if let Some(buffer) = msg_entry.get_buffer() {
             let mut start = buffer.get_start_iter();
@@ -87,7 +111,6 @@ pub fn new(
                     .join("\n")
                     + "\n"
                     + "\n";
-
                 buffer.insert(&mut start, &quote);
                 msg_entry.grab_focus();
             }
@@ -192,7 +215,26 @@ pub fn new(
     let b = backend.clone();
     let u = server_url.clone();
     let tk = access_token.clone();
+    let back_weak = Rc::downgrade(&back_history);
+    let window_weak = ui
+        .builder
+        .get_object::<gtk::ApplicationWindow>("main_window")
+        .expect("Couldn't find main_window in ui file.")
+        .downgrade();
     delete.connect_activate(move |_, data| {
+        let back_history = upgrade_weak!(back_weak);
+        let state = back_history.borrow().last().map(|state| state.clone());
+        match state {
+            Some(AppState::MediaViewer) => {
+                let window = upgrade_weak!(window_weak);
+                if let Some(action_group) = window.get_action_group("app") {
+                    action_group.activate_action("back", None);
+                } else {
+                    error!("The action group app is not attached to the main window.");
+                }
+            }
+            _ => {}
+        };
         if let Some(m) = get_message(data) {
             let _ = b.send(BKCommand::SendMsgRedaction(u.clone(), tk.clone(), m));
         }
diff --git a/fractal-gtk/src/actions/mod.rs b/fractal-gtk/src/actions/mod.rs
index 2f33eedd..29a5c4fc 100644
--- a/fractal-gtk/src/actions/mod.rs
+++ b/fractal-gtk/src/actions/mod.rs
@@ -7,7 +7,7 @@ use gtk::WidgetExt;
 pub mod account_settings;
 pub mod global;
 pub mod login;
-pub mod room_history;
+pub mod message;
 pub mod room_settings;
 
 pub use self::account_settings as AccountSettings;
@@ -16,7 +16,7 @@ pub use self::global::activate_action;
 pub use self::global::AppState;
 pub use self::login as Login;
 pub use self::login::LoginState;
-pub use self::room_history as RoomHistory;
+pub use self::message as Message;
 pub use self::room_settings as RoomSettings;
 
 #[derive(Debug, Clone, PartialEq)]
diff --git a/fractal-gtk/src/appop/media_viewer.rs b/fractal-gtk/src/appop/media_viewer.rs
index bcfc6261..2db26d5a 100644
--- a/fractal-gtk/src/appop/media_viewer.rs
+++ b/fractal-gtk/src/appop/media_viewer.rs
@@ -1,9 +1,12 @@
 use gtk;
 use gtk::prelude::*;
 
+use log::error;
 use std::cell::RefCell;
 use std::rc::Rc;
 
+use crate::actions;
+
 use crate::appop::AppOp;
 use crate::appop::AppState;
 
@@ -42,10 +45,26 @@ impl AppOp {
                 &msg,
                 login_data.server_url,
                 login_data.access_token,
+                login_data.uid,
             );
             panel.display_media_viewer(msg);
             let (body, header) = panel.create()?;
 
+            if let Some(login_data) = self.login_data.clone() {
+                let back_history = self.room_back_history.clone();
+                let actions = actions::Message::new(
+                    self.backend.clone(),
+                    login_data.server_url,
+                    login_data.access_token,
+                    self.ui.clone(),
+                    back_history,
+                );
+                header.insert_action_group("message", Some(&actions));
+                body.insert_action_group("message", Some(&actions));
+            } else {
+                error!("No login data!");
+            }
+
             /* remove old panel */
             if let Some(widget) = stack.get_child_by_name("media-viewer") {
                 stack.remove(&widget);
diff --git a/fractal-gtk/src/appop/room.rs b/fractal-gtk/src/appop/room.rs
index 383f2854..a7c7f5c8 100644
--- a/fractal-gtk/src/appop/room.rs
+++ b/fractal-gtk/src/appop/room.rs
@@ -253,11 +253,13 @@ impl AppOp {
             history.destroy();
         }
 
-        let actions = actions::RoomHistory::new(
+        let back_history = self.room_back_history.clone();
+        let actions = actions::Message::new(
             self.backend.clone(),
             login_data.server_url,
             login_data.access_token,
             self.ui.clone(),
+            back_history,
         );
         let history = widgets::RoomHistory::new(actions, active_room.clone(), self);
         self.history = if let Some(mut history) = history {
diff --git a/fractal-gtk/src/meson.build b/fractal-gtk/src/meson.build
index 8fbd197d..68d12237 100644
--- a/fractal-gtk/src/meson.build
+++ b/fractal-gtk/src/meson.build
@@ -50,7 +50,7 @@ app_sources = files(
   'actions/global.rs',
   'actions/login.rs',
   'actions/mod.rs',
-  'actions/room_history.rs',
+  'actions/message.rs',
   'actions/room_settings.rs',
   'app/connect/account.rs',
   'app/connect/autocomplete.rs',
diff --git a/fractal-gtk/src/widgets/media_viewer.rs b/fractal-gtk/src/widgets/media_viewer.rs
index 1ead9618..b43c37ec 100644
--- a/fractal-gtk/src/widgets/media_viewer.rs
+++ b/fractal-gtk/src/widgets/media_viewer.rs
@@ -4,10 +4,11 @@ use gdk;
 
 use fragile::Fragile;
 use std::cell::RefCell;
+use std::collections::HashMap;
 use std::rc::Rc;
 
 use crate::i18n::i18n;
-use dirs;
+use fractal_api::identifiers::UserId;
 use fractal_api::url::Url;
 use gdk::*;
 use glib;
@@ -16,15 +17,14 @@ use glib::source::Continue;
 use gtk;
 use gtk::prelude::*;
 use gtk::Overlay;
-use gtk::ResponseType;
 
 use crate::types::Message;
 use crate::types::Room;
 
-use std::fs;
-
 use crate::backend::BKCommand;
+use crate::uitypes::RowType;
 use crate::widgets::image;
+use crate::widgets::message_menu::MessageMenu;
 use crate::widgets::ErrorDialog;
 use crate::widgets::PlayerExt;
 use crate::widgets::{MediaPlayer, VideoPlayerWidget};
@@ -131,6 +131,8 @@ struct Data {
     backend: Sender<BKCommand>,
     server_url: Url,
     access_token: AccessToken,
+    uid: UserId,
+    admins: HashMap<UserId, i32>,
 
     widget: Widget,
     media_list: Vec<Message>,
@@ -154,6 +156,8 @@ impl Data {
         current_media_index: usize,
         main_window: gtk::Window,
         builder: gtk::Builder,
+        uid: UserId,
+        admins: HashMap<UserId, i32>,
     ) -> Data {
         let is_fullscreen = main_window
             .clone()
@@ -173,6 +177,8 @@ impl Data {
             backend,
             server_url,
             access_token,
+            uid,
+            admins,
             main_window,
             signal_id: None,
             is_fullscreen,
@@ -180,23 +186,6 @@ impl Data {
         }
     }
 
-    pub fn save_media(&self) {
-        let local_path = match &self.widget {
-            Widget::Image(image) => image.local_path.lock().unwrap().clone(),
-            Widget::Video(widget) => widget.player.get_local_path_access().borrow().clone(),
-            Widget::None => None,
-        };
-        if let Some(local_path) = local_path {
-            save_file_as(
-                &self.main_window,
-                local_path,
-                self.media_list[self.current_media_index].body.clone(),
-            );
-        } else {
-            ErrorDialog::new(false, &i18n("Media is not loaded yet."));
-        }
-    }
-
     pub fn enter_full_screen(&mut self) {
         self.main_window.fullscreen();
         self.is_fullscreen = true;
@@ -394,6 +383,8 @@ impl Data {
             }
             _ => {}
         }
+
+        self.set_context_menu_popover(&msg);
         self.set_nav_btn_visibility();
     }
 
@@ -612,6 +603,25 @@ impl Data {
 
         widget
     }
+
+    fn set_context_menu_popover(&self, msg: &Message) {
+        let mtype = match msg.mtype.as_ref() {
+            "m.image" => RowType::Image,
+            "m.video" => RowType::Video,
+            _ => {
+                panic!("Data in the media viewer has to be of type image or video.");
+            }
+        };
+        let admin = self.admins.get(&self.uid).map(|n| *n).unwrap_or_default();
+        let redactable = admin != 0 || self.uid == msg.sender;
+        let menu = MessageMenu::new(msg.id.as_str(), &mtype, &redactable, None, None);
+        let popover = &menu.get_popover();
+        let menu_button = self
+            .builder
+            .get_object::<gtk::MenuButton>("media_viewer_menu_button")
+            .expect("Can't find media_viewer_menu_button in ui file.");
+        menu_button.set_popover(Some(popover));
+    }
 }
 
 impl Drop for Data {
@@ -636,11 +646,9 @@ impl MediaViewer {
         current_media_msg: &Message,
         server_url: Url,
         access_token: AccessToken,
+        uid: UserId,
     ) -> MediaViewer {
         let builder = gtk::Builder::new();
-        builder
-            .add_from_resource("/org/gnome/Fractal/ui/media_viewer_menu.ui")
-            .expect("Can't load ui file: media_viewer_menu.ui");
         builder
             .add_from_resource("/org/gnome/Fractal/ui/media_viewer.ui")
             .expect("Can't load ui file: media_viewer.ui");
@@ -666,6 +674,8 @@ impl MediaViewer {
                 current_media_index,
                 main_window,
                 builder.clone(),
+                uid,
+                room.admins.clone(),
             ))),
             builder,
             backend,
@@ -731,6 +741,8 @@ impl MediaViewer {
             }
             _ => {}
         }
+
+        self.data.borrow().set_context_menu_popover(&media_msg);
         self.data.borrow_mut().set_nav_btn_visibility();
     }
 
@@ -753,17 +765,6 @@ impl MediaViewer {
                 }
             });
         });
-
-        let save_as_button = self
-            .builder
-            .get_object::<gtk::ModelButton>("save_as_button")
-            .expect("Cant find save_as_button in ui file.");
-        let data_weak = Rc::downgrade(&self.data);
-        save_as_button.connect_clicked(move |_| {
-            data_weak.upgrade().map(|data| {
-                data.borrow().save_media();
-            });
-        });
     }
 
     pub fn connect_media_viewer_box(&self) {
@@ -873,13 +874,18 @@ impl MediaViewer {
                 let sid = gtk::timeout_add(
                     1000,
                     clone!(ui, header_hovered, nav_hovered, source_id => move || {
-                        if !*header_hovered.lock().unwrap() {
-                            let headerbar_revealer = ui
-                                .get_object::<gtk::Revealer>("headerbar_revealer")
-                                .expect("Can't find headerbar_revealer in ui file.");
-                            headerbar_revealer.set_reveal_child(false);
-                        }
-
+                        let menu_popover_is_visible = ui
+                        .get_object::<gtk::MenuButton>("media_viewer_menu_button")
+                        .expect("Can't find headerbar_revealer in ui file.")
+                        .get_popover()
+                        .filter(|p| p.get_visible())
+                        .is_some();
+                            if !*header_hovered.lock().unwrap() && !menu_popover_is_visible {
+                                let headerbar_revealer = ui
+                                    .get_object::<gtk::Revealer>("headerbar_revealer")
+                                    .expect("Can't find headerbar_revealer in ui file.");
+                                headerbar_revealer.set_reveal_child(false);
+                            }
                         if !*nav_hovered.lock().unwrap() {
                             let previous_media_revealer = ui
                                 .get_object::<gtk::Revealer>("previous_media_revealer")
@@ -1099,29 +1105,3 @@ fn load_more_media(data: Rc<RefCell<Data>>, builder: gtk::Builder, backend: Send
         }
     });
 }
-
-/* FIXME: The following two functions should be moved to a different file,
- * so that they can be used again in different locations */
-fn save_file_as(main_window: &gtk::Window, src: String, name: String) {
-    let file_chooser = gtk::FileChooserNative::new(
-        Some(i18n("Save media as").as_str()),
-        Some(main_window),
-        gtk::FileChooserAction::Save,
-        Some(i18n("_Save").as_str()),
-        Some(i18n("_Cancel").as_str()),
-    );
-
-    file_chooser.set_current_folder(dirs::download_dir().unwrap_or_default());
-    file_chooser.set_current_name(&name);
-
-    file_chooser.connect_response(move |fcd, res| {
-        if ResponseType::from(res) == ResponseType::Accept {
-            if let Err(_) = fs::copy(src.clone(), fcd.get_filename().unwrap_or_default()) {
-                let err = i18n("Could not save the file");
-                ErrorDialog::new(false, &err);
-            }
-        }
-    });
-
-    file_chooser.run();
-}
diff --git a/fractal-gtk/src/widgets/message.rs b/fractal-gtk/src/widgets/message.rs
index 9df9b563..bf8093e9 100644
--- a/fractal-gtk/src/widgets/message.rs
+++ b/fractal-gtk/src/widgets/message.rs
@@ -415,7 +415,7 @@ impl MessageBox {
 
         let data = glib::Variant::from(msg.id.as_str());
         download_btn.set_action_target_value(Some(&data));
-        download_btn.set_action_name(Some("room_history.save_as"));
+        download_btn.set_action_name(Some("message.save_as"));
 
         let control_box = PlayerExt::get_controls_container(&player)
             .expect("Every AudioPlayer must have controls.");
@@ -489,13 +489,7 @@ impl MessageBox {
 
         let id = msg.id.clone();
         let redactable = msg.redactable.clone();
-        let menu = MessageMenu::new(
-            id.as_str(),
-            &RowType::Video,
-            &redactable,
-            &self.eventbox,
-            self.eventbox.upcast_ref::<gtk::Widget>(),
-        );
+        let menu = MessageMenu::new(id.as_str(), &RowType::Video, &redactable, None, None);
         menu_button.set_popover(Some(&menu.get_popover()));
 
         bx.pack_start(&overlay, true, true, 0);
@@ -527,7 +521,7 @@ impl MessageBox {
 
         let data = glib::Variant::from(msg.id.as_str());
         download_btn.set_action_target_value(Some(&data));
-        download_btn.set_action_name(Some("room_history.save_as"));
+        download_btn.set_action_name(Some("message.save_as"));
 
         let open_btn = gtk::Button::new_from_icon_name(
             Some("document-open-symbolic"),
@@ -537,7 +531,7 @@ impl MessageBox {
 
         let data = glib::Variant::from(msg.id.as_str());
         open_btn.set_action_target_value(Some(&data));
-        open_btn.set_action_name(Some("room_history.open_with"));
+        open_btn.set_action_name(Some("message.open_with"));
 
         btn_bx.pack_start(&open_btn, false, false, 0);
         btn_bx.pack_start(&download_btn, false, false, 0);
@@ -632,7 +626,7 @@ impl MessageBox {
         widget.connect_button_press_event(move |w, e| {
             if e.get_button() == 3 {
                 let eventbox = upgrade_weak!(evbox, gtk::Inhibit(false));
-                MessageMenu::new(i.as_str(), &mtype, &redactable, &eventbox, w);
+                MessageMenu::new(i.as_str(), &mtype, &redactable, Some(&eventbox), Some(w));
                 Inhibit(true)
             } else {
                 Inhibit(false)
@@ -644,7 +638,7 @@ impl MessageBox {
             let eventbox = upgrade_weak!(eventbox_weak);
             let widget = upgrade_weak!(widget_weak);
 
-            MessageMenu::new(&id, &mtype, &redactable, &eventbox, &widget);
+            MessageMenu::new(&id, &mtype, &redactable, Some(&eventbox), Some(&widget));
         });
         None
     }
diff --git a/fractal-gtk/src/widgets/message_menu.rs b/fractal-gtk/src/widgets/message_menu.rs
index a4d7fad6..c1daf642 100644
--- a/fractal-gtk/src/widgets/message_menu.rs
+++ b/fractal-gtk/src/widgets/message_menu.rs
@@ -125,16 +125,20 @@ impl MessageMenu {
         id: &str,
         mtype: &RowType,
         redactable: &bool,
-        widget: &gtk::EventBox,
-        label: &gtk::Widget,
+        widget: Option<&gtk::EventBox>,
+        label: Option<&gtk::Widget>,
     ) -> MessageMenu {
         let menu = MessageMenu {
             widgets: Widgets::new(id, mtype, redactable),
         };
         /* Copy selected text works a little different then the other actions, because it need the
          * label */
-        menu.connect_copy_selected_text(label);
-        menu.show(widget);
+        if let Some(label) = label {
+            menu.connect_copy_selected_text(label);
+        }
+        if let Some(widget) = widget {
+            menu.show(widget);
+        }
         menu
     }
 
diff --git a/fractal-gtk/src/widgets/room_history.rs b/fractal-gtk/src/widgets/room_history.rs
index 9fea44d4..e8692dcb 100644
--- a/fractal-gtk/src/widgets/room_history.rs
+++ b/fractal-gtk/src/widgets/room_history.rs
@@ -278,7 +278,7 @@ impl RoomHistory {
         let listbox = scroll.get_listbox();
 
         /* Add the action groupe to the room_history */
-        listbox.insert_action_group("room_history", Some(&actions));
+        listbox.insert_action_group("message", Some(&actions));
         let mut rh = RoomHistory {
             rows: Rc::new(RefCell::new(List::new(scroll, listbox))),
             backend: op.backend.clone(),


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