192 lines
5.2 KiB
Rust
192 lines
5.2 KiB
Rust
use std::any::Any;
|
|
use indexmap::IndexMap;
|
|
use matrix_sdk::{Client,
|
|
ruma::{events::{AnyTimelineEvent,
|
|
room::message::RoomMessageEventContent,
|
|
StateEventType},
|
|
RoomId,
|
|
TransactionId},
|
|
room::MessagesOptions};
|
|
use anyhow::{Result, Error};
|
|
use cli_log::{error, warn, info};
|
|
|
|
pub enum State {
|
|
None,
|
|
Main,
|
|
Setup,
|
|
}
|
|
|
|
pub struct Room {
|
|
matrix_room: matrix_sdk::room::Joined,
|
|
name: String,
|
|
timeline: Vec<AnyTimelineEvent>,
|
|
timeline_end: Option<String>,
|
|
view_scroll: Option<usize>,
|
|
}
|
|
|
|
pub struct Status {
|
|
state: State,
|
|
account_name: String,
|
|
account_user_id: String,
|
|
|
|
client: Option<Client>,
|
|
rooms: IndexMap<String, Room>,
|
|
current_room_id: String,
|
|
}
|
|
|
|
impl Room {
|
|
pub fn new (matrix_room: matrix_sdk::room::Joined) -> Self {
|
|
Self {
|
|
matrix_room,
|
|
name: "".to_string(),
|
|
timeline: Vec::new(),
|
|
timeline_end: None,
|
|
view_scroll: None,
|
|
}
|
|
}
|
|
|
|
pub async fn poll_old_timeline(&mut self) -> Result<()> {
|
|
if let Some(AnyTimelineEvent::State(event)) = &self.timeline.get(0) {
|
|
if event.event_type() == StateEventType::RoomCreate {
|
|
return Ok(())
|
|
}
|
|
}
|
|
|
|
let mut messages_options = MessagesOptions::backward();
|
|
messages_options = match &self.timeline_end {
|
|
Some(end) => messages_options.from(end.as_str()),
|
|
None => messages_options
|
|
};
|
|
let events = self.matrix_room.messages(messages_options).await?;
|
|
self.timeline_end = events.end;
|
|
|
|
for event in events.chunk.iter() {
|
|
self.timeline.insert(0, match event.event.deserialize() {
|
|
Ok(ev) => ev,
|
|
Err(err) => {
|
|
warn!("Failed to deserialize timeline event - {err}");
|
|
continue;
|
|
}
|
|
});
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
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(())
|
|
}
|
|
|
|
pub fn timeline_add(&mut self, event: AnyTimelineEvent) {
|
|
self.timeline.push(event);
|
|
}
|
|
|
|
pub fn timeline(&self) -> &Vec<AnyTimelineEvent> { &self.timeline }
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
impl Status {
|
|
pub fn new(client: Option<Client>) -> Self {
|
|
let mut rooms = IndexMap::new();
|
|
if let Some(c) = &client {
|
|
for r in c.joined_rooms() {
|
|
rooms.insert(
|
|
r.room_id().to_string(),
|
|
Room::new(r.clone()));
|
|
}
|
|
};
|
|
|
|
Self {
|
|
state: State::None,
|
|
account_name: "".to_string(),
|
|
account_user_id: "".to_string(),
|
|
client,
|
|
rooms,
|
|
current_room_id: "".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn account_name(&self) -> &String {
|
|
&self.account_name
|
|
}
|
|
|
|
pub fn set_account_name(&mut self, name: String) {
|
|
self.account_name = name;
|
|
}
|
|
|
|
pub fn account_user_id(&self) -> &String {
|
|
&self.account_user_id
|
|
}
|
|
|
|
pub fn set_account_user_id(&mut self, user_id: String) {
|
|
self.account_user_id = user_id;
|
|
}
|
|
|
|
pub fn room(&self) -> Option<&Room> {
|
|
self.rooms.get(self.current_room_id.as_str())
|
|
}
|
|
|
|
pub fn room_mut(&mut self) -> Option<&mut Room> {
|
|
self.rooms.get_mut(self.current_room_id.as_str())
|
|
}
|
|
|
|
pub fn rooms(&self) -> &IndexMap<String, Room> {
|
|
&self.rooms
|
|
}
|
|
|
|
pub fn rooms_mut(&mut self) -> &mut IndexMap<String, Room> {
|
|
&mut self.rooms
|
|
}
|
|
|
|
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 {
|
|
Err(Error::msg(format!("failed to set room -> invalid room id {}", room_id.to_string())))
|
|
}
|
|
}
|
|
|
|
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 {
|
|
Err(Error::msg(format!("failed to set room -> invalid room index {}", room_index)))
|
|
}
|
|
}
|
|
|
|
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())
|
|
}
|
|
|
|
pub fn state(&self) -> &State {
|
|
&self.state
|
|
}
|
|
|
|
pub fn set_state(&mut self, state: State) {
|
|
self.state = state;
|
|
}
|
|
} |