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 }