matrix_sdk_base/response_processors/
changes.rs1use eyeball::SharedObservable;
16use ruma::{
17 events::{ignored_user_list::IgnoredUserListEvent, GlobalAccountDataEventType},
18 serde::Raw,
19};
20use tracing::{error, instrument, trace};
21
22use super::Context;
23use crate::{
24 store::{BaseStateStore, StateStoreExt as _},
25 Result,
26};
27
28#[instrument(skip_all)]
31pub async fn save_only(context: Context, state_store: &BaseStateStore) -> Result<()> {
32 save_changes(&context, state_store, None).await?;
33 broadcast_room_info_notable_updates(&context, state_store);
34
35 Ok(())
36}
37
38#[instrument(skip_all)]
41pub async fn save_and_apply(
42 context: Context,
43 state_store: &BaseStateStore,
44 ignore_user_list_changes: &SharedObservable<Vec<String>>,
45 sync_token: Option<String>,
46) -> Result<()> {
47 trace!("ready to submit changes to store");
48
49 let previous_ignored_user_list =
50 state_store.get_account_data_event_static().await.ok().flatten();
51
52 save_changes(&context, state_store, sync_token).await?;
53 apply_changes(&context, ignore_user_list_changes, previous_ignored_user_list);
54 broadcast_room_info_notable_updates(&context, state_store);
55
56 trace!("applied changes");
57
58 Ok(())
59}
60
61async fn save_changes(
62 context: &Context,
63 state_store: &BaseStateStore,
64 sync_token: Option<String>,
65) -> Result<()> {
66 state_store.save_changes(&context.state_changes).await?;
67
68 if let Some(sync_token) = sync_token {
69 *state_store.sync_token.write().await = Some(sync_token);
70 }
71
72 Ok(())
73}
74
75fn apply_changes(
76 context: &Context,
77 ignore_user_list_changes: &SharedObservable<Vec<String>>,
78 previous_ignored_user_list: Option<Raw<IgnoredUserListEvent>>,
79) {
80 if let Some(event) =
81 context.state_changes.account_data.get(&GlobalAccountDataEventType::IgnoredUserList)
82 {
83 match event.deserialize_as::<IgnoredUserListEvent>() {
84 Ok(event) => {
85 let user_ids: Vec<String> =
86 event.content.ignored_users.keys().map(|id| id.to_string()).collect();
87
88 if let Some(prev_user_ids) =
92 previous_ignored_user_list.and_then(|raw| raw.deserialize().ok()).map(|event| {
93 event
94 .content
95 .ignored_users
96 .keys()
97 .map(|id| id.to_string())
98 .collect::<Vec<_>>()
99 })
100 {
101 if user_ids != prev_user_ids {
102 ignore_user_list_changes.set(user_ids);
103 }
104 } else {
105 ignore_user_list_changes.set(user_ids);
106 }
107 }
108
109 Err(error) => {
110 error!("Failed to deserialize ignored user list event: {error}")
111 }
112 }
113 }
114}
115
116fn broadcast_room_info_notable_updates(context: &Context, state_store: &BaseStateStore) {
117 for (room_id, room_info) in &context.state_changes.room_infos {
118 if let Some(room) = state_store.room(room_id) {
119 let room_info_notable_update_reasons =
120 context.room_info_notable_updates.get(room_id).copied().unwrap_or_default();
121
122 room.set_room_info(room_info.clone(), room_info_notable_update_reasons)
123 }
124 }
125}