diff --git a/examples/login.rs b/examples/login.rs index 30ac6422..9575a71e 100644 --- a/examples/login.rs +++ b/examples/login.rs @@ -26,7 +26,6 @@ impl EventEmitter for EventCallback { println!( "{}: {}", member - .user .display_name .as_ref() .unwrap_or(&sender.to_string()), diff --git a/src/base_client.rs b/src/base_client.rs index 900bad02..5bbcff52 100644 --- a/src/base_client.rs +++ b/src/base_client.rs @@ -31,7 +31,7 @@ use crate::events::collections::only::Event as NonRoomEvent; use crate::events::ignored_user_list::IgnoredUserListEvent; use crate::events::push_rules::{PushRulesEvent, Ruleset}; use crate::events::EventResult; -use crate::identifiers::{RoomAliasId, RoomId, UserId}; +use crate::identifiers::{RoomId, UserId}; use crate::models::Room; use crate::session::Session; use crate::EventEmitter; diff --git a/src/event_emitter/mod.rs b/src/event_emitter/mod.rs index be837c32..f09dd0a8 100644 --- a/src/event_emitter/mod.rs +++ b/src/event_emitter/mod.rs @@ -179,7 +179,7 @@ mod test { } async fn on_room_canonical_alias( &mut self, - r: Arc>, + _: Arc>, _: Arc>, ) { self.0.lock().await.push("canonical".to_string()) @@ -304,7 +304,7 @@ mod test { let vec = Arc::new(Mutex::new(Vec::new())); let test_vec = Arc::clone(&vec); - let mut emitter = Arc::new(Mutex::new( + let emitter = Arc::new(Mutex::new( Box::new(EvEmitterTest(vec)) as Box<(dyn EventEmitter)> )); let mut client = AsyncClient::new(homeserver, Some(session)).unwrap(); diff --git a/src/models/mod.rs b/src/models/mod.rs index d6e31fd0..07fcb00e 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,10 +1,8 @@ mod room; mod room_member; -mod user; pub use room::{Room, RoomName}; pub use room_member::RoomMember; -pub use user::User; #[allow(dead_code)] pub type Token = String; diff --git a/src/models/room.rs b/src/models/room.rs index 7f6bde57..d8eceea1 100644 --- a/src/models/room.rs +++ b/src/models/room.rs @@ -99,7 +99,7 @@ impl RoomName { } else { let mut names = members .values() - .flat_map(|m| m.user.display_name.clone()) + .flat_map(|m| m.display_name.clone()) .take(3) .collect::>(); @@ -311,11 +311,11 @@ impl Room { /// /// * `event` - The presence event for a specified room member. pub fn receive_presence_event(&mut self, event: &PresenceEvent) -> bool { - if let Some(user) = self.members.get_mut(&event.sender).map(|m| &mut m.user) { - if user.did_update_presence(event) { + if let Some(member) = self.members.get_mut(&event.sender) { + if member.did_update_presence(event) { false } else { - user.update_presence(event); + member.update_presence(event); true } } else { diff --git a/src/models/room_member.rs b/src/models/room_member.rs index 69efcab5..4d177226 100644 --- a/src/models/room_member.rs +++ b/src/models/room_member.rs @@ -15,15 +15,15 @@ use std::convert::TryFrom; -use super::User; use crate::events::collections::all::Event; use crate::events::room::{ member::{MemberEvent, MembershipChange, MembershipState}, power_levels::PowerLevelsEvent, }; +use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState}; use crate::identifiers::UserId; -use js_int::Int; +use js_int::{Int, UInt}; // Notes: if Alice invites Bob into a room we will get an event with the sender as Alice and the state key as Bob. @@ -33,12 +33,22 @@ use js_int::Int; pub struct RoomMember { /// The unique mxid of the user. pub user_id: UserId, + /// The human readable name of the user. + pub display_name: Option, + /// The matrix url of the users avatar. + pub avatar_url: Option, + /// The time, in ms, since the user interacted with the server. + pub last_active_ago: Option, + /// If the user should be considered active. + pub currently_active: Option, /// The unique id of the room. pub room_id: Option, /// If the member is typing. pub typing: Option, - /// The user data for this room member. - pub user: User, + /// The presence of the user, if found. + pub presence: Option, + /// The presence status message, if found. + pub status_msg: Option, /// The users power level. pub power_level: Option, /// The normalized power level of this `RoomMember` (0-100). @@ -49,20 +59,27 @@ pub struct RoomMember { pub name: String, /// The events that created the state of this room member. pub events: Vec, + /// The `PresenceEvent`s connected to this user. + pub presence_events: Vec, } impl RoomMember { pub fn new(event: &MemberEvent) -> Self { - let user = User::new(event); Self { + name: event.state_key.clone(), room_id: event.room_id.as_ref().map(|id| id.to_string()), user_id: UserId::try_from(event.state_key.as_str()).unwrap(), + display_name: event.content.displayname.clone(), + avatar_url: event.content.avatar_url.clone(), + presence: None, + status_msg: None, + last_active_ago: None, + currently_active: None, typing: None, - user, power_level: None, power_level_norm: None, membership: event.content.membership, - name: event.state_key.clone(), + presence_events: Vec::default(), events: vec![Event::RoomMember(event.clone())], } } @@ -72,8 +89,8 @@ impl RoomMember { match event.membership_change() { ProfileChanged => { - self.user.display_name = event.content.displayname.clone(); - self.user.avatar_url = event.content.avatar_url.clone(); + self.display_name = event.content.displayname.clone(); + self.avatar_url = event.content.avatar_url.clone(); true } Banned | Kicked | KickedAndBanned | InvitationRejected | InvitationRevoked | Left @@ -110,6 +127,64 @@ impl RoomMember { changed } + + /// If the current `PresenceEvent` updated the state of this `User`. + /// + /// Returns true if the specific users presence has changed, false otherwise. + /// + /// # Arguments + /// + /// * `presence` - The presence event for a this room member. + pub fn did_update_presence(&self, presence: &PresenceEvent) -> bool { + let PresenceEvent { + content: + PresenceEventContent { + avatar_url, + currently_active, + displayname, + last_active_ago, + presence, + status_msg, + }, + .. + } = presence; + self.display_name == *displayname + && self.avatar_url == *avatar_url + && self.presence.as_ref() == Some(presence) + && self.status_msg == *status_msg + && self.last_active_ago == *last_active_ago + && self.currently_active == *currently_active + } + + /// Updates the `User`s presence. + /// + /// This should only be used if `did_update_presence` was true. + /// + /// # Arguments + /// + /// * `presence` - The presence event for a this room member. + pub fn update_presence(&mut self, presence_ev: &PresenceEvent) { + let PresenceEvent { + content: + PresenceEventContent { + avatar_url, + currently_active, + displayname, + last_active_ago, + presence, + status_msg, + }, + .. + } = presence_ev; + + self.presence_events.push(presence_ev.clone()); + self.avatar_url = avatar_url.clone(); + self.currently_active = currently_active.clone(); + self.display_name = displayname.clone(); + self.last_active_ago = last_active_ago.clone(); + self.presence = Some(presence.clone()); + self.status_msg = status_msg.clone(); + } } #[cfg(test)] diff --git a/src/models/user.rs b/src/models/user.rs deleted file mode 100644 index e6a042a6..00000000 --- a/src/models/user.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2020 Damir Jelić -// Copyright 2020 The Matrix.org Foundation C.I.C. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::events::collections::all::Event; -use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState}; -use crate::events::room::member::MemberEvent; - -use js_int::UInt; - -#[derive(Debug)] -/// A Matrix room member. -pub struct User { - /// The human readable name of the user. - pub display_name: Option, - /// The matrix url of the users avatar. - pub avatar_url: Option, - /// The presence of the user, if found. - pub presence: Option, - /// The presence status message, if found. - pub status_msg: Option, - /// The time, in ms, since the user interacted with the server. - pub last_active_ago: Option, - /// If the user should be considered active. - pub currently_active: Option, - /// The events that created the state of the current user. - // TODO do we want to hold the whole state or just update our structures. - pub events: Vec, - /// The `PresenceEvent`s connected to this user. - pub presence_events: Vec, -} - -impl User { - pub fn new(event: &MemberEvent) -> Self { - Self { - display_name: event.content.displayname.clone(), - avatar_url: event.content.avatar_url.clone(), - presence: None, - status_msg: None, - last_active_ago: None, - currently_active: None, - events: Vec::default(), - presence_events: Vec::default(), - } - } - - /// If the current `PresenceEvent` updated the state of this `User`. - /// - /// Returns true if the specific users presence has changed, false otherwise. - /// - /// # Arguments - /// - /// * `presence` - The presence event for a this room member. - pub fn did_update_presence(&self, presence: &PresenceEvent) -> bool { - let PresenceEvent { - content: - PresenceEventContent { - avatar_url, - currently_active, - displayname, - last_active_ago, - presence, - status_msg, - }, - .. - } = presence; - self.display_name == *displayname - && self.avatar_url == *avatar_url - && self.presence.as_ref() == Some(presence) - && self.status_msg == *status_msg - && self.last_active_ago == *last_active_ago - && self.currently_active == *currently_active - } - - /// Updates the `User`s presence. - /// - /// This should only be used if `did_update_presence` was true. - /// - /// # Arguments - /// - /// * `presence` - The presence event for a this room member. - pub fn update_presence(&mut self, presence_ev: &PresenceEvent) { - let PresenceEvent { - content: - PresenceEventContent { - avatar_url, - currently_active, - displayname, - last_active_ago, - presence, - status_msg, - }, - .. - } = presence_ev; - - self.presence_events.push(presence_ev.clone()); - *self = User { - display_name: displayname.clone(), - avatar_url: avatar_url.clone(), - presence: Some(*presence), - status_msg: status_msg.clone(), - last_active_ago: *last_active_ago, - currently_active: *currently_active, - // TODO better way of moving vec over - events: self.events.clone(), - presence_events: self.presence_events.clone(), - } - } -}