User : start handling users. Need to fine a good strategy to process room member events.

This commit is contained in:
ganfra 2019-02-25 21:55:33 +01:00
parent 85b119bdcb
commit 40f1fcab18
10 changed files with 247 additions and 5 deletions

View File

@ -21,12 +21,13 @@ import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.content.ContentUrlResolver
import im.vector.matrix.android.api.session.group.GroupService
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.user.UserService

/**
* This interface defines interactions with a session.
* An instance of a session will be provided by the SDK.
*/
interface Session : RoomService, GroupService {
interface Session : RoomService, GroupService, UserService {

/**
* The params associated to the session

View File

@ -0,0 +1,35 @@
/*
*
* * 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.api.session.user

import im.vector.matrix.android.api.session.user.model.User

/**
* This interface defines methods to get users. It's implemented at the session level.
*/
interface UserService {

/**
* Get a user from a userId
* @param userId the userId to look for.
* @return a user with userId or null
*/
fun getUser(userId: String): User?

}

View File

@ -0,0 +1,29 @@
/*
*
* * 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.api.session.user.model

/**
* Data class which holds information about a user.
* It can be retrieved with [im.vector.matrix.android.api.session.user.UserService]
*/
data class User(
val userId: String,
val displayName: String? = null,
val avatarUrl: String? = null
)

View File

@ -0,0 +1,31 @@
/*
*
* * 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.model

import io.realm.RealmObject
import io.realm.annotations.PrimaryKey

internal open class UserEntity(@PrimaryKey var userId: String = "",
var displayName: String = "",
var avatarUrl: String = ""
) : RealmObject() {

companion object
}

View File

@ -27,8 +27,7 @@ import io.realm.Sort
import io.realm.kotlin.where

internal fun EventEntity.Companion.where(realm: Realm, eventId: String): RealmQuery<EventEntity> {
return realm.where<EventEntity>()
.equalTo(EventEntityFields.EVENT_ID, eventId)
return realm.where<EventEntity>().equalTo(EventEntityFields.EVENT_ID, eventId)
}

internal fun EventEntity.Companion.where(realm: Realm,

View File

@ -0,0 +1,31 @@
/*
*
* * 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.query

import im.vector.matrix.android.internal.database.model.UserEntity
import im.vector.matrix.android.internal.database.model.UserEntityFields
import io.realm.Realm
import io.realm.RealmQuery
import io.realm.kotlin.where

internal fun UserEntity.Companion.where(realm: Realm, userId: String): RealmQuery<UserEntity> {
return realm
.where<UserEntity>()
.equalTo(UserEntityFields.USER_ID, userId)
}

View File

@ -28,6 +28,8 @@ import im.vector.matrix.android.api.session.group.model.GroupSummary
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.model.RoomSummary
import im.vector.matrix.android.api.session.user.UserService
import im.vector.matrix.android.api.session.user.model.User
import im.vector.matrix.android.internal.database.LiveEntityObserver
import im.vector.matrix.android.internal.di.MatrixKoinComponent
import im.vector.matrix.android.internal.di.MatrixKoinHolder
@ -39,7 +41,7 @@ import org.koin.core.scope.Scope
import org.koin.standalone.inject


internal class DefaultSession(override val sessionParams: SessionParams) : Session, MatrixKoinComponent, RoomService {
internal class DefaultSession(override val sessionParams: SessionParams) : Session, MatrixKoinComponent {

companion object {
const val SCOPE: String = "session"
@ -51,6 +53,7 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
private val sessionListeners by inject<SessionListeners>()
private val roomService by inject<RoomService>()
private val groupService by inject<GroupService>()
private val userService by inject<UserService>()
private val syncThread by inject<SyncThread>()
private val contentUrlResolver by inject<ContentUrlResolver>()
private var isOpen = false
@ -118,6 +121,13 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
return groupService.liveGroupSummaries()
}

// USER SERVICE

override fun getUser(userId: String): User? {
assert(isOpen)
return userService.getUser(userId)
}

// Private methods *****************************************************************************

private fun assertMainThread() {

View File

@ -22,17 +22,18 @@ import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.content.ContentUrlResolver
import im.vector.matrix.android.api.session.group.GroupService
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.user.UserService
import im.vector.matrix.android.internal.database.LiveEntityObserver
import im.vector.matrix.android.internal.session.content.DefaultContentUrlResolver
import im.vector.matrix.android.internal.session.group.DefaultGroupService
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
import im.vector.matrix.android.internal.session.room.DefaultRoomService
import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
import im.vector.matrix.android.internal.session.room.RoomFactory
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
import im.vector.matrix.android.internal.session.user.DefaultUserService
import im.vector.matrix.android.internal.util.md5
import io.realm.RealmConfiguration
import org.koin.dsl.module.module
@ -96,6 +97,10 @@ internal class SessionModule(private val sessionParams: SessionParams) {
DefaultGroupService(get()) as GroupService
}

scope(DefaultSession.SCOPE) {
DefaultUserService(get()) as UserService
}

scope(DefaultSession.SCOPE) {
SessionListeners()
}

View File

@ -0,0 +1,40 @@
/*
*
* * 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.session.user

import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.user.UserService
import im.vector.matrix.android.api.session.user.model.User
import im.vector.matrix.android.internal.database.model.UserEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.util.fetchCopied

internal class DefaultUserService(private val monarchy: Monarchy) : UserService {

override fun getUser(userId: String): User? {
val userEntity = monarchy.fetchCopied { UserEntity.where(it, userId).findFirst() }
?: return null

return User(
userEntity.userId,
userEntity.displayName,
userEntity.avatarUrl
)
}
}

View File

@ -0,0 +1,61 @@
/*
*
* * 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.session.user

import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
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.EventEntityFields
import im.vector.matrix.android.internal.database.model.UserEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.members.RoomMembers
import io.realm.Realm
import io.realm.Sort

internal class UserEntityUpdater(monarchy: Monarchy)
: RealmLiveEntityObserver<EventEntity>(monarchy) {

override val query = Monarchy.Query<EventEntity> {
EventEntity.where(it, type = EventType.STATE_ROOM_MEMBER)
.sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING)
.distinct(EventEntityFields.STATE_KEY)
}

override fun process(inserted: List<EventEntity>, updated: List<EventEntity>, deleted: List<EventEntity>) {
val roomMembersEvents = (inserted + updated).map { it.eventId }
monarchy.writeAsync { realm ->
roomMembersEvents.forEach { updateUser(realm, it) }
}
}

private fun updateUser(realm: Realm, eventId: String) {
val event = EventEntity.where(realm, eventId).findFirst()?.asDomain() ?: return
val roomId = event.roomId ?: return
val userId = event.stateKey ?: return
val roomMember = RoomMembers(realm, roomId).getLoaded()[userId] ?: return

val userEntity = UserEntity.where(realm, userId).findFirst()
?: realm.createObject(UserEntity::class.java, userId)
userEntity.displayName = roomMember.displayName ?: ""
userEntity.avatarUrl = roomMember.avatarUrl ?: ""
}

}