mirror of
https://github.com/element-hq/element-android
synced 2024-11-27 20:06:51 +03:00
Start DM - display a local room before creating the real one
Add CreateLocalRoomTask interface and remove DI annotations
This commit is contained in:
parent
26d1a12b74
commit
10d683ad5d
12 changed files with 352 additions and 37 deletions
|
@ -40,6 +40,13 @@ interface RoomService {
|
|||
*/
|
||||
suspend fun createRoom(createRoomParams: CreateRoomParams): String
|
||||
|
||||
/**
|
||||
* Create a room locally.
|
||||
* This room will not be synchronized with the server and will not come back from the sync, so all the events related to this room will be generated
|
||||
* locally.
|
||||
*/
|
||||
suspend fun createLocalRoom(createRoomParams: CreateRoomParams): String
|
||||
|
||||
/**
|
||||
* Create a direct room asynchronously. This is a facility method to create a direct room with the necessary parameters.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2020 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 java.util.UUID
|
||||
|
||||
object RoomLocalEcho {
|
||||
|
||||
private const val PREFIX = "!local."
|
||||
|
||||
fun isLocalEchoId(roomId: String) = roomId.startsWith(PREFIX)
|
||||
|
||||
fun createLocalEchoId() = "${PREFIX}${UUID.randomUUID()}"
|
||||
}
|
|
@ -43,6 +43,7 @@ import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFie
|
|||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
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.create.CreateLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
|
||||
|
@ -60,6 +61,7 @@ import javax.inject.Inject
|
|||
internal class DefaultRoomService @Inject constructor(
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val createRoomTask: CreateRoomTask,
|
||||
private val createLocalRoomTask: CreateLocalRoomTask,
|
||||
private val joinRoomTask: JoinRoomTask,
|
||||
private val markAllRoomsReadTask: MarkAllRoomsReadTask,
|
||||
private val updateBreadcrumbsTask: UpdateBreadcrumbsTask,
|
||||
|
@ -78,6 +80,10 @@ internal class DefaultRoomService @Inject constructor(
|
|||
return createRoomTask.executeRetry(createRoomParams, 3)
|
||||
}
|
||||
|
||||
override suspend fun createLocalRoom(createRoomParams: CreateRoomParams): String {
|
||||
return createLocalRoomTask.execute(createRoomParams)
|
||||
}
|
||||
|
||||
override fun getRoom(roomId: String): Room? {
|
||||
return roomGetter.getRoom(roomId)
|
||||
}
|
||||
|
|
|
@ -43,7 +43,9 @@ 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.CreateLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateLocalRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.create.DefaultCreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetPublicRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.directory.DefaultGetRoomDirectoryVisibilityTask
|
||||
|
@ -192,6 +194,9 @@ internal abstract class RoomModule {
|
|||
@Binds
|
||||
abstract fun bindCreateRoomTask(task: DefaultCreateRoomTask): CreateRoomTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindCreateLocalRoomTask(task: DefaultCreateLocalRoomTask): CreateLocalRoomTask
|
||||
|
||||
@Binds
|
||||
abstract fun bindGetPublicRoomTask(task: DefaultGetPublicRoomTask): GetPublicRoomTask
|
||||
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* 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.session.room.create
|
||||
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmConfiguration
|
||||
import io.realm.kotlin.createObject
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure
|
||||
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
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.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
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
|
||||
import org.matrix.android.sdk.api.session.user.UserService
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import org.matrix.android.sdk.internal.database.awaitNotEmptyResult
|
||||
import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
|
||||
import org.matrix.android.sdk.internal.database.mapper.asDomain
|
||||
import org.matrix.android.sdk.internal.database.mapper.toEntity
|
||||
import org.matrix.android.sdk.internal.database.model.ChunkEntity
|
||||
import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
|
||||
import org.matrix.android.sdk.internal.database.model.EventInsertType
|
||||
import org.matrix.android.sdk.internal.database.model.RoomEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
|
||||
import org.matrix.android.sdk.internal.database.query.getOrCreate
|
||||
import org.matrix.android.sdk.internal.database.query.getOrNull
|
||||
import org.matrix.android.sdk.internal.di.SessionDatabase
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.events.getFixedRoomMemberContent
|
||||
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberEventHandler
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater
|
||||
import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
|
||||
import org.matrix.android.sdk.internal.task.Task
|
||||
import org.matrix.android.sdk.internal.util.awaitTransaction
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
internal interface CreateLocalRoomTask : Task<CreateRoomParams, String>
|
||||
|
||||
internal class DefaultCreateLocalRoomTask @Inject constructor(
|
||||
@UserId private val userId: String,
|
||||
@SessionDatabase private val monarchy: Monarchy,
|
||||
private val roomMemberEventHandler: RoomMemberEventHandler,
|
||||
private val roomSummaryUpdater: RoomSummaryUpdater,
|
||||
@SessionDatabase private val realmConfiguration: RealmConfiguration,
|
||||
private val createRoomBodyBuilder: CreateRoomBodyBuilder,
|
||||
private val userService: UserService,
|
||||
private val clock: Clock,
|
||||
) : CreateLocalRoomTask {
|
||||
|
||||
override suspend fun execute(params: CreateRoomParams): String {
|
||||
val createRoomBody = createRoomBodyBuilder.build(params.withDefault())
|
||||
val roomId = RoomLocalEcho.createLocalEchoId()
|
||||
monarchy.awaitTransaction { realm ->
|
||||
createLocalRoomEntity(realm, roomId, createRoomBody)
|
||||
createLocalRoomSummaryEntity(realm, roomId, createRoomBody)
|
||||
}
|
||||
|
||||
// Wait for room to be created in DB
|
||||
try {
|
||||
awaitNotEmptyResult(realmConfiguration, TimeUnit.MINUTES.toMillis(1L)) { realm ->
|
||||
realm.where(RoomSummaryEntity::class.java)
|
||||
.equalTo(RoomSummaryEntityFields.ROOM_ID, roomId)
|
||||
.equalTo(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.JOIN.name)
|
||||
}
|
||||
} catch (exception: TimeoutCancellationException) {
|
||||
throw CreateRoomFailure.CreatedWithTimeout(roomId)
|
||||
}
|
||||
|
||||
return roomId
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a local room entity from the given room creation params.
|
||||
* This will also generate and store in database the chunk and the events related to the room params in order to retrieve and display the local room.
|
||||
*/
|
||||
private suspend fun createLocalRoomEntity(realm: Realm, roomId: String, createRoomBody: CreateRoomBody) {
|
||||
RoomEntity.getOrCreate(realm, roomId).apply {
|
||||
membership = Membership.JOIN
|
||||
chunks.add(createLocalRoomChunk(realm, roomId, createRoomBody))
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLocalRoomSummaryEntity(realm: Realm, roomId: String, createRoomBody: CreateRoomBody) {
|
||||
val otherUserId = createRoomBody.getDirectUserId()
|
||||
if (otherUserId != null) {
|
||||
RoomSummaryEntity.getOrCreate(realm, roomId).apply {
|
||||
isDirect = true
|
||||
directUserId = otherUserId
|
||||
}
|
||||
}
|
||||
roomSummaryUpdater.update(
|
||||
realm = realm,
|
||||
roomId = roomId,
|
||||
membership = Membership.JOIN,
|
||||
roomSummary = RoomSyncSummary(
|
||||
heroes = createRoomBody.invitedUserIds.orEmpty().take(5),
|
||||
joinedMembersCount = 1,
|
||||
invitedMembersCount = createRoomBody.invitedUserIds?.size ?: 0
|
||||
),
|
||||
updateMembers = !createRoomBody.invitedUserIds.isNullOrEmpty()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single chunk containing the necessary events to display the local room.
|
||||
*
|
||||
* @param realm the current instance of realm
|
||||
* @param roomId the id of the local room
|
||||
* @param createRoomBody the room creation params
|
||||
*
|
||||
* @return a chunk entity
|
||||
*/
|
||||
private suspend fun createLocalRoomChunk(realm: Realm, roomId: String, createRoomBody: CreateRoomBody): ChunkEntity {
|
||||
val chunkEntity = realm.createObject<ChunkEntity>().apply {
|
||||
isLastBackward = true
|
||||
isLastForward = true
|
||||
}
|
||||
|
||||
val eventList = createLocalRoomEvents(createRoomBody)
|
||||
val eventIds = ArrayList<String>(eventList.size)
|
||||
val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
|
||||
|
||||
for (event in eventList) {
|
||||
if (event.eventId == null || event.senderId == null || event.type == null) {
|
||||
continue
|
||||
}
|
||||
|
||||
eventIds.add(event.eventId)
|
||||
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED, null).copyToRealmOrIgnore(realm, EventInsertType.INCREMENTAL_SYNC)
|
||||
if (event.stateKey != null) {
|
||||
CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply {
|
||||
eventId = event.eventId
|
||||
root = eventEntity
|
||||
}
|
||||
if (event.type == EventType.STATE_ROOM_MEMBER) {
|
||||
roomMemberContentsByUser[event.stateKey] = event.getFixedRoomMemberContent()
|
||||
roomMemberEventHandler.handle(realm, roomId, event, false)
|
||||
}
|
||||
}
|
||||
|
||||
roomMemberContentsByUser.getOrPut(event.senderId) {
|
||||
// If we don't have any new state on this user, get it from db
|
||||
val rootStateEvent = CurrentStateEventEntity.getOrNull(realm, roomId, event.senderId, EventType.STATE_ROOM_MEMBER)?.root
|
||||
rootStateEvent?.asDomain()?.getFixedRoomMemberContent()
|
||||
}
|
||||
|
||||
chunkEntity.addTimelineEvent(
|
||||
roomId = roomId,
|
||||
eventEntity = eventEntity,
|
||||
direction = PaginationDirection.FORWARDS,
|
||||
roomMemberContentsByUser = roomMemberContentsByUser
|
||||
)
|
||||
}
|
||||
|
||||
return chunkEntity
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the list of the events related to the room creation params.
|
||||
*
|
||||
* @param createRoomBody the room creation params
|
||||
*
|
||||
* @return the list of events
|
||||
*/
|
||||
private suspend fun createLocalRoomEvents(createRoomBody: CreateRoomBody): List<Event> {
|
||||
val myUser = userService.getUser(userId) ?: User(userId)
|
||||
val invitedUsers = createRoomBody.invitedUserIds.orEmpty()
|
||||
.mapNotNull { tryOrNull { userService.resolveUser(it) } }
|
||||
|
||||
val createRoomEvent = createFakeEvent(
|
||||
type = EventType.STATE_ROOM_CREATE,
|
||||
content = RoomCreateContent(
|
||||
creator = userId
|
||||
).toContent()
|
||||
)
|
||||
val myRoomMemberEvent = createFakeEvent(
|
||||
type = EventType.STATE_ROOM_MEMBER,
|
||||
content = RoomMemberContent(
|
||||
membership = Membership.JOIN,
|
||||
displayName = myUser.displayName,
|
||||
avatarUrl = myUser.avatarUrl
|
||||
).toContent(),
|
||||
stateKey = userId
|
||||
)
|
||||
val roomMemberEvents = invitedUsers.map {
|
||||
createFakeEvent(
|
||||
type = EventType.STATE_ROOM_MEMBER,
|
||||
content = RoomMemberContent(
|
||||
isDirect = createRoomBody.isDirect.orFalse(),
|
||||
membership = Membership.INVITE,
|
||||
displayName = it.displayName,
|
||||
avatarUrl = it.avatarUrl
|
||||
).toContent(),
|
||||
stateKey = it.userId
|
||||
)
|
||||
}
|
||||
|
||||
return buildList {
|
||||
add(createRoomEvent)
|
||||
add(myRoomMemberEvent)
|
||||
addAll(createRoomBody.initialStates.orEmpty().map { createFakeEvent(it.type, it.content, it.stateKey) })
|
||||
addAll(roomMemberEvents)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a local event from the given parameters.
|
||||
*
|
||||
* @param type the event type, see [EventType]
|
||||
* @param content the content of the Event
|
||||
* @param stateKey the stateKey, if any
|
||||
*
|
||||
* @return a fake event
|
||||
*/
|
||||
private fun createFakeEvent(type: String?, content: Content?, stateKey: String? = ""): Event {
|
||||
return Event(
|
||||
type = type,
|
||||
senderId = userId,
|
||||
stateKey = stateKey,
|
||||
content = content,
|
||||
originServerTs = clock.epochMillis(),
|
||||
eventId = UUID.randomUUID().toString()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup default values to the CreateRoomParams as the room is created locally (the default values will not be defined by the server).
|
||||
*/
|
||||
private fun CreateRoomParams.withDefault() = this.apply {
|
||||
if (visibility == null) visibility = RoomDirectoryVisibility.PRIVATE
|
||||
if (historyVisibility == null) historyVisibility = RoomHistoryVisibility.SHARED
|
||||
if (guestAccess == null) guestAccess = GuestAccess.Forbidden
|
||||
}
|
||||
}
|
|
@ -120,3 +120,20 @@ internal data class CreateRoomBody(
|
|||
@Json(name = "room_version")
|
||||
val roomVersion: String?
|
||||
)
|
||||
|
||||
/**
|
||||
* Tells if the created room can be a direct chat one.
|
||||
*
|
||||
* @return true if it is a direct chat
|
||||
*/
|
||||
private fun CreateRoomBody.isDirect(): Boolean {
|
||||
return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT && isDirect == true
|
||||
}
|
||||
|
||||
internal fun CreateRoomBody.getDirectUserId(): String? {
|
||||
return if (isDirect()) {
|
||||
invitedUserIds?.firstOrNull()
|
||||
?: invite3pids?.firstOrNull()?.address
|
||||
?: throw IllegalStateException("You can't create a direct room without an invitedUser")
|
||||
} else null
|
||||
}
|
||||
|
|
|
@ -62,11 +62,6 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||
) : CreateRoomTask {
|
||||
|
||||
override suspend fun execute(params: CreateRoomParams): String {
|
||||
val otherUserId = if (params.isDirect()) {
|
||||
params.getFirstInvitedUserId()
|
||||
?: throw IllegalStateException("You can't create a direct room without an invitedUser")
|
||||
} else null
|
||||
|
||||
if (params.preset == CreateRoomPreset.PRESET_PUBLIC_CHAT) {
|
||||
try {
|
||||
aliasAvailabilityChecker.check(params.roomAliasName)
|
||||
|
@ -111,14 +106,13 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||
RoomSummaryEntity.where(it, roomId).findFirst()?.lastActivityTime = clock.epochMillis()
|
||||
}
|
||||
|
||||
if (otherUserId != null) {
|
||||
handleDirectChatCreation(roomId, otherUserId)
|
||||
}
|
||||
handleDirectChatCreation(roomId, createRoomBody.getDirectUserId())
|
||||
setReadMarkers(roomId)
|
||||
return roomId
|
||||
}
|
||||
|
||||
private suspend fun handleDirectChatCreation(roomId: String, otherUserId: String) {
|
||||
private suspend fun handleDirectChatCreation(roomId: String, otherUserId: String?) {
|
||||
otherUserId ?: return // This is not a direct room
|
||||
monarchy.awaitTransaction { realm ->
|
||||
RoomSummaryEntity.where(realm, roomId).findFirst()?.apply {
|
||||
this.directUserId = otherUserId
|
||||
|
@ -133,21 +127,4 @@ internal class DefaultCreateRoomTask @Inject constructor(
|
|||
val setReadMarkerParams = SetReadMarkersTask.Params(roomId, forceReadReceipt = true, forceReadMarker = true)
|
||||
return readMarkersTask.execute(setReadMarkerParams)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the created room can be a direct chat one.
|
||||
*
|
||||
* @return true if it is a direct chat
|
||||
*/
|
||||
private fun CreateRoomParams.isDirect(): Boolean {
|
||||
return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT &&
|
||||
isDirect == true
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first invited user id
|
||||
*/
|
||||
private fun CreateRoomParams.getFirstInvitedUserId(): String? {
|
||||
return invitedUserIds.firstOrNull() ?: invite3pids.firstOrNull()?.value
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import kotlinx.coroutines.withContext
|
|||
import okhttp3.internal.closeQuietly
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.room.model.localecho.RoomLocalEcho
|
||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||
|
@ -383,6 +384,7 @@ internal class DefaultTimeline(
|
|||
}
|
||||
|
||||
private suspend fun loadRoomMembersIfNeeded() {
|
||||
if (RoomLocalEcho.isLocalEchoId(roomId)) return
|
||||
val loadRoomMembersParam = LoadRoomMembersTask.Params(roomId)
|
||||
try {
|
||||
loadRoomMembersTask.execute(loadRoomMembersParam)
|
||||
|
|
|
@ -20,10 +20,12 @@ import im.vector.app.core.platform.VectorViewModelAction
|
|||
import im.vector.app.features.userdirectory.PendingSelection
|
||||
|
||||
sealed class CreateDirectRoomAction : VectorViewModelAction {
|
||||
data class CreateRoomAndInviteSelectedUsers(
|
||||
data class PrepareRoomWithSelectedUsers(
|
||||
val selections: Set<PendingSelection>
|
||||
) : CreateDirectRoomAction()
|
||||
|
||||
object CreateRoomAndInviteSelectedUsers : CreateDirectRoomAction()
|
||||
|
||||
data class QrScannedAction(
|
||||
val result: String
|
||||
) : CreateDirectRoomAction()
|
||||
|
|
|
@ -161,7 +161,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
|
|||
|
||||
private fun onMenuItemSelected(action: UserListSharedAction.OnMenuItemSelected) {
|
||||
if (action.itemId == R.id.action_create_direct_room) {
|
||||
viewModel.handle(CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers(action.selections))
|
||||
viewModel.handle(CreateDirectRoomAction.PrepareRoomWithSelectedUsers(action.selections))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ class CreateDirectRoomViewModel @AssistedInject constructor(
|
|||
|
||||
override fun handle(action: CreateDirectRoomAction) {
|
||||
when (action) {
|
||||
is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onSubmitInvitees(action.selections)
|
||||
is CreateDirectRoomAction.PrepareRoomWithSelectedUsers -> onSubmitInvitees(action.selections)
|
||||
is CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers -> onCreateRoomWithInvitees()
|
||||
is CreateDirectRoomAction.QrScannedAction -> onCodeParsed(action)
|
||||
}
|
||||
}
|
||||
|
@ -96,16 +97,18 @@ class CreateDirectRoomViewModel @AssistedInject constructor(
|
|||
}
|
||||
if (existingRoomId != null) {
|
||||
// Do not create a new DM, just tell that the creation is successful by passing the existing roomId
|
||||
setState {
|
||||
copy(createAndInviteState = Success(existingRoomId))
|
||||
}
|
||||
setState { copy(createAndInviteState = Success(existingRoomId)) }
|
||||
} else {
|
||||
// Create the DM
|
||||
createRoomAndInviteSelectedUsers(selections)
|
||||
createLocalRoomWithSelectedUsers(selections)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createRoomAndInviteSelectedUsers(selections: Set<PendingSelection>) {
|
||||
private fun onCreateRoomWithInvitees() {
|
||||
// Create the DM
|
||||
withState { createLocalRoomWithSelectedUsers(it.pendingSelections) }
|
||||
}
|
||||
|
||||
private fun createLocalRoomWithSelectedUsers(selections: Set<PendingSelection>) {
|
||||
setState { copy(createAndInviteState = Loading()) }
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
|
@ -127,8 +130,7 @@ class CreateDirectRoomViewModel @AssistedInject constructor(
|
|||
|
||||
val result = runCatchingToAsync {
|
||||
if (vectorFeatures.shouldStartDmOnFirstMessage()) {
|
||||
// Todo: Prepare direct room creation
|
||||
throw Throwable("Start DM on first message is not implemented yet.")
|
||||
session.roomService().createLocalRoom(roomParams)
|
||||
} else {
|
||||
session.roomService().createRoom(roomParams)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@ package im.vector.app.features.createdirect
|
|||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MavericksState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.features.userdirectory.PendingSelection
|
||||
|
||||
data class CreateDirectRoomViewState(
|
||||
val pendingSelections: Set<PendingSelection> = emptySet(),
|
||||
val createAndInviteState: Async<String> = Uninitialized
|
||||
) : MavericksState
|
||||
|
|
Loading…
Reference in a new issue