diff --git a/src/base.rs b/src/base.rs index bb4f491d..c7f64ce9 100644 --- a/src/base.rs +++ b/src/base.rs @@ -910,8 +910,8 @@ pub struct RoomInfo { /// Users currently typing in this room, and when we received notification of them doing so. pub users_typing: Option<(Instant, Vec)>, - /// The display names for users in this room. - pub display_names: HashMap, + /// The display names for users in this room with a flag whether they are ambiguous. + pub display_names: HashMap, /// The last time the room was rendered, used to detect if it is currently open. pub draw_last: Option, diff --git a/src/config.rs b/src/config.rs index 635a2959..d5cb1628 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1057,8 +1057,12 @@ impl ApplicationSettings { (None, UserDisplayStyle::Username) => Cow::Borrowed(user_id.as_str()), (None, UserDisplayStyle::LocalPart) => Cow::Borrowed(user_id.localpart()), (None, UserDisplayStyle::DisplayName) => { - if let Some(display) = info.display_names.get(user_id) { - Cow::Borrowed(display.as_str()) + if let Some((name, ambiguous)) = info.display_names.get(user_id) { + if *ambiguous { + Cow::Owned(format!("{}({})", name, user_id)) + } else { + Cow::Borrowed(name.as_str()) + } } else { Cow::Borrowed(user_id.as_str()) } diff --git a/src/windows/mod.rs b/src/windows/mod.rs index 690399b3..5bfa57e8 100644 --- a/src/windows/mod.rs +++ b/src/windows/mod.rs @@ -1564,7 +1564,7 @@ impl ListItem for MemberItem { if let Some(name) = name { spans.push(Span::styled(name, style)); parens = true; - } else if let Some(display) = info.display_names.get(user_id) { + } else if let Some((display, _)) = info.display_names.get(user_id) { spans.push(Span::styled(display.clone(), style)); parens = true; } diff --git a/src/worker.rs b/src/worker.rs index 22a6fdbf..eaee8427 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -22,7 +22,6 @@ use url::Url; use matrix_sdk::{ authentication::matrix::MatrixSession, config::{RequestConfig, SyncSettings}, - deserialized_responses::DisplayName, encryption::verification::{SasVerification, Verification}, encryption::{BackupDownloadStrategy, EncryptionSettings}, event_handler::Ctx, @@ -420,15 +419,49 @@ fn members_insert( let info = rooms.get_or_default(room_id); for member in members { - let user_id = member.user_id(); - let display_name = - member.display_name().map_or(user_id.to_string(), |str| str.to_string()); - info.display_names.insert(user_id.to_owned(), display_name); + let user_id = member.user_id().to_owned(); + let name = member.display_name().map(|s| s.to_owned()); + member_set_display_name(info, user_id, name); } } // else ??? } +fn member_set_display_name(info: &mut RoomInfo, user_id: OwnedUserId, name: Option) { + let to_remove; + if let Some(display_name) = name { + let ambiguous = info.display_names.iter_mut().any(|(_, (name, is_ambiguous))| { + if name == &display_name { + *is_ambiguous = true; + true + } else { + false + } + }); + + to_remove = info.display_names.insert(user_id, (display_name, ambiguous)); + } else { + to_remove = info.display_names.remove(&user_id); + } + if let Some((display_name, _)) = to_remove { + let mut names: Vec<_> = info + .display_names + .iter_mut() + .filter_map(|(_, (name, is_ambiguous))| { + if name == &display_name { + Some(is_ambiguous) + } else { + None + } + }) + .collect(); + + if names.len() == 1 { + *names[0] = false; + } + } +} + async fn load_older_forever(client: &Client, store: &AsyncProgramStore) { // Load any pending older messages or members every 2 seconds. let mut interval = tokio::time::interval(Duration::from_secs(2)); @@ -1094,34 +1127,15 @@ impl ClientWorker { ); let _ = self.client.add_event_handler( - |ev: OriginalSyncRoomMemberEvent, - room: MatrixRoom, - client: Client, - store: Ctx| { + |ev: OriginalSyncRoomMemberEvent, room: MatrixRoom, store: Ctx| { async move { let room_id = room.room_id(); let user_id = ev.state_key; - let ambiguous_name = DisplayName::new( - ev.content.displayname.as_deref().unwrap_or_else(|| user_id.as_str()), - ); - let ambiguous = client - .state_store() - .get_users_with_display_name(room_id, &ambiguous_name) - .await - .map(|users| users.len() > 1) - .unwrap_or_default(); - let mut locked = store.lock().await; let info = locked.application.get_room_info(room_id.to_owned()); - if ambiguous { - info.display_names.remove(&user_id); - } else if let Some(display) = ev.content.displayname { - info.display_names.insert(user_id, display); - } else { - info.display_names.remove(&user_id); - } + member_set_display_name(info, user_id, ev.content.displayname); } }, );