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?;
for (room_id, room) in &mut response.rooms.join {
let _matrix_room = {
let matrix_room = {
let mut client = self.base_client.write().await;
for event in &room.state.events {
if let EventResult::Ok(e) = event {
@ -572,6 +572,9 @@ impl AsyncClient {
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
for event in &mut room.state.events {
if let EventResult::Ok(e) = event {

View File

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

View File

@ -18,6 +18,7 @@ use std::convert::TryFrom;
use super::RoomMember;
use crate::api::r0::sync::sync_events::RoomSummary;
use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::presence::PresenceEvent;
use crate::events::room::{
@ -42,6 +43,17 @@ pub struct RoomName {
canonical_alias: Option<RoomAliasId>,
/// List of `RoomAliasId`s the room has been given.
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)]
@ -112,11 +124,7 @@ impl RoomName {
true
}
pub fn calculate_name(
&self,
room_id: &RoomId,
members: &HashMap<UserId, RoomMember>,
) -> String {
pub fn calculate_name(&self, members: &HashMap<UserId, RoomMember>) -> String {
// https://matrix.org/docs/spec/client_server/latest#calculating-the-display-name-for-a-room.
// the order in which we check for a name ^^
if let Some(name) = &self.name {
@ -126,19 +134,21 @@ impl RoomName {
} else if !self.aliases.is_empty() {
self.aliases[0].alias().to_string()
} else {
let mut names = members
.values()
.flat_map(|m| m.display_name.clone())
.take(3)
.collect::<Vec<_>>();
let joined = self.joined_member_count.unwrap_or(UInt::max_value());
let invited = self.invited_member_count.unwrap_or(UInt::max_value());
let heroes = UInt::new(self.heroes.len() as u64).unwrap();
let one = UInt::new(1).unwrap();
if names.is_empty() {
// TODO implement the rest of display name for room spec
format!("Room {}", room_id)
} else {
// stabilize order
if heroes >= (joined + invited - one) {
let mut names = self.heroes.iter().take(3).cloned().collect::<Vec<String>>();
names.sort();
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.
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.
@ -239,6 +249,17 @@ impl Room {
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.
///
/// Returns true if the joined member list changed, false otherwise.