Tombstone : handle joining viaserver params

This commit is contained in:
ganfra
2019-07-26 19:17:12 +02:00
parent 9a1e16a170
commit ac38a6461c
28 changed files with 293 additions and 82 deletions

View File

@ -123,9 +123,9 @@ object MatrixPatterns {
*/
fun isEventId(str: String?): Boolean {
return str != null
&& (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
&& (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
}
/**
@ -137,4 +137,23 @@ object MatrixPatterns {
fun isGroupId(str: String?): Boolean {
return str != null && str matches PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
}
/**
* Extract server name from a matrix id
*
* @param matrixId
* @return null if not found or if matrixId is null
*/
fun extractServerNameFromId(matrixId: String?): String? {
if (matrixId == null) {
return null
}
val index = matrixId.lastIndexOf(":")
return if (index == -1) {
null
} else matrixId.substring(index + 1)
}
}

View File

@ -34,11 +34,6 @@ interface RoomDirectoryService {
publicRoomsParams: PublicRoomsParams,
callback: MatrixCallback<PublicRoomsResponse>): Cancelable
/**
* Join a room by id
*/
fun joinRoom(roomId: String,
callback: MatrixCallback<Unit>)
/**
* Fetches the overall metadata about protocols supported by the homeserver.

View File

@ -32,6 +32,15 @@ interface RoomService {
fun createRoom(createRoomParams: CreateRoomParams,
callback: MatrixCallback<String>)
/**
* Join a room by id
* @param roomId the roomId of the room to join
* @param viaServers the servers to attempt to join the room through. One of the servers must be participating in the room.
*/
fun joinRoom(roomId: String,
viaServers: List<String> = emptyList(),
callback: MatrixCallback<Unit>)
/**
* Get a room from a roomId
* @param roomId the roomId to look for.

View File

@ -57,7 +57,7 @@ interface MembershipService {
/**
* Join the room, or accept an invitation.
*/
fun join(callback: MatrixCallback<Unit>)
fun join(viaServers: List<String> = emptyList(), callback: MatrixCallback<Unit>)
/**
* Leave the room, or reject an invitation.

View File

@ -35,5 +35,9 @@ data class RoomSummary(
val highlightCount: Int = 0,
val tags: List<RoomTag> = emptyList(),
val membership: Membership = Membership.NONE,
val isVersioned: Boolean = false
)
val versioningState: VersioningState = VersioningState.NONE
) {
val isVersioned: Boolean
get() = versioningState != VersioningState.NONE
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.model
enum class VersioningState {
NONE,
UPGRADED_ROOM_NOT_JOINED,
UPGRADED_ROOM_JOINED
}

View File

@ -62,7 +62,7 @@ internal class RoomSummaryMapper @Inject constructor(
notificationCount = roomSummaryEntity.notificationCount,
tags = tags,
membership = roomSummaryEntity.membership,
isVersioned = roomSummaryEntity.isVersioned
versioningState = roomSummaryEntity.versioningState
)
}
}

View File

@ -17,6 +17,7 @@
package im.vector.matrix.android.internal.database.model
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.VersioningState
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
@ -35,17 +36,23 @@ internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "",
var otherMemberIds: RealmList<String> = RealmList(),
var notificationCount: Int = 0,
var highlightCount: Int = 0,
var tags: RealmList<RoomTagEntity> = RealmList(),
var isVersioned: Boolean = false
var tags: RealmList<RoomTagEntity> = RealmList()
) : RealmObject() {
private var membershipStr: String = Membership.NONE.name
private var versioningStateStr: String = VersioningState.NONE.name
@delegate:Ignore
var membership: Membership by Delegates.observable(Membership.valueOf(membershipStr)) { _, _, newValue ->
membershipStr = newValue.name
}
@delegate:Ignore
var versioningState: VersioningState by Delegates.observable(VersioningState.valueOf(versioningStateStr)) { _, _, newValue ->
versioningStateStr = newValue.name
}
companion object
}

View File

@ -37,6 +37,7 @@ import im.vector.matrix.android.internal.network.AccessTokenInterceptor
import im.vector.matrix.android.internal.network.RetrofitFactory
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
import im.vector.matrix.android.internal.session.room.EventRelationsAggregationUpdater
import im.vector.matrix.android.internal.session.room.create.RoomCreateEventLiveObserver
import im.vector.matrix.android.internal.session.room.tombstone.RoomTombstoneEventLiveObserver
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
import im.vector.matrix.android.internal.util.md5
@ -131,8 +132,11 @@ internal abstract class SessionModule {
@Binds
@IntoSet
abstract fun bindRoomCreateEventLiveObserver(roomTombstoneEventLiveObserver: RoomTombstoneEventLiveObserver): LiveEntityObserver
abstract fun bindRoomTombstoneEventLiveObserver(roomTombstoneEventLiveObserver: RoomTombstoneEventLiveObserver): LiveEntityObserver
@Binds
@IntoSet
abstract fun bindRoomCreateEventLiveObserver(roomCreateEventLiveObserver: RoomCreateEventLiveObserver): LiveEntityObserver
@Binds
abstract fun bindInitialSyncProgressService(initialSyncProgressService: DefaultInitialSyncProgressService): InitialSyncProgressService

View File

@ -31,7 +31,6 @@ import im.vector.matrix.android.internal.task.toConfigurableTask
import javax.inject.Inject
internal class DefaultRoomDirectoryService @Inject constructor(private val getPublicRoomTask: GetPublicRoomTask,
private val joinRoomTask: JoinRoomTask,
private val getThirdPartyProtocolsTask: GetThirdPartyProtocolsTask,
private val taskExecutor: TaskExecutor) : RoomDirectoryService {
@ -44,13 +43,6 @@ internal class DefaultRoomDirectoryService @Inject constructor(private val getPu
.executeBy(taskExecutor)
}
override fun joinRoom(roomId: String, callback: MatrixCallback<Unit>) {
joinRoomTask
.configureWith(JoinRoomTask.Params(roomId))
.dispatchTo(callback)
.executeBy(taskExecutor)
}
override fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>) {
getThirdPartyProtocolsTask
.toConfigurableTask()

View File

@ -22,6 +22,7 @@ import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.RoomService
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.VersioningState
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper
import im.vector.matrix.android.internal.database.model.RoomEntity
@ -29,6 +30,7 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.fetchManaged
@ -37,6 +39,7 @@ import javax.inject.Inject
internal class DefaultRoomService @Inject constructor(private val monarchy: Monarchy,
private val roomSummaryMapper: RoomSummaryMapper,
private val createRoomTask: CreateRoomTask,
private val joinRoomTask: JoinRoomTask,
private val roomFactory: RoomFactory,
private val taskExecutor: TaskExecutor) : RoomService {
@ -57,9 +60,16 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona
{ realm ->
RoomSummaryEntity.where(realm)
.isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME)
.notEqualTo(RoomSummaryEntityFields.IS_VERSIONED, true)
.notEqualTo(RoomSummaryEntityFields.VERSIONING_STATE_STR, VersioningState.UPGRADED_ROOM_JOINED.name)
},
{ roomSummaryMapper.map(it) }
)
}
override fun joinRoom(roomId: String, viaServers: List<String>, callback: MatrixCallback<Unit>) {
joinRoomTask
.configureWith(JoinRoomTask.Params(roomId, viaServers))
.dispatchTo(callback)
.executeBy(taskExecutor)
}
}

View File

@ -218,6 +218,7 @@ internal interface RoomAPI {
*/
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/join")
fun join(@Path("roomId") roomId: String,
@Query("server_name") viaServers: List<String>,
@Body params: Map<String, String>): Call<Unit>
/**

View File

@ -0,0 +1,74 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.create
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.VersioningState
import im.vector.matrix.android.api.session.room.model.create.RoomCreateContent
import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.types
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.di.SessionDatabase
import io.realm.OrderedCollectionChangeSet
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmResults
import javax.inject.Inject
internal class RoomCreateEventLiveObserver @Inject constructor(@SessionDatabase
realmConfiguration: RealmConfiguration)
: RealmLiveEntityObserver<EventEntity>(realmConfiguration) {
override val query = Monarchy.Query<EventEntity> {
EventEntity.types(it, listOf(EventType.STATE_ROOM_CREATE))
}
override fun onChange(results: RealmResults<EventEntity>, changeSet: OrderedCollectionChangeSet) {
changeSet.insertions
.asSequence()
.mapNotNull {
results[it]?.asDomain()
}
.toList()
.also {
handleRoomCreateEvents(it)
}
}
private fun handleRoomCreateEvents(createEvents: List<Event>) = Realm.getInstance(realmConfiguration).use {
it.executeTransactionAsync { realm ->
for (event in createEvents) {
val createRoomContent = event.getClearContent().toModel<RoomCreateContent>()
val predecessorRoomId = createRoomContent?.predecessor?.roomId ?: continue
val predecessorRoomSummary = RoomSummaryEntity.where(realm, predecessorRoomId).findFirst()
?: RoomSummaryEntity(predecessorRoomId)
predecessorRoomSummary.versioningState = VersioningState.UPGRADED_ROOM_JOINED
realm.insertOrUpdate(predecessorRoomSummary)
}
}
}
}

View File

@ -80,8 +80,8 @@ internal class DefaultMembershipService @Inject constructor(private val roomId:
.executeBy(taskExecutor)
}
override fun join(callback: MatrixCallback<Unit>) {
val params = JoinRoomTask.Params(roomId)
override fun join(viaServers: List<String>, callback: MatrixCallback<Unit>) {
val params = JoinRoomTask.Params(roomId, viaServers)
joinTask.configureWith(params)
.dispatchTo(callback)
.executeBy(taskExecutor)

View File

@ -25,7 +25,8 @@ import javax.inject.Inject
internal interface JoinRoomTask : Task<JoinRoomTask.Params, Unit> {
data class Params(
val roomId: String
val roomId: String,
val viaServers: List<String> = emptyList()
)
}
@ -33,7 +34,7 @@ internal class DefaultJoinRoomTask @Inject constructor(private val roomAPI: Room
override suspend fun execute(params: JoinRoomTask.Params): Try<Unit> {
return executeRequest {
apiCall = roomAPI.join(params.roomId, HashMap())
apiCall = roomAPI.join(params.roomId, params.viaServers, HashMap())
}
}

View File

@ -22,6 +22,7 @@ import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.VersioningState
import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
import im.vector.matrix.android.internal.database.RealmLiveEntityObserver
import im.vector.matrix.android.internal.database.mapper.asDomain
@ -64,8 +65,10 @@ internal class RoomTombstoneEventLiveObserver @Inject constructor(@SessionDataba
if (createRoomContent?.replacementRoom == null) continue
val predecessorRoomSummary = RoomSummaryEntity.where(realm, event.roomId).findFirst()
?: RoomSummaryEntity(event.roomId)
predecessorRoomSummary.isVersioned = true
?: RoomSummaryEntity(event.roomId)
if (predecessorRoomSummary.versioningState == VersioningState.NONE) {
predecessorRoomSummary.versioningState = VersioningState.UPGRADED_ROOM_NOT_JOINED
}
realm.insertOrUpdate(predecessorRoomSummary)
}