diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index 6911d699..f700e4e1 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -62,6 +62,7 @@
ui/identity-verification-widget.ui
ui/qr-code-scanner.ui
ui/components-video-player.ui
+ ui/components-reaction-chooser.ui
style.css
style-dark.css
icons/scalable/actions/send-symbolic.svg
diff --git a/data/resources/style.css b/data/resources/style.css
index 18f62257..79dd4faa 100644
--- a/data/resources/style.css
+++ b/data/resources/style.css
@@ -310,8 +310,12 @@ message-reactions .toggle {
border: 1px solid @light_4;
}
-message-reactions .toggle:checked {
+message-reactions .toggle:checked,
+.reaction-chooser button:checked {
background-color: alpha(@blue_1, 0.4);
+}
+
+message-reactions .toggle:checked {
border-color: @blue_2;
}
@@ -324,6 +328,16 @@ message-reactions .reaction-count {
padding-left: 5px;
}
+.reaction-chooser {
+ margin: 5px;
+}
+
+.reaction-chooser button {
+ font-size: 1.3em;
+ -gtk-icon-size: 1.3em;
+ padding: 2px;
+}
+
.divider-row {
font-size: 0.9em;
font-weight: bold;
diff --git a/data/resources/ui/components-reaction-chooser.ui b/data/resources/ui/components-reaction-chooser.ui
new file mode 100644
index 00000000..5e1caa51
--- /dev/null
+++ b/data/resources/ui/components-reaction-chooser.ui
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/resources/ui/event-menu.ui b/data/resources/ui/event-menu.ui
index 4970f0e6..48ebaa3d 100644
--- a/data/resources/ui/event-menu.ui
+++ b/data/resources/ui/event-menu.ui
@@ -1,6 +1,11 @@
+
diff --git a/src/components/context_menu_bin.rs b/src/components/context_menu_bin.rs
index 0c44e3bb..3a47a6fb 100644
--- a/src/components/context_menu_bin.rs
+++ b/src/components/context_menu_bin.rs
@@ -57,6 +57,11 @@ mod imp {
"context-menu.activate",
None,
);
+
+ klass.install_action("context-menu.close", None, move |widget, _, _| {
+ let priv_ = imp::ContextMenuBin::from_instance(widget);
+ priv_.popover.popdown();
+ });
}
fn instance_init(obj: &InitializingObject) {
@@ -171,11 +176,19 @@ pub trait ContextMenuBinExt: 'static {
/// Get the `MenuModel` used in the context menu.
fn context_menu(&self) -> Option;
+
+ /// Get the `PopoverMenu` used in the context menu.
+ fn popover(&self) -> >k::PopoverMenu;
}
impl> ContextMenuBinExt for O {
fn set_context_menu(&self, menu: Option<&gio::MenuModel>) {
let priv_ = imp::ContextMenuBin::from_instance(self.upcast_ref());
+
+ if self.context_menu().as_ref() == menu {
+ return;
+ }
+
priv_.popover.set_menu_model(menu);
self.notify("context-menu");
}
@@ -184,6 +197,11 @@ impl> ContextMenuBinExt for O {
let priv_ = imp::ContextMenuBin::from_instance(self.upcast_ref());
priv_.popover.menu_model()
}
+
+ fn popover(&self) -> >k::PopoverMenu {
+ let priv_ = imp::ContextMenuBin::from_instance(self.upcast_ref());
+ &priv_.popover
+ }
}
pub trait ContextMenuBinImpl: BinImpl {}
diff --git a/src/components/mod.rs b/src/components/mod.rs
index 5c005a97..81319af7 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -7,6 +7,7 @@ mod in_app_notification;
mod label_with_widgets;
mod loading_listbox_row;
mod pill;
+mod reaction_chooser;
mod room_title;
mod spinner_button;
mod video_player;
@@ -20,6 +21,7 @@ pub use self::in_app_notification::InAppNotification;
pub use self::label_with_widgets::LabelWithWidgets;
pub use self::loading_listbox_row::LoadingListBoxRow;
pub use self::pill::Pill;
+pub use self::reaction_chooser::ReactionChooser;
pub use self::room_title::RoomTitle;
pub use self::spinner_button::SpinnerButton;
pub use self::video_player::VideoPlayer;
diff --git a/src/components/reaction_chooser.rs b/src/components/reaction_chooser.rs
new file mode 100644
index 00000000..211f4a5c
--- /dev/null
+++ b/src/components/reaction_chooser.rs
@@ -0,0 +1,184 @@
+use adw::subclass::prelude::*;
+use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*, CompositeTemplate};
+
+use crate::session::room::ReactionList;
+
+struct ReactionGridItem<'a> {
+ key: &'a str,
+ column: i32,
+ row: i32,
+}
+
+static QUICK_REACTIONS: &[ReactionGridItem] = &[
+ ReactionGridItem {
+ key: "👍️",
+ column: 0,
+ row: 0,
+ },
+ ReactionGridItem {
+ key: "👎️",
+ column: 1,
+ row: 0,
+ },
+ ReactionGridItem {
+ key: "😄",
+ column: 2,
+ row: 0,
+ },
+ ReactionGridItem {
+ key: "🎉",
+ column: 3,
+ row: 0,
+ },
+ ReactionGridItem {
+ key: "😕",
+ column: 0,
+ row: 1,
+ },
+ ReactionGridItem {
+ key: "❤️",
+ column: 1,
+ row: 1,
+ },
+ ReactionGridItem {
+ key: "🚀",
+ column: 2,
+ row: 1,
+ },
+];
+
+mod imp {
+
+ use super::*;
+ use glib::subclass::InitializingObject;
+ use std::{cell::RefCell, collections::HashMap};
+
+ #[derive(Debug, Default, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/components-reaction-chooser.ui")]
+ pub struct ReactionChooser {
+ /// The `ReactionList` associated to this chooser
+ pub reactions: RefCell