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 }