From 40f1fcab18f35c7eeaa4c0584d9cf0a8fde09073 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 25 Feb 2019 21:55:33 +0100 Subject: [PATCH] User : start handling users. Need to fine a good strategy to process room member events. --- .../matrix/android/api/session/Session.kt | 3 +- .../android/api/session/user/UserService.kt | 35 +++++++++++ .../android/api/session/user/model/User.kt | 29 +++++++++ .../internal/database/model/UserEntity.kt | 31 ++++++++++ .../database/query/EventEntityQueries.kt | 3 +- .../database/query/UserEntityQueries.kt | 31 ++++++++++ .../internal/session/DefaultSession.kt | 12 +++- .../android/internal/session/SessionModule.kt | 7 ++- .../session/user/DefaultUserService.kt | 40 ++++++++++++ .../session/user/UserEntityUpdater.kt | 61 +++++++++++++++++++ 10 files changed, 247 insertions(+), 5 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/model/User.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/UserEntity.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/UserEntityQueries.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt index 5d760a16f0..ad45328206 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/Session.kt @@ -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 diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt new file mode 100644 index 0000000000..8e90e5e970 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt @@ -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? + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/model/User.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/model/User.kt new file mode 100644 index 0000000000..14ed96d6b2 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/model/User.kt @@ -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 +) \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/UserEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/UserEntity.kt new file mode 100644 index 0000000000..af68d85601 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/UserEntity.kt @@ -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 +} + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt index 015a47acfe..4aa9088429 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt @@ -27,8 +27,7 @@ import io.realm.Sort import io.realm.kotlin.where internal fun EventEntity.Companion.where(realm: Realm, eventId: String): RealmQuery { - return realm.where() - .equalTo(EventEntityFields.EVENT_ID, eventId) + return realm.where().equalTo(EventEntityFields.EVENT_ID, eventId) } internal fun EventEntity.Companion.where(realm: Realm, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/UserEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/UserEntityQueries.kt new file mode 100644 index 0000000000..a7183dc279 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/UserEntityQueries.kt @@ -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 { + return realm + .where() + .equalTo(UserEntityFields.USER_ID, userId) +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt index 55b09aafe2..e04af0118d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt @@ -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() private val roomService by inject() private val groupService by inject() + private val userService by inject() private val syncThread by inject() private val contentUrlResolver by inject() 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() { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt index 91da7dd547..d12a232483 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/SessionModule.kt @@ -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() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt new file mode 100644 index 0000000000..b8e1f028bb --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt @@ -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 + ) + } +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt new file mode 100644 index 0000000000..6360f5b8d2 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/UserEntityUpdater.kt @@ -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(monarchy) { + + override val query = Monarchy.Query { + EventEntity.where(it, type = EventType.STATE_ROOM_MEMBER) + .sort(EventEntityFields.STATE_INDEX, Sort.DESCENDING) + .distinct(EventEntityFields.STATE_KEY) + } + + override fun process(inserted: List, updated: List, deleted: List) { + 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 ?: "" + } + +} \ No newline at end of file