mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 09:25:49 +03:00
Merge pull request #7125 from vector-im/feature/fre/start_dm_loading
Deferred DM - Add a loading wheel while creating the DM
This commit is contained in:
commit
b4ca16735d
21 changed files with 443 additions and 145 deletions
1
changelog.d/6970.wip
Normal file
1
changelog.d/6970.wip
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Create DM room only on first message - Add a spinner when sending the first message
|
|
@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
|
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
@ -46,6 +47,13 @@ class FlowRoom(private val room: Room) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun liveLocalRoomSummary(): Flow<Optional<LocalRoomSummary>> {
|
||||||
|
return room.getLocalRoomSummaryLive().asFlow()
|
||||||
|
.startWith(room.coroutineDispatchers.io) {
|
||||||
|
room.localRoomSummary().toOptional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Flow<List<RoomMemberSummary>> {
|
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Flow<List<RoomMemberSummary>> {
|
||||||
return room.membershipService().getRoomMembersLive(queryParams).asFlow()
|
return room.membershipService().getRoomMembersLive(queryParams).asFlow()
|
||||||
.startWith(room.coroutineDispatchers.io) {
|
.startWith(room.coroutineDispatchers.io) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
|
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
||||||
import org.matrix.android.sdk.api.session.room.notification.RoomPushRuleService
|
import org.matrix.android.sdk.api.session.room.notification.RoomPushRuleService
|
||||||
|
@ -60,11 +61,22 @@ interface Room {
|
||||||
*/
|
*/
|
||||||
fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>>
|
fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A live [LocalRoomSummary] associated with the room.
|
||||||
|
* You can observe this summary to get dynamic data from this room.
|
||||||
|
*/
|
||||||
|
fun getLocalRoomSummaryLive(): LiveData<Optional<LocalRoomSummary>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A current snapshot of [RoomSummary] associated with the room.
|
* A current snapshot of [RoomSummary] associated with the room.
|
||||||
*/
|
*/
|
||||||
fun roomSummary(): RoomSummary?
|
fun roomSummary(): RoomSummary?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A current snapshot of [LocalRoomSummary] associated with the room.
|
||||||
|
*/
|
||||||
|
fun localRoomSummary(): LocalRoomSummary?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this room as a Space, if the type is correct.
|
* Use this room as a Space, if the type is correct.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
|
import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
|
||||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
@ -117,6 +118,12 @@ interface RoomService {
|
||||||
*/
|
*/
|
||||||
fun getRoomSummaryLive(roomId: String): LiveData<Optional<RoomSummary>>
|
fun getRoomSummaryLive(roomId: String): LiveData<Optional<RoomSummary>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A live [LocalRoomSummary] associated with the room with id [roomId].
|
||||||
|
* You can observe this summary to get dynamic data from this room, even if the room is not joined yet
|
||||||
|
*/
|
||||||
|
fun getLocalRoomSummaryLive(roomId: String): LiveData<Optional<LocalRoomSummary>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a snapshot list of room summaries.
|
* Get a snapshot list of room summaries.
|
||||||
* @return the immutable list of [RoomSummary]
|
* @return the immutable list of [RoomSummary]
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 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.model
|
||||||
|
|
||||||
|
enum class LocalRoomCreationState {
|
||||||
|
NOT_CREATED,
|
||||||
|
CREATING,
|
||||||
|
FAILURE,
|
||||||
|
CREATED
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 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.model
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class holds some data of a local room.
|
||||||
|
* It can be retrieved by [org.matrix.android.sdk.api.session.room.Room] and [org.matrix.android.sdk.api.session.room.RoomService]
|
||||||
|
*/
|
||||||
|
data class LocalRoomSummary(
|
||||||
|
/**
|
||||||
|
* The roomId of the room.
|
||||||
|
*/
|
||||||
|
val roomId: String,
|
||||||
|
/**
|
||||||
|
* The room summary of the room.
|
||||||
|
*/
|
||||||
|
val roomSummary: RoomSummary?,
|
||||||
|
/**
|
||||||
|
* The creation params attached to the room.
|
||||||
|
*/
|
||||||
|
val createRoomParams: CreateRoomParams?,
|
||||||
|
/**
|
||||||
|
* The roomId of the created room (ie. created on the server), if any.
|
||||||
|
*/
|
||||||
|
val replacementRoomId: String?,
|
||||||
|
/**
|
||||||
|
* The creation state of the room.
|
||||||
|
*/
|
||||||
|
val creationState: LocalRoomCreationState,
|
||||||
|
)
|
|
@ -53,6 +53,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo033
|
||||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo034
|
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo034
|
||||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo035
|
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo035
|
||||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo036
|
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo036
|
||||||
|
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo037
|
||||||
import org.matrix.android.sdk.internal.util.Normalizer
|
import org.matrix.android.sdk.internal.util.Normalizer
|
||||||
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
|
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -61,7 +62,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
||||||
private val normalizer: Normalizer
|
private val normalizer: Normalizer
|
||||||
) : MatrixRealmMigration(
|
) : MatrixRealmMigration(
|
||||||
dbName = "Session",
|
dbName = "Session",
|
||||||
schemaVersion = 36L,
|
schemaVersion = 37L,
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Forces all RealmSessionStoreMigration instances to be equal.
|
* Forces all RealmSessionStoreMigration instances to be equal.
|
||||||
|
@ -107,5 +108,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
||||||
if (oldVersion < 34) MigrateSessionTo034(realm).perform()
|
if (oldVersion < 34) MigrateSessionTo034(realm).perform()
|
||||||
if (oldVersion < 35) MigrateSessionTo035(realm).perform()
|
if (oldVersion < 35) MigrateSessionTo035(realm).perform()
|
||||||
if (oldVersion < 36) MigrateSessionTo036(realm).perform()
|
if (oldVersion < 36) MigrateSessionTo036(realm).perform()
|
||||||
|
if (oldVersion < 37) MigrateSessionTo037(realm).perform()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 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.internal.database.mapper
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
|
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class LocalRoomSummaryMapper @Inject constructor(
|
||||||
|
private val roomSummaryMapper: RoomSummaryMapper,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun map(localRoomSummaryEntity: LocalRoomSummaryEntity): LocalRoomSummary {
|
||||||
|
return LocalRoomSummary(
|
||||||
|
roomId = localRoomSummaryEntity.roomId,
|
||||||
|
roomSummary = localRoomSummaryEntity.roomSummaryEntity?.let { roomSummaryMapper.map(it) },
|
||||||
|
createRoomParams = localRoomSummaryEntity.createRoomParams,
|
||||||
|
replacementRoomId = localRoomSummaryEntity.replacementRoomId,
|
||||||
|
creationState = localRoomSummaryEntity.creationState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.internal.database.migration
|
||||||
|
|
||||||
|
import io.realm.DynamicRealm
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||||
|
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
||||||
|
import org.matrix.android.sdk.internal.util.database.RealmMigrator
|
||||||
|
|
||||||
|
internal class MigrateSessionTo037(realm: DynamicRealm) : RealmMigrator(realm, 37) {
|
||||||
|
|
||||||
|
override fun doMigrate(realm: DynamicRealm) {
|
||||||
|
realm.schema.get("LocalRoomSummaryEntity")
|
||||||
|
?.addField(LocalRoomSummaryEntityFields.REPLACEMENT_ROOM_ID, String::class.java)
|
||||||
|
?.addField(LocalRoomSummaryEntityFields.STATE_STR, String::class.java)
|
||||||
|
?.transform { obj ->
|
||||||
|
obj.set(LocalRoomSummaryEntityFields.STATE_STR, LocalRoomCreationState.NOT_CREATED.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,15 +18,24 @@ package org.matrix.android.sdk.internal.database.model
|
||||||
|
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.annotations.PrimaryKey
|
import io.realm.annotations.PrimaryKey
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.toJSONString
|
import org.matrix.android.sdk.api.session.room.model.create.toJSONString
|
||||||
|
|
||||||
internal open class LocalRoomSummaryEntity(
|
internal open class LocalRoomSummaryEntity(
|
||||||
@PrimaryKey var roomId: String = "",
|
@PrimaryKey var roomId: String = "",
|
||||||
var roomSummaryEntity: RoomSummaryEntity? = null,
|
var roomSummaryEntity: RoomSummaryEntity? = null,
|
||||||
private var createRoomParamsStr: String? = null
|
var replacementRoomId: String? = null,
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
|
|
||||||
|
private var stateStr: String = LocalRoomCreationState.NOT_CREATED.name
|
||||||
|
var creationState: LocalRoomCreationState
|
||||||
|
get() = LocalRoomCreationState.valueOf(stateStr)
|
||||||
|
set(value) {
|
||||||
|
stateStr = value.name
|
||||||
|
}
|
||||||
|
|
||||||
|
private var createRoomParamsStr: String? = null
|
||||||
var createRoomParams: CreateRoomParams?
|
var createRoomParams: CreateRoomParams?
|
||||||
get() {
|
get() {
|
||||||
return CreateRoomParams.fromJson(createRoomParamsStr)
|
return CreateRoomParams.fromJson(createRoomParamsStr)
|
||||||
|
|
|
@ -22,10 +22,6 @@ import io.realm.kotlin.where
|
||||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
||||||
|
|
||||||
internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String? = null): RealmQuery<LocalRoomSummaryEntity> {
|
internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<LocalRoomSummaryEntity> {
|
||||||
val query = realm.where<LocalRoomSummaryEntity>()
|
return realm.where<LocalRoomSummaryEntity>().equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId)
|
||||||
if (roomId != null) {
|
|
||||||
query.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId)
|
|
||||||
}
|
|
||||||
return query
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
|
import org.matrix.android.sdk.api.session.room.location.LocationSharingService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
||||||
|
@ -82,6 +83,14 @@ internal class DefaultRoom(
|
||||||
return roomSummaryDataSource.getRoomSummary(roomId)
|
return roomSummaryDataSource.getRoomSummary(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getLocalRoomSummaryLive(): LiveData<Optional<LocalRoomSummary>> {
|
||||||
|
return roomSummaryDataSource.getLocalRoomSummaryLive(roomId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun localRoomSummary(): LocalRoomSummary? {
|
||||||
|
return roomSummaryDataSource.getLocalRoomSummary(roomId)
|
||||||
|
}
|
||||||
|
|
||||||
override fun asSpace(): Space? {
|
override fun asSpace(): Space? {
|
||||||
if (roomSummary()?.roomType != RoomType.SPACE) return null
|
if (roomSummary()?.roomType != RoomType.SPACE) return null
|
||||||
return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder)
|
return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder)
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
|
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
|
||||||
import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
@ -106,6 +107,10 @@ internal class DefaultRoomService @Inject constructor(
|
||||||
return roomSummaryDataSource.getRoomSummaryLive(roomId)
|
return roomSummaryDataSource.getRoomSummaryLive(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getLocalRoomSummaryLive(roomId: String): LiveData<Optional<LocalRoomSummary>> {
|
||||||
|
return roomSummaryDataSource.getLocalRoomSummaryLive(roomId)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getRoomSummaries(
|
override fun getRoomSummaries(
|
||||||
queryParams: RoomSummaryQueryParams,
|
queryParams: RoomSummaryQueryParams,
|
||||||
sortOrder: RoomSortOrder
|
sortOrder: RoomSortOrder
|
||||||
|
|
|
@ -17,38 +17,23 @@
|
||||||
package org.matrix.android.sdk.internal.session.room.create
|
package org.matrix.android.sdk.internal.session.room.create
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import io.realm.kotlin.where
|
|
||||||
import kotlinx.coroutines.TimeoutCancellationException
|
import kotlinx.coroutines.TimeoutCancellationException
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
|
||||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
|
||||||
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
||||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
|
||||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
|
||||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
import org.matrix.android.sdk.internal.database.model.EventEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
|
||||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
import org.matrix.android.sdk.internal.database.query.where
|
||||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
|
||||||
import org.matrix.android.sdk.internal.database.query.whereRoomId
|
import org.matrix.android.sdk.internal.database.query.whereRoomId
|
||||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
|
||||||
import org.matrix.android.sdk.internal.task.Task
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
|
||||||
import org.matrix.android.sdk.internal.util.time.Clock
|
|
||||||
import java.util.UUID
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -56,94 +41,100 @@ import javax.inject.Inject
|
||||||
* Create a room on the server from a local room.
|
* Create a room on the server from a local room.
|
||||||
* The configuration of the local room will be use to configure the new room.
|
* The configuration of the local room will be use to configure the new room.
|
||||||
* The potential local room members will also be invited to this new room.
|
* The potential local room members will also be invited to this new room.
|
||||||
*
|
|
||||||
* A local tombstone event will be created to indicate that the local room has been replacing by the new one.
|
|
||||||
*/
|
*/
|
||||||
internal interface CreateRoomFromLocalRoomTask : Task<CreateRoomFromLocalRoomTask.Params, String> {
|
internal interface CreateRoomFromLocalRoomTask : Task<CreateRoomFromLocalRoomTask.Params, String> {
|
||||||
data class Params(val localRoomId: String)
|
data class Params(val localRoomId: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor(
|
internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor(
|
||||||
@UserId private val userId: String,
|
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
private val createRoomTask: CreateRoomTask,
|
private val createRoomTask: CreateRoomTask,
|
||||||
private val stateEventDataSource: StateEventDataSource,
|
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||||
private val clock: Clock,
|
|
||||||
) : CreateRoomFromLocalRoomTask {
|
) : CreateRoomFromLocalRoomTask {
|
||||||
|
|
||||||
private val realmConfiguration
|
private val realmConfiguration
|
||||||
get() = monarchy.realmConfiguration
|
get() = monarchy.realmConfiguration
|
||||||
|
|
||||||
override suspend fun execute(params: CreateRoomFromLocalRoomTask.Params): String {
|
override suspend fun execute(params: CreateRoomFromLocalRoomTask.Params): String {
|
||||||
val replacementRoomId = stateEventDataSource.getStateEvent(params.localRoomId, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)
|
val localRoomSummary = roomSummaryDataSource.getLocalRoomSummary(params.localRoomId)
|
||||||
?.content.toModel<RoomTombstoneContent>()
|
?: error("## CreateRoomFromLocalRoomTask - Cannot retrieve LocalRoomSummary with roomId ${params.localRoomId}")
|
||||||
?.replacementRoomId
|
|
||||||
|
|
||||||
if (replacementRoomId != null) {
|
// If a room has already been created for the given local room, return the existing roomId
|
||||||
return replacementRoomId
|
if (localRoomSummary.replacementRoomId != null) {
|
||||||
|
return localRoomSummary.replacementRoomId
|
||||||
}
|
}
|
||||||
|
|
||||||
var createRoomParams: CreateRoomParams? = null
|
if (localRoomSummary.createRoomParams != null && localRoomSummary.roomSummary != null) {
|
||||||
var isEncrypted = false
|
return createRoom(params.localRoomId, localRoomSummary.roomSummary, localRoomSummary.createRoomParams)
|
||||||
monarchy.doWithRealm { realm ->
|
} else {
|
||||||
realm.where<LocalRoomSummaryEntity>()
|
error("## CreateRoomFromLocalRoomTask - Invalid LocalRoomSummary: $localRoomSummary")
|
||||||
.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, params.localRoomId)
|
|
||||||
.findFirst()
|
|
||||||
?.let {
|
|
||||||
createRoomParams = it.createRoomParams
|
|
||||||
isEncrypted = it.roomSummaryEntity?.isEncrypted.orFalse()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val roomId = createRoomTask.execute(createRoomParams!!)
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a room on the server for the given local room.
|
||||||
|
*
|
||||||
|
* @param localRoomId the local room identifier.
|
||||||
|
* @param localRoomSummary the RoomSummary of the local room.
|
||||||
|
* @param createRoomParams the CreateRoomParams object which was used to configure the local room.
|
||||||
|
*
|
||||||
|
* @return the identifier of the created room.
|
||||||
|
*/
|
||||||
|
private suspend fun createRoom(localRoomId: String, localRoomSummary: RoomSummary, createRoomParams: CreateRoomParams): String {
|
||||||
|
updateCreationState(localRoomId, LocalRoomCreationState.CREATING)
|
||||||
|
val replacementRoomId = runCatching {
|
||||||
|
createRoomTask.execute(createRoomParams)
|
||||||
|
}.fold(
|
||||||
|
{ it },
|
||||||
|
{
|
||||||
|
updateCreationState(localRoomId, LocalRoomCreationState.FAILURE)
|
||||||
|
throw it
|
||||||
|
}
|
||||||
|
)
|
||||||
|
updateReplacementRoomId(localRoomId, replacementRoomId)
|
||||||
|
waitForRoomEvents(replacementRoomId, localRoomSummary)
|
||||||
|
updateCreationState(localRoomId, LocalRoomCreationState.CREATED)
|
||||||
|
return replacementRoomId
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for all the room events before triggering the created state.
|
||||||
|
*
|
||||||
|
* @param replacementRoomId the identifier of the created room
|
||||||
|
* @param localRoomSummary the RoomSummary of the local room.
|
||||||
|
*/
|
||||||
|
private suspend fun waitForRoomEvents(replacementRoomId: String, localRoomSummary: RoomSummary) {
|
||||||
try {
|
try {
|
||||||
// Wait for all the room events before triggering the replacement room
|
|
||||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||||
realm.where(RoomSummaryEntity::class.java)
|
realm.where(RoomSummaryEntity::class.java)
|
||||||
.equalTo(RoomSummaryEntityFields.ROOM_ID, roomId)
|
.equalTo(RoomSummaryEntityFields.ROOM_ID, replacementRoomId)
|
||||||
.equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, createRoomParams?.invitedUserIds?.size ?: 0)
|
.equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, localRoomSummary.invitedMembersCount)
|
||||||
}
|
}
|
||||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||||
EventEntity.whereRoomId(realm, roomId)
|
EventEntity.whereRoomId(realm, replacementRoomId)
|
||||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_HISTORY_VISIBILITY)
|
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_HISTORY_VISIBILITY)
|
||||||
}
|
}
|
||||||
if (isEncrypted) {
|
if (localRoomSummary.isEncrypted) {
|
||||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||||
EventEntity.whereRoomId(realm, roomId)
|
EventEntity.whereRoomId(realm, replacementRoomId)
|
||||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION)
|
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (exception: TimeoutCancellationException) {
|
} catch (exception: TimeoutCancellationException) {
|
||||||
throw CreateRoomFailure.CreatedWithTimeout(roomId)
|
updateCreationState(localRoomSummary.roomId, LocalRoomCreationState.FAILURE)
|
||||||
|
throw CreateRoomFailure.CreatedWithTimeout(replacementRoomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
createTombstoneEvent(params, roomId)
|
|
||||||
return roomId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun updateCreationState(roomId: String, creationState: LocalRoomCreationState) {
|
||||||
* Create a Tombstone event to indicate that the local room has been replaced by a new one.
|
monarchy.runTransactionSync { realm ->
|
||||||
*/
|
LocalRoomSummaryEntity.where(realm, roomId).findFirst()?.creationState = creationState
|
||||||
private suspend fun createTombstoneEvent(params: CreateRoomFromLocalRoomTask.Params, roomId: String) {
|
}
|
||||||
val now = clock.epochMillis()
|
}
|
||||||
val event = Event(
|
|
||||||
type = EventType.STATE_ROOM_TOMBSTONE,
|
private fun updateReplacementRoomId(localRoomId: String, replacementRoomId: String) {
|
||||||
senderId = userId,
|
monarchy.runTransactionSync { realm ->
|
||||||
originServerTs = now,
|
LocalRoomSummaryEntity.where(realm, localRoomId).findFirst()?.replacementRoomId = replacementRoomId
|
||||||
stateKey = "",
|
|
||||||
eventId = UUID.randomUUID().toString(),
|
|
||||||
content = RoomTombstoneContent(
|
|
||||||
replacementRoomId = roomId
|
|
||||||
).toContent()
|
|
||||||
)
|
|
||||||
monarchy.awaitTransaction { realm ->
|
|
||||||
val eventEntity = event.toEntity(params.localRoomId, SendState.SYNCED, now).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC)
|
|
||||||
if (event.stateKey != null && event.type != null && event.eventId != null) {
|
|
||||||
CurrentStateEventEntity.getOrCreate(realm, params.localRoomId, event.stateKey, event.type).apply {
|
|
||||||
eventId = event.eventId
|
|
||||||
root = eventEntity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.room.ResultBoundaries
|
||||||
import org.matrix.android.sdk.api.session.room.RoomSortOrder
|
import org.matrix.android.sdk.api.session.room.RoomSortOrder
|
||||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
|
import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||||
|
@ -43,7 +44,9 @@ import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotification
|
||||||
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
|
import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
|
import org.matrix.android.sdk.internal.database.mapper.LocalRoomSummaryMapper
|
||||||
import org.matrix.android.sdk.internal.database.mapper.RoomSummaryMapper
|
import org.matrix.android.sdk.internal.database.mapper.RoomSummaryMapper
|
||||||
|
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.query.findByAlias
|
import org.matrix.android.sdk.internal.database.query.findByAlias
|
||||||
|
@ -57,6 +60,7 @@ import javax.inject.Inject
|
||||||
internal class RoomSummaryDataSource @Inject constructor(
|
internal class RoomSummaryDataSource @Inject constructor(
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
private val roomSummaryMapper: RoomSummaryMapper,
|
private val roomSummaryMapper: RoomSummaryMapper,
|
||||||
|
private val localRoomSummaryMapper: LocalRoomSummaryMapper,
|
||||||
private val queryStringValueProcessor: QueryStringValueProcessor,
|
private val queryStringValueProcessor: QueryStringValueProcessor,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -95,6 +99,25 @@ internal class RoomSummaryDataSource @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getLocalRoomSummary(roomId: String): LocalRoomSummary? {
|
||||||
|
return monarchy
|
||||||
|
.fetchCopyMap({
|
||||||
|
LocalRoomSummaryEntity.where(it, roomId).findFirst()
|
||||||
|
}, { entity, _ ->
|
||||||
|
localRoomSummaryMapper.map(entity)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocalRoomSummaryLive(roomId: String): LiveData<Optional<LocalRoomSummary>> {
|
||||||
|
val liveData = monarchy.findAllMappedWithChanges(
|
||||||
|
{ realm -> LocalRoomSummaryEntity.where(realm, roomId) },
|
||||||
|
{ localRoomSummaryMapper.map(it) }
|
||||||
|
)
|
||||||
|
return Transformations.map(liveData) { results ->
|
||||||
|
results.firstOrNull().toOptional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getRoomSummariesLive(
|
fun getRoomSummariesLive(
|
||||||
queryParams: RoomSummaryQueryParams,
|
queryParams: RoomSummaryQueryParams,
|
||||||
sortOrder: RoomSortOrder = RoomSortOrder.NONE
|
sortOrder: RoomSortOrder = RoomSortOrder.NONE
|
||||||
|
|
|
@ -22,21 +22,22 @@ import io.mockk.coVerify
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.mockkStatic
|
import io.mockk.mockkStatic
|
||||||
|
import io.mockk.spyk
|
||||||
import io.mockk.unmockkAll
|
import io.mockk.unmockkAll
|
||||||
|
import io.mockk.verify
|
||||||
|
import io.mockk.verifyOrder
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.amshove.kluent.shouldBeEqualTo
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.amshove.kluent.shouldBeNull
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
|
||||||
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
||||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.EventEntity
|
import org.matrix.android.sdk.internal.database.model.EventEntity
|
||||||
|
@ -44,29 +45,24 @@ import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntity
|
||||||
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
import org.matrix.android.sdk.internal.database.model.LocalRoomSummaryEntityFields
|
||||||
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
||||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||||
import org.matrix.android.sdk.internal.util.time.DefaultClock
|
|
||||||
import org.matrix.android.sdk.test.fakes.FakeMonarchy
|
import org.matrix.android.sdk.test.fakes.FakeMonarchy
|
||||||
import org.matrix.android.sdk.test.fakes.FakeStateEventDataSource
|
import org.matrix.android.sdk.test.fakes.FakeRoomSummaryDataSource
|
||||||
|
|
||||||
private const val A_LOCAL_ROOM_ID = "local.a-local-room-id"
|
private const val A_LOCAL_ROOM_ID = "local.a-local-room-id"
|
||||||
private const val AN_EXISTING_ROOM_ID = "an-existing-room-id"
|
private const val AN_EXISTING_ROOM_ID = "an-existing-room-id"
|
||||||
private const val A_ROOM_ID = "a-room-id"
|
private const val A_ROOM_ID = "a-room-id"
|
||||||
private const val MY_USER_ID = "my-user-id"
|
|
||||||
|
|
||||||
@ExperimentalCoroutinesApi
|
@ExperimentalCoroutinesApi
|
||||||
internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
||||||
|
|
||||||
private val fakeMonarchy = FakeMonarchy()
|
private val fakeMonarchy = FakeMonarchy()
|
||||||
private val clock = DefaultClock()
|
|
||||||
private val createRoomTask = mockk<CreateRoomTask>()
|
private val createRoomTask = mockk<CreateRoomTask>()
|
||||||
private val fakeStateEventDataSource = FakeStateEventDataSource()
|
private val fakeRoomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||||
|
|
||||||
private val defaultCreateRoomFromLocalRoomTask = DefaultCreateRoomFromLocalRoomTask(
|
private val defaultCreateRoomFromLocalRoomTask = DefaultCreateRoomFromLocalRoomTask(
|
||||||
userId = MY_USER_ID,
|
|
||||||
monarchy = fakeMonarchy.instance,
|
monarchy = fakeMonarchy.instance,
|
||||||
createRoomTask = createRoomTask,
|
createRoomTask = createRoomTask,
|
||||||
stateEventDataSource = fakeStateEventDataSource.instance,
|
roomSummaryDataSource = fakeRoomSummaryDataSource.instance,
|
||||||
clock = clock
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -91,13 +87,12 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
||||||
@Test
|
@Test
|
||||||
fun `given a local room id when execute then the existing room id is kept`() = runTest {
|
fun `given a local room id when execute then the existing room id is kept`() = runTest {
|
||||||
// Given
|
// Given
|
||||||
givenATombstoneEvent(
|
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||||
Event(
|
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aCreationState = LocalRoomCreationState.CREATED, aReplacementRoomId = AN_EXISTING_ROOM_ID)
|
||||||
roomId = A_LOCAL_ROOM_ID,
|
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(
|
||||||
type = EventType.STATE_ROOM_TOMBSTONE,
|
aCreateRoomParams = aCreateRoomParams,
|
||||||
stateKey = "",
|
aCreationState = LocalRoomCreationState.CREATED,
|
||||||
content = RoomTombstoneContent(replacementRoomId = AN_EXISTING_ROOM_ID).toContent()
|
aReplacementRoomId = AN_EXISTING_ROOM_ID
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// When
|
// When
|
||||||
|
@ -105,20 +100,18 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
||||||
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
verifyTombstoneEvent(AN_EXISTING_ROOM_ID)
|
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||||
result shouldBeEqualTo AN_EXISTING_ROOM_ID
|
result shouldBeEqualTo AN_EXISTING_ROOM_ID
|
||||||
|
aLocalRoomSummaryEntity.replacementRoomId shouldBeEqualTo AN_EXISTING_ROOM_ID
|
||||||
|
aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.CREATED
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given a local room id when execute then it is correctly executed`() = runTest {
|
fun `given a local room id when execute then it is correctly executed`() = runTest {
|
||||||
// Given
|
// Given
|
||||||
val aCreateRoomParams = mockk<CreateRoomParams>()
|
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||||
val aLocalRoomSummaryEntity = mockk<LocalRoomSummaryEntity> {
|
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||||
every { roomSummaryEntity } returns mockk(relaxed = true)
|
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||||
every { createRoomParams } returns aCreateRoomParams
|
|
||||||
}
|
|
||||||
givenATombstoneEvent(null)
|
|
||||||
givenALocalRoomSummaryEntity(aLocalRoomSummaryEntity)
|
|
||||||
|
|
||||||
coEvery { createRoomTask.execute(any()) } returns A_ROOM_ID
|
coEvery { createRoomTask.execute(any()) } returns A_ROOM_ID
|
||||||
|
|
||||||
|
@ -127,32 +120,84 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
||||||
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
verifyTombstoneEvent(null)
|
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||||
// CreateRoomTask has been called with the initial CreateRoomParams
|
// CreateRoomTask has been called with the initial CreateRoomParams
|
||||||
coVerify { createRoomTask.execute(aCreateRoomParams) }
|
coVerify { createRoomTask.execute(aCreateRoomParams) }
|
||||||
// The resulting roomId matches the roomId returned by the createRoomTask
|
// The resulting roomId matches the roomId returned by the createRoomTask
|
||||||
result shouldBeEqualTo A_ROOM_ID
|
result shouldBeEqualTo A_ROOM_ID
|
||||||
// A tombstone state event has been created
|
// The room creation state has correctly been updated
|
||||||
coVerify { CurrentStateEventEntity.getOrCreate(realm = any(), roomId = A_LOCAL_ROOM_ID, stateKey = any(), type = EventType.STATE_ROOM_TOMBSTONE) }
|
verifyOrder {
|
||||||
|
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATING
|
||||||
|
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATED
|
||||||
|
}
|
||||||
|
// The local room summary has been updated with the created room id
|
||||||
|
verify { aLocalRoomSummaryEntity.replacementRoomId = A_ROOM_ID }
|
||||||
|
aLocalRoomSummaryEntity.replacementRoomId shouldBeEqualTo A_ROOM_ID
|
||||||
|
aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.CREATED
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun givenATombstoneEvent(event: Event?) {
|
@Test
|
||||||
fakeStateEventDataSource.givenGetStateEventReturns(event)
|
fun `given a local room id when execute with an exception then the creation state is correctly updated`() = runTest {
|
||||||
|
// Given
|
||||||
|
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||||
|
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||||
|
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||||
|
|
||||||
|
coEvery { createRoomTask.execute(any()) }.throws(mockk())
|
||||||
|
|
||||||
|
// When
|
||||||
|
val params = CreateRoomFromLocalRoomTask.Params(A_LOCAL_ROOM_ID)
|
||||||
|
tryOrNull { defaultCreateRoomFromLocalRoomTask.execute(params) }
|
||||||
|
|
||||||
|
// Then
|
||||||
|
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||||
|
// CreateRoomTask has been called with the initial CreateRoomParams
|
||||||
|
coVerify { createRoomTask.execute(aCreateRoomParams) }
|
||||||
|
// The room creation state has correctly been updated
|
||||||
|
verifyOrder {
|
||||||
|
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.CREATING
|
||||||
|
aLocalRoomSummaryEntity.creationState = LocalRoomCreationState.FAILURE
|
||||||
|
}
|
||||||
|
// The local room summary has been updated with the created room id
|
||||||
|
aLocalRoomSummaryEntity.replacementRoomId.shouldBeNull()
|
||||||
|
aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.FAILURE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun givenALocalRoomSummaryEntity(localRoomSummaryEntity: LocalRoomSummaryEntity) {
|
private fun givenALocalRoomSummary(
|
||||||
|
aCreateRoomParams: CreateRoomParams,
|
||||||
|
aCreationState: LocalRoomCreationState = LocalRoomCreationState.NOT_CREATED,
|
||||||
|
aReplacementRoomId: String? = null
|
||||||
|
): LocalRoomSummary {
|
||||||
|
val aLocalRoomSummary = LocalRoomSummary(
|
||||||
|
roomId = A_LOCAL_ROOM_ID,
|
||||||
|
roomSummary = mockk(relaxed = true),
|
||||||
|
createRoomParams = aCreateRoomParams,
|
||||||
|
creationState = aCreationState,
|
||||||
|
replacementRoomId = aReplacementRoomId,
|
||||||
|
)
|
||||||
|
fakeRoomSummaryDataSource.givenGetLocalRoomSummaryReturns(A_LOCAL_ROOM_ID, aLocalRoomSummary)
|
||||||
|
return aLocalRoomSummary
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenALocalRoomSummaryEntity(
|
||||||
|
aCreateRoomParams: CreateRoomParams,
|
||||||
|
aCreationState: LocalRoomCreationState = LocalRoomCreationState.NOT_CREATED,
|
||||||
|
aReplacementRoomId: String? = null
|
||||||
|
): LocalRoomSummaryEntity {
|
||||||
|
val aLocalRoomSummaryEntity = spyk(LocalRoomSummaryEntity(
|
||||||
|
roomId = A_LOCAL_ROOM_ID,
|
||||||
|
roomSummaryEntity = mockk(relaxed = true),
|
||||||
|
replacementRoomId = aReplacementRoomId,
|
||||||
|
).apply {
|
||||||
|
createRoomParams = aCreateRoomParams
|
||||||
|
creationState = aCreationState
|
||||||
|
})
|
||||||
every {
|
every {
|
||||||
fakeMonarchy.fakeRealm.instance
|
fakeMonarchy.fakeRealm.instance
|
||||||
.where<LocalRoomSummaryEntity>()
|
.where<LocalRoomSummaryEntity>()
|
||||||
.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, A_LOCAL_ROOM_ID)
|
.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, A_LOCAL_ROOM_ID)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
} returns localRoomSummaryEntity
|
} returns aLocalRoomSummaryEntity
|
||||||
}
|
return aLocalRoomSummaryEntity
|
||||||
|
|
||||||
private fun verifyTombstoneEvent(expectedRoomId: String?) {
|
|
||||||
fakeStateEventDataSource.verifyGetStateEvent(A_LOCAL_ROOM_ID, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)
|
|
||||||
fakeStateEventDataSource.instance.getStateEvent(A_LOCAL_ROOM_ID, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)
|
|
||||||
?.content.toModel<RoomTombstoneContent>()
|
|
||||||
?.replacementRoomId shouldBeEqualTo expectedRoomId
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,11 @@ internal class FakeMonarchy {
|
||||||
} coAnswers {
|
} coAnswers {
|
||||||
firstArg<Monarchy.RealmBlock>().doWithRealm(fakeRealm.instance)
|
firstArg<Monarchy.RealmBlock>().doWithRealm(fakeRealm.instance)
|
||||||
}
|
}
|
||||||
|
coEvery {
|
||||||
|
instance.runTransactionSync(any())
|
||||||
|
} coAnswers {
|
||||||
|
firstArg<Realm.Transaction>().execute(fakeRealm.instance)
|
||||||
|
}
|
||||||
every { instance.realmConfiguration } returns mockk()
|
every { instance.realmConfiguration } returns mockk()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.test.fakes
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||||
|
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||||
|
|
||||||
|
internal class FakeRoomSummaryDataSource {
|
||||||
|
|
||||||
|
val instance: RoomSummaryDataSource = mockk()
|
||||||
|
|
||||||
|
fun givenGetLocalRoomSummaryReturns(roomId: String?, localRoomSummary: LocalRoomSummary?) {
|
||||||
|
every { instance.getLocalRoomSummary(roomId = roomId ?: any()) } returns localRoomSummary
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyGetLocalRoomSummary(roomId: String) {
|
||||||
|
verify { instance.getLocalRoomSummary(roomId) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,7 +51,7 @@ sealed class RoomDetailViewEvents : VectorViewEvents {
|
||||||
object OpenRoomProfile : RoomDetailViewEvents()
|
object OpenRoomProfile : RoomDetailViewEvents()
|
||||||
data class ShowRoomAvatarFullScreen(val matrixItem: MatrixItem?, val view: View?) : RoomDetailViewEvents()
|
data class ShowRoomAvatarFullScreen(val matrixItem: MatrixItem?, val view: View?) : RoomDetailViewEvents()
|
||||||
|
|
||||||
object ShowWaitingView : RoomDetailViewEvents()
|
data class ShowWaitingView(val text: String? = null) : RoomDetailViewEvents()
|
||||||
object HideWaitingView : RoomDetailViewEvents()
|
object HideWaitingView : RoomDetailViewEvents()
|
||||||
|
|
||||||
data class DownloadFileState(
|
data class DownloadFileState(
|
||||||
|
|
|
@ -493,7 +493,7 @@ class TimelineFragment :
|
||||||
is RoomDetailViewEvents.ShowInfoOkDialog -> showDialogWithMessage(it.message)
|
is RoomDetailViewEvents.ShowInfoOkDialog -> showDialogWithMessage(it.message)
|
||||||
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
|
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
|
||||||
RoomDetailViewEvents.LeaveJitsiConference -> leaveJitsiConference()
|
RoomDetailViewEvents.LeaveJitsiConference -> leaveJitsiConference()
|
||||||
RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView()
|
is RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView(it.text)
|
||||||
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
|
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
|
||||||
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it)
|
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it)
|
||||||
is RoomDetailViewEvents.OpenRoom -> handleOpenRoom(it)
|
is RoomDetailViewEvents.OpenRoom -> handleOpenRoom(it)
|
||||||
|
|
|
@ -83,7 +83,6 @@ import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
import org.matrix.android.sdk.api.session.events.model.LocalEcho
|
||||||
import org.matrix.android.sdk.api.session.events.model.RelationType
|
import org.matrix.android.sdk.api.session.events.model.RelationType
|
||||||
|
@ -100,9 +99,11 @@ import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
|
import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
||||||
|
@ -185,6 +186,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||||
init {
|
init {
|
||||||
// This method will take care of a null room to update the state.
|
// This method will take care of a null room to update the state.
|
||||||
observeRoomSummary()
|
observeRoomSummary()
|
||||||
|
observeLocalRoomSummary()
|
||||||
if (room == null) {
|
if (room == null) {
|
||||||
timeline = null
|
timeline = null
|
||||||
} else {
|
} else {
|
||||||
|
@ -617,7 +619,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleAddJitsiConference(action: RoomDetailAction.AddJitsiWidget) {
|
private fun handleAddJitsiConference(action: RoomDetailAction.AddJitsiWidget) {
|
||||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView())
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val widget = jitsiService.createJitsiWidget(initialState.roomId, action.withVideo)
|
val widget = jitsiService.createJitsiWidget(initialState.roomId, action.withVideo)
|
||||||
|
@ -637,7 +639,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||||
if (isJitsiWidget) {
|
if (isJitsiWidget) {
|
||||||
setState { copy(jitsiState = jitsiState.copy(deleteWidgetInProgress = true)) }
|
setState { copy(jitsiState = jitsiState.copy(deleteWidgetInProgress = true)) }
|
||||||
} else {
|
} else {
|
||||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView())
|
||||||
}
|
}
|
||||||
session.widgetService().destroyRoomWidget(initialState.roomId, widgetId)
|
session.widgetService().destroyRoomWidget(initialState.roomId, widgetId)
|
||||||
// local echo
|
// local echo
|
||||||
|
@ -1231,6 +1233,28 @@ class TimelineViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun observeLocalRoomSummary() {
|
||||||
|
if (room != null && RoomLocalEcho.isLocalEchoId(room.roomId)) {
|
||||||
|
room.flow().liveLocalRoomSummary()
|
||||||
|
.unwrap()
|
||||||
|
.map { it.creationState }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.onEach { creationState ->
|
||||||
|
when (creationState) {
|
||||||
|
LocalRoomCreationState.NOT_CREATED -> Unit
|
||||||
|
LocalRoomCreationState.CREATING ->
|
||||||
|
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView(stringProvider.getString(R.string.creating_direct_room)))
|
||||||
|
LocalRoomCreationState.FAILURE -> {
|
||||||
|
_viewEvents.post(RoomDetailViewEvents.HideWaitingView)
|
||||||
|
}
|
||||||
|
LocalRoomCreationState.CREATED ->
|
||||||
|
_viewEvents.post(RoomDetailViewEvents.OpenRoom(room.localRoomSummary()?.replacementRoomId!!, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getUnreadState() {
|
private fun getUnreadState() {
|
||||||
if (room == null) return
|
if (room == null) return
|
||||||
combine(
|
combine(
|
||||||
|
@ -1322,26 +1346,11 @@ class TimelineViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)?.also {
|
room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)?.also {
|
||||||
onRoomTombstoneUpdated(it)
|
setState { copy(tombstoneEvent = it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var roomTombstoneHandled = false
|
|
||||||
private fun onRoomTombstoneUpdated(tombstoneEvent: Event) = withState { state ->
|
|
||||||
if (roomTombstoneHandled) return@withState
|
|
||||||
if (state.isLocalRoom()) {
|
|
||||||
// Local room has been replaced, so navigate to the new room
|
|
||||||
val roomId = tombstoneEvent.getClearContent()?.toModel<RoomTombstoneContent>()
|
|
||||||
?.replacementRoomId
|
|
||||||
?: return@withState
|
|
||||||
_viewEvents.post(RoomDetailViewEvents.OpenRoom(roomId, closeCurrentRoom = true))
|
|
||||||
roomTombstoneHandled = true
|
|
||||||
} else {
|
|
||||||
setState { copy(tombstoneEvent = tombstoneEvent) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigates to the appropriate event (by paginating the thread timeline until the event is found
|
* Navigates to the appropriate event (by paginating the thread timeline until the event is found
|
||||||
* in the snapshot. The main reason for this function is to support the /relations api
|
* in the snapshot. The main reason for this function is to support the /relations api
|
||||||
|
|
Loading…
Reference in a new issue