From b7bfbaa745b7f29be2164bc40b81653cce62810b Mon Sep 17 00:00:00 2001 From: Michelle Tang Date: Wed, 2 Sep 2026 12:49:18 -0400 Subject: [PATCH] Sync blocked users UI. --- .../securesms/blocked/BlockedUsersViewModel.java | 14 +++++++++++--- .../securesms/database/DatabaseObserver.java | 12 ++++++++++++ .../securesms/database/RecipientTable.kt | 2 ++ .../securesms/database/RxDatabaseObserver.kt | 10 ++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/blocked/BlockedUsersViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/blocked/BlockedUsersViewModel.java index baf4cf6edb..d864c3e030 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/blocked/BlockedUsersViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/blocked/BlockedUsersViewModel.java @@ -5,6 +5,7 @@ import androidx.annotation.Nullable; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; +import org.thoughtcrime.securesms.database.RxDatabaseObserver; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; @@ -13,6 +14,7 @@ import java.util.Objects; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.subjects.BehaviorSubject; import io.reactivex.rxjava3.subjects.PublishSubject; import io.reactivex.rxjava3.subjects.Subject; @@ -20,15 +22,21 @@ import io.reactivex.rxjava3.subjects.Subject; public class BlockedUsersViewModel extends ViewModel { private final BlockedUsersRepository repository; - private final Subject> recipients = BehaviorSubject.create(); - private final Subject events = PublishSubject.create(); + private final Subject> recipients = BehaviorSubject.create(); + private final Subject events = PublishSubject.create(); + private final CompositeDisposable disposables = new CompositeDisposable(); private BlockedUsersViewModel(@NonNull BlockedUsersRepository repository) { this.repository = repository; - loadRecipients(); + disposables.add(RxDatabaseObserver.getBlockedUsers().subscribe(unused -> loadRecipients())); } + @Override + protected void onCleared() { + disposables.clear(); + } + public Observable> getRecipients() { return recipients.observeOn(AndroidSchedulers.mainThread()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java index d5ca55cea6..61fd138a61 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseObserver.java @@ -49,6 +49,7 @@ public class DatabaseObserver { private static final String KEY_IN_APP_PAYMENTS = "InAppPayments"; private static final String KEY_CHAT_FOLDER = "ChatFolder"; private static final String KEY_STARRED_MESSAGES = "StarredMessages"; + private static final String KEY_BLOCKED_USERS = "BlockedUsers"; private final Executor executor; @@ -73,6 +74,7 @@ public class DatabaseObserver { private final Set inAppPaymentObservers; private final Set chatFolderObservers; private final Set starredMessageObservers; + private final Set blockedUsersObservers; public DatabaseObserver() { this.executor = new SerialExecutor(SignalExecutors.BOUNDED); @@ -97,6 +99,7 @@ public class DatabaseObserver { this.inAppPaymentObservers = new HashSet<>(); this.chatFolderObservers = new HashSet<>(); this.starredMessageObservers = new HashSet<>(); + this.blockedUsersObservers = new HashSet<>(); } public void registerConversationListObserver(@NonNull Observer listener) { @@ -220,6 +223,10 @@ public class DatabaseObserver { executor.execute(() -> starredMessageObservers.add(observer)); } + public void registerBlockedUsersObserver(@NonNull Observer observer) { + executor.execute(() -> blockedUsersObservers.add(observer)); + } + public void unregisterObserver(@NonNull Observer listener) { executor.execute(() -> { conversationListObservers.remove(listener); @@ -239,6 +246,7 @@ public class DatabaseObserver { unregisterMapped(callLinkObservers, listener); chatFolderObservers.remove(listener); starredMessageObservers.remove(listener); + blockedUsersObservers.remove(listener); }); } @@ -411,6 +419,10 @@ public class DatabaseObserver { runPostSuccessfulTransaction(KEY_STARRED_MESSAGES, () -> notifySet(starredMessageObservers)); } + public void notifyBlockedUsersObservers() { + runPostSuccessfulTransaction(KEY_BLOCKED_USERS, () -> notifySet(blockedUsersObservers)); + } + private void runPostSuccessfulTransaction(@NonNull String dedupeKey, @NonNull Runnable runnable) { SignalDatabase.runPostSuccessfulTransaction(dedupeKey, () -> { executor.execute(runnable); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt index e29cd47de9..0412fcc89e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientTable.kt @@ -1504,6 +1504,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da if (update(id, values)) { rotateStorageId(id) AppDependencies.databaseObserver.notifyRecipientChanged(id) + AppDependencies.databaseObserver.notifyBlockedUsersObservers() } } @@ -4054,6 +4055,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da } } + AppDependencies.databaseObserver.notifyBlockedUsersObservers() AppDependencies.recipientCache.clear() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RxDatabaseObserver.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RxDatabaseObserver.kt index 80b63bc13d..26d6d1a5de 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RxDatabaseObserver.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RxDatabaseObserver.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.database +import com.squareup.wire.internal.JvmStatic import io.reactivex.rxjava3.core.BackpressureStrategy import io.reactivex.rxjava3.core.Emitter import io.reactivex.rxjava3.core.Flowable @@ -18,6 +19,9 @@ object RxDatabaseObserver { val chatFolders: Flowable by lazy { chatFoldersFlowable() } val starredMessages: Flowable by lazy { starredMessagesFlowable() } + @JvmStatic + val blockedUsers: Flowable by lazy { blockedUsersFlowable() } + private fun conversationListFlowable(): Flowable { return databaseFlowable { listener -> AppDependencies.databaseObserver.registerConversationListObserver(listener) @@ -50,6 +54,12 @@ object RxDatabaseObserver { } } + private fun blockedUsersFlowable(): Flowable { + return databaseFlowable { listener -> + AppDependencies.databaseObserver.registerBlockedUsersObserver(listener) + } + } + private fun databaseFlowable(registerObserver: (RxObserver) -> Unit): Flowable { val flowable = Flowable.create( {