mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-08 07:56:55 -04:00
feat(sdk): Add Timeline::fetch_members
This commit is contained in:
committed by
Jonas Platte
parent
c294a376e8
commit
e11dd099d8
@@ -390,7 +390,7 @@ impl Common {
|
||||
}
|
||||
}
|
||||
|
||||
async fn ensure_members(&self) -> Result<()> {
|
||||
pub(crate) async fn ensure_members(&self) -> Result<()> {
|
||||
if !self.are_events_visible() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -209,6 +209,18 @@ impl EventTimelineItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Clone the current event item, and update its `sender_profile`.
|
||||
pub(super) fn with_sender_profile(&self, sender_profile: TimelineDetails<Profile>) -> Self {
|
||||
match self {
|
||||
EventTimelineItem::Local(item) => {
|
||||
Self::Local(LocalEventTimelineItem { sender_profile, ..item.clone() })
|
||||
}
|
||||
EventTimelineItem::Remote(item) => {
|
||||
Self::Remote(RemoteEventTimelineItem { sender_profile, ..item.clone() })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This type represents the "send state" of a local event timeline item.
|
||||
@@ -342,7 +354,7 @@ impl fmt::Debug for RemoteEventTimelineItem {
|
||||
}
|
||||
|
||||
/// The display name and avatar URL of a room member.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Profile {
|
||||
/// The display name, if set.
|
||||
pub display_name: Option<String>,
|
||||
@@ -382,6 +394,17 @@ impl<T> TimelineDetails<T> {
|
||||
None => Self::Unavailable,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_unavailable(&self) -> bool {
|
||||
matches!(self, Self::Unavailable)
|
||||
}
|
||||
|
||||
pub(crate) fn contains<U>(&self, value: &U) -> bool
|
||||
where
|
||||
T: PartialEq<U>,
|
||||
{
|
||||
matches!(self, Self::Ready(v) if v == value)
|
||||
}
|
||||
}
|
||||
|
||||
/// The content of an [`EventTimelineItem`].
|
||||
|
||||
@@ -37,7 +37,7 @@ use super::{
|
||||
use crate::{
|
||||
events::SyncTimelineEventWithoutContent,
|
||||
room::{self, timeline::event_item::RemoteEventTimelineItem},
|
||||
Result,
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -372,6 +372,66 @@ impl<P: ProfileProvider> TimelineInner<P> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_sender_profiles_pending(&self) {
|
||||
self.set_non_ready_sender_profiles(TimelineDetails::Pending);
|
||||
}
|
||||
|
||||
pub(super) fn set_sender_profiles_error(&self, error: Arc<Error>) {
|
||||
self.set_non_ready_sender_profiles(TimelineDetails::Error(error));
|
||||
}
|
||||
|
||||
fn set_non_ready_sender_profiles(&self, state: TimelineDetails<Profile>) {
|
||||
let mut timeline_items = self.items.lock_mut();
|
||||
for idx in 0..timeline_items.len() {
|
||||
let Some(event_item) = timeline_items[idx].as_event() else { continue };
|
||||
if !matches!(event_item.sender_profile(), TimelineDetails::Ready(_)) {
|
||||
timeline_items.set_cloned(
|
||||
idx,
|
||||
Arc::new(TimelineItem::Event(event_item.with_sender_profile(state.clone()))),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn update_sender_profiles(&self) {
|
||||
// Can't lock the timeline items across .await points without making the
|
||||
// resulting future `!Send`. As a (brittle) hack around that, lock the
|
||||
// timeline items in each loop iteration but keep a lock of the metadata
|
||||
// so no event handler runs in parallel and assert the number of items
|
||||
// doesn't change between iterations.
|
||||
let _guard = self.metadata.lock().await;
|
||||
let num_items = self.items().len();
|
||||
|
||||
for idx in 0..num_items {
|
||||
let sender = match self.items()[idx].as_event() {
|
||||
Some(event_item) => event_item.sender().to_owned(),
|
||||
None => continue,
|
||||
};
|
||||
let maybe_profile = self.profile_provider.profile(&sender).await;
|
||||
|
||||
let mut timeline_items = self.items.lock_mut();
|
||||
assert_eq!(timeline_items.len(), num_items);
|
||||
|
||||
let event_item = timeline_items[idx].as_event().unwrap();
|
||||
match maybe_profile {
|
||||
Some(profile) => {
|
||||
if !event_item.sender_profile().contains(&profile) {
|
||||
let updated_item =
|
||||
event_item.with_sender_profile(TimelineDetails::Ready(profile));
|
||||
timeline_items.set_cloned(idx, Arc::new(TimelineItem::Event(updated_item)));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if !event_item.sender_profile().is_unavailable() {
|
||||
let updated_item =
|
||||
event_item.with_sender_profile(TimelineDetails::Unavailable);
|
||||
timeline_items.set_cloned(idx, Arc::new(TimelineItem::Event(updated_item)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_event_item(&self, index: usize, event_item: EventTimelineItem) {
|
||||
self.items.lock_mut().set_cloned(index, Arc::new(TimelineItem::Event(event_item)))
|
||||
}
|
||||
|
||||
@@ -421,6 +421,26 @@ impl Timeline {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fetch all member events for the room this timeline is displaying.
|
||||
///
|
||||
/// If the full member list is not known, sender profiles are currently
|
||||
/// likely not going to be available. This will be fixed in the future.
|
||||
///
|
||||
/// If fetching the members fails, any affected timeline items will have
|
||||
/// the `sender_profile` set to [`TimelineDetails::Error`].
|
||||
#[instrument(skip_all)]
|
||||
pub async fn fetch_members(&self) {
|
||||
self.inner.set_sender_profiles_pending();
|
||||
match self.room().ensure_members().await {
|
||||
Ok(_) => {
|
||||
self.inner.update_sender_profiles().await;
|
||||
}
|
||||
Err(e) => {
|
||||
self.inner.set_sender_profiles_error(Arc::new(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A single entry in timeline.
|
||||
|
||||
Reference in New Issue
Block a user