use ruma::{
RoomId,
events::{AnyRoomAccountDataEvent, marked_unread::MarkedUnreadEventContent},
serde::Raw,
};
use tracing::{instrument, warn};
use super::super::{Context, RoomInfoNotableUpdates};
use crate::{
RoomInfo, RoomInfoNotableUpdateReasons, StateChanges, room::AccountDataSource,
store::BaseStateStore,
};
#[instrument(skip_all, fields(?room_id))]
pub fn for_room(
context: &mut Context,
room_id: &RoomId,
events: &[Raw<AnyRoomAccountDataEvent>],
state_store: &BaseStateStore,
) {
for raw_event in events {
match raw_event.deserialize() {
Ok(event) => {
context.state_changes.add_room_account_data(
room_id,
event.clone(),
raw_event.clone(),
);
match event {
AnyRoomAccountDataEvent::MarkedUnread(event) => {
on_room_info(
room_id,
&mut context.state_changes,
state_store,
|room_info| {
on_unread_marker(
room_id,
&event.content,
AccountDataSource::Stable,
room_info,
&mut context.room_info_notable_updates,
);
},
);
}
AnyRoomAccountDataEvent::UnstableMarkedUnread(event) => {
on_room_info(
room_id,
&mut context.state_changes,
state_store,
|room_info| {
on_unread_marker(
room_id,
&event.content.0,
AccountDataSource::Unstable,
room_info,
&mut context.room_info_notable_updates,
);
},
);
}
AnyRoomAccountDataEvent::Tag(event) => {
on_room_info(
room_id,
&mut context.state_changes,
state_store,
|room_info| {
room_info.base_info.handle_notable_tags(&event.content.tags);
},
);
}
_ => {}
}
}
Err(err) => {
warn!("unable to deserialize account data event: {err}");
}
}
}
}
fn on_room_info<F>(
room_id: &RoomId,
state_changes: &mut StateChanges,
state_store: &BaseStateStore,
mut on_room_info: F,
) where
F: FnMut(&mut RoomInfo),
{
if let Some(room_info) = state_changes.room_infos.get_mut(room_id) {
on_room_info(room_info);
}
else if let Some(room) = state_store.room(room_id) {
let mut room_info = room.clone_info();
on_room_info(&mut room_info);
state_changes.add_room(room_info);
}
}
fn on_unread_marker(
room_id: &RoomId,
content: &MarkedUnreadEventContent,
source: AccountDataSource,
room_info: &mut RoomInfo,
room_info_notable_updates: &mut RoomInfoNotableUpdates,
) {
if room_info.base_info.is_marked_unread_source == AccountDataSource::Stable
&& source != AccountDataSource::Stable
{
return;
}
if room_info.base_info.is_marked_unread != content.unread {
room_info_notable_updates
.entry(room_id.to_owned())
.or_default()
.insert(RoomInfoNotableUpdateReasons::UNREAD_MARKER);
}
room_info.base_info.is_marked_unread = content.unread;
room_info.base_info.is_marked_unread_source = source;
}