From ef597cc67a57d2310183009e3e789ea01266395c Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 3 Jul 2019 14:47:33 +0200 Subject: [PATCH 1/4] RoomSummary: set unreadNotification to 0 by default --- .../internal/session/room/RoomSummaryUpdater.kt | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 766e13fa83..76f2d1516c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -61,9 +61,8 @@ internal class RoomSummaryUpdater @Inject constructor(private val credentials: C membership: Membership? = null, roomSummary: RoomSyncSummary? = null, unreadNotifications: RoomSyncUnreadNotifications? = null) { - val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() - ?: realm.createObject(roomId) + ?: realm.createObject(roomId) if (roomSummary != null) { if (roomSummary.heroes.isNotEmpty()) { @@ -77,12 +76,9 @@ internal class RoomSummaryUpdater @Inject constructor(private val credentials: C roomSummaryEntity.joinedMembersCount = roomSummary.joinedMembersCount } } - if (unreadNotifications?.highlightCount != null) { - roomSummaryEntity.highlightCount = unreadNotifications.highlightCount - } - if (unreadNotifications?.notificationCount != null) { - roomSummaryEntity.notificationCount = unreadNotifications.notificationCount - } + roomSummaryEntity.highlightCount = unreadNotifications?.highlightCount ?: 0 + roomSummaryEntity.notificationCount = unreadNotifications?.notificationCount ?:0 + if (membership != null) { roomSummaryEntity.membership = membership } From eefd09d0227c61a1f89b0b9d5dd00bef43112c49 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 3 Jul 2019 14:48:03 +0200 Subject: [PATCH 2/4] Dagger: don't create MatrixCoroutineDispatchers multiple time!! --- .../matrix/android/internal/di/MatrixModule.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt index 875dd5f7b4..260c80f14b 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MatrixModule.kt @@ -23,6 +23,7 @@ import android.os.HandlerThread import dagger.Module import dagger.Provides import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers +import im.vector.matrix.android.internal.util.createBackgroundHandler import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.android.asCoroutineDispatcher import org.matrix.olm.OlmManager @@ -32,15 +33,12 @@ internal object MatrixModule { @JvmStatic @Provides + @MatrixScope fun providesMatrixCoroutineDispatchers(): MatrixCoroutineDispatchers { - val THREAD_CRYPTO_NAME = "Crypto_Thread" - val handlerThread = HandlerThread(THREAD_CRYPTO_NAME) - handlerThread.start() - return MatrixCoroutineDispatchers(io = Dispatchers.IO, - computation = Dispatchers.IO, - main = Dispatchers.Main, - crypto = Handler(handlerThread.looper).asCoroutineDispatcher("crypto") + computation = Dispatchers.IO, + main = Dispatchers.Main, + crypto = createBackgroundHandler("Crypto_Thread").asCoroutineDispatcher() ) } From 93ce0cc5e95e0f39fe8e9888ab0503f99345ec7c Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 3 Jul 2019 14:48:45 +0200 Subject: [PATCH 3/4] Realm: avoid using monarchy thread for custom work --- .../database/RealmLiveEntityObserver.kt | 21 +++++++++++--- .../internal/session/DefaultSession.kt | 27 +++++++---------- .../session/group/GroupSummaryUpdater.kt | 4 ++- .../room/EventRelationsAggregationUpdater.kt | 6 ++-- .../session/room/prune/EventsPruner.kt | 6 ++-- .../session/room/timeline/DefaultTimeline.kt | 11 +++---- .../session/user/UserEntityUpdater.kt | 6 ++-- .../matrix/android/internal/util/Handler.kt | 29 +++++++++++++++++++ 8 files changed, 75 insertions(+), 35 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/Handler.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveEntityObserver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveEntityObserver.kt index 3f3c9bde78..8be0e697fb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveEntityObserver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveEntityObserver.kt @@ -17,7 +17,10 @@ package im.vector.matrix.android.internal.database import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.internal.util.createBackgroundHandler import io.realm.OrderedCollectionChangeSet +import io.realm.Realm +import io.realm.RealmConfiguration import io.realm.RealmObject import io.realm.RealmResults import java.util.concurrent.atomic.AtomicBoolean @@ -29,17 +32,24 @@ internal interface LiveEntityObserver { fun isStarted(): Boolean } -internal abstract class RealmLiveEntityObserver(protected val monarchy: Monarchy) +internal abstract class RealmLiveEntityObserver(protected val realmConfiguration: RealmConfiguration) : LiveEntityObserver { + private companion object { + val BACKGROUND_HANDLER = createBackgroundHandler("LIVE_ENTITY_BACKGROUND") + } + protected abstract val query: Monarchy.Query private val isStarted = AtomicBoolean(false) + private val backgroundRealm = AtomicReference() private lateinit var results: AtomicReference> override fun start() { if (isStarted.compareAndSet(false, true)) { - monarchy.postToMonarchyThread { - val queryResults = query.createQuery(it).findAll() + BACKGROUND_HANDLER.post { + val realm = Realm.getInstance(realmConfiguration) + backgroundRealm.set(realm) + val queryResults = query.createQuery(realm).findAll() queryResults.addChangeListener { t, changeSet -> onChanged(t, changeSet) } @@ -50,8 +60,11 @@ internal abstract class RealmLiveEntityObserver(protected val m override fun dispose() { if (isStarted.compareAndSet(true, false)) { - monarchy.postToMonarchyThread { + BACKGROUND_HANDLER.post { results.getAndSet(null).removeAllChangeListeners() + backgroundRealm.getAndSet(null).also { + it.close() + } } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index e98b459a49..323118536c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -50,7 +50,6 @@ import javax.inject.Inject internal class DefaultSession @Inject constructor(override val sessionParams: SessionParams, private val context: Context, private val liveEntityObservers: Set<@JvmSuppressWildcards LiveEntityObserver>, - private val monarchy: Monarchy, private val sessionListeners: SessionListeners, private val roomService: RoomService, private val roomDirectoryService: RoomDirectoryService, @@ -66,16 +65,16 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se private val contentUrlResolver: ContentUrlResolver, private val contentUploadProgressTracker: ContentUploadStateTracker) : Session, - RoomService by roomService, - RoomDirectoryService by roomDirectoryService, - GroupService by groupService, - UserService by userService, - CryptoService by cryptoService, - CacheService by cacheService, - SignOutService by signOutService, - FilterService by filterService, - PushRuleService by pushRuleService, - PushersService by pushersService { + RoomService by roomService, + RoomDirectoryService by roomDirectoryService, + GroupService by groupService, + UserService by userService, + CryptoService by cryptoService, + CacheService by cacheService, + SignOutService by signOutService, + FilterService by filterService, + PushRuleService by pushRuleService, + PushersService by pushersService { private var isOpen = false @@ -85,9 +84,6 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se assertMainThread() assert(!isOpen) isOpen = true - if (!monarchy.isMonarchyThreadOpen) { - monarchy.openManually() - } liveEntityObservers.forEach { it.start() } } @@ -123,9 +119,6 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se stopSync() liveEntityObservers.forEach { it.dispose() } cryptoService.close() - if (monarchy.isMonarchyThreadOpen) { - monarchy.closeManually() - } isOpen = false } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt index 43bad2bcf0..a2ca850388 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/group/GroupSummaryUpdater.kt @@ -27,14 +27,16 @@ import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.model.GroupEntity import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.worker.WorkerParamsFactory +import io.realm.RealmConfiguration import javax.inject.Inject private const val GET_GROUP_DATA_WORKER = "GET_GROUP_DATA_WORKER" internal class GroupSummaryUpdater @Inject constructor(private val context: Context, private val credentials: Credentials, - monarchy: Monarchy) : RealmLiveEntityObserver(monarchy) { + @SessionDatabase realmConfiguration: RealmConfiguration) : RealmLiveEntityObserver(realmConfiguration) { override val query = Monarchy.Query { GroupEntity.where(it) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt index 233188877b..76fea187b3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/EventRelationsAggregationUpdater.kt @@ -22,8 +22,10 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.types +import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import io.realm.RealmConfiguration import timber.log.Timber import javax.inject.Inject @@ -33,11 +35,11 @@ import javax.inject.Inject * The summaries can then be extracted and added (as a decoration) to a TimelineEvent for final display. */ -internal class EventRelationsAggregationUpdater @Inject constructor(monarchy: Monarchy, +internal class EventRelationsAggregationUpdater @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration, private val credentials: Credentials, private val task: EventRelationsAggregationTask, private val taskExecutor: TaskExecutor) : - RealmLiveEntityObserver(monarchy) { + RealmLiveEntityObserver(realmConfiguration) { override val query = Monarchy.Query { EventEntity.types(it, listOf( diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt index 456cbde7ed..53b72fa436 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/EventsPruner.kt @@ -23,9 +23,11 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import io.realm.RealmConfiguration import timber.log.Timber import javax.inject.Inject @@ -33,11 +35,11 @@ import javax.inject.Inject * Listens to the database for the insertion of any redaction event. * As it will actually delete the content, it should be called last in the list of listener. */ -internal class EventsPruner @Inject constructor(monarchy: Monarchy, +internal class EventsPruner @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration, private val credentials: Credentials, private val pruneEventTask: PruneEventTask, private val taskExecutor: TaskExecutor) : - RealmLiveEntityObserver(monarchy) { + RealmLiveEntityObserver(realmConfiguration) { override val query = Monarchy.Query { EventEntity.where(it, type = EventType.REDACTION) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt index 34de3708da..8f5c62cdcb 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/DefaultTimeline.kt @@ -16,9 +16,6 @@ package im.vector.matrix.android.internal.session.room.timeline -import android.os.Handler -import android.os.HandlerThread -import android.os.Looper import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.session.crypto.CryptoService import im.vector.matrix.android.api.session.events.model.EventType @@ -43,6 +40,8 @@ import im.vector.matrix.android.internal.database.query.whereInRoom import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.Debouncer +import im.vector.matrix.android.internal.util.createBackgroundHandler +import im.vector.matrix.android.internal.util.createUIHandler import io.realm.OrderedCollectionChangeSet import io.realm.OrderedRealmCollectionChangeListener import io.realm.Realm @@ -75,9 +74,7 @@ internal class DefaultTimeline( ) : Timeline { private companion object { - val BACKGROUND_HANDLER = Handler( - HandlerThread("TIMELINE_DB_THREAD").apply { start() }.looper - ) + val BACKGROUND_HANDLER = createBackgroundHandler("TIMELINE_DB_THREAD") } override var listener: Timeline.Listener? = null @@ -90,7 +87,7 @@ internal class DefaultTimeline( private val isStarted = AtomicBoolean(false) private val isReady = AtomicBoolean(false) - private val mainHandler = Handler(Looper.getMainLooper()) + private val mainHandler = createUIHandler() private val backgroundRealm = AtomicReference() private val cancelableBag = CancelableBag() private val debouncer = Debouncer(mainHandler) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt index b1935e41b1..bfb9786d52 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt @@ -22,17 +22,19 @@ import im.vector.matrix.android.internal.database.RealmLiveEntityObserver import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntityFields import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.configureWith +import io.realm.RealmConfiguration import io.realm.Sort import javax.inject.Inject -internal class UserEntityUpdater @Inject constructor(monarchy: Monarchy, +internal class UserEntityUpdater @Inject constructor(@SessionDatabase realmConfiguration: RealmConfiguration, private val updateUserTask: UpdateUserTask, private val taskExecutor: TaskExecutor) - : RealmLiveEntityObserver(monarchy) { + : RealmLiveEntityObserver(realmConfiguration) { override val query = Monarchy.Query { EventEntity diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/Handler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/Handler.kt new file mode 100644 index 0000000000..51fdbfe227 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/Handler.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.matrix.android.internal.util + +import android.os.Handler +import android.os.HandlerThread +import android.os.Looper + +fun createBackgroundHandler(name: String): Handler = Handler( + HandlerThread(name).apply { start() }.looper +) + +fun createUIHandler(): Handler = Handler( + Looper.getMainLooper() +) \ No newline at end of file From 480f14902d08c6881f527931c82164fd95f1b4ca Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 3 Jul 2019 18:28:56 +0200 Subject: [PATCH 4/4] Rx: observe on computation by default --- .../main/java/im/vector/matrix/rx/RxRoom.kt | 9 ++--- .../java/im/vector/matrix/rx/RxSession.kt | 9 ++--- .../im/vector/riotx/core/utils/RxStore.kt | 3 +- .../features/home/HomeDetailViewModel.kt | 2 ++ .../home/HomeRoomListObservableStore.kt | 13 ++----- .../room/list/RoomListDisplayModeFilter.kt | 3 ++ .../home/room/list/RoomListViewModel.kt | 35 ++++++++++--------- 7 files changed, 38 insertions(+), 36 deletions(-) diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index e209a0ca3b..dbb94a91e2 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -21,23 +21,24 @@ import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import io.reactivex.Observable +import io.reactivex.schedulers.Schedulers class RxRoom(private val room: Room) { fun liveRoomSummary(fetchLastEvent: Boolean): Observable { - return room.liveRoomSummary(fetchLastEvent).asObservable() + return room.liveRoomSummary(fetchLastEvent).asObservable().observeOn(Schedulers.computation()) } fun liveRoomMemberIds(): Observable> { - return room.getRoomMemberIdsLive().asObservable() + return room.getRoomMemberIdsLive().asObservable().observeOn(Schedulers.computation()) } fun liveAnnotationSummary(eventId: String): Observable { - return room.getEventSummaryLive(eventId).asObservable() + return room.getEventSummaryLive(eventId).asObservable().observeOn(Schedulers.computation()) } fun liveTimelineEvent(eventId: String): Observable { - return room.liveTimeLineEvent(eventId).asObservable() + return room.liveTimeLineEvent(eventId).asObservable().observeOn(Schedulers.computation()) } } diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 6490083932..5fd76f0b50 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -22,23 +22,24 @@ import im.vector.matrix.android.api.session.pushers.Pusher import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.sync.SyncState import io.reactivex.Observable +import io.reactivex.schedulers.Schedulers class RxSession(private val session: Session) { fun liveRoomSummaries(fetchLastEvents: Boolean): Observable> { - return session.liveRoomSummaries(fetchLastEvents).asObservable() + return session.liveRoomSummaries(fetchLastEvents).asObservable().observeOn(Schedulers.computation()) } fun liveGroupSummaries(): Observable> { - return session.liveGroupSummaries().asObservable() + return session.liveGroupSummaries().asObservable().observeOn(Schedulers.computation()) } fun liveSyncState(): Observable { - return session.syncState().asObservable() + return session.syncState().asObservable().observeOn(Schedulers.computation()) } fun livePushers(): Observable> { - return session.livePushers().asObservable() + return session.livePushers().asObservable().observeOn(Schedulers.computation()) } } diff --git a/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt b/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt index bf35997369..89780b2463 100644 --- a/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt +++ b/vector/src/main/java/im/vector/riotx/core/utils/RxStore.kt @@ -18,6 +18,7 @@ package im.vector.riotx.core.utils import com.jakewharton.rxrelay2.BehaviorRelay import io.reactivex.Observable +import io.reactivex.schedulers.Schedulers open class RxStore(defaultValue: T? = null) { @@ -28,7 +29,7 @@ open class RxStore(defaultValue: T? = null) { } fun observe(): Observable { - return storeSubject.hide().distinctUntilChanged() + return storeSubject.hide().observeOn(Schedulers.computation()) } fun post(value: T) { diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt index 2b5a993ed2..7f0b610d65 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt @@ -24,6 +24,7 @@ import com.squareup.inject.assisted.AssistedInject import im.vector.matrix.android.api.session.Session import im.vector.matrix.rx.rx import im.vector.riotx.core.platform.VectorViewModel +import io.reactivex.schedulers.Schedulers /** * View model used to update the home bottom bar notification counts @@ -68,6 +69,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho private fun observeRoomSummaries() { homeRoomListStore .observe() + .observeOn(Schedulers.computation()) .subscribe { list -> list.let { summaries -> val peopleNotifications = summaries diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt index f1f7e551d3..4e0b5b70ed 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeRoomListObservableStore.kt @@ -21,18 +21,9 @@ import im.vector.riotx.core.utils.RxStore import im.vector.riotx.features.home.room.list.RoomListDisplayModeFilter import im.vector.riotx.features.home.room.list.RoomListFragment import io.reactivex.Observable +import io.reactivex.schedulers.Schedulers import javax.inject.Inject import javax.inject.Singleton @Singleton -class HomeRoomListObservableStore @Inject constructor() : RxStore>() { - - fun observeFilteredBy(displayMode: RoomListFragment.DisplayMode): Observable> { - return observe() - .flatMapSingle { - Observable.fromIterable(it).filter(RoomListDisplayModeFilter(displayMode)).toList() - } - } - - -} \ No newline at end of file +class HomeRoomListObservableStore @Inject constructor() : RxStore>() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListDisplayModeFilter.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListDisplayModeFilter.kt index 96fad483b4..78bad61bc8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListDisplayModeFilter.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListDisplayModeFilter.kt @@ -23,6 +23,9 @@ import io.reactivex.functions.Predicate class RoomListDisplayModeFilter(private val displayMode: RoomListFragment.DisplayMode) : Predicate { override fun test(roomSummary: RoomSummary): Boolean { + if (roomSummary.membership.isLeft()) { + return false + } return when (displayMode) { RoomListFragment.DisplayMode.HOME -> roomSummary.notificationCount > 0 || roomSummary.membership == Membership.INVITE RoomListFragment.DisplayMode.PEOPLE -> roomSummary.isDirect && roomSummary.membership == Membership.JOIN diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt index 6b814bb94e..a42e129523 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewModel.kt @@ -31,6 +31,7 @@ import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.utils.LiveEvent import im.vector.riotx.features.home.HomeRoomListObservableStore +import io.reactivex.schedulers.Schedulers import timber.log.Timber class RoomListViewModel @AssistedInject constructor(@Assisted initialState: RoomListViewState, @@ -55,6 +56,7 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room } private val displayMode = initialState.displayMode + private val roomListDisplayModeFilter = RoomListDisplayModeFilter(displayMode) private val _openRoomLiveData = MutableLiveData>() val openRoomLiveData: LiveData> @@ -95,7 +97,9 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room copy(asyncRooms = asyncRooms) } - homeRoomListObservableSource.observeFilteredBy(displayMode) + homeRoomListObservableSource + .observe() + .observeOn(Schedulers.computation()) .map { buildRoomSummaries(it) } .execute { async -> copy(asyncFilteredRooms = async) @@ -182,23 +186,24 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room val lowPriorities = ArrayList() val serverNotices = ArrayList() - for (room in rooms) { - if (room.membership.isLeft()) continue - val tags = room.tags.map { it.name } - when { - room.membership == Membership.INVITE -> invites.add(room) - tags.contains(RoomTag.ROOM_TAG_SERVER_NOTICE) -> serverNotices.add(room) - tags.contains(RoomTag.ROOM_TAG_FAVOURITE) -> favourites.add(room) - tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room) - room.isDirect -> directChats.add(room) - else -> groupRooms.add(room) - } - } + rooms + .filter { roomListDisplayModeFilter.test(it) } + .forEach { room -> + val tags = room.tags.map { it.name } + when { + room.membership == Membership.INVITE -> invites.add(room) + tags.contains(RoomTag.ROOM_TAG_SERVER_NOTICE) -> serverNotices.add(room) + tags.contains(RoomTag.ROOM_TAG_FAVOURITE) -> favourites.add(room) + tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room) + room.isDirect -> directChats.add(room) + else -> groupRooms.add(room) + } + } val roomComparator = when (displayMode) { RoomListFragment.DisplayMode.HOME -> chronologicalRoomComparator RoomListFragment.DisplayMode.PEOPLE -> chronologicalRoomComparator - RoomListFragment.DisplayMode.ROOMS -> alphabeticalRoomComparator + RoomListFragment.DisplayMode.ROOMS -> chronologicalRoomComparator } return RoomSummaries().apply { @@ -210,6 +215,4 @@ class RoomListViewModel @AssistedInject constructor(@Assisted initialState: Room put(RoomCategory.SERVER_NOTICE, serverNotices.sortedWith(roomComparator)) } } - - } \ No newline at end of file