use std::collections::HashMap;
use matrix_sdk_common::{
async_trait,
identifiers::{RoomId, UserId},
push::Ruleset,
AsyncTraitDeps,
};
use serde::{Deserialize, Serialize};
#[cfg(not(target_arch = "wasm32"))]
mod json_store;
#[cfg(not(target_arch = "wasm32"))]
pub use json_store::JsonStore;
use crate::{
client::{BaseClient, Token},
Result, Room, RoomState, Session,
};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ClientState {
pub sync_token: Option<Token>,
pub ignored_users: Vec<UserId>,
pub push_ruleset: Option<Ruleset>,
}
impl PartialEq for ClientState {
fn eq(&self, other: &Self) -> bool {
self.sync_token == other.sync_token && self.ignored_users == other.ignored_users
}
}
impl ClientState {
#[allow(clippy::eval_order_dependence)]
pub async fn from_base_client(client: &BaseClient) -> ClientState {
let BaseClient {
sync_token,
ignored_users,
push_ruleset,
..
} = client;
Self {
sync_token: sync_token.read().await.clone(),
ignored_users: ignored_users.read().await.clone(),
push_ruleset: push_ruleset.read().await.clone(),
}
}
}
#[derive(Debug)]
pub struct AllRooms {
pub joined: HashMap<RoomId, Room>,
pub invited: HashMap<RoomId, Room>,
pub left: HashMap<RoomId, Room>,
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait StateStore: AsyncTraitDeps {
async fn load_client_state(&self, _: &Session) -> Result<Option<ClientState>>;
async fn load_all_rooms(&self) -> Result<AllRooms>;
async fn store_client_state(&self, _: ClientState) -> Result<()>;
async fn store_room_state(&self, _: RoomState<&Room>) -> Result<()>;
async fn delete_room_state(&self, _room: RoomState<&RoomId>) -> Result<()>;
}
#[cfg(test)]
mod test {
use super::*;
use std::collections::HashMap;
use crate::identifiers::{room_id, user_id};
#[test]
fn serialize() {
let id = room_id!("!roomid:example.com");
let user = user_id!("@example:example.com");
let room = Room::new(&id, &user);
let state = ClientState {
sync_token: Some("hello".into()),
ignored_users: vec![user],
push_ruleset: None,
};
assert_eq!(
r#"{"sync_token":"hello","ignored_users":["@example:example.com"],"push_ruleset":null}"#,
serde_json::to_string(&state).unwrap()
);
let mut joined_rooms = HashMap::new();
joined_rooms.insert(id, room);
#[cfg(not(feature = "messages"))]
assert_eq!(
serde_json::json!({
"!roomid:example.com": {
"room_id": "!roomid:example.com",
"room_name": {
"name": null,
"canonical_alias": null,
"aliases": [],
"heroes": [],
"joined_member_count": null,
"invited_member_count": null
},
"own_user_id": "@example:example.com",
"creator": null,
"direct_target": null,
"joined_members": {},
"invited_members": {},
"typing_users": [],
"power_levels": null,
"encrypted": null,
"unread_highlight": null,
"unread_notifications": null,
"tombstone": null
}
}),
serde_json::to_value(&joined_rooms).unwrap()
);
#[cfg(feature = "messages")]
assert_eq!(
serde_json::json!({
"!roomid:example.com": {
"room_id": "!roomid:example.com",
"room_name": {
"name": null,
"canonical_alias": null,
"aliases": [],
"heroes": [],
"joined_member_count": null,
"invited_member_count": null
},
"own_user_id": "@example:example.com",
"creator": null,
"direct_target": null,
"joined_members": {},
"invited_members": {},
"messages": [],
"typing_users": [],
"power_levels": null,
"encrypted": null,
"unread_highlight": null,
"unread_notifications": null,
"tombstone": null
}
}),
serde_json::to_value(&joined_rooms).unwrap()
);
}
#[test]
fn deserialize() {
let id = room_id!("!roomid:example.com");
let user = user_id!("@example:example.com");
let room = Room::new(&id, &user);
let state = ClientState {
sync_token: Some("hello".into()),
ignored_users: vec![user],
push_ruleset: None,
};
let json = serde_json::to_string(&state).unwrap();
assert_eq!(state, serde_json::from_str(&json).unwrap());
let mut joined_rooms = HashMap::new();
joined_rooms.insert(id, room);
let json = serde_json::to_string(&joined_rooms).unwrap();
assert_eq!(joined_rooms, serde_json::from_str(&json).unwrap());
}
}