diff --git a/src/session/view/content/room_history/mod.rs b/src/session/view/content/room_history/mod.rs index 06889741..ee6c5926 100644 --- a/src/session/view/content/room_history/mod.rs +++ b/src/session/view/content/room_history/mod.rs @@ -40,6 +40,7 @@ use self::{ }; use super::{RoomDetails, room_details}; use crate::{ + Window, components::{DragOverlay, confirm_leave_room_dialog}, ngettext_f, prelude::*, @@ -129,6 +130,7 @@ mod imp { membership_handler: RefCell>, join_rule_handler: RefCell>, knock_items_changed_handler: RefCell>, + window_active_handler: RefCell>, } #[glib::object_subclass] @@ -281,10 +283,38 @@ mod imp { revealer.set_visible(false); } }); + + self.obj().connect_root_notify(|obj| { + let imp = obj.imp(); + + let Some(window) = imp.parent_window() else { + return; + }; + + let active_handler = window.connect_is_active_notify(clone!( + #[weak] + imp, + move |window| { + if !window.is_active() { + return; + } + + // When the window becomes active, trigger a read receipt update. + imp.trigger_read_receipts_update(); + } + )); + imp.window_active_handler.replace(Some(active_handler)); + }); } fn dispose(&self) { self.disconnect_all(); + + if let Some(handler) = self.window_active_handler.take() { + if let Some(window) = self.parent_window() { + window.disconnect(handler); + } + } } } @@ -296,6 +326,13 @@ mod imp { self.room_title.grab_focus() } } + + fn map(&self) { + self.parent_map(); + + // When the room history becomes mapped, trigger a read receipt update. + self.trigger_read_receipts_update(); + } } impl BinImpl for RoomHistory {} @@ -811,6 +848,21 @@ mod imp { } } + /// The ancestor window of the room history. + fn parent_window(&self) -> Option { + self.obj().root().and_downcast() + } + + /// Whether the room history is active. + /// + /// It means that the ancestor window is active and the room history is + /// mapped. + fn is_active(&self) -> bool { + self.parent_window() + .is_some_and(|window| window.is_active()) + && self.obj().is_mapped() + } + /// Trigger the process to update read receipts. fn trigger_read_receipts_update(&self) { let Some(timeline) = self.timeline.obj() else { @@ -825,6 +877,10 @@ mod imp { source_id.remove(); } + if !self.is_active() { + return; + } + // Only send read receipt when scrolling stopped. self.scroll_timeout .replace(Some(glib::timeout_add_local_once( @@ -848,6 +904,10 @@ mod imp { source_id.remove(); } + if !self.is_active() { + return; + } + self.read_timeout.replace(Some(glib::timeout_add_local_once( READ_TIMEOUT, clone!( @@ -877,6 +937,10 @@ mod imp { fn update_read_marker(&self) { self.read_timeout.take(); + if !self.is_active() { + return; + } + let Some(position) = self.receipt_position() else { return; };