mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
TimelineEvent : update sender data when loading room members and prune event (+ remove RoomSummaryMapper param)
This commit is contained in:
parent
7e6e09bc19
commit
dd07f5c2a6
@ -25,8 +25,8 @@ import io.reactivex.schedulers.Schedulers
|
|||||||
|
|
||||||
class RxRoom(private val room: Room) {
|
class RxRoom(private val room: Room) {
|
||||||
|
|
||||||
fun liveRoomSummary(fetchLastEvent: Boolean): Observable<RoomSummary> {
|
fun liveRoomSummary(): Observable<RoomSummary> {
|
||||||
return room.liveRoomSummary(fetchLastEvent).asObservable().observeOn(Schedulers.computation())
|
return room.liveRoomSummary().asObservable().observeOn(Schedulers.computation())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveRoomMemberIds(): Observable<List<String>> {
|
fun liveRoomMemberIds(): Observable<List<String>> {
|
||||||
|
@ -26,8 +26,8 @@ import io.reactivex.schedulers.Schedulers
|
|||||||
|
|
||||||
class RxSession(private val session: Session) {
|
class RxSession(private val session: Session) {
|
||||||
|
|
||||||
fun liveRoomSummaries(fetchLastEvents: Boolean): Observable<List<RoomSummary>> {
|
fun liveRoomSummaries(): Observable<List<RoomSummary>> {
|
||||||
return session.liveRoomSummaries(fetchLastEvents).asObservable().observeOn(Schedulers.computation())
|
return session.liveRoomSummaries().asObservable().observeOn(Schedulers.computation())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
|
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
|
||||||
|
@ -47,8 +47,8 @@ interface Room :
|
|||||||
* A live [RoomSummary] associated with the room
|
* A live [RoomSummary] associated with the room
|
||||||
* You can observe this summary to get dynamic data from this room.
|
* You can observe this summary to get dynamic data from this room.
|
||||||
*/
|
*/
|
||||||
fun liveRoomSummary(fetchLastEvent: Boolean = false): LiveData<RoomSummary>
|
fun liveRoomSummary(): LiveData<RoomSummary>
|
||||||
|
|
||||||
fun roomSummary(fetchLastEvent: Boolean = false): RoomSummary?
|
fun roomSummary(): RoomSummary?
|
||||||
|
|
||||||
}
|
}
|
@ -43,6 +43,6 @@ interface RoomService {
|
|||||||
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
|
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
|
||||||
* @return the [LiveData] of [RoomSummary]
|
* @return the [LiveData] of [RoomSummary]
|
||||||
*/
|
*/
|
||||||
fun liveRoomSummaries(fetchLastEvents: Boolean = true): LiveData<List<RoomSummary>>
|
fun liveRoomSummaries(): LiveData<List<RoomSummary>>
|
||||||
|
|
||||||
}
|
}
|
@ -31,8 +31,7 @@ class RealmLiveData<T : RealmModel>(private val realmConfiguration: RealmConfigu
|
|||||||
|
|
||||||
override fun onActive() {
|
override fun onActive() {
|
||||||
val realm = Realm.getInstance(realmConfiguration)
|
val realm = Realm.getInstance(realmConfiguration)
|
||||||
val results = query.invoke(realm).findAll()
|
val results = query.invoke(realm).findAllAsync()
|
||||||
value = results
|
|
||||||
results.addChangeListener(listener)
|
results.addChangeListener(listener)
|
||||||
this.realm = realm
|
this.realm = realm
|
||||||
this.results = results
|
this.results = results
|
||||||
|
@ -18,28 +18,17 @@ package im.vector.matrix.android.internal.database.helper
|
|||||||
|
|
||||||
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.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.room.model.RoomMember
|
|
||||||
import im.vector.matrix.android.api.session.room.send.SendState
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
|
||||||
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.mapper.toEntity
|
import im.vector.matrix.android.internal.database.mapper.toEntity
|
||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
|
import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
|
||||||
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.find
|
import im.vector.matrix.android.internal.database.query.find
|
||||||
import im.vector.matrix.android.internal.database.query.next
|
|
||||||
import im.vector.matrix.android.internal.database.query.prev
|
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
||||||
import io.realm.RealmList
|
|
||||||
import io.realm.RealmQuery
|
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
|
|
||||||
// By default if a chunk is empty we consider it unlinked
|
// By default if a chunk is empty we consider it unlinked
|
||||||
@ -76,10 +65,14 @@ internal fun ChunkEntity.merge(roomId: String,
|
|||||||
eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING)
|
eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING)
|
||||||
}
|
}
|
||||||
val events = eventsToMerge.mapNotNull { it.root?.asDomain() }
|
val events = eventsToMerge.mapNotNull { it.root?.asDomain() }
|
||||||
|
val eventIds = ArrayList<String>()
|
||||||
events.forEach { event ->
|
events.forEach { event ->
|
||||||
add(roomId, event, direction, isUnlinked = isUnlinked)
|
add(roomId, event, direction, isUnlinked = isUnlinked)
|
||||||
|
if (event.eventId != null) {
|
||||||
|
eventIds.add(event.eventId)
|
||||||
}
|
}
|
||||||
updateSenderDataFor(roomId, isUnlinked, events)
|
}
|
||||||
|
updateSenderDataFor(eventIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun ChunkEntity.addAll(roomId: String,
|
internal fun ChunkEntity.addAll(roomId: String,
|
||||||
@ -89,30 +82,20 @@ internal fun ChunkEntity.addAll(roomId: String,
|
|||||||
// Set to true for Event retrieved from a Permalink (i.e. not linked to live Chunk)
|
// Set to true for Event retrieved from a Permalink (i.e. not linked to live Chunk)
|
||||||
isUnlinked: Boolean = false) {
|
isUnlinked: Boolean = false) {
|
||||||
assertIsManaged()
|
assertIsManaged()
|
||||||
|
val eventIds = ArrayList<String>()
|
||||||
events.forEach { event ->
|
events.forEach { event ->
|
||||||
add(roomId, event, direction, stateIndexOffset, isUnlinked)
|
add(roomId, event, direction, stateIndexOffset, isUnlinked)
|
||||||
|
if (event.eventId != null) {
|
||||||
|
eventIds.add(event.eventId)
|
||||||
}
|
}
|
||||||
updateSenderDataFor(roomId, isUnlinked, events)
|
}
|
||||||
|
updateSenderDataFor(eventIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ChunkEntity.updateSenderDataFor(roomId: String, isUnlinked: Boolean, events: List<Event>) {
|
internal fun ChunkEntity.updateSenderDataFor(eventIds: List<String>) {
|
||||||
for (event in events) {
|
for (eventId in eventIds) {
|
||||||
val eventId = event.eventId ?: continue
|
|
||||||
val timelineEventEntity = timelineEvents.find(eventId) ?: continue
|
val timelineEventEntity = timelineEvents.find(eventId) ?: continue
|
||||||
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() ?: continue
|
timelineEventEntity.updateSenderData()
|
||||||
val stateIndex = timelineEventEntity.root?.stateIndex ?: continue
|
|
||||||
val senderId = timelineEventEntity.root?.sender ?: continue
|
|
||||||
|
|
||||||
val senderRoomMemberContent = when {
|
|
||||||
stateIndex <= 0 -> timelineEvents.build(senderId, isUnlinked).next(from = stateIndex)?.root?.prevContent
|
|
||||||
else -> timelineEvents.build(senderId, isUnlinked).prev(since = stateIndex)?.root?.content
|
|
||||||
}
|
|
||||||
val fallbackContent = senderRoomMemberContent
|
|
||||||
?: roomEntity.untimelinedStateEvents.build(senderId).prev(since = stateIndex)?.content
|
|
||||||
val senderRoomMember: RoomMember? = ContentMapper.map(fallbackContent).toModel()
|
|
||||||
timelineEventEntity.senderAvatar = senderRoomMember?.avatarUrl
|
|
||||||
timelineEventEntity.senderName = senderRoomMember?.displayName
|
|
||||||
timelineEventEntity.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(senderRoomMember?.displayName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,19 +144,6 @@ private fun ChunkEntity.add(roomId: String,
|
|||||||
timelineEvents.add(position, eventEntity)
|
timelineEvents.add(position, eventEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RealmList<TimelineEventEntity>.build(sender: String, isUnlinked: Boolean): RealmQuery<TimelineEventEntity> {
|
|
||||||
return where()
|
|
||||||
.equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, sender)
|
|
||||||
.equalTo(TimelineEventEntityFields.ROOT.TYPE, EventType.STATE_ROOM_MEMBER)
|
|
||||||
.equalTo(TimelineEventEntityFields.ROOT.IS_UNLINKED, isUnlinked)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun RealmList<EventEntity>.build(sender: String): RealmQuery<EventEntity> {
|
|
||||||
return where()
|
|
||||||
.equalTo(EventEntityFields.STATE_KEY, sender)
|
|
||||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun ChunkEntity.lastDisplayIndex(direction: PaginationDirection, defaultValue: Int = 0): Int {
|
internal fun ChunkEntity.lastDisplayIndex(direction: PaginationDirection, defaultValue: Int = 0): Int {
|
||||||
return when (direction) {
|
return when (direction) {
|
||||||
PaginationDirection.FORWARDS -> forwardsDisplayIndex
|
PaginationDirection.FORWARDS -> forwardsDisplayIndex
|
||||||
|
@ -72,6 +72,7 @@ internal fun RoomEntity.addSendingEvent(event: Event) {
|
|||||||
it.senderName = myUser?.displayName
|
it.senderName = myUser?.displayName
|
||||||
it.senderAvatar = myUser?.avatarUrl
|
it.senderAvatar = myUser?.avatarUrl
|
||||||
it.isUniqueDisplayName = roomMembers.isUniqueDisplayName(myUser?.displayName)
|
it.isUniqueDisplayName = roomMembers.isUniqueDisplayName(myUser?.displayName)
|
||||||
|
it.senderMembershipEvent = roomMembers.queryRoomMemberEvent(senderId).findFirst()
|
||||||
}
|
}
|
||||||
sendingTimelineEvents.add(0, timelineEventEntity)
|
sendingTimelineEvents.add(0, timelineEventEntity)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.matrix.android.internal.database.helper
|
||||||
|
|
||||||
|
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.room.model.RoomMember
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||||
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields
|
||||||
|
import im.vector.matrix.android.internal.database.query.next
|
||||||
|
import im.vector.matrix.android.internal.database.query.prev
|
||||||
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.extensions.assertIsManaged
|
||||||
|
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
|
||||||
|
import io.realm.RealmList
|
||||||
|
import io.realm.RealmQuery
|
||||||
|
|
||||||
|
internal fun TimelineEventEntity.updateSenderData() {
|
||||||
|
assertIsManaged()
|
||||||
|
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() ?: return
|
||||||
|
val stateIndex = root?.stateIndex ?: return
|
||||||
|
val senderId = root?.sender ?: return
|
||||||
|
val chunkEntity = chunk?.firstOrNull() ?: return
|
||||||
|
val isUnlinked = chunkEntity.isUnlinked()
|
||||||
|
var senderMembershipEvent: EventEntity?
|
||||||
|
var senderRoomMemberContent: String?
|
||||||
|
when {
|
||||||
|
stateIndex <= 0 -> {
|
||||||
|
senderMembershipEvent = chunkEntity.timelineEvents.buildQuery(senderId, isUnlinked).next(from = stateIndex)?.root
|
||||||
|
senderRoomMemberContent = senderMembershipEvent?.prevContent
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
senderMembershipEvent = chunkEntity.timelineEvents.buildQuery(senderId, isUnlinked).prev(since = stateIndex)?.root
|
||||||
|
senderRoomMemberContent = senderMembershipEvent?.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We fallback to untimelinedStateEvents if we can't find membership events in timeline
|
||||||
|
if (senderMembershipEvent == null) {
|
||||||
|
senderMembershipEvent = roomEntity.untimelinedStateEvents
|
||||||
|
.where()
|
||||||
|
.equalTo(EventEntityFields.STATE_KEY, senderId)
|
||||||
|
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
|
||||||
|
.prev(since = stateIndex)
|
||||||
|
senderRoomMemberContent = senderMembershipEvent?.content
|
||||||
|
}
|
||||||
|
val senderRoomMember: RoomMember? = ContentMapper.map(senderRoomMemberContent).toModel()
|
||||||
|
this.senderAvatar = senderRoomMember?.avatarUrl
|
||||||
|
this.senderName = senderRoomMember?.displayName
|
||||||
|
this.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(senderRoomMember?.displayName)
|
||||||
|
this.senderMembershipEvent = senderMembershipEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RealmList<TimelineEventEntity>.buildQuery(sender: String, isUnlinked: Boolean): RealmQuery<TimelineEventEntity> {
|
||||||
|
return where()
|
||||||
|
.equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, sender)
|
||||||
|
.equalTo(TimelineEventEntityFields.ROOT.TYPE, EventType.STATE_ROOM_MEMBER)
|
||||||
|
.equalTo(TimelineEventEntityFields.ROOT.IS_UNLINKED, isUnlinked)
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ internal class RoomSummaryMapper @Inject constructor(
|
|||||||
val cryptoService: CryptoService
|
val cryptoService: CryptoService
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun map(roomSummaryEntity: RoomSummaryEntity, getLatestEvent: Boolean = false): RoomSummary {
|
fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary {
|
||||||
val tags = roomSummaryEntity.tags.map {
|
val tags = roomSummaryEntity.tags.map {
|
||||||
RoomTag(it.tagName, it.tagOrder)
|
RoomTag(it.tagName, it.tagOrder)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,8 @@ internal open class TimelineEventEntity(@PrimaryKey var localId: String = UUID.r
|
|||||||
var annotations: EventAnnotationsSummaryEntity? = null,
|
var annotations: EventAnnotationsSummaryEntity? = null,
|
||||||
var senderName: String? = null,
|
var senderName: String? = null,
|
||||||
var isUniqueDisplayName: Boolean = false,
|
var isUniqueDisplayName: Boolean = false,
|
||||||
var senderAvatar: String? = null
|
var senderAvatar: String? = null,
|
||||||
|
var senderMembershipEvent: EventEntity? = null
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
||||||
@LinkingObjects("timelineEvents")
|
@LinkingObjects("timelineEvents")
|
||||||
|
@ -54,6 +54,12 @@ internal fun TimelineEventEntity.Companion.where(realm: Realm,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun TimelineEventEntity.Companion.findWithSenderMembershipEvent(realm: Realm, senderMembershipEventId: String): List<TimelineEventEntity> {
|
||||||
|
return realm.where<TimelineEventEntity>()
|
||||||
|
.equalTo(TimelineEventEntityFields.SENDER_MEMBERSHIP_EVENT.EVENT_ID, senderMembershipEventId)
|
||||||
|
.findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun TimelineEventEntity.Companion.latestEvent(realm: Realm,
|
internal fun TimelineEventEntity.Companion.latestEvent(realm: Realm,
|
||||||
roomId: String,
|
roomId: String,
|
||||||
|
@ -33,8 +33,6 @@ import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper
|
|||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
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.model.RoomSummaryEntityFields
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.util.fetchCopied
|
|
||||||
import im.vector.matrix.android.internal.util.fetchCopyMap
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class DefaultRoom @Inject constructor(override val roomId: String,
|
internal class DefaultRoom @Inject constructor(override val roomId: String,
|
||||||
@ -55,12 +53,12 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||||||
RelationService by relationService,
|
RelationService by relationService,
|
||||||
MembershipService by roomMembersService {
|
MembershipService by roomMembersService {
|
||||||
|
|
||||||
override fun liveRoomSummary(fetchLastEvent: Boolean): LiveData<RoomSummary> {
|
override fun liveRoomSummary(): LiveData<RoomSummary> {
|
||||||
val liveRealmData = RealmLiveData<RoomSummaryEntity>(monarchy.realmConfiguration) { realm ->
|
val liveRealmData = RealmLiveData<RoomSummaryEntity>(monarchy.realmConfiguration) { realm ->
|
||||||
RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
|
RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
|
||||||
}
|
}
|
||||||
return Transformations.map(liveRealmData) { results ->
|
return Transformations.map(liveRealmData) { results ->
|
||||||
val roomSummaries = results.map { roomSummaryMapper.map(it, fetchLastEvent) }
|
val roomSummaries = results.map { roomSummaryMapper.map(it) }
|
||||||
|
|
||||||
if (roomSummaries.isEmpty()) {
|
if (roomSummaries.isEmpty()) {
|
||||||
// Create a dummy RoomSummary to avoid Crash during Sign Out or clear cache
|
// Create a dummy RoomSummary to avoid Crash during Sign Out or clear cache
|
||||||
@ -71,10 +69,10 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun roomSummary(fetchLastEvent: Boolean): RoomSummary? {
|
override fun roomSummary(): RoomSummary? {
|
||||||
return monarchy.fetchAllMappedSync(
|
return monarchy.fetchAllMappedSync(
|
||||||
{ realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
|
{ realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
|
||||||
{ roomSummaryMapper.map(it, fetchLastEvent) }
|
{ roomSummaryMapper.map(it) }
|
||||||
).firstOrNull()
|
).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +52,10 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
|
|||||||
return roomFactory.create(roomId)
|
return roomFactory.create(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun liveRoomSummaries(fetchLastEvents: Boolean): LiveData<List<RoomSummary>> {
|
override fun liveRoomSummaries(): LiveData<List<RoomSummary>> {
|
||||||
return monarchy.findAllMappedWithChanges(
|
return monarchy.findAllMappedWithChanges(
|
||||||
{ realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
|
{ realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
|
||||||
{ roomSummaryMapper.map(it, fetchLastEvents) }
|
{ roomSummaryMapper.map(it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,15 +20,16 @@ import arrow.core.Try
|
|||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.internal.database.helper.addStateEvents
|
import im.vector.matrix.android.internal.database.helper.addStateEvents
|
||||||
|
import im.vector.matrix.android.internal.database.helper.updateSenderData
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
|
||||||
import im.vector.matrix.android.internal.session.room.RoomAPI
|
import im.vector.matrix.android.internal.session.room.RoomAPI
|
||||||
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
|
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
import im.vector.matrix.android.internal.util.tryTransactionSync
|
import im.vector.matrix.android.internal.util.tryTransactionSync
|
||||||
|
import io.realm.Realm
|
||||||
import io.realm.kotlin.createObject
|
import io.realm.kotlin.createObject
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -68,20 +69,20 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(private val roomAP
|
|||||||
|
|
||||||
val roomMembers = RoomMembers(realm, roomId).getLoaded()
|
val roomMembers = RoomMembers(realm, roomId).getLoaded()
|
||||||
val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) }
|
val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) }
|
||||||
|
|
||||||
roomEntity.addStateEvents(eventsToInsert)
|
roomEntity.addStateEvents(eventsToInsert)
|
||||||
|
roomEntity.chunks.flatMap { it.timelineEvents }.forEach {
|
||||||
|
it.updateSenderData()
|
||||||
|
}
|
||||||
roomEntity.areAllMembersLoaded = true
|
roomEntity.areAllMembersLoaded = true
|
||||||
|
|
||||||
roomSummaryUpdater.update(realm, roomId)
|
roomSummaryUpdater.update(realm, roomId)
|
||||||
}
|
}
|
||||||
.map { response }
|
.map { response }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areAllMembersAlreadyLoaded(roomId: String): Boolean {
|
private fun areAllMembersAlreadyLoaded(roomId: String): Boolean {
|
||||||
return monarchy
|
return Realm.getInstance(monarchy.realmConfiguration).use {
|
||||||
.fetchAllCopiedSync { RoomEntity.where(it, roomId) }
|
RoomEntity.where(it, roomId).findFirst()?.areAllMembersLoaded ?: false
|
||||||
.firstOrNull()
|
}
|
||||||
?.areAllMembersLoaded ?: false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -29,6 +29,10 @@ import io.realm.Realm
|
|||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is an helper around STATE_ROOM_MEMBER events.
|
||||||
|
* It allows to get the live membership of a user.
|
||||||
|
*/
|
||||||
internal class RoomMembers(private val realm: Realm,
|
internal class RoomMembers(private val realm: Realm,
|
||||||
private val roomId: String
|
private val roomId: String
|
||||||
) {
|
) {
|
||||||
|
@ -21,12 +21,14 @@ import im.vector.matrix.android.api.session.events.model.Event
|
|||||||
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.UnsignedData
|
import im.vector.matrix.android.api.session.events.model.UnsignedData
|
||||||
import im.vector.matrix.android.api.session.room.send.SendState
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
|
import im.vector.matrix.android.internal.database.helper.updateSenderData
|
||||||
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
import im.vector.matrix.android.internal.database.mapper.ContentMapper
|
||||||
import im.vector.matrix.android.internal.database.mapper.EventMapper
|
import im.vector.matrix.android.internal.database.mapper.EventMapper
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.query.findWithSenderMembershipEvent
|
||||||
import im.vector.matrix.android.internal.database.query.where
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import im.vector.matrix.android.internal.session.SessionScope
|
|
||||||
import im.vector.matrix.android.internal.task.Task
|
import im.vector.matrix.android.internal.task.Task
|
||||||
import im.vector.matrix.android.internal.util.tryTransactionSync
|
import im.vector.matrix.android.internal.util.tryTransactionSync
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
@ -94,6 +96,12 @@ internal class DefaultPruneEventTask @Inject constructor(private val monarchy: M
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (eventToPrune.type == EventType.STATE_ROOM_MEMBER) {
|
||||||
|
val timelineEventsToUpdate = TimelineEventEntity.findWithSenderMembershipEvent(realm, eventToPrune.eventId)
|
||||||
|
for (timelineEvent in timelineEventsToUpdate) {
|
||||||
|
timelineEvent.updateSenderData()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ class PushrulesConditionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun liveRoomSummaries(fetchLastEvents: Boolean): LiveData<List<RoomSummary>> {
|
override fun liveRoomSummaries(): LiveData<List<RoomSummary>> {
|
||||||
return MutableLiveData()
|
return MutableLiveData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,11 +194,11 @@ class PushrulesConditionTest {
|
|||||||
return _numberOfJoinedMembers
|
return _numberOfJoinedMembers
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun liveRoomSummary(fetchLastEvent: Boolean): LiveData<RoomSummary> {
|
override fun liveRoomSummary(): LiveData<RoomSummary> {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun roomSummary(fetchLastEvent: Boolean): RoomSummary? {
|
override fun roomSummary(): RoomSummary? {
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ class HomeActivityViewModel @AssistedInject constructor(@Assisted initialState:
|
|||||||
private fun observeRoomAndGroup() {
|
private fun observeRoomAndGroup() {
|
||||||
Observable
|
Observable
|
||||||
.combineLatest<List<RoomSummary>, Option<GroupSummary>, List<RoomSummary>>(
|
.combineLatest<List<RoomSummary>, Option<GroupSummary>, List<RoomSummary>>(
|
||||||
session.rx().liveRoomSummaries(fetchLastEvents = true).throttleLast(300, TimeUnit.MILLISECONDS),
|
session.rx().liveRoomSummaries().throttleLast(300, TimeUnit.MILLISECONDS),
|
||||||
selectedGroupStore.observe(),
|
selectedGroupStore.observe(),
|
||||||
BiFunction { rooms, selectedGroupOption ->
|
BiFunction { rooms, selectedGroupOption ->
|
||||||
val selectedGroup = selectedGroupOption.orNull()
|
val selectedGroup = selectedGroupOption.orNull()
|
||||||
|
@ -500,17 +500,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRoomSummary() {
|
private fun observeRoomSummary() {
|
||||||
room.rx().liveRoomSummary(false)
|
room.rx().liveRoomSummary()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.flatMap {
|
|
||||||
if (it.membership != Membership.INVITE || it.latestEvent != null) {
|
|
||||||
// Not an invitation, or already fetching last event
|
|
||||||
Observable.just(it)
|
|
||||||
} else {
|
|
||||||
// We need the last event
|
|
||||||
room.rx().liveRoomSummary(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.execute { async ->
|
.execute { async ->
|
||||||
copy(
|
copy(
|
||||||
asyncRoomSummary = async,
|
asyncRoomSummary = async,
|
||||||
|
@ -86,7 +86,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState:
|
|||||||
private fun observeJoinedRooms() {
|
private fun observeJoinedRooms() {
|
||||||
session
|
session
|
||||||
.rx()
|
.rx()
|
||||||
.liveRoomSummaries(fetchLastEvents = false)
|
.liveRoomSummaries()
|
||||||
.subscribe { list ->
|
.subscribe { list ->
|
||||||
val joinedRoomIds = list
|
val joinedRoomIds = list
|
||||||
// Keep only joined room
|
// Keep only joined room
|
||||||
|
@ -54,7 +54,7 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted initialState: R
|
|||||||
private fun observeJoinedRooms() {
|
private fun observeJoinedRooms() {
|
||||||
session
|
session
|
||||||
.rx()
|
.rx()
|
||||||
.liveRoomSummaries(fetchLastEvents = false)
|
.liveRoomSummaries()
|
||||||
.subscribe { list ->
|
.subscribe { list ->
|
||||||
withState { state ->
|
withState { state ->
|
||||||
val isRoomJoined = list
|
val isRoomJoined = list
|
||||||
|
Loading…
Reference in New Issue
Block a user