From 3c2fa40b58ad47ccb7eef46985f07d873e35cf77 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Jan 2020 17:57:06 +0100 Subject: [PATCH 1/2] Sharing things to RiotX: sort list by recent room first (#771) --- .idea/codeStyles/codeStyleConfig.xml | 1 + CHANGES.md | 2 +- .../api/session/room/model/RoomSummary.kt | 7 ++- .../database/mapper/RoomSummaryMapper.kt | 5 +- .../database/model/RoomSummaryEntity.kt | 54 +++++++++---------- .../session/room/DefaultRoomService.kt | 2 +- .../sync/UserAccountDataSyncHandler.kt | 18 +++++-- .../user/accountdata/SaveBreadcrumbsTask.kt | 5 +- .../room/list/BreadcrumbsRoomComparator.kt | 44 +++++++++++++++ .../room/list/ChronologicalRoomComparator.kt | 34 +++++------- .../features/share/IncomingShareViewModel.kt | 7 ++- 11 files changed, 120 insertions(+), 59 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/room/list/BreadcrumbsRoomComparator.kt diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index 79ee123c2b..6e6eec1148 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,6 @@ \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index 7a39b8021d..54dd5e5247 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,7 @@ Features ✨: - Enable encryption in unencrypted rooms, from the room settings (#212) Improvements 🙌: - - + - Sharing things to RiotX: sort list by recent room first (#771) Other changes: - diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt index 1f7a7b144a..7ec6254613 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt @@ -45,7 +45,8 @@ data class RoomSummary( val readMarkerId: String? = null, val userDrafts: List = emptyList(), var isEncrypted: Boolean, - val typingRoomMemberIds: List = emptyList() + val typingRoomMemberIds: List = emptyList(), + val breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS ) { val isVersioned: Boolean @@ -53,4 +54,8 @@ data class RoomSummary( val hasNewMessages: Boolean get() = notificationCount != 0 + + companion object { + const val NOT_IN_BREADCRUMBS = -1 + } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index 72d221aafe..896f994c99 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -22,7 +22,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult import im.vector.matrix.android.internal.database.model.RoomSummaryEntity -import java.util.* +import java.util.UUID import javax.inject.Inject internal class RoomSummaryMapper @Inject constructor( @@ -74,7 +74,8 @@ internal class RoomSummaryMapper @Inject constructor( canonicalAlias = roomSummaryEntity.canonicalAlias, aliases = roomSummaryEntity.aliases.toList(), isEncrypted = roomSummaryEntity.isEncrypted, - typingRoomMemberIds = roomSummaryEntity.typingUserIds.toList() + typingRoomMemberIds = roomSummaryEntity.typingUserIds.toList(), + breadcrumbsIndex = roomSummaryEntity.breadcrumbsIndex ) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt index d857d8810c..c56e9ba10e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt @@ -17,35 +17,37 @@ package im.vector.matrix.android.internal.database.model import im.vector.matrix.android.api.session.room.model.Membership +import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.VersioningState import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.PrimaryKey -internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", - var displayName: String? = "", - var avatarUrl: String? = "", - var topic: String? = "", - var latestPreviewableEvent: TimelineEventEntity? = null, - var heroes: RealmList = RealmList(), - var joinedMembersCount: Int? = 0, - var invitedMembersCount: Int? = 0, - var isDirect: Boolean = false, - var directUserId: String? = null, - var otherMemberIds: RealmList = RealmList(), - var notificationCount: Int = 0, - var highlightCount: Int = 0, - var readMarkerId: String? = null, - var hasUnreadMessages: Boolean = false, - var tags: RealmList = RealmList(), - var userDrafts: UserDraftsEntity? = null, - var breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS, - var canonicalAlias: String? = null, - var aliases: RealmList = RealmList(), - // this is required for querying - var flatAliases: String = "", - var isEncrypted: Boolean = false, - var typingUserIds: RealmList = RealmList() +internal open class RoomSummaryEntity( + @PrimaryKey var roomId: String = "", + var displayName: String? = "", + var avatarUrl: String? = "", + var topic: String? = "", + var latestPreviewableEvent: TimelineEventEntity? = null, + var heroes: RealmList = RealmList(), + var joinedMembersCount: Int? = 0, + var invitedMembersCount: Int? = 0, + var isDirect: Boolean = false, + var directUserId: String? = null, + var otherMemberIds: RealmList = RealmList(), + var notificationCount: Int = 0, + var highlightCount: Int = 0, + var readMarkerId: String? = null, + var hasUnreadMessages: Boolean = false, + var tags: RealmList = RealmList(), + var userDrafts: UserDraftsEntity? = null, + var breadcrumbsIndex: Int = RoomSummary.NOT_IN_BREADCRUMBS, + var canonicalAlias: String? = null, + var aliases: RealmList = RealmList(), + // this is required for querying + var flatAliases: String = "", + var isEncrypted: Boolean = false, + var typingUserIds: RealmList = RealmList() ) : RealmObject() { private var membershipStr: String = Membership.NONE.name @@ -66,7 +68,5 @@ internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", versioningStateStr = value.name } - companion object { - const val NOT_IN_BREADCRUMBS = -1 - } + companion object } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index 0cfc5aad3c..cf4c858bbd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -130,7 +130,7 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona return RoomSummaryEntity.where(realm) .isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) .notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name) - .greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummaryEntity.NOT_IN_BREADCRUMBS) + .greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummary.NOT_IN_BREADCRUMBS) .sort(RoomSummaryEntityFields.BREADCRUMBS_INDEX) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt index 07e8664102..f76c2ff448 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt @@ -21,16 +21,26 @@ import im.vector.matrix.android.api.pushrules.RuleScope import im.vector.matrix.android.api.pushrules.RuleSetKey import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.RoomMemberContent +import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.internal.database.mapper.PushRulesMapper import im.vector.matrix.android.internal.database.mapper.asDomain -import im.vector.matrix.android.internal.database.model.* +import im.vector.matrix.android.internal.database.model.BreadcrumbsEntity +import im.vector.matrix.android.internal.database.model.IgnoredUserEntity +import im.vector.matrix.android.internal.database.model.PushRulesEntity +import im.vector.matrix.android.internal.database.model.RoomSummaryEntity +import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields import im.vector.matrix.android.internal.database.query.getDirectRooms import im.vector.matrix.android.internal.database.query.getOrCreate import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync -import im.vector.matrix.android.internal.session.sync.model.accountdata.* +import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataBreadcrumbs +import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataDirectMessages +import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataFallback +import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataIgnoredUsers +import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataPushRules +import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataSync import im.vector.matrix.android.internal.session.user.accountdata.DirectChatsHelper import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask import io.realm.Realm @@ -177,10 +187,10 @@ internal class UserAccountDataSyncHandler @Inject constructor( // Update the room summaries // Reset all the indexes... RoomSummaryEntity.where(realm) - .greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummaryEntity.NOT_IN_BREADCRUMBS) + .greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummary.NOT_IN_BREADCRUMBS) .findAll() .forEach { - it.breadcrumbsIndex = RoomSummaryEntity.NOT_IN_BREADCRUMBS + it.breadcrumbsIndex = RoomSummary.NOT_IN_BREADCRUMBS } // ...and apply new indexes diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/SaveBreadcrumbsTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/SaveBreadcrumbsTask.kt index 008dd1d652..ecdcdb8768 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/SaveBreadcrumbsTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/accountdata/SaveBreadcrumbsTask.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.session.user.accountdata import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.internal.database.model.BreadcrumbsEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields @@ -50,10 +51,10 @@ internal class DefaultSaveBreadcrumbsTask @Inject constructor( // Update the room summaries // Reset all the indexes... RoomSummaryEntity.where(realm) - .greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummaryEntity.NOT_IN_BREADCRUMBS) + .greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummary.NOT_IN_BREADCRUMBS) .findAll() .forEach { - it.breadcrumbsIndex = RoomSummaryEntity.NOT_IN_BREADCRUMBS + it.breadcrumbsIndex = RoomSummary.NOT_IN_BREADCRUMBS } // ...and apply new indexes diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/BreadcrumbsRoomComparator.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/BreadcrumbsRoomComparator.kt new file mode 100644 index 0000000000..3b858b39fb --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/BreadcrumbsRoomComparator.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2020 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.riotx.features.home.room.list + +import im.vector.matrix.android.api.session.room.model.RoomSummary +import javax.inject.Inject + +class BreadcrumbsRoomComparator @Inject constructor( + private val chronologicalRoomComparator: ChronologicalRoomComparator +) : Comparator { + + override fun compare(leftRoomSummary: RoomSummary?, rightRoomSummary: RoomSummary?): Int { + val leftBreadcrumbsIndex = leftRoomSummary?.breadcrumbsIndex ?: RoomSummary.NOT_IN_BREADCRUMBS + val rightBreadcrumbsIndex = rightRoomSummary?.breadcrumbsIndex ?: RoomSummary.NOT_IN_BREADCRUMBS + + return if (leftBreadcrumbsIndex == RoomSummary.NOT_IN_BREADCRUMBS) { + if (rightBreadcrumbsIndex == RoomSummary.NOT_IN_BREADCRUMBS) { + chronologicalRoomComparator.compare(leftRoomSummary, rightRoomSummary) + } else { + 1 + } + } else { + if (rightBreadcrumbsIndex == RoomSummary.NOT_IN_BREADCRUMBS) { + -1 + } else { + leftBreadcrumbsIndex - rightBreadcrumbsIndex + } + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/ChronologicalRoomComparator.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/ChronologicalRoomComparator.kt index 047a518974..618d6c901b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/ChronologicalRoomComparator.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/ChronologicalRoomComparator.kt @@ -22,26 +22,20 @@ import javax.inject.Inject class ChronologicalRoomComparator @Inject constructor() : Comparator { override fun compare(leftRoomSummary: RoomSummary?, rightRoomSummary: RoomSummary?): Int { - var rightTimestamp = 0L - var leftTimestamp = 0L - if (null != leftRoomSummary) { - leftTimestamp = leftRoomSummary.latestPreviewableEvent?.root?.originServerTs ?: 0 - } - if (null != rightRoomSummary) { - rightTimestamp = rightRoomSummary.latestPreviewableEvent?.root?.originServerTs ?: 0 - } - return if (rightRoomSummary?.latestPreviewableEvent?.root == null) { - -1 - } else if (leftRoomSummary?.latestPreviewableEvent?.root == null) { - 1 - } else { - val deltaTimestamp = rightTimestamp - leftTimestamp - if (deltaTimestamp > 0) { - 1 - } else if (deltaTimestamp < 0) { - -1 - } else { - 0 + return when { + rightRoomSummary?.latestPreviewableEvent?.root == null -> -1 + leftRoomSummary?.latestPreviewableEvent?.root == null -> 1 + else -> { + val rightTimestamp = rightRoomSummary.latestPreviewableEvent?.root?.originServerTs ?: 0 + val leftTimestamp = leftRoomSummary.latestPreviewableEvent?.root?.originServerTs ?: 0 + + val deltaTimestamp = rightTimestamp - leftTimestamp + + when { + deltaTimestamp > 0 -> 1 + deltaTimestamp < 0 -> -1 + else -> 0 + } } } } diff --git a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt index 37b429d3d7..8b791fbf1b 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareViewModel.kt @@ -28,6 +28,7 @@ import im.vector.riotx.ActiveSessionDataSource import im.vector.riotx.core.platform.EmptyAction import im.vector.riotx.core.platform.EmptyViewEvents import im.vector.riotx.core.platform.VectorViewModel +import im.vector.riotx.features.home.room.list.BreadcrumbsRoomComparator import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import java.util.concurrent.TimeUnit @@ -39,7 +40,8 @@ data class IncomingShareState(private val dummy: Boolean = false) : MvRxState */ class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState: IncomingShareState, private val sessionObservableStore: ActiveSessionDataSource, - private val shareRoomListObservableStore: ShareRoomListDataSource) + private val shareRoomListObservableStore: ShareRoomListDataSource, + private val breadcrumbsRoomComparator: BreadcrumbsRoomComparator) : VectorViewModel(initialState) { @AssistedInject.Factory @@ -69,6 +71,9 @@ class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState: ?: Observable.just(emptyList()) } .throttleLast(300, TimeUnit.MILLISECONDS) + .map { + it.sortedWith(breadcrumbsRoomComparator) + } .subscribe { shareRoomListObservableStore.post(it) } From c971f18fc0d76c1cdbf47505570e68ea679fea2a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Jan 2020 19:02:41 +0100 Subject: [PATCH 2/2] Add section header when displaying room list to share (#771) --- .../home/room/list/RoomListViewModel.kt | 72 +++++++----- .../home/room/list/RoomListViewState.kt | 15 ++- .../home/room/list/RoomSummaryController.kt | 107 +++++++++++------- .../features/share/IncomingShareActivity.kt | 4 +- vector/src/main/res/values/strings_riotX.xml | 3 + 5 files changed, 132 insertions(+), 69 deletions(-) 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 f2f563cf26..397df50c2b 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 @@ -26,6 +26,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.tag.RoomTag import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.utils.DataSource +import im.vector.riotx.features.home.RoomListDisplayMode import io.reactivex.schedulers.Schedulers import timber.log.Timber import javax.inject.Inject @@ -202,35 +203,54 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState, } private fun buildRoomSummaries(rooms: List): RoomSummaries { - // Set up init size on directChats and groupRooms as they are the biggest ones - val invites = ArrayList() - val favourites = ArrayList() - val directChats = ArrayList(rooms.size) - val groupRooms = ArrayList(rooms.size) - val lowPriorities = ArrayList() - val serverNotices = ArrayList() + if (displayMode == RoomListDisplayMode.SHARE) { + val recentRooms = ArrayList(20) + val otherRooms = ArrayList(rooms.size) - 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) + rooms + .filter { roomListDisplayModeFilter.test(it) } + .forEach { room -> + when (room.breadcrumbsIndex) { + RoomSummary.NOT_IN_BREADCRUMBS -> otherRooms.add(room) + else -> recentRooms.add(room) + } } - } - return RoomSummaries().apply { - put(RoomCategory.INVITE, invites) - put(RoomCategory.FAVOURITE, favourites) - put(RoomCategory.DIRECT, directChats) - put(RoomCategory.GROUP, groupRooms) - put(RoomCategory.LOW_PRIORITY, lowPriorities) - put(RoomCategory.SERVER_NOTICE, serverNotices) + return RoomSummaries().apply { + put(RoomCategory.RECENT_ROOMS, recentRooms) + put(RoomCategory.OTHER_ROOMS, otherRooms) + } + } else { + // Set up init size on directChats and groupRooms as they are the biggest ones + val invites = ArrayList() + val favourites = ArrayList() + val directChats = ArrayList(rooms.size) + val groupRooms = ArrayList(rooms.size) + val lowPriorities = ArrayList() + val serverNotices = ArrayList() + + 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) + } + } + + return RoomSummaries().apply { + put(RoomCategory.INVITE, invites) + put(RoomCategory.FAVOURITE, favourites) + put(RoomCategory.DIRECT, directChats) + put(RoomCategory.GROUP, groupRooms) + put(RoomCategory.LOW_PRIORITY, lowPriorities) + put(RoomCategory.SERVER_NOTICE, serverNotices) + } } } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt index b41b4b9eeb..c127fa10e2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListViewState.kt @@ -43,7 +43,10 @@ data class RoomListViewState( val isDirectRoomsExpanded: Boolean = true, val isGroupRoomsExpanded: Boolean = true, val isLowPriorityRoomsExpanded: Boolean = true, - val isServerNoticeRoomsExpanded: Boolean = true + val isServerNoticeRoomsExpanded: Boolean = true, + // For sharing + val isRecentExpanded: Boolean = true, + val isOtherExpanded: Boolean = true ) : MvRxState { constructor(args: RoomListParams) : this(displayMode = args.displayMode) @@ -56,6 +59,8 @@ data class RoomListViewState( RoomCategory.GROUP -> isGroupRoomsExpanded RoomCategory.LOW_PRIORITY -> isLowPriorityRoomsExpanded RoomCategory.SERVER_NOTICE -> isServerNoticeRoomsExpanded + RoomCategory.RECENT_ROOMS -> isRecentExpanded + RoomCategory.OTHER_ROOMS -> isOtherExpanded } } @@ -67,6 +72,8 @@ data class RoomListViewState( RoomCategory.GROUP -> copy(isGroupRoomsExpanded = !isGroupRoomsExpanded) RoomCategory.LOW_PRIORITY -> copy(isLowPriorityRoomsExpanded = !isLowPriorityRoomsExpanded) RoomCategory.SERVER_NOTICE -> copy(isServerNoticeRoomsExpanded = !isServerNoticeRoomsExpanded) + RoomCategory.RECENT_ROOMS -> copy(isRecentExpanded = !isRecentExpanded) + RoomCategory.OTHER_ROOMS -> copy(isOtherExpanded = !isOtherExpanded) } } @@ -86,7 +93,11 @@ enum class RoomCategory(@StringRes val titleRes: Int) { DIRECT(R.string.bottom_action_people_x), GROUP(R.string.bottom_action_rooms), LOW_PRIORITY(R.string.low_priority_header), - SERVER_NOTICE(R.string.system_alerts_header) + SERVER_NOTICE(R.string.system_alerts_header), + + // For Sharing + RECENT_ROOMS(R.string.room_list_sharing_header_recent_rooms), + OTHER_ROOMS(R.string.room_list_sharing_header_other_rooms) } fun RoomSummaries?.isNullOrEmpty(): Boolean { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt index 6ffe37cb15..c4afd442ab 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryController.kt @@ -59,39 +59,9 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri override fun buildModels() { val nonNullViewState = viewState ?: return when (nonNullViewState.displayMode) { - RoomListDisplayMode.FILTERED, - RoomListDisplayMode.SHARE -> { - buildFilteredRooms(nonNullViewState) - } - else -> { - var showHelp = false - val roomSummaries = nonNullViewState.asyncFilteredRooms() - roomSummaries?.forEach { (category, summaries) -> - if (summaries.isEmpty()) { - return@forEach - } else { - val isExpanded = nonNullViewState.isCategoryExpanded(category) - buildRoomCategory(nonNullViewState, summaries, category.titleRes, nonNullViewState.isCategoryExpanded(category)) { - listener?.onToggleRoomCategory(category) - } - if (isExpanded) { - buildRoomModels(summaries, - nonNullViewState.joiningRoomsIds, - nonNullViewState.joiningErrorRoomsIds, - nonNullViewState.rejectingRoomsIds, - nonNullViewState.rejectingErrorRoomsIds) - // Never set showHelp to true for invitation - if (category != RoomCategory.INVITE) { - showHelp = userPreferencesProvider.shouldShowLongClickOnRoomHelp() - } - } - } - } - - if (showHelp) { - buildLongClickHelp() - } - } + RoomListDisplayMode.FILTERED -> buildFilteredRooms(nonNullViewState) + RoomListDisplayMode.SHARE -> buildShareRooms(nonNullViewState) + else -> buildRooms(nonNullViewState) } } @@ -109,9 +79,69 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri viewState.rejectingRoomsIds, viewState.rejectingErrorRoomsIds) - when { - viewState.displayMode == RoomListDisplayMode.FILTERED -> addFilterFooter(viewState) - filteredSummaries.isEmpty() -> addEmptyFooter() + addFilterFooter(viewState) + } + + private fun buildShareRooms(viewState: RoomListViewState) { + var hasResult = false + val roomSummaries = viewState.asyncFilteredRooms() + + roomListNameFilter.filter = viewState.roomFilter + + roomSummaries?.forEach { (category, summaries) -> + val filteredSummaries = summaries + .filter { it.membership == Membership.JOIN && roomListNameFilter.test(it) } + + if (filteredSummaries.isEmpty()) { + return@forEach + } else { + hasResult = true + val isExpanded = viewState.isCategoryExpanded(category) + buildRoomCategory(viewState, emptyList(), category.titleRes, viewState.isCategoryExpanded(category)) { + listener?.onToggleRoomCategory(category) + } + if (isExpanded) { + buildRoomModels(filteredSummaries, + emptySet(), + emptySet(), + emptySet(), + emptySet() + ) + } + } + } + if (!hasResult) { + addNoResultItem() + } + } + + private fun buildRooms(viewState: RoomListViewState) { + var showHelp = false + val roomSummaries = viewState.asyncFilteredRooms() + roomSummaries?.forEach { (category, summaries) -> + if (summaries.isEmpty()) { + return@forEach + } else { + val isExpanded = viewState.isCategoryExpanded(category) + buildRoomCategory(viewState, summaries, category.titleRes, viewState.isCategoryExpanded(category)) { + listener?.onToggleRoomCategory(category) + } + if (isExpanded) { + buildRoomModels(summaries, + viewState.joiningRoomsIds, + viewState.joiningErrorRoomsIds, + viewState.rejectingRoomsIds, + viewState.rejectingErrorRoomsIds) + // Never set showHelp to true for invitation + if (category != RoomCategory.INVITE) { + showHelp = userPreferencesProvider.shouldShowLongClickOnRoomHelp() + } + } + } + } + + if (showHelp) { + buildLongClickHelp() } } @@ -130,7 +160,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri } } - private fun addEmptyFooter() { + private fun addNoResultItem() { noResultItem { id("no_result") text(stringProvider.getString(R.string.no_result_placeholder)) @@ -142,9 +172,6 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri @StringRes titleRes: Int, isExpanded: Boolean, mutateExpandedState: () -> Unit) { - if (summaries.isEmpty()) { - return - } // TODO should add some business logic later val unreadCount = if (summaries.isEmpty()) { 0 diff --git a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt index e48c8246d2..3669a51937 100644 --- a/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/share/IncomingShareActivity.kt @@ -44,7 +44,9 @@ class IncomingShareActivity : @Inject lateinit var sessionHolder: ActiveSessionHolder @Inject lateinit var incomingShareViewModelFactory: IncomingShareViewModel.Factory private lateinit var attachmentsHelper: AttachmentsHelper - private val incomingShareViewModel: IncomingShareViewModel by viewModel() + // Do not remove, even if not used, it instantiates the view model + @Suppress("unused") + private val viewModel: IncomingShareViewModel by viewModel() private val roomListFragment: RoomListFragment? get() { return supportFragmentManager.findFragmentById(R.id.shareRoomListFragmentContainer) as? RoomListFragment diff --git a/vector/src/main/res/values/strings_riotX.xml b/vector/src/main/res/values/strings_riotX.xml index 4ca908128e..781912fbe5 100644 --- a/vector/src/main/res/values/strings_riotX.xml +++ b/vector/src/main/res/values/strings_riotX.xml @@ -34,6 +34,9 @@ Unignore + Recent rooms + Other rooms + Timeline