fractal/session/view/content/room_history/member_timestamp/
row.rs

1use adw::{prelude::*, subclass::prelude::*};
2use gettextrs::gettext;
3use gtk::{CompositeTemplate, glib, glib::clone};
4
5use super::MemberTimestamp;
6use crate::{
7    Application, system_settings::ClockFormat, utils::matrix::seconds_since_unix_epoch_to_date,
8};
9
10mod imp {
11    use std::cell::RefCell;
12
13    use glib::subclass::InitializingObject;
14
15    use super::*;
16
17    #[derive(Debug, Default, CompositeTemplate, glib::Properties)]
18    #[template(
19        resource = "/org/gnome/Fractal/ui/session/view/content/room_history/member_timestamp/row.ui"
20    )]
21    #[properties(wrapper_type = super::MemberTimestampRow)]
22    pub struct MemberTimestampRow {
23        #[template_child]
24        timestamp: TemplateChild<gtk::Label>,
25        /// The `MemberTimestamp` presented by this row.
26        #[property(get, set = Self::set_data, explicit_notify, nullable)]
27        data: glib::WeakRef<MemberTimestamp>,
28        system_settings_handler: RefCell<Option<glib::SignalHandlerId>>,
29    }
30
31    #[glib::object_subclass]
32    impl ObjectSubclass for MemberTimestampRow {
33        const NAME: &'static str = "ContentMemberTimestampRow";
34        type Type = super::MemberTimestampRow;
35        type ParentType = adw::Bin;
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 MemberTimestampRow {
48        fn constructed(&self) {
49            self.parent_constructed();
50
51            let system_settings = Application::default().system_settings();
52            let system_settings_handler = system_settings.connect_clock_format_notify(clone!(
53                #[weak(rename_to = imp)]
54                self,
55                move |_| {
56                    imp.update_timestamp();
57                }
58            ));
59            self.system_settings_handler
60                .replace(Some(system_settings_handler));
61        }
62
63        fn dispose(&self) {
64            if let Some(handler) = self.system_settings_handler.take() {
65                Application::default().system_settings().disconnect(handler);
66            }
67        }
68    }
69
70    impl WidgetImpl for MemberTimestampRow {}
71    impl BinImpl for MemberTimestampRow {}
72
73    impl MemberTimestampRow {
74        /// Set the `MemberTimestamp` presented by this row.
75        fn set_data(&self, data: Option<&MemberTimestamp>) {
76            if self.data.upgrade().as_ref() == data {
77                return;
78            }
79
80            self.data.set(data);
81
82            self.obj().notify_data();
83            self.update_timestamp();
84        }
85
86        /// The formatted date and time of this receipt.
87        fn update_timestamp(&self) {
88            let Some(timestamp) = self
89                .data
90                .upgrade()
91                .map(|d| d.timestamp())
92                .filter(|t| *t > 0)
93            else {
94                // No timestamp.
95                self.timestamp.set_visible(false);
96                return;
97            };
98
99            let timestamp = timestamp.try_into().unwrap_or(i64::MAX);
100            let datetime = seconds_since_unix_epoch_to_date(timestamp);
101
102            let clock_format = Application::default().system_settings().clock_format();
103
104            let format = if clock_format == ClockFormat::TwelveHours {
105                // Translators: this is a date and a time in 12h format.
106                // For example, "May 5 at 01:20 PM".
107                // Do not change the time format as it will follow the system settings.
108                // See `man strftime` or the documentation of g_date_time_format for the available specifiers: <https://docs.gtk.org/glib/method.DateTime.format.html>
109                gettext("%B %-e at %I:%M %p")
110            } else {
111                // Translators: this is a date and a time in 24h format.
112                // For example, "May 5 at 13:20".
113                // Do not change the time format as it will follow the system settings.
114                // See `man strftime` or the documentation of g_date_time_format for the available specifiers: <https://docs.gtk.org/glib/method.DateTime.format.html>
115                gettext("%B %-e at %H:%M")
116            };
117            let label = datetime.format(&format).unwrap();
118
119            self.timestamp.set_label(&label);
120            self.timestamp.set_visible(true);
121        }
122    }
123}
124
125glib::wrapper! {
126    /// A row displaying a room member and timestamp.
127    pub struct MemberTimestampRow(ObjectSubclass<imp::MemberTimestampRow>)
128        @extends gtk::Widget, adw::Bin;
129}
130
131impl MemberTimestampRow {
132    pub fn new() -> Self {
133        glib::Object::new()
134    }
135}
136
137impl Default for MemberTimestampRow {
138    fn default() -> Self {
139        Self::new()
140    }
141}