mirror of
https://gitlab.com/schmiddi-on-mobile/flare.git
synced 2026-10-26 13:37:46 -04:00
Merge branch 'fix/channel-cache-miss' into 'master'
fix(backend): Return cached Channel from channel_from_uuid_or_group See merge request schmiddi-on-mobile/flare!214
This commit is contained in:
commit
71fa50ba65
1 file changed
+56
@@ -490,6 +490,16 @@ impl Manager {
|
||||
Thread::Contact(uuid)
|
||||
};
|
||||
|
||||
// Fast path: if we already know this thread, return the cached
|
||||
// `Channel` so callers see notify-signals (e.g. `is-typing`) on the
|
||||
// same GObject instance the UI is bound to. Without this, the
|
||||
// incoming `TypingMessage` handler would toggle `is-typing` on a
|
||||
// freshly-built orphan `Channel` and the typing indicator would
|
||||
// silently never light up for known contacts.
|
||||
if let Some(cached) = self.imp().channels.borrow().get(&thread).cloned() {
|
||||
return cached;
|
||||
}
|
||||
|
||||
let contact = Contact::from_service_address(&uuid, self).await;
|
||||
let channel = Channel::from_contact_or_group(contact, group, self).await;
|
||||
channel.initialize_avatar().await;
|
||||
@@ -977,3 +987,49 @@ mod imp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use libsignal_service::prelude::Uuid;
|
||||
use libsignal_service::protocol::ServiceId;
|
||||
|
||||
/// Regression test for the channel-cache miss in
|
||||
/// [`Manager::channel_from_uuid_or_group`].
|
||||
///
|
||||
/// The function previously always built and returned a fresh
|
||||
/// `Channel` GObject, even when one for the same thread already
|
||||
/// lived in the cache. Property notifications (e.g. `is-typing`
|
||||
/// for incoming `TypingMessage`s) were therefore emitted on an
|
||||
/// orphan instance the UI was not bound to, and indicators
|
||||
/// silently never reflected the change. This test asserts the
|
||||
/// invariant that a cached thread short-circuits to the cached
|
||||
/// `Channel` instance.
|
||||
#[test]
|
||||
fn cached_thread_returns_cached_channel() {
|
||||
gtk::init().expect("gtk to initialize");
|
||||
let manager: Manager = glib::Object::new();
|
||||
let cached: Channel = glib::Object::new();
|
||||
let uuid = Uuid::from_u128(0x1);
|
||||
let thread = Thread::Contact(ServiceId::Aci(uuid.into()));
|
||||
|
||||
manager
|
||||
.imp()
|
||||
.channels
|
||||
.borrow_mut()
|
||||
.insert(thread, cached.clone());
|
||||
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("tokio current-thread runtime to build");
|
||||
let result = runtime
|
||||
.block_on(manager.channel_from_uuid_or_group(ServiceId::Aci(uuid.into()), &None));
|
||||
|
||||
assert!(
|
||||
cached.eq(&result),
|
||||
"channel_from_uuid_or_group must return the cached `Channel` instance \
|
||||
so notify-signals reach widgets bound to it"
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user