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

sync.rs (7865B)


      1 use std::mem;
      2 use std::sync::Arc;
      3 use std::sync::Mutex;
      4 use std::time::Duration;
      5 
      6 use log::*;
      7 use matrix_sdk::{
      8     api::r0::filter::{FilterDefinition, LazyLoadOptions, RoomEventFilter, RoomFilter},
      9     api::r0::sync::sync_events::Filter,
     10     api::r0::sync::sync_events::Response as SyncResponse,
     11     events::{
     12         room::message::MessageEventContent, AnySyncMessageEvent, AnySyncRoomEvent,
     13         AnySyncStateEvent,
     14     },
     15     identifiers::RoomId,
     16     locks::RwLock,
     17     Client, Raw, Room, SyncSettings,
     18 };
     19 use wasm_bindgen_futures::spawn_local;
     20 use yew::Callback;
     21 
     22 use lazy_static::lazy_static;
     23 use matrix_sdk::js_int::UInt;
     24 
     25 use crate::app::components::events::RoomExt;
     26 use crate::app::matrix::types::{get_media_download_url, get_video_media_download_url};
     27 use crate::app::matrix::Response;
     28 use crate::utils::notifications::Notifications;
     29 
     30 lazy_static! {
     31     static ref SYNC_NUMBER: Mutex<i32> = Mutex::new(0);
     32 }
     33 
     34 pub struct Sync {
     35     pub(crate) matrix_client: Client,
     36     pub(crate) callback: Callback<Response>,
     37 }
     38 
     39 impl Sync {
     40     pub async fn start_sync(&self) {
     41         debug!("start sync!");
     42         let client = self.matrix_client.clone();
     43         let settings = SyncSettings::default()
     44             .timeout(Duration::from_secs(30))
     45             .filter(Filter::FilterDefinition(FilterDefinition {
     46                 room: Some(RoomFilter {
     47                     timeline: Some(RoomEventFilter {
     48                         limit: Some(UInt::new(20).unwrap()),
     49                         lazy_load_options: LazyLoadOptions::Enabled {
     50                             include_redundant_members: true,
     51                         },
     52                         ..Default::default()
     53                     }),
     54                     ..Default::default()
     55                 }),
     56                 ..Default::default()
     57             }));
     58         //.full_state(true);
     59 
     60         debug!("start sync_forever!");
     61         client
     62             .sync_forever(settings, |response| self.on_sync_response(response))
     63             .await;
     64     }
     65 
     66     async fn on_sync_response(&self, response: SyncResponse) {
     67         debug!("got sync!");
     68 
     69         // FIXME: Is there a smarter way?
     70         let resp = Response::SyncPing;
     71         self.callback.emit(resp);
     72         for (room_id, room) in response.rooms.join {
     73             for event in room.state.events {
     74                 if let Ok(event) = event.deserialize() {
     75                     self.on_state_event(&room_id, event).await
     76                 }
     77             }
     78             for event in room.timeline.events {
     79                 if let Ok(event) = event.deserialize() {
     80                     self.on_room_message(&room_id, event).await
     81                 }
     82             }
     83         }
     84         let mut sync_number = SYNC_NUMBER.lock().unwrap();
     85         if *sync_number == 0 {
     86             *sync_number = 1;
     87         }
     88     }
     89 
     90     async fn on_state_event(&self, room_id: &RoomId, event: AnySyncStateEvent) {
     91         if let AnySyncStateEvent::RoomCreate(_event) = event {
     92             info!("Sent JoinedRoomSync State");
     93             let resp = Response::JoinedRoomSync(room_id.clone());
     94             self.callback.emit(resp);
     95         }
     96     }
     97 
     98     async fn on_room_message(&self, room_id: &RoomId, event: AnySyncRoomEvent) {
     99         // TODO handle all messages...
    100 
    101         if let AnySyncRoomEvent::State(AnySyncStateEvent::RoomCreate(_create_event)) = event.clone()
    102         {
    103             info!("Sent JoinedRoomSync Timeline");
    104             let resp = Response::JoinedRoomSync(room_id.clone());
    105             self.callback.emit(resp);
    106         }
    107 
    108         if let AnySyncRoomEvent::Message(AnySyncMessageEvent::RoomMessage(mut event)) = event {
    109             if let MessageEventContent::Text(text_event) = event.content.clone() {
    110                 let homeserver_url = self.matrix_client.clone().homeserver().clone();
    111 
    112                 let cloned_event = event.clone();
    113                 let client = self.matrix_client.clone();
    114                 let local_room_id = room_id.clone();
    115                 let sync_number = SYNC_NUMBER.lock().unwrap();
    116                 if *sync_number == 1 {
    117                     spawn_local(async move {
    118                         let room: Arc<RwLock<Room>> = client
    119                             .clone()
    120                             .get_joined_room(&local_room_id)
    121                             .await
    122                             .unwrap();
    123                         if cloned_event.sender.clone() != client.user_id().await.unwrap() {
    124                             let (avatar_url, room_name, displayname) = {
    125                                 let room = room.read().await;
    126                                 (
    127                                     room.get_sender_avatar(
    128                                         &homeserver_url,
    129                                         &AnySyncMessageEvent::RoomMessage(cloned_event.clone()),
    130                                     ),
    131                                     room.display_name(),
    132                                     room.get_sender_displayname(&AnySyncMessageEvent::RoomMessage(
    133                                         cloned_event,
    134                                     ))
    135                                     .to_string(),
    136                                 )
    137                             };
    138 
    139                             let title = if displayname == room_name {
    140                                 displayname
    141                             } else {
    142                                 format!("{} ({})", displayname, room_name)
    143                             };
    144 
    145                             let notification =
    146                                 Notifications::new(avatar_url, title, text_event.body.clone());
    147                             notification.show();
    148                         }
    149                     });
    150                 }
    151             }
    152             if let MessageEventContent::Image(image_event) = &mut event.content {
    153                 if let Some(image_url) = &mut image_event.url {
    154                     let old_image_url = mem::take(image_url);
    155                     *image_url = get_media_download_url(
    156                         self.matrix_client.clone().homeserver(),
    157                         &old_image_url,
    158                     )
    159                     .to_string();
    160                 }
    161 
    162                 if let Some(info) = &mut image_event.info {
    163                     if let Some(thumbnail_url) = &mut info.thumbnail_url {
    164                         let old_thumbnail_url = mem::take(thumbnail_url);
    165                         *thumbnail_url = get_media_download_url(
    166                             self.matrix_client.clone().homeserver(),
    167                             &old_thumbnail_url,
    168                         )
    169                         .to_string();
    170                     }
    171                 }
    172             }
    173             if let MessageEventContent::Video(video_event) = &mut event.content {
    174                 if let Some(video_url) = &mut video_event.url {
    175                     let old_video_url = mem::take(video_url);
    176                     *video_url = get_video_media_download_url(
    177                         self.matrix_client.clone().homeserver(),
    178                         old_video_url,
    179                     )
    180                     .to_string();
    181                 }
    182 
    183                 if let Some(info) = &mut video_event.info {
    184                     if let Some(thumbnail_url) = &mut info.thumbnail_url {
    185                         let old_thumbnail_url = mem::take(thumbnail_url);
    186                         *thumbnail_url = get_media_download_url(
    187                             self.matrix_client.clone().homeserver(),
    188                             &old_thumbnail_url,
    189                         )
    190                         .to_string();
    191                     }
    192                 }
    193             }
    194 
    195             let serialized_event = Raw::from(AnySyncMessageEvent::RoomMessage(event));
    196             let resp = Response::Sync((room_id.clone(), serialized_event));
    197             self.callback.emit(resp);
    198         }
    199     }
    200 }