Skip to content

Commit

Permalink
Reduce CPU usage by instead fetching read receipts after related sync…
Browse files Browse the repository at this point in the history
… events (#168)
  • Loading branch information
olivia-fl authored Oct 16, 2023
1 parent df3148b commit b2b47ed
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 82 deletions.
53 changes: 29 additions & 24 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,6 @@ pub type IambResult<T> = UIResult<T, IambInfo>;
/// it's reacting to.
pub type MessageReactions = HashMap<OwnedEventId, (String, OwnedUserId)>;

/// Map of read receipts for different events.
pub type Receipts = HashMap<OwnedEventId, Vec<OwnedUserId>>;

/// Errors encountered during application use.
#[derive(thiserror::Error, Debug)]
pub enum IambError {
Expand Down Expand Up @@ -549,7 +546,14 @@ pub struct RoomInfo {
pub messages: Messages,

/// A map of read markers to display on different events.
pub receipts: HashMap<OwnedEventId, Vec<OwnedUserId>>,
pub event_receipts: HashMap<OwnedEventId, HashSet<OwnedUserId>>,

/// A map of the most recent read marker for each user.
///
/// Every receipt in this map should also have an entry in [`event_receipts`],
/// however not every user has an entry. If a user's most recent receipt is
/// older than the oldest loaded event, that user will not be included.
pub user_receipts: HashMap<OwnedUserId, OwnedEventId>,

/// An event ID for where we should indicate we've read up to.
pub read_till: Option<OwnedEventId>,
Expand Down Expand Up @@ -698,6 +702,27 @@ impl RoomInfo {
self.fetch_last.map_or(false, |i| i.elapsed() < ROOM_FETCH_DEBOUNCE)
}

fn clear_receipt(&mut self, user_id: &OwnedUserId) -> Option<()> {
let old_event_id = self.user_receipts.get(user_id)?;
let old_receipts = self.event_receipts.get_mut(old_event_id)?;
old_receipts.remove(user_id);

if old_receipts.is_empty() {
self.event_receipts.remove(old_event_id);
}

None
}

pub fn set_receipt(&mut self, user_id: OwnedUserId, event_id: OwnedEventId) {
self.clear_receipt(&user_id);
self.event_receipts
.entry(event_id.clone())
.or_default()
.insert(user_id.clone());
self.user_receipts.insert(user_id, event_id);
}

fn get_typers(&self) -> &[OwnedUserId] {
if let Some((t, users)) = &self.users_typing {
if t.elapsed() < Duration::from_secs(4) {
Expand Down Expand Up @@ -860,26 +885,6 @@ impl ChatStore {
.unwrap_or_else(|| "Untitled Matrix Room".to_string())
}

/// Update the receipts for multiple rooms.
pub async fn set_receipts(
&mut self,
receipts: Vec<(OwnedRoomId, Receipts)>,
) -> Vec<(OwnedRoomId, OwnedEventId)> {
let mut updates = vec![];

for (room_id, receipts) in receipts.into_iter() {
if let Some(info) = self.rooms.get_mut(&room_id) {
info.receipts = receipts;

if let Some(read_till) = info.read_till.take() {
updates.push((room_id, read_till));
}
}
}

return updates;
}

/// Mark a room for loading more scrollback.
pub fn mark_for_load(&mut self, room_id: OwnedRoomId) {
self.need_load.insert(room_id);
Expand Down
22 changes: 10 additions & 12 deletions src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
use std::borrow::Cow;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::hash_map::DefaultHasher;
use std::collections::hash_set;
use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::hash::{Hash, Hasher};
use std::slice::Iter;

use chrono::{DateTime, Local as LocalTz, NaiveDateTime, TimeZone};
use comrak::{markdown_to_html, ComrakOptions};
Expand Down Expand Up @@ -501,7 +501,7 @@ struct MessageFormatter<'a> {
date: Option<Span<'a>>,

/// Iterator over the users who have read up to this message.
read: Iter<'a, OwnedUserId>,
read: Option<hash_set::Iter<'a, OwnedUserId>>,
}

impl<'a> MessageFormatter<'a> {
Expand Down Expand Up @@ -533,10 +533,11 @@ impl<'a> MessageFormatter<'a> {
// Show read receipts.
let user_char =
|user: &'a OwnedUserId| -> Span<'a> { settings.get_user_char_span(user) };
let mut read = self.read.iter_mut().flatten();

let a = self.read.next().map(user_char).unwrap_or_else(|| Span::raw(" "));
let b = self.read.next().map(user_char).unwrap_or_else(|| Span::raw(" "));
let c = self.read.next().map(user_char).unwrap_or_else(|| Span::raw(" "));
let a = read.next().map(user_char).unwrap_or_else(|| Span::raw(" "));
let b = read.next().map(user_char).unwrap_or_else(|| Span::raw(" "));
let c = read.next().map(user_char).unwrap_or_else(|| Span::raw(" "));

line.push(Span::raw(" "));
line.push(c);
Expand Down Expand Up @@ -650,34 +651,31 @@ impl Message {
let fill = width - USER_GUTTER - TIME_GUTTER - READ_GUTTER;
let user = self.show_sender(prev, true, info, settings);
let time = self.timestamp.show_time();
let read = match info.receipts.get(self.event.event_id()) {
Some(read) => read.iter(),
None => [].iter(),
};
let read = info.event_receipts.get(self.event.event_id()).map(|read| read.iter());

MessageFormatter { settings, cols, orig, fill, user, date, time, read }
} else if USER_GUTTER + TIME_GUTTER + MIN_MSG_LEN <= width {
let cols = MessageColumns::Three;
let fill = width - USER_GUTTER - TIME_GUTTER;
let user = self.show_sender(prev, true, info, settings);
let time = self.timestamp.show_time();
let read = [].iter();
let read = None;

MessageFormatter { settings, cols, orig, fill, user, date, time, read }
} else if USER_GUTTER + MIN_MSG_LEN <= width {
let cols = MessageColumns::Two;
let fill = width - USER_GUTTER;
let user = self.show_sender(prev, true, info, settings);
let time = None;
let read = [].iter();
let read = None;

MessageFormatter { settings, cols, orig, fill, user, date, time, read }
} else {
let cols = MessageColumns::One;
let fill = width.saturating_sub(2);
let user = self.show_sender(prev, false, info, settings);
let time = None;
let read = [].iter();
let read = None;

MessageFormatter { settings, cols, orig, fill, user, date, time, read }
}
Expand Down
3 changes: 2 additions & 1 deletion src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ pub fn mock_room() -> RoomInfo {
keys: mock_keys(),
messages: mock_messages(),

receipts: HashMap::new(),
event_receipts: HashMap::new(),
user_receipts: HashMap::new(),
read_till: None,
reactions: HashMap::new(),

Expand Down
Loading

0 comments on commit b2b47ed

Please sign in to comment.