Start DM - Handle third party invites

This commit is contained in:
Florian Renaud 2022-07-02 00:11:41 +02:00
parent b14e3c61b3
commit 69917ebc2e
5 changed files with 95 additions and 6 deletions

View File

@ -70,6 +70,9 @@ object EventType {
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
const val STATE_ROOM_SERVER_ACL = "m.room.server_acl"
// This type is for local purposes, it should never be processed by the server
const val LOCAL_STATE_ROOM_THIRD_PARTY_INVITE = "local.room.third_party_invite"
// Call Events
const val CALL_INVITE = "m.call.invite"
const val CALL_CANDIDATES = "m.call.candidates"

View File

@ -0,0 +1,39 @@
/*
* 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.localecho
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.room.model.Membership
/**
* Class representing the EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE state event content
* This class is only used to store the third party invite data of a local room.
*/
@JsonClass(generateAdapter = true)
data class LocalRoomThirdPartyInviteContent(
@Json(name = "membership") val membership: Membership,
@Json(name = "displayname") val displayName: String? = null,
@Json(name = "is_direct") val isDirect: Boolean = false,
@Json(name = "third_party_invite") val thirdPartyInvite: LocalThreePid? = null,
)
@JsonClass(generateAdapter = true)
data class LocalThreePid(
val email: String? = null,
val msisdn: String? = null,
)

View File

@ -34,8 +34,11 @@ import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
import org.matrix.android.sdk.api.session.room.model.localecho.LocalRoomThirdPartyInviteContent
import org.matrix.android.sdk.api.session.room.model.localecho.LocalThreePid
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
@ -204,6 +207,7 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
val myUser = userService.getUser(userId) ?: User(userId)
val invitedUsers = createRoomBody.invitedUserIds.orEmpty()
.mapNotNull { tryOrNull { userService.resolveUser(it) } }
val invited3Pids = createRoomBody.invite3pids.orEmpty()
val createRoomEvent = createLocalEvent(
type = EventType.STATE_ROOM_CREATE,
@ -233,11 +237,40 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
)
}
val localRoomThreePidEvents = invited3Pids.map { body ->
createLocalEvent(
type = EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE,
content = LocalRoomThirdPartyInviteContent(
isDirect = createRoomBody.isDirect.orFalse(),
membership = Membership.INVITE,
displayName = body.address,
thirdPartyInvite = LocalThreePid(
msisdn = body.address.takeIf { body.medium == "msisdn" },
email = body.address.takeIf { body.medium == "email" }
)
).toContent()
)
}
val roomThreePidEvents = invited3Pids.map { body ->
createLocalEvent(
type = EventType.STATE_ROOM_THIRD_PARTY_INVITE,
content = RoomThirdPartyInviteContent(
displayName = body.address,
keyValidityUrl = null,
publicKey = null,
publicKeys = null
).toContent()
)
}
return buildList {
add(createRoomEvent)
add(myRoomMemberEvent)
addAll(createRoomBody.initialStates.orEmpty().map { createLocalEvent(it.type, it.content, it.stateKey) })
addAll(roomMemberEvents)
addAll(roomThreePidEvents)
addAll(localRoomThreePidEvents)
}
}

View File

@ -44,6 +44,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomNameContent
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
import org.matrix.android.sdk.api.session.room.model.localecho.LocalRoomThirdPartyInviteContent
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
@ -104,13 +105,11 @@ internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor(
val roomId = createRoomTask.execute(createRoomParams)
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.minus(1) + createRoomParams.invite3pids.size
)
.equalTo(RoomSummaryEntityFields.INVITED_MEMBERS_COUNT, createRoomParams.invitedUserIds.size.minus(1))
}
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
EventEntity.whereRoomId(realm, roomId)
@ -140,6 +139,7 @@ internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor(
stateEvents.forEach { event ->
createRoomParams = when (event.type) {
EventType.STATE_ROOM_MEMBER -> handleRoomMemberEvent(realm, event, createRoomParams)
EventType.LOCAL_STATE_ROOM_THIRD_PARTY_INVITE -> handleLocalRoomThirdPartyInviteEvent(realm, event, createRoomParams)
EventType.STATE_ROOM_HISTORY_VISIBILITY -> handleRoomHistoryVisibilityEvent(realm, event, createRoomParams)
EventType.STATE_ROOM_ALIASES -> handleRoomAliasesEvent(realm, event, createRoomParams)
EventType.STATE_ROOM_AVATAR -> handleRoomAvatarEvent(realm, event, createRoomParams)
@ -196,6 +196,19 @@ internal class DefaultCreateRoomFromLocalRoomTask @Inject constructor(
}
}
private fun handleLocalRoomThirdPartyInviteEvent(realm: Realm, event: CurrentStateEventEntity, params: CreateRoomParams): CreateRoomParams = params.apply {
val content = getEventContent<LocalRoomThirdPartyInviteContent>(realm, event.eventId) ?: return@apply
val threePid = when {
content.thirdPartyInvite?.email != null -> ThreePid.Email(content.thirdPartyInvite.email)
content.thirdPartyInvite?.msisdn != null -> ThreePid.Msisdn(content.thirdPartyInvite.msisdn)
else -> return@apply
}
invite3pids.add(threePid)
if (content.isDirect) {
setDirectMessage()
}
}
private fun handleRoomHistoryVisibilityEvent(realm: Realm, event: CurrentStateEventEntity, params: CreateRoomParams): CreateRoomParams = params.apply {
val content = getEventContent<RoomHistoryVisibilityContent>(realm, event.eventId) ?: return@apply
historyVisibility = content.historyVisibility

View File

@ -229,8 +229,9 @@ class TimelineEventVisibilityHelper @Inject constructor(
// Hide fake events for local rooms
if (RoomLocalEcho.isLocalEchoId(roomId) &&
root.getClearType() == EventType.STATE_ROOM_MEMBER ||
root.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY) {
(root.getClearType() == EventType.STATE_ROOM_MEMBER ||
root.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY ||
root.getClearType() == EventType.STATE_ROOM_THIRD_PARTY_INVITE)) {
return true
}