diff --git a/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt b/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt index b8370270..3b3bd51d 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt @@ -27,6 +27,7 @@ import im.vector.riotredesign.features.home.room.detail.timeline.TimelineDateFor import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController import im.vector.riotredesign.features.home.room.detail.timeline.TimelineItemFactory import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider +import im.vector.riotredesign.features.home.room.list.RoomSummaryComparator import im.vector.riotredesign.features.home.room.list.RoomSummaryController import org.koin.dsl.module.module @@ -90,6 +91,10 @@ class HomeModule { HomePermalinkHandler(get()) } + single { + RoomSummaryComparator() + } + } } \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt index f53e1a34..d8edf515 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomListViewModel.kt @@ -40,7 +40,8 @@ class RoomListViewModel(initialState: RoomListViewState, private val session: Session, private val selectedGroupHolder: SelectedGroupHolder, private val visibleRoomHolder: VisibleRoomHolder, - private val roomSelectionRepository: RoomSelectionRepository) + private val roomSelectionRepository: RoomSelectionRepository, + private val roomSummaryComparator: RoomSummaryComparator) : RiotViewModel(initialState) { companion object : MvRxViewModelFactory { @@ -51,7 +52,8 @@ class RoomListViewModel(initialState: RoomListViewState, val roomSelectionRepository = viewModelContext.activity.get() val selectedGroupHolder = viewModelContext.activity.get() val visibleRoomHolder = viewModelContext.activity.get() - return RoomListViewModel(state, currentSession, selectedGroupHolder, visibleRoomHolder, roomSelectionRepository) + val roomSummaryComparator = viewModelContext.activity.get() + return RoomListViewModel(state, currentSession, selectedGroupHolder, visibleRoomHolder, roomSelectionRepository, roomSummaryComparator) } } @@ -154,7 +156,14 @@ class RoomListViewModel(initialState: RoomListViewState, else -> groupRooms.add(room) } } - return RoomSummaries(favourites, directChats, groupRooms, lowPriorities, serverNotices) + + return RoomSummaries( + favourites = favourites.sortedWith(roomSummaryComparator), + directRooms = directChats.sortedWith(roomSummaryComparator), + groupRooms = groupRooms.sortedWith(roomSummaryComparator), + lowPriorities = lowPriorities.sortedWith(roomSummaryComparator), + serverNotices = serverNotices.sortedWith(roomSummaryComparator) + ) } diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryComparator.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryComparator.kt new file mode 100644 index 00000000..8d92b694 --- /dev/null +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryComparator.kt @@ -0,0 +1,70 @@ +/* + * 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.riotredesign.features.home.room.list + +import im.vector.matrix.android.api.session.room.model.RoomSummary + +class RoomSummaryComparator + : Comparator { + + override fun compare(leftRoomSummary: RoomSummary?, rightRoomSummary: RoomSummary?): Int { + val retValue: Int + var leftHighlightCount = 0 + var rightHighlightCount = 0 + var leftNotificationCount = 0 + var rightNotificationCount = 0 + var rightTimestamp = 0L + var leftTimestamp = 0L + + if (null != leftRoomSummary) { + leftHighlightCount = leftRoomSummary.highlightCount + leftNotificationCount = leftRoomSummary.notificationCount + leftTimestamp = leftRoomSummary.lastMessage?.originServerTs ?: 0 + } + if (null != rightRoomSummary) { + rightHighlightCount = rightRoomSummary.highlightCount + rightNotificationCount = rightRoomSummary.notificationCount + rightTimestamp = rightRoomSummary.lastMessage?.originServerTs ?: 0 + } + + if (leftRoomSummary?.lastMessage == null) { + retValue = 1 + } else if (rightRoomSummary?.lastMessage == null) { + retValue = -1 + } else if (rightHighlightCount > 0 && leftHighlightCount == 0) { + retValue = 1 + } else if (rightHighlightCount == 0 && leftHighlightCount > 0) { + retValue = -1 + } else if (rightNotificationCount > 0 && leftNotificationCount == 0) { + retValue = 1 + } else if (rightNotificationCount == 0 && leftNotificationCount > 0) { + retValue = -1 + } else { + val deltaTimestamp = rightTimestamp - leftTimestamp + if (deltaTimestamp > 0) { + retValue = 1 + } else if (deltaTimestamp < 0) { + retValue = -1 + } else { + retValue = 0 + } + } + return retValue + + } + +} \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt index 931a0f6c..cc69d375 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt @@ -25,11 +25,11 @@ import im.vector.riotredesign.core.resources.StringProvider class RoomSummaryController(private val stringProvider: StringProvider ) : TypedEpoxyController() { - private var isDirectRoomsExpanded = true - private var isGroupRoomsExpanded = true private var isFavoriteRoomsExpanded = true - private var isLowPriorityRoomsExpanded = true - private var isServerNoticeRoomsExpanded = true + private var isDirectRoomsExpanded = false + private var isGroupRoomsExpanded = false + private var isLowPriorityRoomsExpanded = false + private var isServerNoticeRoomsExpanded = false var callback: Callback? = null @@ -79,7 +79,11 @@ class RoomSummaryController(private val stringProvider: StringProvider private fun buildRoomCategory(viewState: RoomListViewState, summaries: List, @StringRes titleRes: Int, isExpanded: Boolean, mutateExpandedState: () -> Unit) { //TODO should add some business logic later - val unreadCount = summaries.map { it.notificationCount }.reduce { acc, i -> acc + i } + val unreadCount = if (summaries.isEmpty()) { + 0 + } else { + summaries.map { it.notificationCount }.reduce { acc, i -> acc + i } + } val showHighlighted = summaries.any { it.highlightCount > 0 } RoomCategoryItem( title = stringProvider.getString(titleRes).toUpperCase(), 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 507de556..bda5a54c 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 @@ -16,6 +16,7 @@ package im.vector.matrix.android.api.session.room.model +import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.model.tag.RoomTag /** @@ -28,6 +29,7 @@ data class RoomSummary( val topic: String = "", val avatarUrl: String = "", val isDirect: Boolean, + val lastMessage: Event? = null, val otherMemberIds: List = emptyList(), var notificationCount: Int = 0, var highlightCount: Int = 0, 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 5ef8fb48..9243d1de 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 @@ -33,6 +33,7 @@ internal object RoomSummaryMapper { topic = roomSummaryEntity.topic ?: "", avatarUrl = roomSummaryEntity.avatarUrl ?: "", isDirect = roomSummaryEntity.isDirect, + lastMessage = roomSummaryEntity.lastMessage?.asDomain(), otherMemberIds = roomSummaryEntity.otherMemberIds.toList(), highlightCount = roomSummaryEntity.highlightCount, notificationCount = roomSummaryEntity.notificationCount, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt index d6efe178..80e194e3 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt @@ -50,9 +50,13 @@ internal fun EventEntity.Companion.where(realm: Realm, } internal fun EventEntity.Companion.latestEvent(realm: Realm, - roomId: String): EventEntity? { - val chunkEntity = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId) - return chunkEntity?.events?.where()?.sort(EventEntityFields.DISPLAY_INDEX)?.findFirst() + roomId: String, + excludedTypes: List = emptyList()): EventEntity? { + val query = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)?.events?.where() + return query + ?.not()?.`in`(EventEntityFields.TYPE, excludedTypes.toTypedArray()) + ?.sort(EventEntityFields.DISPLAY_INDEX) + ?.findFirst() } 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 bb998328..3e5fe1b1 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 @@ -28,6 +28,7 @@ import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.query.last +import im.vector.matrix.android.internal.database.query.latestEvent import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver import im.vector.matrix.android.internal.session.room.members.RoomMembers @@ -57,7 +58,7 @@ internal class RoomSummaryUpdater(monarchy: Monarchy, val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) - val lastMessageEvent = EventEntity.where(realm, roomId, EventType.MESSAGE).last() + val lastEvent = EventEntity.latestEvent(realm, roomId) val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).last()?.asDomain() val otherRoomMembers = RoomMembers(realm, roomId).getLoaded().filterKeys { it != credentials.userId } @@ -65,7 +66,7 @@ internal class RoomSummaryUpdater(monarchy: Monarchy, roomSummary.displayName = roomDisplayNameResolver.resolve(context, roomId).toString() roomSummary.avatarUrl = roomAvatarResolver.resolve(roomId) roomSummary.topic = lastTopicEvent?.content.toModel()?.topic - roomSummary.lastMessage = lastMessageEvent + roomSummary.lastMessage = lastEvent roomSummary.otherMemberIds.clear() roomSummary.otherMemberIds.addAll(otherRoomMembers.keys) }