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()
|
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
|
/// Add a callback that will be called every time the client receives a room
|
||||||
/// event
|
/// event
|
||||||
///
|
///
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
|
@ -22,6 +23,10 @@ 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;
|
||||||
|
// `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::{
|
use crate::events::room::{
|
||||||
aliases::AliasesEvent,
|
aliases::AliasesEvent,
|
||||||
canonical_alias::CanonicalAliasEvent,
|
canonical_alias::CanonicalAliasEvent,
|
||||||
|
@ -29,11 +34,13 @@ use crate::events::room::{
|
||||||
name::NameEvent,
|
name::NameEvent,
|
||||||
};
|
};
|
||||||
use crate::events::EventResult;
|
use crate::events::EventResult;
|
||||||
use crate::identifiers::RoomAliasId;
|
use crate::identifiers::{RoomAliasId, UserId as Uid};
|
||||||
use crate::models::Room;
|
use crate::models::Room;
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use js_int::UInt;
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
@ -57,6 +64,27 @@ pub struct RoomName {
|
||||||
aliases: Vec<RoomAliasId>,
|
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)]
|
#[derive(Debug)]
|
||||||
/// A no IO Client implementation.
|
/// A no IO Client implementation.
|
||||||
///
|
///
|
||||||
|
@ -70,6 +98,13 @@ pub struct Client {
|
||||||
pub sync_token: Option<Token>,
|
pub sync_token: Option<Token>,
|
||||||
/// A map of the rooms our user is joined in.
|
/// A map of the rooms our user is joined in.
|
||||||
pub joined_rooms: HashMap<String, Arc<RwLock<Room>>>,
|
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")]
|
#[cfg(feature = "encryption")]
|
||||||
olm: Arc<Mutex<Option<OlmMachine>>>,
|
olm: Arc<Mutex<Option<OlmMachine>>>,
|
||||||
}
|
}
|
||||||
|
@ -92,6 +127,9 @@ impl Client {
|
||||||
session,
|
session,
|
||||||
sync_token: None,
|
sync_token: None,
|
||||||
joined_rooms: HashMap::new(),
|
joined_rooms: HashMap::new(),
|
||||||
|
current_room_id: CurrentRoom::default(),
|
||||||
|
ignored_users: Vec::new(),
|
||||||
|
push_ruleset: None,
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
olm: Arc::new(Mutex::new(olm)),
|
olm: Arc::new(Mutex::new(olm)),
|
||||||
})
|
})
|
||||||
|
@ -147,6 +185,10 @@ impl Client {
|
||||||
.collect()
|
.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>> {
|
pub(crate) fn get_or_create_room(&mut self, room_id: &str) -> &mut Arc<RwLock<Room>> {
|
||||||
#[allow(clippy::or_fun_call)]
|
#[allow(clippy::or_fun_call)]
|
||||||
self.joined_rooms
|
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.
|
/// 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
|
/// 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.
|
/// * `event` - The event that should be handled by the client.
|
||||||
pub fn receive_presence_event(&mut self, room_id: &str, event: &PresenceEvent) -> bool {
|
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.
|
// 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();
|
let mut room = self.get_or_create_room(room_id).write().unwrap();
|
||||||
room.receive_presence_event(event)
|
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.
|
/// Receive a response from a sync call.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
|
|
@ -17,7 +17,7 @@ use std::collections::HashMap;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use super::{RoomMember, User, UserId};
|
use super::{RoomMember, User, UserId};
|
||||||
use crate::api::r0 as api;
|
|
||||||
use crate::events::collections::all::{RoomEvent, StateEvent};
|
use crate::events::collections::all::{RoomEvent, StateEvent};
|
||||||
use crate::events::room::{
|
use crate::events::room::{
|
||||||
aliases::AliasesEvent,
|
aliases::AliasesEvent,
|
||||||
|
@ -33,6 +33,8 @@ use crate::events::{
|
||||||
use crate::identifiers::RoomAliasId;
|
use crate::identifiers::RoomAliasId;
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
|
|
||||||
|
use js_int::UInt;
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
@ -69,6 +71,10 @@ pub struct Room {
|
||||||
pub typing_users: Vec<UserId>,
|
pub typing_users: Vec<UserId>,
|
||||||
/// A flag indicating if the room is encrypted.
|
/// A flag indicating if the room is encrypted.
|
||||||
pub encrypted: bool,
|
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 {
|
impl RoomName {
|
||||||
|
@ -133,6 +139,8 @@ impl Room {
|
||||||
members: HashMap::new(),
|
members: HashMap::new(),
|
||||||
typing_users: Vec::new(),
|
typing_users: Vec::new(),
|
||||||
encrypted: false,
|
encrypted: false,
|
||||||
|
unread_highlight: None,
|
||||||
|
unread_notifications: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,22 +156,6 @@ impl Room {
|
||||||
true
|
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.
|
/// Add to the list of `RoomAliasId`s.
|
||||||
fn room_aliases(&mut self, alias: &RoomAliasId) -> bool {
|
fn room_aliases(&mut self, alias: &RoomAliasId) -> bool {
|
||||||
self.room_name.push_alias(alias.clone());
|
self.room_name.push_alias(alias.clone());
|
||||||
|
@ -181,6 +173,22 @@ impl Room {
|
||||||
true
|
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.
|
/// Handle a room.aliases event, updating the room state if necessary.
|
||||||
///
|
///
|
||||||
/// Returns true if the room name changed, false otherwise.
|
/// 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.
|
/// 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.
|
/// Returns true if the specific users presence has changed, false otherwise.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
|
Loading…
Reference in New Issue