Invites : start handling invite/left sync

This commit is contained in:
ganfra 2019-05-06 19:17:30 +02:00
parent ceac06caf6
commit 72cd409735
9 changed files with 52 additions and 26 deletions

View File

@ -31,7 +31,8 @@ data class RoomSummary(
val isDirect: Boolean = false, val isDirect: Boolean = false,
val lastMessage: Event? = null, val lastMessage: Event? = null,
val otherMemberIds: List<String> = emptyList(), val otherMemberIds: List<String> = emptyList(),
var notificationCount: Int = 0, val notificationCount: Int = 0,
var highlightCount: Int = 0, val highlightCount: Int = 0,
var tags: List<RoomTag> = emptyList() val tags: List<RoomTag> = emptyList(),
val membership: MyMembership = MyMembership.NONE
) )

View File

@ -86,10 +86,9 @@ internal fun ChunkEntity.add(roomId: String,
isUnlinked: Boolean = false) { isUnlinked: Boolean = false) {


assertIsManaged() assertIsManaged()
if (event.eventId.isNullOrEmpty() || this.events.fastContains(event.eventId)) { if (event.eventId != null && events.fastContains(event.eventId)) {
return return
} }

var currentDisplayIndex = lastDisplayIndex(direction, 0) var currentDisplayIndex = lastDisplayIndex(direction, 0)
if (direction == PaginationDirection.FORWARDS) { if (direction == PaginationDirection.FORWARDS) {
currentDisplayIndex += 1 currentDisplayIndex += 1

View File

@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.database.mapper
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.UnsignedData import im.vector.matrix.android.api.session.events.model.UnsignedData
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntity
import java.util.*




internal object EventMapper { internal object EventMapper {
@ -26,7 +27,7 @@ internal object EventMapper {


fun map(event: Event, roomId: String): EventEntity { fun map(event: Event, roomId: String): EventEntity {
val eventEntity = EventEntity() val eventEntity = EventEntity()
eventEntity.eventId = event.eventId ?: "" eventEntity.eventId = event.eventId ?: UUID.randomUUID().toString()
eventEntity.roomId = event.roomId ?: roomId eventEntity.roomId = event.roomId ?: roomId
eventEntity.content = ContentMapper.map(event.content) eventEntity.content = ContentMapper.map(event.content)
val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent

View File

@ -37,7 +37,8 @@ internal object RoomSummaryMapper {
otherMemberIds = roomSummaryEntity.otherMemberIds.toList(), otherMemberIds = roomSummaryEntity.otherMemberIds.toList(),
highlightCount = roomSummaryEntity.highlightCount, highlightCount = roomSummaryEntity.highlightCount,
notificationCount = roomSummaryEntity.notificationCount, notificationCount = roomSummaryEntity.notificationCount,
tags = tags tags = tags,
membership = roomSummaryEntity.membership
) )
} }
} }

View File

@ -16,9 +16,12 @@


package im.vector.matrix.android.internal.database.model package im.vector.matrix.android.internal.database.model


import im.vector.matrix.android.api.session.room.model.MyMembership
import io.realm.RealmList import io.realm.RealmList
import io.realm.RealmObject import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey import io.realm.annotations.PrimaryKey
import kotlin.properties.Delegates


internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "",
var displayName: String? = "", var displayName: String? = "",
@ -35,6 +38,13 @@ internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "",
var tags: RealmList<RoomTagEntity> = RealmList() var tags: RealmList<RoomTagEntity> = RealmList()
) : RealmObject() { ) : RealmObject() {


private var membershipStr: String = MyMembership.NONE.name

@delegate:Ignore
var membership: MyMembership by Delegates.observable(MyMembership.valueOf(membershipStr)) { _, _, newValue ->
membershipStr = newValue.name
}

companion object companion object


} }

View File

@ -21,6 +21,7 @@ package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.RoomTopicContent import im.vector.matrix.android.api.session.room.model.RoomTopicContent
import im.vector.matrix.android.internal.database.mapper.asDomain 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.model.EventEntity
@ -41,11 +42,12 @@ internal class RoomSummaryUpdater(private val credentials: Credentials,


fun update(realm: Realm, fun update(realm: Realm,
roomId: String, roomId: String,
membership: MyMembership? = null,
roomSummary: RoomSyncSummary? = null, roomSummary: RoomSyncSummary? = null,
unreadNotifications: RoomSyncUnreadNotifications? = null) { unreadNotifications: RoomSyncUnreadNotifications? = null) {


val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId) ?: realm.createObject(roomId)


if (roomSummary != null) { if (roomSummary != null) {
if (roomSummary.heroes.isNotEmpty()) { if (roomSummary.heroes.isNotEmpty()) {
@ -65,6 +67,9 @@ internal class RoomSummaryUpdater(private val credentials: Credentials,
if (unreadNotifications?.notificationCount != null) { if (unreadNotifications?.notificationCount != null) {
roomSummaryEntity.notificationCount = unreadNotifications.notificationCount roomSummaryEntity.notificationCount = unreadNotifications.notificationCount
} }
if (membership != null) {
roomSummaryEntity.membership = membership
}


val lastEvent = EventEntity.latestEvent(realm, roomId, includedTypes = listOf(EventType.MESSAGE)) val lastEvent = EventEntity.latestEvent(realm, roomId, includedTypes = listOf(EventType.MESSAGE))
val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev()?.asDomain() val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev()?.asDomain()

View File

@ -67,7 +67,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
val rooms = when (handlingStrategy) { val rooms = when (handlingStrategy) {
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) } is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) } is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) }
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) } is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(realm, it.key, it.value) }
} }
realm.insertOrUpdate(rooms) realm.insertOrUpdate(rooms)
} }
@ -84,7 +84,6 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
if (roomEntity.membership == MyMembership.INVITED) { if (roomEntity.membership == MyMembership.INVITED) {
roomEntity.chunks.deleteAllFromRealm() roomEntity.chunks.deleteAllFromRealm()
} }

roomEntity.membership = MyMembership.JOINED roomEntity.membership = MyMembership.JOINED


val lastChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId) val lastChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
@ -119,7 +118,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
} }
} }
} }
roomSummaryUpdater.update(realm, roomId, roomSync.summary, roomSync.unreadNotifications) roomSummaryUpdater.update(realm, roomId, MyMembership.JOINED, roomSync.summary, roomSync.unreadNotifications)


if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) { if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) {
handleEphemeral(realm, roomId, roomSync.ephemeral) handleEphemeral(realm, roomId, roomSync.ephemeral)
@ -128,7 +127,6 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
if (roomSync.accountData != null && roomSync.accountData.events.isNullOrEmpty().not()) { if (roomSync.accountData != null && roomSync.accountData.events.isNullOrEmpty().not()) {
handleRoomAccountDataEvents(realm, roomId, roomSync.accountData) handleRoomAccountDataEvents(realm, roomId, roomSync.accountData)
} }

return roomEntity return roomEntity
} }


@ -136,26 +134,28 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
roomId: String, roomId: String,
roomSync: roomSync:
InvitedRoomSync): RoomEntity { InvitedRoomSync): RoomEntity {

Timber.v("Handle invited sync for room $roomId") Timber.v("Handle invited sync for room $roomId")

val roomEntity = RoomEntity.where(realm, roomId).findFirst()
val roomEntity = RoomEntity() ?: realm.createObject(roomId)
roomEntity.roomId = roomId
roomEntity.membership = MyMembership.INVITED roomEntity.membership = MyMembership.INVITED
if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) { if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.inviteState.events) val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.inviteState.events)
roomEntity.addOrUpdate(chunkEntity) roomEntity.addOrUpdate(chunkEntity)
} }
roomSummaryUpdater.update(realm, roomId, MyMembership.INVITED)
return roomEntity return roomEntity
} }


// TODO : handle it private fun handleLeftRoom(realm: Realm,
private fun handleLeftRoom(roomId: String, roomId: String,
roomSync: RoomSync): RoomEntity { roomSync: RoomSync): RoomEntity {
return RoomEntity().apply { val roomEntity = RoomEntity.where(realm, roomId).findFirst()
this.roomId = roomId ?: realm.createObject(roomId)
this.membership = MyMembership.LEFT
} roomEntity.membership = MyMembership.LEFT
roomEntity.chunks.deleteAllFromRealm()
roomSummaryUpdater.update(realm, roomId, MyMembership.LEFT, roomSync.summary, roomSync.unreadNotifications)
return roomEntity
} }


private fun handleTimelineEvents(realm: Realm, private fun handleTimelineEvents(realm: Realm,

View File

@ -24,6 +24,7 @@ import com.airbnb.mvrx.ViewModelContext
import com.jakewharton.rxrelay2.BehaviorRelay import com.jakewharton.rxrelay2.BehaviorRelay
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.group.model.GroupSummary import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.RoomSummary 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.api.session.room.model.tag.RoomTag
import im.vector.matrix.rx.rx import im.vector.matrix.rx.rx
@ -153,6 +154,7 @@ class RoomListViewModel(initialState: RoomListViewState,
} }


private fun buildRoomSummaries(rooms: List<RoomSummary>): RoomSummaries { private fun buildRoomSummaries(rooms: List<RoomSummary>): RoomSummaries {
val invites = ArrayList<RoomSummary>()
val favourites = ArrayList<RoomSummary>() val favourites = ArrayList<RoomSummary>()
val directChats = ArrayList<RoomSummary>() val directChats = ArrayList<RoomSummary>()
val groupRooms = ArrayList<RoomSummary>() val groupRooms = ArrayList<RoomSummary>()
@ -160,17 +162,20 @@ class RoomListViewModel(initialState: RoomListViewState,
val serverNotices = ArrayList<RoomSummary>() val serverNotices = ArrayList<RoomSummary>()


for (room in rooms) { for (room in rooms) {
if (room.membership == MyMembership.LEFT) continue
val tags = room.tags.map { it.name } val tags = room.tags.map { it.name }
when { when {
tags.contains(RoomTag.ROOM_TAG_SERVER_NOTICE) -> serverNotices.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_FAVOURITE) -> favourites.add(room)
tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room) tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room)
room.isDirect -> directChats.add(room) room.isDirect -> directChats.add(room)
room.membership == MyMembership.INVITED -> invites.add(room)
else -> groupRooms.add(room) else -> groupRooms.add(room)
} }
} }


return RoomSummaries().apply { return RoomSummaries().apply {
put(RoomCategory.INVITE, invites.sortedWith(roomSummaryComparator))
put(RoomCategory.FAVOURITE, favourites.sortedWith(roomSummaryComparator)) put(RoomCategory.FAVOURITE, favourites.sortedWith(roomSummaryComparator))
put(RoomCategory.DIRECT, directChats.sortedWith(roomSummaryComparator)) put(RoomCategory.DIRECT, directChats.sortedWith(roomSummaryComparator))
put(RoomCategory.GROUP, groupRooms.sortedWith(roomSummaryComparator)) put(RoomCategory.GROUP, groupRooms.sortedWith(roomSummaryComparator))

View File

@ -26,15 +26,17 @@ import im.vector.riotredesign.R
data class RoomListViewState( data class RoomListViewState(
val asyncRooms: Async<RoomSummaries> = Uninitialized, val asyncRooms: Async<RoomSummaries> = Uninitialized,
val visibleRoomId: String? = null, val visibleRoomId: String? = null,
val isInviteExpanded: Boolean = true,
val isFavouriteRoomsExpanded: Boolean = true, val isFavouriteRoomsExpanded: Boolean = true,
val isDirectRoomsExpanded: Boolean = false, val isDirectRoomsExpanded: Boolean = true,
val isGroupRoomsExpanded: Boolean = false, val isGroupRoomsExpanded: Boolean = true,
val isLowPriorityRoomsExpanded: Boolean = false, val isLowPriorityRoomsExpanded: Boolean = true,
val isServerNoticeRoomsExpanded: Boolean = false val isServerNoticeRoomsExpanded: Boolean = true
) : MvRxState { ) : MvRxState {


fun isCategoryExpanded(roomCategory: RoomCategory): Boolean { fun isCategoryExpanded(roomCategory: RoomCategory): Boolean {
return when (roomCategory) { return when (roomCategory) {
RoomCategory.INVITE -> isInviteExpanded
RoomCategory.FAVOURITE -> isFavouriteRoomsExpanded RoomCategory.FAVOURITE -> isFavouriteRoomsExpanded
RoomCategory.DIRECT -> isDirectRoomsExpanded RoomCategory.DIRECT -> isDirectRoomsExpanded
RoomCategory.GROUP -> isGroupRoomsExpanded RoomCategory.GROUP -> isGroupRoomsExpanded
@ -45,6 +47,7 @@ data class RoomListViewState(


fun toggle(roomCategory: RoomCategory): RoomListViewState { fun toggle(roomCategory: RoomCategory): RoomListViewState {
return when (roomCategory) { return when (roomCategory) {
RoomCategory.INVITE -> copy(isInviteExpanded = !isInviteExpanded)
RoomCategory.FAVOURITE -> copy(isFavouriteRoomsExpanded = !isFavouriteRoomsExpanded) RoomCategory.FAVOURITE -> copy(isFavouriteRoomsExpanded = !isFavouriteRoomsExpanded)
RoomCategory.DIRECT -> copy(isDirectRoomsExpanded = !isDirectRoomsExpanded) RoomCategory.DIRECT -> copy(isDirectRoomsExpanded = !isDirectRoomsExpanded)
RoomCategory.GROUP -> copy(isGroupRoomsExpanded = !isGroupRoomsExpanded) RoomCategory.GROUP -> copy(isGroupRoomsExpanded = !isGroupRoomsExpanded)
@ -57,6 +60,7 @@ data class RoomListViewState(
typealias RoomSummaries = LinkedHashMap<RoomCategory, List<RoomSummary>> typealias RoomSummaries = LinkedHashMap<RoomCategory, List<RoomSummary>>


enum class RoomCategory(@StringRes val titleRes: Int) { enum class RoomCategory(@StringRes val titleRes: Int) {
INVITE(R.string.invitations_header),
FAVOURITE(R.string.bottom_action_favourites), FAVOURITE(R.string.bottom_action_favourites),
DIRECT(R.string.bottom_action_people), DIRECT(R.string.bottom_action_people),
GROUP(R.string.bottom_action_rooms), GROUP(R.string.bottom_action_rooms),