diff --git a/src/models/room.rs b/src/models/room.rs index e85c6a13..7d1f3933 100644 --- a/src/models/room.rs +++ b/src/models/room.rs @@ -24,6 +24,7 @@ use crate::events::room::{ canonical_alias::CanonicalAliasEvent, member::{MemberEvent, MembershipState}, name::NameEvent, + power_levels::PowerLevelsEvent, }; use crate::events::{ presence::{PresenceEvent, PresenceEventContent}, @@ -188,10 +189,8 @@ impl Room { match &event.content.membership { MembershipState::Invite | MembershipState::Join => self.add_member(event), _ => { - if let Some(member) = self.members.get_mut(&event.sender.to_string()) { - let changed = member.membership == event.content.membership; - member.membership = event.content.membership; - changed + if let Some(member) = self.members.get_mut(&event.state_key) { + member.update_member(event) } else { false } @@ -247,6 +246,17 @@ impl Room { } } + /// Handle a room.power_levels event, updating the room state if necessary. + /// + /// Returns true if the room name changed, false otherwise. + pub fn handle_power_level(&mut self, event: &PowerLevelsEvent) -> bool { + if let Some(member) = self.members.get_mut(&event.state_key) { + member.update_power(event) + } else { + false + } + } + /// Receive a timeline event for this room and update the room state. /// /// Returns true if the joined member list changed, false otherwise. @@ -263,7 +273,7 @@ impl Room { RoomEvent::RoomCanonicalAlias(ca) => self.handle_canonical(ca), RoomEvent::RoomAliases(a) => self.handle_room_aliases(a), // power levels of the room members - // RoomEvent::RoomPowerLevels(p) => self.handle_power_level(p), + RoomEvent::RoomPowerLevels(p) => self.handle_power_level(p), _ => false, } } diff --git a/src/models/room_member.rs b/src/models/room_member.rs index 33105ac0..896fd1c8 100644 --- a/src/models/room_member.rs +++ b/src/models/room_member.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; -use super::{User, UserId}; +use super::User; use crate::api::r0 as api; use crate::events::collections::all::{Event, RoomEvent, StateEvent}; use crate::events::room::{ @@ -24,9 +24,10 @@ use crate::events::room::{ canonical_alias::CanonicalAliasEvent, member::{MemberEvent, MemberEventContent, MembershipState}, name::NameEvent, + power_levels::PowerLevelsEvent, }; use crate::events::EventResult; -use crate::identifiers::RoomAliasId; +use crate::identifiers::{RoomAliasId, UserId}; use crate::session::Session; use js_int::{Int, UInt}; @@ -66,7 +67,7 @@ impl RoomMember { let user = User::new(event); Self { room_id: event.room_id.as_ref().map(|id| id.to_string()), - user_id: event.state_key.clone(), + user_id: event.sender.clone(), typing: None, user, power_level: None, @@ -77,34 +78,31 @@ impl RoomMember { } } - pub fn update(&mut self, event: &MemberEvent) { - let MemberEvent { - content: MemberEventContent { membership, .. }, - room_id, - state_key, - .. - } = event; + pub fn update_member(&mut self, event: &MemberEvent) -> bool { + let changed = self.membership == event.content.membership; + self.membership = event.content.membership; + changed + } - let mut events = Vec::new(); - events.extend( - self.events - .drain(..) - .chain(Some(Event::RoomMember(event.clone()))), - ); - - *self = Self { - room_id: room_id - .as_ref() - .map(|id| id.to_string()) - .or(self.room_id.take()), - user_id: state_key.clone(), - typing: None, - user: User::new(event), - power_level: None, - power_level_norm: None, - membership: membership.clone(), - name: state_key.clone(), - events, + pub fn update_power(&mut self, event: &PowerLevelsEvent) -> bool { + let mut max_power = event.content.users_default; + for power in event.content.users.values() { + max_power = *power.max(&max_power); } + + let mut changed = false; + if let Some(user_power) = event.content.users.get(&self.user_id) { + changed = self.power_level == Some(*user_power); + self.power_level = Some(*user_power); + } else { + changed = self.power_level == Some(event.content.users_default); + self.power_level = Some(event.content.users_default); + } + + if max_power > Int::from(0) { + self.power_level_norm = Some((self.power_level.unwrap() * Int::from(100)) / max_power); + } + + changed } }