feature (status - rooms): Implemented a timeline event caching layer
This commit is contained in:
parent
1eb04dd23a
commit
f8bf6ee07d
|
@ -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(())
|
||||||
|
|
|
@ -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,10 +104,18 @@ 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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<_>>()
|
||||||
|
|
Reference in New Issue