Refact some more code

This commit is contained in:
ganfra 2020-06-23 21:54:23 +02:00 committed by ganfra
parent 360666a758
commit 95c05f6107
19 changed files with 231 additions and 202 deletions

View File

@ -17,8 +17,8 @@ package im.vector.matrix.android.api.session.room.model
data class EventAnnotationsSummary(
var eventId: String,
var reactionsSummary: List<ReactionAggregatedSummary>,
var editSummary: EditAggregatedSummary?,
var pollResponseSummary: PollResponseAggregatedSummary?,
var reactionsSummary: List<ReactionAggregatedSummary> = emptyList(),
var editSummary: EditAggregatedSummary?= null,
var pollResponseSummary: PollResponseAggregatedSummary? = null,
var referencesAggregatedSummary: ReferencesAggregatedSummary? = null
)

View File

@ -22,7 +22,7 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.SessionLifecycleObserver
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.summary.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.util.createBackgroundHandler

View File

@ -22,8 +22,9 @@ import im.vector.matrix.android.internal.database.model.ReadMarkerEntity
import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
import io.realm.Realm
import io.realm.RealmConfiguration
internal fun isEventRead(monarchy: Monarchy,
internal fun isEventRead(realmConfiguration: RealmConfiguration,
userId: String?,
roomId: String?,
eventId: String?): Boolean {
@ -35,14 +36,14 @@ internal fun isEventRead(monarchy: Monarchy,
}
var isEventRead = false
monarchy.doWithRealm { realm ->
val liveChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: return@doWithRealm
Realm.getInstance(realmConfiguration).use{ realm ->
val liveChunk = ChunkEntity.findLastForwardChunkOfRoom(realm, roomId) ?: return@use
val eventToCheck = liveChunk.timelineEvents.find(eventId)
isEventRead = if (eventToCheck == null || eventToCheck.root?.sender == userId) {
true
} else {
val readReceipt = ReadReceiptEntity.where(realm, roomId, userId).findFirst()
?: return@doWithRealm
?: return@use
val readReceiptIndex = liveChunk.timelineEvents.find(readReceipt.eventId)?.displayIndex
?: Int.MIN_VALUE
val eventToCheckIndex = eventToCheck.displayIndex
@ -54,13 +55,13 @@ internal fun isEventRead(monarchy: Monarchy,
return isEventRead
}
internal fun isReadMarkerMoreRecent(monarchy: Monarchy,
internal fun isReadMarkerMoreRecent(realmConfiguration: RealmConfiguration,
roomId: String?,
eventId: String?): Boolean {
if (roomId.isNullOrBlank() || eventId.isNullOrBlank()) {
return false
}
return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
return Realm.getInstance(realmConfiguration).use { realm ->
val eventToCheck = TimelineEventEntity.where(realm, roomId = roomId, eventId = eventId).findFirst()
val eventToCheckChunk = eventToCheck?.chunk?.firstOrNull()
val readMarker = ReadMarkerEntity.where(realm, roomId).findFirst() ?: return false

View File

@ -37,15 +37,12 @@ import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesSer
import im.vector.matrix.android.api.session.securestorage.SecureStorageService
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageService
import im.vector.matrix.android.api.session.typing.TypingUsersTracker
import im.vector.matrix.android.api.session.widgets.WidgetURLFormatter
import im.vector.matrix.android.internal.crypto.crosssigning.ShieldTrustUpdater
import im.vector.matrix.android.internal.crypto.secrets.DefaultSharedSecretStorageService
import im.vector.matrix.android.internal.crypto.verification.VerificationMessageLiveObserver
import im.vector.matrix.android.internal.database.LiveEntityObserver
import im.vector.matrix.android.internal.database.SessionRealmConfigurationFactory
import im.vector.matrix.android.internal.di.Authenticated
import im.vector.matrix.android.internal.di.DeviceId
import im.vector.matrix.android.internal.di.InMemorySessionDatabase
import im.vector.matrix.android.internal.di.SessionCacheDirectory
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.SessionFilesDirectory
@ -284,7 +281,6 @@ internal abstract class SessionModule {
@IntoSet
abstract fun bindIdentityService(observer: DefaultIdentityService): SessionLifecycleObserver
@Binds
abstract fun bindInitialSyncProgressService(service: DefaultInitialSyncProgressService): InitialSyncProgressService

View File

@ -17,8 +17,6 @@
package im.vector.matrix.android.internal.session.room
import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.crypto.CryptoService
import im.vector.matrix.android.api.session.events.model.EventType
@ -37,22 +35,16 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineService
import im.vector.matrix.android.api.session.room.typing.TypingService
import im.vector.matrix.android.api.session.room.uploads.UploadsService
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.api.util.toOptional
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
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.RoomSummaryEntityFields
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.room.state.SendStateTask
import im.vector.matrix.android.internal.session.room.summary.RoomSummaryDataSource
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import java.security.InvalidParameterException
import javax.inject.Inject
internal class DefaultRoom @Inject constructor(override val roomId: String,
@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val roomSummaryDataSource: RoomSummaryDataSource,
private val timelineService: TimelineService,
private val sendService: SendService,
private val draftService: DraftService,
@ -83,20 +75,11 @@ internal class DefaultRoom @Inject constructor(override val roomId: String,
RoomPushRuleService by roomPushRuleService {
override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> {
val liveData = monarchy.findAllMappedWithChanges(
{ realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
{ roomSummaryMapper.map(it) }
)
return Transformations.map(liveData) { results ->
results.firstOrNull().toOptional()
}
return roomSummaryDataSource.getRoomSummaryLive(roomId)
}
override fun roomSummary(): RoomSummary? {
return monarchy.fetchAllMappedSync(
{ realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
{ roomSummaryMapper.map(it) }
).firstOrNull()
return roomSummaryDataSource.getRoomSummary(roomId)
}
override fun isEncrypted(): Boolean {

View File

@ -23,38 +23,29 @@ import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.VersioningState
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.api.util.Optional
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.RoomSummaryEntityFields
import im.vector.matrix.android.internal.database.query.findByAlias
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.query.process
import im.vector.matrix.android.internal.session.room.alias.GetRoomIdByAliasTask
import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.read.MarkAllRoomsReadTask
import im.vector.matrix.android.internal.session.room.summary.RoomSummaryDataSource
import im.vector.matrix.android.internal.session.user.accountdata.UpdateBreadcrumbsTask
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.fetchCopyMap
import io.realm.Realm
import io.realm.RealmQuery
import javax.inject.Inject
internal class DefaultRoomService @Inject constructor(
@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val createRoomTask: CreateRoomTask,
private val joinRoomTask: JoinRoomTask,
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
private val roomIdByAliasTask: GetRoomIdByAliasTask,
private val roomGetter: RoomGetter,
private val roomSummaryDataSource: RoomSummaryDataSource,
private val taskExecutor: TaskExecutor
) : RoomService {
@ -75,61 +66,23 @@ internal class DefaultRoomService @Inject constructor(
}
override fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {
return monarchy
.fetchCopyMap({
if (roomIdOrAlias.startsWith("!")) {
// It's a roomId
RoomSummaryEntity.where(it, roomId = roomIdOrAlias).findFirst()
} else {
// Assume it's a room alias
RoomSummaryEntity.findByAlias(it, roomIdOrAlias)
}
}, { entity, _ ->
roomSummaryMapper.map(entity)
})
return roomSummaryDataSource.getRoomSummary(roomIdOrAlias)
}
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
return monarchy.fetchAllMappedSync(
{ roomSummariesQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
return roomSummaryDataSource.getRoomSummaries(queryParams)
}
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{ roomSummariesQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
private fun roomSummariesQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
val query = RoomSummaryEntity.where(realm)
query.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
query.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias)
query.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
query.notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name)
return query
return roomSummaryDataSource.getRoomSummariesLive(queryParams)
}
override fun getBreadcrumbs(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
return monarchy.fetchAllMappedSync(
{ breadcrumbsQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
return roomSummaryDataSource.getBreadcrumbs(queryParams)
}
override fun getBreadcrumbsLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{ breadcrumbsQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
private fun breadcrumbsQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
return roomSummariesQuery(realm, queryParams)
.greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummary.NOT_IN_BREADCRUMBS)
.sort(RoomSummaryEntityFields.BREADCRUMBS_INDEX)
return roomSummaryDataSource.getBreadcrumbsLive(queryParams)
}
override fun onRoomDisplayed(roomId: String): Cancelable {

View File

@ -16,7 +16,6 @@
package im.vector.matrix.android.internal.session.room
import com.zhuinden.monarchy.Monarchy
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.RoomAvatarContent
@ -24,36 +23,34 @@ import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.UserId
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
import io.realm.Realm
import javax.inject.Inject
internal class RoomAvatarResolver @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
@UserId private val userId: String) {
internal class RoomAvatarResolver @Inject constructor(@UserId private val userId: String) {
/**
* Compute the room avatar url
* @param realm: the current instance of realm
* @param roomId the roomId of the room to resolve avatar
* @return the room avatar url, can be a fallback to a room member avatar or null
*/
fun resolve(roomId: String): String? {
var res: String? = null
monarchy.doWithRealm { realm ->
val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_AVATAR, stateKey = "")?.root
res = ContentMapper.map(roomName?.content).toModel<RoomAvatarContent>()?.avatarUrl
if (!res.isNullOrEmpty()) {
return@doWithRealm
}
val roomMembers = RoomMemberHelper(realm, roomId)
val members = roomMembers.queryActiveRoomMembersEvent().findAll()
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
if (members.size == 1) {
res = members.firstOrNull()?.avatarUrl
} else if (members.size == 2) {
val firstOtherMember = members.where().notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId).findFirst()
res = firstOtherMember?.avatarUrl
}
fun resolve(realm: Realm, roomId: String): String? {
var res: String?
val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_AVATAR, stateKey = "")?.root
res = ContentMapper.map(roomName?.content).toModel<RoomAvatarContent>()?.avatarUrl
if (!res.isNullOrEmpty()) {
return res
}
val roomMembers = RoomMemberHelper(realm, roomId)
val members = roomMembers.queryActiveRoomMembersEvent().findAll()
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
if (members.size == 1) {
res = members.firstOrNull()?.avatarUrl
} else if (members.size == 2) {
val firstOtherMember = members.where().notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId).findFirst()
res = firstOtherMember?.avatarUrl
}
return res
}

View File

@ -16,11 +16,8 @@
package im.vector.matrix.android.internal.session.room
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.crypto.CryptoService
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.session.room.draft.DefaultDraftService
import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService
@ -31,6 +28,7 @@ import im.vector.matrix.android.internal.session.room.reporting.DefaultReporting
import im.vector.matrix.android.internal.session.room.send.DefaultSendService
import im.vector.matrix.android.internal.session.room.state.DefaultStateService
import im.vector.matrix.android.internal.session.room.state.SendStateTask
import im.vector.matrix.android.internal.session.room.summary.RoomSummaryDataSource
import im.vector.matrix.android.internal.session.room.tags.DefaultTagsService
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimelineService
import im.vector.matrix.android.internal.session.room.typing.DefaultTypingService
@ -43,9 +41,8 @@ internal interface RoomFactory {
}
@SessionScope
internal class DefaultRoomFactory @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val cryptoService: CryptoService,
internal class DefaultRoomFactory @Inject constructor(private val cryptoService: CryptoService,
private val roomSummaryDataSource: RoomSummaryDataSource,
private val timelineServiceFactory: DefaultTimelineService.Factory,
private val sendServiceFactory: DefaultSendService.Factory,
private val draftServiceFactory: DefaultDraftService.Factory,
@ -65,8 +62,7 @@ internal class DefaultRoomFactory @Inject constructor(@SessionDatabase private v
override fun create(roomId: String): Room {
return DefaultRoom(
roomId = roomId,
monarchy = monarchy,
roomSummaryMapper = roomSummaryMapper,
roomSummaryDataSource = roomSummaryDataSource,
timelineService = timelineServiceFactory.create(roomId),
sendService = sendServiceFactory.create(roomId),
draftService = draftServiceFactory.create(roomId),

View File

@ -28,7 +28,7 @@ import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.network.executeRequest
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.summary.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.util.awaitTransaction

View File

@ -17,7 +17,6 @@
package im.vector.matrix.android.internal.session.room.membership
import android.content.Context
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.R
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
@ -33,96 +32,92 @@ import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityF
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.UserId
import io.realm.Realm
import javax.inject.Inject
/**
* This class computes room display name
*/
internal class RoomDisplayNameResolver @Inject constructor(private val context: Context,
@SessionDatabase private val monarchy: Monarchy,
@UserId private val userId: String
) {
/**
* Compute the room display name
*
* @param realm: the current instance of realm
* @param roomId: the roomId to resolve the name of.
* @return the room display name
*/
fun resolve(roomId: String): CharSequence {
fun resolve(realm: Realm, roomId: String): CharSequence {
// this algorithm is the one defined in
// https://github.com/matrix-org/matrix-js-sdk/blob/develop/lib/models/room.js#L617
// calculateRoomName(room, userId)
// For Lazy Loaded room, see algorithm here:
// https://docs.google.com/document/d/11i14UI1cUz-OJ0knD5BFu7fmT6Fo327zvMYqfSAR7xs/edit#heading=h.qif6pkqyjgzn
var name: CharSequence? = null
monarchy.doWithRealm { realm ->
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()
val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_NAME, stateKey = "")?.root
name = ContentMapper.map(roomName?.content).toModel<RoomNameContent>()?.name
if (!name.isNullOrEmpty()) {
return@doWithRealm
var name: CharSequence?
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()
val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_NAME, stateKey = "")?.root
name = ContentMapper.map(roomName?.content).toModel<RoomNameContent>()?.name
if (!name.isNullOrEmpty()) {
return name
}
val canonicalAlias = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_CANONICAL_ALIAS, stateKey = "")?.root
name = ContentMapper.map(canonicalAlias?.content).toModel<RoomCanonicalAliasContent>()?.canonicalAlias
if (!name.isNullOrEmpty()) {
return name
}
val aliases = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_ALIASES, stateKey = "")?.root
name = ContentMapper.map(aliases?.content).toModel<RoomAliasesContent>()?.aliases?.firstOrNull()
if (!name.isNullOrEmpty()) {
return name
}
val roomMembers = RoomMemberHelper(realm, roomId)
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
if (roomEntity?.membership == Membership.INVITE) {
val inviteMeEvent = roomMembers.getLastStateEvent(userId)
val inviterId = inviteMeEvent?.sender
name = if (inviterId != null) {
activeMembers.where()
.equalTo(RoomMemberSummaryEntityFields.USER_ID, inviterId)
.findFirst()
?.displayName
} else {
context.getString(R.string.room_displayname_room_invite)
}
val canonicalAlias = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_CANONICAL_ALIAS, stateKey = "")?.root
name = ContentMapper.map(canonicalAlias?.content).toModel<RoomCanonicalAliasContent>()?.canonicalAlias
if (!name.isNullOrEmpty()) {
return@doWithRealm
}
val aliases = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_ALIASES, stateKey = "")?.root
name = ContentMapper.map(aliases?.content).toModel<RoomAliasesContent>()?.aliases?.firstOrNull()
if (!name.isNullOrEmpty()) {
return@doWithRealm
}
val roomMembers = RoomMemberHelper(realm, roomId)
val activeMembers = roomMembers.queryActiveRoomMembersEvent().findAll()
if (roomEntity?.membership == Membership.INVITE) {
val inviteMeEvent = roomMembers.getLastStateEvent(userId)
val inviterId = inviteMeEvent?.sender
name = if (inviterId != null) {
activeMembers.where()
.equalTo(RoomMemberSummaryEntityFields.USER_ID, inviterId)
.findFirst()
?.displayName
} else {
context.getString(R.string.room_displayname_room_invite)
}
} else if (roomEntity?.membership == Membership.JOIN) {
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
val otherMembersSubset: List<RoomMemberSummaryEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
roomSummary.heroes.mapNotNull { userId ->
roomMembers.getLastRoomMember(userId)?.takeIf {
it.membership == Membership.INVITE || it.membership == Membership.JOIN
}
} else if (roomEntity?.membership == Membership.JOIN) {
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
val otherMembersSubset: List<RoomMemberSummaryEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
roomSummary.heroes.mapNotNull { userId ->
roomMembers.getLastRoomMember(userId)?.takeIf {
it.membership == Membership.INVITE || it.membership == Membership.JOIN
}
} else {
activeMembers.where()
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
.limit(3)
.findAll()
.createSnapshot()
}
val otherMembersCount = otherMembersSubset.count()
name = when (otherMembersCount) {
0 -> context.getString(R.string.room_displayname_empty_room)
1 -> resolveRoomMemberName(otherMembersSubset[0], roomMembers)
2 -> context.getString(R.string.room_displayname_two_members,
resolveRoomMemberName(otherMembersSubset[0], roomMembers),
resolveRoomMemberName(otherMembersSubset[1], roomMembers)
)
else -> context.resources.getQuantityString(R.plurals.room_displayname_three_and_more_members,
roomMembers.getNumberOfJoinedMembers() - 1,
resolveRoomMemberName(otherMembersSubset[0], roomMembers),
roomMembers.getNumberOfJoinedMembers() - 1)
}
} else {
activeMembers.where()
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
.limit(3)
.findAll()
.createSnapshot()
}
val otherMembersCount = otherMembersSubset.count()
name = when (otherMembersCount) {
0 -> context.getString(R.string.room_displayname_empty_room)
1 -> resolveRoomMemberName(otherMembersSubset[0], roomMembers)
2 -> context.getString(R.string.room_displayname_two_members,
resolveRoomMemberName(otherMembersSubset[0], roomMembers),
resolveRoomMemberName(otherMembersSubset[1], roomMembers)
)
else -> context.resources.getQuantityString(R.plurals.room_displayname_three_and_more_members,
roomMembers.getNumberOfJoinedMembers() - 1,
resolveRoomMemberName(otherMembersSubset[0], roomMembers),
roomMembers.getNumberOfJoinedMembers() - 1)
}
return@doWithRealm
}
return name ?: roomId
}

View File

@ -83,7 +83,7 @@ internal class DefaultReadService @AssistedInject constructor(
}
override fun isEventRead(eventId: String): Boolean {
return isEventRead(monarchy, userId, roomId, eventId)
return isEventRead(monarchy.realmConfiguration, userId, roomId, eventId)
}
override fun getReadMarkerLive(): LiveData<Optional<String>> {

View File

@ -75,7 +75,7 @@ internal class DefaultSetReadMarkersTask @Inject constructor(
} else {
params.readReceiptEventId
}
if (fullyReadEventId != null && !isReadMarkerMoreRecent(monarchy, params.roomId, fullyReadEventId)) {
if (fullyReadEventId != null && !isReadMarkerMoreRecent(monarchy.realmConfiguration, params.roomId, fullyReadEventId)) {
if (LocalEcho.isLocalEchoId(fullyReadEventId)) {
Timber.w("Can't set read marker for local event $fullyReadEventId")
} else {
@ -83,7 +83,7 @@ internal class DefaultSetReadMarkersTask @Inject constructor(
}
}
if (readReceiptEventId != null
&& !isEventRead(monarchy, userId, params.roomId, readReceiptEventId)) {
&& !isEventRead(monarchy.realmConfiguration, userId, params.roomId, readReceiptEventId)) {
if (LocalEcho.isLocalEchoId(readReceiptEventId)) {
Timber.w("Can't set read receipt for local event $readReceiptEventId")
} else {

View File

@ -34,7 +34,7 @@ import im.vector.matrix.android.internal.database.model.TimelineEventEntity
import im.vector.matrix.android.internal.database.query.findAllInRoomWithSendStates
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.summary.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimeline
import im.vector.matrix.android.internal.util.awaitTransaction

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 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.matrix.android.internal.session.room.summary
import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.VersioningState
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.api.util.toOptional
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.RoomSummaryEntityFields
import im.vector.matrix.android.internal.database.query.findByAlias
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.query.process
import im.vector.matrix.android.internal.util.fetchCopyMap
import io.realm.Realm
import io.realm.RealmQuery
import javax.inject.Inject
internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper) {
fun getRoomSummary(roomIdOrAlias: String): RoomSummary? {
return monarchy
.fetchCopyMap({
if (roomIdOrAlias.startsWith("!")) {
// It's a roomId
RoomSummaryEntity.where(it, roomId = roomIdOrAlias).findFirst()
} else {
// Assume it's a room alias
RoomSummaryEntity.findByAlias(it, roomIdOrAlias)
}
}, { entity, _ ->
roomSummaryMapper.map(entity)
})
}
fun getRoomSummaryLive(roomId: String): LiveData<Optional<RoomSummary>>{
val liveData = monarchy.findAllMappedWithChanges(
{ realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) },
{ roomSummaryMapper.map(it) }
)
return Transformations.map(liveData) { results ->
results.firstOrNull().toOptional()
}
}
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
return monarchy.fetchAllMappedSync(
{ roomSummariesQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{ roomSummariesQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
fun getBreadcrumbs(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
return monarchy.fetchAllMappedSync(
{ breadcrumbsQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
fun getBreadcrumbsLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
return monarchy.findAllMappedWithChanges(
{ breadcrumbsQuery(it, queryParams) },
{ roomSummaryMapper.map(it) }
)
}
private fun breadcrumbsQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
return roomSummariesQuery(realm, queryParams)
.greaterThan(RoomSummaryEntityFields.BREADCRUMBS_INDEX, RoomSummary.NOT_IN_BREADCRUMBS)
.sort(RoomSummaryEntityFields.BREADCRUMBS_INDEX)
}
private fun roomSummariesQuery(realm: Realm, queryParams: RoomSummaryQueryParams): RealmQuery<RoomSummaryEntity> {
val query = RoomSummaryEntity.where(realm)
query.process(RoomSummaryEntityFields.DISPLAY_NAME, queryParams.displayName)
query.process(RoomSummaryEntityFields.CANONICAL_ALIAS, queryParams.canonicalAlias)
query.process(RoomSummaryEntityFields.MEMBERSHIP_STR, queryParams.memberships)
query.notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name)
return query
}
}

View File

@ -14,9 +14,8 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room
package im.vector.matrix.android.internal.session.room.summary
import com.zhuinden.monarchy.Monarchy
import dagger.Lazy
import im.vector.matrix.android.api.crypto.RoomEncryptionTrustLevel
import im.vector.matrix.android.api.session.events.model.EventType
@ -39,12 +38,11 @@ import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.isEventRead
import im.vector.matrix.android.internal.database.query.latestEvent
import im.vector.matrix.android.internal.database.query.whereType
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.di.UserId
import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
import im.vector.matrix.android.internal.session.room.timeline.TimelineEventDecryptor
import im.vector.matrix.android.internal.session.sync.RoomSyncHandler
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications
import io.realm.Realm
@ -57,8 +55,7 @@ internal class RoomSummaryUpdater @Inject constructor(
private val roomDisplayNameResolver: RoomDisplayNameResolver,
private val roomAvatarResolver: RoomAvatarResolver,
private val timelineEventDecryptor: Lazy<TimelineEventDecryptor>,
private val eventBus: EventBus,
@SessionDatabase private val monarchy: Monarchy) {
private val eventBus: EventBus) {
companion object {
// TODO: maybe allow user of SDK to give that list
@ -121,17 +118,17 @@ internal class RoomSummaryUpdater @Inject constructor(
roomSummaryEntity.hasUnreadMessages = roomSummaryEntity.notificationCount > 0
// avoid this call if we are sure there are unread events
|| !isEventRead(monarchy, userId, roomId, latestPreviewableEvent?.eventId)
|| !isEventRead(realm.configuration, userId, roomId, latestPreviewableEvent?.eventId)
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(roomId).toString()
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(roomId)
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(realm, roomId).toString()
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(realm, roomId)
roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel<RoomTopicContent>()?.topic
roomSummaryEntity.latestPreviewableEvent = latestPreviewableEvent
roomSummaryEntity.canonicalAlias = ContentMapper.map(lastCanonicalAliasEvent?.content).toModel<RoomCanonicalAliasContent>()
?.canonicalAlias
val roomAliases = ContentMapper.map(lastAliasesEvent?.content).toModel<RoomAliasesContent>()?.aliases
.orEmpty()
.orEmpty()
roomSummaryEntity.aliases.clear()
roomSummaryEntity.aliases.addAll(roomAliases)
roomSummaryEntity.flatAliases = roomAliases.joinToString(separator = "|", prefix = "|")

View File

@ -21,8 +21,11 @@ import im.vector.matrix.android.api.extensions.orFalse
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.RelationType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
import im.vector.matrix.android.api.session.room.model.ReactionAggregatedSummary
import im.vector.matrix.android.api.session.room.model.ReadReceipt
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
@ -341,6 +344,7 @@ internal class DefaultTimeline(
listeners.forEach {
it.onNewTimelineEvents(listOf(onLocalEchoCreated.timelineEvent.eventId))
}
Timber.v("On local echo created: $onLocalEchoCreated")
inMemorySendingEvents.add(0, onLocalEchoCreated.timelineEvent)
postSnapshot()
}

View File

@ -40,7 +40,7 @@ import im.vector.matrix.android.internal.database.query.getOrCreate
import im.vector.matrix.android.internal.database.query.latestEvent
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.summary.RoomSummaryUpdater
import im.vector.matrix.android.internal.util.awaitTransaction
import io.realm.Realm
import timber.log.Timber

View File

@ -46,7 +46,7 @@ import im.vector.matrix.android.internal.di.MoshiProvider
import im.vector.matrix.android.internal.di.UserId
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.mapWithProgress
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.summary.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.membership.RoomMemberEventHandler
import im.vector.matrix.android.internal.session.room.read.FullyReadContent
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimeline

View File

@ -69,7 +69,6 @@ internal class SyncResponseHandler @Inject constructor(@SessionDatabase private
}.also {
Timber.v("Finish handling toDevice in $it ms")
}
// Start one big transaction
monarchy.awaitTransaction { realm ->
measureTimeMillis {
@ -104,7 +103,6 @@ internal class SyncResponseHandler @Inject constructor(@SessionDatabase private
}
tokenStore.saveToken(realm, syncResponse.nextBatch)
}
// Everything else we need to do outside the transaction
syncResponse.rooms?.also {
checkPushRules(it, isInitialSync)