2023-07-08 21:09:53 +00:00
|
|
|
use std::any::Any;
|
2023-07-09 05:58:18 +00:00
|
|
|
|
|
|
|
use anyhow::{Error, Result};
|
|
|
|
use cli_log::{error, info, warn};
|
2023-07-08 12:45:08 +00:00
|
|
|
use indexmap::IndexMap;
|
2023-07-09 05:58:18 +00:00
|
|
|
use matrix_sdk::{
|
|
|
|
room::MessagesOptions,
|
|
|
|
ruma::{
|
|
|
|
events::{room::message::RoomMessageEventContent, AnyTimelineEvent, StateEventType},
|
|
|
|
RoomId, TransactionId,
|
|
|
|
},
|
|
|
|
Client,
|
|
|
|
};
|
2023-07-04 16:32:57 +00:00
|
|
|
|
|
|
|
pub enum State {
|
|
|
|
None,
|
|
|
|
Main,
|
|
|
|
Setup,
|
|
|
|
}
|
|
|
|
|
2023-07-06 22:52:16 +00:00
|
|
|
pub struct Room {
|
|
|
|
matrix_room: matrix_sdk::room::Joined,
|
2023-07-08 12:45:08 +00:00
|
|
|
name: String,
|
2023-07-08 21:37:10 +00:00
|
|
|
encrypted: bool,
|
2023-07-06 22:52:16 +00:00
|
|
|
timeline: Vec<AnyTimelineEvent>,
|
|
|
|
timeline_end: Option<String>,
|
2023-07-08 21:09:53 +00:00
|
|
|
view_scroll: Option<usize>,
|
2023-07-06 22:52:16 +00:00
|
|
|
}
|
|
|
|
|
2023-07-04 16:32:57 +00:00
|
|
|
pub struct Status {
|
|
|
|
state: State,
|
|
|
|
account_name: String,
|
|
|
|
account_user_id: String,
|
2023-07-06 18:47:06 +00:00
|
|
|
|
|
|
|
client: Option<Client>,
|
2023-07-08 12:45:08 +00:00
|
|
|
rooms: IndexMap<String, Room>,
|
|
|
|
current_room_id: String,
|
2023-07-04 16:32:57 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 22:52:16 +00:00
|
|
|
impl Room {
|
2023-07-09 05:58:18 +00:00
|
|
|
pub fn new(matrix_room: matrix_sdk::room::Joined) -> Self {
|
2023-07-06 22:52:16 +00:00
|
|
|
Self {
|
|
|
|
matrix_room,
|
2023-07-08 12:45:08 +00:00
|
|
|
name: "".to_string(),
|
2023-07-08 21:37:10 +00:00
|
|
|
encrypted: false,
|
2023-07-06 22:52:16 +00:00
|
|
|
timeline: Vec::new(),
|
|
|
|
timeline_end: None,
|
2023-07-08 21:09:53 +00:00
|
|
|
view_scroll: None,
|
2023-07-06 22:52:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn poll_old_timeline(&mut self) -> Result<()> {
|
2023-07-08 21:09:53 +00:00
|
|
|
if let Some(AnyTimelineEvent::State(event)) = &self.timeline.get(0) {
|
|
|
|
if event.event_type() == StateEventType::RoomCreate {
|
2023-07-09 05:58:18 +00:00
|
|
|
return Ok(());
|
2023-07-08 21:09:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-06 22:52:16 +00:00
|
|
|
let mut messages_options = MessagesOptions::backward();
|
|
|
|
messages_options = match &self.timeline_end {
|
|
|
|
Some(end) => messages_options.from(end.as_str()),
|
2023-07-09 05:58:18 +00:00
|
|
|
None => messages_options,
|
2023-07-06 22:52:16 +00:00
|
|
|
};
|
|
|
|
let events = self.matrix_room.messages(messages_options).await?;
|
|
|
|
self.timeline_end = events.end;
|
|
|
|
|
|
|
|
for event in events.chunk.iter() {
|
2023-07-09 05:58:18 +00:00
|
|
|
self.timeline.insert(
|
|
|
|
0,
|
|
|
|
match event.event.deserialize() {
|
|
|
|
Ok(ev) => ev,
|
|
|
|
Err(err) => {
|
|
|
|
warn!("Failed to deserialize timeline event - {err}");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
2023-07-06 22:52:16 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-07-08 12:45:08 +00:00
|
|
|
pub fn name(&self) -> &String {
|
|
|
|
&self.name
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn update_name(&mut self) -> Result<()> {
|
|
|
|
self.name = self.matrix_room.display_name().await?.to_string();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-07-06 22:52:16 +00:00
|
|
|
pub fn timeline_add(&mut self, event: AnyTimelineEvent) {
|
|
|
|
self.timeline.push(event);
|
|
|
|
}
|
|
|
|
|
2023-07-09 05:58:18 +00:00
|
|
|
pub fn timeline(&self) -> &Vec<AnyTimelineEvent> {
|
|
|
|
&self.timeline
|
|
|
|
}
|
2023-07-08 21:09:53 +00:00
|
|
|
|
|
|
|
pub async fn send(&mut self, message: String) -> Result<()> {
|
|
|
|
let content = RoomMessageEventContent::text_plain(message);
|
|
|
|
let id = TransactionId::new();
|
|
|
|
self.matrix_room.send(content, Some(&id)).await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn view_scroll(&self) -> Option<usize> {
|
|
|
|
self.view_scroll
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_view_scroll(&mut self, scroll: Option<usize>) {
|
|
|
|
self.view_scroll = scroll;
|
|
|
|
}
|
2023-07-08 21:37:10 +00:00
|
|
|
|
|
|
|
pub fn encrypted(&self) -> bool {
|
|
|
|
self.matrix_room.is_encrypted()
|
|
|
|
}
|
2023-07-06 22:52:16 +00:00
|
|
|
}
|
|
|
|
|
2023-07-06 18:47:06 +00:00
|
|
|
impl Status {
|
|
|
|
pub fn new(client: Option<Client>) -> Self {
|
2023-07-08 12:45:08 +00:00
|
|
|
let mut rooms = IndexMap::new();
|
|
|
|
if let Some(c) = &client {
|
|
|
|
for r in c.joined_rooms() {
|
2023-07-09 05:58:18 +00:00
|
|
|
rooms.insert(r.room_id().to_string(), Room::new(r.clone()));
|
2023-07-08 12:45:08 +00:00
|
|
|
}
|
2023-07-06 18:47:06 +00:00
|
|
|
};
|
|
|
|
|
2023-07-04 16:32:57 +00:00
|
|
|
Self {
|
|
|
|
state: State::None,
|
|
|
|
account_name: "".to_string(),
|
|
|
|
account_user_id: "".to_string(),
|
2023-07-06 18:47:06 +00:00
|
|
|
client,
|
|
|
|
rooms,
|
2023-07-08 12:45:08 +00:00
|
|
|
current_room_id: "".to_string(),
|
2023-07-04 16:32:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn account_name(&self) -> &String {
|
|
|
|
&self.account_name
|
|
|
|
}
|
|
|
|
|
2023-07-06 15:34:55 +00:00
|
|
|
pub fn set_account_name(&mut self, name: String) {
|
|
|
|
self.account_name = name;
|
|
|
|
}
|
|
|
|
|
2023-07-04 16:32:57 +00:00
|
|
|
pub fn account_user_id(&self) -> &String {
|
|
|
|
&self.account_user_id
|
|
|
|
}
|
|
|
|
|
2023-07-06 15:34:55 +00:00
|
|
|
pub fn set_account_user_id(&mut self, user_id: String) {
|
|
|
|
self.account_user_id = user_id;
|
|
|
|
}
|
|
|
|
|
2023-07-06 22:52:16 +00:00
|
|
|
pub fn room(&self) -> Option<&Room> {
|
2023-07-08 12:45:08 +00:00
|
|
|
self.rooms.get(self.current_room_id.as_str())
|
2023-07-04 16:32:57 +00:00
|
|
|
}
|
2023-07-06 22:52:16 +00:00
|
|
|
|
2023-07-08 21:09:53 +00:00
|
|
|
pub fn room_mut(&mut self) -> Option<&mut Room> {
|
|
|
|
self.rooms.get_mut(self.current_room_id.as_str())
|
|
|
|
}
|
|
|
|
|
2023-07-08 12:45:08 +00:00
|
|
|
pub fn rooms(&self) -> &IndexMap<String, Room> {
|
2023-07-06 22:52:16 +00:00
|
|
|
&self.rooms
|
|
|
|
}
|
|
|
|
|
2023-07-08 12:45:08 +00:00
|
|
|
pub fn rooms_mut(&mut self) -> &mut IndexMap<String, Room> {
|
2023-07-06 22:52:16 +00:00
|
|
|
&mut self.rooms
|
|
|
|
}
|
2023-07-08 12:45:08 +00:00
|
|
|
|
|
|
|
pub fn set_room(&mut self, room_id: &RoomId) -> Result<()> {
|
|
|
|
if self.rooms.contains_key(room_id.as_str()) {
|
|
|
|
self.current_room_id = room_id.to_string();
|
|
|
|
Ok(())
|
|
|
|
} else {
|
2023-07-09 05:58:18 +00:00
|
|
|
Err(Error::msg(format!(
|
|
|
|
"failed to set room -> invalid room id {}",
|
|
|
|
room_id.to_string()
|
|
|
|
)))
|
2023-07-08 12:45:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_room_by_index(&mut self, room_index: usize) -> Result<()> {
|
|
|
|
if let Some((room_id, _)) = self.rooms.get_index(room_index) {
|
|
|
|
self.current_room_id = room_id.clone();
|
|
|
|
Ok(())
|
|
|
|
} else {
|
2023-07-09 05:58:18 +00:00
|
|
|
Err(Error::msg(format!(
|
|
|
|
"failed to set room -> invalid room index {}",
|
|
|
|
room_index
|
|
|
|
)))
|
2023-07-08 12:45:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_room(&self, room_id: &RoomId) -> Option<&Room> {
|
|
|
|
self.rooms.get(room_id.as_str())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_room_mut(&mut self, room_id: &RoomId) -> Option<&mut Room> {
|
|
|
|
self.rooms.get_mut(room_id.as_str())
|
|
|
|
}
|
2023-07-09 05:58:18 +00:00
|
|
|
|
2023-07-04 16:32:57 +00:00
|
|
|
pub fn state(&self) -> &State {
|
|
|
|
&self.state
|
|
|
|
}
|
2023-07-09 05:58:18 +00:00
|
|
|
|
2023-07-04 16:32:57 +00:00
|
|
|
pub fn set_state(&mut self, state: State) {
|
|
|
|
self.state = state;
|
|
|
|
}
|
2023-07-09 05:58:18 +00:00
|
|
|
}
|