mirror of
https://github.com/element-hq/element-android
synced 2024-11-22 09:25:33 +03:00
Start DM - Add loading wheel while creating the room
This commit is contained in:
parent
824a4bcae5
commit
e2f0e14133
20 changed files with 429 additions and 145 deletions
|
@ -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.members.RoomMemberQueryParams
|
||||
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.RoomMemberSummary
|
||||
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>> {
|
||||
return room.membershipService().getRoomMembersLive(queryParams).asFlow()
|
||||
.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.location.LocationSharingService
|
||||
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.relation.RelationService
|
||||
import org.matrix.android.sdk.api.session.room.notification.RoomPushRuleService
|
||||
|
@ -60,11 +61,22 @@ interface Room {
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -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.room.alias.RoomAliasDescription
|
||||
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.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
@ -117,6 +118,12 @@ interface RoomService {
|
|||
*/
|
||||
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.
|
||||
* @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.MigrateSessionTo035
|
||||
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.database.MatrixRealmMigration
|
||||
import javax.inject.Inject
|
||||
|
@ -61,7 +62,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
|||
private val normalizer: Normalizer
|
||||
) : MatrixRealmMigration(
|
||||
dbName = "Session",
|
||||
schemaVersion = 36L,
|
||||
schemaVersion = 37L,
|
||||
) {
|
||||
/**
|
||||
* Forces all RealmSessionStoreMigration instances to be equal.
|
||||
|
@ -107,5 +108,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
|
|||
if (oldVersion < 34) MigrateSessionTo034(realm).perform()
|
||||
if (oldVersion < 35) MigrateSessionTo035(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.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.toJSONString
|
||||
|
||||
internal open class LocalRoomSummaryEntity(
|
||||
@PrimaryKey var roomId: String = "",
|
||||
var roomSummaryEntity: RoomSummaryEntity? = null,
|
||||
private var createRoomParamsStr: String? = null
|
||||
var replacementRoomId: String? = null,
|
||||
) : 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?
|
||||
get() {
|
||||
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.LocalRoomSummaryEntityFields
|
||||
|
||||
internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String? = null): RealmQuery<LocalRoomSummaryEntity> {
|
||||
val query = realm.where<LocalRoomSummaryEntity>()
|
||||
if (roomId != null) {
|
||||
query.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId)
|
||||
}
|
||||
return query
|
||||
internal fun LocalRoomSummaryEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<LocalRoomSummaryEntity> {
|
||||
return realm.where<LocalRoomSummaryEntity>().equalTo(LocalRoomSummaryEntityFields.ROOM_ID, roomId)
|
||||
}
|
||||
|
|
|
@ -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.location.LocationSharingService
|
||||
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.RoomType
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationService
|
||||
|
@ -82,6 +83,14 @@ internal class DefaultRoom(
|
|||
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? {
|
||||
if (roomSummary()?.roomType != RoomType.SPACE) return null
|
||||
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.alias.RoomAliasDescription
|
||||
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.RoomMemberSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
|
@ -106,6 +107,10 @@ internal class DefaultRoomService @Inject constructor(
|
|||
return roomSummaryDataSource.getRoomSummaryLive(roomId)
|
||||
}
|
||||
|
||||
override fun getLocalRoomSummaryLive(roomId: String): LiveData<Optional<LocalRoomSummary>> {
|
||||
return roomSummaryDataSource.getLocalRoomSummaryLive(roomId)
|
||||
}
|
||||
|
||||
override fun getRoomSummaries(
|
||||
queryParams: RoomSummaryQueryParams,
|
||||
sortOrder: RoomSortOrder
|
||||
|
|
|
@ -18,36 +18,22 @@ package org.matrix.android.sdk.internal.session.room.create
|
|||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
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.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.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.api.session.room.model.LocalRoomCreationState
|
||||
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.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.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.RoomSummaryEntity
|
||||
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.getOrCreate
|
||||
import org.matrix.android.sdk.internal.database.query.where
|
||||
import org.matrix.android.sdk.internal.database.query.whereRoomId
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||
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 javax.inject.Inject
|
||||
|
||||
|
@ -55,94 +41,85 @@ import javax.inject.Inject
|
|||
* 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 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> {
|
||||
data class Params(val localRoomId: String)
|
||||
}
|
||||
|
||||
internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val createRoomTask: CreateRoomTask,
|
||||
private val stateEventDataSource: StateEventDataSource,
|
||||
private val clock: Clock,
|
||||
private val roomSummaryDataSource: RoomSummaryDataSource,
|
||||
) : CreateRoomFromLocalRoomTask {
|
||||
|
||||
private val realmConfiguration
|
||||
get() = monarchy.realmConfiguration
|
||||
|
||||
override suspend fun execute(params: CreateRoomFromLocalRoomTask.Params): String {
|
||||
// If a room has already been created for the given local room, return the existing roomId
|
||||
val replacementRoomId = stateEventDataSource.getStateEvent(params.localRoomId, EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)
|
||||
?.content.toModel<RoomTombstoneContent>()
|
||||
?.replacementRoomId
|
||||
val localRoomSummary = roomSummaryDataSource.getLocalRoomSummary(params.localRoomId)
|
||||
?.takeIf { it.createRoomParams != null && it.roomSummary != null }
|
||||
?: error("Invalid LocalRoomSummary for ${params.localRoomId}")
|
||||
|
||||
if (replacementRoomId != null) {
|
||||
// If a room has already been created for the given local room, return the existing roomId
|
||||
if (localRoomSummary.replacementRoomId != null) {
|
||||
return localRoomSummary.replacementRoomId
|
||||
}
|
||||
|
||||
return createRoom(localRoomSummary)
|
||||
}
|
||||
|
||||
private suspend fun createRoom(localRoomSummary: LocalRoomSummary): String {
|
||||
updateCreationState(localRoomSummary.roomId, LocalRoomCreationState.CREATING)
|
||||
val replacementRoomId = runCatching {
|
||||
createRoomTask.execute(localRoomSummary.createRoomParams!!)
|
||||
}.fold(
|
||||
{ it },
|
||||
{
|
||||
updateCreationState(roomId = localRoomSummary.roomId, LocalRoomCreationState.FAILURE)
|
||||
throw it
|
||||
}
|
||||
)
|
||||
updateReplacementRoomId(localRoomSummary.roomId, replacementRoomId)
|
||||
waitForRoomEvents(replacementRoomId, localRoomSummary.roomSummary!!)
|
||||
updateCreationState(localRoomSummary.roomId, LocalRoomCreationState.CREATED)
|
||||
return replacementRoomId
|
||||
}
|
||||
|
||||
var createRoomParams: CreateRoomParams? = null
|
||||
var isEncrypted = false
|
||||
monarchy.doWithRealm { realm ->
|
||||
LocalRoomSummaryEntity.where(realm, params.localRoomId)
|
||||
.findFirst()
|
||||
?.let {
|
||||
createRoomParams = it.createRoomParams
|
||||
isEncrypted = it.roomSummaryEntity?.isEncrypted.orFalse()
|
||||
}
|
||||
}
|
||||
val roomId = createRoomTask.execute(createRoomParams!!)
|
||||
|
||||
/**
|
||||
* Wait for all the room events before triggering the created state.
|
||||
*/
|
||||
private suspend fun waitForRoomEvents(replacementRoomId: String, roomSummary: RoomSummary) {
|
||||
try {
|
||||
// Wait for all the room events before triggering the replacement room
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
realm.where(RoomSummaryEntity::class.java)
|
||||
.equalTo(RoomSummaryEntityFields.ROOM_ID, roomId)
|
||||
.equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, createRoomParams?.invitedUserIds?.size ?: 0)
|
||||
.equalTo(RoomSummaryEntityFields.ROOM_ID, replacementRoomId)
|
||||
.equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, roomSummary.invitedMembersCount)
|
||||
}
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
EventEntity.whereRoomId(realm, roomId)
|
||||
EventEntity.whereRoomId(realm, replacementRoomId)
|
||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_HISTORY_VISIBILITY)
|
||||
}
|
||||
if (isEncrypted) {
|
||||
if (roomSummary.isEncrypted) {
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
EventEntity.whereRoomId(realm, roomId)
|
||||
EventEntity.whereRoomId(realm, replacementRoomId)
|
||||
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_ENCRYPTION)
|
||||
}
|
||||
}
|
||||
} catch (exception: TimeoutCancellationException) {
|
||||
throw CreateRoomFailure.CreatedWithTimeout(roomId)
|
||||
updateCreationState(roomSummary.roomId, LocalRoomCreationState.FAILURE)
|
||||
throw CreateRoomFailure.CreatedWithTimeout(replacementRoomId)
|
||||
}
|
||||
}
|
||||
|
||||
createTombstoneEvent(params, roomId)
|
||||
return roomId
|
||||
private fun updateCreationState(roomId: String, creationState: LocalRoomCreationState) {
|
||||
monarchy.runTransactionSync { realm ->
|
||||
LocalRoomSummaryEntity.where(realm, roomId).findFirst()?.creationState = creationState
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Tombstone event to indicate that the local room has been replaced by a new one.
|
||||
*/
|
||||
private suspend fun createTombstoneEvent(params: CreateRoomFromLocalRoomTask.Params, roomId: String) {
|
||||
val now = clock.epochMillis()
|
||||
val event = Event(
|
||||
type = EventType.STATE_ROOM_TOMBSTONE,
|
||||
senderId = userId,
|
||||
originServerTs = now,
|
||||
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
|
||||
}
|
||||
}
|
||||
private fun updateReplacementRoomId(localRoomId: String, replacementRoomId: String) {
|
||||
monarchy.runTransactionSync { realm ->
|
||||
LocalRoomSummaryEntity.where(realm, localRoomId).findFirst()?.replacementRoomId = replacementRoomId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.RoomSummaryQueryParams
|
||||
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.RoomSummary
|
||||
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.util.Optional
|
||||
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.model.LocalRoomSummaryEntity
|
||||
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.query.findByAlias
|
||||
|
@ -57,6 +60,7 @@ import javax.inject.Inject
|
|||
internal class RoomSummaryDataSource @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val roomSummaryMapper: RoomSummaryMapper,
|
||||
private val localRoomSummaryMapper: LocalRoomSummaryMapper,
|
||||
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(
|
||||
queryParams: RoomSummaryQueryParams,
|
||||
sortOrder: RoomSortOrder = RoomSortOrder.NONE
|
||||
|
|
|
@ -22,21 +22,22 @@ import io.mockk.coVerify
|
|||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.spyk
|
||||
import io.mockk.unmockkAll
|
||||
import io.mockk.verify
|
||||
import io.mockk.verifyOrder
|
||||
import io.realm.kotlin.where
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.amshove.kluent.shouldBeEqualTo
|
||||
import org.amshove.kluent.shouldBeNull
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
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.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomCreationState
|
||||
import org.matrix.android.sdk.api.session.room.model.LocalRoomSummary
|
||||
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.model.CurrentStateEventEntity
|
||||
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.query.copyToRealmOrIgnore
|
||||
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.FakeStateEventDataSource
|
||||
import org.matrix.android.sdk.test.fakes.FakeRoomSummaryDataSource
|
||||
|
||||
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 A_ROOM_ID = "a-room-id"
|
||||
private const val MY_USER_ID = "my-user-id"
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
||||
|
||||
private val fakeMonarchy = FakeMonarchy()
|
||||
private val clock = DefaultClock()
|
||||
private val createRoomTask = mockk<CreateRoomTask>()
|
||||
private val fakeStateEventDataSource = FakeStateEventDataSource()
|
||||
private val fakeRoomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||
|
||||
private val defaultCreateRoomFromLocalRoomTask = DefaultCreateRoomFromLocalRoomTask(
|
||||
userId = MY_USER_ID,
|
||||
monarchy = fakeMonarchy.instance,
|
||||
createRoomTask = createRoomTask,
|
||||
stateEventDataSource = fakeStateEventDataSource.instance,
|
||||
clock = clock
|
||||
roomSummaryDataSource = fakeRoomSummaryDataSource.instance,
|
||||
)
|
||||
|
||||
@Before
|
||||
|
@ -91,13 +87,12 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
|||
@Test
|
||||
fun `given a local room id when execute then the existing room id is kept`() = runTest {
|
||||
// Given
|
||||
givenATombstoneEvent(
|
||||
Event(
|
||||
roomId = A_LOCAL_ROOM_ID,
|
||||
type = EventType.STATE_ROOM_TOMBSTONE,
|
||||
stateKey = "",
|
||||
content = RoomTombstoneContent(replacementRoomId = AN_EXISTING_ROOM_ID).toContent()
|
||||
)
|
||||
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aCreationState = LocalRoomCreationState.CREATED, aReplacementRoomId = AN_EXISTING_ROOM_ID)
|
||||
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(
|
||||
aCreateRoomParams = aCreateRoomParams,
|
||||
aCreationState = LocalRoomCreationState.CREATED,
|
||||
aReplacementRoomId = AN_EXISTING_ROOM_ID
|
||||
)
|
||||
|
||||
// When
|
||||
|
@ -105,20 +100,18 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
|||
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
||||
|
||||
// Then
|
||||
verifyTombstoneEvent(AN_EXISTING_ROOM_ID)
|
||||
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||
result shouldBeEqualTo AN_EXISTING_ROOM_ID
|
||||
aLocalRoomSummaryEntity.replacementRoomId shouldBeEqualTo AN_EXISTING_ROOM_ID
|
||||
aLocalRoomSummaryEntity.creationState shouldBeEqualTo LocalRoomCreationState.CREATED
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a local room id when execute then it is correctly executed`() = runTest {
|
||||
// Given
|
||||
val aCreateRoomParams = mockk<CreateRoomParams>()
|
||||
val aLocalRoomSummaryEntity = mockk<LocalRoomSummaryEntity> {
|
||||
every { roomSummaryEntity } returns mockk(relaxed = true)
|
||||
every { createRoomParams } returns aCreateRoomParams
|
||||
}
|
||||
givenATombstoneEvent(null)
|
||||
givenALocalRoomSummaryEntity(aLocalRoomSummaryEntity)
|
||||
val aCreateRoomParams = mockk<CreateRoomParams>(relaxed = true)
|
||||
givenALocalRoomSummary(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||
val aLocalRoomSummaryEntity = givenALocalRoomSummaryEntity(aCreateRoomParams = aCreateRoomParams, aReplacementRoomId = null)
|
||||
|
||||
coEvery { createRoomTask.execute(any()) } returns A_ROOM_ID
|
||||
|
||||
|
@ -127,32 +120,84 @@ internal class DefaultCreateRoomFromLocalRoomTaskTest {
|
|||
val result = defaultCreateRoomFromLocalRoomTask.execute(params)
|
||||
|
||||
// Then
|
||||
verifyTombstoneEvent(null)
|
||||
fakeRoomSummaryDataSource.verifyGetLocalRoomSummary(A_LOCAL_ROOM_ID)
|
||||
// CreateRoomTask has been called with the initial CreateRoomParams
|
||||
coVerify { createRoomTask.execute(aCreateRoomParams) }
|
||||
// The resulting roomId matches the roomId returned by the createRoomTask
|
||||
result shouldBeEqualTo A_ROOM_ID
|
||||
// A tombstone state event has been created
|
||||
coVerify { CurrentStateEventEntity.getOrCreate(realm = any(), roomId = A_LOCAL_ROOM_ID, stateKey = any(), type = EventType.STATE_ROOM_TOMBSTONE) }
|
||||
// The room creation state has correctly been updated
|
||||
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?) {
|
||||
fakeStateEventDataSource.givenGetStateEventReturns(event)
|
||||
@Test
|
||||
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 {
|
||||
fakeMonarchy.fakeRealm.instance
|
||||
.where<LocalRoomSummaryEntity>()
|
||||
.equalTo(LocalRoomSummaryEntityFields.ROOM_ID, A_LOCAL_ROOM_ID)
|
||||
.findFirst()
|
||||
} returns localRoomSummaryEntity
|
||||
}
|
||||
|
||||
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
|
||||
} returns aLocalRoomSummaryEntity
|
||||
return aLocalRoomSummaryEntity
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,11 @@ internal class FakeMonarchy {
|
|||
} coAnswers {
|
||||
firstArg<Monarchy.RealmBlock>().doWithRealm(fakeRealm.instance)
|
||||
}
|
||||
coEvery {
|
||||
instance.runTransactionSync(any())
|
||||
} coAnswers {
|
||||
firstArg<Realm.Transaction>().execute(fakeRealm.instance)
|
||||
}
|
||||
every { instance.realmConfiguration } returns mockk()
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.api.session.room.model.RoomSummary
|
||||
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()
|
||||
data class ShowRoomAvatarFullScreen(val matrixItem: MatrixItem?, val view: View?) : RoomDetailViewEvents()
|
||||
|
||||
object ShowWaitingView : RoomDetailViewEvents()
|
||||
data class ShowWaitingView(val text: String? = null) : RoomDetailViewEvents()
|
||||
object HideWaitingView : RoomDetailViewEvents()
|
||||
|
||||
data class DownloadFileState(
|
||||
|
|
|
@ -493,7 +493,7 @@ class TimelineFragment :
|
|||
is RoomDetailViewEvents.ShowInfoOkDialog -> showDialogWithMessage(it.message)
|
||||
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
|
||||
RoomDetailViewEvents.LeaveJitsiConference -> leaveJitsiConference()
|
||||
RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView()
|
||||
is RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView(it.text)
|
||||
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
|
||||
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(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.session.Session
|
||||
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.LocalEcho
|
||||
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.members.ChangeMembershipState
|
||||
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.RoomMemberSummary
|
||||
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.relation.RelationDefaultContent
|
||||
import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent
|
||||
|
@ -185,6 +186,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
init {
|
||||
// This method will take care of a null room to update the state.
|
||||
observeRoomSummary()
|
||||
observeLocalRoomSummary()
|
||||
if (room == null) {
|
||||
timeline = null
|
||||
} else {
|
||||
|
@ -617,7 +619,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun handleAddJitsiConference(action: RoomDetailAction.AddJitsiWidget) {
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView())
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val widget = jitsiService.createJitsiWidget(initialState.roomId, action.withVideo)
|
||||
|
@ -637,7 +639,7 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
if (isJitsiWidget) {
|
||||
setState { copy(jitsiState = jitsiState.copy(deleteWidgetInProgress = true)) }
|
||||
} else {
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView())
|
||||
}
|
||||
session.widgetService().destroyRoomWidget(initialState.roomId, widgetId)
|
||||
// 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() {
|
||||
if (room == null) return
|
||||
combine(
|
||||
|
@ -1322,26 +1346,11 @@ class TimelineViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
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
|
||||
* in the snapshot. The main reason for this function is to support the /relations api
|
||||
|
|
Loading…
Reference in a new issue