@@ -1254,9 +1254,10 @@ impl BaseClient {
1254
1254
1255
1255
{
1256
1256
let _sync_lock = self . sync_lock ( ) . lock ( ) . await ;
1257
+ let prev_ignored_user_list = self . load_previous_ignored_user_list ( ) . await ;
1257
1258
self . store . save_changes ( & changes) . await ?;
1258
1259
* self . store . sync_token . write ( ) . await = Some ( response. next_batch . clone ( ) ) ;
1259
- self . apply_changes ( & changes, room_info_notable_updates) ;
1260
+ self . apply_changes ( & changes, room_info_notable_updates, prev_ignored_user_list ) ;
1260
1261
}
1261
1262
1262
1263
// Now that all the rooms information have been saved, update the display name
@@ -1286,10 +1287,17 @@ impl BaseClient {
1286
1287
Ok ( response)
1287
1288
}
1288
1289
1290
+ pub ( crate ) async fn load_previous_ignored_user_list (
1291
+ & self ,
1292
+ ) -> Option < Raw < IgnoredUserListEvent > > {
1293
+ self . store ( ) . get_account_data_event_static ( ) . await . ok ( ) . flatten ( )
1294
+ }
1295
+
1289
1296
pub ( crate ) fn apply_changes (
1290
1297
& self ,
1291
1298
changes : & StateChanges ,
1292
1299
room_info_notable_updates : BTreeMap < OwnedRoomId , RoomInfoNotableUpdateReasons > ,
1300
+ prev_ignored_user_list : Option < Raw < IgnoredUserListEvent > > ,
1293
1301
) {
1294
1302
if let Some ( event) = changes. account_data . get ( & GlobalAccountDataEventType :: IgnoredUserList )
1295
1303
{
@@ -1298,8 +1306,27 @@ impl BaseClient {
1298
1306
let user_ids: Vec < String > =
1299
1307
event. content . ignored_users . keys ( ) . map ( |id| id. to_string ( ) ) . collect ( ) ;
1300
1308
1301
- self . ignore_user_list_changes . set ( user_ids) ;
1309
+ // Try to only trigger the observable if the ignored user list has changed,
1310
+ // from the previous time we've seen it. If we couldn't load the previous event
1311
+ // for any reason, always trigger.
1312
+ if let Some ( prev_user_ids) =
1313
+ prev_ignored_user_list. and_then ( |raw| raw. deserialize ( ) . ok ( ) ) . map ( |event| {
1314
+ event
1315
+ . content
1316
+ . ignored_users
1317
+ . keys ( )
1318
+ . map ( |id| id. to_string ( ) )
1319
+ . collect :: < Vec < _ > > ( )
1320
+ } )
1321
+ {
1322
+ if user_ids != prev_user_ids {
1323
+ self . ignore_user_list_changes . set ( user_ids) ;
1324
+ }
1325
+ } else {
1326
+ self . ignore_user_list_changes . set ( user_ids) ;
1327
+ }
1302
1328
}
1329
+
1303
1330
Err ( error) => {
1304
1331
error ! ( "Failed to deserialize ignored user list event: {error}" )
1305
1332
}
@@ -1419,8 +1446,9 @@ impl BaseClient {
1419
1446
room_info. mark_members_synced ( ) ;
1420
1447
changes. add_room ( room_info) ;
1421
1448
1449
+ let prev_ignored_user_list = self . load_previous_ignored_user_list ( ) . await ;
1422
1450
self . store . save_changes ( & changes) . await ?;
1423
- self . apply_changes ( & changes, Default :: default ( ) ) ;
1451
+ self . apply_changes ( & changes, Default :: default ( ) , prev_ignored_user_list ) ;
1424
1452
1425
1453
let _ = room. room_member_updates_sender . send ( RoomMembersUpdate :: FullReload ) ;
1426
1454
@@ -1758,9 +1786,11 @@ fn handle_room_member_event_for_profiles(
1758
1786
1759
1787
#[ cfg( test) ]
1760
1788
mod tests {
1789
+ use assert_matches2:: assert_let;
1790
+ use futures_util:: FutureExt as _;
1761
1791
use matrix_sdk_test:: {
1762
1792
async_test, event_factory:: EventFactory , ruma_response_from_json, InvitedRoomBuilder ,
1763
- LeftRoomBuilder , StateTestEvent , StrippedStateTestEvent , SyncResponseBuilder ,
1793
+ LeftRoomBuilder , StateTestEvent , StrippedStateTestEvent , SyncResponseBuilder , BOB ,
1764
1794
} ;
1765
1795
use ruma:: {
1766
1796
api:: client as api, event_id, events:: room:: member:: MembershipState , room_id, serde:: Raw ,
@@ -2152,4 +2182,75 @@ mod tests {
2152
2182
assert_eq ! ( member. display_name( ) . unwrap( ) , "Invited Alice" ) ;
2153
2183
assert_eq ! ( member. avatar_url( ) . unwrap( ) . to_string( ) , "mxc://localhost/fewjilfewjil42" ) ;
2154
2184
}
2185
+
2186
+ #[ async_test]
2187
+ async fn test_ignored_user_list_changes ( ) {
2188
+ let user_id = user_id ! ( "@alice:example.org" ) ;
2189
+ let client = BaseClient :: with_store_config ( StoreConfig :: new (
2190
+ "cross-process-store-locks-holder-name" . to_owned ( ) ,
2191
+ ) ) ;
2192
+ client
2193
+ . set_session_meta (
2194
+ SessionMeta { user_id : user_id. to_owned ( ) , device_id : "FOOBAR" . into ( ) } ,
2195
+ #[ cfg( feature = "e2e-encryption" ) ]
2196
+ None ,
2197
+ )
2198
+ . await
2199
+ . unwrap ( ) ;
2200
+
2201
+ let mut subscriber = client. subscribe_to_ignore_user_list_changes ( ) ;
2202
+ assert ! ( subscriber. next( ) . now_or_never( ) . is_none( ) ) ;
2203
+
2204
+ let mut sync_builder = SyncResponseBuilder :: new ( ) ;
2205
+ let response = sync_builder
2206
+ . add_global_account_data_event ( matrix_sdk_test:: GlobalAccountDataTestEvent :: Custom (
2207
+ json ! ( {
2208
+ "content" : {
2209
+ "ignored_users" : {
2210
+ * BOB : { }
2211
+ }
2212
+ } ,
2213
+ "type" : "m.ignored_user_list" ,
2214
+ } ) ,
2215
+ ) )
2216
+ . build_sync_response ( ) ;
2217
+ client. receive_sync_response ( response) . await . unwrap ( ) ;
2218
+
2219
+ assert_let ! ( Some ( ignored) = subscriber. next( ) . await ) ;
2220
+ assert_eq ! ( ignored, [ BOB . to_string( ) ] ) ;
2221
+
2222
+ // Receive the same response.
2223
+ let response = sync_builder
2224
+ . add_global_account_data_event ( matrix_sdk_test:: GlobalAccountDataTestEvent :: Custom (
2225
+ json ! ( {
2226
+ "content" : {
2227
+ "ignored_users" : {
2228
+ * BOB : { }
2229
+ }
2230
+ } ,
2231
+ "type" : "m.ignored_user_list" ,
2232
+ } ) ,
2233
+ ) )
2234
+ . build_sync_response ( ) ;
2235
+ client. receive_sync_response ( response) . await . unwrap ( ) ;
2236
+
2237
+ // No changes in the ignored list.
2238
+ assert ! ( subscriber. next( ) . now_or_never( ) . is_none( ) ) ;
2239
+
2240
+ // Now remove Bob from the ignored list.
2241
+ let response = sync_builder
2242
+ . add_global_account_data_event ( matrix_sdk_test:: GlobalAccountDataTestEvent :: Custom (
2243
+ json ! ( {
2244
+ "content" : {
2245
+ "ignored_users" : { }
2246
+ } ,
2247
+ "type" : "m.ignored_user_list" ,
2248
+ } ) ,
2249
+ ) )
2250
+ . build_sync_response ( ) ;
2251
+ client. receive_sync_response ( response) . await . unwrap ( ) ;
2252
+
2253
+ assert_let ! ( Some ( ignored) = subscriber. next( ) . await ) ;
2254
+ assert ! ( ignored. is_empty( ) ) ;
2255
+ }
2155
2256
}
0 commit comments