feature (status - rooms): Implemented a timeline event caching layer

This commit is contained in:
antifallobst 2023-07-07 00:52:16 +02:00
parent 1eb04dd23a
commit f8bf6ee07d
3 changed files with 103 additions and 44 deletions

View File

@ -139,6 +139,13 @@ impl App<'_> {
self.status.set_account_name(name); self.status.set_account_name(name);
self.status.set_account_user_id(user_id); self.status.set_account_user_id(user_id);
for room in self.status.rooms_mut() {
room.poll_old_timeline().await?;
room.poll_old_timeline().await?;
room.poll_old_timeline().await?;
}
info!("Initializing client for the current account"); info!("Initializing client for the current account");
Ok(()) Ok(())

View File

@ -1,5 +1,9 @@
use matrix_sdk::Client; use matrix_sdk::{Client,
use matrix_sdk::ruma::{room_id, RoomId, ServerName}; ruma::{events::{AnyTimelineEvent}},
deserialized_responses::TimelineEvent,
room::MessagesOptions};
use anyhow::{Result, Error};
use cli_log::{error, warn, info};
pub enum State { pub enum State {
None, None,
@ -7,20 +11,70 @@ pub enum State {
Setup, Setup,
} }
pub struct Room {
matrix_room: matrix_sdk::room::Joined,
timeline: Vec<AnyTimelineEvent>,
timeline_end: Option<String>,
}
pub struct Status { pub struct Status {
state: State, state: State,
account_name: String, account_name: String,
account_user_id: String, account_user_id: String,
client: Option<Client>, client: Option<Client>,
rooms: Vec<matrix_sdk::room::Joined>, rooms: Vec<Room>,
current_room_id: Option<u32>, current_room_id: Option<u32>,
} }
impl Room {
pub fn new (matrix_room: matrix_sdk::room::Joined) -> Self {
Self {
matrix_room,
timeline: Vec::new(),
timeline_end: None,
}
}
pub async fn poll_old_timeline(&mut self) -> Result<()> {
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 timeline_add(&mut self, event: AnyTimelineEvent) {
self.timeline.push(event);
}
pub fn timeline(&self) -> &Vec<AnyTimelineEvent> { &self.timeline }
}
impl Status { impl Status {
pub fn new(client: Option<Client>) -> Self { pub fn new(client: Option<Client>) -> Self {
let rooms = match &client { let rooms = match &client {
Some(c) => c.joined_rooms(), Some(c) => {
c.joined_rooms()
.iter()
.map(|r| {
Room::new(r.clone())
})
.collect::<Vec<_>>()
},
None => Vec::new(), None => Vec::new(),
}; };
@ -50,9 +104,17 @@ impl Status {
self.account_user_id = user_id; self.account_user_id = user_id;
} }
pub fn room(&self) -> Option<&matrix_sdk::room::Joined> { pub fn room(&self) -> Option<&Room> {
self.rooms.get(self.current_room_id? as usize) self.rooms.get(self.current_room_id? as usize)
} }
pub fn rooms(&self) -> &Vec<Room> {
&self.rooms
}
pub fn rooms_mut(&mut self) -> &mut Vec<Room> {
&mut self.rooms
}
pub fn state(&self) -> &State { pub fn state(&self) -> &State {
&self.state &self.state

View File

@ -276,52 +276,42 @@ impl UI<'_> {
status_content.extend(Text::styled(status.account_user_id(), Style::default())); status_content.extend(Text::styled(status.account_user_id(), Style::default()));
status_content.extend(Text::styled("settings", Style::default().fg(Color::LightMagenta).add_modifier(Modifier::ITALIC | Modifier::UNDERLINED))); status_content.extend(Text::styled("settings", Style::default().fg(Color::LightMagenta).add_modifier(Modifier::ITALIC | Modifier::UNDERLINED)));
let messages_config = MessagesOptions::backward();
let messages_content = match status.room() { let messages_content = match status.room() {
Some(r) => { Some(r) => {
r.messages(messages_config) r.timeline()
.await?
.chunk
.iter() .iter()
.rev()
.map(|event| { .map(|event| {
match event.event.deserialize() { match event {
Ok(timeline_event) => match timeline_event {
// Message Like Events // Message Like Events
AnyTimelineEvent::MessageLike(message_like_event) => { AnyTimelineEvent::MessageLike(message_like_event) => {
let (content, color) = match &message_like_event { let (content, color) = match &message_like_event {
AnyMessageLikeEvent::RoomMessage(room_message_event) => { AnyMessageLikeEvent::RoomMessage(room_message_event) => {
let message_content = &room_message_event let message_content = &room_message_event
.as_original() .as_original()
.unwrap() .unwrap()
.content .content
.body(); .body();
(message_content.to_string(), Color::White) (message_content.to_string(), Color::White)
}, },
_ => ("~~~ not supported message like event ~~~".to_string(), Color::Red) _ => ("~~~ not supported message like event ~~~".to_string(), Color::Red)
}; };
Spans::from(vec![ Spans::from(vec![
Span::styled(message_like_event.sender().to_string(), Style::default().fg(Color::Cyan)), Span::styled(message_like_event.sender().to_string(), Style::default().fg(Color::Cyan)),
Span::styled(": ", Style::default().fg(Color::Cyan)), Span::styled(": ", Style::default().fg(Color::Cyan)),
Span::styled(content, Style::default().fg(color)), Span::styled(content, Style::default().fg(color)),
]) ])
},
// State Events
AnyTimelineEvent::State(state) => {
Spans::from(vec![
Span::styled(state.sender().to_string(), Style::default().fg(Color::DarkGray)),
Span::styled(": ", Style::default().fg(Color::DarkGray)),
Span::styled(state.event_type().to_string(), Style::default().fg(Color::DarkGray))
])
}
}, },
Err(_) => Spans::from(
Span::styled("Failed to deserialize event", Style::default().fg(Color::Red)) // State Events
) AnyTimelineEvent::State(state) => {
Spans::from(vec![
Span::styled(state.sender().to_string(), Style::default().fg(Color::DarkGray)),
Span::styled(": ", Style::default().fg(Color::DarkGray)),
Span::styled(state.event_type().to_string(), Style::default().fg(Color::DarkGray))
])
}
} }
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()