From 5657931dd606845bd50a609b3f5ac9a1294213c6 Mon Sep 17 00:00:00 2001 From: alanpoon Date: Fri, 4 Oct 2024 12:31:38 +0800 Subject: [PATCH 01/40] reduce complexity of send_read_receipt --- src/home/room_screen.rs | 65 +++++++++-------------------------------- 1 file changed, 13 insertions(+), 52 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index a836df4f..038ef098 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -962,49 +962,16 @@ impl RoomScreen{ let Some(room_id) = self.room_id.as_ref() else { return }; if let Some(ref mut index) = tl_state.prev_first_index { // to detect change of scroll when scroll ends - if *index != first_index { + if *index != first_index { // scroll changed - self.fully_read_timer = cx.start_interval(5.0); - let time_now = std::time::Instant::now(); if first_index > *index { - // Store visible event messages with current time into a hashmap - let mut read_receipt_event = None; - for r in first_index .. (first_index + portal_list.visible_items() + 1) { - if let Some(v) = tl_state.items.get(r) { - if let Some(e) = v.as_event().and_then(|f| f.event_id()) { - read_receipt_event = Some(e.to_owned()); - if !tl_state.read_event_hashmap.contains_key(&e.to_string()) { - tl_state.read_event_hashmap.insert( - e.to_string(), - (room_id.clone(), e.to_owned(), time_now, false), - ); - } - } - } - } - if let Some(event_id) = read_receipt_event { - submit_async_request(MatrixRequest::ReadReceipt { room_id: room_id.clone(), event_id }); - } - let mut fully_read_receipt_event = None; - // Implements sending fully read receipts when message is scrolled out of first row - for r in *index..first_index { - if let Some(v) = tl_state.items.get(r).clone() { - if let Some(e) = v.as_event().and_then(|f| f.event_id()) { - let mut to_remove = vec![]; - for (event_id_string, (_, event_id)) in &tl_state.marked_fully_read_queue { - if e == event_id { - fully_read_receipt_event = Some(event_id.clone()); - to_remove.push(event_id_string.clone()); - } - } - for r in to_remove { - tl_state.marked_fully_read_queue.remove(&r); - } - } - } - } - if let Some(event_id) = fully_read_receipt_event { - submit_async_request(MatrixRequest::FullyReadReceipt { room_id: room_id.clone(), event_id: event_id.clone()}); + cx.stop_timer(self.fully_read_timer); + self.fully_read_timer = cx.start_interval(5.0); + let index_to_send_read = first_index + portal_list.visible_items(); + if let Some(event_id) = tl_state.items.get(index_to_send_read) + .and_then(|f|f.as_event()).and_then(|f|f.event_id()) { + submit_async_request(MatrixRequest::ReadReceipt { room_id: room_id.clone(), event_id: event_id.to_owned() }); + tl_state.last_displayed_event = Some(event_id.to_owned()); } } *index = first_index; @@ -1264,13 +1231,9 @@ impl Widget for RoomScreen { // Mark events as fully read after they have been displayed on screen for 5 seconds. if self.fully_read_timer.is_event(event).is_some() { - if let (Some(ref mut tl_state), Some(ref _room_id)) = (&mut self.tl_state, &self.room_id) { - for (k, (room, event, start, ref mut moved_to_queue)) in &mut tl_state.read_event_hashmap { - if start.elapsed() > std::time::Duration::new(5, 0) && !*moved_to_queue{ - tl_state.marked_fully_read_queue.insert(k.clone(), (room.clone(), event.clone())); - *moved_to_queue = true; - } - } + if let (Some(ref mut tl_state), Some(ref room_id)) = (&mut self.tl_state, &self.room_id) { + let Some(last_displayed_event) = &tl_state.last_displayed_event else { return }; + submit_async_request(MatrixRequest::FullyReadReceipt { room_id: room_id.clone(), event_id: last_displayed_event.clone()}); } cx.stop_timer(self.fully_read_timer); } @@ -1664,8 +1627,7 @@ impl RoomScreen { saved_state: SavedState::default(), message_highlight_animation_state: MessageHighlightAnimationState::default(), prev_first_index: None, - read_event_hashmap: HashMap::new(), - marked_fully_read_queue: HashMap::new(), + last_displayed_event: None, }; (new_tl_state, true) }; @@ -1918,8 +1880,7 @@ struct TimelineUiState { message_highlight_animation_state: MessageHighlightAnimationState, prev_first_index: Option, - read_event_hashmap: HashMap, - marked_fully_read_queue: HashMap, + last_displayed_event: Option, } /// The item index, scroll position, and optional unique IDs of the first `N` events From bb92afbd4e5502fb593148ff6627583b20671b2a Mon Sep 17 00:00:00 2001 From: alanpoon Date: Fri, 4 Oct 2024 13:44:31 +0800 Subject: [PATCH 02/40] cleanup --- src/home/room_screen.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 038ef098..6622c815 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -967,9 +967,9 @@ impl RoomScreen{ if first_index > *index { cx.stop_timer(self.fully_read_timer); self.fully_read_timer = cx.start_interval(5.0); - let index_to_send_read = first_index + portal_list.visible_items(); - if let Some(event_id) = tl_state.items.get(index_to_send_read) - .and_then(|f|f.as_event()).and_then(|f|f.event_id()) { + if let Some(event_id) = tl_state.items.get(first_index + portal_list.visible_items()) + .and_then(|f| f.as_event() ) + .and_then(|f| f.event_id() ) { submit_async_request(MatrixRequest::ReadReceipt { room_id: room_id.clone(), event_id: event_id.to_owned() }); tl_state.last_displayed_event = Some(event_id.to_owned()); } From 925536594f05226eaee06ce6f2073a8c4c71b8c5 Mon Sep 17 00:00:00 2001 From: alanpoon Date: Fri, 4 Oct 2024 14:07:31 +0800 Subject: [PATCH 03/40] removed unnecessary import --- src/home/room_screen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 6622c815..4a365d36 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -1,7 +1,7 @@ //! A room screen is the UI page that displays a single Room's timeline of events/messages //! along with a message input bar at the bottom. -use std::{borrow::Cow, collections::{BTreeMap, HashMap}, ops::{DerefMut, Range}, sync::{Arc, Mutex}, time::Instant}; +use std::{borrow::Cow, collections::BTreeMap, ops::{DerefMut, Range}, sync::{Arc, Mutex}}; use imbl::Vector; use makepad_widgets::*; From 24be468fb95b5254994be9471c24eceb474f059a Mon Sep 17 00:00:00 2001 From: alanpoon Date: Thu, 10 Oct 2024 23:37:07 +0800 Subject: [PATCH 04/40] added unread_message_badge --- src/home/room_screen.rs | 64 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 37aaa5fd..73293a22 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -656,26 +656,56 @@ live_design! { flow: Down, align: {x: 1.0, y: 1.0}, margin: {right: 15.0, bottom: 15.0}, - visible: false, + visible: true, jump_to_bottom_button = { width: 50, height: 50, draw_icon: {svg_file: (ICO_JUMP_TO_BOTTOM)}, - icon_walk: {width: 20, height: 20, margin: {top: 10, right: 4.5} } - // draw a circular background for the button + icon_walk: {width: 20, height: 20, margin: {top: 10, right: 4.5} }, draw_bg: { instance background_color: #edededee, fn pixel(self) -> vec4 { let sdf = Sdf2d::viewport(self.pos * self.rect_size); let c = self.rect_size * 0.5; - sdf.circle(c.x, c.x, c.x) + sdf.circle(c.x, c.x, c.x); sdf.fill_keep(self.background_color); return sdf.result } } } - } + // Badge overlay for unread messages + unread_message_badge = { + width: 20, height: 20, + margin: {top: -10.0, right: 15.0}, + visible: true, + show_bg: true, + draw_bg: { + instance background_color: (#5D5E5E) + + fn pixel(self) -> vec4 { + let sdf = Sdf2d::viewport(self.pos * self.rect_size); + let c = self.rect_size * 0.5; + sdf.circle(c.x, c.x, c.x); + sdf.fill_keep(self.background_color); + return sdf.result; + } + } + + // Text to display the unread message count + label =