fractal/session/view/content/room_history/message_row/
reply.rs

1use adw::{prelude::*, subclass::prelude::*};
2use gtk::{glib, CompositeTemplate};
3
4use crate::session::model::User;
5
6mod imp {
7    use std::cell::{Cell, RefCell};
8
9    use glib::subclass::InitializingObject;
10
11    use super::*;
12
13    #[derive(Debug, Default, CompositeTemplate, glib::Properties)]
14    #[template(
15        resource = "/org/gnome/Fractal/ui/session/view/content/room_history/message_row/reply.ui"
16    )]
17    #[properties(wrapper_type = super::MessageReply)]
18    pub struct MessageReply {
19        #[template_child]
20        related_content_sender: TemplateChild<gtk::Label>,
21        #[template_child]
22        related_content: TemplateChild<adw::Bin>,
23        #[template_child]
24        content: TemplateChild<adw::Bin>,
25        /// Whether to show the header of the related content.
26        #[property(get, set = Self::set_show_related_content_header, explicit_notify)]
27        show_related_content_header: Cell<bool>,
28        related_display_name_binding: RefCell<Option<glib::Binding>>,
29    }
30
31    #[glib::object_subclass]
32    impl ObjectSubclass for MessageReply {
33        const NAME: &'static str = "ContentMessageReply";
34        type Type = super::MessageReply;
35        type ParentType = gtk::Grid;
36
37        fn class_init(klass: &mut Self::Class) {
38            Self::bind_template(klass);
39        }
40
41        fn instance_init(obj: &InitializingObject<Self>) {
42            obj.init_template();
43        }
44    }
45
46    #[glib::derived_properties]
47    impl ObjectImpl for MessageReply {
48        fn dispose(&self) {
49            if let Some(binding) = self.related_display_name_binding.take() {
50                binding.unbind();
51            }
52        }
53    }
54
55    impl WidgetImpl for MessageReply {}
56    impl GridImpl for MessageReply {}
57
58    impl MessageReply {
59        /// Set whether to show the header of the related content.
60        fn set_show_related_content_header(&self, show: bool) {
61            if self.show_related_content_header.get() == show {
62                return;
63            }
64
65            self.show_related_content_header.set(show);
66            self.obj().notify_show_related_content_header();
67        }
68
69        /// Set the sender of the replied-to event.
70        pub(super) fn set_related_content_sender(&self, user: &User) {
71            if let Some(binding) = self.related_display_name_binding.take() {
72                binding.unbind();
73            }
74
75            let related_display_name_binding = user
76                .bind_property("disambiguated-name", &*self.related_content_sender, "label")
77                .sync_create()
78                .build();
79            self.related_display_name_binding
80                .replace(Some(related_display_name_binding));
81        }
82
83        /// The widget containing the replied-to content.
84        pub(super) fn related_content(&self) -> &adw::Bin {
85            self.related_content.as_ref()
86        }
87
88        /// The widget containing the reply's content.
89        pub(super) fn content(&self) -> &adw::Bin {
90            self.content.as_ref()
91        }
92    }
93}
94
95glib::wrapper! {
96    /// A widget displaying a reply to a message.
97    pub struct MessageReply(ObjectSubclass<imp::MessageReply>)
98        @extends gtk::Widget, gtk::Grid, @implements gtk::Accessible;
99}
100
101impl MessageReply {
102    pub fn new() -> Self {
103        glib::Object::new()
104    }
105
106    /// Set the sender of the replied-to event.
107    pub(crate) fn set_related_content_sender(&self, user: &User) {
108        self.imp().set_related_content_sender(user);
109    }
110
111    /// The widget containing the replied-to content.
112    pub(crate) fn related_content(&self) -> &adw::Bin {
113        self.imp().related_content()
114    }
115
116    /// The widget containing the reply's content.
117    pub(crate) fn content(&self) -> &adw::Bin {
118        self.imp().content()
119    }
120}