add account data, current room_id calc, unread, push ruleset, ignored users
parent
05b6f4679a
commit
c89ae2537e
|
@ -284,6 +284,11 @@ impl AsyncClient {
|
|||
self.base_client.read().await.calculate_room_names()
|
||||
}
|
||||
|
||||
/// Calculate the room names this client knows about.
|
||||
pub async fn current_room_id(&self) -> Option<RoomId> {
|
||||
self.base_client.read().await.current_room_id()
|
||||
}
|
||||
|
||||
/// Add a callback that will be called every time the client receives a room
|
||||
/// event
|
||||
///
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
use std::result::Result as StdResult;
|
||||
|
@ -22,6 +23,10 @@ use crate::api::r0 as api;
|
|||
use crate::error::Result;
|
||||
use crate::events::collections::all::{RoomEvent, StateEvent};
|
||||
use crate::events::presence::PresenceEvent;
|
||||
// `NonRoomEvent` is what it is aliased as
|
||||
use crate::events::collections::only::Event as NonRoomEvent;
|
||||
use crate::events::ignored_user_list::IgnoredUserListEvent;
|
||||
use crate::events::push_rules::{ Ruleset, PushRulesEvent};
|
||||
use crate::events::room::{
|
||||
aliases::AliasesEvent,
|
||||
canonical_alias::CanonicalAliasEvent,
|
||||
|
@ -29,11 +34,13 @@ use crate::events::room::{
|
|||
name::NameEvent,
|
||||
};
|
||||
use crate::events::EventResult;
|
||||
use crate::identifiers::RoomAliasId;
|
||||
use crate::identifiers::{RoomAliasId, UserId as Uid};
|
||||
use crate::models::Room;
|
||||
use crate::session::Session;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use js_int::UInt;
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
|
@ -57,6 +64,27 @@ pub struct RoomName {
|
|||
aliases: Vec<RoomAliasId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct CurrentRoom {
|
||||
last_active: Option<UInt>,
|
||||
current_room_id: Option<RoomId>,
|
||||
}
|
||||
|
||||
impl CurrentRoom {
|
||||
pub(crate) fn comes_after(&self, user: &Uid, event: &PresenceEvent) -> bool {
|
||||
if user == &event.sender {
|
||||
event.content.last_active_ago < self.last_active
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update(&mut self, room_id: &str, event: &PresenceEvent) {
|
||||
self.last_active = event.content.last_active_ago;
|
||||
self.current_room_id = Some(RoomId::try_from(room_id).expect("room id failed CurrentRoom::update"));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// A no IO Client implementation.
|
||||
///
|
||||
|
@ -70,6 +98,13 @@ pub struct Client {
|
|||
pub sync_token: Option<Token>,
|
||||
/// A map of the rooms our user is joined in.
|
||||
pub joined_rooms: HashMap<String, Arc<RwLock<Room>>>,
|
||||
/// The most recent room the logged in user used by `RoomId`.
|
||||
pub current_room_id: CurrentRoom,
|
||||
/// A list of ignored users.
|
||||
pub ignored_users: Vec<UserId>,
|
||||
/// The push ruleset for the logged in user.
|
||||
pub push_ruleset: Option<Ruleset>,
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
olm: Arc<Mutex<Option<OlmMachine>>>,
|
||||
}
|
||||
|
@ -92,6 +127,9 @@ impl Client {
|
|||
session,
|
||||
sync_token: None,
|
||||
joined_rooms: HashMap::new(),
|
||||
current_room_id: CurrentRoom::default(),
|
||||
ignored_users: Vec::new(),
|
||||
push_ruleset: None,
|
||||
#[cfg(feature = "encryption")]
|
||||
olm: Arc::new(Mutex::new(olm)),
|
||||
})
|
||||
|
@ -147,6 +185,10 @@ impl Client {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn current_room_id(&self) -> Option<RoomId> {
|
||||
self.current_room_id.current_room_id.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn get_or_create_room(&mut self, room_id: &str) -> &mut Arc<RwLock<Room>> {
|
||||
#[allow(clippy::or_fun_call)]
|
||||
self.joined_rooms
|
||||
|
@ -162,6 +204,32 @@ impl Client {
|
|||
))))
|
||||
}
|
||||
|
||||
/// Handle a m.ignored_user_list event, updating the room state if necessary.
|
||||
///
|
||||
/// Returns true if the room name changed, false otherwise.
|
||||
pub(crate) fn handle_ignored_users(&mut self, event: &IgnoredUserListEvent) -> bool {
|
||||
// TODO use actual UserId instead of string?
|
||||
if self.ignored_users == event.content.ignored_users.iter().map(|u| u.to_string()).collect::<Vec<String>>() {
|
||||
false
|
||||
} else {
|
||||
self.ignored_users = event.content.ignored_users.iter().map(|u| u.to_string()).collect();
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle a m.ignored_user_list event, updating the room state if necessary.
|
||||
///
|
||||
/// Returns true if the room name changed, false otherwise.
|
||||
pub(crate) fn handle_push_rules(&mut self, event: &PushRulesEvent) -> bool {
|
||||
// TODO this is basically a stub
|
||||
if self.push_ruleset.as_ref() == Some(&event.content.global) {
|
||||
false
|
||||
} else {
|
||||
self.push_ruleset = Some(event.content.global.clone());
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Receive a timeline event for a joined room and update the client state.
|
||||
///
|
||||
/// If the event was a encrypted room event and decryption was successful
|
||||
|
@ -236,11 +304,32 @@ impl Client {
|
|||
///
|
||||
/// * `event` - The event that should be handled by the client.
|
||||
pub fn receive_presence_event(&mut self, room_id: &str, event: &PresenceEvent) -> bool {
|
||||
let user_id = &self.session.as_ref().expect("to receive events you must be logged in").user_id;
|
||||
if self.current_room_id.comes_after(user_id, event) {
|
||||
self.current_room_id.update(room_id, event);
|
||||
}
|
||||
// this should be guaranteed to find the room that was just created in the `Client::sync` loop.
|
||||
let mut room = self.get_or_create_room(room_id).write().unwrap();
|
||||
room.receive_presence_event(event)
|
||||
}
|
||||
|
||||
/// Receive a presence event from an `IncomingResponse` and updates the client state.
|
||||
///
|
||||
/// This will only update the user if found in the current room looped through by `AsyncClient::sync`.
|
||||
/// Returns true if the specific users presence has changed, false otherwise.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event` - The presence event for a specified room member.
|
||||
pub fn receive_account_data(&mut self, room_id: &str, event: &NonRoomEvent) -> bool {
|
||||
match event {
|
||||
NonRoomEvent::IgnoredUserList(iu) => self.handle_ignored_users(iu),
|
||||
NonRoomEvent::Presence(p) => self.receive_presence_event(room_id, p),
|
||||
NonRoomEvent::PushRules(pr) => self.handle_push_rules(pr),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Receive a response from a sync call.
|
||||
///
|
||||
/// # Arguments
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::collections::HashMap;
|
|||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use super::{RoomMember, User, UserId};
|
||||
use crate::api::r0 as api;
|
||||
|
||||
use crate::events::collections::all::{RoomEvent, StateEvent};
|
||||
use crate::events::room::{
|
||||
aliases::AliasesEvent,
|
||||
|
@ -33,6 +33,8 @@ use crate::events::{
|
|||
use crate::identifiers::RoomAliasId;
|
||||
use crate::session::Session;
|
||||
|
||||
use js_int::UInt;
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
|
@ -69,6 +71,10 @@ pub struct Room {
|
|||
pub typing_users: Vec<UserId>,
|
||||
/// A flag indicating if the room is encrypted.
|
||||
pub encrypted: bool,
|
||||
/// Number of unread notifications with highlight flag set.
|
||||
pub unread_highlight: Option<UInt>,
|
||||
/// Number of unread notifications.
|
||||
pub unread_notifications: Option<UInt>,
|
||||
}
|
||||
|
||||
impl RoomName {
|
||||
|
@ -133,6 +139,8 @@ impl Room {
|
|||
members: HashMap::new(),
|
||||
typing_users: Vec::new(),
|
||||
encrypted: false,
|
||||
unread_highlight: None,
|
||||
unread_notifications: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,22 +156,6 @@ impl Room {
|
|||
true
|
||||
}
|
||||
|
||||
/// Handle a room.member updating the room state if necessary.
|
||||
///
|
||||
/// Returns true if the joined member list changed, false otherwise.
|
||||
pub fn handle_membership(&mut self, event: &MemberEvent) -> bool {
|
||||
match event.membership_change() {
|
||||
MembershipChange::Invited | MembershipChange::Joined => self.add_member(event),
|
||||
_ => {
|
||||
if let Some(member) = self.members.get_mut(&event.sender.to_string()) {
|
||||
member.update_member(event)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Add to the list of `RoomAliasId`s.
|
||||
fn room_aliases(&mut self, alias: &RoomAliasId) -> bool {
|
||||
self.room_name.push_alias(alias.clone());
|
||||
|
@ -181,6 +173,22 @@ impl Room {
|
|||
true
|
||||
}
|
||||
|
||||
/// Handle a room.member updating the room state if necessary.
|
||||
///
|
||||
/// Returns true if the joined member list changed, false otherwise.
|
||||
pub fn handle_membership(&mut self, event: &MemberEvent) -> bool {
|
||||
match event.membership_change() {
|
||||
MembershipChange::Invited | MembershipChange::Joined => self.add_member(event),
|
||||
_ => {
|
||||
if let Some(member) = self.members.get_mut(&event.sender.to_string()) {
|
||||
member.update_member(event)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle a room.aliases event, updating the room state if necessary.
|
||||
///
|
||||
/// Returns true if the room name changed, false otherwise.
|
||||
|
@ -263,6 +271,7 @@ impl Room {
|
|||
|
||||
/// Receive a presence event from an `IncomingResponse` and updates the client state.
|
||||
///
|
||||
/// This will only update the user if found in the current room looped through by `AsyncClient::sync`.
|
||||
/// Returns true if the specific users presence has changed, false otherwise.
|
||||
///
|
||||
/// # Arguments
|
||||
|
|
Loading…
Reference in New Issue