mirror of
https://gitlab.gnome.org/World/fractal.git
synced 2025-06-01 00:00:37 -04:00
notifications: Fix notifications for invites
There was a race condition where we would not be able to show the invite for a room because we didn't have the room yet in the room list.
This commit is contained in:
parent
b84a584995
commit
e5ed751c1f
@ -387,7 +387,7 @@ mod imp {
|
||||
Ok(room_id) => {
|
||||
let obj = self.obj();
|
||||
|
||||
if let Some(local_room) = room_list.get_wait(&room_id).await {
|
||||
if let Some(local_room) = room_list.get_wait(&room_id, None).await {
|
||||
if let Some(window) = obj.root().and_downcast_ref::<Window>() {
|
||||
window.session_view().select_room(local_room);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::borrow::Cow;
|
||||
use std::{borrow::Cow, cell::Cell, time::Duration};
|
||||
|
||||
use gettextrs::gettext;
|
||||
use gtk::{gdk, gio, glib, prelude::*, subclass::prelude::*};
|
||||
@ -182,11 +182,31 @@ impl Notifications {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(room) = session.room_list().get(room_id) else {
|
||||
let Some(room) = session
|
||||
.room_list()
|
||||
.get_wait(room_id, Some(Duration::from_secs(10)))
|
||||
.await
|
||||
else {
|
||||
warn!("Could not display notification for missing room {room_id}",);
|
||||
return;
|
||||
};
|
||||
|
||||
if !room.is_room_info_initialized() {
|
||||
// Wait for the room to finish initializing, otherwise we will not have the
|
||||
// display name or the avatar.
|
||||
let (sender, receiver) = futures_channel::oneshot::channel();
|
||||
|
||||
let sender_cell = Cell::new(Some(sender));
|
||||
let handler_id = room.connect_is_room_info_initialized_notify(move |_| {
|
||||
if let Some(sender) = sender_cell.take() {
|
||||
let _ = sender.send(());
|
||||
}
|
||||
});
|
||||
|
||||
let _ = receiver.await;
|
||||
room.disconnect(handler_id);
|
||||
}
|
||||
|
||||
let event = match AnySyncOrStrippedTimelineEvent::from_raw(&matrix_notification.event) {
|
||||
Ok(event) => event,
|
||||
Err(error) => {
|
||||
|
@ -224,6 +224,7 @@ mod imp {
|
||||
/// Whether the room info is initialized.
|
||||
///
|
||||
/// Used to silence logs during initialization.
|
||||
#[property(get)]
|
||||
is_room_info_initialized: Cell<bool>,
|
||||
}
|
||||
|
||||
@ -277,7 +278,9 @@ mod imp {
|
||||
imp.update_with_room_info(imp.matrix_room().clone_info())
|
||||
.await;
|
||||
imp.watch_room_info();
|
||||
|
||||
imp.is_room_info_initialized.set(true);
|
||||
imp.obj().notify_is_room_info_initialized();
|
||||
|
||||
// Only initialize the following after we have loaded the category of the
|
||||
// room since we only load them for some categories.
|
||||
|
@ -1,6 +1,8 @@
|
||||
use std::{
|
||||
cell::Cell,
|
||||
collections::{HashMap, HashSet},
|
||||
rc::Rc,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use gtk::{
|
||||
@ -49,6 +51,7 @@ mod imp {
|
||||
/// The rooms metainfo that allow to restore this `RoomList` from its
|
||||
/// previous state.
|
||||
metainfo: RoomListMetainfo,
|
||||
pub(super) get_wait_source: RefCell<Option<glib::SourceId>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
@ -70,6 +73,12 @@ mod imp {
|
||||
self.parent_constructed();
|
||||
self.metainfo.set_room_list(&self.obj());
|
||||
}
|
||||
|
||||
fn dispose(&self) {
|
||||
if let Some(source) = self.get_wait_source.take() {
|
||||
source.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ListModelImpl for RoomList {
|
||||
@ -405,28 +414,51 @@ impl RoomList {
|
||||
}
|
||||
|
||||
/// Wait till the room with the given ID becomes available.
|
||||
pub(crate) async fn get_wait(&self, room_id: &RoomId) -> Option<Room> {
|
||||
pub(crate) async fn get_wait(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
timeout: Option<Duration>,
|
||||
) -> Option<Room> {
|
||||
if let Some(room) = self.get(room_id) {
|
||||
return Some(room);
|
||||
}
|
||||
|
||||
let imp = self.imp();
|
||||
let (sender, receiver) = futures_channel::oneshot::channel();
|
||||
|
||||
let room_id = room_id.to_owned();
|
||||
let sender = Cell::new(Some(sender));
|
||||
// FIXME: add a timeout
|
||||
let handler_id = self.connect_items_changed(move |obj, _, _, _| {
|
||||
if let Some(room) = obj.get(&room_id) {
|
||||
if let Some(sender) = sender.take() {
|
||||
let _ = sender.send(Some(room));
|
||||
let sender_cell = Rc::new(Cell::new(Some(sender)));
|
||||
|
||||
let handler_id = self.connect_items_changed(clone!(
|
||||
#[strong]
|
||||
sender_cell,
|
||||
move |obj, _, _, _| {
|
||||
if let Some(room) = obj.get(&room_id) {
|
||||
if let Some(sender) = sender_cell.take() {
|
||||
let _ = sender.send(Some(room));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
));
|
||||
|
||||
if let Some(timeout) = timeout {
|
||||
let get_wait_source = glib::timeout_add_local_once(timeout, move || {
|
||||
if let Some(sender) = sender_cell.take() {
|
||||
let _ = sender.send(None);
|
||||
}
|
||||
});
|
||||
imp.get_wait_source.replace(Some(get_wait_source));
|
||||
}
|
||||
|
||||
let room = receiver.await.ok().flatten();
|
||||
|
||||
self.disconnect(handler_id);
|
||||
|
||||
// Remove the source if we got a room.
|
||||
if let Some(source) = imp.get_wait_source.take().filter(|_| room.is_some()) {
|
||||
source.remove();
|
||||
}
|
||||
|
||||
room
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ mod imp {
|
||||
let room = self
|
||||
.session()
|
||||
.room_list()
|
||||
.get_wait(matrix_room.room_id())
|
||||
.get_wait(matrix_room.room_id(), None)
|
||||
.await
|
||||
.expect("The newly created room was not found");
|
||||
Ok(room)
|
||||
|
@ -208,7 +208,11 @@ mod imp {
|
||||
let Some(window) = obj.root().and_downcast::<Window>() else {
|
||||
return;
|
||||
};
|
||||
if let Some(room) = session.room_list().get_wait(matrix_room.room_id()).await {
|
||||
if let Some(room) = session
|
||||
.room_list()
|
||||
.get_wait(matrix_room.room_id(), None)
|
||||
.await
|
||||
{
|
||||
window.session_view().select_room(room);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user