diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt index c2f8e6d0be..aec358218b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.api.session.room import androidx.lifecycle.LiveData import androidx.paging.PagedList -import kotlinx.coroutines.flow.Flow import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.Membership @@ -218,7 +217,8 @@ interface RoomService { sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): UpdatableLivePageResult /** - * Retrieve a LiveData on the number of rooms. + * Return a LiveData on the number of rooms + * @param queryParams parameters to query the room summaries. It can be use to keep only joined rooms, for instance. */ fun getRoomCountLive(queryParams: RoomSummaryQueryParams): LiveData diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt index 2869628576..1bc98015aa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt @@ -20,7 +20,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import androidx.paging.PagedList import com.zhuinden.monarchy.Monarchy -import kotlinx.coroutines.flow.Flow import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.RoomService diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt index f69fdb37c7..1925fe8e9f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt @@ -241,7 +241,7 @@ internal class RoomSummaryDataSource @Inject constructor( roomSummariesQuery(it, queryParams) } return Transformations.map(liveRooms) { - it.realmResults.count() + it.realmResults.where().count().toInt() } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index 1ae4bc135b..67d7a732cc 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -53,6 +53,7 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA import im.vector.app.features.home.room.list.widget.NotifsFabMenuView import im.vector.app.features.notifications.NotificationDrawerManager import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -287,7 +288,7 @@ class RoomListFragment @Inject constructor( } val contentAdapter = when { - section.livePages != null -> { + section.livePages != null -> { pagedControllerFactory.createRoomSummaryPagedController() .also { controller -> section.livePages.observe(viewLifecycleOwner) { pl -> @@ -405,6 +406,7 @@ class RoomListFragment @Inject constructor( lifecycleScope.launch { section.itemCount .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) + .filter { it > 0 } .collect { count -> sectionAdapter.updateSection { it.copy(itemCount = count) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt index d687c68092..bd43a83f2c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt @@ -70,22 +70,20 @@ class RoomListSectionBuilderGroup( }, { qpm -> val name = stringProvider.getString(R.string.bottom_action_rooms) - session.getFilteredPagedRoomSummariesLive(qpm) - .let { updatableFilterLivePageResult -> - onUpdatable(updatableFilterLivePageResult) + val updatableFilterLivePageResult = session.getFilteredPagedRoomSummariesLive(qpm) + onUpdatable(updatableFilterLivePageResult) - val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() - .flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } - .distinctUntilChanged() + val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() + .flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } + .distinctUntilChanged() - sections.add( - RoomsSection( - sectionName = name, - livePages = updatableFilterLivePageResult.livePagedList, - itemCount = itemCountFlow - ) - ) - } + sections.add( + RoomsSection( + sectionName = name, + livePages = updatableFilterLivePageResult.livePagedList, + itemCount = itemCountFlow + ) + ) } ) } @@ -252,37 +250,33 @@ class RoomListSectionBuilderGroup( @StringRes nameRes: Int, notifyOfLocalEcho: Boolean = false, query: (RoomSummaryQueryParams.Builder) -> Unit) { - withQueryParams( - { query.invoke(it) }, - { roomQueryParams -> - val name = stringProvider.getString(nameRes) - session.getFilteredPagedRoomSummariesLive(roomQueryParams) - .also { - activeSpaceUpdaters.add(it) - }.livePagedList - .let { livePagedList -> - // use it also as a source to update count - livePagedList.asFlow() - .onEach { - sections.find { it.sectionName == name } - ?.notificationCount - ?.postValue(session.getNotificationCountForRooms(roomQueryParams)) - } - .flowOn(Dispatchers.Default) - .launchIn(coroutineScope) + withQueryParams(query) { roomQueryParams -> + val name = stringProvider.getString(nameRes) + session.getFilteredPagedRoomSummariesLive(roomQueryParams) + .also { + activeSpaceUpdaters.add(it) + }.livePagedList + .let { livePagedList -> + // use it also as a source to update count + livePagedList.asFlow() + .onEach { + sections.find { it.sectionName == name } + ?.notificationCount + ?.postValue(session.getNotificationCountForRooms(roomQueryParams)) + } + .flowOn(Dispatchers.Default) + .launchIn(coroutineScope) - sections.add( - RoomsSection( - sectionName = name, - livePages = livePagedList, - notifyOfLocalEcho = notifyOfLocalEcho, - itemCount = session.getRoomCountLive(roomQueryParams).asFlow() - ) + sections.add( + RoomsSection( + sectionName = name, + livePages = livePagedList, + notifyOfLocalEcho = notifyOfLocalEcho, + itemCount = session.getRoomCountLive(roomQueryParams).asFlow() ) - } - } - - ) + ) + } + } } private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt index 3e21b0f58f..262df2784a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt @@ -32,6 +32,7 @@ import im.vector.app.features.invite.showInvites import im.vector.app.space import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest @@ -40,6 +41,7 @@ import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.update import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.query.ActiveSpaceFilter import org.matrix.android.sdk.api.query.RoomCategoryFilter @@ -83,64 +85,10 @@ class RoomListSectionBuilderSpace( } RoomListDisplayMode.FILTERED -> { // Used when searching for rooms - withQueryParams( - { - it.memberships = Membership.activeMemberships() - }, - { qpm -> - val name = stringProvider.getString(R.string.bottom_action_rooms) - session.getFilteredPagedRoomSummariesLive(qpm) - .let { updatableFilterLivePageResult -> - onUpdatable(updatableFilterLivePageResult) - - val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() - .flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } - .distinctUntilChanged() - - sections.add( - RoomsSection( - sectionName = name, - livePages = updatableFilterLivePageResult.livePagedList, - itemCount = itemCountFlow - ) - ) - } - } - ) + buildFilteredSection(sections) } RoomListDisplayMode.NOTIFICATIONS -> { - if (autoAcceptInvites.showInvites()) { - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.invitations_header, - notifyOfLocalEcho = true, - spaceFilterStrategy = if (onlyOrphansInHome) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL - } else { - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - }, - countRoomAsNotif = true - ) { - it.memberships = listOf(Membership.INVITE) - it.roomCategoryFilter = RoomCategoryFilter.ALL - } - } - - addSection( - sections = sections, - activeSpaceUpdaters = activeSpaceAwareQueries, - nameRes = R.string.bottom_action_rooms, - notifyOfLocalEcho = false, - spaceFilterStrategy = if (onlyOrphansInHome) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL - } else { - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL - } - ) { - it.memberships = listOf(Membership.JOIN) - it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS - } + buildNotificationsSection(sections, activeSpaceAwareQueries) } } @@ -332,6 +280,67 @@ class RoomListSectionBuilderSpace( } } + private fun buildNotificationsSection(sections: MutableList, activeSpaceAwareQueries: MutableList) { + if (autoAcceptInvites.showInvites()) { + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.invitations_header, + notifyOfLocalEcho = true, + spaceFilterStrategy = if (onlyOrphansInHome) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL + } else { + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + }, + countRoomAsNotif = true + ) { + it.memberships = listOf(Membership.INVITE) + it.roomCategoryFilter = RoomCategoryFilter.ALL + } + } + + addSection( + sections = sections, + activeSpaceUpdaters = activeSpaceAwareQueries, + nameRes = R.string.bottom_action_rooms, + notifyOfLocalEcho = false, + spaceFilterStrategy = if (onlyOrphansInHome) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL + } else { + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL + } + ) { + it.memberships = listOf(Membership.JOIN) + it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS + } + } + + private fun buildFilteredSection(sections: MutableList) { + // Used when searching for rooms + withQueryParams( + { + it.memberships = Membership.activeMemberships() + }, + { qpm -> + val name = stringProvider.getString(R.string.bottom_action_rooms) + val updatableFilterLivePageResult = session.getFilteredPagedRoomSummariesLive(qpm) + onUpdatable(updatableFilterLivePageResult) + + val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() + .flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } + .distinctUntilChanged() + + sections.add( + RoomsSection( + sectionName = name, + livePages = updatableFilterLivePageResult.livePagedList, + itemCount = itemCountFlow + ) + ) + } + ) + } + private fun addSection(sections: MutableList, activeSpaceUpdaters: MutableList, @StringRes nameRes: Int, @@ -339,83 +348,82 @@ class RoomListSectionBuilderSpace( spaceFilterStrategy: RoomListViewModel.SpaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.NONE, countRoomAsNotif: Boolean = false, query: (RoomSummaryQueryParams.Builder) -> Unit) { - withQueryParams( - { query.invoke(it) }, - { roomQueryParams -> - val name = stringProvider.getString(nameRes) - session.getFilteredPagedRoomSummariesLive( - roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()), - pagedListConfig - ).also { - when (spaceFilterStrategy) { - RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> { - activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { - override fun updateForSpaceId(roomId: String?) { - it.queryParams = roomQueryParams.copy( - activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId) - ) - } - }) - } - RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> { - activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { - override fun updateForSpaceId(roomId: String?) { - if (roomId != null) { - it.queryParams = roomQueryParams.copy( - activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId) - ) - } else { - it.queryParams = roomQueryParams.copy( - activeSpaceFilter = ActiveSpaceFilter.None - ) - } - } - }) - } - RoomListViewModel.SpaceFilterStrategy.NONE -> { - // we ignore current space for this one - } + withQueryParams(query) { roomQueryParams -> + val updatedQueryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) + val liveQueryParams = MutableStateFlow(updatedQueryParams) + val itemCountFlow = liveQueryParams + .flatMapLatest { + session.getRoomCountLive(it).asFlow() + } + .flowOn(Dispatchers.Main) + .distinctUntilChanged() + + val name = stringProvider.getString(nameRes) + val filteredPagedRoomSummariesLive = session.getFilteredPagedRoomSummariesLive( + roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()), + pagedListConfig + ) + when (spaceFilterStrategy) { + RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> { + activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { + override fun updateForSpaceId(roomId: String?) { + filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( + activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId) + ) + liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams } } - }.livePagedList - .let { livePagedList -> - // use it also as a source to update count - livePagedList.asFlow() - .onEach { - Timber.v("Thread space list: ${Thread.currentThread()}") - sections.find { it.sectionName == name } - ?.notificationCount - ?.postValue( - if (countRoomAsNotif) { - RoomAggregateNotificationCount(it.size, it.size) - } else { - session.getNotificationCountForRooms( - roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) - ) - } - ) - } - .flowOn(Dispatchers.Default) - .launchIn(viewModelScope) - - val itemCountFlow = livePagedList.asFlow() - .flatMapLatest { - val queryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) - session.getRoomCountLive(queryParams).asFlow() - } - .distinctUntilChanged() - - sections.add( - RoomsSection( - sectionName = name, - livePages = livePagedList, - notifyOfLocalEcho = notifyOfLocalEcho, - itemCount = itemCountFlow - ) + }) + } + RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> { + activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { + override fun updateForSpaceId(roomId: String?) { + if (roomId != null) { + filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( + activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId) + ) + } else { + filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy( + activeSpaceFilter = ActiveSpaceFilter.None ) } + liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams } + } + }) } + RoomListViewModel.SpaceFilterStrategy.NONE -> { + // we ignore current space for this one + } + } - ) + val livePagedList = filteredPagedRoomSummariesLive.livePagedList + // use it also as a source to update count + livePagedList.asFlow() + .onEach { + Timber.v("Thread space list: ${Thread.currentThread()}") + sections.find { it.sectionName == name } + ?.notificationCount + ?.postValue( + if (countRoomAsNotif) { + RoomAggregateNotificationCount(it.size, it.size) + } else { + session.getNotificationCountForRooms( + roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) + ) + } + ) + } + .flowOn(Dispatchers.Default) + .launchIn(viewModelScope) + + sections.add( + RoomsSection( + sectionName = name, + livePages = livePagedList, + notifyOfLocalEcho = notifyOfLocalEcho, + itemCount = itemCountFlow + ) + ) + } } private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) {