Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create the DM when sending an event #6127

Merged
merged 20 commits into from
Aug 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/5525.wip
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Create DM room only on first message - Create the DM and navigate to the new room after sending an event
1 change: 1 addition & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ ext.libs = [
'moshi' : "com.squareup.moshi:moshi:$moshi",
'moshiKt' : "com.squareup.moshi:moshi-kotlin:$moshi",
'moshiKotlin' : "com.squareup.moshi:moshi-kotlin-codegen:$moshi",
'moshiAdapters' : "com.squareup.moshi:moshi-adapters:$moshi",
'retrofit' : "com.squareup.retrofit2:retrofit:$retrofit",
'retrofitMoshi' : "com.squareup.retrofit2:converter-moshi:$retrofit"
],
Expand Down
1 change: 1 addition & 0 deletions matrix-sdk-android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ dependencies {
implementation 'com.squareup.okhttp3:logging-interceptor'

implementation libs.squareup.moshi
implementation libs.squareup.moshiAdapters
kapt libs.squareup.moshiKotlin

api "com.atlassian.commonmark:commonmark:0.13.0"
Expand Down
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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be internal, as well as LocalRoomThirdPartyInviteContent (and maybe move this class to the internal package?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


// 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
Expand Up @@ -18,10 +18,14 @@ package org.matrix.android.sdk.api.session.identity

import com.google.i18n.phonenumbers.NumberParseException
import com.google.i18n.phonenumbers.PhoneNumberUtil
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.internal.session.profile.ThirdPartyIdentifier

sealed class ThreePid(open val value: String) {
@JsonClass(generateAdapter = true)
data class Email(val email: String) : ThreePid(email)

@JsonClass(generateAdapter = true)
data class Msisdn(val msisdn: String) : ThreePid(msisdn)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
package org.matrix.android.sdk.api.session.room.model.create

import android.net.Uri
import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
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.internal.di.MoshiProvider

@JsonClass(generateAdapter = true)
open class CreateRoomParams {
/**
* A public visibility indicates that the room will be shown in the published room list.
Expand Down Expand Up @@ -61,12 +64,12 @@ open class CreateRoomParams {
* A list of user IDs to invite to the room.
* This will tell the server to invite everyone in the list to the newly created room.
*/
val invitedUserIds = mutableListOf<String>()
var invitedUserIds = mutableListOf<String>()

/**
* A list of objects representing third party IDs to invite into the room.
*/
val invite3pids = mutableListOf<ThreePid>()
var invite3pids = mutableListOf<ThreePid>()

/**
* Initial Guest Access.
Expand Down Expand Up @@ -99,14 +102,14 @@ open class CreateRoomParams {
* The server will clobber the following keys: creator.
* Future versions of the specification may allow the server to clobber other keys.
*/
val creationContent = mutableMapOf<String, Any>()
var creationContent = mutableMapOf<String, Any>()

/**
* A list of state events to set in the new room. This allows the user to override the default state events
* set in the new room. The expected format of the state events are an object with type, state_key and content keys set.
* Takes precedence over events set by preset, but gets overridden by name and topic keys.
*/
val initialStates = mutableListOf<CreateRoomStateEvent>()
var initialStates = mutableListOf<CreateRoomStateEvent>()

/**
* Set to true to disable federation of this room.
Expand Down Expand Up @@ -151,7 +154,7 @@ open class CreateRoomParams {
* Supported value: MXCRYPTO_ALGORITHM_MEGOLM.
*/
var algorithm: String? = null
private set
internal set
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to change the visibility for JSON conversion


var historyVisibility: RoomHistoryVisibility? = null

Expand All @@ -161,10 +164,18 @@ open class CreateRoomParams {

var roomVersion: String? = null

var featurePreset: RoomFeaturePreset? = null
@Transient var featurePreset: RoomFeaturePreset? = null

companion object {
private const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate"
private const val CREATION_CONTENT_KEY_ROOM_TYPE = "type"
internal const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate"
internal const val CREATION_CONTENT_KEY_ROOM_TYPE = "type"

fun fromJson(json: String?): CreateRoomParams? {
return json?.let { MoshiProvider.providesMoshi().adapter(CreateRoomParams::class.java).fromJson(it) }
}
}
}

internal fun CreateRoomParams.toJSONString(): String {
return MoshiProvider.providesMoshi().adapter(CreateRoomParams::class.java).toJson(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@

package org.matrix.android.sdk.api.session.room.model.create

import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.Content

@JsonClass(generateAdapter = true)
data class CreateRoomStateEvent(
/**
* Required. The type of event to send.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
package org.matrix.android.sdk.internal.crypto.tasks

import org.matrix.android.sdk.api.session.events.model.Event
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.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.session.room.RoomAPI
import org.matrix.android.sdk.internal.session.room.create.CreateRoomFromLocalRoomTask
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository
import org.matrix.android.sdk.internal.task.Task
Expand All @@ -37,12 +39,17 @@ internal class DefaultSendEventTask @Inject constructor(
private val localEchoRepository: LocalEchoRepository,
private val encryptEventTask: EncryptEventTask,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val createRoomFromLocalRoomTask: CreateRoomFromLocalRoomTask,
private val roomAPI: RoomAPI,
private val globalErrorReceiver: GlobalErrorReceiver
) : SendEventTask {

override suspend fun execute(params: SendEventTask.Params): String {
try {
if (params.event.isLocalRoomEvent) {
return createRoomAndSendEvent(params)
}

// Make sure to load all members in the room before sending the event.
params.event.roomId
?.takeIf { params.encrypt }
Expand Down Expand Up @@ -78,6 +85,12 @@ internal class DefaultSendEventTask @Inject constructor(
}
}

private suspend fun createRoomAndSendEvent(params: SendEventTask.Params): String {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could add a unit test for the case of local room id?

val roomId = createRoomFromLocalRoomTask.execute(CreateRoomFromLocalRoomTask.Params(params.event.roomId.orEmpty()))
Timber.d("State event: convert local room (${params.event.roomId}) to existing room ($roomId) before sending the event.")
return execute(params.copy(event = params.event.copy(roomId = roomId)))
}

@Throws
private suspend fun handleEncryption(params: SendEventTask.Params): Event {
if (params.encrypt && !params.event.isEncrypted()) {
Expand All @@ -91,4 +104,7 @@ internal class DefaultSendEventTask @Inject constructor(
}
return params.event
}

private val Event.isLocalRoomEvent
get() = RoomLocalEcho.isLocalEchoId(roomId.orEmpty())
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo032
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.util.Normalizer
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
import javax.inject.Inject
Expand All @@ -60,7 +61,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
private val normalizer: Normalizer
) : MatrixRealmMigration(
dbName = "Session",
schemaVersion = 35L,
schemaVersion = 36L,
) {
/**
* Forces all RealmSessionStoreMigration instances to be equal.
Expand Down Expand Up @@ -105,5 +106,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
if (oldVersion < 33) MigrateSessionTo033(realm).perform()
if (oldVersion < 34) MigrateSessionTo034(realm).perform()
if (oldVersion < 35) MigrateSessionTo035(realm).perform()
if (oldVersion < 36) MigrateSessionTo036(realm).perform()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.internal.database.model.LocalRoomSummaryEntityFields
import org.matrix.android.sdk.internal.util.database.RealmMigrator

internal class MigrateSessionTo036(realm: DynamicRealm) : RealmMigrator(realm, 36) {

override fun doMigrate(realm: DynamicRealm) {
realm.schema.create("LocalRoomSummaryEntity")
.addField(LocalRoomSummaryEntityFields.ROOM_ID, String::class.java)
.addPrimaryKey(LocalRoomSummaryEntityFields.ROOM_ID)
.setRequired(LocalRoomSummaryEntityFields.ROOM_ID, true)
.addField(LocalRoomSummaryEntityFields.CREATE_ROOM_PARAMS_STR, String::class.java)
.addRealmObjectField(LocalRoomSummaryEntityFields.ROOM_SUMMARY_ENTITY.`$`, realm.schema.get("RoomSummaryEntity")!!)
}
}
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.internal.database.model

import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
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
) : RealmObject() {

var createRoomParams: CreateRoomParams?
get() {
return CreateRoomParams.fromJson(createRoomParamsStr)
}
set(value) {
createRoomParamsStr = value?.toJSONString()
}

companion object
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.matrix.android.sdk.internal.database.model.threads.ThreadSummaryEntit
ReadReceiptEntity::class,
RoomEntity::class,
RoomSummaryEntity::class,
LocalRoomSummaryEntity::class,
RoomTagEntity::class,
SyncEntity::class,
PendingThreePidEntity::class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.query

import io.realm.Realm
import io.realm.RealmQuery
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
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package org.matrix.android.sdk.internal.di

import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageDefaultContent
Expand Down Expand Up @@ -60,6 +62,12 @@ internal object MoshiProvider {
.registerSubtype(MessagePollResponseContent::class.java, MessageType.MSGTYPE_POLL_RESPONSE)
)
.add(SerializeNulls.JSON_ADAPTER_FACTORY)
.add(
PolymorphicJsonAdapterFactory.of(ThreePid::class.java, "type")
.withSubtype(ThreePid.Email::class.java, "email")
.withSubtype(ThreePid.Msisdn::class.java, "msisdn")
.withDefaultValue(null)
)
.build()

fun providesMoshi(): Moshi {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,13 @@ import org.matrix.android.sdk.internal.session.room.alias.DefaultGetRoomLocalAli
import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
import org.matrix.android.sdk.internal.session.room.alias.GetRoomLocalAliasesTask
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomStateEventsTask
import org.matrix.android.sdk.internal.session.room.create.CreateLocalRoomTask
import org.matrix.android.sdk.internal.session.room.create.CreateRoomFromLocalRoomTask
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomStateEventsTask
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomTask
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomFromLocalRoomTask
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask
import org.matrix.android.sdk.internal.session.room.delete.DefaultDeleteLocalRoomTask
import org.matrix.android.sdk.internal.session.room.delete.DeleteLocalRoomTask
Expand Down Expand Up @@ -213,6 +217,12 @@ internal abstract class RoomModule {
@Binds
abstract fun bindCreateLocalRoomTask(task: DefaultCreateLocalRoomTask): CreateLocalRoomTask

@Binds
abstract fun bindCreateLocalRoomStateEventsTask(task: DefaultCreateLocalRoomStateEventsTask): CreateLocalRoomStateEventsTask

@Binds
abstract fun bindCreateRoomFromLocalRoomTask(task: DefaultCreateRoomFromLocalRoomTask): CreateRoomFromLocalRoomTask

@Binds
abstract fun bindDeleteLocalRoomTask(task: DefaultDeleteLocalRoomTask): DeleteLocalRoomTask

Expand Down
Loading