From 3c2fa40b58ad47ccb7eef46985f07d873e35cf77 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 21 Jan 2020 17:57:06 +0100 Subject: [PATCH] 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) }