daydream.meta

Issues/PRs archive for daydream-mx/Daydream
git clone git://archive.git.mtrnord.blog/daydream-mx/daydream.meta.git
Log | Files | Refs

22.diff (40644B)


      1 diff --git a/src/app/components/event_list.rs b/src/app/components/event_list.rs
      2 index 77a4a93..63a80ff 100644
      3 --- a/src/app/components/event_list.rs
      4 +++ b/src/app/components/event_list.rs
      5 @@ -1,10 +1,11 @@
      6 +use std::{collections::HashMap, rc::Rc};
      7 +
      8  use log::*;
      9  use matrix_sdk::{
     10      events::room::message::{MessageEvent, MessageEventContent},
     11      identifiers::RoomId,
     12      Room,
     13  };
     14 -use std::collections::HashMap;
     15  use yew::prelude::*;
     16  
     17  use crate::app::components::{
     18 @@ -35,8 +36,7 @@ pub enum Msg {
     19  
     20  #[derive(Clone, PartialEq, Properties, Debug)]
     21  pub struct Props {
     22 -    #[prop_or_default]
     23 -    pub current_room: Option<Room>,
     24 +    pub current_room: Rc<Room>,
     25  }
     26  
     27  impl Component for EventList {
     28 @@ -51,11 +51,9 @@ impl Component for EventList {
     29              events: Default::default(),
     30          };
     31  
     32 -        if props.current_room.is_some() {
     33 -            let room_id = props.current_room.clone().unwrap().room_id;
     34 -            if !state.events.contains_key(&room_id) {
     35 -                matrix_agent.send(Request::GetOldMessages((room_id, None)));
     36 -            }
     37 +        let room_id = props.current_room.room_id.clone();
     38 +        if !state.events.contains_key(&room_id) {
     39 +            matrix_agent.send(Request::GetOldMessages((room_id, None)));
     40          }
     41  
     42          EventList {
     43 @@ -79,14 +77,14 @@ impl Component for EventList {
     44                                      .any(|x| x.event_id == msg.event_id))
     45                                  {
     46                                      self.state.events.get_mut(&room_id).unwrap().push(msg);
     47 -                                    room_id == self.props.current_room.clone().unwrap().room_id
     48 +                                    room_id == self.props.current_room.room_id
     49                                  } else {
     50                                      false
     51                                  }
     52                              } else {
     53                                  let msgs = vec![msg];
     54                                  self.state.events.insert(room_id.clone(), msgs);
     55 -                                room_id == self.props.current_room.clone().unwrap().room_id
     56 +                                room_id == self.props.current_room.room_id
     57                              }
     58                          } else {
     59                              false
     60 @@ -119,7 +117,7 @@ impl Component for EventList {
     61              Msg::SendMessage(message) => {
     62                  info!("Sending Message");
     63                  self.matrix_agent.send(Request::SendMessage((
     64 -                    self.props.current_room.clone().unwrap().room_id,
     65 +                    self.props.current_room.room_id.clone(),
     66                      message,
     67                  )));
     68                  false
     69 @@ -130,13 +128,12 @@ impl Component for EventList {
     70  
     71      fn change(&mut self, props: Self::Properties) -> bool {
     72          if self.props != props {
     73 -            if props.current_room.is_some() {
     74 -                let room_id = props.clone().current_room.unwrap().room_id;
     75 -                if !self.state.events.contains_key(&room_id) {
     76 -                    self.matrix_agent
     77 -                        .send(Request::GetOldMessages((room_id, None)));
     78 -                }
     79 +            let room_id = props.current_room.room_id.clone();
     80 +            if !self.state.events.contains_key(&room_id) {
     81 +                self.matrix_agent
     82 +                    .send(Request::GetOldMessages((room_id, None)));
     83              }
     84 +
     85              self.props = props;
     86              true
     87          } else {
     88 @@ -147,14 +144,14 @@ impl Component for EventList {
     89      fn view(&self) -> Html {
     90          return html! {
     91              <div class="event-list">
     92 -                <div class="room-title"><h1>{ self.props.current_room.as_ref().unwrap().display_name() }</h1></div>
     93 +                <div class="room-title"><h1>{ self.props.current_room.display_name() }</h1></div>
     94                  <div class="scrollable" style="height: auto; flex-grow: 1;">
     95                      <div class="message-container">
     96                          {
     97 -                            if self.state.events.contains_key(&self.props.current_room.as_ref().unwrap().room_id) {
     98 -                                let events = self.state.events[&self.props.current_room.as_ref().unwrap().room_id].clone();
     99 +                            if self.state.events.contains_key(&self.props.current_room.room_id) {
    100 +                                let events = self.state.events[&self.props.current_room.room_id].clone();
    101                                  let mut elements: Vec<Html> = Vec::new();
    102 -                                for (pos, event) in self.state.events[&self.props.current_room.as_ref().unwrap().room_id].iter().enumerate() {
    103 +                                for (pos, event) in self.state.events[&self.props.current_room.room_id].iter().enumerate() {
    104                                      if pos == 0 {
    105                                          elements.push(self.get_event(None, event));
    106                                      } else {
    107 @@ -186,9 +183,9 @@ impl EventList {
    108                  html! {
    109                      <Text
    110                          prev_event=prev_event.clone()
    111 -                        event=Some(event.clone())
    112 -                        room=Some(self.props.current_room.clone().unwrap())
    113 -                        text_event=Some(text_event.clone())
    114 +                        event=event.clone()
    115 +                        room=self.props.current_room.clone()
    116 +                        text_event=text_event.clone()
    117                      />
    118                  }
    119              }
    120 @@ -196,9 +193,9 @@ impl EventList {
    121                  html! {
    122                      <Notice
    123                          prev_event=prev_event.clone()
    124 -                        event=Some(event.clone())
    125 -                        room=Some(self.props.current_room.clone().unwrap())
    126 -                        notice_event=Some(notice_event.clone())
    127 +                        event=event.clone()
    128 +                        room=self.props.current_room.clone()
    129 +                        notice_event=notice_event.clone()
    130                      />
    131                  }
    132              }
    133 @@ -206,9 +203,9 @@ impl EventList {
    134                  html! {
    135                      <Image
    136                          prev_event=prev_event.clone()
    137 -                        event=Some(event.clone())
    138 -                        room=Some(self.props.current_room.clone().unwrap())
    139 -                        image_event=Some(image_event.clone())
    140 +                        event=event.clone()
    141 +                        room=self.props.current_room.clone()
    142 +                        image_event=image_event.clone()
    143                      />
    144                  }
    145              }
    146 @@ -216,9 +213,9 @@ impl EventList {
    147                  html! {
    148                      <Video
    149                          prev_event=prev_event.clone()
    150 -                        event=Some(event.clone())
    151 -                        room=Some(self.props.current_room.clone().unwrap())
    152 -                        video_event=Some(video_event.clone())
    153 +                        event=event.clone()
    154 +                        room=self.props.current_room.clone()
    155 +                        video_event=video_event.clone()
    156                      />
    157                  }
    158              }
    159 diff --git a/src/app/components/events/image.rs b/src/app/components/events/image.rs
    160 index 62792e7..0fe5f74 100644
    161 --- a/src/app/components/events/image.rs
    162 +++ b/src/app/components/events/image.rs
    163 @@ -1,3 +1,5 @@
    164 +use std::rc::Rc;
    165 +
    166  use crate::app::components::events::{get_sender_displayname, is_new_user};
    167  use matrix_sdk::{
    168      events::room::message::{ImageMessageEventContent, MessageEvent},
    169 @@ -14,12 +16,9 @@ pub(crate) struct Image {
    170  pub struct Props {
    171      #[prop_or_default]
    172      pub prev_event: Option<MessageEvent>,
    173 -    #[prop_or_default]
    174 -    pub event: Option<MessageEvent>,
    175 -    #[prop_or_default]
    176 -    pub image_event: Option<ImageMessageEventContent>,
    177 -    #[prop_or_default]
    178 -    pub room: Option<Room>,
    179 +    pub event: MessageEvent,
    180 +    pub image_event: ImageMessageEventContent,
    181 +    pub room: Rc<Room>,
    182  }
    183  
    184  impl Component for Image {
    185 @@ -47,49 +46,24 @@ impl Component for Image {
    186  
    187      //noinspection RsTypeCheck
    188      fn view(&self) -> Html {
    189 -        let new_user = is_new_user(
    190 -            self.props.prev_event.clone(),
    191 -            self.props.event.clone().unwrap(),
    192 -        );
    193 +        let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event);
    194          let sender_displayname = if new_user {
    195 -            get_sender_displayname(
    196 -                self.props.room.clone().unwrap(),
    197 -                self.props.event.clone().unwrap(),
    198 -            )
    199 +            get_sender_displayname(&self.props.room, &self.props.event)
    200          } else {
    201              "".to_string()
    202          };
    203  
    204 -        if self
    205 -            .props
    206 -            .image_event
    207 -            .as_ref()
    208 -            .unwrap()
    209 -            .url
    210 -            .clone()
    211 -            .is_some()
    212 -        {
    213 -            let image_url = self
    214 +        if let Some(image_url) = &self.props.image_event.url {
    215 +            let thumbnail = self
    216                  .props
    217                  .image_event
    218 -                .as_ref()
    219 -                .unwrap()
    220 -                .url
    221 -                .clone()
    222 -                .unwrap();
    223 -            let thumbnail = match self
    224 -                .props
    225 -                .image_event
    226 -                .as_ref()
    227 -                .unwrap()
    228                  .info
    229 -                .clone()
    230 +                .as_ref()
    231                  .unwrap()
    232                  .thumbnail_url
    233 -            {
    234 -                None => image_url.clone(),
    235 -                Some(v) => v,
    236 -            };
    237 +                .as_ref()
    238 +                .unwrap_or(image_url);
    239 +
    240              let lightbox_id: u8 = random();
    241              let lightbox_id_full = format!("image_{}", lightbox_id);
    242              let lightbox_href_full = format!("#image_{}", lightbox_id);
    243 diff --git a/src/app/components/events/mod.rs b/src/app/components/events/mod.rs
    244 index ae68c30..a27fc71 100644
    245 --- a/src/app/components/events/mod.rs
    246 +++ b/src/app/components/events/mod.rs
    247 @@ -8,7 +8,7 @@ pub mod notice;
    248  pub mod text;
    249  pub mod video;
    250  
    251 -pub fn is_new_user(prev_event: Option<MessageEvent>, event: MessageEvent) -> bool {
    252 +pub fn is_new_user(prev_event: Option<&MessageEvent>, event: &MessageEvent) -> bool {
    253      if let Some(prev_event) = prev_event {
    254          prev_event.sender != event.sender
    255      } else {
    256 @@ -16,7 +16,7 @@ pub fn is_new_user(prev_event: Option<MessageEvent>, event: MessageEvent) -> boo
    257      }
    258  }
    259  
    260 -pub fn get_sender_displayname(room: Room, event: MessageEvent) -> String {
    261 +pub fn get_sender_displayname(room: &Room, event: &MessageEvent) -> String {
    262      match room.members.get(&event.sender) {
    263          None => event.sender.to_string(),
    264          Some(member) => member
    265 @@ -27,15 +27,12 @@ pub fn get_sender_displayname(room: Room, event: MessageEvent) -> String {
    266      }
    267  }
    268  
    269 -pub fn get_sender_avatar(homeserver_url: Url, room: Room, event: MessageEvent) -> Option<String> {
    270 -    match room.members.get(&event.sender) {
    271 -        None => None,
    272 -        Some(member) => {
    273 -            let avatar_url_mxc = member.avatar_url.as_ref().map(ToString::to_string);
    274 -            match avatar_url_mxc {
    275 -                None => None,
    276 -                Some(v) => Some(get_media_download_url(&homeserver_url, v)),
    277 -            }
    278 -        }
    279 -    }
    280 +pub fn get_sender_avatar(homeserver_url: Url, room: &Room, event: &MessageEvent) -> Option<String> {
    281 +    room.members.get(&event.sender).and_then(|member| {
    282 +        member
    283 +            .avatar_url
    284 +            .as_ref()
    285 +            .map(ToString::to_string)
    286 +            .map(|v| get_media_download_url(&homeserver_url, v))
    287 +    })
    288  }
    289 diff --git a/src/app/components/events/notice.rs b/src/app/components/events/notice.rs
    290 index be33780..7d65785 100644
    291 --- a/src/app/components/events/notice.rs
    292 +++ b/src/app/components/events/notice.rs
    293 @@ -1,3 +1,5 @@
    294 +use std::rc::Rc;
    295 +
    296  use linkify::LinkFinder;
    297  use matrix_sdk::{
    298      events::room::message::{MessageEvent, NoticeMessageEventContent},
    299 @@ -17,12 +19,9 @@ pub(crate) struct Notice {
    300  pub struct Props {
    301      #[prop_or_default]
    302      pub prev_event: Option<MessageEvent>,
    303 -    #[prop_or_default]
    304 -    pub event: Option<MessageEvent>,
    305 -    #[prop_or_default]
    306 -    pub notice_event: Option<NoticeMessageEventContent>,
    307 -    #[prop_or_default]
    308 -    pub room: Option<Room>,
    309 +    pub event: MessageEvent,
    310 +    pub notice_event: NoticeMessageEventContent,
    311 +    pub room: Rc<Room>,
    312  }
    313  
    314  impl Component for Notice {
    315 @@ -50,38 +49,29 @@ impl Component for Notice {
    316  
    317      //noinspection RsTypeCheck
    318      fn view(&self) -> Html {
    319 -        let new_user = is_new_user(
    320 -            self.props.prev_event.clone(),
    321 -            self.props.event.clone().unwrap(),
    322 -        );
    323 +        let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event);
    324          let sender_displayname = if new_user {
    325 -            get_sender_displayname(
    326 -                self.props.room.clone().unwrap(),
    327 -                self.props.event.clone().unwrap(),
    328 -            )
    329 +            get_sender_displayname(&self.props.room, &self.props.event)
    330          } else {
    331              "".to_string()
    332          };
    333  
    334 -        let mut pure_content = self.props.notice_event.clone().unwrap().body;
    335 +        let mut pure_content = self.props.notice_event.body.clone();
    336          let finder = LinkFinder::new();
    337          let pure_content_clone = pure_content.clone();
    338          let links: Vec<_> = finder.links(&pure_content_clone).collect();
    339  
    340 -        let content = if !links.is_empty() {
    341 +        if !links.is_empty() {
    342              for link in links {
    343                  let html_link = format!("<a href={}>{}</a>", link.as_str(), link.as_str());
    344                  pure_content.replace_range(link.start()..link.end(), &html_link);
    345              }
    346 -            pure_content
    347 -        } else {
    348 -            pure_content
    349 -        };
    350 +        }
    351  
    352          if new_user {
    353              let full_html = format!(
    354                  "<p style=\"opacity: .6;\"><displayname>{}: </displayname>{}</p>",
    355 -                sender_displayname, content
    356 +                sender_displayname, pure_content
    357              );
    358              let js_text_event = {
    359                  let div = web_sys::window()
    360 @@ -96,7 +86,7 @@ impl Component for Notice {
    361              let node = Node::from(js_text_event);
    362              VNode::VRef(node)
    363          } else {
    364 -            let full_html = format!("<p style=\"opacity: .6;\">{}</p>", content);
    365 +            let full_html = format!("<p style=\"opacity: .6;\">{}</p>", pure_content);
    366              let js_text_event = {
    367                  let div = web_sys::window()
    368                      .unwrap()
    369 diff --git a/src/app/components/events/text.rs b/src/app/components/events/text.rs
    370 index 4015b45..cda0e18 100644
    371 --- a/src/app/components/events/text.rs
    372 +++ b/src/app/components/events/text.rs
    373 @@ -1,3 +1,5 @@
    374 +use std::rc::Rc;
    375 +
    376  use crate::app::components::events::{get_sender_displayname, is_new_user};
    377  use linkify::LinkFinder;
    378  use matrix_sdk::{
    379 @@ -16,12 +18,9 @@ pub struct Text {
    380  pub struct Props {
    381      #[prop_or_default]
    382      pub prev_event: Option<MessageEvent>,
    383 -    #[prop_or_default]
    384 -    pub event: Option<MessageEvent>,
    385 -    #[prop_or_default]
    386 -    pub text_event: Option<TextMessageEventContent>,
    387 -    #[prop_or_default]
    388 -    pub room: Option<Room>,
    389 +    pub event: MessageEvent,
    390 +    pub text_event: TextMessageEventContent,
    391 +    pub room: Rc<Room>,
    392  }
    393  
    394  impl Component for Text {
    395 @@ -49,20 +48,14 @@ impl Component for Text {
    396  
    397      //noinspection RsTypeCheck
    398      fn view(&self) -> Html {
    399 -        let new_user = is_new_user(
    400 -            self.props.prev_event.clone(),
    401 -            self.props.event.clone().unwrap(),
    402 -        );
    403 +        let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event);
    404          let sender_displayname = if new_user {
    405 -            get_sender_displayname(
    406 -                self.props.room.clone().unwrap(),
    407 -                self.props.event.clone().unwrap(),
    408 -            )
    409 +            get_sender_displayname(&self.props.room, &self.props.event)
    410          } else {
    411              "".to_string()
    412          };
    413  
    414 -        let mut pure_content = self.props.text_event.clone().unwrap().body;
    415 +        let mut pure_content = self.props.text_event.body.clone();
    416          let finder = LinkFinder::new();
    417          let pure_content_clone = pure_content.clone();
    418          let links: Vec<_> = finder.links(&pure_content_clone).collect();
    419 @@ -77,27 +70,16 @@ impl Component for Text {
    420              pure_content
    421          };
    422  
    423 -        if self.props.text_event.clone().unwrap().formatted.is_some() {
    424 +        if let Some(formatted) = &self.props.text_event.formatted {
    425 +            let format_slot;
    426              let message = if new_user {
    427 -                format!(
    428 +                format_slot = format!(
    429                      "<displayname>{}:</displayname> {}",
    430 -                    sender_displayname,
    431 -                    self.props
    432 -                        .text_event
    433 -                        .clone()
    434 -                        .unwrap()
    435 -                        .formatted
    436 -                        .unwrap()
    437 -                        .body
    438 -                )
    439 +                    sender_displayname, formatted.body
    440 +                );
    441 +                &format_slot
    442              } else {
    443 -                self.props
    444 -                    .text_event
    445 -                    .clone()
    446 -                    .unwrap()
    447 -                    .formatted
    448 -                    .unwrap()
    449 -                    .body
    450 +                &formatted.body
    451              };
    452              let js_text_event = {
    453                  let div = web_sys::window()
    454 diff --git a/src/app/components/events/video.rs b/src/app/components/events/video.rs
    455 index 02209ea..5892d7e 100644
    456 --- a/src/app/components/events/video.rs
    457 +++ b/src/app/components/events/video.rs
    458 @@ -1,3 +1,5 @@
    459 +use std::rc::Rc;
    460 +
    461  use crate::app::components::events::{get_sender_displayname, is_new_user};
    462  use matrix_sdk::{
    463      events::room::message::{MessageEvent, VideoMessageEventContent},
    464 @@ -14,12 +16,9 @@ pub(crate) struct Video {
    465  pub struct Props {
    466      #[prop_or_default]
    467      pub prev_event: Option<MessageEvent>,
    468 -    #[prop_or_default]
    469 -    pub event: Option<MessageEvent>,
    470 -    #[prop_or_default]
    471 -    pub video_event: Option<VideoMessageEventContent>,
    472 -    #[prop_or_default]
    473 -    pub room: Option<Room>,
    474 +    pub event: MessageEvent,
    475 +    pub video_event: VideoMessageEventContent,
    476 +    pub room: Rc<Room>,
    477  }
    478  
    479  impl Component for Video {
    480 @@ -47,54 +46,26 @@ impl Component for Video {
    481  
    482      //noinspection RsTypeCheck
    483      fn view(&self) -> Html {
    484 -        let new_user = is_new_user(
    485 -            self.props.prev_event.clone(),
    486 -            self.props.event.clone().unwrap(),
    487 -        );
    488 +        let new_user = is_new_user(self.props.prev_event.as_ref(), &self.props.event);
    489          let sender_displayname = if new_user {
    490 -            get_sender_displayname(
    491 -                self.props.room.clone().unwrap(),
    492 -                self.props.event.clone().unwrap(),
    493 -            )
    494 +            get_sender_displayname(&self.props.room, &self.props.event)
    495          } else {
    496              "".to_string()
    497          };
    498  
    499 -        let _caption = format!(
    500 -            "{}: {}",
    501 -            sender_displayname,
    502 -            self.props.video_event.as_ref().unwrap().body
    503 -        );
    504 -        if self
    505 -            .props
    506 -            .video_event
    507 -            .as_ref()
    508 -            .unwrap()
    509 -            .url
    510 -            .clone()
    511 -            .is_some()
    512 -        {
    513 -            let video_url = self
    514 -                .props
    515 -                .video_event
    516 -                .as_ref()
    517 -                .unwrap()
    518 -                .url
    519 -                .clone()
    520 -                .unwrap();
    521 -            let thumbnail = match self
    522 +        let _caption = format!("{}: {}", sender_displayname, self.props.video_event.body);
    523 +
    524 +        if let Some(video_url) = self.props.video_event.url.as_ref() {
    525 +            let thumbnail = self
    526                  .props
    527                  .video_event
    528 -                .as_ref()
    529 -                .unwrap()
    530                  .info
    531 -                .clone()
    532 +                .as_ref()
    533                  .unwrap()
    534                  .thumbnail_url
    535 -            {
    536 -                None => video_url.clone(),
    537 -                Some(v) => v,
    538 -            };
    539 +                .as_ref()
    540 +                .unwrap_or(video_url);
    541 +
    542              let lightbox_id: u8 = random();
    543              let lightbox_id_full = format!("video_{}", lightbox_id);
    544              let lightbox_href_full = format!("#video_{}", lightbox_id);
    545 @@ -102,8 +73,8 @@ impl Component for Video {
    546                  html! {
    547                      <div>
    548                          <p><displayname>{sender_displayname}{": "}</displayname></p>
    549 -                        <a href={lightbox_href_full.clone()}><img src=thumbnail/></a>
    550 -                        <div class="lightbox short-animate" id={lightbox_id_full.clone()}>
    551 +                        <a href={lightbox_href_full}><img src=thumbnail/></a>
    552 +                        <div class="lightbox short-animate" id={lightbox_id_full}>
    553                              <video class="long-animate" controls=true>
    554                                <source src=video_url type="video/mp4"/>
    555                              {"Your browser does not support the video tag."}
    556 @@ -117,8 +88,8 @@ impl Component for Video {
    557              } else {
    558                  html! {
    559                      <div>
    560 -                        <a href={lightbox_href_full.clone()}><img src=thumbnail/></a>
    561 -                        <div class="lightbox short-animate" id={lightbox_id_full.clone()}>
    562 +                        <a href={lightbox_href_full}><img src=thumbnail/></a>
    563 +                        <div class="lightbox short-animate" id={lightbox_id_full}>
    564                              <video class="long-animate" controls=true>
    565                                <source src=video_url type="video/mp4"/>
    566                              {"Your browser does not support the video tag."}
    567 diff --git a/src/app/components/room_list/item.rs b/src/app/components/room_list/item.rs
    568 index fa79d05..c25138c 100644
    569 --- a/src/app/components/room_list/item.rs
    570 +++ b/src/app/components/room_list/item.rs
    571 @@ -1,3 +1,5 @@
    572 +use std::rc::Rc;
    573 +
    574  use matrix_sdk::{events::room::message::MessageEventContent, identifiers::RoomId, Room};
    575  use yew::prelude::*;
    576  use yewtil::NeqAssign;
    577 @@ -8,13 +10,12 @@ pub(crate) struct RoomItem {
    578  }
    579  
    580  pub enum Msg {
    581 -    ChangeRoom(Room),
    582 +    ChangeRoom(Rc<Room>),
    583  }
    584  
    585  #[derive(Clone, Properties, Debug, PartialEq)]
    586  pub struct Props {
    587 -    #[prop_or_default]
    588 -    pub room: Option<Room>,
    589 +    pub room: Rc<Room>,
    590  
    591      #[prop_or_default]
    592      pub change_room_callback: Callback<RoomId>,
    593 @@ -31,7 +32,7 @@ impl Component for RoomItem {
    594      fn update(&mut self, msg: Self::Message) -> bool {
    595          match msg {
    596              Msg::ChangeRoom(room) => {
    597 -                self.props.change_room_callback.emit(room.room_id);
    598 +                self.props.change_room_callback.emit(room.room_id.clone());
    599              }
    600          }
    601          false
    602 @@ -43,28 +44,22 @@ impl Component for RoomItem {
    603  
    604      //noinspection RsTypeCheck
    605      fn view(&self) -> Html {
    606 -        let room = self.props.room.clone().unwrap();
    607 +        let room = self.props.room.clone();
    608  
    609          // TODO placeholder for encrypted rooms
    610 -        let last_message = match self
    611 -            .props
    612 -            .room
    613 -            .as_ref()
    614 -            .unwrap()
    615 -            .messages
    616 -            .clone()
    617 -            .into_iter()
    618 -            .last()
    619 -        {
    620 +        let last_message = match room.messages.iter().last() {
    621              None => "".to_string(),
    622              Some(m) => {
    623                  if let MessageEventContent::Text(text_event) = &m.content {
    624 -                    text_event.clone().body
    625 +                    text_event.body.clone()
    626                  } else {
    627                      "".to_string()
    628                  }
    629              }
    630          };
    631 +
    632 +        let display_name = room.display_name();
    633 +
    634          html! {
    635              <div class="room-list-item">
    636                  <a onclick=self.link.callback(move |e: MouseEvent| Msg::ChangeRoom(room.clone()))>
    637 @@ -72,7 +67,7 @@ impl Component for RoomItem {
    638                          // TODO remove placeholder
    639                          <img class="avatar" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAARUlEQVRYhe3OMQ0AIADAMBKUowmBoIKMo0f/jrnX+dmoA4KCdUBQsA4ICtYBQcE6IChYBwQF64CgYB0QFKwDgoJ1QPC1C8gY0kSgNLTWAAAAAElFTkSuQmCC"/>
    640                          <div>
    641 -                            <h5 class="name">{self.props.room.as_ref().unwrap().display_name()}</h5>
    642 +                            <h5 class="name">{display_name}</h5>
    643                              <p class="latest-msg">{last_message}</p>
    644                          </div>
    645                      </div>
    646 diff --git a/src/app/components/room_list/mod.rs b/src/app/components/room_list/mod.rs
    647 index f99eb43..516ecc0 100644
    648 --- a/src/app/components/room_list/mod.rs
    649 +++ b/src/app/components/room_list/mod.rs
    650 @@ -1,5 +1,4 @@
    651 -use std::collections::HashMap;
    652 -use std::include_str;
    653 +use std::{collections::HashMap, rc::Rc};
    654  
    655  use log::*;
    656  use matrix_sdk::{identifiers::RoomId, Room};
    657 @@ -36,7 +35,7 @@ pub enum Msg {
    658  
    659  #[derive(Serialize, Deserialize, Default)]
    660  pub struct State {
    661 -    rooms: HashMap<RoomId, Room>,
    662 +    rooms: HashMap<RoomId, Rc<Room>>,
    663      current_room: Option<RoomId>,
    664      loading: bool,
    665      search_query: Option<String>,
    666 @@ -46,7 +45,7 @@ pub struct State {
    667  #[derive(Clone, PartialEq, Properties)]
    668  pub struct Props {
    669      #[prop_or_default]
    670 -    pub change_room_callback: Callback<Room>,
    671 +    pub change_room_callback: Callback<Rc<Room>>,
    672  }
    673  
    674  impl Component for RoomList {
    675 @@ -85,7 +84,7 @@ impl Component for RoomList {
    676                  }
    677                  Response::JoinedRoom((room_id, room)) => {
    678                      info!("Got JoinedRoom");
    679 -                    self.state.rooms.insert(room_id, room);
    680 +                    self.state.rooms.insert(room_id, Rc::new(room));
    681                      if self.state.loading {
    682                          self.state.loading = false;
    683                      }
    684 @@ -144,6 +143,27 @@ impl Component for RoomList {
    685                  </div>
    686              }
    687          } else {
    688 +            let rooms = if self.state.search_query.is_none()
    689 +                || (self.state.search_query.as_ref().unwrap_or(&"".to_string()) == &"".to_string())
    690 +            {
    691 +                self.state
    692 +                    .rooms
    693 +                    .iter()
    694 +                    .map(|(_, room)| self.get_room(room))
    695 +                    .collect::<Html>()
    696 +            } else {
    697 +                self.state
    698 +                    .rooms
    699 +                    .iter()
    700 +                    .filter(|(_, room)| {
    701 +                        room.display_name()
    702 +                            .to_lowercase()
    703 +                            .contains(&self.state.search_query.as_ref().unwrap().to_lowercase())
    704 +                    })
    705 +                    .map(|(_, room)| self.get_room(room))
    706 +                    .collect::<Html>()
    707 +            };
    708 +
    709              html! {
    710                  <div class="roomlist" style="height: 100%">
    711                      <div class="top-bar">
    712 @@ -166,16 +186,7 @@ impl Component for RoomList {
    713                              </div>
    714                          </div>
    715                      </div>
    716 -
    717 -                    <div class="scrollable list">
    718 -                        {
    719 -                            if self.state.search_query.is_none() || (self.state.search_query.as_ref().unwrap_or(&"".to_string()) == &"".to_string()) {
    720 -                                self.state.rooms.iter().map(|(_, room)| self.get_room(room)).collect::<Html>()
    721 -                            } else {
    722 -                                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>()
    723 -                            }
    724 -                        }
    725 -                    </div>
    726 +                    <div class="scrollable list">{rooms}</div>
    727                      <div class="bottom-bar">
    728                          <div class="toggleWrapper">
    729                              <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})/>
    730 @@ -201,10 +212,10 @@ impl Component for RoomList {
    731  }
    732  
    733  impl RoomList {
    734 -    fn get_room(&self, matrix_room: &Room) -> Html {
    735 +    fn get_room(&self, matrix_room: &Rc<Room>) -> Html {
    736          let room = matrix_room.clone();
    737          html! {
    738 -            <RoomItem change_room_callback=self.link.callback(Msg::ChangeRoom) room=Some(room)/>
    739 +            <RoomItem change_room_callback=self.link.callback(Msg::ChangeRoom) room=room.clone() />
    740          }
    741          /*html! {
    742              <li class=classes>
    743 diff --git a/src/app/matrix/mod.rs b/src/app/matrix/mod.rs
    744 index 1f30583..921b686 100644
    745 --- a/src/app/matrix/mod.rs
    746 +++ b/src/app/matrix/mod.rs
    747 @@ -308,7 +308,7 @@ impl Agent for MatrixAgent {
    748                              {
    749                                  if image_event.url.is_some() {
    750                                      let new_url = Some(get_media_download_url(
    751 -                                        agent.matrix_client.clone().unwrap().homeserver(),
    752 +                                        agent.matrix_client.as_ref().unwrap().homeserver(),
    753                                          image_event.url.unwrap(),
    754                                      ));
    755                                      image_event.url = new_url;
    756 @@ -317,7 +317,7 @@ impl Agent for MatrixAgent {
    757                                      let mut info = image_event.info.unwrap();
    758                                      if info.thumbnail_url.is_some() {
    759                                          let new_url = Some(get_media_download_url(
    760 -                                            agent.matrix_client.clone().unwrap().homeserver(),
    761 +                                            agent.matrix_client.as_ref().unwrap().homeserver(),
    762                                              info.thumbnail_url.unwrap(),
    763                                          ));
    764                                          info.thumbnail_url = new_url;
    765 @@ -329,7 +329,7 @@ impl Agent for MatrixAgent {
    766                              if let MessageEventContent::Video(mut video_event) = event.content {
    767                                  if video_event.url.is_some() {
    768                                      let new_url = Some(get_video_media_download_url(
    769 -                                        agent.matrix_client.clone().unwrap().homeserver(),
    770 +                                        agent.matrix_client.as_ref().unwrap().homeserver(),
    771                                          video_event.url.unwrap(),
    772                                      ));
    773                                      video_event.url = new_url;
    774 @@ -338,7 +338,7 @@ impl Agent for MatrixAgent {
    775                                      let mut info = video_event.info.unwrap();
    776                                      if info.thumbnail_url.is_some() {
    777                                          let new_url = Some(get_media_download_url(
    778 -                                            agent.matrix_client.clone().unwrap().homeserver(),
    779 +                                            agent.matrix_client.as_ref().unwrap().homeserver(),
    780                                              info.thumbnail_url.unwrap(),
    781                                          ));
    782                                          info.thumbnail_url = new_url;
    783 @@ -441,10 +441,10 @@ impl MatrixAgent {
    784          info!("preparing client");
    785          if self.session.is_some() {
    786              info!("restoring login");
    787 -            let homeserver = self.session.clone().unwrap().homeserver_url;
    788 +            let homeserver = &self.session.as_ref().unwrap().homeserver_url;
    789  
    790              let client_config = ClientConfig::new();
    791 -            let homeserver_url = Url::parse(&homeserver).unwrap();
    792 +            let homeserver_url = Url::parse(homeserver).unwrap();
    793              let client = Client::new_with_config(homeserver_url, client_config).unwrap();
    794              self.matrix_client = Some(client.clone());
    795  
    796 diff --git a/src/app/matrix/sync.rs b/src/app/matrix/sync.rs
    797 index c41880c..7448b9f 100644
    798 --- a/src/app/matrix/sync.rs
    799 +++ b/src/app/matrix/sync.rs
    800 @@ -1,3 +1,4 @@
    801 +use std::mem;
    802  use std::sync::Arc;
    803  use std::sync::Mutex;
    804  use std::time::Duration;
    805 @@ -88,7 +89,7 @@ impl Sync {
    806          }
    807  
    808          if let RoomEvent::RoomMessage(mut event) = event {
    809 -            if let MessageEventContent::Text(text_event) = event.clone().content {
    810 +            if let MessageEventContent::Text(text_event) = event.content.clone() {
    811                  let homeserver_url = self.matrix_client.clone().homeserver().clone();
    812  
    813                  let cloned_event = event.clone();
    814 @@ -99,18 +100,19 @@ impl Sync {
    815                      spawn_local(async move {
    816                          let room: Arc<RwLock<Room>> = client
    817                              .clone()
    818 -                            .get_joined_room(&local_room_id.clone())
    819 +                            .get_joined_room(&local_room_id)
    820                              .await
    821                              .unwrap();
    822 -                        let read_clone = room.read().await;
    823 -                        let clean_room = (*read_clone).clone();
    824 -                        let avatar_url = get_sender_avatar(
    825 -                            homeserver_url,
    826 -                            clean_room.clone(),
    827 -                            cloned_event.clone(),
    828 -                        );
    829 -                        let room_name = clean_room.display_name();
    830 -                        let displayname = get_sender_displayname(clean_room, cloned_event.clone());
    831 +
    832 +                        let (avatar_url, room_name, displayname) = {
    833 +                            let room = room.read().await;
    834 +
    835 +                            (
    836 +                                get_sender_avatar(homeserver_url, &room, &cloned_event),
    837 +                                room.display_name(),
    838 +                                get_sender_displayname(&room, &cloned_event),
    839 +                            )
    840 +                        };
    841  
    842                          let title = if displayname == room_name {
    843                              displayname
    844 @@ -124,47 +126,43 @@ impl Sync {
    845                      });
    846                  }
    847              }
    848 -            if let MessageEventContent::Image(mut image_event) = event.clone().content {
    849 -                if image_event.url.is_some() {
    850 -                    let new_url = Some(get_media_download_url(
    851 +            if let MessageEventContent::Image(image_event) = &mut event.content {
    852 +                if let Some(image_url) = &mut image_event.url {
    853 +                    let old_image_url = mem::take(image_url);
    854 +                    *image_url = get_media_download_url(
    855                          self.matrix_client.clone().homeserver(),
    856 -                        image_event.url.unwrap(),
    857 -                    ));
    858 -                    image_event.url = new_url;
    859 +                        old_image_url,
    860 +                    );
    861                  }
    862 -                if image_event.info.is_some() {
    863 -                    let mut info = image_event.info.unwrap();
    864 -                    if info.thumbnail_url.is_some() {
    865 -                        let new_url = Some(get_media_download_url(
    866 +
    867 +                if let Some(info) = &mut image_event.info {
    868 +                    if let Some(thumbnail_url) = &mut info.thumbnail_url {
    869 +                        let old_thumbnail_url = mem::take(thumbnail_url);
    870 +                        *thumbnail_url = get_media_download_url(
    871                              self.matrix_client.clone().homeserver(),
    872 -                            info.thumbnail_url.unwrap(),
    873 -                        ));
    874 -                        info.thumbnail_url = new_url;
    875 +                            old_thumbnail_url,
    876 +                        );
    877                      }
    878 -                    image_event.info = Some(info);
    879                  }
    880 -                event.content = MessageEventContent::Image(image_event);
    881              }
    882 -            if let MessageEventContent::Video(mut video_event) = event.content {
    883 -                if video_event.url.is_some() {
    884 -                    let new_url = Some(get_video_media_download_url(
    885 +            if let MessageEventContent::Video(video_event) = &mut event.content {
    886 +                if let Some(video_url) = &mut video_event.url {
    887 +                    let old_video_url = mem::take(video_url);
    888 +                    *video_url = get_video_media_download_url(
    889                          self.matrix_client.clone().homeserver(),
    890 -                        video_event.url.unwrap(),
    891 -                    ));
    892 -                    video_event.url = new_url;
    893 +                        old_video_url,
    894 +                    );
    895                  }
    896 -                if video_event.info.is_some() {
    897 -                    let mut info = video_event.info.unwrap();
    898 -                    if info.thumbnail_url.is_some() {
    899 -                        let new_url = Some(get_media_download_url(
    900 +
    901 +                if let Some(info) = &mut video_event.info {
    902 +                    if let Some(thumbnail_url) = &mut info.thumbnail_url {
    903 +                        let old_thumbnail_url = mem::take(thumbnail_url);
    904 +                        *thumbnail_url = get_media_download_url(
    905                              self.matrix_client.clone().homeserver(),
    906 -                            info.thumbnail_url.unwrap(),
    907 -                        ));
    908 -                        info.thumbnail_url = new_url;
    909 +                            old_thumbnail_url,
    910 +                        );
    911                      }
    912 -                    video_event.info = Some(info);
    913                  }
    914 -                event.content = MessageEventContent::Video(video_event);
    915              }
    916  
    917              let serialized_event = EventJson::from(event);
    918 diff --git a/src/app/views/main_view.rs b/src/app/views/main_view.rs
    919 index b470eca..b957b29 100644
    920 --- a/src/app/views/main_view.rs
    921 +++ b/src/app/views/main_view.rs
    922 @@ -1,3 +1,5 @@
    923 +use std::rc::Rc;
    924 +
    925  use log::*;
    926  use matrix_sdk::Room;
    927  use serde::{Deserialize, Serialize};
    928 @@ -15,12 +17,12 @@ pub struct MainView {
    929  }
    930  
    931  pub enum Msg {
    932 -    ChangeRoom(Room),
    933 +    ChangeRoom(Rc<Room>),
    934  }
    935  
    936  #[derive(Serialize, Deserialize, Default)]
    937  pub struct State {
    938 -    pub current_room: Option<Room>,
    939 +    pub current_room: Option<Rc<Room>>,
    940      pub current_room_displayname: String,
    941  }
    942  
    943 @@ -55,8 +57,8 @@ impl Component for MainView {
    944  
    945      //noinspection RsTypeCheck
    946      fn view(&self) -> Html {
    947 -        if self.state.current_room.is_none() {
    948 -            html! {
    949 +        match &self.state.current_room {
    950 +            None => html! {
    951                  <div class="uk-flex auto-scrollable-container uk-background-default" style="height: 100%">
    952                      <RoomList change_room_callback=self.link.callback(Msg::ChangeRoom)/>
    953  
    954 @@ -66,13 +68,12 @@ impl Component for MainView {
    955                          </div>
    956                      </div>
    957                  </div>
    958 -            }
    959 -        } else if self.state.current_room.as_ref().unwrap().is_encrypted() {
    960 -            html! {
    961 +            },
    962 +            Some(room) if room.is_encrypted() => html! {
    963                  <div class="uk-flex auto-scrollable-container" style="height: 100%">
    964                      <RoomList change_room_callback=self.link.callback(Msg::ChangeRoom)/>
    965                      <div class="event-list">
    966 -                        <div class="room-title"><h1>{ self.state.current_room.as_ref().unwrap().display_name() }</h1></div>
    967 +                        <div class="room-title"><h1>{ room.display_name() }</h1></div>
    968                          <h4>
    969                              {
    970                                  tr!(
    971 @@ -83,14 +84,13 @@ impl Component for MainView {
    972                          </h4>
    973                      </div>
    974                  </div>
    975 -            }
    976 -        } else {
    977 -            html! {
    978 +            },
    979 +            Some(room) => html! {
    980                  <div class="uk-flex auto-scrollable-container" style="height: 100%">
    981                      <RoomList change_room_callback=self.link.callback(Msg::ChangeRoom)/>
    982 -                    <EventList current_room=self.state.current_room.as_ref().unwrap() />
    983 +                    <EventList current_room=room />
    984                  </div>
    985 -            }
    986 +            },
    987          }
    988      }
    989  }