create room : start adding new options in ui
This commit is contained in:
parent
5674d10d9b
commit
f6938fa737
15 changed files with 447 additions and 110 deletions
|
|
@ -8,7 +8,7 @@
|
||||||
package io.element.android.features.createroom.impl
|
package io.element.android.features.createroom.impl
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomPrivacy
|
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -18,5 +18,5 @@ data class CreateRoomConfig(
|
||||||
val topic: String? = null,
|
val topic: String? = null,
|
||||||
val avatarUri: Uri? = null,
|
val avatarUri: Uri? = null,
|
||||||
val invites: ImmutableList<MatrixUser> = persistentListOf(),
|
val invites: ImmutableList<MatrixUser> = persistentListOf(),
|
||||||
val privacy: RoomPrivacy = RoomPrivacy.Private,
|
val roomVisibility: RoomVisibilityState = RoomVisibilityState.Private,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,11 @@
|
||||||
package io.element.android.features.createroom.impl
|
package io.element.android.features.createroom.impl
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomPrivacy
|
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.RoomAddress
|
||||||
|
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.di.CreateRoomScope
|
import io.element.android.features.createroom.impl.di.CreateRoomScope
|
||||||
import io.element.android.features.createroom.impl.userlist.UserListDataStore
|
import io.element.android.features.createroom.impl.userlist.UserListDataStore
|
||||||
import io.element.android.libraries.androidutils.file.safeDelete
|
import io.element.android.libraries.androidutils.file.safeDelete
|
||||||
|
|
@ -17,7 +21,9 @@ import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
|
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)
|
||||||
|
|
@ -31,28 +37,87 @@ class CreateRoomDataStore @Inject constructor(
|
||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCreateRoomConfig(): Flow<CreateRoomConfig> = combine(
|
val createRoomConfig: Flow<CreateRoomConfig> = combine(
|
||||||
selectedUserListDataStore.selectedUsers(),
|
selectedUserListDataStore.selectedUsers(),
|
||||||
createRoomConfigFlow,
|
createRoomConfigFlow,
|
||||||
) { selectedUsers, config ->
|
) { selectedUsers, config ->
|
||||||
config.copy(invites = selectedUsers.toImmutableList())
|
config.copy(invites = selectedUsers.toImmutableList())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setRoomName(roomName: String?) {
|
fun setRoomName(roomName: String) {
|
||||||
createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(roomName = roomName?.takeIf { it.isNotEmpty() }))
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
val newVisibility = when (config.roomVisibility) {
|
||||||
|
is RoomVisibilityState.Public -> {
|
||||||
|
val roomAddress = config.roomVisibility.roomAddress
|
||||||
|
if (roomAddress is RoomAddress.AutoFilled || roomName.isEmpty()) {
|
||||||
|
config.roomVisibility.copy(
|
||||||
|
roomAddress = RoomAddress.AutoFilled(roomName),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
config.roomVisibility
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> config.roomVisibility
|
||||||
|
}
|
||||||
|
config.copy(
|
||||||
|
roomName = roomName.takeIf { it.isNotEmpty() },
|
||||||
|
roomVisibility = newVisibility,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTopic(topic: String?) {
|
fun setTopic(topic: String) {
|
||||||
createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(topic = topic?.takeIf { it.isNotEmpty() }))
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(topic = topic.takeIf { it.isNotEmpty() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setAvatarUri(uri: Uri?, cached: Boolean = false) {
|
fun setAvatarUri(uri: Uri?, cached: Boolean = false) {
|
||||||
cachedAvatarUri = uri.takeIf { cached }
|
cachedAvatarUri = uri.takeIf { cached }
|
||||||
createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(avatarUri = uri))
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(avatarUri = uri)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setPrivacy(privacy: RoomPrivacy) {
|
fun setRoomVisibility(visibility: RoomVisibilityItem) {
|
||||||
createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(privacy = privacy))
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(
|
||||||
|
roomVisibility = when (visibility) {
|
||||||
|
RoomVisibilityItem.Private -> RoomVisibilityState.Private
|
||||||
|
RoomVisibilityItem.Public -> RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled(config.roomName.orEmpty()),
|
||||||
|
roomAccess = RoomAccess.Anyone,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRoomAddress(address: String) {
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(
|
||||||
|
roomVisibility = when (config.roomVisibility) {
|
||||||
|
is RoomVisibilityState.Public -> config.roomVisibility.copy(roomAddress = RoomAddress.Edited(address))
|
||||||
|
else -> config.roomVisibility
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setRoomAccess(access: RoomAccessItem) {
|
||||||
|
createRoomConfigFlow.getAndUpdate { config ->
|
||||||
|
config.copy(
|
||||||
|
roomVisibility = when (config.roomVisibility) {
|
||||||
|
is RoomVisibilityState.Public -> {
|
||||||
|
when (access) {
|
||||||
|
RoomAccessItem.Anyone -> config.roomVisibility.copy(roomAccess = RoomAccess.Anyone)
|
||||||
|
RoomAccessItem.AskToJoin -> config.roomVisibility.copy(roomAccess = RoomAccess.Knocking)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> config.roomVisibility
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearCachedData() {
|
fun clearCachedData() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.selection.selectable
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.Role
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.element.android.compound.theme.ElementTheme
|
||||||
|
import io.element.android.features.createroom.impl.configureroom.RoomAccessItem
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.RadioButton
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RoomAccessOption(
|
||||||
|
roomAccessItem: RoomAccessItem,
|
||||||
|
onOptionClick: (RoomAccessItem) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
isSelected: Boolean = false,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.selectable(
|
||||||
|
selected = isSelected,
|
||||||
|
onClick = { onOptionClick(roomAccessItem) },
|
||||||
|
role = Role.RadioButton,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column(Modifier.weight(1f)) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(roomAccessItem.title),
|
||||||
|
style = ElementTheme.typography.fontBodyLgRegular,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
)
|
||||||
|
Spacer(Modifier.size(8.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(roomAccessItem.description),
|
||||||
|
style = ElementTheme.typography.fontBodySmRegular,
|
||||||
|
color = MaterialTheme.colorScheme.tertiary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
RadioButton(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
.size(48.dp),
|
||||||
|
selected = isSelected,
|
||||||
|
// null recommended for accessibility with screenreaders
|
||||||
|
onClick = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreviewsDayNight
|
||||||
|
@Composable
|
||||||
|
internal fun RoomAccessOptionPreview() = ElementPreview {
|
||||||
|
val aRoomAccessItem = RoomAccessItem.Anyone
|
||||||
|
Column {
|
||||||
|
RoomAccessOption(
|
||||||
|
roomAccessItem = aRoomAccessItem,
|
||||||
|
onOptionClick = {},
|
||||||
|
isSelected = true,
|
||||||
|
)
|
||||||
|
RoomAccessOption(
|
||||||
|
roomAccessItem = aRoomAccessItem,
|
||||||
|
onOptionClick = {},
|
||||||
|
isSelected = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.components
|
package io.element.android.features.createroom.impl.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -14,15 +16,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.selection.selectable
|
import androidx.compose.foundation.selection.selectable
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.Role
|
import androidx.compose.ui.semantics.Role
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.features.createroom.impl.configureroom.RoomPrivacyItem
|
import io.element.android.features.createroom.impl.configureroom.RoomVisibilityItem
|
||||||
import io.element.android.features.createroom.impl.configureroom.roomPrivacyItems
|
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||||
|
|
@ -30,9 +34,9 @@ import io.element.android.libraries.designsystem.theme.components.RadioButton
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RoomPrivacyOption(
|
fun RoomVisibilityOption(
|
||||||
roomPrivacyItem: RoomPrivacyItem,
|
roomPrivacyItem: RoomVisibilityItem,
|
||||||
onOptionClick: (RoomPrivacyItem) -> Unit,
|
onOptionClick: (RoomVisibilityItem) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
isSelected: Boolean = false,
|
isSelected: Boolean = false,
|
||||||
) {
|
) {
|
||||||
|
|
@ -44,28 +48,31 @@ fun RoomPrivacyOption(
|
||||||
onClick = { onOptionClick(roomPrivacyItem) },
|
onClick = { onOptionClick(roomPrivacyItem) },
|
||||||
role = Role.RadioButton,
|
role = Role.RadioButton,
|
||||||
)
|
)
|
||||||
.padding(8.dp),
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Box(
|
||||||
modifier = Modifier.padding(horizontal = 8.dp),
|
modifier = modifier
|
||||||
resourceId = roomPrivacyItem.icon,
|
.size(30.dp)
|
||||||
contentDescription = null,
|
.clip(RoundedCornerShape(8.dp))
|
||||||
tint = MaterialTheme.colorScheme.secondary,
|
.background(ElementTheme.colors.bgSubtleSecondary)
|
||||||
)
|
.padding(3.dp),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
Column(
|
|
||||||
Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.padding(horizontal = 8.dp)
|
|
||||||
) {
|
) {
|
||||||
|
Icon(
|
||||||
|
resourceId = roomPrivacyItem.icon,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = if(isSelected) ElementTheme.colors.iconPrimary else ElementTheme.colors.iconSecondary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(Modifier.size(16.dp))
|
||||||
|
Column(Modifier.weight(1f)) {
|
||||||
Text(
|
Text(
|
||||||
text = roomPrivacyItem.title,
|
text = stringResource(roomPrivacyItem.title),
|
||||||
style = ElementTheme.typography.fontBodyLgRegular,
|
style = ElementTheme.typography.fontBodyLgRegular,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
)
|
)
|
||||||
Spacer(Modifier.size(3.dp))
|
Spacer(Modifier.size(3.dp))
|
||||||
Text(
|
Text(
|
||||||
text = roomPrivacyItem.description,
|
text = stringResource(roomPrivacyItem.description),
|
||||||
style = ElementTheme.typography.fontBodySmRegular,
|
style = ElementTheme.typography.fontBodySmRegular,
|
||||||
color = MaterialTheme.colorScheme.tertiary,
|
color = MaterialTheme.colorScheme.tertiary,
|
||||||
)
|
)
|
||||||
|
|
@ -85,14 +92,14 @@ fun RoomPrivacyOption(
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun RoomPrivacyOptionPreview() = ElementPreview {
|
internal fun RoomPrivacyOptionPreview() = ElementPreview {
|
||||||
val aRoomPrivacyItem = roomPrivacyItems().first()
|
val aRoomPrivacyItem = RoomVisibilityItem.Private
|
||||||
Column {
|
Column {
|
||||||
RoomPrivacyOption(
|
RoomVisibilityOption(
|
||||||
roomPrivacyItem = aRoomPrivacyItem,
|
roomPrivacyItem = aRoomPrivacyItem,
|
||||||
onOptionClick = {},
|
onOptionClick = {},
|
||||||
isSelected = true,
|
isSelected = true,
|
||||||
)
|
)
|
||||||
RoomPrivacyOption(
|
RoomVisibilityOption(
|
||||||
roomPrivacyItem = aRoomPrivacyItem,
|
roomPrivacyItem = aRoomPrivacyItem,
|
||||||
onOptionClick = {},
|
onOptionClick = {},
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
|
|
@ -14,8 +14,10 @@ import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
sealed interface ConfigureRoomEvents {
|
sealed interface ConfigureRoomEvents {
|
||||||
data class RoomNameChanged(val name: String) : ConfigureRoomEvents
|
data class RoomNameChanged(val name: String) : ConfigureRoomEvents
|
||||||
data class TopicChanged(val topic: String) : ConfigureRoomEvents
|
data class TopicChanged(val topic: String) : ConfigureRoomEvents
|
||||||
data class RoomPrivacyChanged(val privacy: RoomPrivacy) : ConfigureRoomEvents
|
data class RoomVisibilityChanged(val visibilityItem: RoomVisibilityItem) : ConfigureRoomEvents
|
||||||
data class RemoveFromSelection(val matrixUser: MatrixUser) : ConfigureRoomEvents
|
data class RoomAccessChanged(val roomAccess: RoomAccessItem) : ConfigureRoomEvents
|
||||||
|
data class RoomAddressChanged(val roomAddress: String) : ConfigureRoomEvents
|
||||||
|
data class RemoveUserFromSelection(val matrixUser: MatrixUser) : ConfigureRoomEvents
|
||||||
data class CreateRoom(val config: CreateRoomConfig) : ConfigureRoomEvents
|
data class CreateRoom(val config: CreateRoomConfig) : ConfigureRoomEvents
|
||||||
data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents
|
data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents
|
||||||
data object CancelCreateRoom : ConfigureRoomEvents
|
data object CancelCreateRoom : ConfigureRoomEvents
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): ConfigureRoomState {
|
override fun present(): ConfigureRoomState {
|
||||||
val cameraPermissionState = cameraPermissionPresenter.present()
|
val cameraPermissionState = cameraPermissionPresenter.present()
|
||||||
val createRoomConfig = dataStore.getCreateRoomConfig().collectAsState(CreateRoomConfig())
|
val createRoomConfig = dataStore.createRoomConfig.collectAsState(CreateRoomConfig())
|
||||||
|
|
||||||
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(
|
val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker(
|
||||||
onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) },
|
onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) },
|
||||||
|
|
@ -92,8 +92,10 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
when (event) {
|
when (event) {
|
||||||
is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name)
|
is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name)
|
||||||
is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic)
|
is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic)
|
||||||
is ConfigureRoomEvents.RoomPrivacyChanged -> dataStore.setPrivacy(event.privacy)
|
is ConfigureRoomEvents.RoomVisibilityChanged -> dataStore.setRoomVisibility(event.visibilityItem)
|
||||||
is ConfigureRoomEvents.RemoveFromSelection -> dataStore.selectedUserListDataStore.removeUserFromSelection(event.matrixUser)
|
is ConfigureRoomEvents.RemoveUserFromSelection -> dataStore.selectedUserListDataStore.removeUserFromSelection(event.matrixUser)
|
||||||
|
is ConfigureRoomEvents.RoomAccessChanged -> dataStore.setRoomAccess(event.roomAccess)
|
||||||
|
is ConfigureRoomEvents.RoomAddressChanged -> dataStore.setRoomAddress(event.roomAddress)
|
||||||
is ConfigureRoomEvents.CreateRoom -> createRoom(event.config)
|
is ConfigureRoomEvents.CreateRoom -> createRoom(event.config)
|
||||||
is ConfigureRoomEvents.HandleAvatarAction -> {
|
is ConfigureRoomEvents.HandleAvatarAction -> {
|
||||||
when (event.action) {
|
when (event.action) {
|
||||||
|
|
@ -109,6 +111,7 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureRoomEvents.CancelCreateRoom -> createRoomAction.value = AsyncAction.Uninitialized
|
ConfigureRoomEvents.CancelCreateRoom -> createRoomAction.value = AsyncAction.Uninitialized
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,10 +133,10 @@ class ConfigureRoomPresenter @Inject constructor(
|
||||||
val params = CreateRoomParameters(
|
val params = CreateRoomParameters(
|
||||||
name = config.roomName,
|
name = config.roomName,
|
||||||
topic = config.topic,
|
topic = config.topic,
|
||||||
isEncrypted = config.privacy == RoomPrivacy.Private,
|
isEncrypted = config.roomVisibility is RoomVisibilityState.Private,
|
||||||
isDirect = false,
|
isDirect = false,
|
||||||
visibility = if (config.privacy == RoomPrivacy.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE,
|
visibility = if (config.roomVisibility is RoomVisibilityState.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE,
|
||||||
preset = if (config.privacy == RoomPrivacy.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,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,10 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider<ConfigureRoomSt
|
||||||
roomName = "Room 101",
|
roomName = "Room 101",
|
||||||
topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines",
|
topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines",
|
||||||
invites = aMatrixUserList().toImmutableList(),
|
invites = aMatrixUserList().toImmutableList(),
|
||||||
privacy = RoomPrivacy.Public,
|
roomVisibility = RoomVisibilityState.Public(
|
||||||
|
roomAddress = RoomAddress.AutoFilled("Room 101"),
|
||||||
|
roomAccess = RoomAccess.Knocking
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -11,16 +11,22 @@ import android.net.Uri
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.imePadding
|
import androidx.compose.foundation.layout.imePadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.selection.selectableGroup
|
import androidx.compose.foundation.selection.selectableGroup
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -29,22 +35,26 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.features.createroom.impl.R
|
import io.element.android.features.createroom.impl.R
|
||||||
import io.element.android.features.createroom.impl.components.RoomPrivacyOption
|
import io.element.android.features.createroom.impl.components.RoomAccessOption
|
||||||
|
import io.element.android.features.createroom.impl.components.RoomVisibilityOption
|
||||||
import io.element.android.libraries.designsystem.components.LabelledTextField
|
import io.element.android.libraries.designsystem.components.LabelledTextField
|
||||||
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||||
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
import io.element.android.libraries.designsystem.modifiers.clearFocusOnTap
|
import io.element.android.libraries.designsystem.modifiers.clearFocusOnTap
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
|
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
||||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
|
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
|
||||||
|
|
@ -103,23 +113,38 @@ fun ConfigureRoomView(
|
||||||
)
|
)
|
||||||
if (state.config.invites.isNotEmpty()) {
|
if (state.config.invites.isNotEmpty()) {
|
||||||
SelectedUsersRowList(
|
SelectedUsersRowList(
|
||||||
modifier = Modifier.padding(bottom = 16.dp),
|
|
||||||
contentPadding = PaddingValues(horizontal = 24.dp),
|
contentPadding = PaddingValues(horizontal = 24.dp),
|
||||||
selectedUsers = state.config.invites,
|
selectedUsers = state.config.invites,
|
||||||
onUserRemove = {
|
onUserRemove = {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
state.eventSink(ConfigureRoomEvents.RemoveFromSelection(it))
|
state.eventSink(ConfigureRoomEvents.RemoveUserFromSelection(it))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
RoomPrivacyOptions(
|
RoomVisibilityOptions(
|
||||||
modifier = Modifier.padding(bottom = 40.dp),
|
selected = when (state.config.roomVisibility) {
|
||||||
selected = state.config.privacy,
|
is RoomVisibilityState.Private -> RoomVisibilityItem.Private
|
||||||
|
is RoomVisibilityState.Public -> RoomVisibilityItem.Public
|
||||||
|
},
|
||||||
onOptionClick = {
|
onOptionClick = {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
state.eventSink(ConfigureRoomEvents.RoomPrivacyChanged(it.privacy))
|
state.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(it))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
if (state.config.roomVisibility is RoomVisibilityState.Public) {
|
||||||
|
RoomAccessOptions(
|
||||||
|
selected = state.config.roomVisibility.roomAccess,
|
||||||
|
onOptionClick = {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
state.eventSink(ConfigureRoomEvents.RoomAccessChanged(it))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
RoomAddress(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
address = state.config.roomVisibility.roomAddress,
|
||||||
|
onAddressChange = { state.eventSink(ConfigureRoomEvents.RoomAddressChanged(it)) },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,24 +246,125 @@ private fun RoomTopic(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RoomPrivacyOptions(
|
private fun ConfigureRoomOptions(
|
||||||
selected: RoomPrivacy?,
|
title: String,
|
||||||
onOptionClick: (RoomPrivacyItem) -> Unit,
|
verticalArrangement: Arrangement.Vertical,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
content: @Composable ColumnScope.() -> Unit,
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.selectableGroup()
|
||||||
|
.padding(horizontal = 12.dp),
|
||||||
|
verticalArrangement = verticalArrangement,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = ElementTheme.typography.fontBodyLgMedium,
|
||||||
|
color = ElementTheme.colors.textPrimary,
|
||||||
|
)
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RoomVisibilityOptions(
|
||||||
|
selected: RoomVisibilityItem,
|
||||||
|
onOptionClick: (RoomVisibilityItem) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val items = roomPrivacyItems()
|
ConfigureRoomOptions(
|
||||||
Column(modifier = modifier.selectableGroup()) {
|
title = "Room visibility",
|
||||||
items.forEach { item ->
|
modifier = modifier,
|
||||||
RoomPrivacyOption(
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
) {
|
||||||
|
RoomVisibilityItem.entries.forEach { item ->
|
||||||
|
RoomVisibilityOption(
|
||||||
roomPrivacyItem = item,
|
roomPrivacyItem = item,
|
||||||
isSelected = selected == item.privacy,
|
isSelected = item == selected,
|
||||||
onOptionClick = onOptionClick,
|
onOptionClick = onOptionClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RoomAccessOptions(
|
||||||
|
selected: RoomAccess,
|
||||||
|
onOptionClick: (RoomAccessItem) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
ConfigureRoomOptions(
|
||||||
|
title = "Room access",
|
||||||
|
modifier = modifier,
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
) {
|
||||||
|
RoomAccessItem.entries.forEach { item ->
|
||||||
|
RoomAccessOption(
|
||||||
|
roomAccessItem = item,
|
||||||
|
isSelected = when (item) {
|
||||||
|
RoomAccessItem.Anyone -> selected == RoomAccess.Anyone
|
||||||
|
RoomAccessItem.AskToJoin -> selected == RoomAccess.Knocking
|
||||||
|
},
|
||||||
|
onOptionClick = onOptionClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RoomAddress(
|
||||||
|
address: RoomAddress,
|
||||||
|
onAddressChange: (String) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
){
|
||||||
|
Column(
|
||||||
|
modifier = modifier,
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
style = ElementTheme.typography.fontBodyMdRegular,
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
text = "Room address",
|
||||||
|
)
|
||||||
|
|
||||||
|
TextField(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
value = when(address) {
|
||||||
|
is RoomAddress.AutoFilled -> address.address
|
||||||
|
is RoomAddress.Edited -> address.address
|
||||||
|
},
|
||||||
|
leadingIcon = {
|
||||||
|
Text(
|
||||||
|
text = "#",
|
||||||
|
style = ElementTheme.typography.fontBodyLgMedium,
|
||||||
|
color = ElementTheme.colors.textSecondary,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
trailingIcon = {
|
||||||
|
Text(
|
||||||
|
text = ":myserver.com",
|
||||||
|
style = ElementTheme.typography.fontBodyLgMedium,
|
||||||
|
color = ElementTheme.colors.textSecondary,
|
||||||
|
modifier = Modifier.padding(end = 16.dp)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
supportingText = {
|
||||||
|
Text(
|
||||||
|
text = "In order for this room to be visible in the public room directory, you will need to a room address. ",
|
||||||
|
style = ElementTheme.typography.fontBodySmRegular,
|
||||||
|
color = ElementTheme.colors.textSecondary,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onValueChange = onAddressChange,
|
||||||
|
singleLine = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
|
@PreviewWithLargeHeight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview {
|
internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview {
|
||||||
ConfigureRoomView(
|
ConfigureRoomView(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
* Copyright 2024 New Vector Ltd.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
* Please see LICENSE in the repository root for full details.
|
* Please see LICENSE in the repository root for full details.
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.configureroom
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
enum class RoomPrivacy {
|
enum class RoomAccess {
|
||||||
Private,
|
Anyone, Knocking, Invite
|
||||||
Public,
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
|
enum class RoomAccessItem(
|
||||||
|
@StringRes val title: Int,
|
||||||
|
@StringRes val description: Int
|
||||||
|
) {
|
||||||
|
Anyone(
|
||||||
|
title = CommonStrings.screen_create_room_access_section_anyone_option_title,
|
||||||
|
description = CommonStrings.screen_create_room_access_section_anyone_option_description,
|
||||||
|
),
|
||||||
|
AskToJoin(
|
||||||
|
title = CommonStrings.screen_create_room_access_section_knocking_option_title,
|
||||||
|
description = CommonStrings.screen_create_room_access_section_knocking_option_description,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
sealed interface RoomAddress {
|
||||||
|
data class AutoFilled(val address: String) : RoomAddress
|
||||||
|
data class Edited(val address: String) : RoomAddress
|
||||||
|
}
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2023, 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
|
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import io.element.android.features.createroom.impl.R
|
|
||||||
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
data class RoomPrivacyItem(
|
|
||||||
val privacy: RoomPrivacy,
|
|
||||||
@DrawableRes val icon: Int,
|
|
||||||
val title: String,
|
|
||||||
val description: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun roomPrivacyItems(): ImmutableList<RoomPrivacyItem> {
|
|
||||||
return RoomPrivacy.entries
|
|
||||||
.map {
|
|
||||||
when (it) {
|
|
||||||
RoomPrivacy.Private -> RoomPrivacyItem(
|
|
||||||
privacy = it,
|
|
||||||
icon = CompoundDrawables.ic_compound_lock_solid,
|
|
||||||
title = stringResource(R.string.screen_create_room_private_option_title),
|
|
||||||
description = stringResource(R.string.screen_create_room_private_option_description),
|
|
||||||
)
|
|
||||||
RoomPrivacy.Public -> RoomPrivacyItem(
|
|
||||||
privacy = it,
|
|
||||||
icon = CompoundDrawables.ic_compound_public,
|
|
||||||
title = stringResource(R.string.screen_create_room_public_option_title),
|
|
||||||
description = stringResource(R.string.screen_create_room_public_option_description),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.toImmutableList()
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023, 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
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import io.element.android.features.createroom.impl.R
|
||||||
|
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
||||||
|
|
||||||
|
enum class RoomVisibilityItem(
|
||||||
|
@DrawableRes val icon: Int,
|
||||||
|
@StringRes val title: Int,
|
||||||
|
@StringRes val description: Int
|
||||||
|
) {
|
||||||
|
Private(
|
||||||
|
icon = CompoundDrawables.ic_compound_lock,
|
||||||
|
title = R.string.screen_create_room_private_option_title,
|
||||||
|
description = R.string.screen_create_room_private_option_description,
|
||||||
|
),
|
||||||
|
Public(
|
||||||
|
icon = CompoundDrawables.ic_compound_public,
|
||||||
|
title = R.string.screen_create_room_public_option_title,
|
||||||
|
description = R.string.screen_create_room_public_option_description,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023, 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
|
||||||
|
|
||||||
|
sealed interface RoomVisibilityState {
|
||||||
|
val roomAccess: RoomAccess
|
||||||
|
|
||||||
|
data object Private : RoomVisibilityState {
|
||||||
|
override val roomAccess: RoomAccess = RoomAccess.Invite
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Public(
|
||||||
|
val roomAddress: RoomAddress,
|
||||||
|
override val roomAccess: RoomAccess
|
||||||
|
) : RoomVisibilityState
|
||||||
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ class ConfigureRoomPresenterTest {
|
||||||
assertThat(initialState.config.topic).isNull()
|
assertThat(initialState.config.topic).isNull()
|
||||||
assertThat(initialState.config.invites).isEmpty()
|
assertThat(initialState.config.invites).isEmpty()
|
||||||
assertThat(initialState.config.avatarUri).isNull()
|
assertThat(initialState.config.avatarUri).isNull()
|
||||||
assertThat(initialState.config.privacy).isEqualTo(RoomPrivacy.Private)
|
assertThat(initialState.config.roomVisibility).isEqualTo(RoomVisibilityState.Private)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,13 +200,13 @@ class ConfigureRoomPresenterTest {
|
||||||
assertThat(newState.config).isEqualTo(expectedConfig)
|
assertThat(newState.config).isEqualTo(expectedConfig)
|
||||||
|
|
||||||
// Room privacy
|
// Room privacy
|
||||||
newState.eventSink(ConfigureRoomEvents.RoomPrivacyChanged(RoomPrivacy.Public))
|
newState.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(RoomVisibilityState.Public))
|
||||||
newState = awaitItem()
|
newState = awaitItem()
|
||||||
expectedConfig = expectedConfig.copy(privacy = RoomPrivacy.Public)
|
expectedConfig = expectedConfig.copy(roomVisibility = RoomVisibilityState.Public)
|
||||||
assertThat(newState.config).isEqualTo(expectedConfig)
|
assertThat(newState.config).isEqualTo(expectedConfig)
|
||||||
|
|
||||||
// Remove user
|
// Remove user
|
||||||
newState.eventSink(ConfigureRoomEvents.RemoveFromSelection(selectedUser1))
|
newState.eventSink(ConfigureRoomEvents.RemoveUserFromSelection(selectedUser1))
|
||||||
newState = awaitItem()
|
newState = awaitItem()
|
||||||
expectedConfig = expectedConfig.copy(invites = expectedConfig.invites.minus(selectedUser1).toImmutableList())
|
expectedConfig = expectedConfig.copy(invites = expectedConfig.invites.minus(selectedUser1).toImmutableList())
|
||||||
assertThat(newState.config).isEqualTo(expectedConfig)
|
assertThat(newState.config).isEqualTo(expectedConfig)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue