daydream

A small matrix web client written in rust
git clone git://archive.git.mtrnord.blog/daydream-mx/daydream.git
Log | Files | Refs | README | LICENSE

commit 94108195cdffce537bc2180563a9c6a530b7829b
parent ef69e107b4ce5598fe0ac07537d986067c27555a
Author: Marcel <MTRNord@users.noreply.github.com>
Date:   Fri,  3 Jul 2020 22:00:01 +0200

Merge pull request #22 from jplatte/less-cloning

Less cloning
Diffstat:
Msrc/app/components/event_list.rs | 63++++++++++++++++++++++++++++++---------------------------------
Msrc/app/components/events/image.rs | 52+++++++++++++---------------------------------------
Msrc/app/components/events/mod.rs | 23++++++++++-------------
Msrc/app/components/events/notice.rs | 34++++++++++++----------------------
Msrc/app/components/events/text.rs | 48+++++++++++++++---------------------------------
Msrc/app/components/events/video.rs | 67+++++++++++++++++++------------------------------------------------
Msrc/app/components/room_list/item.rs | 29++++++++++++-----------------
Msrc/app/components/room_list/mod.rs | 45++++++++++++++++++++++++++++-----------------
Msrc/app/matrix/mod.rs | 12++++++------
Msrc/app/matrix/sync.rs | 80+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/app/views/main_view.rs | 26+++++++++++++-------------
11 files changed, 197 insertions(+), 282 deletions(-)

diff --git a/src/app/components/event_list.rs b/src/app/components/event_list.rs @@ -1,10 +1,11 @@ +use std::{collections::HashMap, rc::Rc}; + use log::*; use matrix_sdk::{ events::room::message::{MessageEvent, MessageEventContent}, identifiers::RoomId, Room, }; -use std::collections::HashMap; use yew::prelude::*; use crate::app::components::{ @@ -35,8 +36,7 @@ pub enum Msg { #[derive(Clone, PartialEq, Properties, Debug)] pub struct Props { - #[prop_or_default] - pub current_room: Option<Room>, + pub current_room: Rc<Room>, } impl Component for EventList { @@ -51,11 +51,9 @@ impl Component for EventList { events: Default::default(), }; - if props.current_room.is_some() { - let room_id = props.current_room.clone().unwrap().room_id; - if !state.events.contains_key(&room_id) { - matrix_agent.send(Request::GetOldMessages((room_id, None))); - } + let room_id = props.current_room.room_id.clone(); + if !state.events.contains_key(&room_id) { + matrix_agent.send(Request::GetOldMessages((room_id, None))); } EventList { @@ -79,14 +77,14 @@ impl Component for EventList { .any(|x| x.event_id == msg.event_id)) { self.state.events.get_mut(&room_id).unwrap().push(msg); - room_id == self.props.current_room.clone().unwrap().room_id + room_id == self.props.current_room.room_id } else { false } } else { let msgs = vec![msg]; self.state.events.insert(room_id.clone(), msgs); - room_id == self.props.current_room.clone().unwrap().room_id + room_id == self.props.current_room.room_id } } else { false @@ -119,7 +117,7 @@ impl Component for EventList { Msg::SendMessage(message) => { info!("Sending Message"); self.matrix_agent.send(Request::SendMessage(( - self.props.current_room.clone().unwrap().room_id, + self.props.current_room.room_id.clone(), message, ))); false @@ -130,13 +128,12 @@ impl Component for EventList { fn change(&mut self, props: Self::Properties) -> bool { if self.props != props { - if props.current_room.is_some() { - let room_id = props.clone().current_room.unwrap().room_id; - if !self.state.events.contains_key(&room_id) { - self.matrix_agent - .send(Request::GetOldMessages((room_id, None))); - } + let room_id = props.current_room.room_id.clone(); + if !self.state.events.contains_key(&room_id) { + self.matrix_agent + .send(Request::GetOldMessages((room_id, None))); } + self.props = props; true } else { @@ -147,14 +144,14 @@ impl Component for EventList { fn view(&self) -> Html { return html! { <div class="event-list"> - <div class="room-title"><h1>{ self.props.current_room.as_ref().unwrap().display_name() }</h1></div> + <div class="room-title"><h1>{ self.props.current_room.display_name() }</h1></div> <div class="scrollable" style="height: auto; flex-grow: 1;"> <div class="message-container"> { - if self.state.events.contains_key(&self.props.current_room.as_ref().unwrap().room_id) { - let events = self.state.events[&self.props.current_room.as_ref().unwrap().room_id].clone(); + if self.state.events.contains_key(&self.props.current_room.room_id) { + let events = self.state.events[&self.props.current_room.room_id].clone(); let mut elements: Vec<Html> = Vec::new(); - for (pos, event) in self.state.events[&self.props.current_room.as_ref().unwrap().room_id].iter().enumerate() { + for (pos, event) in self.state.events[&self.props.current_room.room_id].iter().enumerate() { if pos == 0 { elements.push(self.get_event(None, event)); } else { @@ -186,9 +183,9 @@ impl EventList { html! { <Text prev_event=prev_event.clone() - event=Some(event.clone()) - room=Some(self.props.current_room.clone().unwrap()) - text_event=Some(text_event.clone()) + event=event.clone() + room=self.props.current_room.clone() + text_event=text_event.clone() /> } } @@ -196,9 +193,9 @@ impl EventList { html! { <Notice prev_event=prev_event.clone() - event=Some(event.clone()) - room=Some(self.props.current_room.clone().unwrap()) - notice_event=Some(notice_event.clone()) + event=event.clone() + room=self.props.current_room.clone() + notice_event=notice_event.clone() /> } } @@ -206,9 +203,9 @@ impl EventList { html! { <Image prev_event=prev_event.clone() - event=Some(event.clone()) - room=Some(self.props.current_room.clone().unwrap()) - image_event=Some(image_event.clone()) + event=event.clone() + room=self.props.current_room.clone() + image_event=image_event.clone() /> } } @@ -216,9 +213,9 @@ impl EventList { html! { <Video prev_event=prev_event.clone() - event=Some(event.clone()) - room=Some(self.props.current_room.clone().unwrap()) - video_event=Some(video_event.clone()) + event=event.clone() + room=self.props.current_room.clone() + video_event=video_event.clone() /> } } diff --git a/src/app/components/events/image.rs b/src/app/components/events/image.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::app::components::events::{get_sender_displayname, is_new_user}; use matrix_sdk::{ events::room::message::{ImageMessageEventContent, MessageEvent}, @@ -14,12 +16,9 @@ pub(crate) struct Image { pub struct Props { #[prop_or_default] pub prev_event: Option<MessageEvent>, - #[prop_or_default] - pub event: Option<MessageEvent>, - #[prop_or_default] - pub image_event: Option<ImageMessageEventContent>, - #[prop_or_default] - pub room: Option<Room>, + pub event: MessageEvent, + pub image_event: ImageMessageEventContent, + pub room: Rc<Room>, } impl Component for Image { @@ -47,49 +46,24 @@ impl Component for Image { //noinspection RsTypeCheck fn view(&self) -> Html { - let new_user = is_new_user( - self.props.prev_event.clone(), - self.props.event.clone().unwrap(), - ); + let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event); let sender_displayname = if new_user { - get_sender_displayname( - self.props.room.clone().unwrap(), - self.props.event.clone().unwrap(), - ) + get_sender_displayname(&self.props.room, &self.props.event) } else { "".to_string() }; - if self - .props - .image_event - .as_ref() - .unwrap() - .url - .clone() - .is_some() - { - let image_url = self + if let Some(image_url) = &self.props.image_event.url { + let thumbnail = self .props .image_event - .as_ref() - .unwrap() - .url - .clone() - .unwrap(); - let thumbnail = match self - .props - .image_event - .as_ref() - .unwrap() .info - .clone() + .as_ref() .unwrap() .thumbnail_url - { - None => image_url.clone(), - Some(v) => v, - }; + .as_ref() + .unwrap_or(image_url); + let lightbox_id: u8 = random(); let lightbox_id_full = format!("image_{}", lightbox_id); let lightbox_href_full = format!("#image_{}", lightbox_id); diff --git a/src/app/components/events/mod.rs b/src/app/components/events/mod.rs @@ -8,7 +8,7 @@ pub mod notice; pub mod text; pub mod video; -pub fn is_new_user(prev_event: Option<MessageEvent>, event: MessageEvent) -> bool { +pub fn is_new_user(prev_event: Option<&MessageEvent>, event: &MessageEvent) -> bool { if let Some(prev_event) = prev_event { prev_event.sender != event.sender } else { @@ -16,7 +16,7 @@ pub fn is_new_user(prev_event: Option<MessageEvent>, event: MessageEvent) -> boo } } -pub fn get_sender_displayname(room: Room, event: MessageEvent) -> String { +pub fn get_sender_displayname(room: &Room, event: &MessageEvent) -> String { match room.members.get(&event.sender) { None => event.sender.to_string(), Some(member) => member @@ -27,15 +27,12 @@ pub fn get_sender_displayname(room: Room, event: MessageEvent) -> String { } } -pub fn get_sender_avatar(homeserver_url: Url, room: Room, event: MessageEvent) -> Option<String> { - match room.members.get(&event.sender) { - None => None, - Some(member) => { - let avatar_url_mxc = member.avatar_url.as_ref().map(ToString::to_string); - match avatar_url_mxc { - None => None, - Some(v) => Some(get_media_download_url(&homeserver_url, v)), - } - } - } +pub fn get_sender_avatar(homeserver_url: Url, room: &Room, event: &MessageEvent) -> Option<String> { + room.members.get(&event.sender).and_then(|member| { + member + .avatar_url + .as_ref() + .map(ToString::to_string) + .map(|v| get_media_download_url(&homeserver_url, v)) + }) } diff --git a/src/app/components/events/notice.rs b/src/app/components/events/notice.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use linkify::LinkFinder; use matrix_sdk::{ events::room::message::{MessageEvent, NoticeMessageEventContent}, @@ -17,12 +19,9 @@ pub(crate) struct Notice { pub struct Props { #[prop_or_default] pub prev_event: Option<MessageEvent>, - #[prop_or_default] - pub event: Option<MessageEvent>, - #[prop_or_default] - pub notice_event: Option<NoticeMessageEventContent>, - #[prop_or_default] - pub room: Option<Room>, + pub event: MessageEvent, + pub notice_event: NoticeMessageEventContent, + pub room: Rc<Room>, } impl Component for Notice { @@ -50,38 +49,29 @@ impl Component for Notice { //noinspection RsTypeCheck fn view(&self) -> Html { - let new_user = is_new_user( - self.props.prev_event.clone(), - self.props.event.clone().unwrap(), - ); + let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event); let sender_displayname = if new_user { - get_sender_displayname( - self.props.room.clone().unwrap(), - self.props.event.clone().unwrap(), - ) + get_sender_displayname(&self.props.room, &self.props.event) } else { "".to_string() }; - let mut pure_content = self.props.notice_event.clone().unwrap().body; + let mut pure_content = self.props.notice_event.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() { + 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 - } else { - pure_content - }; + } if new_user { let full_html = format!( "<p style=\"opacity: .6;\"><displayname>{}: </displayname>{}</p>", - sender_displayname, content + sender_displayname, pure_content ); let js_text_event = { let div = web_sys::window() @@ -96,7 +86,7 @@ impl Component for Notice { let node = Node::from(js_text_event); VNode::VRef(node) } else { - let full_html = format!("<p style=\"opacity: .6;\">{}</p>", content); + let full_html = format!("<p style=\"opacity: .6;\">{}</p>", pure_content); let js_text_event = { let div = web_sys::window() .unwrap() diff --git a/src/app/components/events/text.rs b/src/app/components/events/text.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::app::components::events::{get_sender_displayname, is_new_user}; use linkify::LinkFinder; use matrix_sdk::{ @@ -16,12 +18,9 @@ pub struct Text { pub struct Props { #[prop_or_default] pub prev_event: Option<MessageEvent>, - #[prop_or_default] - pub event: Option<MessageEvent>, - #[prop_or_default] - pub text_event: Option<TextMessageEventContent>, - #[prop_or_default] - pub room: Option<Room>, + pub event: MessageEvent, + pub text_event: TextMessageEventContent, + pub room: Rc<Room>, } impl Component for Text { @@ -49,20 +48,14 @@ impl Component for Text { //noinspection RsTypeCheck fn view(&self) -> Html { - let new_user = is_new_user( - self.props.prev_event.clone(), - self.props.event.clone().unwrap(), - ); + let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event); let sender_displayname = if new_user { - get_sender_displayname( - self.props.room.clone().unwrap(), - self.props.event.clone().unwrap(), - ) + get_sender_displayname(&self.props.room, &self.props.event) } else { "".to_string() }; - let mut pure_content = self.props.text_event.clone().unwrap().body; + let mut pure_content = self.props.text_event.body.clone(); let finder = LinkFinder::new(); let pure_content_clone = pure_content.clone(); let links: Vec<_> = finder.links(&pure_content_clone).collect(); @@ -77,27 +70,16 @@ impl Component for Text { pure_content }; - if self.props.text_event.clone().unwrap().formatted.is_some() { + if let Some(formatted) = &self.props.text_event.formatted { + let format_slot; let message = if new_user { - format!( + format_slot = format!( "<displayname>{}:</displayname> {}", - sender_displayname, - self.props - .text_event - .clone() - .unwrap() - .formatted - .unwrap() - .body - ) + sender_displayname, formatted.body + ); + &format_slot } else { - self.props - .text_event - .clone() - .unwrap() - .formatted - .unwrap() - .body + &formatted.body }; let js_text_event = { let div = web_sys::window() diff --git a/src/app/components/events/video.rs b/src/app/components/events/video.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use crate::app::components::events::{get_sender_displayname, is_new_user}; use matrix_sdk::{ events::room::message::{MessageEvent, VideoMessageEventContent}, @@ -14,12 +16,9 @@ pub(crate) struct Video { pub struct Props { #[prop_or_default] pub prev_event: Option<MessageEvent>, - #[prop_or_default] - pub event: Option<MessageEvent>, - #[prop_or_default] - pub video_event: Option<VideoMessageEventContent>, - #[prop_or_default] - pub room: Option<Room>, + pub event: MessageEvent, + pub video_event: VideoMessageEventContent, + pub room: Rc<Room>, } impl Component for Video { @@ -47,54 +46,26 @@ impl Component for Video { //noinspection RsTypeCheck fn view(&self) -> Html { - let new_user = is_new_user( - self.props.prev_event.clone(), - self.props.event.clone().unwrap(), - ); + let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event); let sender_displayname = if new_user { - get_sender_displayname( - self.props.room.clone().unwrap(), - self.props.event.clone().unwrap(), - ) + get_sender_displayname(&self.props.room, &self.props.event) } else { "".to_string() }; - let _caption = format!( - "{}: {}", - sender_displayname, - self.props.video_event.as_ref().unwrap().body - ); - if self - .props - .video_event - .as_ref() - .unwrap() - .url - .clone() - .is_some() - { - let video_url = self - .props - .video_event - .as_ref() - .unwrap() - .url - .clone() - .unwrap(); - let thumbnail = match self + let _caption = format!("{}: {}", sender_displayname, self.props.video_event.body); + + if let Some(video_url) = self.props.video_event.url.as_ref() { + let thumbnail = self .props .video_event - .as_ref() - .unwrap() .info - .clone() + .as_ref() .unwrap() .thumbnail_url - { - None => video_url.clone(), - Some(v) => v, - }; + .as_ref() + .unwrap_or(video_url); + let lightbox_id: u8 = random(); let lightbox_id_full = format!("video_{}", lightbox_id); let lightbox_href_full = format!("#video_{}", lightbox_id); @@ -102,8 +73,8 @@ impl Component for Video { html! { <div> <p><displayname>{sender_displayname}{": "}</displayname></p> - <a href={lightbox_href_full.clone()}><img src=thumbnail/></a> - <div class="lightbox short-animate" id={lightbox_id_full.clone()}> + <a href={lightbox_href_full}><img src=thumbnail/></a> + <div class="lightbox short-animate" id={lightbox_id_full}> <video class="long-animate" controls=true> <source src=video_url type="video/mp4"/> {"Your browser does not support the video tag."} @@ -117,8 +88,8 @@ impl Component for Video { } else { html! { <div> - <a href={lightbox_href_full.clone()}><img src=thumbnail/></a> - <div class="lightbox short-animate" id={lightbox_id_full.clone()}> + <a href={lightbox_href_full}><img src=thumbnail/></a> + <div class="lightbox short-animate" id={lightbox_id_full}> <video class="long-animate" controls=true> <source src=video_url type="video/mp4"/> {"Your browser does not support the video tag."} diff --git a/src/app/components/room_list/item.rs b/src/app/components/room_list/item.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use matrix_sdk::{events::room::message::MessageEventContent, identifiers::RoomId, Room}; use yew::prelude::*; use yewtil::NeqAssign; @@ -8,13 +10,12 @@ pub(crate) struct RoomItem { } pub enum Msg { - ChangeRoom(Room), + ChangeRoom(Rc<Room>), } #[derive(Clone, Properties, Debug, PartialEq)] pub struct Props { - #[prop_or_default] - pub room: Option<Room>, + pub room: Rc<Room>, #[prop_or_default] pub change_room_callback: Callback<RoomId>, @@ -31,7 +32,7 @@ impl Component for RoomItem { fn update(&mut self, msg: Self::Message) -> bool { match msg { Msg::ChangeRoom(room) => { - self.props.change_room_callback.emit(room.room_id); + self.props.change_room_callback.emit(room.room_id.clone()); } } false @@ -43,28 +44,22 @@ impl Component for RoomItem { //noinspection RsTypeCheck fn view(&self) -> Html { - let room = self.props.room.clone().unwrap(); + let room = self.props.room.clone(); // TODO placeholder for encrypted rooms - let last_message = match self - .props - .room - .as_ref() - .unwrap() - .messages - .clone() - .into_iter() - .last() - { + let last_message = match room.messages.iter().last() { None => "".to_string(), Some(m) => { if let MessageEventContent::Text(text_event) = &m.content { - text_event.clone().body + text_event.body.clone() } else { "".to_string() } } }; + + let display_name = room.display_name(); + html! { <div class="room-list-item"> <a onclick=self.link.callback(move |e: MouseEvent| Msg::ChangeRoom(room.clone()))> @@ -72,7 +67,7 @@ impl Component for RoomItem { // TODO remove placeholder <img class="avatar" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAARUlEQVRYhe3OMQ0AIADAMBKUowmBoIKMo0f/jrnX+dmoA4KCdUBQsA4ICtYBQcE6IChYBwQF64CgYB0QFKwDgoJ1QPC1C8gY0kSgNLTWAAAAAElFTkSuQmCC"/> <div> - <h5 class="name">{self.props.room.as_ref().unwrap().display_name()}</h5> + <h5 class="name">{display_name}</h5> <p class="latest-msg">{last_message}</p> </div> </div> diff --git a/src/app/components/room_list/mod.rs b/src/app/components/room_list/mod.rs @@ -1,5 +1,4 @@ -use std::collections::HashMap; -use std::include_str; +use std::{collections::HashMap, rc::Rc}; use log::*; use matrix_sdk::{identifiers::RoomId, Room}; @@ -36,7 +35,7 @@ pub enum Msg { #[derive(Serialize, Deserialize, Default)] pub struct State { - rooms: HashMap<RoomId, Room>, + rooms: HashMap<RoomId, Rc<Room>>, current_room: Option<RoomId>, loading: bool, search_query: Option<String>, @@ -46,7 +45,7 @@ pub struct State { #[derive(Clone, PartialEq, Properties)] pub struct Props { #[prop_or_default] - pub change_room_callback: Callback<Room>, + pub change_room_callback: Callback<Rc<Room>>, } impl Component for RoomList { @@ -85,7 +84,7 @@ impl Component for RoomList { } Response::JoinedRoom((room_id, room)) => { info!("Got JoinedRoom"); - self.state.rooms.insert(room_id, room); + self.state.rooms.insert(room_id, Rc::new(room)); if self.state.loading { self.state.loading = false; } @@ -144,6 +143,27 @@ impl Component for RoomList { </div> } } else { + let rooms = if self.state.search_query.is_none() + || (self.state.search_query.as_ref().unwrap_or(&"".to_string()) == &"".to_string()) + { + self.state + .rooms + .iter() + .map(|(_, room)| self.get_room(room)) + .collect::<Html>() + } else { + self.state + .rooms + .iter() + .filter(|(_, room)| { + room.display_name() + .to_lowercase() + .contains(&self.state.search_query.as_ref().unwrap().to_lowercase()) + }) + .map(|(_, room)| self.get_room(room)) + .collect::<Html>() + }; + html! { <div class="roomlist" style="height: 100%"> <div class="top-bar"> @@ -166,16 +186,7 @@ impl Component for RoomList { </div> </div> </div> - - <div class="scrollable list"> - { - if self.state.search_query.is_none() || (self.state.search_query.as_ref().unwrap_or(&"".to_string()) == &"".to_string()) { - self.state.rooms.iter().map(|(_, room)| self.get_room(room)).collect::<Html>() - } else { - self.state.rooms.iter().filter(|(_, room)| room.display_name().to_lowercase().contains(&self.state.search_query.as_ref().unwrap().to_lowercase())).map(|(_, room)| self.get_room(room)).collect::<Html>() - } - } - </div> + <div class="scrollable list">{rooms}</div> <div class="bottom-bar"> <div class="toggleWrapper"> <input type="checkbox" class="dn" id="dn" checked=self.state.dark_theme value=self.state.dark_theme onclick=self.link.callback(|e: MouseEvent| {Msg::ToggleTheme})/> @@ -201,10 +212,10 @@ impl Component for RoomList { } impl RoomList { - fn get_room(&self, matrix_room: &Room) -> Html { + fn get_room(&self, matrix_room: &Rc<Room>) -> Html { let room = matrix_room.clone(); html! { - <RoomItem change_room_callback=self.link.callback(Msg::ChangeRoom) room=Some(room)/> + <RoomItem change_room_callback=self.link.callback(Msg::ChangeRoom) room=room.clone() /> } /*html! { <li class=classes> diff --git a/src/app/matrix/mod.rs b/src/app/matrix/mod.rs @@ -308,7 +308,7 @@ impl Agent for MatrixAgent { { if image_event.url.is_some() { let new_url = Some(get_media_download_url( - agent.matrix_client.clone().unwrap().homeserver(), + agent.matrix_client.as_ref().unwrap().homeserver(), image_event.url.unwrap(), )); image_event.url = new_url; @@ -317,7 +317,7 @@ impl Agent for MatrixAgent { let mut info = image_event.info.unwrap(); if info.thumbnail_url.is_some() { let new_url = Some(get_media_download_url( - agent.matrix_client.clone().unwrap().homeserver(), + agent.matrix_client.as_ref().unwrap().homeserver(), info.thumbnail_url.unwrap(), )); info.thumbnail_url = new_url; @@ -329,7 +329,7 @@ impl Agent for MatrixAgent { if let MessageEventContent::Video(mut video_event) = event.content { if video_event.url.is_some() { let new_url = Some(get_video_media_download_url( - agent.matrix_client.clone().unwrap().homeserver(), + agent.matrix_client.as_ref().unwrap().homeserver(), video_event.url.unwrap(), )); video_event.url = new_url; @@ -338,7 +338,7 @@ impl Agent for MatrixAgent { let mut info = video_event.info.unwrap(); if info.thumbnail_url.is_some() { let new_url = Some(get_media_download_url( - agent.matrix_client.clone().unwrap().homeserver(), + agent.matrix_client.as_ref().unwrap().homeserver(), info.thumbnail_url.unwrap(), )); info.thumbnail_url = new_url; @@ -441,10 +441,10 @@ impl MatrixAgent { info!("preparing client"); if self.session.is_some() { info!("restoring login"); - let homeserver = self.session.clone().unwrap().homeserver_url; + let homeserver = &self.session.as_ref().unwrap().homeserver_url; let client_config = ClientConfig::new(); - let homeserver_url = Url::parse(&homeserver).unwrap(); + let homeserver_url = Url::parse(homeserver).unwrap(); let client = Client::new_with_config(homeserver_url, client_config).unwrap(); self.matrix_client = Some(client.clone()); diff --git a/src/app/matrix/sync.rs b/src/app/matrix/sync.rs @@ -1,3 +1,4 @@ +use std::mem; use std::sync::Arc; use std::sync::Mutex; use std::time::Duration; @@ -88,7 +89,7 @@ impl Sync { } if let RoomEvent::RoomMessage(mut event) = event { - if let MessageEventContent::Text(text_event) = event.clone().content { + if let MessageEventContent::Text(text_event) = event.content.clone() { let homeserver_url = self.matrix_client.clone().homeserver().clone(); let cloned_event = event.clone(); @@ -99,18 +100,19 @@ impl Sync { spawn_local(async move { let room: Arc<RwLock<Room>> = client .clone() - .get_joined_room(&local_room_id.clone()) + .get_joined_room(&local_room_id) .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 room_name = clean_room.display_name(); - let displayname = get_sender_displayname(clean_room, cloned_event.clone()); + + let (avatar_url, room_name, displayname) = { + let room = room.read().await; + + ( + get_sender_avatar(homeserver_url, &room, &cloned_event), + room.display_name(), + get_sender_displayname(&room, &cloned_event), + ) + }; let title = if displayname == room_name { displayname @@ -124,47 +126,43 @@ impl Sync { }); } } - if let MessageEventContent::Image(mut image_event) = event.clone().content { - if image_event.url.is_some() { - let new_url = Some(get_media_download_url( + if let MessageEventContent::Image(image_event) = &mut event.content { + if let Some(image_url) = &mut image_event.url { + let old_image_url = mem::take(image_url); + *image_url = get_media_download_url( self.matrix_client.clone().homeserver(), - image_event.url.unwrap(), - )); - image_event.url = new_url; + old_image_url, + ); } - if image_event.info.is_some() { - let mut info = image_event.info.unwrap(); - if info.thumbnail_url.is_some() { - let new_url = Some(get_media_download_url( + + if let Some(info) = &mut image_event.info { + if let Some(thumbnail_url) = &mut info.thumbnail_url { + let old_thumbnail_url = mem::take(thumbnail_url); + *thumbnail_url = get_media_download_url( self.matrix_client.clone().homeserver(), - info.thumbnail_url.unwrap(), - )); - info.thumbnail_url = new_url; + old_thumbnail_url, + ); } - image_event.info = Some(info); } - event.content = MessageEventContent::Image(image_event); } - if let MessageEventContent::Video(mut video_event) = event.content { - if video_event.url.is_some() { - let new_url = Some(get_video_media_download_url( + if let MessageEventContent::Video(video_event) = &mut event.content { + if let Some(video_url) = &mut video_event.url { + let old_video_url = mem::take(video_url); + *video_url = get_video_media_download_url( self.matrix_client.clone().homeserver(), - video_event.url.unwrap(), - )); - video_event.url = new_url; + old_video_url, + ); } - if video_event.info.is_some() { - let mut info = video_event.info.unwrap(); - if info.thumbnail_url.is_some() { - let new_url = Some(get_media_download_url( + + if let Some(info) = &mut video_event.info { + if let Some(thumbnail_url) = &mut info.thumbnail_url { + let old_thumbnail_url = mem::take(thumbnail_url); + *thumbnail_url = get_media_download_url( self.matrix_client.clone().homeserver(), - info.thumbnail_url.unwrap(), - )); - info.thumbnail_url = new_url; + old_thumbnail_url, + ); } - video_event.info = Some(info); } - event.content = MessageEventContent::Video(video_event); } let serialized_event = EventJson::from(event); diff --git a/src/app/views/main_view.rs b/src/app/views/main_view.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use log::*; use matrix_sdk::Room; use serde::{Deserialize, Serialize}; @@ -15,12 +17,12 @@ pub struct MainView { } pub enum Msg { - ChangeRoom(Room), + ChangeRoom(Rc<Room>), } #[derive(Serialize, Deserialize, Default)] pub struct State { - pub current_room: Option<Room>, + pub current_room: Option<Rc<Room>>, pub current_room_displayname: String, } @@ -55,8 +57,8 @@ impl Component for MainView { //noinspection RsTypeCheck fn view(&self) -> Html { - if self.state.current_room.is_none() { - html! { + match &self.state.current_room { + None => html! { <div class="uk-flex auto-scrollable-container uk-background-default" style="height: 100%"> <RoomList change_room_callback=self.link.callback(Msg::ChangeRoom)/> @@ -66,13 +68,12 @@ impl Component for MainView { </div> </div> </div> - } - } else if self.state.current_room.as_ref().unwrap().is_encrypted() { - html! { + }, + Some(room) if room.is_encrypted() => html! { <div class="uk-flex auto-scrollable-container" style="height: 100%"> <RoomList change_room_callback=self.link.callback(Msg::ChangeRoom)/> <div class="event-list"> - <div class="room-title"><h1>{ self.state.current_room.as_ref().unwrap().display_name() }</h1></div> + <div class="room-title"><h1>{ room.display_name() }</h1></div> <h4> { tr!( @@ -83,14 +84,13 @@ impl Component for MainView { </h4> </div> </div> - } - } else { - html! { + }, + Some(room) => html! { <div class="uk-flex auto-scrollable-container" style="height: 100%"> <RoomList change_room_callback=self.link.callback(Msg::ChangeRoom)/> - <EventList current_room=self.state.current_room.as_ref().unwrap() /> + <EventList current_room=room /> </div> - } + }, } } }