commit 6c68df0a3b17e7e4b38b9543cacd6a91902f7ccd
parent b0fc038f3750fb6e979f7df9368f1bcafbed11d9
Author: Marcel <mtrnord1@gmail.com>
Date: Wed, 27 May 2020 17:52:23 +0200
Add basic backfilling
Took 55 minutes
Diffstat:
3 files changed, 109 insertions(+), 9 deletions(-)
diff --git a/src/app/matrix.rs b/src/app/matrix.rs
@@ -2,8 +2,17 @@ use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::sync::{Arc, Mutex};
+use futures_locks::RwLock;
+use js_int::UInt;
+use linked_hash_set::LinkedHashSet;
use log::*;
-use matrix_sdk::{identifiers::RoomId, Client, ClientConfig, Room, Session};
+use matrix_sdk::{
+ api::r0::{filter::RoomEventFilter, message::get_message_events::Direction},
+ events::collections::all::RoomEvent,
+ events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
+ identifiers::RoomId,
+ Client, ClientConfig, MessagesRequestBuilder, Room, Session,
+};
use serde::{Deserialize, Serialize};
use url::Url;
use wasm_bindgen_futures::spawn_local;
@@ -14,7 +23,6 @@ use yew::worker::*;
use crate::app::matrix::types::{MessageWrapper, SmallRoom};
use crate::constants::AUTH_KEY;
use crate::errors::MatrixError;
-use futures_locks::RwLock;
mod sync;
pub mod types;
@@ -52,6 +60,8 @@ pub enum Request {
SetPassword(String),
Login(),
GetLoggedIn,
+ GetUserdata,
+ GetOldMessages((RoomId, Option<String>)),
StartSync,
GetJoinedRooms,
}
@@ -64,6 +74,8 @@ pub enum Response {
Sync(MessageWrapper),
FinishedFirstSync,
JoinedRoomList(HashMap<RoomId, SmallRoom>),
+ Userdata(),
+ OldMessages(LinkedHashSet<MessageWrapper>),
}
impl Agent for MatrixAgent {
@@ -226,6 +238,78 @@ impl Agent for MatrixAgent {
}
});
}
+ Request::GetUserdata => {
+ // Noop
+ }
+ Request::GetOldMessages((room_id, from)) => {
+ let agent = self.clone();
+ let client = self.matrix_client.clone().unwrap();
+ spawn_local(async move {
+ let mut builder = &mut MessagesRequestBuilder::new();
+ builder = builder.room_id(room_id.clone());
+ if from.is_some() {
+ builder = builder.from(from.unwrap());
+ } else {
+ builder = builder.from(client.clone().sync_token().await.unwrap());
+ }
+ let filter = RoomEventFilter {
+ types: Some(vec!["m.room.message".to_string()]),
+ ..Default::default()
+ };
+ builder = builder
+ .filter(filter)
+ .direction(Direction::Backward)
+ .limit(UInt::new(30).unwrap());
+
+ let messsages = client.room_messages(builder.clone()).await.unwrap();
+ // TODO save end point for future loading
+
+ let mut wrapped_messages: LinkedHashSet<MessageWrapper> = LinkedHashSet::new();
+ for event in messsages.chunk.iter().rev() {
+ if let Ok(event) = event.deserialize() {
+ if let RoomEvent::RoomMessage(MessageEvent {
+ content:
+ MessageEventContent::Text(TextMessageEventContent {
+ body: msg_body,
+ ..
+ }),
+ sender,
+ ..
+ }) = event
+ {
+ let name = {
+ let room: Arc<RwLock<Room>> = client
+ .clone()
+ .get_joined_room(&room_id.clone())
+ .await
+ .unwrap();
+ let room = room.read().await;
+ let member = room.members.get(&sender).unwrap();
+ member
+ .display_name
+ .as_ref()
+ .map(ToString::to_string)
+ .unwrap_or(sender.to_string())
+ };
+
+ let wrapper = MessageWrapper {
+ sender_displayname: name.clone(),
+ room_id: room_id.clone(),
+ content: msg_body.clone(),
+ };
+ wrapped_messages.insert(wrapper);
+ } else {
+ continue;
+ };
+ }
+ }
+
+ for sub in agent.subscribers.iter() {
+ let resp = Response::OldMessages(wrapped_messages.clone());
+ agent.link.respond(*sub, resp);
+ }
+ });
+ }
}
}
diff --git a/src/app/matrix/sync.rs b/src/app/matrix/sync.rs
@@ -1,5 +1,6 @@
use crate::app::matrix::types::MessageWrapper;
use crate::app::matrix::Response;
+use futures_locks::RwLock;
use log::*;
use matrix_sdk::{
api::r0::sync::sync_events::Response as SyncResponse,
@@ -8,9 +9,7 @@ use matrix_sdk::{
identifiers::RoomId,
Client, Room, SyncSettings,
};
-use futures::AsyncReadExt;
use std::sync::Arc;
-use futures_locks::RwLock;
pub struct Sync<F>
where
@@ -61,7 +60,8 @@ where
}) = event
{
let name = {
- let room: Arc<RwLock<Room>> = self.matrix_client.get_joined_room(room_id).await.unwrap();
+ let room: Arc<RwLock<Room>> =
+ self.matrix_client.get_joined_room(room_id).await.unwrap();
let room = room.read().await;
let member = room.members.get(&sender).unwrap();
member
diff --git a/src/app/views/main_view.rs b/src/app/views/main_view.rs
@@ -1,4 +1,4 @@
-use std::collections::{HashMap, HashSet};
+use std::collections::{HashMap};
use std::convert::TryFrom;
use js_int::UInt;
@@ -64,11 +64,27 @@ impl Component for MainView {
self.state.events.insert(msg);
}
Response::JoinedRoomList(rooms) => self.state.rooms = rooms,
+ Response::OldMessages(messages) => {
+ // TODO this doesn't seem smart
+ let mut new_events_map = LinkedHashSet::new();
+ for event in messages.into_iter() {
+ new_events_map.insert(event);
+ }
+ for event in self.state.events.clone().into_iter() {
+ new_events_map.insert(event);
+ }
+ self.state.events = new_events_map;
+ }
_ => {}
}
}
Msg::ChangeRoom(room) => {
- self.state.current_room = Some(RoomId::try_from(room).unwrap());
+ let room_id = RoomId::try_from(room).unwrap();
+ if self.state.events.iter().filter(|x| x.room_id == room_id).collect::<LinkedHashSet<&MessageWrapper>>().is_empty() {
+ self.matrix_agent
+ .send(Request::GetOldMessages((room_id.clone(), None)));
+ }
+ self.state.current_room = Some(room_id.clone());
}
}
true
@@ -91,7 +107,7 @@ impl Component for MainView {
</div>
<div class="container uk-height-1-1 uk-width-5-6 uk-padding">
- <div class="scrollable uk-height-1-1">
+ <div class="scrollable" uk-height-viewport="expand: true">
// TODO add some content to the empty page
</div>
</div>
@@ -109,7 +125,7 @@ impl Component for MainView {
<div class="container uk-height-1-1 uk-width-5-6 uk-padding">
<h1>{ self.state.rooms.iter().filter(|(id, _)| **id == self.state.current_room.clone().unwrap()).map(|(_, room)| room.name.clone()).collect::<String>() }</h1>
- <div class="scrollable uk-height-1-1">
+ <div class="scrollable" uk-height-viewport="expand: true">
{ self.state.events.iter().filter(|x| x.room_id == self.state.current_room.clone().unwrap()).map(|event| self.get_event(event.clone())).collect::<Html>() }
</div>
</div>