CreateRoomParams has been replaced by CreateRoomParamsBuilder, to be able to invite 3pids
This commit is contained in:
parent
6c0bb2a949
commit
4b3a6a883d
|
@ -28,7 +28,7 @@ Translations 🗣:
|
|||
-
|
||||
|
||||
SDK API changes ⚠️:
|
||||
-
|
||||
- CreateRoomParams has been replaced by CreateRoomParamsBuilder
|
||||
|
||||
Build 🧱:
|
||||
- Upgrade some dependencies
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.matrix.rx
|
|||
import android.net.Uri
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||
import im.vector.matrix.android.api.session.room.Room
|
||||
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
|
||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||
|
@ -104,6 +105,10 @@ class RxRoom(private val room: Room) {
|
|||
room.invite(userId, reason, it)
|
||||
}
|
||||
|
||||
fun invite3pid(threePid: ThreePid): Completable = completableBuilder<Unit> {
|
||||
room.invite3pid(threePid, it)
|
||||
}
|
||||
|
||||
fun updateTopic(topic: String): Completable = completableBuilder<Unit> {
|
||||
room.updateTopic(topic, it)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import im.vector.matrix.android.api.session.pushers.Pusher
|
|||
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
|
||||
import im.vector.matrix.android.api.session.room.members.ChangeMembershipState
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.api.session.sync.SyncState
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.matrix.android.api.session.widgets.model.Widget
|
||||
|
@ -110,7 +110,7 @@ class RxSession(private val session: Session) {
|
|||
.startWithCallable { session.getThreePids() }
|
||||
}
|
||||
|
||||
fun createRoom(roomParams: CreateRoomParams): Single<String> = singleBuilder {
|
||||
fun createRoom(roomParams: CreateRoomParamsBuilder): Single<String> = singleBuilder {
|
||||
session.createRoom(roomParams, it)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import im.vector.matrix.android.api.session.events.model.toContent
|
|||
import im.vector.matrix.android.api.session.room.Room
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.api.session.room.roomSummaryQueryParams
|
||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
|
@ -65,7 +65,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
|||
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
|
||||
|
||||
val roomId = mTestHelper.doSync<String> {
|
||||
aliceSession.createRoom(CreateRoomParams(name = "MyRoom"), it)
|
||||
aliceSession.createRoom(CreateRoomParamsBuilder().apply { name = "MyRoom" }, it)
|
||||
}
|
||||
|
||||
if (encryptedRoom) {
|
||||
|
@ -286,9 +286,11 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
|||
fun createDM(alice: Session, bob: Session): String {
|
||||
val roomId = mTestHelper.doSync<String> {
|
||||
alice.createRoom(
|
||||
CreateRoomParams(invitedUserIds = listOf(bob.myUserId))
|
||||
.setDirectMessage()
|
||||
.enableEncryptionIfInvitedUsersSupportIt(),
|
||||
CreateRoomParamsBuilder().apply {
|
||||
invitedUserIds.add(bob.myUserId)
|
||||
setDirectMessage()
|
||||
enableEncryptionIfInvitedUsersSupportIt = true
|
||||
},
|
||||
it
|
||||
)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import im.vector.matrix.android.api.session.crypto.verification.VerificationTran
|
|||
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.common.CommonTestHelper
|
||||
import im.vector.matrix.android.common.CryptoTestHelper
|
||||
import im.vector.matrix.android.common.SessionTestParams
|
||||
|
@ -66,7 +66,10 @@ class KeyShareTests : InstrumentedTest {
|
|||
// Create an encrypted room and add a message
|
||||
val roomId = mTestHelper.doSync<String> {
|
||||
aliceSession.createRoom(
|
||||
CreateRoomParams(RoomDirectoryVisibility.PRIVATE).enableEncryptionWithAlgorithm(true),
|
||||
CreateRoomParamsBuilder().apply {
|
||||
visibility = RoomDirectoryVisibility.PRIVATE
|
||||
enableEncryption()
|
||||
},
|
||||
it
|
||||
)
|
||||
}
|
||||
|
@ -285,7 +288,7 @@ class KeyShareTests : InstrumentedTest {
|
|||
mTestHelper.waitWithLatch(60_000) { latch ->
|
||||
val keysBackupService = aliceSession2.cryptoService().keysBackupService()
|
||||
mTestHelper.retryPeriodicallyWithLatch(latch) {
|
||||
Log.d("#TEST", "Recovery :${ keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey}")
|
||||
Log.d("#TEST", "Recovery :${keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey}")
|
||||
keysBackupService.getKeyBackupRecoveryKeyInfo()?.recoveryKey == creationInfo.recoveryKey
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import androidx.lifecycle.LiveData
|
|||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.room.members.ChangeMembershipState
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
|
@ -32,7 +32,7 @@ interface RoomService {
|
|||
/**
|
||||
* Create a room asynchronously
|
||||
*/
|
||||
fun createRoom(createRoomParams: CreateRoomParams,
|
||||
fun createRoom(createRoomParams: CreateRoomParamsBuilder,
|
||||
callback: MatrixCallback<String>): Cancelable
|
||||
|
||||
/**
|
||||
|
@ -113,5 +113,5 @@ interface RoomService {
|
|||
*/
|
||||
fun getChangeMembershipsLive(): LiveData<Map<String, ChangeMembershipState>>
|
||||
|
||||
fun getExistingDirectRoomWithUser(otherUserId: String) : Room?
|
||||
fun getExistingDirectRoomWithUser(otherUserId: String): Room?
|
||||
}
|
||||
|
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* 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.create
|
||||
|
||||
import android.util.Patterns
|
||||
import androidx.annotation.CheckResult
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.MatrixPatterns.isUserId
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
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.toContent
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
||||
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Parameter to create a room, with facilities functions to configure it
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class CreateRoomParams(
|
||||
/**
|
||||
* A public visibility indicates that the room will be shown in the published room list.
|
||||
* A private visibility will hide the room from the published room list.
|
||||
* Rooms default to private visibility if this key is not included.
|
||||
* NB: This should not be confused with join_rules which also uses the word public. One of: ["public", "private"]
|
||||
*/
|
||||
@Json(name = "visibility")
|
||||
val visibility: RoomDirectoryVisibility? = null,
|
||||
|
||||
/**
|
||||
* The desired room alias local part. If this is included, a room alias will be created and mapped to the newly created room.
|
||||
* The alias will belong on the same homeserver which created the room.
|
||||
* For example, if this was set to "foo" and sent to the homeserver "example.com" the complete room alias would be #foo:example.com.
|
||||
*/
|
||||
@Json(name = "room_alias_name")
|
||||
val roomAliasName: String? = null,
|
||||
|
||||
/**
|
||||
* If this is included, an m.room.name event will be sent into the room to indicate the name of the room.
|
||||
* See Room Events for more information on m.room.name.
|
||||
*/
|
||||
@Json(name = "name")
|
||||
val name: String? = null,
|
||||
|
||||
/**
|
||||
* If this is included, an m.room.topic event will be sent into the room to indicate the topic for the room.
|
||||
* See Room Events for more information on m.room.topic.
|
||||
*/
|
||||
@Json(name = "topic")
|
||||
val topic: String? = null,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Json(name = "invite")
|
||||
val invitedUserIds: List<String>? = null,
|
||||
|
||||
/**
|
||||
* A list of objects representing third party IDs to invite into the room.
|
||||
*/
|
||||
@Json(name = "invite_3pid")
|
||||
val invite3pids: List<Invite3Pid>? = null,
|
||||
|
||||
/**
|
||||
* Extra keys to be added to the content of the m.room.create.
|
||||
* The server will clobber the following keys: creator.
|
||||
* Future versions of the specification may allow the server to clobber other keys.
|
||||
*/
|
||||
@Json(name = "creation_content")
|
||||
val creationContent: Any? = null,
|
||||
|
||||
/**
|
||||
* 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 presets, but gets overridden by name and topic keys.
|
||||
*/
|
||||
@Json(name = "initial_state")
|
||||
val initialStates: List<Event>? = null,
|
||||
|
||||
/**
|
||||
* Convenience parameter for setting various default state events based on a preset. Must be either:
|
||||
* private_chat => join_rules is set to invite. history_visibility is set to shared.
|
||||
* trusted_private_chat => join_rules is set to invite. history_visibility is set to shared. All invitees are given the same power level as the
|
||||
* room creator.
|
||||
* public_chat: => join_rules is set to public. history_visibility is set to shared.
|
||||
*/
|
||||
@Json(name = "preset")
|
||||
val preset: CreateRoomPreset? = null,
|
||||
|
||||
/**
|
||||
* This flag makes the server set the is_direct flag on the m.room.member events sent to the users in invite and invite_3pid.
|
||||
* See Direct Messaging for more information.
|
||||
*/
|
||||
@Json(name = "is_direct")
|
||||
val isDirect: Boolean? = null,
|
||||
|
||||
/**
|
||||
* The power level content to override in the default power level event
|
||||
*/
|
||||
@Json(name = "power_level_content_override")
|
||||
val powerLevelContentOverride: PowerLevelsContent? = null
|
||||
) {
|
||||
@Transient
|
||||
internal var enableEncryptionIfInvitedUsersSupportIt: Boolean = false
|
||||
private set
|
||||
|
||||
/**
|
||||
* After calling this method, when the room will be created, if cross-signing is enabled and we can get keys for every invited users,
|
||||
* the encryption will be enabled on the created room
|
||||
* @param value true to activate this behavior.
|
||||
* @return this, to allow chaining methods
|
||||
*/
|
||||
fun enableEncryptionIfInvitedUsersSupportIt(value: Boolean = true): CreateRoomParams {
|
||||
enableEncryptionIfInvitedUsersSupportIt = value
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the crypto algorithm to the room creation parameters.
|
||||
*
|
||||
* @param enable true to enable encryption.
|
||||
* @param algorithm the algorithm, default to [MXCRYPTO_ALGORITHM_MEGOLM], which is actually the only supported algorithm for the moment
|
||||
* @return a modified copy of the CreateRoomParams object, or this if there is no modification
|
||||
*/
|
||||
@CheckResult
|
||||
fun enableEncryptionWithAlgorithm(enable: Boolean = true,
|
||||
algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM): CreateRoomParams {
|
||||
// Remove the existing value if any.
|
||||
val newInitialStates = initialStates
|
||||
?.filter { it.type != EventType.STATE_ROOM_ENCRYPTION }
|
||||
|
||||
return if (algorithm == MXCRYPTO_ALGORITHM_MEGOLM) {
|
||||
if (enable) {
|
||||
val contentMap = mapOf("algorithm" to algorithm)
|
||||
|
||||
val algoEvent = Event(
|
||||
type = EventType.STATE_ROOM_ENCRYPTION,
|
||||
stateKey = "",
|
||||
content = contentMap.toContent()
|
||||
)
|
||||
|
||||
copy(
|
||||
initialStates = newInitialStates.orEmpty() + algoEvent
|
||||
)
|
||||
} else {
|
||||
return copy(
|
||||
initialStates = newInitialStates
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.e("Unsupported algorithm: $algorithm")
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the history visibility in the room creation parameters.
|
||||
*
|
||||
* @param historyVisibility the expected history visibility, set null to remove any existing value.
|
||||
* @return a modified copy of the CreateRoomParams object
|
||||
*/
|
||||
@CheckResult
|
||||
fun setHistoryVisibility(historyVisibility: RoomHistoryVisibility?): CreateRoomParams {
|
||||
// Remove the existing value if any.
|
||||
val newInitialStates = initialStates
|
||||
?.filter { it.type != EventType.STATE_ROOM_HISTORY_VISIBILITY }
|
||||
|
||||
if (historyVisibility != null) {
|
||||
val contentMap = mapOf("history_visibility" to historyVisibility)
|
||||
|
||||
val historyVisibilityEvent = Event(
|
||||
type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
stateKey = "",
|
||||
content = contentMap.toContent())
|
||||
|
||||
return copy(
|
||||
initialStates = newInitialStates.orEmpty() + historyVisibilityEvent
|
||||
)
|
||||
} else {
|
||||
return copy(
|
||||
initialStates = newInitialStates
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark as a direct message room.
|
||||
* @return a modified copy of the CreateRoomParams object
|
||||
*/
|
||||
@CheckResult
|
||||
fun setDirectMessage(): CreateRoomParams {
|
||||
return copy(
|
||||
preset = CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT,
|
||||
isDirect = true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the created room can be a direct chat one.
|
||||
*
|
||||
* @return true if it is a direct chat
|
||||
*/
|
||||
fun isDirect(): Boolean {
|
||||
return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT
|
||||
&& isDirect == true
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first invited user id
|
||||
*/
|
||||
fun getFirstInvitedUserId(): String? {
|
||||
return invitedUserIds?.firstOrNull() ?: invite3pids?.firstOrNull()?.address
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some ids to the room creation
|
||||
* ids might be a matrix id or an email address.
|
||||
*
|
||||
* @param ids the participant ids to add.
|
||||
* @return a modified copy of the CreateRoomParams object
|
||||
*/
|
||||
@CheckResult
|
||||
fun addParticipantIds(hsConfig: HomeServerConnectionConfig,
|
||||
userId: String,
|
||||
ids: List<String>): CreateRoomParams {
|
||||
return copy(
|
||||
invite3pids = (invite3pids.orEmpty() + ids
|
||||
.takeIf { hsConfig.identityServerUri != null }
|
||||
?.filter { id -> Patterns.EMAIL_ADDRESS.matcher(id).matches() }
|
||||
?.map { id ->
|
||||
Invite3Pid(
|
||||
idServer = hsConfig.identityServerUri!!.host!!,
|
||||
medium = ThreePidMedium.EMAIL,
|
||||
address = id
|
||||
)
|
||||
}
|
||||
.orEmpty())
|
||||
.distinct(),
|
||||
invitedUserIds = (invitedUserIds.orEmpty() + ids
|
||||
.filter { id -> isUserId(id) }
|
||||
// do not invite oneself
|
||||
.filter { id -> id != userId })
|
||||
.distinct()
|
||||
)
|
||||
// TODO add phonenumbers when it will be available
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.create
|
||||
|
||||
import im.vector.matrix.android.api.session.identity.ThreePid
|
||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
|
||||
class CreateRoomParamsBuilder {
|
||||
var visibility: RoomDirectoryVisibility? = null
|
||||
var roomAliasName: String? = null
|
||||
var name: String? = null
|
||||
var topic: String? = null
|
||||
|
||||
/**
|
||||
* UserIds to invite
|
||||
*/
|
||||
val invitedUserIds = mutableListOf<String>()
|
||||
|
||||
/**
|
||||
* ThreePids to invite
|
||||
*/
|
||||
val invite3pids = mutableListOf<ThreePid>()
|
||||
|
||||
/**
|
||||
* If set to true, when the room will be created, if cross-signing is enabled and we can get keys for every invited users,
|
||||
* the encryption will be enabled on the created room
|
||||
*/
|
||||
var enableEncryptionIfInvitedUsersSupportIt: Boolean = false
|
||||
|
||||
var preset: CreateRoomPreset? = null
|
||||
|
||||
var isDirect: Boolean? = null
|
||||
|
||||
/**
|
||||
* Mark as a direct message room.
|
||||
*/
|
||||
fun setDirectMessage() {
|
||||
preset = CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT
|
||||
isDirect = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported value: MXCRYPTO_ALGORITHM_MEGOLM
|
||||
*/
|
||||
var algorithm: String? = null
|
||||
private set
|
||||
|
||||
var historyVisibility: RoomHistoryVisibility? = null
|
||||
|
||||
fun enableEncryption() {
|
||||
algorithm = MXCRYPTO_ALGORITHM_MEGOLM
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the created room can be a direct chat one.
|
||||
*
|
||||
* @return true if it is a direct chat
|
||||
*/
|
||||
fun isDirect(): Boolean {
|
||||
return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT
|
||||
&& isDirect == true
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first invited user id
|
||||
*/
|
||||
fun getFirstInvitedUserId(): String? {
|
||||
return invitedUserIds.firstOrNull() ?: invite3pids.firstOrNull()?.value
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* 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.create
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Invite3Pid(
|
||||
/**
|
||||
* Required.
|
||||
* The hostname+port of the identity server which should be used for third party identifier lookups.
|
||||
*/
|
||||
@Json(name = "id_server")
|
||||
val idServer: String,
|
||||
|
||||
/**
|
||||
* Required.
|
||||
* An access token previously registered with the identity server. Servers can treat this as optional to
|
||||
* distinguish between r0.5-compatible clients and this specification version.
|
||||
*/
|
||||
@Json(name = "id_access_token")
|
||||
val idAccessToken: String,
|
||||
|
||||
/**
|
||||
* Required.
|
||||
* The kind of address being passed in the address field, for example email.
|
||||
*/
|
||||
val medium: String,
|
||||
|
||||
/**
|
||||
* Required.
|
||||
* The invitee's third party identifier.
|
||||
*/
|
||||
val address: String
|
||||
)
|
|
@ -23,7 +23,7 @@ import im.vector.matrix.android.api.session.room.RoomService
|
|||
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
|
||||
import im.vector.matrix.android.api.session.room.members.ChangeMembershipState
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
import im.vector.matrix.android.internal.session.room.alias.GetRoomIdByAliasTask
|
||||
|
@ -49,7 +49,7 @@ internal class DefaultRoomService @Inject constructor(
|
|||
private val taskExecutor: TaskExecutor
|
||||
) : RoomService {
|
||||
|
||||
override fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>): Cancelable {
|
||||
override fun createRoom(createRoomParams: CreateRoomParamsBuilder, callback: MatrixCallback<String>): Cancelable {
|
||||
return createRoomTask
|
||||
.configureWith(createRoomParams) {
|
||||
this.callback = callback
|
||||
|
|
|
@ -18,9 +18,6 @@ package im.vector.matrix.android.internal.session.room
|
|||
|
||||
import im.vector.matrix.android.api.session.events.model.Content
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse
|
||||
import im.vector.matrix.android.api.session.room.model.create.JoinRoomResponse
|
||||
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||
import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||
import im.vector.matrix.android.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
|
@ -28,6 +25,9 @@ import im.vector.matrix.android.api.util.JsonDict
|
|||
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||
import im.vector.matrix.android.internal.session.room.alias.AddRoomAliasBody
|
||||
import im.vector.matrix.android.internal.session.room.alias.RoomAliasDescription
|
||||
import im.vector.matrix.android.internal.session.room.create.CreateRoomParams
|
||||
import im.vector.matrix.android.internal.session.room.create.CreateRoomResponse
|
||||
import im.vector.matrix.android.internal.session.room.create.JoinRoomResponse
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomMembersResponse
|
||||
import im.vector.matrix.android.internal.session.room.membership.admin.UserIdAndReason
|
||||
import im.vector.matrix.android.internal.session.room.membership.joining.InviteBody
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomPreset
|
||||
import im.vector.matrix.android.internal.session.room.membership.threepid.ThreePidInviteBody
|
||||
|
||||
/**
|
||||
* Parameter to create a room
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class CreateRoomParams(
|
||||
/**
|
||||
* A public visibility indicates that the room will be shown in the published room list.
|
||||
* A private visibility will hide the room from the published room list.
|
||||
* Rooms default to private visibility if this key is not included.
|
||||
* NB: This should not be confused with join_rules which also uses the word public. One of: ["public", "private"]
|
||||
*/
|
||||
@Json(name = "visibility")
|
||||
val visibility: RoomDirectoryVisibility?,
|
||||
|
||||
/**
|
||||
* The desired room alias local part. If this is included, a room alias will be created and mapped to the newly created room.
|
||||
* The alias will belong on the same homeserver which created the room.
|
||||
* For example, if this was set to "foo" and sent to the homeserver "example.com" the complete room alias would be #foo:example.com.
|
||||
*/
|
||||
@Json(name = "room_alias_name")
|
||||
val roomAliasName: String?,
|
||||
|
||||
/**
|
||||
* If this is included, an m.room.name event will be sent into the room to indicate the name of the room.
|
||||
* See Room Events for more information on m.room.name.
|
||||
*/
|
||||
@Json(name = "name")
|
||||
val name: String?,
|
||||
|
||||
/**
|
||||
* If this is included, an m.room.topic event will be sent into the room to indicate the topic for the room.
|
||||
* See Room Events for more information on m.room.topic.
|
||||
*/
|
||||
@Json(name = "topic")
|
||||
val topic: String?,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Json(name = "invite")
|
||||
val invitedUserIds: List<String>?,
|
||||
|
||||
/**
|
||||
* A list of objects representing third party IDs to invite into the room.
|
||||
*/
|
||||
@Json(name = "invite_3pid")
|
||||
val invite3pids: List<ThreePidInviteBody>?,
|
||||
|
||||
/**
|
||||
* Extra keys to be added to the content of the m.room.create.
|
||||
* The server will clobber the following keys: creator.
|
||||
* Future versions of the specification may allow the server to clobber other keys.
|
||||
*/
|
||||
@Json(name = "creation_content")
|
||||
val creationContent: 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 presets, but gets overridden by name and topic keys.
|
||||
*/
|
||||
@Json(name = "initial_state")
|
||||
val initialStates: List<Event>?,
|
||||
|
||||
/**
|
||||
* Convenience parameter for setting various default state events based on a preset. Must be either:
|
||||
* private_chat => join_rules is set to invite. history_visibility is set to shared.
|
||||
* trusted_private_chat => join_rules is set to invite. history_visibility is set to shared. All invitees are given the same power level as the
|
||||
* room creator.
|
||||
* public_chat: => join_rules is set to public. history_visibility is set to shared.
|
||||
*/
|
||||
@Json(name = "preset")
|
||||
val preset: CreateRoomPreset?,
|
||||
|
||||
/**
|
||||
* This flag makes the server set the is_direct flag on the m.room.member events sent to the users in invite and invite_3pid.
|
||||
* See Direct Messaging for more information.
|
||||
*/
|
||||
@Json(name = "is_direct")
|
||||
val isDirect: Boolean?,
|
||||
|
||||
/**
|
||||
* The power level content to override in the default power level event
|
||||
*/
|
||||
@Json(name = "power_level_content_override")
|
||||
val powerLevelContentOverride: PowerLevelsContent?
|
||||
)
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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 im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
|
||||
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.toContent
|
||||
import im.vector.matrix.android.api.session.identity.IdentityServiceError
|
||||
import im.vector.matrix.android.api.session.identity.toMedium
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
||||
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||
import im.vector.matrix.android.internal.di.AuthenticatedIdentity
|
||||
import im.vector.matrix.android.internal.network.token.AccessTokenProvider
|
||||
import im.vector.matrix.android.internal.session.identity.EnsureIdentityTokenTask
|
||||
import im.vector.matrix.android.internal.session.identity.data.IdentityStore
|
||||
import im.vector.matrix.android.internal.session.identity.data.getIdentityServerUrlWithoutProtocol
|
||||
import im.vector.matrix.android.internal.session.room.membership.threepid.ThreePidInviteBody
|
||||
import java.security.InvalidParameterException
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class CreateRoomParamsInternalBuilder @Inject constructor(
|
||||
private val ensureIdentityTokenTask: EnsureIdentityTokenTask,
|
||||
private val crossSigningService: CrossSigningService,
|
||||
private val deviceListManager: DeviceListManager,
|
||||
private val identityStore: IdentityStore,
|
||||
@AuthenticatedIdentity
|
||||
private val accessTokenProvider: AccessTokenProvider
|
||||
) {
|
||||
|
||||
suspend fun build(builder: CreateRoomParamsBuilder): CreateRoomParams {
|
||||
val invite3pids = builder.invite3pids
|
||||
.takeIf { it.isNotEmpty() }
|
||||
.let {
|
||||
// This can throw Exception if Identity server is not configured
|
||||
ensureIdentityTokenTask.execute(Unit)
|
||||
|
||||
val identityServerUrlWithoutProtocol = identityStore.getIdentityServerUrlWithoutProtocol()
|
||||
?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||
val identityServerAccessToken = accessTokenProvider.getToken() ?: throw IdentityServiceError.NoIdentityServerConfigured
|
||||
|
||||
builder.invite3pids.map {
|
||||
ThreePidInviteBody(
|
||||
id_server = identityServerUrlWithoutProtocol,
|
||||
id_access_token = identityServerAccessToken,
|
||||
medium = it.toMedium(),
|
||||
address = it.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val initialStates = listOfNotNull(
|
||||
buildEncryptionWithAlgorithmEvent(builder),
|
||||
buildHistoryVisibilityEvent(builder)
|
||||
)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
|
||||
return CreateRoomParams(
|
||||
visibility = builder.visibility,
|
||||
roomAliasName = builder.roomAliasName,
|
||||
name = builder.name,
|
||||
topic = builder.topic,
|
||||
invitedUserIds = builder.invitedUserIds,
|
||||
invite3pids = invite3pids,
|
||||
// TODO Support this
|
||||
creationContent = null,
|
||||
initialStates = initialStates,
|
||||
preset = builder.preset,
|
||||
isDirect = builder.isDirect,
|
||||
// TODO Support this
|
||||
powerLevelContentOverride = null
|
||||
)
|
||||
}
|
||||
|
||||
private fun buildHistoryVisibilityEvent(builder: CreateRoomParamsBuilder): Event? {
|
||||
return builder.historyVisibility
|
||||
?.let {
|
||||
val contentMap = mapOf("history_visibility" to it)
|
||||
|
||||
Event(
|
||||
type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||
stateKey = "",
|
||||
content = contentMap.toContent())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the crypto algorithm to the room creation parameters.
|
||||
*/
|
||||
private suspend fun buildEncryptionWithAlgorithmEvent(builder: CreateRoomParamsBuilder): Event? {
|
||||
if (builder.algorithm == null
|
||||
&& canEnableEncryption(builder)) {
|
||||
// Enable the encryption
|
||||
builder.enableEncryption()
|
||||
}
|
||||
return builder.algorithm
|
||||
?.let {
|
||||
if (it != MXCRYPTO_ALGORITHM_MEGOLM) {
|
||||
throw InvalidParameterException("Unsupported algorithm: $it")
|
||||
}
|
||||
val contentMap = mapOf("algorithm" to it)
|
||||
|
||||
Event(
|
||||
type = EventType.STATE_ROOM_ENCRYPTION,
|
||||
stateKey = "",
|
||||
content = contentMap.toContent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun canEnableEncryption(builder: CreateRoomParamsBuilder): Boolean {
|
||||
return (builder.enableEncryptionIfInvitedUsersSupportIt
|
||||
&& crossSigningService.isCrossSigningVerified()
|
||||
&& builder.invite3pids.isEmpty())
|
||||
&& builder.invitedUserIds.isNotEmpty()
|
||||
&& builder.invitedUserIds.let { userIds ->
|
||||
val keys = deviceListManager.downloadKeys(userIds, forceDownload = false)
|
||||
|
||||
userIds.all { userId ->
|
||||
keys.map[userId].let { deviceMap ->
|
||||
if (deviceMap.isNullOrEmpty()) {
|
||||
// A user has no device, so do not enable encryption
|
||||
false
|
||||
} else {
|
||||
// Check that every user's device have at least one key
|
||||
deviceMap.values.all { !it.keys.isNullOrEmpty() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2019 New Vector Ltd
|
||||
* Copyright (c) 2020 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.
|
||||
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.room.model.create
|
||||
package im.vector.matrix.android.internal.session.room.create
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
|
@ -17,11 +17,8 @@
|
|||
package im.vector.matrix.android.internal.session.room.create
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.CrossSigningService
|
||||
import im.vector.matrix.android.api.session.room.failure.CreateRoomFailure
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse
|
||||
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.internal.database.awaitNotEmptyResult
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntityFields
|
||||
|
@ -41,7 +38,7 @@ import org.greenrobot.eventbus.EventBus
|
|||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface CreateRoomTask : Task<CreateRoomParams, String>
|
||||
internal interface CreateRoomTask : Task<CreateRoomParamsBuilder, String>
|
||||
|
||||
internal class DefaultCreateRoomTask @Inject constructor(
|
||||
private val roomAPI: RoomAPI,
|
||||
|
@ -51,17 +48,12 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||
private val readMarkersTask: SetReadMarkersTask,
|
||||
@SessionDatabase
|
||||
private val realmConfiguration: RealmConfiguration,
|
||||
private val crossSigningService: CrossSigningService,
|
||||
private val deviceListManager: DeviceListManager,
|
||||
private val createRoomParamsInternalBuilder: CreateRoomParamsInternalBuilder,
|
||||
private val eventBus: EventBus
|
||||
) : CreateRoomTask {
|
||||
|
||||
override suspend fun execute(params: CreateRoomParams): String {
|
||||
val createRoomParams = if (canEnableEncryption(params)) {
|
||||
params.enableEncryptionWithAlgorithm()
|
||||
} else {
|
||||
params
|
||||
}
|
||||
override suspend fun execute(params: CreateRoomParamsBuilder): String {
|
||||
val createRoomParams = createRoomParamsInternalBuilder.build(params)
|
||||
|
||||
val createRoomResponse = executeRequest<CreateRoomResponse>(eventBus) {
|
||||
apiCall = roomAPI.createRoom(createRoomParams)
|
||||
|
@ -76,36 +68,14 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||
} catch (exception: TimeoutCancellationException) {
|
||||
throw CreateRoomFailure.CreatedWithTimeout
|
||||
}
|
||||
if (createRoomParams.isDirect()) {
|
||||
handleDirectChatCreation(createRoomParams, roomId)
|
||||
if (params.isDirect()) {
|
||||
handleDirectChatCreation(params, roomId)
|
||||
}
|
||||
setReadMarkers(roomId)
|
||||
return roomId
|
||||
}
|
||||
|
||||
private suspend fun canEnableEncryption(params: CreateRoomParams): Boolean {
|
||||
return params.enableEncryptionIfInvitedUsersSupportIt
|
||||
&& crossSigningService.isCrossSigningVerified()
|
||||
&& params.invite3pids.isNullOrEmpty()
|
||||
&& params.invitedUserIds?.isNotEmpty() == true
|
||||
&& params.invitedUserIds.let { userIds ->
|
||||
val keys = deviceListManager.downloadKeys(userIds, forceDownload = false)
|
||||
|
||||
userIds.all { userId ->
|
||||
keys.map[userId].let { deviceMap ->
|
||||
if (deviceMap.isNullOrEmpty()) {
|
||||
// A user has no device, so do not enable encryption
|
||||
false
|
||||
} else {
|
||||
// Check that every user's device have at least one key
|
||||
deviceMap.values.all { !it.keys.isNullOrEmpty() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleDirectChatCreation(params: CreateRoomParams, roomId: String) {
|
||||
private suspend fun handleDirectChatCreation(params: CreateRoomParamsBuilder, roomId: String) {
|
||||
val otherUserId = params.getFirstInvitedUserId()
|
||||
?: throw IllegalStateException("You can't create a direct room without an invitedUser")
|
||||
|
||||
|
|
|
@ -18,13 +18,13 @@ package im.vector.matrix.android.internal.session.room.membership.joining
|
|||
|
||||
import im.vector.matrix.android.api.session.room.failure.JoinRoomFailure
|
||||
import im.vector.matrix.android.api.session.room.members.ChangeMembershipState
|
||||
import im.vector.matrix.android.api.session.room.model.create.JoinRoomResponse
|
||||
import im.vector.matrix.android.internal.database.awaitNotEmptyResult
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntityFields
|
||||
import im.vector.matrix.android.internal.di.SessionDatabase
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.session.room.RoomAPI
|
||||
import im.vector.matrix.android.internal.session.room.create.JoinRoomResponse
|
||||
import im.vector.matrix.android.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
||||
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
|
||||
import im.vector.matrix.android.internal.task.Task
|
||||
|
|
|
@ -22,8 +22,9 @@ import com.airbnb.mvrx.ViewModelContext
|
|||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.features.userdirectory.PendingInvitee
|
||||
|
||||
|
@ -53,11 +54,17 @@ class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted
|
|||
}
|
||||
|
||||
private fun createRoomAndInviteSelectedUsers(selectedUsers: Set<PendingInvitee>) {
|
||||
val roomParams = CreateRoomParams(
|
||||
invitedUserIds = selectedUsers.map { it.userId }
|
||||
)
|
||||
.setDirectMessage()
|
||||
.enableEncryptionIfInvitedUsersSupportIt()
|
||||
val roomParams = CreateRoomParamsBuilder()
|
||||
.apply {
|
||||
selectedUsers.forEach {
|
||||
when (it) {
|
||||
is PendingInvitee.UserPendingInvitee -> invitedUserIds.add(it.user.userId)
|
||||
is PendingInvitee.ThreePidPendingInvitee -> invite3pids.add(it.threePid)
|
||||
}.exhaustive
|
||||
}
|
||||
setDirectMessage()
|
||||
enableEncryptionIfInvitedUsersSupportIt = true
|
||||
}
|
||||
|
||||
session.rx()
|
||||
.createRoom(roomParams)
|
||||
|
|
|
@ -43,7 +43,7 @@ import im.vector.matrix.android.api.session.crypto.verification.VerificationServ
|
|||
import im.vector.matrix.android.api.session.crypto.verification.VerificationTransaction
|
||||
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
|
||||
import im.vector.matrix.android.api.session.events.model.LocalEcho
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.api.util.MatrixItem
|
||||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64
|
||||
|
@ -235,11 +235,12 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
pendingRequest = Loading()
|
||||
)
|
||||
}
|
||||
val roomParams = CreateRoomParams(
|
||||
invitedUserIds = listOf(otherUserId)
|
||||
)
|
||||
.setDirectMessage()
|
||||
.enableEncryptionIfInvitedUsersSupportIt()
|
||||
val roomParams = CreateRoomParamsBuilder()
|
||||
.apply {
|
||||
invitedUserIds.add(otherUserId)
|
||||
setDirectMessage()
|
||||
enableEncryptionIfInvitedUsersSupportIt = true
|
||||
}
|
||||
|
||||
session.createRoom(roomParams, object : MatrixCallback<String> {
|
||||
override fun onSuccess(data: String) {
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
package im.vector.riotx.features.invite
|
||||
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||
import im.vector.riotx.features.userdirectory.PendingInvitee
|
||||
|
||||
sealed class InviteUsersToRoomAction : VectorViewModelAction {
|
||||
data class InviteSelectedUsers(val selectedUsers: Set<User>) : InviteUsersToRoomAction()
|
||||
data class InviteSelectedUsers(val selectedUsers: Set<PendingInvitee>) : InviteUsersToRoomAction()
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@ import com.airbnb.mvrx.ViewModelContext
|
|||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.features.userdirectory.PendingInvitee
|
||||
import io.reactivex.Observable
|
||||
|
||||
class InviteUsersToRoomViewModel @AssistedInject constructor(@Assisted
|
||||
|
@ -57,11 +57,14 @@ class InviteUsersToRoomViewModel @AssistedInject constructor(@Assisted
|
|||
}
|
||||
}
|
||||
|
||||
private fun inviteUsersToRoom(selectedUsers: Set<User>) {
|
||||
private fun inviteUsersToRoom(selectedUsers: Set<PendingInvitee>) {
|
||||
_viewEvents.post(InviteUsersToRoomViewEvents.Loading)
|
||||
|
||||
Observable.fromIterable(selectedUsers).flatMapCompletable { user ->
|
||||
room.rx().invite(user.userId, null)
|
||||
when (user) {
|
||||
is PendingInvitee.UserPendingInvitee -> room.rx().invite(user.user.userId, null)
|
||||
is PendingInvitee.ThreePidPendingInvitee -> room.rx().invite3pid(user.threePid)
|
||||
}
|
||||
}.subscribe(
|
||||
{
|
||||
val successMessage = when (selectedUsers.size) {
|
||||
|
|
|
@ -28,7 +28,7 @@ import com.squareup.inject.assisted.AssistedInject
|
|||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParamsBuilder
|
||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomPreset
|
||||
import im.vector.riotx.core.platform.EmptyViewEvents
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
|
@ -84,15 +84,19 @@ class CreateRoomViewModel @AssistedInject constructor(@Assisted initialState: Cr
|
|||
copy(asyncCreateRoomRequest = Loading())
|
||||
}
|
||||
|
||||
val createRoomParams = CreateRoomParams(
|
||||
name = state.roomName.takeIf { it.isNotBlank() },
|
||||
// Directory visibility
|
||||
visibility = if (state.isInRoomDirectory) RoomDirectoryVisibility.PUBLIC else RoomDirectoryVisibility.PRIVATE,
|
||||
// Public room
|
||||
preset = if (state.isPublic) CreateRoomPreset.PRESET_PUBLIC_CHAT else CreateRoomPreset.PRESET_PRIVATE_CHAT
|
||||
)
|
||||
// Encryption
|
||||
.enableEncryptionWithAlgorithm(state.isEncrypted)
|
||||
val createRoomParams = CreateRoomParamsBuilder()
|
||||
.apply {
|
||||
name = state.roomName.takeIf { it.isNotBlank() }
|
||||
// Directory visibility
|
||||
visibility = if (state.isInRoomDirectory) RoomDirectoryVisibility.PUBLIC else RoomDirectoryVisibility.PRIVATE
|
||||
// Public room
|
||||
preset = if (state.isPublic) CreateRoomPreset.PRESET_PUBLIC_CHAT else CreateRoomPreset.PRESET_PRIVATE_CHAT
|
||||
|
||||
// Encryption
|
||||
if (state.isEncrypted) {
|
||||
enableEncryption()
|
||||
}
|
||||
}
|
||||
|
||||
session.createRoom(createRoomParams, object : MatrixCallback<String> {
|
||||
override fun onSuccess(data: String) {
|
||||
|
|
|
@ -160,10 +160,7 @@ class KnownUsersFragment @Inject constructor(
|
|||
val chip = Chip(requireContext())
|
||||
chip.setChipBackgroundColorResource(android.R.color.transparent)
|
||||
chip.chipStrokeWidth = dimensionConverter.dpToPx(1).toFloat()
|
||||
chip.text = when (pendingInvitee) {
|
||||
is PendingInvitee.UserPendingInvitee -> pendingInvitee.user.getBestName()
|
||||
is PendingInvitee.ThreePidPendingInvitee -> pendingInvitee.threePid.value
|
||||
}
|
||||
chip.text = pendingInvitee.getBestName()
|
||||
chip.isClickable = true
|
||||
chip.isCheckable = false
|
||||
chip.isCloseIconVisible = true
|
||||
|
|
|
@ -20,6 +20,13 @@ import im.vector.matrix.android.api.session.identity.ThreePid
|
|||
import im.vector.matrix.android.api.session.user.model.User
|
||||
|
||||
sealed class PendingInvitee {
|
||||
data class UserPendingInvitee(val user: User): PendingInvitee()
|
||||
data class ThreePidPendingInvitee(val threePid: ThreePid): PendingInvitee()
|
||||
data class UserPendingInvitee(val user: User) : PendingInvitee()
|
||||
data class ThreePidPendingInvitee(val threePid: ThreePid) : PendingInvitee()
|
||||
|
||||
fun getBestName(): String {
|
||||
return when (this) {
|
||||
is UserPendingInvitee -> user.getBestName()
|
||||
is ThreePidPendingInvitee -> threePid.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.view.View
|
|||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.extensions.cleanup
|
||||
import im.vector.riotx.core.extensions.configureWith
|
||||
|
@ -81,9 +82,9 @@ class UserDirectoryFragment @Inject constructor(
|
|||
directRoomController.setData(it)
|
||||
}
|
||||
|
||||
override fun onItemClick(pendingInvitee: PendingInvitee) {
|
||||
override fun onItemClick(user: User) {
|
||||
view?.hideKeyboard()
|
||||
viewModel.handle(UserDirectoryAction.SelectPendingInvitee(pendingInvitee))
|
||||
viewModel.handle(UserDirectoryAction.SelectPendingInvitee(PendingInvitee.UserPendingInvitee(user)))
|
||||
sharedActionViewModel.post(UserDirectorySharedAction.GoBack)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue