Skip to content

Commit

Permalink
Start DM - Handle third party invites
Browse files Browse the repository at this point in the history
  • Loading branch information
Florian Renaud committed Jul 1, 2022
1 parent 7096c29 commit 2a597a8
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,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
Expand Down Expand Up @@ -202,6 +205,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 = createFakeEvent(
type = EventType.STATE_ROOM_CREATE,
Expand Down Expand Up @@ -231,11 +235,40 @@ internal class DefaultCreateLocalRoomTask @Inject constructor(
)
}

val localRoomThreePidEvents = invited3Pids.map { body ->
createFakeEvent(
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 ->
createFakeEvent(
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 { createFakeEvent(it.type, it.content, it.stateKey) })
addAll(roomMemberEvents)
addAll(roomThreePidEvents)
addAll(localRoomThreePidEvents)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -144,6 +143,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)
Expand Down Expand Up @@ -200,6 +200,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen

// 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
}

Expand Down

0 comments on commit 2a597a8

Please sign in to comment.