create room : start integrating the address field
This commit is contained in:
parent
93bb02ef3b
commit
2c107eeab3
11 changed files with 65 additions and 25 deletions
|
|
@ -19,4 +19,6 @@ data class CreateRoomConfig(
|
||||||
val avatarUri: Uri? = null,
|
val avatarUri: Uri? = null,
|
||||||
val invites: ImmutableList<MatrixUser> = persistentListOf(),
|
val invites: ImmutableList<MatrixUser> = persistentListOf(),
|
||||||
val roomVisibility: RoomVisibilityState = RoomVisibilityState.Private,
|
val roomVisibility: RoomVisibilityState = RoomVisibilityState.Private,
|
||||||
)
|
) {
|
||||||
|
val isValid = roomName.isNullOrEmpty().not() && roomVisibility.isValid()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import android.net.Uri
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomAccess
|
import io.element.android.features.createroom.impl.configureroom.RoomAccess
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomAccessItem
|
import io.element.android.features.createroom.impl.configureroom.RoomAccessItem
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomAddress
|
import io.element.android.features.createroom.impl.configureroom.RoomAddress
|
||||||
|
import io.element.android.features.createroom.impl.configureroom.RoomAddressErrorState
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityItem
|
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityItem
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState
|
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState
|
||||||
import io.element.android.features.createroom.impl.di.CreateRoomScope
|
import io.element.android.features.createroom.impl.di.CreateRoomScope
|
||||||
|
|
@ -23,7 +24,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.getAndUpdate
|
import kotlinx.coroutines.flow.getAndUpdate
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.Normalizer
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@SingleIn(CreateRoomScope::class)
|
@SingleIn(CreateRoomScope::class)
|
||||||
|
|
@ -86,6 +86,7 @@ class CreateRoomDataStore @Inject constructor(
|
||||||
RoomVisibilityItem.Private -> RoomVisibilityState.Private
|
RoomVisibilityItem.Private -> RoomVisibilityState.Private
|
||||||
RoomVisibilityItem.Public -> RoomVisibilityState.Public(
|
RoomVisibilityItem.Public -> RoomVisibilityState.Public(
|
||||||
roomAddress = RoomAddress.AutoFilled(config.roomName.orEmpty()),
|
roomAddress = RoomAddress.AutoFilled(config.roomName.orEmpty()),
|
||||||
|
roomAddressErrorState = RoomAddressErrorState.None,
|
||||||
roomAccess = RoomAccess.Anyone,
|
roomAccess = RoomAccess.Anyone,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import io.element.android.features.createroom.impl.CreateRoomConfig
|
||||||
import io.element.android.features.createroom.impl.CreateRoomDataStore
|
import io.element.android.features.createroom.impl.CreateRoomDataStore
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
import io.element.android.libraries.architecture.runUpdatingState
|
||||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
@ -39,7 +39,7 @@ import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Optional
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ConfigureRoomPresenter @Inject constructor(
|
class ConfigureRoomPresenter @Inject constructor(
|
||||||
|
|
@ -132,7 +132,7 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
config: CreateRoomConfig,
|
config: CreateRoomConfig,
|
||||||
createRoomAction: MutableState<AsyncAction<RoomId>>
|
createRoomAction: MutableState<AsyncAction<RoomId>>
|
||||||
) = launch {
|
) = launch {
|
||||||
suspend {
|
runUpdatingState(createRoomAction) {
|
||||||
val avatarUrl = config.avatarUri?.let { uploadAvatar(it) }
|
val avatarUrl = config.avatarUri?.let { uploadAvatar(it) }
|
||||||
val params = CreateRoomParameters(
|
val params = CreateRoomParameters(
|
||||||
name = config.roomName,
|
name = config.roomName,
|
||||||
|
|
@ -144,13 +144,17 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
preset = if (config.roomVisibility is RoomVisibilityState.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT,
|
preset = if (config.roomVisibility is RoomVisibilityState.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT,
|
||||||
invite = config.invites.map { it.userId },
|
invite = config.invites.map { it.userId },
|
||||||
avatar = avatarUrl,
|
avatar = avatarUrl,
|
||||||
|
canonicalAlias = config.roomVisibility.roomAddress()
|
||||||
)
|
)
|
||||||
matrixClient.createRoom(params).getOrThrow()
|
matrixClient.createRoom(params)
|
||||||
.also {
|
.onFailure { failure ->
|
||||||
|
Timber.e(failure, "Failed to create room")
|
||||||
|
}
|
||||||
|
.onSuccess {
|
||||||
dataStore.clearCachedData()
|
dataStore.clearCachedData()
|
||||||
analyticsService.capture(CreatedRoom(isDM = false))
|
analyticsService.capture(CreatedRoom(isDM = false))
|
||||||
}
|
}
|
||||||
}.runCatchingUpdatingState(createRoomAction)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun uploadAvatar(avatarUri: Uri): String {
|
private suspend fun uploadAvatar(avatarUri: Uri): String {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,4 @@ data class ConfigureRoomState(
|
||||||
val cameraPermissionState: PermissionsState,
|
val cameraPermissionState: PermissionsState,
|
||||||
val homeserverName: String,
|
val homeserverName: String,
|
||||||
val eventSink: (ConfigureRoomEvents) -> Unit
|
val eventSink: (ConfigureRoomEvents) -> Unit
|
||||||
) {
|
)
|
||||||
val isCreateButtonEnabled: Boolean = config.roomName.isNullOrEmpty().not()
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider<ConfigureRoomSt
|
||||||
invites = aMatrixUserList().toImmutableList(),
|
invites = aMatrixUserList().toImmutableList(),
|
||||||
roomVisibility = RoomVisibilityState.Public(
|
roomVisibility = RoomVisibilityState.Public(
|
||||||
roomAddress = RoomAddress.AutoFilled("Room 101"),
|
roomAddress = RoomAddress.AutoFilled("Room 101"),
|
||||||
roomAccess = RoomAccess.Knocking
|
roomAccess = RoomAccess.Knocking,
|
||||||
|
roomAddressErrorState = RoomAddressErrorState.None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ fun ConfigureRoomView(
|
||||||
modifier = modifier.clearFocusOnTap(focusManager),
|
modifier = modifier.clearFocusOnTap(focusManager),
|
||||||
topBar = {
|
topBar = {
|
||||||
ConfigureRoomToolbar(
|
ConfigureRoomToolbar(
|
||||||
isNextActionEnabled = state.isCreateButtonEnabled,
|
isNextActionEnabled = state.config.isValid,
|
||||||
onBackClick = onBackClick,
|
onBackClick = onBackClick,
|
||||||
onNextClick = {
|
onNextClick = {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
|
|
@ -138,7 +138,7 @@ fun ConfigureRoomView(
|
||||||
state.eventSink(ConfigureRoomEvents.RoomAccessChanged(it))
|
state.eventSink(ConfigureRoomEvents.RoomAccessChanged(it))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
RoomAddress(
|
RoomAddressField(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
address = state.config.roomVisibility.roomAddress,
|
address = state.config.roomVisibility.roomAddress,
|
||||||
homeserverName = state.homeserverName,
|
homeserverName = state.homeserverName,
|
||||||
|
|
@ -310,7 +310,7 @@ private fun RoomAccessOptions(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RoomAddress(
|
private fun RoomAddressField(
|
||||||
address: RoomAddress,
|
address: RoomAddress,
|
||||||
homeserverName: String,
|
homeserverName: String,
|
||||||
onAddressChange: (String) -> Unit,
|
onAddressChange: (String) -> Unit,
|
||||||
|
|
@ -326,13 +326,10 @@ private fun RoomAddress(
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
text = "Room address",
|
text = "Room address",
|
||||||
)
|
)
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = when (address) {
|
value = address.value,
|
||||||
is RoomAddress.AutoFilled -> address.address
|
|
||||||
is RoomAddress.Edited -> address.address
|
|
||||||
},
|
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
Text(
|
Text(
|
||||||
text = "#",
|
text = "#",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.configureroom
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
sealed interface RoomAddress {
|
sealed class RoomAddress(open val value: String) {
|
||||||
data class AutoFilled(val address: String) : RoomAddress
|
data class AutoFilled(override val value: String) : RoomAddress(value)
|
||||||
data class Edited(val address: String) : RoomAddress
|
data class Edited(override val value: String) : RoomAddress(value)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
* Please see LICENSE in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the error state of a room address.
|
||||||
|
*/
|
||||||
|
sealed interface RoomAddressErrorState {
|
||||||
|
data object InvalidCharacters : RoomAddressErrorState
|
||||||
|
data object AlreadyExists : RoomAddressErrorState
|
||||||
|
data object None : RoomAddressErrorState
|
||||||
|
}
|
||||||
|
|
@ -7,11 +7,28 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.configureroom
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
|
import java.util.Optional
|
||||||
|
|
||||||
sealed interface RoomVisibilityState {
|
sealed interface RoomVisibilityState {
|
||||||
data object Private : RoomVisibilityState
|
data object Private : RoomVisibilityState
|
||||||
|
|
||||||
data class Public(
|
data class Public(
|
||||||
val roomAddress: RoomAddress,
|
val roomAddress: RoomAddress,
|
||||||
val roomAccess: RoomAccess
|
val roomAddressErrorState: RoomAddressErrorState,
|
||||||
|
val roomAccess: RoomAccess,
|
||||||
) : RoomVisibilityState
|
) : RoomVisibilityState
|
||||||
|
|
||||||
|
fun roomAddress(): Optional<String> {
|
||||||
|
return when (this) {
|
||||||
|
is Private -> Optional.empty()
|
||||||
|
is Public -> Optional.of(roomAddress.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isValid(): Boolean {
|
||||||
|
return when (this) {
|
||||||
|
is Private -> true
|
||||||
|
is Public -> roomAddressErrorState is RoomAddressErrorState.None && roomAddress.value.isNotEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
package io.element.android.libraries.matrix.api.createroom
|
package io.element.android.libraries.matrix.api.createroom
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
import java.util.Optional
|
||||||
|
|
||||||
data class CreateRoomParameters(
|
data class CreateRoomParameters(
|
||||||
val name: String?,
|
val name: String?,
|
||||||
|
|
@ -19,4 +20,5 @@ data class CreateRoomParameters(
|
||||||
val invite: List<UserId>? = null,
|
val invite: List<UserId>? = null,
|
||||||
val avatar: String? = null,
|
val avatar: String? = null,
|
||||||
val joinRuleOverride: JoinRuleOverride = JoinRuleOverride.None,
|
val joinRuleOverride: JoinRuleOverride = JoinRuleOverride.None,
|
||||||
|
val canonicalAlias: Optional<String> = Optional.empty(),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,8 @@ class RustMatrixClient(
|
||||||
joinRuleOverride = when (createRoomParams.joinRuleOverride) {
|
joinRuleOverride = when (createRoomParams.joinRuleOverride) {
|
||||||
JoinRuleOverride.Knock -> RustJoinRule.Knock
|
JoinRuleOverride.Knock -> RustJoinRule.Knock
|
||||||
JoinRuleOverride.None -> null
|
JoinRuleOverride.None -> null
|
||||||
}
|
},
|
||||||
|
canonicalAlias = createRoomParams.canonicalAlias.getOrNull(),
|
||||||
)
|
)
|
||||||
val roomId = RoomId(client.createRoom(rustParams))
|
val roomId = RoomId(client.createRoom(rustParams))
|
||||||
// Wait to receive the room back from the sync but do not returns failure if it fails.
|
// Wait to receive the room back from the sync but do not returns failure if it fails.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue