From 1d793de21305a4c58bd73543430e129af56d62d1 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Fri, 21 Apr 2023 13:37:03 -0400 Subject: [PATCH] Fix notification profile UI state bug and crash. --- .../profiles/NotificationProfilesRepository.kt | 17 +++++++---------- .../profiles/NotificationProfilesViewModel.kt | 4 ++-- .../conversation/ConversationViewModel.java | 7 +++---- .../ConversationListFragment.java | 2 +- .../ConversationListViewModel.kt | 11 ++++------- .../securesms/database/RxDatabaseObserver.kt | 18 +++++++++++++++++- 6 files changed, 34 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesRepository.kt index 0d53608de4..eeddaaf7ea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesRepository.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.components.settings.app.notifications.profiles import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.ObservableEmitter import io.reactivex.rxjava3.core.Single @@ -8,6 +9,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers import org.thoughtcrime.securesms.conversation.colors.AvatarColor import org.thoughtcrime.securesms.database.DatabaseObserver import org.thoughtcrime.securesms.database.NotificationProfileDatabase +import org.thoughtcrime.securesms.database.RxDatabaseObserver import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.keyvalue.SignalStore @@ -24,16 +26,11 @@ import org.thoughtcrime.securesms.util.toMillis class NotificationProfilesRepository { private val database: NotificationProfileDatabase = SignalDatabase.notificationProfiles - fun getProfiles(): Observable> { - return Observable.create { emitter: ObservableEmitter> -> - val databaseObserver: DatabaseObserver = ApplicationDependencies.getDatabaseObserver() - val profileObserver = DatabaseObserver.Observer { emitter.onNext(database.getProfiles()) } - - databaseObserver.registerNotificationProfileObserver(profileObserver) - - emitter.setCancellable { databaseObserver.unregisterObserver(profileObserver) } - emitter.onNext(database.getProfiles()) - }.subscribeOn(Schedulers.io()) + fun getProfiles(): Flowable> { + return RxDatabaseObserver + .notificationProfiles + .map { database.getProfiles() } + .subscribeOn(Schedulers.io()) } fun getProfile(profileId: Long): Observable { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesViewModel.kt index 17284814b3..785719cb32 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/notifications/profiles/NotificationProfilesViewModel.kt @@ -3,12 +3,12 @@ package org.thoughtcrime.securesms.components.settings.app.notifications.profile import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers -import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.core.Flowable import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile class NotificationProfilesViewModel(private val repository: NotificationProfilesRepository) : ViewModel() { - fun getProfiles(): Observable> { + fun getProfiles(): Flowable> { return repository.getProfiles() .observeOn(AndroidSchedulers.mainThread()) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java index 058162da0a..8776114afb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java @@ -52,7 +52,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.concurrent.TimeUnit; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.BackpressureStrategy; @@ -436,10 +435,10 @@ public class ConversationViewModel extends ViewModel { } @NonNull LiveData> getActiveNotificationProfile() { - final Observable> activeProfile = Observable.combineLatest(Observable.interval(0, 30, TimeUnit.SECONDS), notificationProfilesRepository.getProfiles(), (interval, profiles) -> profiles) - .map(profiles -> Optional.ofNullable(NotificationProfiles.getActiveProfile(profiles))); + Flowable> activeProfile = notificationProfilesRepository.getProfiles() + .map(profiles -> Optional.ofNullable(NotificationProfiles.getActiveProfile(profiles))); - return LiveDataReactiveStreams.fromPublisher(activeProfile.toFlowable(BackpressureStrategy.LATEST)); + return LiveDataReactiveStreams.fromPublisher(activeProfile); } @NonNull diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index 646f7ed055..293c0385f9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -79,6 +79,7 @@ import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import org.signal.core.util.DimensionUnit; import org.signal.core.util.Stopwatch; +import org.signal.core.util.concurrent.LifecycleDisposable; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SimpleTask; import org.signal.core.util.logging.Log; @@ -169,7 +170,6 @@ import org.thoughtcrime.securesms.util.BottomSheetUtil; import org.thoughtcrime.securesms.util.CachedInflater; import org.thoughtcrime.securesms.util.ConversationUtil; import org.thoughtcrime.securesms.util.FeatureFlags; -import org.signal.core.util.concurrent.LifecycleDisposable; import org.thoughtcrime.securesms.util.PlayStoreUtil; import org.thoughtcrime.securesms.util.ServiceUtil; import org.thoughtcrime.securesms.util.SignalLocalMetrics; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.kt index 93e867f73f..b50f0c4e6c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListViewModel.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.conversationlist import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.BackpressureStrategy import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Observable @@ -185,13 +186,9 @@ class ConversationListViewModel( megaphoneRepository.markVisible(visible.event) } - fun getNotificationProfiles(): Observable> { - return Observable - .combineLatest( - Observable.interval(0, 30, TimeUnit.SECONDS), - notificationProfilesRepository.getProfiles() - ) { _, profiles -> profiles } - .distinctUntilChanged() + fun getNotificationProfiles(): Flowable> { + return notificationProfilesRepository.getProfiles() + .observeOn(AndroidSchedulers.mainThread()) } private fun setSelection(newSelection: Collection) { 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 4537f74e36..c40c3aa1f3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RxDatabaseObserver.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RxDatabaseObserver.kt @@ -5,6 +5,7 @@ import io.reactivex.rxjava3.core.Emitter import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.schedulers.Schedulers import org.thoughtcrime.securesms.dependencies.ApplicationDependencies +import java.util.concurrent.TimeUnit /** * Provide a shared Rx interface to listen to database updates and ensure listeners @@ -13,13 +14,28 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies object RxDatabaseObserver { val conversationList: Flowable by lazy { conversationListFlowable() } + val notificationProfiles: Flowable by lazy { notificationProfilesFlowable() } private fun conversationListFlowable(): Flowable { + return databaseFlowable { listener -> + ApplicationDependencies.getDatabaseObserver().registerConversationListObserver(listener) + } + } + + @Suppress("RedundantUnitExpression") + private fun notificationProfilesFlowable(): Flowable { + return Flowable.combineLatest( + Flowable.interval(0, 30, TimeUnit.SECONDS), + databaseFlowable { ApplicationDependencies.getDatabaseObserver().registerNotificationProfileObserver(it) } + ) { _, _ -> Unit } + } + + private fun databaseFlowable(registerObserver: (RxObserver) -> Unit): Flowable { val flowable = Flowable.create( { val listener = RxObserver(it) - ApplicationDependencies.getDatabaseObserver().registerConversationListObserver(listener) + registerObserver(listener) it.setCancellable { ApplicationDependencies.getDatabaseObserver().unregisterObserver(listener) } listener.prime()