Skip to content

Commit

Permalink
Maintain our own list of ignored users
Browse files Browse the repository at this point in the history
Do not attempt to trust or use the Matrix SDK's list of ignored users,
as it does not get updated properly in the current version of the SDK.

We now maintain our own list, which does properly get synced
when the logged-in users ignores/unignores other users on a different
client or session.
This includes correctly setting the `ignore_user_button`'s text.
  • Loading branch information
kevinaboos committed Aug 2, 2024
1 parent 3442926 commit 20da196
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 10 deletions.
11 changes: 7 additions & 4 deletions src/profile/user_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crossbeam_queue::SegQueue;
use makepad_widgets::*;
use matrix_sdk::{room::{RoomMember, RoomMemberRole}, ruma::{events::room::member::MembershipState, OwnedRoomId, OwnedUserId, UserId}};
use crate::{
shared::avatar::AvatarWidgetExt, sliding_sync::{get_client, submit_async_request, MatrixRequest}, utils
shared::avatar::AvatarWidgetExt, sliding_sync::{get_client, is_user_ignored, submit_async_request, MatrixRequest}, utils
};

thread_local! {
Expand Down Expand Up @@ -728,9 +728,12 @@ impl Widget for UserProfileSlidingPane {

let ignore_user_button = self.button(id!(ignore_user_button));
ignore_user_button.set_enabled(!is_pane_showing_current_account && info.room_member.is_some());
ignore_user_button.set_text(info.room_member.as_ref()
.and_then(|rm| rm.is_ignored().then_some("Unignore (Unblock) User"))
.unwrap_or("Ignore (Block) User")
// Unfortunately the Matrix SDK's RoomMember type does not properly track
// the `ignored` state of a user, so we have to maintain it separately.
let is_ignored = info.room_member.as_ref()
.is_some_and(|rm| is_user_ignored(rm.user_id()));
ignore_user_button.set_text(
if is_ignored { "Unignore (Unblock) User" } else { "Ignore (Block) User" }
);

self.view.draw_walk(cx, scope, walk)
Expand Down
50 changes: 44 additions & 6 deletions src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ use imbl::Vector;
use makepad_widgets::{error, log, SignalToUI};
use matrix_sdk::{
config::RequestConfig, media::MediaRequest, room::RoomMember, ruma::{
api::client::session::get_login_types::v3::LoginType, assign, events::{room::message::RoomMessageEventContent, FullStateEventContent, StateEventType}, MilliSecondsSinceUnixEpoch, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, UInt
}, sliding_sync::http::request::{AccountData, E2EE, ListFilters, ToDevice}, Client, Room, SlidingSyncList, SlidingSyncMode
api::client::session::get_login_types::v3::LoginType, assign, events::{room::message::RoomMessageEventContent, FullStateEventContent, StateEventType}, MilliSecondsSinceUnixEpoch, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, UInt, UserId
}, sliding_sync::http::request::{AccountData, ListFilters, ToDevice, E2EE}, Client, Room, SlidingSyncList, SlidingSyncMode
};
use matrix_sdk_ui::{timeline::{AnyOtherFullStateEventContent, LiveBackPaginationStatus, TimelineItem, TimelineItemContent}, Timeline};
use tokio::{
runtime::Handle,
sync::mpsc::{UnboundedSender, UnboundedReceiver}, task::JoinHandle,
};
use unicode_segmentation::UnicodeSegmentation;
use std::{cmp::{max, min}, collections::BTreeMap, ops::Range, sync::{Arc, Mutex, OnceLock}};
use std::{cmp::{max, min}, collections::{BTreeMap, BTreeSet}, ops::Range, sync::{Arc, Mutex, OnceLock}};
use url::Url;

use crate::{home::{room_screen::TimelineUpdate, rooms_list::{self, enqueue_rooms_list_update, RoomPreviewAvatar, RoomPreviewEntry, RoomsListUpdate}}, media_cache::{MediaCacheEntry, AVATAR_CACHE}, profile::user_profile::{enqueue_user_profile_update, UserProfile, UserProfileUpdate}, utils::MEDIA_THUMBNAIL_FORMAT};
Expand Down Expand Up @@ -570,6 +570,22 @@ pub fn get_client() -> Option<Client> {
CLIENT.get().cloned()
}

/// The list of users that the current user has chosen to ignore.
/// Ideally we shouldn't have to maintain this list ourselves,
/// but the Matrix SDK doesn't currently properly maintain the list of ignored users.
static IGNORED_USERS: Mutex<BTreeSet<OwnedUserId>> = Mutex::new(BTreeSet::new());

/// Returns a deep clone of the current list of ignored users.
pub fn get_ignored_users() -> BTreeSet<OwnedUserId> {
IGNORED_USERS.lock().unwrap().clone()
}

/// Returns whether the given user ID is currently being ignored.
pub fn is_user_ignored(user_id: &UserId) -> bool {
IGNORED_USERS.lock().unwrap().contains(user_id)
}


/// Returns the timeline update sender and receiver endpoints for the given room,
/// if and only if the receiver exists.
///
Expand Down Expand Up @@ -720,7 +736,7 @@ async fn async_main_loop() -> Result<()> {
Some(Err(e)) => {
error!("sync loop was stopped by client error processing: {e}");
stream_error = Some(e);
continue;
break;
}
None => {
error!("sync loop ended unexpectedly");
Expand Down Expand Up @@ -902,11 +918,33 @@ async fn async_main_loop() -> Result<()> {
}


#[allow(unused)]
async fn current_ignore_user_list(client: &Client) -> Option<BTreeSet<OwnedUserId>> {
use matrix_sdk::ruma::events::ignored_user_list::IgnoredUserListEventContent;
let ignored_users = client.account()
.account_data::<IgnoredUserListEventContent>()
.await
.ok()??
.deserialize()
.ok()?
.ignored_users
.into_keys()
.collect();

Some(ignored_users)
}


fn handle_ignore_user_list_subscriber(client: Client) {
let mut subscriber = client.subscribe_to_ignore_user_list_changes();
Handle::current().spawn(async move {
while let Some(_ignore_list) = subscriber.next().await {
log!("Received an updated ignored-user list: {_ignore_list:?}");
while let Some(ignore_list) = subscriber.next().await {
log!("Received an updated ignored-user list: {ignore_list:?}");
let ignored_users_set = ignore_list
.into_iter()
.filter_map(|u| OwnedUserId::try_from(u).ok())
.collect::<BTreeSet<_>>();
*IGNORED_USERS.lock().unwrap() = ignored_users_set;

// After successfully (un)ignoring a user, all timelines are fully cleared by the Matrix SDK.
// Therefore, we need to re-fetch all timelines for all rooms,
Expand Down

0 comments on commit 20da196

Please sign in to comment.