commit 76fc33e66a85a7bc7b30fab5675842d246b679f1
parent b8d005b9bb1f55bf0c9e0e72c5a179e94a214462
Author: Marcel <mtrnord1@gmail.com>
Date: Fri, 29 May 2020 18:36:42 +0200
Add parsing of image and notice events
Took 1 hour 7 minutes
Diffstat:
6 files changed, 211 insertions(+), 59 deletions(-)
diff --git a/src/app/components/event_list.rs b/src/app/components/event_list.rs
@@ -3,7 +3,6 @@ use log::*;
use matrix_sdk::identifiers::{EventId, RoomId};
use serde::{Deserialize, Serialize};
use yew::prelude::*;
-use yewtil::NeqAssign;
use crate::app::matrix::types::MessageWrapper;
use crate::app::matrix::{MatrixAgent, Request, Response};
@@ -189,9 +188,39 @@ impl Component for EventList {
}
impl EventList {
+ // Typeinspection of IDEA breaks with this :D
+ //noinspection RsTypeCheck
fn get_event(&self, event: MessageWrapper) -> Html {
- html! {
- <p>{event.sender_displayname.unwrap_or(event.sender.to_string()).clone()}{": "}{event.content.clone()}</p>
+ if event.event_type == "m.text" {
+ html! {
+ <p>{event.sender_displayname.unwrap_or(event.sender.to_string()).clone()}{": "}{event.content.clone()}</p>
+ }
+ } else if event.event_type == "m.notice" {
+ html! {
+ <p style="opacity: .6;">{event.sender_displayname.unwrap_or(event.sender.to_string()).clone()}{": "}{event.content.clone()}</p>
+ }
+ } else if event.event_type == "m.image" {
+ let caption = format!(
+ "{}: {}",
+ event
+ .sender_displayname
+ .unwrap_or(event.sender.to_string())
+ .clone(),
+ event.content.clone()
+ );
+ let thumbnail = match event.info.clone().unwrap().thumbnail_url {
+ None => event.info.clone().unwrap().url.clone().unwrap(),
+ Some(v) => v,
+ };
+ html! {
+ <div uk-lightbox="">
+ <a class="uk-inline" href=event.info.clone().unwrap().url.clone().unwrap() data-caption=caption.clone() >
+ <img src=thumbnail.clone() alt=caption.clone() />
+ </a>
+ </div>
+ }
+ } else {
+ html! {}
}
}
}
diff --git a/src/app/components/room_list.rs b/src/app/components/room_list.rs
@@ -3,11 +3,11 @@ use std::collections::HashMap;
use log::*;
use matrix_sdk::{identifiers::RoomId, js_int::UInt};
use serde::{Deserialize, Serialize};
+use wasm_bindgen::JsCast;
+use web_sys::HtmlElement;
use yew::prelude::*;
use yew::{Bridge, Bridged, Component, ComponentLink, Html};
use yewtil::NeqAssign;
-use web_sys::HtmlElement;
-use wasm_bindgen::JsCast;
use crate::app::matrix::types::SmallRoom;
use crate::app::matrix::{MatrixAgent, Request, Response};
diff --git a/src/app/matrix.rs b/src/app/matrix.rs
@@ -20,7 +20,7 @@ use yew::format::Json;
use yew::services::{storage::Area, StorageService};
use yew::worker::*;
-use crate::app::matrix::types::{MessageWrapper, SmallRoom};
+use crate::app::matrix::types::{ImageInfoWrapper, MessageWrapper, SmallRoom};
use crate::constants::AUTH_KEY;
use crate::errors::MatrixError;
use comrak::{format_html, parse_document, Arena, ComrakOptions};
@@ -285,24 +285,59 @@ impl Agent for MatrixAgent {
for event in messsages.chunk.iter().rev() {
if let Ok(event) = event.deserialize() {
match event {
- RoomEvent::RoomMessage(event) => match event.content {
- MessageEventContent::Text(_) => {
- let mut wrapped_event: MessageWrapper =
- event.try_into().expect("m.room.message");
-
- if wrapped_event.room_id.is_none() {
- wrapped_event.room_id = Some(room_id.clone());
+ RoomEvent::RoomMessage(event) => {
+ let wrapped_event_result: Result<MessageWrapper, MatrixError> =
+ event.try_into();
+ match wrapped_event_result {
+ Ok(mut wrapped_event) => {
+ if wrapped_event.room_id.is_none() {
+ wrapped_event.room_id = Some(room_id.clone());
+ }
+
+ wrapped_event.sender_displayname = Some(
+ wrapped_event.get_displayname(client.clone()).await,
+ );
+
+ // Convert mxc URLs
+ if wrapped_event.info.is_some() {
+ let mxc_url = wrapped_event
+ .info
+ .clone()
+ .unwrap()
+ .url
+ .clone()
+ .unwrap();
+ let download_url = wrapped_event
+ .get_media_download_url(
+ client.clone(),
+ mxc_url,
+ );
+ let mxc_thumbnail_url = wrapped_event
+ .info
+ .clone()
+ .unwrap()
+ .thumbnail_url
+ .clone()
+ .unwrap();
+ let thumbnail_download_url = wrapped_event
+ .get_media_download_url(
+ client.clone(),
+ mxc_thumbnail_url,
+ );
+ wrapped_event.info = Some(ImageInfoWrapper {
+ url: Some(download_url),
+ thumbnail_url: Some(thumbnail_download_url),
+ });
+ }
+
+ wrapped_messages.insert(wrapped_event);
+ }
+ Err(_) => {
+ // Ignore events we cant parse
+ continue;
}
-
- wrapped_event.sender_displayname = Some(
- wrapped_event.get_displayname(client.clone()).await,
- );
- wrapped_messages.insert(wrapped_event);
- }
- _ => {
- return;
}
- },
+ }
_ => {
continue;
}
diff --git a/src/app/matrix/sync.rs b/src/app/matrix/sync.rs
@@ -3,11 +3,12 @@ use std::convert::TryInto;
use log::*;
use matrix_sdk::{
api::r0::sync::sync_events::Response as SyncResponse, events::collections::all::RoomEvent,
- events::room::message::MessageEventContent, identifiers::RoomId, Client, SyncSettings,
+ identifiers::RoomId, Client, SyncSettings,
};
-use crate::app::matrix::types::MessageWrapper;
+use crate::app::matrix::types::{MessageWrapper, ImageInfoWrapper};
use crate::app::matrix::Response;
+use crate::errors::MatrixError;
use yew::Callback;
pub struct Sync {
@@ -48,27 +49,60 @@ impl Sync {
// TODO handle all messages...
match event {
- RoomEvent::RoomMessage(event) => match event.content {
- MessageEventContent::Text(_) => {
- let mut wrapped_event: MessageWrapper =
- event.try_into().expect("m.room.message");
+ RoomEvent::RoomMessage(event) => {
+ let wrapped_event_result: Result<MessageWrapper, MatrixError> = event.try_into();
+ match wrapped_event_result {
+ Ok(mut wrapped_event) => {
+ if wrapped_event.room_id.is_none() {
+ wrapped_event.room_id = Some(room_id.clone());
+ }
- if wrapped_event.room_id.is_none() {
- wrapped_event.room_id = Some(room_id.clone());
- }
+ wrapped_event.sender_displayname = Some(
+ wrapped_event
+ .get_displayname(self.matrix_client.clone())
+ .await,
+ );
- wrapped_event.sender_displayname = Some(
- wrapped_event
- .get_displayname(self.matrix_client.clone())
- .await,
- );
- let resp = Response::Sync(wrapped_event);
- self.callback.emit(resp);
- }
- _ => {
- return;
+ // Convert mxc URLs
+ if wrapped_event.info.is_some() {
+ let mxc_url = wrapped_event
+ .info
+ .clone()
+ .unwrap()
+ .url
+ .clone()
+ .unwrap();
+ let download_url = wrapped_event
+ .get_media_download_url(
+ self.matrix_client.clone(),
+ mxc_url,
+ );
+ let mxc_thumbnail_url = wrapped_event
+ .info
+ .clone()
+ .unwrap()
+ .thumbnail_url
+ .clone()
+ .unwrap();
+ let thumbnail_download_url = wrapped_event
+ .get_media_download_url(
+ self.matrix_client.clone(),
+ mxc_thumbnail_url,
+ );
+ wrapped_event.info = Some(ImageInfoWrapper {
+ url: Some(download_url),
+ thumbnail_url: Some(thumbnail_download_url),
+ });
+ }
+ let resp = Response::Sync(wrapped_event);
+ self.callback.emit(resp);
+ }
+ Err(_) => {
+ // Ignore events we cant parse
+ return;
+ }
}
- },
+ }
_ => {
return;
}
diff --git a/src/app/matrix/types.rs b/src/app/matrix/types.rs
@@ -3,13 +3,15 @@ use std::sync::Arc;
use futures_locks::RwLock;
use matrix_sdk::{
- events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
+ events::room::message::{MessageEvent, MessageEventContent},
identifiers::{EventId, RoomId, UserId},
js_int::UInt,
Client, Room,
};
use serde::{Deserialize, Serialize};
+use crate::errors::MatrixError;
+
// TODO: Add Into trait
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SmallRoom {
@@ -20,13 +22,21 @@ pub struct SmallRoom {
}
#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
+pub struct ImageInfoWrapper {
+ pub(crate) url: Option<String>,
+ pub(crate) thumbnail_url: Option<String>,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone, Hash, Eq, PartialEq)]
pub struct MessageWrapper {
pub(crate) sender_displayname: Option<String>,
pub(crate) room_id: Option<RoomId>,
pub(crate) event_id: EventId,
+ pub(crate) event_type: String,
pub(crate) sender: UserId,
// TODO use ruma structs
pub(crate) content: String,
+ pub(crate) info: Option<ImageInfoWrapper>,
}
impl MessageWrapper {
@@ -48,27 +58,69 @@ impl MessageWrapper {
.map(ToString::to_string)
.unwrap_or(self.sender.clone().to_string())
}
+
+ pub fn get_media_download_url(&self, client: Client, mxc_url: String) -> String {
+ let url_parts_raw = mxc_url.clone().replace("mxc://", "");
+ let url_parts: Vec<&str> = url_parts_raw.split("/").collect();
+ let server_name = url_parts.first().unwrap().to_string();
+ let media_id = url_parts.last().unwrap().to_string();
+ let new_path = format!(
+ "_matrix/media/r0/download/{}/{}/fix.jpg",
+ server_name.clone(),
+ media_id.clone()
+ );
+ let mut new_url = client.clone().homeserver().clone();
+ new_url.set_path(new_path.as_str());
+ new_url.to_string()
+ }
}
impl TryFrom<MessageEvent> for MessageWrapper {
- type Error = ();
+ type Error = MatrixError;
fn try_from(event: MessageEvent) -> Result<Self, Self::Error> {
- return if let MessageEvent {
- content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
- sender,
- ..
- } = event
- {
- Ok(MessageWrapper {
- sender_displayname: None, // We cant get it without a Client and therefor cant calculate it here
- room_id: event.room_id,
- event_id: event.event_id,
- sender,
- content: msg_body,
- })
- } else {
- Err(())
+ return match event.content {
+ MessageEventContent::Text(text_event) => {
+ Ok(MessageWrapper {
+ sender_displayname: None, // We cant get it without a Client and therefor cant calculate it here
+ room_id: event.room_id,
+ event_id: event.event_id,
+ event_type: "m.text".to_string(),
+ sender: event.sender,
+ content: text_event.body,
+ info: None,
+ })
+ }
+ MessageEventContent::Image(image_event) => {
+ let thumbnail_url = match image_event.info {
+ None => None,
+ Some(i) => i.thumbnail_url,
+ };
+ Ok(MessageWrapper {
+ sender_displayname: None, // We cant get it without a Client and therefor cant calculate it here
+ room_id: event.room_id,
+ event_id: event.event_id,
+ event_type: "m.image".to_string(),
+ sender: event.sender,
+ content: image_event.body,
+ info: Some(ImageInfoWrapper {
+ url: image_event.url,
+ thumbnail_url,
+ }),
+ })
+ }
+ MessageEventContent::Notice(notice_event) => {
+ Ok(MessageWrapper {
+ sender_displayname: None, // We cant get it without a Client and therefor cant calculate it here
+ room_id: event.room_id,
+ event_id: event.event_id,
+ event_type: "m.notice".to_string(),
+ sender: event.sender,
+ content: notice_event.body,
+ info: None,
+ })
+ }
+ _ => Err(MatrixError::UnsupportedEvent),
};
}
}
diff --git a/src/errors.rs b/src/errors.rs
@@ -7,4 +7,6 @@ pub enum MatrixError {
MissingClient,
#[error("Missing required Data")]
MissingFields,
+ #[error("This Matrix Event is not yet supported by Daydream")]
+ UnsupportedEvent,
}