From 8c989f716a584e685d80497314369d41446ca247 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 25 Oct 2024 18:27:23 +0200 Subject: [PATCH 01/22] create room : start adding new options in ui --- .../createroom/impl/CreateRoomConfig.kt | 4 +- .../createroom/impl/CreateRoomDataStore.kt | 83 +++++++++- .../impl/components/RoomAccessOption.kt | 87 ++++++++++ ...ivacyOption.kt => RoomVisibilityOption.kt} | 51 +++--- .../impl/configureroom/ConfigureRoomEvents.kt | 6 +- .../configureroom/ConfigureRoomPresenter.kt | 15 +- .../ConfigureRoomStateProvider.kt | 5 +- .../impl/configureroom/ConfigureRoomView.kt | 156 ++++++++++++++++-- .../{RoomPrivacy.kt => RoomAccess.kt} | 7 +- .../impl/configureroom/RoomAccessItem.kt | 26 +++ .../impl/configureroom/RoomAddress.kt | 13 ++ .../impl/configureroom/RoomPrivacyItem.kt | 45 ----- .../impl/configureroom/RoomVisibilityItem.kt | 30 ++++ .../impl/configureroom/RoomVisibilityState.kt | 21 +++ .../ConfigureRoomPresenterTest.kt | 8 +- 15 files changed, 447 insertions(+), 110 deletions(-) create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt rename features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/{RoomPrivacyOption.kt => RoomVisibilityOption.kt} (68%) rename features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/{RoomPrivacy.kt => RoomAccess.kt} (67%) create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt delete mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomPrivacyItem.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityItem.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt index 731dc27d07..a83673886d 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt @@ -8,7 +8,7 @@ package io.element.android.features.createroom.impl 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 kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -18,5 +18,5 @@ data class CreateRoomConfig( val topic: String? = null, val avatarUri: Uri? = null, val invites: ImmutableList = persistentListOf(), - val privacy: RoomPrivacy = RoomPrivacy.Private, + val roomVisibility: RoomVisibilityState = RoomVisibilityState.Private, ) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt index 5925ca7818..17d7d5cc3d 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt @@ -8,7 +8,11 @@ package io.element.android.features.createroom.impl 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.userlist.UserListDataStore 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.MutableStateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.getAndUpdate import java.io.File +import java.text.Normalizer import javax.inject.Inject @SingleIn(CreateRoomScope::class) @@ -31,28 +37,87 @@ class CreateRoomDataStore @Inject constructor( field = value } - fun getCreateRoomConfig(): Flow = combine( + val createRoomConfig: Flow = combine( selectedUserListDataStore.selectedUsers(), createRoomConfigFlow, ) { selectedUsers, config -> config.copy(invites = selectedUsers.toImmutableList()) } - fun setRoomName(roomName: String?) { - createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(roomName = roomName?.takeIf { it.isNotEmpty() })) + fun setRoomName(roomName: String) { + 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?) { - createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(topic = topic?.takeIf { it.isNotEmpty() })) + fun setTopic(topic: String) { + createRoomConfigFlow.getAndUpdate { config -> + config.copy(topic = topic.takeIf { it.isNotEmpty() }) + } } fun setAvatarUri(uri: Uri?, cached: Boolean = false) { cachedAvatarUri = uri.takeIf { cached } - createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(avatarUri = uri)) + createRoomConfigFlow.getAndUpdate { config -> + config.copy(avatarUri = uri) + } + } + + fun setRoomVisibility(visibility: RoomVisibilityItem) { + 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 setPrivacy(privacy: RoomPrivacy) { - createRoomConfigFlow.tryEmit(createRoomConfigFlow.value.copy(privacy = privacy)) + 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() { diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt new file mode 100644 index 0000000000..4d39f698be --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt @@ -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, + ) + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomPrivacyOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt similarity index 68% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomPrivacyOption.kt rename to features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt index 302f6134e6..cf6ab077a4 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomPrivacyOption.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt @@ -7,6 +7,8 @@ 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.Row 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.size import androidx.compose.foundation.selection.selectable +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment 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.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.features.createroom.impl.configureroom.RoomPrivacyItem -import io.element.android.features.createroom.impl.configureroom.roomPrivacyItems +import io.element.android.features.createroom.impl.configureroom.RoomVisibilityItem import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight 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 @Composable -fun RoomPrivacyOption( - roomPrivacyItem: RoomPrivacyItem, - onOptionClick: (RoomPrivacyItem) -> Unit, +fun RoomVisibilityOption( + roomPrivacyItem: RoomVisibilityItem, + onOptionClick: (RoomVisibilityItem) -> Unit, modifier: Modifier = Modifier, isSelected: Boolean = false, ) { @@ -44,28 +48,31 @@ fun RoomPrivacyOption( onClick = { onOptionClick(roomPrivacyItem) }, role = Role.RadioButton, ) - .padding(8.dp), ) { - Icon( - modifier = Modifier.padding(horizontal = 8.dp), - resourceId = roomPrivacyItem.icon, - contentDescription = null, - tint = MaterialTheme.colorScheme.secondary, - ) - - Column( - Modifier - .weight(1f) - .padding(horizontal = 8.dp) + Box( + modifier = modifier + .size(30.dp) + .clip(RoundedCornerShape(8.dp)) + .background(ElementTheme.colors.bgSubtleSecondary) + .padding(3.dp), + contentAlignment = Alignment.Center, ) { + 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 = roomPrivacyItem.title, + text = stringResource(roomPrivacyItem.title), style = ElementTheme.typography.fontBodyLgRegular, color = MaterialTheme.colorScheme.primary, ) Spacer(Modifier.size(3.dp)) Text( - text = roomPrivacyItem.description, + text = stringResource(roomPrivacyItem.description), style = ElementTheme.typography.fontBodySmRegular, color = MaterialTheme.colorScheme.tertiary, ) @@ -85,14 +92,14 @@ fun RoomPrivacyOption( @PreviewsDayNight @Composable internal fun RoomPrivacyOptionPreview() = ElementPreview { - val aRoomPrivacyItem = roomPrivacyItems().first() + val aRoomPrivacyItem = RoomVisibilityItem.Private Column { - RoomPrivacyOption( + RoomVisibilityOption( roomPrivacyItem = aRoomPrivacyItem, onOptionClick = {}, isSelected = true, ) - RoomPrivacyOption( + RoomVisibilityOption( roomPrivacyItem = aRoomPrivacyItem, onOptionClick = {}, isSelected = false, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt index d6f647fe61..048cd1cfe0 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt @@ -14,8 +14,10 @@ import io.element.android.libraries.matrix.ui.media.AvatarAction sealed interface ConfigureRoomEvents { data class RoomNameChanged(val name: String) : ConfigureRoomEvents data class TopicChanged(val topic: String) : ConfigureRoomEvents - data class RoomPrivacyChanged(val privacy: RoomPrivacy) : ConfigureRoomEvents - data class RemoveFromSelection(val matrixUser: MatrixUser) : ConfigureRoomEvents + data class RoomVisibilityChanged(val visibilityItem: RoomVisibilityItem) : 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 HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents data object CancelCreateRoom : ConfigureRoomEvents diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index 09553d6160..a07bb57c84 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -54,7 +54,7 @@ class ConfigureRoomPresenter @Inject constructor( @Composable override fun present(): ConfigureRoomState { val cameraPermissionState = cameraPermissionPresenter.present() - val createRoomConfig = dataStore.getCreateRoomConfig().collectAsState(CreateRoomConfig()) + val createRoomConfig = dataStore.createRoomConfig.collectAsState(CreateRoomConfig()) val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) }, @@ -92,8 +92,10 @@ class ConfigureRoomPresenter @Inject constructor( when (event) { is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name) is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic) - is ConfigureRoomEvents.RoomPrivacyChanged -> dataStore.setPrivacy(event.privacy) - is ConfigureRoomEvents.RemoveFromSelection -> dataStore.selectedUserListDataStore.removeUserFromSelection(event.matrixUser) + is ConfigureRoomEvents.RoomVisibilityChanged -> dataStore.setRoomVisibility(event.visibilityItem) + 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.HandleAvatarAction -> { when (event.action) { @@ -109,6 +111,7 @@ class ConfigureRoomPresenter @Inject constructor( } ConfigureRoomEvents.CancelCreateRoom -> createRoomAction.value = AsyncAction.Uninitialized + } } @@ -130,10 +133,10 @@ class ConfigureRoomPresenter @Inject constructor( val params = CreateRoomParameters( name = config.roomName, topic = config.topic, - isEncrypted = config.privacy == RoomPrivacy.Private, + isEncrypted = config.roomVisibility is RoomVisibilityState.Private, isDirect = false, - visibility = if (config.privacy == RoomPrivacy.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE, - preset = if (config.privacy == RoomPrivacy.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT, + visibility = if (config.roomVisibility is RoomVisibilityState.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE, + preset = if (config.roomVisibility is RoomVisibilityState.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT, invite = config.invites.map { it.userId }, avatar = avatarUrl, ) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt index ba49ffcbdd..e89ec0e927 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt @@ -24,7 +24,10 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider RoomVisibilityItem.Private + is RoomVisibilityState.Public -> RoomVisibilityItem.Public + }, onOptionClick = { 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 -private fun RoomPrivacyOptions( - selected: RoomPrivacy?, - onOptionClick: (RoomPrivacyItem) -> Unit, +private fun ConfigureRoomOptions( + title: String, + verticalArrangement: Arrangement.Vertical, modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit, ) { - val items = roomPrivacyItems() - Column(modifier = modifier.selectableGroup()) { - items.forEach { item -> - RoomPrivacyOption( + 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, +) { + ConfigureRoomOptions( + title = "Room visibility", + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + RoomVisibilityItem.entries.forEach { item -> + RoomVisibilityOption( roomPrivacyItem = item, - isSelected = selected == item.privacy, + isSelected = item == selected, + 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 +@PreviewWithLargeHeight @Composable internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview { ConfigureRoomView( diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomPrivacy.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt similarity index 67% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomPrivacy.kt rename to features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt index d376b84681..3a86280f11 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomPrivacy.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2024 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only * Please see LICENSE in the repository root for full details. @@ -7,7 +7,6 @@ package io.element.android.features.createroom.impl.configureroom -enum class RoomPrivacy { - Private, - Public, +enum class RoomAccess { + Anyone, Knocking, Invite } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt new file mode 100644 index 0000000000..6c21935196 --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt @@ -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, + ) +} + diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt new file mode 100644 index 0000000000..a26888e08d --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt @@ -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 +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomPrivacyItem.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomPrivacyItem.kt deleted file mode 100644 index a0b7e4cc05..0000000000 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomPrivacyItem.kt +++ /dev/null @@ -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 { - 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() -} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityItem.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityItem.kt new file mode 100644 index 0000000000..12909cdd5e --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityItem.kt @@ -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, + ) +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt new file mode 100644 index 0000000000..0a50a98a3f --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt @@ -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 +} diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTest.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTest.kt index 9294f95b78..3c09e34ce0 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTest.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTest.kt @@ -103,7 +103,7 @@ class ConfigureRoomPresenterTest { assertThat(initialState.config.topic).isNull() assertThat(initialState.config.invites).isEmpty() 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) // Room privacy - newState.eventSink(ConfigureRoomEvents.RoomPrivacyChanged(RoomPrivacy.Public)) + newState.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(RoomVisibilityState.Public)) newState = awaitItem() - expectedConfig = expectedConfig.copy(privacy = RoomPrivacy.Public) + expectedConfig = expectedConfig.copy(roomVisibility = RoomVisibilityState.Public) assertThat(newState.config).isEqualTo(expectedConfig) // Remove user - newState.eventSink(ConfigureRoomEvents.RemoveFromSelection(selectedUser1)) + newState.eventSink(ConfigureRoomEvents.RemoveUserFromSelection(selectedUser1)) newState = awaitItem() expectedConfig = expectedConfig.copy(invites = expectedConfig.invites.minus(selectedUser1).toImmutableList()) assertThat(newState.config).isEqualTo(expectedConfig) From dc9e883e934bc43ca51faf44d941fc34035475fb Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 25 Oct 2024 18:36:08 +0200 Subject: [PATCH 02/22] create room : remove RoomAccess.Invite as we are not displaying it. --- .../impl/configureroom/ConfigureRoomView.kt | 20 ++++++++----------- .../impl/configureroom/RoomAccess.kt | 2 +- .../impl/configureroom/RoomAccessItem.kt | 2 +- .../impl/configureroom/RoomVisibilityState.kt | 8 ++------ 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index 636230ec71..d2bf16fdc4 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -14,15 +14,12 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer 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.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.selection.selectableGroup -import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api @@ -35,7 +32,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource 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.unit.dp import io.element.android.compound.theme.ElementTheme @@ -133,7 +129,10 @@ fun ConfigureRoomView( ) if (state.config.roomVisibility is RoomVisibilityState.Public) { RoomAccessOptions( - selected = state.config.roomVisibility.roomAccess, + selected = when (state.config.roomVisibility.roomAccess) { + RoomAccess.Anyone -> RoomAccessItem.Anyone + RoomAccess.Knocking -> RoomAccessItem.AskToJoin + }, onOptionClick = { focusManager.clearFocus() state.eventSink(ConfigureRoomEvents.RoomAccessChanged(it)) @@ -290,7 +289,7 @@ private fun RoomVisibilityOptions( @Composable private fun RoomAccessOptions( - selected: RoomAccess, + selected: RoomAccessItem, onOptionClick: (RoomAccessItem) -> Unit, modifier: Modifier = Modifier, ) { @@ -302,10 +301,7 @@ private fun RoomAccessOptions( RoomAccessItem.entries.forEach { item -> RoomAccessOption( roomAccessItem = item, - isSelected = when (item) { - RoomAccessItem.Anyone -> selected == RoomAccess.Anyone - RoomAccessItem.AskToJoin -> selected == RoomAccess.Knocking - }, + isSelected = item == selected, onOptionClick = onOptionClick, ) } @@ -317,7 +313,7 @@ private fun RoomAddress( address: RoomAddress, onAddressChange: (String) -> Unit, modifier: Modifier = Modifier, -){ +) { Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp), @@ -331,7 +327,7 @@ private fun RoomAddress( TextField( modifier = Modifier.fillMaxWidth(), - value = when(address) { + value = when (address) { is RoomAddress.AutoFilled -> address.address is RoomAddress.Edited -> address.address }, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt index 3a86280f11..aeaf63b2c5 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt @@ -8,5 +8,5 @@ package io.element.android.features.createroom.impl.configureroom enum class RoomAccess { - Anyone, Knocking, Invite + Anyone, Knocking } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt index 6c21935196..c8791e1138 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt @@ -21,6 +21,6 @@ enum class RoomAccessItem( AskToJoin( title = CommonStrings.screen_create_room_access_section_knocking_option_title, description = CommonStrings.screen_create_room_access_section_knocking_option_description, - ) + ), } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt index 0a50a98a3f..ad61fadb3a 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt @@ -8,14 +8,10 @@ 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 object Private : RoomVisibilityState data class Public( val roomAddress: RoomAddress, - override val roomAccess: RoomAccess + val roomAccess: RoomAccess ) : RoomVisibilityState } From 9e2b01e4cea0c28d850ce9cc449c12322dd32a13 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 29 Oct 2024 16:54:09 +0100 Subject: [PATCH 03/22] create room : use user homeserver in the address field. --- .../createroom/impl/configureroom/ConfigureRoomPresenter.kt | 2 ++ .../createroom/impl/configureroom/ConfigureRoomState.kt | 1 + .../impl/configureroom/ConfigureRoomStateProvider.kt | 1 + .../createroom/impl/configureroom/ConfigureRoomView.kt | 4 +++- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index a07bb57c84..ec3e31f1e0 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -55,6 +55,7 @@ class ConfigureRoomPresenter @Inject constructor( override fun present(): ConfigureRoomState { val cameraPermissionState = cameraPermissionPresenter.present() val createRoomConfig = dataStore.createRoomConfig.collectAsState(CreateRoomConfig()) + val homeserverName = remember { matrixClient.userIdServerName() } val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) }, @@ -120,6 +121,7 @@ class ConfigureRoomPresenter @Inject constructor( avatarActions = avatarActions, createRoomAction = createRoomAction.value, cameraPermissionState = cameraPermissionState, + homeserverName = homeserverName, eventSink = ::handleEvents, ) } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt index 70a0a9b76d..b59ae887e5 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt @@ -19,6 +19,7 @@ data class ConfigureRoomState( val avatarActions: ImmutableList, val createRoomAction: AsyncAction, val cameraPermissionState: PermissionsState, + val homeserverName: String, val eventSink: (ConfigureRoomEvents) -> Unit ) { val isCreateButtonEnabled: Boolean = config.roomName.isNullOrEmpty().not() diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt index e89ec0e927..af32ac8b13 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt @@ -38,5 +38,6 @@ fun aConfigureRoomState() = ConfigureRoomState( avatarActions = persistentListOf(), createRoomAction = AsyncAction.Uninitialized, cameraPermissionState = aPermissionsState(showDialog = false), + homeserverName = "matrix.org", eventSink = { }, ) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index d2bf16fdc4..74521197b5 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -141,6 +141,7 @@ fun ConfigureRoomView( RoomAddress( modifier = Modifier.padding(horizontal = 16.dp), address = state.config.roomVisibility.roomAddress, + homeserverName = state.homeserverName, onAddressChange = { state.eventSink(ConfigureRoomEvents.RoomAddressChanged(it)) }, ) } @@ -311,6 +312,7 @@ private fun RoomAccessOptions( @Composable private fun RoomAddress( address: RoomAddress, + homeserverName: String, onAddressChange: (String) -> Unit, modifier: Modifier = Modifier, ) { @@ -340,7 +342,7 @@ private fun RoomAddress( }, trailingIcon = { Text( - text = ":myserver.com", + text = homeserverName, style = ElementTheme.typography.fontBodyLgMedium, color = ElementTheme.colors.textSecondary, modifier = Modifier.padding(end = 16.dp) From f0c1dfa768d6319de251abcceeb8c87f25bb46b0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 29 Oct 2024 18:10:55 +0100 Subject: [PATCH 04/22] create room : branch the join rule override --- .../configureroom/ConfigureRoomPresenter.kt | 3 +++ .../impl/configureroom/RoomAccess.kt | 9 ++++++++ .../api/createroom/CreateRoomParameters.kt | 1 + .../matrix/api/createroom/JoinRuleOverride.kt | 16 ++++++++++++++ .../libraries/matrix/impl/RustMatrixClient.kt | 21 +++++++++++++++---- 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/JoinRuleOverride.kt diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index ec3e31f1e0..13a4952308 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters +import io.element.android.libraries.matrix.api.createroom.JoinRuleOverride import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.createroom.RoomVisibility import io.element.android.libraries.matrix.ui.media.AvatarAction @@ -38,6 +39,7 @@ import io.element.android.services.analytics.api.AnalyticsService import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import java.util.Optional import javax.inject.Inject class ConfigureRoomPresenter @Inject constructor( @@ -138,6 +140,7 @@ class ConfigureRoomPresenter @Inject constructor( isEncrypted = config.roomVisibility is RoomVisibilityState.Private, isDirect = false, visibility = if (config.roomVisibility is RoomVisibilityState.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE, + joinRuleOverride = if (config.roomVisibility is RoomVisibilityState.Public) config.roomVisibility.roomAccess.toJoinRule() else JoinRuleOverride.None, preset = if (config.roomVisibility is RoomVisibilityState.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT, invite = config.invites.map { it.userId }, avatar = avatarUrl, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt index aeaf63b2c5..b966d98db6 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccess.kt @@ -7,6 +7,15 @@ package io.element.android.features.createroom.impl.configureroom +import io.element.android.libraries.matrix.api.createroom.JoinRuleOverride + enum class RoomAccess { Anyone, Knocking } + +fun RoomAccess.toJoinRule(): JoinRuleOverride { + return when (this) { + RoomAccess.Anyone -> JoinRuleOverride.None + RoomAccess.Knocking -> JoinRuleOverride.Knock + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt index 940fef7326..4c74153a31 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt @@ -18,4 +18,5 @@ data class CreateRoomParameters( val preset: RoomPreset, val invite: List? = null, val avatar: String? = null, + val joinRuleOverride: JoinRuleOverride = JoinRuleOverride.None, ) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/JoinRuleOverride.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/JoinRuleOverride.kt new file mode 100644 index 0000000000..f59f393c3e --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/JoinRuleOverride.kt @@ -0,0 +1,16 @@ +/* + * 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.libraries.matrix.api.createroom + +/** + * Rules to override the default room join rules. + */ +sealed interface JoinRuleOverride { + data object Knock : JoinRuleOverride + data object None : JoinRuleOverride +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 101d049659..c73b3c50a6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters +import io.element.android.libraries.matrix.api.createroom.JoinRuleOverride import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.createroom.RoomVisibility import io.element.android.libraries.matrix.api.encryption.EncryptionService @@ -108,6 +109,7 @@ import kotlin.jvm.optionals.getOrNull import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds import org.matrix.rustcomponents.sdk.CreateRoomParameters as RustCreateRoomParameters +import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService @@ -304,14 +306,25 @@ class RustMatrixClient( RoomVisibility.PUBLIC -> RustRoomVisibility.PUBLIC RoomVisibility.PRIVATE -> RustRoomVisibility.PRIVATE }, - preset = when (createRoomParams.preset) { - RoomPreset.PRIVATE_CHAT -> RustRoomPreset.PRIVATE_CHAT - RoomPreset.PUBLIC_CHAT -> RustRoomPreset.PUBLIC_CHAT - RoomPreset.TRUSTED_PRIVATE_CHAT -> RustRoomPreset.TRUSTED_PRIVATE_CHAT + preset = when (createRoomParams.visibility) { + RoomVisibility.PRIVATE -> { + if (createRoomParams.isDirect) { + RustRoomPreset.TRUSTED_PRIVATE_CHAT + } else { + RustRoomPreset.PRIVATE_CHAT + } + } + RoomVisibility.PUBLIC -> { + RustRoomPreset.PUBLIC_CHAT + } }, invite = createRoomParams.invite?.map { it.value }, avatar = createRoomParams.avatar, powerLevelContentOverride = defaultRoomCreationPowerLevels, + joinRuleOverride = when (createRoomParams.joinRuleOverride) { + JoinRuleOverride.Knock -> RustJoinRule.Knock + JoinRuleOverride.None -> null + } ) val roomId = RoomId(client.createRoom(rustParams)) // Wait to receive the room back from the sync but do not returns failure if it fails. From a4be2106d06447ef786ef7fec9c4b041b089a883 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 30 Oct 2024 18:20:57 +0100 Subject: [PATCH 05/22] create room : start integrating the address field --- .../createroom/impl/CreateRoomConfig.kt | 4 +++- .../createroom/impl/CreateRoomDataStore.kt | 3 ++- .../configureroom/ConfigureRoomPresenter.kt | 16 ++++++++++------ .../impl/configureroom/ConfigureRoomState.kt | 4 +--- .../ConfigureRoomStateProvider.kt | 3 ++- .../impl/configureroom/ConfigureRoomView.kt | 13 +++++-------- .../impl/configureroom/RoomAddress.kt | 6 +++--- .../configureroom/RoomAddressErrorState.kt | 17 +++++++++++++++++ .../impl/configureroom/RoomVisibilityState.kt | 19 ++++++++++++++++++- .../api/createroom/CreateRoomParameters.kt | 2 ++ .../libraries/matrix/impl/RustMatrixClient.kt | 3 ++- 11 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddressErrorState.kt diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt index a83673886d..ab6e116598 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt @@ -19,4 +19,6 @@ data class CreateRoomConfig( val avatarUri: Uri? = null, val invites: ImmutableList = persistentListOf(), val roomVisibility: RoomVisibilityState = RoomVisibilityState.Private, -) +) { + val isValid = roomName.isNullOrEmpty().not() && roomVisibility.isValid() +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt index 17d7d5cc3d..1c08068d67 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt @@ -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.RoomAccessItem 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.RoomVisibilityState 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.getAndUpdate import java.io.File -import java.text.Normalizer import javax.inject.Inject @SingleIn(CreateRoomScope::class) @@ -86,6 +86,7 @@ class CreateRoomDataStore @Inject constructor( RoomVisibilityItem.Private -> RoomVisibilityState.Private RoomVisibilityItem.Public -> RoomVisibilityState.Public( roomAddress = RoomAddress.AutoFilled(config.roomName.orEmpty()), + roomAddressErrorState = RoomAddressErrorState.None, roomAccess = RoomAccess.Anyone, ) } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index 13a4952308..7addc8aca9 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -22,7 +22,7 @@ import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.features.createroom.impl.CreateRoomDataStore import io.element.android.libraries.architecture.AsyncAction 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.matrix.api.MatrixClient 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.coroutines.CoroutineScope import kotlinx.coroutines.launch -import java.util.Optional +import timber.log.Timber import javax.inject.Inject class ConfigureRoomPresenter @Inject constructor( @@ -132,7 +132,7 @@ class ConfigureRoomPresenter @Inject constructor( config: CreateRoomConfig, createRoomAction: MutableState> ) = launch { - suspend { + runUpdatingState(createRoomAction) { val avatarUrl = config.avatarUri?.let { uploadAvatar(it) } val params = CreateRoomParameters( 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, invite = config.invites.map { it.userId }, avatar = avatarUrl, + canonicalAlias = config.roomVisibility.roomAddress() ) - matrixClient.createRoom(params).getOrThrow() - .also { + matrixClient.createRoom(params) + .onFailure { failure -> + Timber.e(failure, "Failed to create room") + } + .onSuccess { dataStore.clearCachedData() analyticsService.capture(CreatedRoom(isDM = false)) } - }.runCatchingUpdatingState(createRoomAction) + } } private suspend fun uploadAvatar(avatarUri: Uri): String { diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt index b59ae887e5..2bbcd521ac 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt @@ -21,6 +21,4 @@ data class ConfigureRoomState( val cameraPermissionState: PermissionsState, val homeserverName: String, val eventSink: (ConfigureRoomEvents) -> Unit -) { - val isCreateButtonEnabled: Boolean = config.roomName.isNullOrEmpty().not() -} +) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt index af32ac8b13..42ace6c73a 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt @@ -26,7 +26,8 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider Unit, @@ -326,13 +326,10 @@ private fun RoomAddress( color = MaterialTheme.colorScheme.primary, text = "Room address", ) - + TextField( modifier = Modifier.fillMaxWidth(), - value = when (address) { - is RoomAddress.AutoFilled -> address.address - is RoomAddress.Edited -> address.address - }, + value = address.value, leadingIcon = { Text( text = "#", diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt index a26888e08d..5c10cfb7b5 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddress.kt @@ -7,7 +7,7 @@ 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 +sealed class RoomAddress(open val value: String) { + data class AutoFilled(override val value: String) : RoomAddress(value) + data class Edited(override val value: String) : RoomAddress(value) } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddressErrorState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddressErrorState.kt new file mode 100644 index 0000000000..f2cadfd6bb --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAddressErrorState.kt @@ -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 +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt index ad61fadb3a..cc5af7836e 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomVisibilityState.kt @@ -7,11 +7,28 @@ package io.element.android.features.createroom.impl.configureroom +import java.util.Optional + sealed interface RoomVisibilityState { data object Private : RoomVisibilityState data class Public( val roomAddress: RoomAddress, - val roomAccess: RoomAccess + val roomAddressErrorState: RoomAddressErrorState, + val roomAccess: RoomAccess, ) : RoomVisibilityState + + fun roomAddress(): Optional { + 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() + } + } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt index 4c74153a31..2e13623c96 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/createroom/CreateRoomParameters.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.api.createroom import io.element.android.libraries.matrix.api.core.UserId +import java.util.Optional data class CreateRoomParameters( val name: String?, @@ -19,4 +20,5 @@ data class CreateRoomParameters( val invite: List? = null, val avatar: String? = null, val joinRuleOverride: JoinRuleOverride = JoinRuleOverride.None, + val canonicalAlias: Optional = Optional.empty(), ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index c73b3c50a6..3417c9b377 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -324,7 +324,8 @@ class RustMatrixClient( joinRuleOverride = when (createRoomParams.joinRuleOverride) { JoinRuleOverride.Knock -> RustJoinRule.Knock JoinRuleOverride.None -> null - } + }, + canonicalAlias = createRoomParams.canonicalAlias.getOrNull(), ) val roomId = RoomId(client.createRoom(rustParams)) // Wait to receive the room back from the sync but do not returns failure if it fails. From 68bdc313210bbed55c0b43cb4aca4e6b881011ce Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 31 Oct 2024 17:11:58 +0100 Subject: [PATCH 06/22] create room : add Knock feature flag --- features/createroom/impl/build.gradle.kts | 2 + .../configureroom/ConfigureRoomPresenter.kt | 5 +++ .../impl/configureroom/ConfigureRoomState.kt | 1 + .../ConfigureRoomStateProvider.kt | 41 +++++++++++++++---- .../impl/configureroom/ConfigureRoomView.kt | 2 +- .../libraries/featureflag/api/FeatureFlags.kt | 9 +++- 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts index bcd3799c92..6ddae68a72 100644 --- a/features/createroom/impl/build.gradle.kts +++ b/features/createroom/impl/build.gradle.kts @@ -40,6 +40,7 @@ dependencies { implementation(projects.libraries.usersearch.impl) implementation(projects.services.analytics.api) implementation(libs.coil.compose) + implementation(projects.libraries.featureflag.api) api(projects.features.createroom.api) testImplementation(libs.test.junit) @@ -56,6 +57,7 @@ dependencies { testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.usersearch.test) testImplementation(projects.features.createroom.test) + testImplementation(projects.libraries.featureflag.test) testImplementation(projects.tests.testutils) testImplementation(libs.androidx.compose.ui.test.junit) testReleaseImplementation(libs.androidx.compose.ui.test.manifest) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index 7addc8aca9..41a9dc8f97 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -24,6 +24,8 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.core.mimetype.MimeTypes +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters @@ -49,6 +51,7 @@ class ConfigureRoomPresenter @Inject constructor( private val mediaPreProcessor: MediaPreProcessor, private val analyticsService: AnalyticsService, permissionsPresenterFactory: PermissionsPresenter.Factory, + private val featureFlagService: FeatureFlagService, ) : Presenter { private val cameraPermissionPresenter: PermissionsPresenter = permissionsPresenterFactory.create(android.Manifest.permission.CAMERA) private var pendingPermissionRequest = false @@ -58,6 +61,7 @@ class ConfigureRoomPresenter @Inject constructor( val cameraPermissionState = cameraPermissionPresenter.present() val createRoomConfig = dataStore.createRoomConfig.collectAsState(CreateRoomConfig()) val homeserverName = remember { matrixClient.userIdServerName() } + val isKnockFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock).collectAsState(initial = false) val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) }, @@ -119,6 +123,7 @@ class ConfigureRoomPresenter @Inject constructor( } return ConfigureRoomState( + isKnockFeatureEnabled = isKnockFeatureEnabled, config = createRoomConfig.value, avatarActions = avatarActions, createRoomAction = createRoomAction.value, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt index 2bbcd521ac..8a2122c306 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt @@ -15,6 +15,7 @@ import io.element.android.libraries.permissions.api.PermissionsState import kotlinx.collections.immutable.ImmutableList data class ConfigureRoomState( + val isKnockFeatureEnabled: Boolean, val config: CreateRoomConfig, val avatarActions: ImmutableList, val createRoomAction: AsyncAction, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt index 42ace6c73a..5b1427cd47 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt @@ -10,7 +10,10 @@ package io.element.android.features.createroom.impl.configureroom import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.libraries.matrix.ui.media.AvatarAction +import io.element.android.libraries.permissions.api.PermissionsState import io.element.android.libraries.permissions.api.aPermissionsState import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -19,7 +22,20 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider get() = sequenceOf( aConfigureRoomState(), - aConfigureRoomState().copy( + aConfigureRoomState( + config = CreateRoomConfig( + 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", + invites = aMatrixUserList().toImmutableList(), + roomVisibility = RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled("Room 101"), + roomAccess = RoomAccess.Knocking, + roomAddressErrorState = RoomAddressErrorState.None, + ), + ), + ), + aConfigureRoomState( + isKnockFeatureEnabled = false, config = CreateRoomConfig( 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", @@ -34,11 +50,20 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider = emptyList(), + createRoomAction: AsyncAction = AsyncAction.Uninitialized, + cameraPermissionState: PermissionsState = aPermissionsState(showDialog = false), + homeserverName: String = "matrix.org", + eventSink: (ConfigureRoomEvents) -> Unit = { }, +) = ConfigureRoomState( + config = config, + isKnockFeatureEnabled = isKnockFeatureEnabled, + avatarActions = avatarActions.toImmutableList(), + createRoomAction = createRoomAction, + cameraPermissionState = cameraPermissionState, + homeserverName = homeserverName, + eventSink = eventSink, ) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index 13c1179fe0..cfce124019 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -127,7 +127,7 @@ fun ConfigureRoomView( state.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(it)) }, ) - if (state.config.roomVisibility is RoomVisibilityState.Public) { + if (state.config.roomVisibility is RoomVisibilityState.Public && state.isKnockFeatureEnabled) { RoomAccessOptions( selected = when (state.config.roomVisibility.roomAccess) { RoomAccess.Anyone -> RoomAccessItem.Anyone diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 1a8b8935b4..de7fe02b5d 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -124,5 +124,12 @@ enum class FeatureFlags( " You'll have to stop and re-open the app manually for that setting to take effect.", defaultValue = { false }, isFinished = false, - ) + ), + Knock( + key = "feature.knock", + title = "Ask to join", + description = "Allow creating rooms which users can request access to.", + defaultValue = { false }, + isFinished = false, + ), } From 1b1884c3e8be1d20eb418ef208fd78cab9f42f32 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 4 Nov 2024 15:35:33 +0100 Subject: [PATCH 07/22] create room : fix tests and remove auto-fill alias for now. --- .../createroom/impl/CreateRoomDataStore.kt | 3 +- .../impl/components/RoomAccessOption.kt | 19 +- .../impl/components/RoomVisibilityOption.kt | 4 +- .../impl/configureroom/ConfigureRoomEvents.kt | 3 +- .../configureroom/ConfigureRoomPresenter.kt | 50 +++-- .../ConfigureRoomStateProvider.kt | 3 +- .../impl/configureroom/ConfigureRoomView.kt | 8 +- .../impl/configureroom/RoomAccess.kt | 3 +- .../impl/configureroom/RoomAccessItem.kt | 1 - .../ConfigureRoomPresenterTest.kt | 198 +++++++++++------- 10 files changed, 169 insertions(+), 123 deletions(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt index 1c08068d67..36feb0aec3 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt @@ -46,6 +46,7 @@ class CreateRoomDataStore @Inject constructor( fun setRoomName(roomName: String) { createRoomConfigFlow.getAndUpdate { config -> + /* val newVisibility = when (config.roomVisibility) { is RoomVisibilityState.Public -> { val roomAddress = config.roomVisibility.roomAddress @@ -59,9 +60,9 @@ class CreateRoomDataStore @Inject constructor( } else -> config.roomVisibility } + */ config.copy( roomName = roomName.takeIf { it.isNotEmpty() }, - roomVisibility = newVisibility, ) } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt index 4d39f698be..6cde477f2e 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt @@ -11,7 +11,6 @@ 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 @@ -36,13 +35,13 @@ fun RoomAccessOption( isSelected: Boolean = false, ) { Row( - modifier - .fillMaxWidth() - .selectable( - selected = isSelected, - onClick = { onOptionClick(roomAccessItem) }, - role = Role.RadioButton, - ) + modifier + .fillMaxWidth() + .selectable( + selected = isSelected, + onClick = { onOptionClick(roomAccessItem) }, + role = Role.RadioButton, + ) ) { Column(Modifier.weight(1f)) { Text( @@ -59,8 +58,8 @@ fun RoomAccessOption( } RadioButton( modifier = Modifier - .align(Alignment.CenterVertically) - .size(48.dp), + .align(Alignment.CenterVertically) + .size(48.dp), selected = isSelected, // null recommended for accessibility with screenreaders onClick = null diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt index cf6ab077a4..15ae5c11a1 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt @@ -50,7 +50,7 @@ fun RoomVisibilityOption( ) ) { Box( - modifier = modifier + modifier = Modifier .size(30.dp) .clip(RoundedCornerShape(8.dp)) .background(ElementTheme.colors.bgSubtleSecondary) @@ -60,7 +60,7 @@ fun RoomVisibilityOption( Icon( resourceId = roomPrivacyItem.icon, contentDescription = null, - tint = if(isSelected) ElementTheme.colors.iconPrimary else ElementTheme.colors.iconSecondary, + tint = if (isSelected) ElementTheme.colors.iconPrimary else ElementTheme.colors.iconSecondary, ) } Spacer(Modifier.size(16.dp)) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt index 048cd1cfe0..26fee055ee 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt @@ -7,7 +7,6 @@ package io.element.android.features.createroom.impl.configureroom -import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.media.AvatarAction @@ -18,7 +17,7 @@ sealed interface 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 object CreateRoom : ConfigureRoomEvents data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents data object CancelCreateRoom : ConfigureRoomEvents } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index 41a9dc8f97..1b7623adfb 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -22,14 +22,13 @@ import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.features.createroom.impl.CreateRoomDataStore import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.architecture.runUpdatingState +import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters -import io.element.android.libraries.matrix.api.createroom.JoinRuleOverride import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.createroom.RoomVisibility import io.element.android.libraries.matrix.ui.media.AvatarAction @@ -61,7 +60,7 @@ class ConfigureRoomPresenter @Inject constructor( val cameraPermissionState = cameraPermissionPresenter.present() val createRoomConfig = dataStore.createRoomConfig.collectAsState(CreateRoomConfig()) val homeserverName = remember { matrixClient.userIdServerName() } - val isKnockFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock).collectAsState(initial = false) + val isKnockFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock).collectAsState(initial = false) val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) }, @@ -103,7 +102,7 @@ class ConfigureRoomPresenter @Inject constructor( 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(createRoomConfig.value) is ConfigureRoomEvents.HandleAvatarAction -> { when (event.action) { AvatarAction.ChoosePhoto -> galleryImagePicker.launch() @@ -118,7 +117,6 @@ class ConfigureRoomPresenter @Inject constructor( } ConfigureRoomEvents.CancelCreateRoom -> createRoomAction.value = AsyncAction.Uninitialized - } } @@ -137,20 +135,33 @@ class ConfigureRoomPresenter @Inject constructor( config: CreateRoomConfig, createRoomAction: MutableState> ) = launch { - runUpdatingState(createRoomAction) { + suspend { val avatarUrl = config.avatarUri?.let { uploadAvatar(it) } - val params = CreateRoomParameters( - name = config.roomName, - topic = config.topic, - isEncrypted = config.roomVisibility is RoomVisibilityState.Private, - isDirect = false, - visibility = if (config.roomVisibility is RoomVisibilityState.Public) RoomVisibility.PUBLIC else RoomVisibility.PRIVATE, - joinRuleOverride = if (config.roomVisibility is RoomVisibilityState.Public) config.roomVisibility.roomAccess.toJoinRule() else JoinRuleOverride.None, - preset = if (config.roomVisibility is RoomVisibilityState.Public) RoomPreset.PUBLIC_CHAT else RoomPreset.PRIVATE_CHAT, - invite = config.invites.map { it.userId }, - avatar = avatarUrl, - canonicalAlias = config.roomVisibility.roomAddress() - ) + val params = if (config.roomVisibility is RoomVisibilityState.Public) { + CreateRoomParameters( + name = config.roomName, + topic = config.topic, + isEncrypted = false, + isDirect = false, + visibility = RoomVisibility.PUBLIC, + joinRuleOverride = config.roomVisibility.roomAccess.toJoinRule(), + preset = RoomPreset.PUBLIC_CHAT, + invite = config.invites.map { it.userId }, + avatar = avatarUrl, + canonicalAlias = config.roomVisibility.roomAddress() + ) + } else { + CreateRoomParameters( + name = config.roomName, + topic = config.topic, + isEncrypted = config.roomVisibility is RoomVisibilityState.Private, + isDirect = false, + visibility = RoomVisibility.PRIVATE, + preset = RoomPreset.PRIVATE_CHAT, + invite = config.invites.map { it.userId }, + avatar = avatarUrl, + ) + } matrixClient.createRoom(params) .onFailure { failure -> Timber.e(failure, "Failed to create room") @@ -159,7 +170,8 @@ class ConfigureRoomPresenter @Inject constructor( dataStore.clearCachedData() analyticsService.capture(CreatedRoom(isDM = false)) } - } + .getOrThrow() + }.runCatchingUpdatingState(createRoomAction) } private suspend fun uploadAvatar(avatarUri: Uri): String { diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt index 5b1427cd47..80445fbff4 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt @@ -15,7 +15,6 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.permissions.api.PermissionsState import io.element.android.libraries.permissions.api.aPermissionsState -import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList open class ConfigureRoomStateProvider : PreviewParameterProvider { @@ -23,6 +22,7 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider().readBytes() } returns byteArrayOf() } @@ -94,50 +75,56 @@ class ConfigureRoomPresenterTest { @Test fun `present - initial state`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() + val presenter = createConfigureRoomPresenter() + presenter.test { + val initialState = initialState() assertThat(initialState.config).isEqualTo(CreateRoomConfig()) assertThat(initialState.config.roomName).isNull() assertThat(initialState.config.topic).isNull() assertThat(initialState.config.invites).isEmpty() assertThat(initialState.config.avatarUri).isNull() assertThat(initialState.config.roomVisibility).isEqualTo(RoomVisibilityState.Private) + assertThat(initialState.createRoomAction).isInstanceOf(AsyncAction.Uninitialized::class.java) + assertThat(initialState.homeserverName).isEqualTo("matrix.org") } } @Test fun `present - create room button is enabled only if the required fields are completed`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() + val presenter = createConfigureRoomPresenter() + presenter.test { + val initialState = initialState() var config = initialState.config - assertThat(initialState.isCreateButtonEnabled).isFalse() + assertThat(initialState.config.isValid).isFalse() // Room name not empty initialState.eventSink(ConfigureRoomEvents.RoomNameChanged(A_ROOM_NAME)) var newState: ConfigureRoomState = awaitItem() config = config.copy(roomName = A_ROOM_NAME) assertThat(newState.config).isEqualTo(config) - assertThat(newState.isCreateButtonEnabled).isTrue() + assertThat(newState.config.isValid).isTrue() // Clear room name newState.eventSink(ConfigureRoomEvents.RoomNameChanged("")) newState = awaitItem() config = config.copy(roomName = null) assertThat(newState.config).isEqualTo(config) - assertThat(newState.isCreateButtonEnabled).isFalse() + assertThat(newState.config.isValid).isFalse() } } @Test fun `present - state is updated when fields are changed`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() + val userListDataStore = UserListDataStore() + val pickerProvider = FakePickerProvider() + val permissionsPresenter = FakePermissionsPresenter() + val presenter = createConfigureRoomPresenter( + createRoomDataStore = CreateRoomDataStore(userListDataStore), + pickerProvider = pickerProvider, + permissionsPresenter = permissionsPresenter, + ) + presenter.test { + val initialState = initialState() var expectedConfig = CreateRoomConfig() assertThat(initialState.config).isEqualTo(expectedConfig) @@ -165,22 +152,22 @@ class ConfigureRoomPresenterTest { // Room avatar // Pick avatar - fakePickerProvider.givenResult(null) + pickerProvider.givenResult(null) // From gallery val uriFromGallery = Uri.parse(AN_URI_FROM_GALLERY) - fakePickerProvider.givenResult(uriFromGallery) + pickerProvider.givenResult(uriFromGallery) newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) newState = awaitItem() expectedConfig = expectedConfig.copy(avatarUri = uriFromGallery) assertThat(newState.config).isEqualTo(expectedConfig) // From camera val uriFromCamera = Uri.parse(AN_URI_FROM_CAMERA) - fakePickerProvider.givenResult(uriFromCamera) + pickerProvider.givenResult(uriFromCamera) assertThat(newState.cameraPermissionState.permissionGranted).isFalse() newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.TakePhoto)) newState = awaitItem() assertThat(newState.cameraPermissionState.showDialog).isTrue() - fakePermissionsPresenter.setPermissionGranted() + permissionsPresenter.setPermissionGranted() newState = awaitItem() assertThat(newState.cameraPermissionState.permissionGranted).isTrue() newState = awaitItem() @@ -188,7 +175,7 @@ class ConfigureRoomPresenterTest { assertThat(newState.config).isEqualTo(expectedConfig) // Do it again, no permission is requested val uriFromCamera2 = Uri.parse(AN_URI_FROM_CAMERA_2) - fakePickerProvider.givenResult(uriFromCamera2) + pickerProvider.givenResult(uriFromCamera2) newState.eventSink(ConfigureRoomEvents.HandleAvatarAction(AvatarAction.TakePhoto)) newState = awaitItem() expectedConfig = expectedConfig.copy(avatarUri = uriFromCamera2) @@ -200,9 +187,15 @@ class ConfigureRoomPresenterTest { assertThat(newState.config).isEqualTo(expectedConfig) // Room privacy - newState.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(RoomVisibilityState.Public)) + newState.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(RoomVisibilityItem.Public)) newState = awaitItem() - expectedConfig = expectedConfig.copy(roomVisibility = RoomVisibilityState.Public) + expectedConfig = expectedConfig.copy( + roomVisibility = RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled(expectedConfig.roomName ?: ""), + roomAddressErrorState = RoomAddressErrorState.None, + roomAccess = RoomAccess.Anyone, + ) + ) assertThat(newState.config).isEqualTo(expectedConfig) // Remove user @@ -215,15 +208,17 @@ class ConfigureRoomPresenterTest { @Test fun `present - trigger create room action`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() + val matrixClient = createMatrixClient() + val presenter = createConfigureRoomPresenter( + matrixClient = matrixClient + ) + presenter.test { + val initialState = initialState() val createRoomResult = Result.success(RoomId("!createRoomResult:domain")) - fakeMatrixClient.givenCreateRoomResult(createRoomResult) + matrixClient.givenCreateRoomResult(createRoomResult) - initialState.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + initialState.eventSink(ConfigureRoomEvents.CreateRoom) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Loading::class.java) val stateAfterCreateRoom = awaitItem() assertThat(stateAfterCreateRoom.createRoomAction).isInstanceOf(AsyncAction.Success::class.java) @@ -233,18 +228,22 @@ class ConfigureRoomPresenterTest { @Test fun `present - record analytics when creating room`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() + val matrixClient = createMatrixClient() + val analyticsService = FakeAnalyticsService() + val presenter = createConfigureRoomPresenter( + matrixClient = matrixClient, + analyticsService = analyticsService + ) + presenter.test { + val initialState = initialState() val createRoomResult = Result.success(RoomId("!createRoomResult:domain")) - fakeMatrixClient.givenCreateRoomResult(createRoomResult) + matrixClient.givenCreateRoomResult(createRoomResult) - initialState.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + initialState.eventSink(ConfigureRoomEvents.CreateRoom) skipItems(2) - val analyticsEvent = fakeAnalyticsService.capturedEvents.filterIsInstance().firstOrNull() + val analyticsEvent = analyticsService.capturedEvents.filterIsInstance().firstOrNull() assertThat(analyticsEvent).isNotNull() assertThat(analyticsEvent?.isDM).isFalse() } @@ -252,23 +251,31 @@ class ConfigureRoomPresenterTest { @Test fun `present - trigger create room with upload error and retry`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - skipItems(1) + val matrixClient = createMatrixClient() + val analyticsService = FakeAnalyticsService() + val mediaPreProcessor = FakeMediaPreProcessor() + val createRoomDataStore = CreateRoomDataStore(UserListDataStore()) + val presenter = createConfigureRoomPresenter( + createRoomDataStore = createRoomDataStore, + mediaPreProcessor = mediaPreProcessor, + matrixClient = matrixClient, + analyticsService = analyticsService + ) + presenter.test { + val initialState = initialState() createRoomDataStore.setAvatarUri(Uri.parse(AN_URI_FROM_GALLERY)) - fakeMediaPreProcessor.givenResult(Result.success(MediaUploadInfo.Image(mockk(), mockk(), mockk()))) - fakeMatrixClient.givenUploadMediaResult(Result.failure(A_THROWABLE)) + skipItems(1) + mediaPreProcessor.givenResult(Result.success(MediaUploadInfo.Image(mockk(), mockk(), mockk()))) + matrixClient.givenUploadMediaResult(Result.failure(A_THROWABLE)) - val initialState = awaitItem() - initialState.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + initialState.eventSink(ConfigureRoomEvents.CreateRoom) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Loading::class.java) val stateAfterCreateRoom = awaitItem() assertThat(stateAfterCreateRoom.createRoomAction).isInstanceOf(AsyncAction.Failure::class.java) - assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance()).isEmpty() + assertThat(analyticsService.capturedEvents.filterIsInstance()).isEmpty() - fakeMatrixClient.givenUploadMediaResult(Result.success(AN_AVATAR_URL)) - stateAfterCreateRoom.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + matrixClient.givenUploadMediaResult(Result.success(AN_AVATAR_URL)) + stateAfterCreateRoom.eventSink(ConfigureRoomEvents.CreateRoom) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Uninitialized::class.java) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Loading::class.java) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Success::class.java) @@ -277,23 +284,25 @@ class ConfigureRoomPresenterTest { @Test fun `present - trigger retry and cancel actions`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitItem() + val fakeMatrixClient = createMatrixClient() + val presenter = createConfigureRoomPresenter( + matrixClient = fakeMatrixClient + ) + presenter.test { + val initialState = initialState() val createRoomResult = Result.failure(A_THROWABLE) fakeMatrixClient.givenCreateRoomResult(createRoomResult) // Create - initialState.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + initialState.eventSink(ConfigureRoomEvents.CreateRoom) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Loading::class.java) val stateAfterCreateRoom = awaitItem() assertThat(stateAfterCreateRoom.createRoomAction).isInstanceOf(AsyncAction.Failure::class.java) assertThat((stateAfterCreateRoom.createRoomAction as? AsyncAction.Failure)?.error).isEqualTo(createRoomResult.exceptionOrNull()) // Retry - stateAfterCreateRoom.eventSink(ConfigureRoomEvents.CreateRoom(initialState.config)) + stateAfterCreateRoom.eventSink(ConfigureRoomEvents.CreateRoom) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Uninitialized::class.java) assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Loading::class.java) val stateAfterRetry = awaitItem() @@ -305,4 +314,33 @@ class ConfigureRoomPresenterTest { assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Uninitialized::class.java) } } + + private suspend fun TurbineTestContext.initialState(): ConfigureRoomState { + skipItems(1) + return awaitItem() + } + + private fun createMatrixClient() = FakeMatrixClient( + userIdServerNameLambda = { "matrix.org" }, + ) + + private fun createConfigureRoomPresenter( + createRoomDataStore: CreateRoomDataStore = CreateRoomDataStore(UserListDataStore()), + matrixClient: MatrixClient = createMatrixClient(), + pickerProvider: PickerProvider = FakePickerProvider(), + mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(), + analyticsService: AnalyticsService = FakeAnalyticsService(), + permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(), + isKnockFeatureEnabled: Boolean = true, + ) = ConfigureRoomPresenter( + dataStore = createRoomDataStore, + matrixClient = matrixClient, + mediaPickerProvider = pickerProvider, + mediaPreProcessor = mediaPreProcessor, + analyticsService = analyticsService, + permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionsPresenter), + featureFlagService = FakeFeatureFlagService( + mapOf(FeatureFlags.Knock.key to isKnockFeatureEnabled) + ) + ) } From 59168e4c054de02b10c9c4895cb25405b8c61049 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 4 Nov 2024 16:25:14 +0100 Subject: [PATCH 08/22] create room : remove hardcoded strings and sync strings. --- .../createroom/impl/configureroom/ConfigureRoomView.kt | 8 ++++---- .../createroom/impl/configureroom/RoomAccessItem.kt | 10 +++++----- .../impl/src/main/res/values-be/translations.xml | 3 +++ .../impl/src/main/res/values-cs/translations.xml | 8 ++++++++ .../impl/src/main/res/values-el/translations.xml | 5 +++++ .../impl/src/main/res/values-et/translations.xml | 8 ++++++++ .../impl/src/main/res/values-fr/translations.xml | 8 ++++++++ .../impl/src/main/res/values-hu/translations.xml | 8 ++++++++ .../impl/src/main/res/values-in/translations.xml | 8 ++++++++ .../impl/src/main/res/values-nl/translations.xml | 5 +++++ .../impl/src/main/res/values-pl/translations.xml | 8 ++++++++ .../impl/src/main/res/values-pt/translations.xml | 8 ++++++++ .../impl/src/main/res/values-ru/translations.xml | 8 ++++++++ .../impl/src/main/res/values-sk/translations.xml | 8 ++++++++ .../createroom/impl/src/main/res/values/localazy.xml | 8 ++++++++ .../ui-strings/src/main/res/values-be/translations.xml | 3 --- .../ui-strings/src/main/res/values-cs/translations.xml | 8 -------- .../ui-strings/src/main/res/values-el/translations.xml | 5 ----- .../ui-strings/src/main/res/values-et/translations.xml | 8 -------- .../ui-strings/src/main/res/values-fr/translations.xml | 8 -------- .../ui-strings/src/main/res/values-hu/translations.xml | 8 -------- .../ui-strings/src/main/res/values-in/translations.xml | 8 -------- .../ui-strings/src/main/res/values-nl/translations.xml | 5 ----- .../ui-strings/src/main/res/values-pl/translations.xml | 8 -------- .../ui-strings/src/main/res/values-pt/translations.xml | 8 -------- .../ui-strings/src/main/res/values-ru/translations.xml | 8 -------- .../ui-strings/src/main/res/values-sk/translations.xml | 8 -------- libraries/ui-strings/src/main/res/values/localazy.xml | 8 -------- tools/localazy/config.json | 1 + 29 files changed, 103 insertions(+), 102 deletions(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index e4fd848a20..1101f9d35f 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -273,7 +273,7 @@ private fun RoomVisibilityOptions( modifier: Modifier = Modifier, ) { ConfigureRoomOptions( - title = "Room visibility", + title = stringResource(R.string.screen_create_room_room_visibility_section_title), modifier = modifier, verticalArrangement = Arrangement.spacedBy(16.dp), ) { @@ -294,7 +294,7 @@ private fun RoomAccessOptions( modifier: Modifier = Modifier, ) { ConfigureRoomOptions( - title = "Room access", + title = stringResource(R.string.screen_create_room_room_access_section_header), modifier = modifier, verticalArrangement = Arrangement.spacedBy(12.dp), ) { @@ -323,7 +323,7 @@ private fun RoomAddressField( modifier = Modifier.padding(horizontal = 16.dp), style = ElementTheme.typography.fontBodyMdRegular, color = MaterialTheme.colorScheme.primary, - text = "Room address", + text = stringResource(R.string.screen_create_room_room_address_section_title), ) TextField( @@ -346,7 +346,7 @@ private fun RoomAddressField( }, supportingText = { Text( - text = "In order for this room to be visible in the public room directory, you will need to a room address. ", + text = stringResource(R.string.screen_create_room_room_address_section_footer), style = ElementTheme.typography.fontBodySmRegular, color = ElementTheme.colors.textSecondary, ) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt index 0e036de9b6..ce1e249396 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/RoomAccessItem.kt @@ -8,18 +8,18 @@ package io.element.android.features.createroom.impl.configureroom import androidx.annotation.StringRes -import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.features.createroom.impl.R 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, + title = R.string.screen_create_room_room_access_section_anyone_option_title, + description = R.string.screen_create_room_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, + title = R.string.screen_create_room_room_access_section_knocking_option_title, + description = R.string.screen_create_room_room_access_section_knocking_option_description, ), } diff --git a/features/createroom/impl/src/main/res/values-be/translations.xml b/features/createroom/impl/src/main/res/values-be/translations.xml index 2415fe6bb6..861fca4d05 100644 --- a/features/createroom/impl/src/main/res/values-be/translations.xml +++ b/features/createroom/impl/src/main/res/values-be/translations.xml @@ -7,6 +7,9 @@ "Прыватны пакой (толькі па запрашэнні)" "Паведамленні не зашыфраваны, і кожны можа іх прачытаць. Вы можаце ўключыць шыфраванне пазней." "Публічны пакой (для ўсіх)" + "Хто заўгодна" + "Доступ у пакой" + "Папрасіце далучыцца" "Назва пакоя" "Стварыце пакой" "Тэма (неабавязкова)" diff --git a/features/createroom/impl/src/main/res/values-cs/translations.xml b/features/createroom/impl/src/main/res/values-cs/translations.xml index 13ed58be07..697120201d 100644 --- a/features/createroom/impl/src/main/res/values-cs/translations.xml +++ b/features/createroom/impl/src/main/res/values-cs/translations.xml @@ -8,7 +8,15 @@ "Tuto místnost může najít kdokoli. To můžete kdykoli změnit v nastavení místnosti." "Veřejná místnost" + "Do této místnosti může vstoupit kdokoli" + "Kdokoliv" + "Přístup do místnosti" + "Kdokoli může požádat o vstup do místnosti, ale správce nebo moderátor bude muset žádost přijmout" + "Požádat o připojení" + "Aby byla tato místnost viditelná v adresáři veřejných místností, budete potřebovat adresu místnosti." + "Adresa místnosti" "Název místnosti" + "Viditelnost místnosti" "Vytvořit místnost" "Téma (nepovinné)" "Při pokusu o zahájení chatu došlo k chybě" diff --git a/features/createroom/impl/src/main/res/values-el/translations.xml b/features/createroom/impl/src/main/res/values-el/translations.xml index 82eda078f4..72e1d997db 100644 --- a/features/createroom/impl/src/main/res/values-el/translations.xml +++ b/features/createroom/impl/src/main/res/values-el/translations.xml @@ -8,6 +8,11 @@ "Ο καθένας μπορεί να βρει αυτό το δωμάτιο. Μπορείς να το αλλάξεις ανά πάσα στιγμή στις ρυθμίσεις δωματίου." "Δημόσιο δωμάτιο" + "Οποιοσδήποτε μπορεί να συμμετάσχει σε αυτό το δωμάτιο" + "Οποιοσδήποτε" + "Πρόσβαση Δωματίου" + "Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα" + "Αίτημα συμμετοχής" "Όνομα δωματίου" "Δημιούργησε ένα δωμάτιο" "Θέμα (προαιρετικό)" diff --git a/features/createroom/impl/src/main/res/values-et/translations.xml b/features/createroom/impl/src/main/res/values-et/translations.xml index 043c228dea..67db887f2c 100644 --- a/features/createroom/impl/src/main/res/values-et/translations.xml +++ b/features/createroom/impl/src/main/res/values-et/translations.xml @@ -8,7 +8,15 @@ "Kõik saavad seda jututuba leida. Sa võid seda jututoa seadistustest alati muuta." "Avalik jututuba" + "Kõik võivad selle jututoaga liituda" + "Kõik" + "Ligipääs jututoale" + "Kõik võivad paluda selle jututoaga liitumist, kuid peakasutaja või moderaator peavad selle kinnitama" + "Küsi võimalust liitumiseks" + "Selleks, et see jututuba oleks nähtav jututubade avalikus kataloogis, sa vajad jututoa aadressi." + "Jututoa aadress" "Jututoa nimi" + "Jututoa nähtavus" "Loo jututuba" "Teema (kui soovid lisada)" "Vestluse alustamisel tekkis viga" diff --git a/features/createroom/impl/src/main/res/values-fr/translations.xml b/features/createroom/impl/src/main/res/values-fr/translations.xml index 732dfe89a0..af40d1f9fe 100644 --- a/features/createroom/impl/src/main/res/values-fr/translations.xml +++ b/features/createroom/impl/src/main/res/values-fr/translations.xml @@ -8,7 +8,15 @@ "N’importe qui peut trouver ce salon. Vous pouvez modifier cela à tout moment dans les paramètres du salon." "Salon public" + "Tout le monde peut rejoindre ce salon" + "Tout le monde" + "Accès au salon" + "Tout le monde peut demander à rejoindre le salon, mais un administrateur ou un modérateur devra accepter la demande" + "Demander à rejoindre" + "Pour que ce salon soit visible dans le répertoire des salons publics, vous aurez besoin d’une adresse de salon." + "Adresse du salon" "Nom du salon" + "Visibilité du salon" "Créer un salon" "Sujet (facultatif)" "Une erreur s’est produite lors de la tentative de création de la discussion" diff --git a/features/createroom/impl/src/main/res/values-hu/translations.xml b/features/createroom/impl/src/main/res/values-hu/translations.xml index a521ec214e..ee935c8c60 100644 --- a/features/createroom/impl/src/main/res/values-hu/translations.xml +++ b/features/createroom/impl/src/main/res/values-hu/translations.xml @@ -8,7 +8,15 @@ "Bárki megtalálhatja ezt a szobát. Ezt bármikor módosíthatja a szobabeállításokban." "Nyilvános szoba" + "Bárki csatlakozhat ehhez a szobához" + "Bárki" + "Szobahozzáférés" + "Bárki kérheti, hogy csatlakozzon a szobához, de egy adminisztrátornak vagy moderátornak el kell fogadnia a kérést" + "Csatlakozás kérése" + "Ahhoz, hogy ez a szoba látható legyen a nyilvános szobák címtárában, meg kell adnia a szoba címét." + "Szoba címe" "Szoba neve" + "Szoba láthatósága" "Szoba létrehozása" "Téma (nem kötelező)" "Hiba történt a csevegés indításakor" diff --git a/features/createroom/impl/src/main/res/values-in/translations.xml b/features/createroom/impl/src/main/res/values-in/translations.xml index a9f795983e..b1c7aeef1c 100644 --- a/features/createroom/impl/src/main/res/values-in/translations.xml +++ b/features/createroom/impl/src/main/res/values-in/translations.xml @@ -8,7 +8,15 @@ "Siapa pun dapat mencari ruangan ini. Anda dapat mengubah ini kapan pun dalam pengaturan ruangan." "Ruangan publik" + "Siapa pun dapat bergabung dengan ruangan ini" + "Siapa pun" + "Akses Ruangan" + "Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut" + "Minta untuk bergabung" + "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." + "Alamat ruangan" "Nama ruangan" + "Keterlihatan ruangan" "Buat ruangan" "Topik (opsional)" "Terjadi kesalahan saat mencoba memulai obrolan" diff --git a/features/createroom/impl/src/main/res/values-nl/translations.xml b/features/createroom/impl/src/main/res/values-nl/translations.xml index 9421cface6..c1f0fd92f5 100644 --- a/features/createroom/impl/src/main/res/values-nl/translations.xml +++ b/features/createroom/impl/src/main/res/values-nl/translations.xml @@ -8,6 +8,11 @@ "Iedereen kan deze kamer vinden. Je kunt dit op elk gewenst moment wijzigen in de kamerinstellingen." "Openbare kamer" + "Iedereen kan toetreden tot deze kamer" + "Iedereen" + "Toegang tot de kamer" + "Iedereen kan vragen om toe te treden tot de kamer, maar een beheerder of moderator moet het verzoek accepteren" + "Vraag om toe te treden" "Naam van de kamer" "Creëer een kamer" "Onderwerp (optioneel)" diff --git a/features/createroom/impl/src/main/res/values-pl/translations.xml b/features/createroom/impl/src/main/res/values-pl/translations.xml index 3c3ad1fa12..7902fb4c3c 100644 --- a/features/createroom/impl/src/main/res/values-pl/translations.xml +++ b/features/createroom/impl/src/main/res/values-pl/translations.xml @@ -8,7 +8,15 @@ "Każdy może znaleźć ten pokój. Możesz to zmienić w ustawieniach pokoju." "Pokój publiczny" + "Każdy może dołączyć do tego pokoju" + "Wszyscy" + "Dostęp do pokoju" + "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę" + "Poproś o dołączenie" + "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju." + "Adres pokoju" "Nazwa pokoju" + "Widoczność pomieszczenia" "Utwórz pokój" "Temat (opcjonalnie)" "Wystąpił błąd podczas próby rozpoczęcia czatu" diff --git a/features/createroom/impl/src/main/res/values-pt/translations.xml b/features/createroom/impl/src/main/res/values-pt/translations.xml index 019a6dd47c..60ee753b13 100644 --- a/features/createroom/impl/src/main/res/values-pt/translations.xml +++ b/features/createroom/impl/src/main/res/values-pt/translations.xml @@ -8,7 +8,15 @@ "Qualquer um pode encontrar esta sala. Pode alterar esta opção nas definições da sala." "Sala pública" + "Qualquer pessoa pode entrar nesta sala" + "Qualquer pessoa" + "Acesso à sala" + "Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou um moderador terá de aceitar o pedido" + "Pedir para participar" + "Para que esta sala seja visível no diretório público de salas, precisas de um endereço de sala." + "Endereço da sala" "Nome da sala" + "Visibilidade da sala" "Criar uma sala" "Descrição (opcional)" "Ocorreu um erro ao tentar iniciar uma conversa" diff --git a/features/createroom/impl/src/main/res/values-ru/translations.xml b/features/createroom/impl/src/main/res/values-ru/translations.xml index 39df1f0ef5..b21bcb68ac 100644 --- a/features/createroom/impl/src/main/res/values-ru/translations.xml +++ b/features/createroom/impl/src/main/res/values-ru/translations.xml @@ -8,7 +8,15 @@ "Любой желающий может найти эту комнату. Вы можете изменить это в любое время в настройках комнаты." "Общедоступная комната" + "Любой желающий может присоединиться к этой комнате" + "Любой" + "Доступ в комнату" + "Любой желающий может подать заявку на присоединение к комнате, но администратор или модератор должен будет принять запрос." + "Попросить присоединиться" + "Чтобы эта комната была видна в каталоге общедоступных, вам необходим ее адрес" + "Адрес комнаты" "Название комнаты" + "Видимость комнаты" "Создать комнату" "Тема (необязательно)" "Произошла ошибка при запуске чата" diff --git a/features/createroom/impl/src/main/res/values-sk/translations.xml b/features/createroom/impl/src/main/res/values-sk/translations.xml index 12a94590c8..d2d742239f 100644 --- a/features/createroom/impl/src/main/res/values-sk/translations.xml +++ b/features/createroom/impl/src/main/res/values-sk/translations.xml @@ -8,7 +8,15 @@ "Túto miestnosť môže nájsť ktokoľvek. Môžete to kedykoľvek zmeniť v nastaveniach miestnosti." "Verejná miestnosť" + "Do tejto miestnosti sa môže pripojiť ktokoľvek" + "Ktokoľvek" + "Prístup do miestnosti" + "Ktokoľvek môže požiadať o pripojenie sa k miestnosti, ale administrátor alebo moderátor bude musieť žiadosť schváliť" + "Požiadať o pripojenie" + "Aby bola táto miestnosť viditeľná v adresári verejných miestností, budete potrebovať adresu miestnosti." + "Adresa miestnosti" "Názov miestnosti" + "Viditeľnosť miestnosti" "Vytvoriť miestnosť" "Téma (voliteľné)" "Pri pokuse o spustenie konverzácie sa vyskytla chyba" diff --git a/features/createroom/impl/src/main/res/values/localazy.xml b/features/createroom/impl/src/main/res/values/localazy.xml index e5256d928b..6ed5510ce0 100644 --- a/features/createroom/impl/src/main/res/values/localazy.xml +++ b/features/createroom/impl/src/main/res/values/localazy.xml @@ -8,7 +8,15 @@ "Anyone can find this room. You can change this anytime in room settings." "Public room" + "Anyone can join this room" + "Anyone" + "Room Access" + "Anyone can ask to join the room but an administrator or a moderator will have to accept the request" + "Ask to join" + "In order for this room to be visible in the public room directory, you will need a room address." + "Room address" "Room name" + "Room visibility" "Create a room" "Topic (optional)" "An error occurred when trying to start a chat" diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index 52272f43e3..38de3c79a9 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -284,9 +284,6 @@ "Гэй, пагавары са мной у %1$s: %2$s" "%1$s Android" "Паведаміць аб памылцы з дапамогай Rageshake" - "Хто заўгодна" - "Доступ у пакой" - "Папрасіце далучыцца" "Не ўдалося выбраць носьбіт, паўтарыце спробу." "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз." diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index bdf97164ba..421b5b8523 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -295,14 +295,6 @@ Důvod: %1$s." "Ahoj, ozvi se mi na %1$s: %2$s" "%1$s Android" "Zatřeste zařízením pro nahlášení chyby" - "Do této místnosti může vstoupit kdokoli" - "Kdokoliv" - "Přístup do místnosti" - "Kdokoli může požádat o vstup do místnosti, ale správce nebo moderátor bude muset žádost přijmout" - "Požádat o připojení" - "Aby byla tato místnost viditelná v adresáři veřejných místností, budete potřebovat adresu místnosti." - "Adresa místnosti" - "Viditelnost místnosti" "Výběr média se nezdařil, zkuste to prosím znovu." "Nahrání média se nezdařilo, zkuste to prosím znovu." "Nahrání média se nezdařilo, zkuste to prosím znovu." diff --git a/libraries/ui-strings/src/main/res/values-el/translations.xml b/libraries/ui-strings/src/main/res/values-el/translations.xml index e737fa106c..de35c4d797 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -285,11 +285,6 @@ "Γεια, μίλα μου στην εφαρμογή %1$s :%2$s" "%1$s Android" "Κούνησε δυνατά τη συσκευή σου για να αναφέρεις κάποιο σφάλμα" - "Οποιοσδήποτε μπορεί να συμμετάσχει σε αυτό το δωμάτιο" - "Οποιοσδήποτε" - "Πρόσβαση Δωματίου" - "Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στο δωμάτιο, αλλά ένας διαχειριστής ή συντονιστής θα πρέπει να αποδεχθεί το αίτημα" - "Αίτημα συμμετοχής" "Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά." "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά." "Αποτυχία μεταφόρτωσης πολυμέσων, δοκίμασε ξανά." diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index 201cfd5165..c0607c60e4 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -291,14 +291,6 @@ Põhjus: %1$s." "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" - "Kõik võivad selle jututoaga liituda" - "Kõik" - "Ligipääs jututoale" - "Kõik võivad paluda selle jututoaga liitumist, kuid peakasutaja või moderaator peavad selle kinnitama" - "Küsi võimalust liitumiseks" - "Selleks, et see jututuba oleks nähtav jututubade avalikus kataloogis, sa vajad jututoa aadressi." - "Jututoa aadress" - "Jututoa nähtavus" "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti." diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index e26cc1ce05..f9159b6d6c 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -290,14 +290,6 @@ Raison: %1$s." "Salut, parle-moi sur %1$s : %2$s" "%1$s Android" "Rageshake pour signaler un problème" - "Tout le monde peut rejoindre ce salon" - "Tout le monde" - "Accès au salon" - "Tout le monde peut demander à rejoindre le salon, mais un administrateur ou un modérateur devra accepter la demande" - "Demander à rejoindre" - "Pour que ce salon soit visible dans le répertoire des salons publics, vous aurez besoin d’une adresse de salon." - "Adresse du salon" - "Visibilité du salon" "Échec de la sélection du média, veuillez réessayer." "Échec du traitement des médias à télécharger, veuillez réessayer." "Échec du téléchargement du média, veuillez réessayer." diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index fe376455ec..a80e8de9e5 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -291,14 +291,6 @@ Ok: %1$s." "Beszélgessünk itt: %1$s, %2$s" "%1$s Android" "Az eszköz rázása a hibajelentéshez" - "Bárki csatlakozhat ehhez a szobához" - "Bárki" - "Szobahozzáférés" - "Bárki kérheti, hogy csatlakozzon a szobához, de egy adminisztrátornak vagy moderátornak el kell fogadnia a kérést" - "Csatlakozás kérése" - "Ahhoz, hogy ez a szoba látható legyen a nyilvános szobák címtárában, meg kell adnia a szoba címét." - "Szoba címe" - "Szoba láthatósága" "Nem sikerült kiválasztani a médiát, próbálja újra." "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült a média feltöltése, próbálja újra." diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index 48a619a009..a5beab01d3 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -287,14 +287,6 @@ Alasan: %1$s." "Hai, bicaralah dengan saya di %1$s: %2$s" "%1$s Android" "Rageshake untuk melaporkan kutu" - "Siapa pun dapat bergabung dengan ruangan ini" - "Siapa pun" - "Akses Ruangan" - "Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut" - "Minta untuk bergabung" - "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." - "Alamat ruangan" - "Keterlihatan ruangan" "Gagal memilih media, silakan coba lagi." "Gagal memproses media untuk diunggah, silakan coba lagi." "Gagal mengunggah media, silakan coba lagi." diff --git a/libraries/ui-strings/src/main/res/values-nl/translations.xml b/libraries/ui-strings/src/main/res/values-nl/translations.xml index ec174da0f7..4b10c17180 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -283,11 +283,6 @@ Reden: %1$s." "Hé, praat met me op %1$s: %2$s" "%1$s Android" "Schudden om een bug te melden" - "Iedereen kan toetreden tot deze kamer" - "Iedereen" - "Toegang tot de kamer" - "Iedereen kan vragen om toe te treden tot de kamer, maar een beheerder of moderator moet het verzoek accepteren" - "Vraag om toe te treden" "Het selecteren van media is mislukt. Probeer het opnieuw." "Het verwerken van media voor uploaden is mislukt. Probeer het opnieuw." "Het uploaden van media is mislukt. Probeer het opnieuw." diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index baef162dc9..77decc684f 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -292,14 +292,6 @@ Powód: %1$s." "Hej, porozmawiajmy na %1$s: %2$s" "%1$s Android" "Wstrząśnij gniewnie, aby zgłosić błąd" - "Każdy może dołączyć do tego pokoju" - "Wszyscy" - "Dostęp do pokoju" - "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę" - "Poproś o dołączenie" - "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju." - "Adres pokoju" - "Widoczność pomieszczenia" "Nie udało się wybrać multimediów. Spróbuj ponownie." "Przetwarzanie multimediów do przesłania nie powiodło się, spróbuj ponownie." "Przesyłanie multimediów nie powiodło się, spróbuj ponownie." diff --git a/libraries/ui-strings/src/main/res/values-pt/translations.xml b/libraries/ui-strings/src/main/res/values-pt/translations.xml index 10c534064b..65e2a5d483 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -291,14 +291,6 @@ Razão: %1$s." "Alô! Fala comigo na %1$s: %2$s" "%1$s Android" "Agita o dispositivo em fúria para comunicar um problema" - "Qualquer pessoa pode entrar nesta sala" - "Qualquer pessoa" - "Acesso à sala" - "Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou um moderador terá de aceitar o pedido" - "Pedir para participar" - "Para que esta sala seja visível no diretório público de salas, precisas de um endereço de sala." - "Endereço da sala" - "Visibilidade da sala" "Falha ao selecionar multimédia, por favor tente novamente." "Falha ao processar multimédia para carregamento, por favor tente novamente." "Falhar ao carregar multimédia, por favor tente novamente." diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index dcf525d5fd..e6f3bc4767 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -295,14 +295,6 @@ "Привет, поговори со мной по %1$s: %2$s" "%1$s Android" "Встряхните устройство, чтобы сообщить об ошибке" - "Любой желающий может присоединиться к этой комнате" - "Любой" - "Доступ в комнату" - "Любой желающий может подать заявку на присоединение к комнате, но администратор или модератор должен будет принять запрос." - "Попросить присоединиться" - "Чтобы эта комната была видна в каталоге общедоступных, вам необходим ее адрес" - "Адрес комнаты" - "Видимость комнаты" "Не удалось выбрать носитель, попробуйте еще раз." "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось загрузить медиафайлы, попробуйте еще раз." diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index 3df443c6cf..3d1cc9d416 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -293,14 +293,6 @@ Dôvod: %1$s." "Ahoj, porozprávajte sa so mnou na %1$s: %2$s" "%1$s Android" "Zúrivo potriasť pre nahlásenie chyby" - "Do tejto miestnosti sa môže pripojiť ktokoľvek" - "Ktokoľvek" - "Prístup do miestnosti" - "Ktokoľvek môže požiadať o pripojenie sa k miestnosti, ale administrátor alebo moderátor bude musieť žiadosť schváliť" - "Požiadať o pripojenie" - "Aby bola táto miestnosť viditeľná v adresári verejných miestností, budete potrebovať adresu miestnosti." - "Adresa miestnosti" - "Viditeľnosť miestnosti" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa nahrať médiá, skúste to prosím znova." diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index ea1b0f05fd..d1f17f147f 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -291,14 +291,6 @@ Reason: %1$s." "Hey, talk to me on %1$s: %2$s" "%1$s Android" "Rageshake to report bug" - "Anyone can join this room" - "Anyone" - "Room Access" - "Anyone can ask to join the room but an administrator or a moderator will have to accept the request" - "Ask to join" - "In order for this room to be visible in the public room directory, you will need a room address." - "Room address" - "Room visibility" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." diff --git a/tools/localazy/config.json b/tools/localazy/config.json index fb05345687..f18744bae9 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -61,6 +61,7 @@ "name" : ":features:createroom:impl", "includeRegex" : [ "screen_create_room_.*", + "screen\\.create_room\\..*", "screen_start_chat_.*" ] }, From 0ebb21093c5365b080302b087a6db083a3aad00c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 5 Nov 2024 08:44:20 +0000 Subject: [PATCH 09/22] Update screenshots --- ...s.createroom.impl.components_RoomAccessOption_Day_0_en.png | 3 +++ ...createroom.impl.components_RoomAccessOption_Night_0_en.png | 3 +++ ....createroom.impl.components_RoomPrivacyOption_Day_0_en.png | 4 ++-- ...reateroom.impl.components_RoomPrivacyOption_Night_0_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomView_Day_0_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomView_Day_1_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomView_Day_2_en.png | 3 +++ ...teroom.impl.configureroom_ConfigureRoomView_Night_0_en.png | 4 ++-- ...teroom.impl.configureroom_ConfigureRoomView_Night_1_en.png | 4 ++-- ...teroom.impl.configureroom_ConfigureRoomView_Night_2_en.png | 3 +++ 10 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png new file mode 100644 index 0000000000..a45ad2fd47 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39e248b3ba5e1c1b41d557471826f1d67d9c1d71b6b8ec34ca6226358dd396b5 +size 15609 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png new file mode 100644 index 0000000000..a5b7c14008 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81760d5d90b82dee085f30b6c20e259caaafc63a68033137ae28d1b2d8f2f121 +size 15125 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Day_0_en.png index dff2945ebf..453d07fd59 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ef1c5aa8a1be3fc5c2fd55b8fde64f7ec7c3d12037e4e2b08049c6a1ea21a3d -size 30128 +oid sha256:43e7348faba79c517dc05d92f8bbc40a6bee7d977f8667ee6e945a7e722b20b5 +size 30728 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Night_0_en.png index ca8cc5e534..6e18ae0790 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f5762dcb065b0406441e7f67d2b3a120f11bed71d1f56b96cb334b831d96ce3 -size 29511 +oid sha256:aec1f68cd88c087e22fae3f1334c6d7afaa085c71c8f121b4d653bca3bcfa8a6 +size 30074 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png index 8337a1e532..155986b58b 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8344c5a707a3af3aaeab22006e84bd93f1cdf8389199d88beb276a8b672b0a4a -size 50817 +oid sha256:901462c6c5f40e95db357ad964aff83179e36182e0ec61b832fe73c76697257a +size 53949 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png index 0f46643716..871fa11194 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c39135c177aa7b22c9451ef86bee41a216931759448ed2764d3bef4ea410230 -size 72685 +oid sha256:db6b448c513d3f173a988f1151a82af8455b00d822f75b76103067260ae1bac7 +size 76200 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png new file mode 100644 index 0000000000..12208bc0e9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a2b4959fc4ca3a0b363b08e3724d0ad957f588320a69f901faaeb36d913b60f +size 76229 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png index 82896e9306..e349d30b1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b05e067c92747ac92f10efcec20df0a1a7e1040c0be7a4b04009a5cf50c0aeb5 -size 49720 +oid sha256:90cd88d155bf54dc233d95c27c43d4ede4eccfd175840f592ff4882d3b2cb261 +size 52329 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png index 02e544dca1..f7483d3eb3 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79b1423947e9f87d9139f1742f845a80d6474c0b36d3557b1c30fee6a3e808ad -size 71946 +oid sha256:0601ca5a9c3183e8244b5eaf1a14cf052afe15c61cd69a74472b9db4062caa3f +size 75345 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png new file mode 100644 index 0000000000..86368097a9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcb08e5d84df7a89e4851d631f1ad7b2bce6213cfd9be37d98782d1d778d0b23 +size 75375 From d68afd2cbec71785c1685f136ed95cc97d6e2b39 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:04:52 +0000 Subject: [PATCH 10/22] fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v0.2.59 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 12c0bf626b..4737ef942a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -173,7 +173,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.58" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.59" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From ed1d208d9c0d160bf60ad08d32abbb1834b23537 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 5 Nov 2024 21:10:20 +0100 Subject: [PATCH 11/22] create room : fix konsist test --- .../features/createroom/impl/components/RoomVisibilityOption.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt index 15ae5c11a1..e76296fa4c 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt @@ -91,7 +91,7 @@ fun RoomVisibilityOption( @PreviewsDayNight @Composable -internal fun RoomPrivacyOptionPreview() = ElementPreview { +internal fun RoomVisibilityOptionPreview() = ElementPreview { val aRoomPrivacyItem = RoomVisibilityItem.Private Column { RoomVisibilityOption( From 4ff1e7962d76ee6e5cb6b743a7498525b70ae704 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 5 Nov 2024 21:12:39 +0100 Subject: [PATCH 12/22] create room : override invite power level for knockable rooms --- .../android/libraries/matrix/impl/RustMatrixClient.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 3417c9b377..d734d7e44b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -33,6 +33,7 @@ import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.PendingRoom +import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import io.element.android.libraries.matrix.api.room.preview.RoomPreview @@ -320,7 +321,14 @@ class RustMatrixClient( }, invite = createRoomParams.invite?.map { it.value }, avatar = createRoomParams.avatar, - powerLevelContentOverride = defaultRoomCreationPowerLevels, + powerLevelContentOverride = defaultRoomCreationPowerLevels.copy( + invite = if (createRoomParams.joinRuleOverride == JoinRuleOverride.Knock) { + // override the invite power level so it's the same as kick. + RoomMember.Role.MODERATOR.powerLevel.toInt() + } else { + null + } + ), joinRuleOverride = when (createRoomParams.joinRuleOverride) { JoinRuleOverride.Knock -> RustJoinRule.Knock JoinRuleOverride.None -> null From 6f1de0cecc5e7e04ff4a80172bfce13523335227 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 6 Nov 2024 09:18:47 +0000 Subject: [PATCH 13/22] Update screenshots --- ....createroom.impl.components_RoomVisibilityOption_Day_0_en.png} | 0 ...reateroom.impl.components_RoomVisibilityOption_Night_0_en.png} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/uitests/src/test/snapshots/images/{features.createroom.impl.components_RoomPrivacyOption_Day_0_en.png => features.createroom.impl.components_RoomVisibilityOption_Day_0_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.createroom.impl.components_RoomPrivacyOption_Night_0_en.png => features.createroom.impl.components_RoomVisibilityOption_Night_0_en.png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Day_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Day_0_en.png rename to tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Day_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Night_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomPrivacyOption_Night_0_en.png rename to tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Night_0_en.png From cd481d3ca98355773af07fad879b434a5f7d9609 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Nov 2024 15:32:52 +0100 Subject: [PATCH 14/22] Add a message in the notification for the caption. Fixes #2602 --- .../notifications/factories/NotificationCreator.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt index dc57b0fe7b..b2a7a62679 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt @@ -424,6 +424,17 @@ class DefaultNotificationCreator @Inject constructor( message.extras.putString(MESSAGE_EVENT_ID, event.eventId.value) } addMessage(message) + + // Add additional message for captions + if (event.imageUri != null && event.body != null) { + addMessage( + MessagingStyle.Message( + event.body, + event.timestamp, + senderPerson, + ) + ) + } } } } From 64b189c48a74d95122f6ffba2acc4ec2c0eb758f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Nov 2024 15:41:42 +0100 Subject: [PATCH 15/22] Notification with image: provide the mimetype if available. --- .../DefaultNotifiableEventResolver.kt | 14 ++++++++++++++ .../NotificationBroadcastReceiverHandler.kt | 1 + .../notifications/factories/NotificationCreator.kt | 2 +- .../notifications/model/NotifiableMessageEvent.kt | 3 ++- .../DefaultNotifiableEventResolverTest.kt | 3 +++ .../fixtures/NotifiableEventFixture.kt | 1 + 6 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt index 2fb6186bd4..97e80f4dbf 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt @@ -107,6 +107,7 @@ class DefaultNotifiableEventResolver @Inject constructor( senderDisambiguatedDisplayName = senderDisambiguatedDisplayName, body = messageBody, imageUriString = content.fetchImageIfPresent(client)?.toString(), + imageMimeType = content.getImageMimetype(), roomName = roomDisplayName, roomIsDm = isDm, roomAvatarPath = roomAvatarUrl, @@ -316,6 +317,17 @@ class DefaultNotifiableEventResolver @Inject constructor( } .getOrNull() } + + private suspend fun NotificationContent.MessageLike.RoomMessage.getImageMimetype(): String? { + if (appPreferencesStore.doesHideImagesAndVideosFlow().first()) { + return null + } + return when (val messageType = messageType) { + is ImageMessageType -> messageType.info?.mimetype + is VideoMessageType -> null // Use the thumbnail here? + else -> null + } + } } @Suppress("LongParameterList") @@ -333,6 +345,7 @@ internal fun buildNotifiableMessageEvent( // We cannot use Uri? type here, as that could trigger a // NotSerializableException when persisting this to storage imageUriString: String? = null, + imageMimeType: String? = null, threadId: ThreadId? = null, roomName: String? = null, roomIsDm: Boolean = false, @@ -358,6 +371,7 @@ internal fun buildNotifiableMessageEvent( senderDisambiguatedDisplayName = senderDisambiguatedDisplayName, body = body, imageUriString = imageUriString, + imageMimeType = imageMimeType, threadId = threadId, roomName = roomName, roomIsDm = roomIsDm, diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt index 97c53e945b..a3d553ba91 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt @@ -150,6 +150,7 @@ class NotificationBroadcastReceiverHandler @Inject constructor( ?: stringProvider.getString(R.string.notification_sender_me), body = message, imageUriString = null, + imageMimeType = null, threadId = threadId, roomName = room.displayName, roomIsDm = room.isDm, diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt index b2a7a62679..559322eaae 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt @@ -419,7 +419,7 @@ class DefaultNotificationCreator @Inject constructor( senderPerson ).also { message -> event.imageUri?.let { - message.setData("image/", it) + message.setData(event.imageMimeType ?: "image/", it) } message.extras.putString(MESSAGE_EVENT_ID, event.eventId.value) } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt index 4a4d2612ae..d51c7e09de 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/model/NotifiableMessageEvent.kt @@ -31,7 +31,8 @@ data class NotifiableMessageEvent( val body: String?, // We cannot use Uri? type here, as that could trigger a // NotSerializableException when persisting this to storage - val imageUriString: String?, + private val imageUriString: String?, + val imageMimeType: String?, val threadId: ThreadId?, val roomName: String?, val roomIsDm: Boolean = false, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index de29fcf1f0..153ebe1ffc 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -590,6 +590,7 @@ class DefaultNotifiableEventResolverTest { senderDisambiguatedDisplayName = A_USER_NAME_2, body = "Call in progress (unsupported)", imageUriString = null, + imageMimeType = null, threadId = null, roomName = A_ROOM_NAME, roomAvatarPath = null, @@ -669,6 +670,7 @@ class DefaultNotifiableEventResolverTest { canBeReplaced = false, isRedacted = false, imageUriString = null, + imageMimeType = null, type = EventType.CALL_NOTIFY, ) ) @@ -704,6 +706,7 @@ class DefaultNotifiableEventResolverTest { canBeReplaced = false, isRedacted = false, imageUriString = null, + imageMimeType = null, type = EventType.CALL_NOTIFY, ) ) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt index faba6a6c65..438718582f 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/fixtures/NotifiableEventFixture.kt @@ -100,6 +100,7 @@ fun aNotifiableMessageEvent( canBeReplaced = false, isRedacted = isRedacted, imageUriString = null, + imageMimeType = null, roomAvatarPath = null, senderAvatarPath = null, soundName = null, From c04bd64ca4208c62ed7fc5e9f3e48e6cbe642e0d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Nov 2024 15:47:10 +0100 Subject: [PATCH 16/22] Fix wrong description. --- .../impl/timeline/components/event/TimelineItemVideoView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt index 675f9adfc6..a6432c79ad 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt @@ -70,7 +70,7 @@ fun TimelineItemVideoView( onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, ) { - val description = stringResource(CommonStrings.common_image) + val description = stringResource(CommonStrings.common_video) Column( modifier = modifier.semantics { contentDescription = description } ) { From f00478d9f37b1b16a1e5997172e2820f4a072b21 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Nov 2024 15:47:49 +0100 Subject: [PATCH 17/22] Format file... --- .../timeline/components/event/TimelineItemVideoView.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt index a6432c79ad..849084ea1c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemVideoView.kt @@ -76,8 +76,8 @@ fun TimelineItemVideoView( ) { val containerModifier = if (content.showCaption) { Modifier - .padding(top = 6.dp) - .clip(RoundedCornerShape(6.dp)) + .padding(top = 6.dp) + .clip(RoundedCornerShape(6.dp)) } else { Modifier } @@ -93,8 +93,8 @@ fun TimelineItemVideoView( var isLoaded by remember { mutableStateOf(false) } AsyncImage( modifier = Modifier - .fillMaxWidth() - .then(if (isLoaded) Modifier.background(Color.White) else Modifier), + .fillMaxWidth() + .then(if (isLoaded) Modifier.background(Color.White) else Modifier), model = MediaRequestData( source = content.thumbnailSource, kind = MediaRequestData.Kind.File( From 461c31420e145627441a8fe30d7c89625d4c5285 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Nov 2024 16:04:38 +0100 Subject: [PATCH 18/22] Improve last message formatter: add caption (or filename) --- .../impl/DefaultRoomLastMessageFormatter.kt | 16 ++++--- .../DefaultRoomLastMessageFormatterTest.kt | 44 ++++++++++++++----- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt index 6b43fc3607..4031915445 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatter.kt @@ -110,25 +110,27 @@ class DefaultRoomLastMessageFormatter @Inject constructor( messageType.toPlainText(permalinkParser) } is VideoMessageType -> { - sp.getString(CommonStrings.common_video) + messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_video)) } is ImageMessageType -> { - sp.getString(CommonStrings.common_image) + messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_image)) } is StickerMessageType -> { - sp.getString(CommonStrings.common_sticker) + messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_sticker)) } is LocationMessageType -> { sp.getString(CommonStrings.common_shared_location) } is FileMessageType -> { - sp.getString(CommonStrings.common_file) + messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_file)) } is AudioMessageType -> { - sp.getString(CommonStrings.common_audio) + messageType.bestDescription.prefixWith(sp.getString(CommonStrings.common_audio)) } is VoiceMessageType -> { - sp.getString(CommonStrings.common_voice_message) + // In this case, do not use bestDescription, because the filename is useless, only use the caption if available. + messageType.caption?.prefixWith(sp.getString(CommonStrings.common_voice_message)) + ?: sp.getString(CommonStrings.common_voice_message) } is OtherMessageType -> { messageType.body @@ -140,7 +142,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor( return message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } - private fun String.prefixIfNeeded( + private fun CharSequence.prefixIfNeeded( senderDisambiguatedDisplayName: String, isDmRoom: Boolean, isOutgoing: Boolean, diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt index efc748d10f..3c5038069a 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTest.kt @@ -208,32 +208,51 @@ class DefaultRoomLastMessageFormatterTest { // Verify results of DM mode for ((type, result) in resultsInDm) { + val string = result.toString() val expectedResult = when (type) { - is VideoMessageType -> "Video" - is AudioMessageType -> "Audio" + is VideoMessageType -> "Video: Shared body" + is AudioMessageType -> "Audio: Shared body" is VoiceMessageType -> "Voice message" - is ImageMessageType -> "Image" - is StickerMessageType -> "Sticker" - is FileMessageType -> "File" + is ImageMessageType -> "Image: Shared body" + is StickerMessageType -> "Sticker: Shared body" + is FileMessageType -> "File: Shared body" is LocationMessageType -> "Shared location" is EmoteMessageType -> "* $senderName ${type.body}" is TextMessageType, is NoticeMessageType, is OtherMessageType -> body } - assertWithMessage("$type was not properly handled for DM").that(result).isEqualTo(expectedResult) + val shouldCreateAnnotatedString = when (type) { + is VideoMessageType -> true + is AudioMessageType -> true + is VoiceMessageType -> false + is ImageMessageType -> true + is StickerMessageType -> true + is FileMessageType -> true + is LocationMessageType -> false + is EmoteMessageType -> false + is TextMessageType -> false + is NoticeMessageType -> false + is OtherMessageType -> false + } + if (shouldCreateAnnotatedString) { + assertWithMessage("$type doesn't produce an AnnotatedString") + .that(result) + .isInstanceOf(AnnotatedString::class.java) + } + assertWithMessage("$type was not properly handled for DM").that(string).isEqualTo(expectedResult) } // Verify results of Room mode for ((type, result) in resultsInRoom) { val string = result.toString() val expectedResult = when (type) { - is VideoMessageType -> "$expectedPrefix: Video" - is AudioMessageType -> "$expectedPrefix: Audio" + is VideoMessageType -> "$expectedPrefix: Video: Shared body" + is AudioMessageType -> "$expectedPrefix: Audio: Shared body" is VoiceMessageType -> "$expectedPrefix: Voice message" - is ImageMessageType -> "$expectedPrefix: Image" - is StickerMessageType -> "$expectedPrefix: Sticker" - is FileMessageType -> "$expectedPrefix: File" + is ImageMessageType -> "$expectedPrefix: Image: Shared body" + is StickerMessageType -> "$expectedPrefix: Sticker: Shared body" + is FileMessageType -> "$expectedPrefix: File: Shared body" is LocationMessageType -> "$expectedPrefix: Shared location" is TextMessageType, is NoticeMessageType, @@ -249,7 +268,8 @@ class DefaultRoomLastMessageFormatterTest { is FileMessageType -> true is LocationMessageType -> false is EmoteMessageType -> false - is TextMessageType, is NoticeMessageType -> true + is TextMessageType -> true + is NoticeMessageType -> true is OtherMessageType -> true } if (shouldCreateAnnotatedString) { From f2c63a5a62da634e5b6d4c2d18d25c52ad46cc64 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Nov 2024 16:05:23 +0100 Subject: [PATCH 19/22] Do not render filename of voice message. --- .../impl/DefaultPinnedMessagesBannerFormatter.kt | 4 +++- .../impl/DefaultPinnedMessagesBannerFormatterTest.kt | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt index ab7a19a9c7..11873ee7c1 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatter.kt @@ -95,7 +95,9 @@ class DefaultPinnedMessagesBannerFormatter @Inject constructor( messageType.bestDescription.prefixWith(CommonStrings.common_audio) } is VoiceMessageType -> { - messageType.bestDescription.prefixWith(CommonStrings.common_voice_message) + // In this case, do not use bestDescription, because the filename is useless, only use the caption if available. + messageType.caption?.prefixWith(sp.getString(CommonStrings.common_voice_message)) + ?: sp.getString(CommonStrings.common_voice_message) } is OtherMessageType -> { messageType.body diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt index af347135fb..80a7691a1d 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultPinnedMessagesBannerFormatterTest.kt @@ -159,11 +159,11 @@ class DefaultPinnedMessagesBannerFormatterTest { val expectedResult = when (type) { is VideoMessageType, is AudioMessageType, - is VoiceMessageType, is ImageMessageType, is StickerMessageType, is FileMessageType, is LocationMessageType -> AnnotatedString::class.java + is VoiceMessageType, is EmoteMessageType, is TextMessageType, is NoticeMessageType, @@ -176,7 +176,7 @@ class DefaultPinnedMessagesBannerFormatterTest { val expectedResult = when (type) { is VideoMessageType -> "Video: Shared body" is AudioMessageType -> "Audio: Shared body" - is VoiceMessageType -> "Voice message: Shared body" + is VoiceMessageType -> "Voice message" is ImageMessageType -> "Image: Shared body" is StickerMessageType -> "Sticker: Shared body" is FileMessageType -> "File: Shared body" From 24d4270215d749d257ee7b34b08d6d19b27a1399 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 6 Nov 2024 14:57:55 +0100 Subject: [PATCH 20/22] create room : clean up after review. --- .../createroom/impl/CreateRoomDataStore.kt | 2 +- .../impl/components/RoomAccessOption.kt | 86 -------------- .../impl/components/RoomVisibilityOption.kt | 108 ------------------ .../configureroom/ConfigureRoomPresenter.kt | 2 +- .../impl/configureroom/ConfigureRoomView.kt | 41 ++++--- 5 files changed, 26 insertions(+), 213 deletions(-) delete mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt delete mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt index 36feb0aec3..56ebe326dd 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt @@ -37,7 +37,7 @@ class CreateRoomDataStore @Inject constructor( field = value } - val createRoomConfig: Flow = combine( + val createRoomConfigWithInvites: Flow = combine( selectedUserListDataStore.selectedUsers(), createRoomConfigFlow, ) { selectedUsers, config -> diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt deleted file mode 100644 index 6cde477f2e..0000000000 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomAccessOption.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.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, - ) - } -} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt deleted file mode 100644 index e76296fa4c..0000000000 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/RoomVisibilityOption.kt +++ /dev/null @@ -1,108 +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.components - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -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.foundation.shape.RoundedCornerShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -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.unit.dp -import io.element.android.compound.theme.ElementTheme -import io.element.android.features.createroom.impl.configureroom.RoomVisibilityItem -import io.element.android.libraries.designsystem.preview.ElementPreview -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.RadioButton -import io.element.android.libraries.designsystem.theme.components.Text - -@Composable -fun RoomVisibilityOption( - roomPrivacyItem: RoomVisibilityItem, - onOptionClick: (RoomVisibilityItem) -> Unit, - modifier: Modifier = Modifier, - isSelected: Boolean = false, -) { - Row( - modifier - .fillMaxWidth() - .selectable( - selected = isSelected, - onClick = { onOptionClick(roomPrivacyItem) }, - role = Role.RadioButton, - ) - ) { - Box( - modifier = Modifier - .size(30.dp) - .clip(RoundedCornerShape(8.dp)) - .background(ElementTheme.colors.bgSubtleSecondary) - .padding(3.dp), - contentAlignment = Alignment.Center, - ) { - 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 = stringResource(roomPrivacyItem.title), - style = ElementTheme.typography.fontBodyLgRegular, - color = MaterialTheme.colorScheme.primary, - ) - Spacer(Modifier.size(3.dp)) - Text( - text = stringResource(roomPrivacyItem.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 RoomVisibilityOptionPreview() = ElementPreview { - val aRoomPrivacyItem = RoomVisibilityItem.Private - Column { - RoomVisibilityOption( - roomPrivacyItem = aRoomPrivacyItem, - onOptionClick = {}, - isSelected = true, - ) - RoomVisibilityOption( - roomPrivacyItem = aRoomPrivacyItem, - onOptionClick = {}, - isSelected = false, - ) - } -} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index 1b7623adfb..ad19d2cb9b 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -58,7 +58,7 @@ class ConfigureRoomPresenter @Inject constructor( @Composable override fun present(): ConfigureRoomState { val cameraPermissionState = cameraPermissionPresenter.present() - val createRoomConfig = dataStore.createRoomConfig.collectAsState(CreateRoomConfig()) + val createRoomConfig = dataStore.createRoomConfigWithInvites.collectAsState(CreateRoomConfig()) val homeserverName = remember { matrixClient.userIdServerName() } val isKnockFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock).collectAsState(initial = false) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index 1101f9d35f..b0084f68f6 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -36,16 +36,18 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.createroom.impl.R -import io.element.android.features.createroom.impl.components.RoomAccessOption -import io.element.android.features.createroom.impl.components.RoomVisibilityOption +import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtom +import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtomSize 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.AsyncActionViewDefaults import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.modifiers.clearFocusOnTap import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.aliasScreenTitle +import io.element.android.libraries.designsystem.theme.components.ListItem 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.TextButton @@ -247,20 +249,17 @@ private fun RoomTopic( @Composable private fun ConfigureRoomOptions( title: String, - verticalArrangement: Arrangement.Vertical, modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit, ) { Column( - modifier = modifier - .selectableGroup() - .padding(horizontal = 12.dp), - verticalArrangement = verticalArrangement, + modifier = modifier.selectableGroup() ) { Text( text = title, style = ElementTheme.typography.fontBodyLgMedium, color = ElementTheme.colors.textPrimary, + modifier = Modifier.padding(horizontal = 16.dp), ) content() } @@ -275,13 +274,21 @@ private fun RoomVisibilityOptions( ConfigureRoomOptions( title = stringResource(R.string.screen_create_room_room_visibility_section_title), modifier = modifier, - verticalArrangement = Arrangement.spacedBy(16.dp), ) { RoomVisibilityItem.entries.forEach { item -> - RoomVisibilityOption( - roomPrivacyItem = item, - isSelected = item == selected, - onOptionClick = onOptionClick, + val isSelected = item == selected + ListItem( + leadingContent = ListItemContent.Custom { + RoundedIconAtom( + size = RoundedIconAtomSize.Big, + resourceId = item.icon, + tint = if (isSelected) ElementTheme.colors.iconPrimary else ElementTheme.colors.iconSecondary, + ) + }, + headlineContent = { Text(text = stringResource(item.title)) }, + supportingContent = { Text(text = stringResource(item.description)) }, + trailingContent = ListItemContent.RadioButton(selected = isSelected), + onClick = { onOptionClick(item) }, ) } } @@ -296,13 +303,13 @@ private fun RoomAccessOptions( ConfigureRoomOptions( title = stringResource(R.string.screen_create_room_room_access_section_header), modifier = modifier, - verticalArrangement = Arrangement.spacedBy(12.dp), ) { RoomAccessItem.entries.forEach { item -> - RoomAccessOption( - roomAccessItem = item, - isSelected = item == selected, - onOptionClick = onOptionClick, + ListItem( + headlineContent = { Text(text = stringResource(item.title)) }, + supportingContent = { Text(text = stringResource(item.description)) }, + trailingContent = ListItemContent.RadioButton(selected = item == selected), + onClick = { onOptionClick(item) }, ) } } From 2ab6289b893b23835338aca1214d961b6ce74a03 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 6 Nov 2024 14:09:08 +0000 Subject: [PATCH 21/22] Update screenshots --- ...s.createroom.impl.components_RoomAccessOption_Day_0_en.png | 3 --- ...createroom.impl.components_RoomAccessOption_Night_0_en.png | 3 --- ...eateroom.impl.components_RoomVisibilityOption_Day_0_en.png | 3 --- ...teroom.impl.components_RoomVisibilityOption_Night_0_en.png | 3 --- ...eateroom.impl.configureroom_ConfigureRoomView_Day_0_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomView_Day_1_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomView_Day_2_en.png | 4 ++-- ...teroom.impl.configureroom_ConfigureRoomView_Night_0_en.png | 4 ++-- ...teroom.impl.configureroom_ConfigureRoomView_Night_1_en.png | 4 ++-- ...teroom.impl.configureroom_ConfigureRoomView_Night_2_en.png | 4 ++-- 10 files changed, 12 insertions(+), 24 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png deleted file mode 100644 index a45ad2fd47..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:39e248b3ba5e1c1b41d557471826f1d67d9c1d71b6b8ec34ca6226358dd396b5 -size 15609 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png deleted file mode 100644 index a5b7c14008..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomAccessOption_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81760d5d90b82dee085f30b6c20e259caaafc63a68033137ae28d1b2d8f2f121 -size 15125 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Day_0_en.png deleted file mode 100644 index 453d07fd59..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:43e7348faba79c517dc05d92f8bbc40a6bee7d977f8667ee6e945a7e722b20b5 -size 30728 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Night_0_en.png deleted file mode 100644 index 6e18ae0790..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.components_RoomVisibilityOption_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aec1f68cd88c087e22fae3f1334c6d7afaa085c71c8f121b4d653bca3bcfa8a6 -size 30074 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png index 155986b58b..28f4bd5c7d 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:901462c6c5f40e95db357ad964aff83179e36182e0ec61b832fe73c76697257a -size 53949 +oid sha256:e7de44cc8f686264788aa79cde24b9896c6ca4dabc49b246abbd1d3dd0311e25 +size 57891 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png index 871fa11194..3131e96896 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db6b448c513d3f173a988f1151a82af8455b00d822f75b76103067260ae1bac7 -size 76200 +oid sha256:2df49a9c82438dbf1ba0ba0670cadd8e7bb47a7e25de27793fd756760cf7c5f2 +size 79562 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png index 12208bc0e9..3131e96896 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a2b4959fc4ca3a0b363b08e3724d0ad957f588320a69f901faaeb36d913b60f -size 76229 +oid sha256:2df49a9c82438dbf1ba0ba0670cadd8e7bb47a7e25de27793fd756760cf7c5f2 +size 79562 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png index e349d30b1e..a1a2247eb8 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90cd88d155bf54dc233d95c27c43d4ede4eccfd175840f592ff4882d3b2cb261 -size 52329 +oid sha256:c754daf307554dc0c83ba0f89c38f5fa7f5c2edff82907b0826c2b781498dbcb +size 56047 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png index f7483d3eb3..2a7721de80 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0601ca5a9c3183e8244b5eaf1a14cf052afe15c61cd69a74472b9db4062caa3f -size 75345 +oid sha256:b6e43161abdccacbede4a8c4b4ff446026035df4be0894a55c6364681458bb2f +size 78805 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png index 86368097a9..2a7721de80 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcb08e5d84df7a89e4851d631f1ad7b2bce6213cfd9be37d98782d1d778d0b23 -size 75375 +oid sha256:b6e43161abdccacbede4a8c4b4ff446026035df4be0894a55c6364681458bb2f +size 78805 From cc4a8d47ebcca14e966426b507e4114806e84ad4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 6 Nov 2024 15:31:22 +0100 Subject: [PATCH 22/22] rust sdk : handle api breaks for 0.2.59 --- .../impl/RoomAliasResolverPresenter.kt | 5 ++++- .../impl/RoomAliasResolverPresenterTest.kt | 5 +++-- .../impl/root/RoomDirectoryPresenter.kt | 4 +++- .../impl/root/RoomDirectoryPresenterTest.kt | 4 ++-- .../android/libraries/matrix/api/MatrixClient.kt | 9 ++++++++- .../api/roomdirectory/RoomDirectoryList.kt | 16 +++++++++++++++- .../libraries/matrix/impl/RustMatrixClient.kt | 16 ++++++++-------- .../impl/roomdirectory/RustRoomDirectoryList.kt | 4 ++-- .../fakes/FakeRustRoomDirectorySearch.kt | 2 +- .../roomdirectory/RustRoomDirectoryListTest.kt | 2 +- .../libraries/matrix/test/FakeMatrixClient.kt | 8 ++++++-- .../test/roomdirectory/FakeRoomDirectoryList.kt | 4 ++-- 12 files changed, 55 insertions(+), 24 deletions(-) diff --git a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt index abb6682a66..ffe98680dd 100644 --- a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt +++ b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import kotlin.jvm.optionals.getOrElse class RoomAliasResolverPresenter @AssistedInject constructor( @Assisted private val roomAlias: RoomAlias, @@ -57,7 +58,9 @@ class RoomAliasResolverPresenter @AssistedInject constructor( private fun CoroutineScope.resolveAlias(resolveState: MutableState>) = launch { suspend { - matrixClient.resolveRoomAlias(roomAlias).getOrThrow() + matrixClient.resolveRoomAlias(roomAlias) + .getOrThrow() + .getOrElse { error("Failed to resolve room alias $roomAlias") } }.runCatchingUpdatingState(resolveState) } } diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt index e651cf41e8..9894c2b342 100644 --- a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt @@ -24,6 +24,7 @@ import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import java.util.Optional class RoomAliasResolverPresenterTest { @get:Rule @@ -42,7 +43,7 @@ class RoomAliasResolverPresenterTest { @Test fun `present - resolve alias to roomId`() = runTest { - val result = aResolvedRoomAlias() + val result = Optional.of(aResolvedRoomAlias()) val client = FakeMatrixClient( resolveRoomAliasResult = { Result.success(result) } ) @@ -54,7 +55,7 @@ class RoomAliasResolverPresenterTest { assertThat(awaitItem().resolveState.isLoading()).isTrue() val resultState = awaitItem() assertThat(resultState.roomAlias).isEqualTo(A_ROOM_ALIAS) - assertThat(resultState.resolveState.dataOrNull()).isEqualTo(result) + assertThat(resultState.resolveState.dataOrNull()).isEqualTo(result.get()) } } diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt index 2f3b0cff75..a5b62ff1e3 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt @@ -28,6 +28,8 @@ import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import javax.inject.Inject +private const val SEARCH_BATCH_SIZE = 20 + class RoomDirectoryPresenter @Inject constructor( private val dispatchers: CoroutineDispatchers, private val roomDirectoryService: RoomDirectoryService, @@ -51,7 +53,7 @@ class RoomDirectoryPresenter @Inject constructor( loadingMore = false // debounce search query delay(300) - roomDirectoryList.filter(searchQuery, 20) + roomDirectoryList.filter(filter = searchQuery, batchSize = SEARCH_BATCH_SIZE, viaServerName = null) } LaunchedEffect(loadingMore) { if (loadingMore) { diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt index 10dda624bd..20a709bce7 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt @@ -81,7 +81,7 @@ import org.junit.Test @Test fun `present - emit search event`() = runTest { - val filterLambda = lambdaRecorder { _: String?, _: Int -> + val filterLambda = lambdaRecorder { _: String?, _: Int, _: String? -> Result.success(Unit) } val roomDirectoryList = FakeRoomDirectoryList(filterLambda = filterLambda) @@ -99,7 +99,7 @@ import org.junit.Test } assert(filterLambda) .isCalledOnce() - .with(value("test"), any()) + .with(value("test"), any(), value(null)) } @Test diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 6af1763e83..504db1c6d9 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -108,7 +108,14 @@ interface MatrixClient : Closeable { suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result suspend fun getRecentlyVisitedRooms(): Result> - suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result + + /** + * Resolves the given room alias to a roomID (and a list of servers), if possible. + * @param roomAlias the room alias to resolve + * @return the resolved room alias if any, an empty result if not found,or an error if the resolution failed. + * + */ + suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result> /** * Enables or disables the sending queue, according to the given parameter. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt index 5f362dfda5..88cabf265b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt @@ -10,8 +10,22 @@ package io.element.android.libraries.matrix.api.roomdirectory import kotlinx.coroutines.flow.Flow interface RoomDirectoryList { - suspend fun filter(filter: String?, batchSize: Int): Result + /** + * Starts a filtered search for the server. + * If the filter is not provided it will search for all the rooms. You can specify a batch_size to control the number of rooms to fetch per request. + * If the via_server is not provided it will search in the current homeserver by default. + * This method will clear the current search results and start a new one + */ + suspend fun filter(filter: String?, batchSize: Int, viaServerName: String?): Result + + /** + * Load more rooms from the current search results. + */ suspend fun loadMore(): Result + + /** + * The current search results as a state flow. + */ val state: Flow data class State( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 101d049659..375d704ef9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -71,7 +71,6 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.Channel @@ -112,7 +111,6 @@ import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService -@OptIn(ExperimentalCoroutinesApi::class) class RustMatrixClient( private val client: Client, private val baseDirectory: File, @@ -420,13 +418,15 @@ class RustMatrixClient( } } - override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result = withContext(sessionDispatcher) { + override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result> = withContext(sessionDispatcher) { runCatching { - val result = client.resolveRoomAlias(roomAlias.value) - ResolvedRoomAlias( - roomId = RoomId(result.roomId), - servers = result.servers, - ) + val result = client.resolveRoomAlias(roomAlias.value)?.let { + ResolvedRoomAlias( + roomId = RoomId(it.roomId), + servers = it.servers, + ) + } + Optional.ofNullable(result) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt index 7219e9c3ed..576b93d26d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt @@ -41,9 +41,9 @@ class RustRoomDirectoryList( .launchIn(coroutineScope) } - override suspend fun filter(filter: String?, batchSize: Int): Result { + override suspend fun filter(filter: String?, batchSize: Int, viaServerName: String?): Result { return execute { - inner.search(filter = filter, batchSize = batchSize.toUInt()) + inner.search(filter = filter, batchSize = batchSize.toUInt(), viaServerName = viaServerName) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt index 0569ee55c8..42e078d1c8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt @@ -21,7 +21,7 @@ class FakeRustRoomDirectorySearch( return isAtLastPage } - override suspend fun search(filter: String?, batchSize: UInt) = simulateLongTask { } + override suspend fun search(filter: String?, batchSize: UInt, viaServerName: String?) = simulateLongTask { } override suspend fun nextPage() = simulateLongTask { } private var listener: RoomDirectorySearchEntriesListener? = null diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt index 134b90adc9..0eca9edde5 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt @@ -36,7 +36,7 @@ class RustRoomDirectoryListTest { // Let the mxCallback be ready runCurrent() sut.state.test { - sut.filter("", 20) + sut.filter(filter = "", batchSize = 20, viaServerName = null) roomDirectorySearch.emitResult( listOf( RoomDirectorySearchEntryUpdate.Append(listOf(aRustRoomDescription())) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 2c69048c39..dd7869cdf7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -73,7 +73,11 @@ class FakeMatrixClient( private val encryptionService: FakeEncryptionService = FakeEncryptionService(), private val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(), private val accountManagementUrlString: Result = Result.success(null), - private val resolveRoomAliasResult: (RoomAlias) -> Result = { Result.success(ResolvedRoomAlias(A_ROOM_ID, emptyList())) }, + private val resolveRoomAliasResult: (RoomAlias) -> Result> = { + Result.success( + Optional.of(ResolvedRoomAlias(A_ROOM_ID, emptyList())) + ) + }, private val getRoomPreviewResult: (RoomIdOrAlias, List) -> Result = { _, _ -> Result.failure(AN_EXCEPTION) }, private val clearCacheLambda: () -> Unit = { lambdaError() }, private val userIdServerNameLambda: () -> String = { lambdaError() }, @@ -305,7 +309,7 @@ class FakeMatrixClient( return Result.success(Unit) } - override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result = simulateLongTask { + override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result> = simulateLongTask { resolveRoomAliasResult(roomAlias) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt index afe1e52074..6a3fcb3b45 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt @@ -13,10 +13,10 @@ import kotlinx.coroutines.flow.emptyFlow class FakeRoomDirectoryList( override val state: Flow = emptyFlow(), - val filterLambda: (String?, Int) -> Result = { _, _ -> Result.success(Unit) }, + val filterLambda: (String?, Int, String?) -> Result = { _, _, _ -> Result.success(Unit) }, val loadMoreLambda: () -> Result = { Result.success(Unit) } ) : RoomDirectoryList { - override suspend fun filter(filter: String?, batchSize: Int) = filterLambda(filter, batchSize) + override suspend fun filter(filter: String?, batchSize: Int, viaServerName: String?): Result = filterLambda(filter, batchSize, viaServerName) override suspend fun loadMore(): Result = loadMoreLambda() }