commit c9159791a7d70099c41455a00177d99115771165
parent 774306eb22d4e2e14e42735183651e5e3b249c47
Author: Marcel <mtrnord1@gmail.com>
Date: Tue, 16 Jun 2020 20:32:15 +0200
Linkify links in non formatted body events
Took 22 minutes
Diffstat:
7 files changed, 125 insertions(+), 61 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -40,6 +40,9 @@ tr = { version = "0.1.3", default-features = false, features = ["gettext"]}
i18n-embed = { version = "0.4", features = ["web-sys-requester"] }
rust-embed = { version = "5", features = ["debug-embed", "compression"]}
+# Make links links again!
+linkify = "0.4.0"
+
# Used for lightboxes
rand = "0.7"
diff --git a/src/app/components/event_list.rs b/src/app/components/event_list.rs
@@ -7,11 +7,8 @@ use matrix_sdk::{
use std::collections::HashMap;
use yew::prelude::*;
-use crate::app::components::events::{
- get_sender_avatar, image::Image, notice::Notice, text::Text, video::Video,
-};
+use crate::app::components::events::{image::Image, notice::Notice, text::Text, video::Video};
use crate::app::matrix::{MatrixAgent, Request, Response};
-use crate::utils::notifications::Notifications;
pub struct EventList {
link: ComponentLink<Self>,
diff --git a/src/app/components/events/notice.rs b/src/app/components/events/notice.rs
@@ -1,8 +1,11 @@
+use linkify::LinkFinder;
use matrix_sdk::{
events::room::message::{MessageEvent, NoticeMessageEventContent},
Room,
};
+use web_sys::Node;
use yew::prelude::*;
+use yew::virtual_dom::VNode;
use crate::app::components::events::{get_sender_displayname, is_new_user};
@@ -59,28 +62,53 @@ impl Component for Notice {
"".to_string()
};
- if new_user {
- html! {
- <p style="opacity: .6;"><displayname>{sender_displayname}{": "}</displayname>
- {
- self.props
- .notice_event
- .clone()
- .unwrap().body.clone()
- }
- </p>
+ let mut pure_content = self.props.notice_event.clone().unwrap().body.clone();
+ let finder = LinkFinder::new();
+ let pure_content_clone = pure_content.clone();
+ let links: Vec<_> = finder.links(&pure_content_clone).collect();
+
+ let content = if !links.is_empty() {
+ for link in links {
+ let html_link = format!("<a href={}>{}</a>", link.as_str(), link.as_str());
+ pure_content.replace_range(link.start()..link.end(), &html_link);
}
+ pure_content.clone()
} else {
- html! {
- <p style="opacity: .6;">
- {
- self.props
- .notice_event
- .clone()
- .unwrap().body.clone()
- }
- </p>
- }
+ pure_content
+ };
+
+ if new_user {
+ let full_html = format!(
+ "<p style=\"opacity: .6;\"><displayname>{}: </displayname>{}</p>",
+ sender_displayname,
+ content.clone()
+ );
+ let js_text_event = {
+ let div = web_sys::window()
+ .unwrap()
+ .document()
+ .unwrap()
+ .create_element("p")
+ .unwrap();
+ div.set_inner_html(full_html.as_str());
+ div
+ };
+ let node = Node::from(js_text_event);
+ VNode::VRef(node)
+ } else {
+ let full_html = format!("<p style=\"opacity: .6;\">{}</p>", content.clone());
+ let js_text_event = {
+ let div = web_sys::window()
+ .unwrap()
+ .document()
+ .unwrap()
+ .create_element("p")
+ .unwrap();
+ div.set_inner_html(full_html.as_str());
+ div
+ };
+ let node = Node::from(js_text_event);
+ VNode::VRef(node)
}
}
}
diff --git a/src/app/components/events/text.rs b/src/app/components/events/text.rs
@@ -1,4 +1,5 @@
use crate::app::components::events::{get_sender_displayname, is_new_user};
+use linkify::LinkFinder;
use matrix_sdk::{
events::room::message::{MessageEvent, TextMessageEventContent},
Room,
@@ -59,6 +60,22 @@ impl Component for Text {
} else {
"".to_string()
};
+
+ let mut pure_content = self.props.text_event.clone().unwrap().body.clone();
+ let finder = LinkFinder::new();
+ let pure_content_clone = pure_content.clone();
+ let links: Vec<_> = finder.links(&pure_content_clone).collect();
+
+ let content = if !links.is_empty() {
+ for link in links {
+ let html_link = format!("<a href={}>{}</a>", link.as_str(), link.as_str());
+ pure_content.replace_range(link.start()..link.end(), &html_link);
+ }
+ pure_content.clone()
+ } else {
+ pure_content
+ };
+
if self.props.text_event.clone().unwrap().formatted.is_some() {
let message = if new_user {
format!(
@@ -94,13 +111,37 @@ impl Component for Text {
let node = Node::from(js_text_event);
VNode::VRef(node)
} else if new_user {
- html! {
- <p><displayname>{sender_displayname}{": "}</displayname>{self.props.text_event.clone().unwrap().body.clone()}</p>
- }
+ let full_html = format!(
+ "<p><displayname>{}: </displayname>{}</p>",
+ sender_displayname,
+ content.clone()
+ );
+ let js_text_event = {
+ let div = web_sys::window()
+ .unwrap()
+ .document()
+ .unwrap()
+ .create_element("p")
+ .unwrap();
+ div.set_inner_html(full_html.as_str());
+ div
+ };
+ let node = Node::from(js_text_event);
+ VNode::VRef(node)
} else {
- html! {
- <p>{self.props.text_event.clone().unwrap().body.clone()}</p>
- }
+ let full_html = format!("<p>{}</p>", content.clone());
+ let js_text_event = {
+ let div = web_sys::window()
+ .unwrap()
+ .document()
+ .unwrap()
+ .create_element("p")
+ .unwrap();
+ div.set_inner_html(full_html.as_str());
+ div
+ };
+ let node = Node::from(js_text_event);
+ VNode::VRef(node)
}
}
}
diff --git a/src/app/matrix/sync.rs b/src/app/matrix/sync.rs
@@ -60,18 +60,26 @@ impl Sync {
let client = self.matrix_client.clone();
let local_room_id = room_id.clone();
spawn_local(async move {
- let room: Arc<RwLock<Room>> = client.clone()
- .get_joined_room(&local_room_id.clone())
- .await
- .unwrap();
- let read_clone = room.read().await;
- let clean_room = (*read_clone).clone();
- let avatar_url =
- get_sender_avatar(homeserver_url, clean_room.clone(), cloned_event.clone());
- let displayname = get_sender_displayname(clean_room.clone(), cloned_event.clone());
- let notification =
- Notifications::new(avatar_url, displayname, text_event.body.clone());
- notification.show();
+ if Notifications::browser_support() {
+ let room: Arc<RwLock<Room>> = client
+ .clone()
+ .get_joined_room(&local_room_id.clone())
+ .await
+ .unwrap();
+ let read_clone = room.read().await;
+ let clean_room = (*read_clone).clone();
+ let avatar_url = get_sender_avatar(
+ homeserver_url,
+ clean_room.clone(),
+ cloned_event.clone(),
+ );
+ let displayname =
+ get_sender_displayname(clean_room.clone(), cloned_event.clone());
+
+ let notification =
+ Notifications::new(avatar_url, displayname, text_event.body.clone());
+ notification.show();
+ }
});
}
if let MessageEventContent::Image(mut image_event) = event.clone().content {
diff --git a/src/app/matrix/types.rs b/src/app/matrix/types.rs
@@ -1,4 +1,3 @@
-use matrix_sdk::Client;
use url::Url;
pub fn get_media_download_url(homeserver: &Url, mxc_url: String) -> String {
diff --git a/src/utils/notifications.rs b/src/utils/notifications.rs
@@ -1,10 +1,9 @@
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
-use web_sys::{window, Notification, NotificationOptions, NotificationPermission, Window};
+use web_sys::{window, Notification, NotificationOptions, NotificationPermission};
#[derive(Clone)]
pub(crate) struct Notifications {
- window: Option<Window>,
avatar: Option<String>,
displayname: String,
content: String,
@@ -13,30 +12,19 @@ pub(crate) struct Notifications {
impl Notifications {
pub fn new(avatar: Option<String>, displayname: String, content: String) -> Self {
Notifications {
- window: None,
avatar,
displayname,
content,
}
}
- fn browser_support(&mut self) -> bool {
- return match &self.window {
- None => match window() {
- Some(v) => {
- self.window = window();
- match v.get("Notification") {
- Some(_) => true,
- _ => false,
- }
- }
-
- _ => false,
- },
+ pub fn browser_support() -> bool {
+ match window() {
Some(v) => match v.get("Notification") {
Some(_) => true,
_ => false,
},
- };
+ _ => false,
+ }
}
fn notifications_allowed(&self) -> bool {
@@ -64,7 +52,7 @@ impl Notifications {
fn show_actual(&self) {
let mut options = NotificationOptions::new() as NotificationOptions;
- let mut options = options.body(&self.content).tag("daydream") as &mut NotificationOptions;
+ let options = options.body(&self.content).tag("daydream") as &mut NotificationOptions;
let options = if self.avatar.is_some() {
options.icon(self.avatar.as_ref().unwrap())
} else {