diff --git a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt index 89475585ce..3e9094e09b 100644 --- a/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/org/matrix/android/sdk/rx/RxSession.kt @@ -24,7 +24,7 @@ import kotlinx.coroutines.rx2.rxSingle import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo @@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.pushers.Pusher import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams +import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -177,13 +178,21 @@ class RxSession(private val session: Session) { } } - fun liveUserAccountData(types: Set): Observable> { + fun liveUserAccountData(types: Set): Observable> { return session.accountDataService().getLiveUserAccountDataEvents(types).asObservable() .startWithCallable { session.accountDataService().getUserAccountDataEvents(types) } } + fun liveRoomAccountData(types: Set): Observable> { + return session.accountDataService().getLiveRoomAccountDataEvents(types).asObservable() + .startWithCallable { + session.accountDataService().getRoomAccountDataEvents(types) + } + } + + fun liveRoomWidgets( roomId: String, widgetId: QueryStringValue, @@ -201,7 +210,7 @@ class RxSession(private val session: Session) { } fun liveSecretSynchronisationInfo(): Observable { - return Observable.combineLatest, Optional, Optional, SecretsSynchronisationInfo>( + return Observable.combineLatest, Optional, Optional, SecretsSynchronisationInfo>( liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME)), liveCrossSigningInfo(session.myUserId), liveCrossSigningPrivateKeys(), diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt index ce6da664c3..d14de30c90 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt @@ -33,7 +33,7 @@ import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -73,12 +73,12 @@ class QuadSTests : InstrumentedTest { // Assert Account data is updated val accountDataLock = CountDownLatch(1) - var accountData: AccountDataEvent? = null + var accountData: UserAccountDataEvent? = null val liveAccountData = runBlocking(Dispatchers.Main) { aliceSession.accountDataService().getLiveUserAccountDataEvent("${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") } - val accountDataObserver = Observer?> { t -> + val accountDataObserver = Observer?> { t -> if (t?.getOrNull()?.type == "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") { accountData = t.getOrNull() accountDataLock.countDown() @@ -100,13 +100,13 @@ class QuadSTests : InstrumentedTest { quadS.setDefaultKey(TEST_KEY_ID) } - var defaultKeyAccountData: AccountDataEvent? = null + var defaultKeyAccountData: UserAccountDataEvent? = null val defaultDataLock = CountDownLatch(1) val liveDefAccountData = runBlocking(Dispatchers.Main) { aliceSession.accountDataService().getLiveUserAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID) } - val accountDefDataObserver = Observer?> { t -> + val accountDefDataObserver = Observer?> { t -> if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) { defaultKeyAccountData = t.getOrNull()!! defaultDataLock.countDown() @@ -275,14 +275,14 @@ class QuadSTests : InstrumentedTest { mTestHelper.signOutAndClose(aliceSession) } - private fun assertAccountData(session: Session, type: String): AccountDataEvent { + private fun assertAccountData(session: Session, type: String): UserAccountDataEvent { val accountDataLock = CountDownLatch(1) - var accountData: AccountDataEvent? = null + var accountData: UserAccountDataEvent? = null val liveAccountData = runBlocking(Dispatchers.Main) { session.accountDataService().getLiveUserAccountDataEvent(type) } - val accountDataObserver = Observer?> { t -> + val accountDataObserver = Observer?> { t -> if (t?.getOrNull()?.type == type) { accountData = t.getOrNull() accountDataLock.countDown() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt index ac10f80911..2ffb9112d1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/SessionAccountDataService.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.accountdata import androidx.lifecycle.LiveData import org.matrix.android.sdk.api.session.events.model.Content +import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent import org.matrix.android.sdk.api.util.Optional /** @@ -27,24 +28,36 @@ interface SessionAccountDataService { /** * Retrieve the account data with the provided type or null if not found */ - fun getUserAccountDataEvent(type: String): AccountDataEvent? + fun getUserAccountDataEvent(type: String): UserAccountDataEvent? /** * Observe the account data with the provided type */ - fun getLiveUserAccountDataEvent(type: String): LiveData> + fun getLiveUserAccountDataEvent(type: String): LiveData> /** * Retrieve the account data with the provided types. The return list can have a different size that * the size of the types set, because some AccountData may not exist. * If an empty set is provided, all the AccountData are retrieved */ - fun getUserAccountDataEvents(types: Set): List + fun getUserAccountDataEvents(types: Set): List /** * Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed */ - fun getLiveUserAccountDataEvents(types: Set): LiveData> + fun getLiveUserAccountDataEvents(types: Set): LiveData> + + /** + * Retrieve the room account data with the provided types. The return list can have a different size that + * the size of the types set, because some AccountData may not exist. + * If an empty set is provided, all the room AccountData are retrieved + */ + fun getRoomAccountDataEvents(types: Set): List + + /** + * Observe the room account data with the provided types. If an empty set is provided, AccountData of every room are observed + */ + fun getLiveRoomAccountDataEvents(types: Set): LiveData> /** * Update the account data with the provided type and the provided account data content diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/UserAccountDataEvent.kt similarity index 91% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataEvent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/UserAccountDataEvent.kt index e5cbd07aaf..77381a28c4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/AccountDataEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/accountdata/UserAccountDataEvent.kt @@ -22,10 +22,10 @@ import org.matrix.android.sdk.api.session.events.model.Content /** * This is a simplified Event with just a type and a content. - * Currently used types are defined in [UserAccountDataTypes]. + * Currently used types are defined in [UserAccountDataTypes] */ @JsonClass(generateAdapter = true) -data class AccountDataEvent( +data class UserAccountDataEvent( @Json(name = "type") val type: String, @Json(name = "content") val content: Content ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataEvent.kt new file mode 100644 index 0000000000..eb676ab5e7 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataEvent.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api.session.room.accountdata + +import org.matrix.android.sdk.api.session.events.model.Content + +/** + * This is a simplified Event with just a roomId, a type and a content. + * Currently used types are defined in [RoomAccountDataTypes]. + */ +data class RoomAccountDataEvent( + val roomId: String, + val type: String, + val content: Content +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt index 045070d2b4..190749c85c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/accountdata/RoomAccountDataService.kt @@ -17,7 +17,6 @@ package org.matrix.android.sdk.api.session.room.accountdata import androidx.lifecycle.LiveData -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.util.Optional @@ -28,24 +27,24 @@ interface RoomAccountDataService { /** * Retrieve the account data with the provided type or null if not found */ - fun getAccountDataEvent(type: String): AccountDataEvent? + fun getAccountDataEvent(type: String): RoomAccountDataEvent? /** * Observe the account data with the provided type */ - fun getLiveAccountDataEvent(type: String): LiveData> + fun getLiveAccountDataEvent(type: String): LiveData> /** * Retrieve the account data with the provided types. The return list can have a different size that * the size of the types set, because some AccountData may not exist. * If an empty set is provided, all the AccountData are retrieved */ - fun getAccountDataEvents(types: Set): List + fun getAccountDataEvents(types: Set): List /** * Observe the account data with the provided types. If an empty set is provided, all the AccountData are observed */ - fun getLiveAccountDataEvents(types: Set): LiveData> + fun getLiveAccountDataEvents(types: Set): LiveData> /** * Update the account data with the provided type and the provided account data content diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt index 4edfdad897..dca0f927ad 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/AccountDataMapper.kt @@ -17,7 +17,8 @@ package org.matrix.android.sdk.internal.database.mapper import com.squareup.moshi.Moshi -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent +import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntity import org.matrix.android.sdk.internal.database.model.UserAccountDataEntity @@ -27,15 +28,16 @@ internal class AccountDataMapper @Inject constructor(moshi: Moshi) { private val adapter = moshi.adapter>(JSON_DICT_PARAMETERIZED_TYPE) - fun map(entity: UserAccountDataEntity): AccountDataEvent { - return AccountDataEvent( + fun map(entity: UserAccountDataEntity): UserAccountDataEvent { + return UserAccountDataEvent( type = entity.type ?: "", content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty() ) } - fun map(entity: RoomAccountDataEntity): AccountDataEvent { - return AccountDataEvent( + fun map(roomId: String, entity: RoomAccountDataEntity): RoomAccountDataEvent { + return RoomAccountDataEvent( + roomId = roomId, type = entity.type ?: "", content = entity.contentStr?.let { adapter.fromJson(it) }.orEmpty() ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt index f79f8084a8..aa82cf9222 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/integrationmanager/IntegrationManager.kt @@ -33,7 +33,7 @@ import org.matrix.android.sdk.internal.extensions.observeNotNull import org.matrix.android.sdk.api.session.SessionLifecycleObserver import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory @@ -240,7 +240,7 @@ internal class IntegrationManager @Inject constructor(matrixConfiguration: Matri ) } - private fun AccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? { + private fun UserAccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? { return extractWidgetSequence(widgetFactory) .filter { WidgetType.IntegrationManager == it.type diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt index 0bcf9d7f38..0e4493846c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataDataSource.kt @@ -20,14 +20,16 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.Transformations import com.zhuinden.monarchy.Monarchy -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import io.realm.Realm +import io.realm.RealmQuery +import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.internal.database.RealmSessionProvider import org.matrix.android.sdk.internal.database.mapper.AccountDataMapper import org.matrix.android.sdk.internal.database.model.RoomAccountDataEntityFields import org.matrix.android.sdk.internal.database.model.RoomEntity -import org.matrix.android.sdk.internal.database.query.where +import org.matrix.android.sdk.internal.database.model.RoomEntityFields import org.matrix.android.sdk.internal.di.SessionDatabase import javax.inject.Inject @@ -35,43 +37,62 @@ internal class RoomAccountDataDataSource @Inject constructor(@SessionDatabase pr private val realmSessionProvider: RealmSessionProvider, private val accountDataMapper: AccountDataMapper) { - fun getAccountDataEvent(roomId: String, type: String): AccountDataEvent? { + fun getAccountDataEvent(roomId: String, type: String): RoomAccountDataEvent? { return getAccountDataEvents(roomId, setOf(type)).firstOrNull() } - fun getLiveAccountDataEvent(roomId: String, type: String): LiveData> { + fun getLiveAccountDataEvent(roomId: String, type: String): LiveData> { return Transformations.map(getLiveAccountDataEvents(roomId, setOf(type))) { it.firstOrNull()?.toOptional() } } - fun getAccountDataEvents(roomId: String, types: Set): List { + /** + * @param roomId the roomId to search for account data event. If null will check in every room. + * @param types the types to filter. If empty will return all account data event in given room (or every room if roomId is null) + * + */ + fun getAccountDataEvents(roomId: String?, types: Set): List { return realmSessionProvider.withRealm { realm -> - val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: return@withRealm emptyList() + val roomEntity = buildRoomQuery(realm, roomId, types).findFirst() ?: return@withRealm emptyList() roomEntity.accountDataEvents(types) } } - fun getLiveAccountDataEvents(roomId: String, types: Set): LiveData> { - val liveRoomEntity = monarchy.findAllManagedWithChanges { RoomEntity.where(it, roomId) } - val resultLiveData = MediatorLiveData>() - resultLiveData.addSource(liveRoomEntity) { - val roomEntity = it.realmResults.firstOrNull() - if (roomEntity == null) { - resultLiveData.postValue(emptyList()) - } else { - val mappedResult = roomEntity.accountDataEvents(types) - resultLiveData.postValue(mappedResult) - } + /** + * @param roomId the roomId to search for account data event. If null will check in every room. + * @param types the types to filter. If empty will return all account data event in the given room (or every room if roomId is null). + * + */ + fun getLiveAccountDataEvents(roomId: String?, types: Set): LiveData> { + val liveRoomEntity = monarchy.findAllManagedWithChanges { + buildRoomQuery(it, roomId, types) + } + val resultLiveData = MediatorLiveData>() + resultLiveData.addSource(liveRoomEntity) { changeSet -> + val mappedResult = changeSet.realmResults.flatMap { it.accountDataEvents(types) } + resultLiveData.postValue(mappedResult) } return resultLiveData } - private fun RoomEntity.accountDataEvents(types: Set): List { + private fun buildRoomQuery(realm: Realm, roomId: String?, types: Set): RealmQuery { + val query = realm.where(RoomEntity::class.java) + if (roomId != null) { + query.equalTo(RoomEntityFields.ROOM_ID, roomId) + } + query.isNotEmpty(RoomEntityFields.ACCOUNT_DATA.`$`) + if (types.isNotEmpty()) { + query.`in`(RoomEntityFields.ACCOUNT_DATA.TYPE, types.toTypedArray()) + } + return query + } + + private fun RoomEntity.accountDataEvents(types: Set): List { val query = accountData.where() if (types.isNotEmpty()) { query.`in`(RoomAccountDataEntityFields.TYPE, types.toTypedArray()) } - return query.findAll().map { accountDataMapper.map(it) } + return query.findAll().map { accountDataMapper.map(roomId, it) } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataService.kt index 6035160de2..d43c1d3217 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/accountdata/RoomAccountDataService.kt @@ -20,9 +20,8 @@ import androidx.lifecycle.LiveData import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent -import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService import org.matrix.android.sdk.api.session.events.model.Content +import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService import org.matrix.android.sdk.api.util.Optional @@ -36,19 +35,19 @@ internal class DefaultRoomAccountDataService @AssistedInject constructor(@Assist fun create(roomId: String): DefaultRoomAccountDataService } - override fun getAccountDataEvent(type: String): AccountDataEvent? { + override fun getAccountDataEvent(type: String): RoomAccountDataEvent? { return dataSource.getAccountDataEvent(roomId, type) } - override fun getLiveAccountDataEvent(type: String): LiveData> { + override fun getLiveAccountDataEvent(type: String): LiveData> { return dataSource.getLiveAccountDataEvent(roomId, type) } - override fun getAccountDataEvents(types: Set): List { + override fun getAccountDataEvents(types: Set): List { return dataSource.getAccountDataEvents(roomId, types) } - override fun getLiveAccountDataEvents(types: Set): LiveData> { + override fun getLiveAccountDataEvents(types: Set): LiveData> { return dataSource.getLiveAccountDataEvents(roomId, types) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt index 3aebd90ed2..b8d987d500 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/UserAccountDataSyncHandler.kt @@ -23,7 +23,7 @@ import io.realm.kotlin.where import org.matrix.android.sdk.api.pushrules.RuleScope import org.matrix.android.sdk.api.pushrules.RuleSetKey import org.matrix.android.sdk.api.pushrules.rest.GetPushRulesResponse -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.toModel @@ -113,7 +113,7 @@ internal class UserAccountDataSyncHandler @Inject constructor( } } - private fun handlePushRules(realm: Realm, event: AccountDataEvent) { + private fun handlePushRules(realm: Realm, event: UserAccountDataEvent) { val pushRules = event.content.toModel() ?: return realm.where(PushRulesEntity::class.java) .findAll() @@ -155,7 +155,7 @@ internal class UserAccountDataSyncHandler @Inject constructor( realm.insertOrUpdate(underrides) } - private fun handleDirectChatRooms(realm: Realm, event: AccountDataEvent) { + private fun handleDirectChatRooms(realm: Realm, event: UserAccountDataEvent) { val content = event.content.toModel() ?: return content.forEach { (userId, roomIds) -> roomIds.forEach { roomId -> @@ -181,7 +181,7 @@ internal class UserAccountDataSyncHandler @Inject constructor( } } - private fun handleIgnoredUsers(realm: Realm, event: AccountDataEvent) { + private fun handleIgnoredUsers(realm: Realm, event: UserAccountDataEvent) { val userIds = event.content.toModel()?.ignoredUsers?.keys ?: return realm.where(IgnoredUserEntity::class.java) .findAll() @@ -191,7 +191,7 @@ internal class UserAccountDataSyncHandler @Inject constructor( // TODO If not initial sync, we should execute a init sync } - private fun handleBreadcrumbs(realm: Realm, event: AccountDataEvent) { + private fun handleBreadcrumbs(realm: Realm, event: UserAccountDataEvent) { val recentRoomIds = event.content.toModel()?.recentRoomIds ?: return val entity = BreadcrumbsEntity.getOrCreate(realm) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt index ddb71cd19f..05b50ab2c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/model/accountdata/UserAccountDataSync.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.internal.session.sync.model.accountdata import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent @JsonClass(generateAdapter = true) internal data class UserAccountDataSync( - @Json(name = "events") val list: List = emptyList() + @Json(name = "events") val list: List = emptyList() ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt index c8aab586a0..8bf9ad5b90 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/RoomSyncAccountDataHandler.kt @@ -56,7 +56,6 @@ internal class RoomSyncAccountDataHandler @Inject constructor(private val roomTa private fun handleGeneric(roomEntity: RoomEntity, content: JsonDict?, eventType: String) { val existing = roomEntity.accountData.where().equalTo(RoomAccountDataEntityFields.TYPE, eventType).findFirst() if (existing != null) { - // Update current value existing.contentStr = ContentMapper.map(content) } else { val roomAccountData = RoomAccountDataEntity( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt index fac92deefd..ff1750ce8e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt @@ -23,7 +23,9 @@ import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.session.sync.UserAccountDataSyncHandler -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent +import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent +import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataDataSource import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.util.awaitCallback @@ -33,24 +35,33 @@ internal class DefaultSessionAccountDataService @Inject constructor( @SessionDatabase private val monarchy: Monarchy, private val updateUserAccountDataTask: UpdateUserAccountDataTask, private val userAccountDataSyncHandler: UserAccountDataSyncHandler, - private val accountDataDataSource: UserAccountDataDataSource, + private val userAccountDataDataSource: UserAccountDataDataSource, + private val roomAccountDataDataSource: RoomAccountDataDataSource, private val taskExecutor: TaskExecutor ) : SessionAccountDataService { - override fun getUserAccountDataEvent(type: String): AccountDataEvent? { - return accountDataDataSource.getAccountDataEvent(type) + override fun getUserAccountDataEvent(type: String): UserAccountDataEvent? { + return userAccountDataDataSource.getAccountDataEvent(type) } - override fun getLiveUserAccountDataEvent(type: String): LiveData> { - return accountDataDataSource.getLiveAccountDataEvent(type) + override fun getLiveUserAccountDataEvent(type: String): LiveData> { + return userAccountDataDataSource.getLiveAccountDataEvent(type) } - override fun getUserAccountDataEvents(types: Set): List { - return accountDataDataSource.getAccountDataEvents(types) + override fun getUserAccountDataEvents(types: Set): List { + return userAccountDataDataSource.getAccountDataEvents(types) } - override fun getLiveUserAccountDataEvents(types: Set): LiveData> { - return accountDataDataSource.getLiveAccountDataEvents(types) + override fun getLiveUserAccountDataEvents(types: Set): LiveData> { + return userAccountDataDataSource.getLiveAccountDataEvents(types) + } + + override fun getRoomAccountDataEvents(types: Set): List { + return roomAccountDataDataSource.getAccountDataEvents(null, types) + } + + override fun getLiveRoomAccountDataEvents(types: Set): LiveData> { + return roomAccountDataDataSource.getLiveAccountDataEvents(null, types) } override suspend fun updateUserAccountData(type: String, content: Content) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt index f64b1bdd2e..b36bdc80f8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/UserAccountDataDataSource.kt @@ -21,7 +21,7 @@ import androidx.lifecycle.Transformations import com.zhuinden.monarchy.Monarchy import io.realm.Realm import io.realm.RealmQuery -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.internal.database.RealmSessionProvider @@ -35,23 +35,23 @@ internal class UserAccountDataDataSource @Inject constructor(@SessionDatabase pr private val realmSessionProvider: RealmSessionProvider, private val accountDataMapper: AccountDataMapper) { - fun getAccountDataEvent(type: String): AccountDataEvent? { + fun getAccountDataEvent(type: String): UserAccountDataEvent? { return getAccountDataEvents(setOf(type)).firstOrNull() } - fun getLiveAccountDataEvent(type: String): LiveData> { + fun getLiveAccountDataEvent(type: String): LiveData> { return Transformations.map(getLiveAccountDataEvents(setOf(type))) { it.firstOrNull()?.toOptional() } } - fun getAccountDataEvents(types: Set): List { + fun getAccountDataEvents(types: Set): List { return realmSessionProvider.withRealm { accountDataEventsQuery(it, types).findAll().map(accountDataMapper::map) } } - fun getLiveAccountDataEvents(types: Set): LiveData> { + fun getLiveAccountDataEvents(types: Set): LiveData> { return monarchy.findAllMappedWithChanges( { accountDataEventsQuery(it, types) }, accountDataMapper::map diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt index ca1a129da7..e0f43a11c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt @@ -23,7 +23,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event @@ -47,7 +47,7 @@ import javax.inject.Inject @SessionScope internal class WidgetManager @Inject constructor(private val integrationManager: IntegrationManager, - private val accountDataDataSource: UserAccountDataDataSource, + private val userAccountDataDataSource: UserAccountDataDataSource, private val stateEventDataSource: StateEventDataSource, private val createWidgetTask: CreateWidgetTask, private val widgetFactory: WidgetFactory, @@ -136,7 +136,7 @@ internal class WidgetManager @Inject constructor(private val integrationManager: widgetTypes: Set? = null, excludedTypes: Set? = null ): LiveData> { - val widgetsAccountData = accountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) + val widgetsAccountData = userAccountDataDataSource.getLiveAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) return Transformations.map(widgetsAccountData) { it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes).orEmpty() } @@ -146,12 +146,12 @@ internal class WidgetManager @Inject constructor(private val integrationManager: widgetTypes: Set? = null, excludedTypes: Set? = null ): List { - val widgetsAccountData = accountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList() + val widgetsAccountData = userAccountDataDataSource.getAccountDataEvent(UserAccountDataTypes.TYPE_WIDGETS) ?: return emptyList() return widgetsAccountData.mapToWidgets(widgetTypes, excludedTypes) } - private fun AccountDataEvent.mapToWidgets(widgetTypes: Set? = null, - excludedTypes: Set? = null): List { + private fun UserAccountDataEvent.mapToWidgets(widgetTypes: Set? = null, + excludedTypes: Set? = null): List { return extractWidgetSequence(widgetFactory) .filter { val widgetType = it.widgetContent.type ?: return@filter false diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt index 5aa32d5a31..6f423b38a0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/helper/UserAccountWidgets.kt @@ -19,10 +19,10 @@ package org.matrix.android.sdk.internal.session.widgets.helper import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.widgets.model.Widget -internal fun AccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence { +internal fun UserAccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence { return content.asSequence() .mapNotNull { @Suppress("UNCHECKED_CAST") diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt index fd3cd0962b..5f0004c0de 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt @@ -26,7 +26,7 @@ import im.vector.app.core.epoxy.loadingItem import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.core.ui.list.genericWithValueItem -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import javax.inject.Inject class AccountDataEpoxyController @Inject constructor( @@ -34,8 +34,8 @@ class AccountDataEpoxyController @Inject constructor( ) : TypedEpoxyController() { interface InteractionListener { - fun didTap(data: AccountDataEvent) - fun didLongTap(data: AccountDataEvent) + fun didTap(data: UserAccountDataEvent) + fun didLongTap(data: UserAccountDataEvent) } var interactionListener: InteractionListener? = null diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt index df6c8bd5fa..c50dd3c187 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt @@ -35,7 +35,7 @@ import im.vector.app.core.utils.createJSonViewerStyleProvider import im.vector.app.databinding.FragmentGenericRecyclerBinding import org.billcarsonfr.jsonviewer.JSonViewerDialog -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.internal.di.MoshiProvider import javax.inject.Inject @@ -73,9 +73,9 @@ class AccountDataFragment @Inject constructor( super.onDestroyView() } - override fun didTap(data: AccountDataEvent) { + override fun didTap(data: UserAccountDataEvent) { val jsonString = MoshiProvider.providesMoshi() - .adapter(AccountDataEvent::class.java) + .adapter(UserAccountDataEvent::class.java) .toJson(data) JSonViewerDialog.newInstance( jsonString, @@ -84,7 +84,7 @@ class AccountDataFragment @Inject constructor( ).show(childFragmentManager, "JSON_VIEWER") } - override fun didLongTap(data: AccountDataEvent) { + override fun didLongTap(data: UserAccountDataEvent) { AlertDialog.Builder(requireActivity()) .setTitle(R.string.delete) .setMessage(getString(R.string.delete_account_data_warning, data.type)) diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt index 9ee7e48ed7..d50caea579 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataViewModel.kt @@ -31,11 +31,11 @@ import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.rx.rx data class AccountDataViewState( - val accountData: Async> = Uninitialized + val accountData: Async> = Uninitialized ) : MvRxState class AccountDataViewModel @AssistedInject constructor(@Assisted initialState: AccountDataViewState, diff --git a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt index 00b388bfb8..6d95911bdb 100644 --- a/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/workers/signout/ServerBackupStatusViewModel.kt @@ -35,7 +35,7 @@ import io.reactivex.functions.Function4 import io.reactivex.subjects.PublishSubject import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.accountdata.AccountDataEvent +import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME @@ -98,7 +98,7 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS keysBackupState.value = session.cryptoService().keysBackupService().state - Observable.combineLatest, Optional, KeysBackupState, Optional, BannerState>( + Observable.combineLatest, Optional, KeysBackupState, Optional, BannerState>( session.rx().liveUserAccountData(setOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME)), session.rx().liveCrossSigningInfo(session.myUserId), keyBackupPublishSubject,