room: implement room_name according to spec, add RoomSummary to RoomName

master
Devin R 2020-04-16 21:00:50 -04:00
parent bd3b0e7b74
commit ebe4f03c36
3 changed files with 45 additions and 20 deletions

View File

@ -561,7 +561,7 @@ impl AsyncClient {
let mut response = self.send(request).await?; let mut response = self.send(request).await?;
for (room_id, room) in &mut response.rooms.join { for (room_id, room) in &mut response.rooms.join {
let _matrix_room = { let matrix_room = {
let mut client = self.base_client.write().await; let mut client = self.base_client.write().await;
for event in &room.state.events { for event in &room.state.events {
if let EventResult::Ok(e) = event { if let EventResult::Ok(e) = event {
@ -572,6 +572,9 @@ impl AsyncClient {
client.get_or_create_room(&room_id).clone() client.get_or_create_room(&room_id).clone()
}; };
// RoomSummary contains information for calculating room name
matrix_room.write().await.set_room_summary(&room.summary);
// re looping is not ideal here // re looping is not ideal here
for event in &mut room.state.events { for event in &mut room.state.events {
if let EventResult::Ok(e) = event { if let EventResult::Ok(e) = event {

View File

@ -26,6 +26,7 @@ use crate::api::r0 as api;
use crate::error::Result; use crate::error::Result;
use crate::events::collections::all::{RoomEvent, StateEvent}; use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::presence::PresenceEvent; use crate::events::presence::PresenceEvent;
use api::sync::sync_events::RoomSummary;
// `NonRoomEvent` is what it is aliased as // `NonRoomEvent` is what it is aliased as
use crate::events::collections::only::Event as NonRoomEvent; use crate::events::collections::only::Event as NonRoomEvent;
use crate::events::ignored_user_list::IgnoredUserListEvent; use crate::events::ignored_user_list::IgnoredUserListEvent;
@ -160,7 +161,7 @@ impl Client {
pub(crate) async fn calculate_room_name(&self, room_id: &RoomId) -> Option<String> { pub(crate) async fn calculate_room_name(&self, room_id: &RoomId) -> Option<String> {
if let Some(room) = self.joined_rooms.get(room_id) { if let Some(room) = self.joined_rooms.get(room_id) {
let room = room.read().await; let room = room.read().await;
Some(room.room_name.calculate_name(room_id, &room.members)) Some(room.room_name.calculate_name(&room.members))
} else { } else {
None None
} }
@ -168,9 +169,9 @@ impl Client {
pub(crate) async fn calculate_room_names(&self) -> Vec<String> { pub(crate) async fn calculate_room_names(&self) -> Vec<String> {
let mut res = Vec::new(); let mut res = Vec::new();
for (id, room) in &self.joined_rooms { for (_id, room) in &self.joined_rooms {
let room = room.read().await; let room = room.read().await;
res.push(room.room_name.calculate_name(id, &room.members)) res.push(room.room_name.calculate_name(&room.members))
} }
res res
} }

View File

@ -18,6 +18,7 @@ use std::convert::TryFrom;
use super::RoomMember; use super::RoomMember;
use crate::api::r0::sync::sync_events::RoomSummary;
use crate::events::collections::all::{RoomEvent, StateEvent}; use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::presence::PresenceEvent; use crate::events::presence::PresenceEvent;
use crate::events::room::{ use crate::events::room::{
@ -42,6 +43,17 @@ pub struct RoomName {
canonical_alias: Option<RoomAliasId>, canonical_alias: Option<RoomAliasId>,
/// List of `RoomAliasId`s the room has been given. /// List of `RoomAliasId`s the room has been given.
aliases: Vec<RoomAliasId>, aliases: Vec<RoomAliasId>,
/// Users which can be used to generate a room name if the room does not have
/// one. Required if room name or canonical aliases are not set or empty.
pub heroes: Vec<String>,
/// Number of users whose membership status is `join`.
/// Required if field has changed since last sync; otherwise, it may be
/// omitted.
pub joined_member_count: Option<UInt>,
/// Number of users whose membership status is `invite`.
/// Required if field has changed since last sync; otherwise, it may be
/// omitted.
pub invited_member_count: Option<UInt>,
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@ -112,11 +124,7 @@ impl RoomName {
true true
} }
pub fn calculate_name( pub fn calculate_name(&self, members: &HashMap<UserId, RoomMember>) -> String {
&self,
room_id: &RoomId,
members: &HashMap<UserId, RoomMember>,
) -> String {
// https://matrix.org/docs/spec/client_server/latest#calculating-the-display-name-for-a-room. // https://matrix.org/docs/spec/client_server/latest#calculating-the-display-name-for-a-room.
// the order in which we check for a name ^^ // the order in which we check for a name ^^
if let Some(name) = &self.name { if let Some(name) = &self.name {
@ -126,19 +134,21 @@ impl RoomName {
} else if !self.aliases.is_empty() { } else if !self.aliases.is_empty() {
self.aliases[0].alias().to_string() self.aliases[0].alias().to_string()
} else { } else {
let mut names = members let joined = self.joined_member_count.unwrap_or(UInt::max_value());
.values() let invited = self.invited_member_count.unwrap_or(UInt::max_value());
.flat_map(|m| m.display_name.clone()) let heroes = UInt::new(self.heroes.len() as u64).unwrap();
.take(3) let one = UInt::new(1).unwrap();
.collect::<Vec<_>>();
if names.is_empty() { if heroes >= (joined + invited - one) {
// TODO implement the rest of display name for room spec let mut names = self.heroes.iter().take(3).cloned().collect::<Vec<String>>();
format!("Room {}", room_id)
} else {
// stabilize order
names.sort(); names.sort();
names.join(", ") names.join(", ")
} else if heroes < (joined + invited - one) && invited + joined > one {
let mut names = self.heroes.iter().take(3).cloned().collect::<Vec<String>>();
names.sort();
format!("{}, and {} others", names.join(", "), (joined + invited))
} else {
format!("Empty Room (was {} others)", members.len())
} }
} }
} }
@ -169,7 +179,7 @@ impl Room {
/// Return the display name of the room. /// Return the display name of the room.
pub fn calculate_name(&self) -> String { pub fn calculate_name(&self) -> String {
self.room_name.calculate_name(&self.room_id, &self.members) self.room_name.calculate_name(&self.members)
} }
/// Is the room a encrypted room. /// Is the room a encrypted room.
@ -239,6 +249,17 @@ impl Room {
true true
} }
pub(crate) fn set_room_summary(&mut self, summary: &RoomSummary) {
let RoomSummary {
heroes,
joined_member_count,
invited_member_count,
} = summary;
self.room_name.heroes = heroes.clone();
self.room_name.invited_member_count = invited_member_count.clone();
self.room_name.joined_member_count = joined_member_count.clone();
}
/// Handle a room.member updating the room state if necessary. /// Handle a room.member updating the room state if necessary.
/// ///
/// Returns true if the joined member list changed, false otherwise. /// Returns true if the joined member list changed, false otherwise.