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 85c64adc83..e2b0e05444 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 @@ -82,10 +82,6 @@ class ConfigureRoomPresenter( private val cameraPermissionPresenter: PermissionsPresenter = permissionsPresenterFactory.create(android.Manifest.permission.CAMERA) private var pendingPermissionRequest = false - init { - dataStore.setIsSpace(isSpace) - } - @Composable override fun present(): ConfigureRoomState { val canAddRoomToSpace by featureFlagService.isFeatureEnabledFlow(FeatureFlags.CreateSpaces).collectAsState(false) @@ -123,9 +119,10 @@ class ConfigureRoomPresenter( } else { persistentListOf() } - val parentSpace = spaces.find { it.roomId == initialParentSpaceId } - parentSpace?.let { dataStore.setParentSpace(it) } + parentSpace?.let { + dataStore.setParentSpace(parentSpace = parentSpace, updateVisibility = true) + } } LaunchedEffect(cameraPermissionState.permissionGranted) { @@ -152,21 +149,42 @@ class ConfigureRoomPresenter( // 2. If it has a parent space. // 3. If knocking is enabled. val parentSpace = createRoomConfig.parentSpace - val availableJoinRules = remember(createRoomConfig.parentSpace, isSpace, isKnockFeatureEnabled) { + val availableJoinRules = remember(parentSpace, isSpace, isKnockFeatureEnabled) { when { isSpace && parentSpace != null -> TODO("Adding a space to a parent space is not supported yet! How did you get here?") parentSpace == null || parentSpace.joinRule == JoinRule.Public -> listOfNotNull( JoinRuleItem.PublicVisibility.Public, JoinRuleItem.PublicVisibility.AskToJoin.takeIf { !isSpace && isKnockFeatureEnabled }, - JoinRuleItem.Private, + JoinRuleItem.PrivateVisibility.Private, ).toImmutableList() else -> listOfNotNull( - JoinRuleItem.PublicVisibility.Restricted(parentSpace.roomId), - JoinRuleItem.PublicVisibility.AskToJoinRestricted(parentSpace.roomId).takeIf { !isSpace && isKnockFeatureEnabled }, - JoinRuleItem.Private, + JoinRuleItem.PrivateVisibility.Restricted(parentSpace.roomId), + JoinRuleItem.PrivateVisibility.AskToJoinRestricted(parentSpace.roomId).takeIf { isKnockFeatureEnabled }, + JoinRuleItem.PrivateVisibility.Private, ).toImmutableList() } } + val currentJoinRule = createRoomConfig.visibilityState?.joinRuleItem + LaunchedEffect(availableJoinRules, currentJoinRule) { + // Find matching rule by type (ignoring parentSpaceId parameter for Restricted types) + val matchingRule = when (currentJoinRule) { + is JoinRuleItem.PrivateVisibility.Restricted -> + availableJoinRules.filterIsInstance().firstOrNull() + is JoinRuleItem.PrivateVisibility.AskToJoinRestricted -> + availableJoinRules.filterIsInstance().firstOrNull() + else -> availableJoinRules.find { it == currentJoinRule } + } + when { + matchingRule == null -> { + // No matching type fallback to Private (always available) + dataStore.setJoinRule(JoinRuleItem.PrivateVisibility.Private) + } + matchingRule != currentJoinRule -> { + // Same type but different params (e.g., different parentSpaceId), update + dataStore.setJoinRule(matchingRule) + } + } + } fun createRoom(config: CreateRoomConfig) { createRoomAction.value = AsyncAction.Uninitialized @@ -193,7 +211,7 @@ class ConfigureRoomPresenter( } } is ConfigureRoomEvents.SetParentSpace -> { - dataStore.setParentSpace(event.space) + dataStore.setParentSpace(event.space, false) } ConfigureRoomEvents.CancelCreateRoom -> { createRoomAction.value = AsyncAction.Uninitialized @@ -210,6 +228,7 @@ class ConfigureRoomPresenter( roomAddressValidity = roomAddressValidity.value, availableJoinRules = availableJoinRules, spaces = spaces, + isSpace = isSpace, eventSink = ::handleEvent, ) } @@ -220,35 +239,41 @@ class ConfigureRoomPresenter( ) = launch { suspend { val avatarUrl = config.avatarUri?.let { uploadAvatar(it.toUri()) } - val params = if (config.visibilityState is RoomVisibilityState.Public) { - CreateRoomParameters( - name = config.roomName, - topic = config.topic, - isEncrypted = false, - isDirect = false, - visibility = RoomVisibility.Public, - joinRuleOverride = config.visibilityState.joinRuleItem.toJoinRule() - // No need to specify the public join rule override, since the preset is already PUBLIC_CHAT - .takeIf { it != JoinRule.Public }, - preset = RoomPreset.PUBLIC_CHAT, - invite = config.invites.map { it.userId }, - avatar = avatarUrl, - roomAliasName = config.visibilityState.roomAddress(), - isSpace = isSpace, - ) - } else { - CreateRoomParameters( - name = config.roomName, - topic = config.topic, - isEncrypted = config.visibilityState is RoomVisibilityState.Private, - isDirect = false, - visibility = RoomVisibility.Private, - historyVisibilityOverride = RoomHistoryVisibility.Invited, - preset = RoomPreset.PRIVATE_CHAT, - invite = config.invites.map { it.userId }, - avatar = avatarUrl, - isSpace = isSpace, - ) + val params = when (config.visibilityState) { + is RoomVisibilityState.Public -> { + CreateRoomParameters( + name = config.roomName, + topic = config.topic, + isEncrypted = false, + isDirect = false, + visibility = RoomVisibility.Public, + joinRuleOverride = config.visibilityState.joinRuleItem.toJoinRule() + // No need to specify the public join rule override, since the preset is already PUBLIC_CHAT + .takeIf { it != JoinRule.Public }, + preset = RoomPreset.PUBLIC_CHAT, + invite = config.invites.map { it.userId }, + avatar = avatarUrl, + roomAliasName = config.visibilityState.roomAddress(), + isSpace = isSpace, + ) + } + is RoomVisibilityState.Private -> { + CreateRoomParameters( + name = config.roomName, + topic = config.topic, + isEncrypted = true, + isDirect = false, + visibility = RoomVisibility.Private, + historyVisibilityOverride = RoomHistoryVisibility.Invited, + joinRuleOverride = config.visibilityState.joinRuleItem.toJoinRule() + // No need to specify the Invite join rule override, since the preset is already PRIVATE_CHAT + .takeIf { it != JoinRule.Invite }, + preset = RoomPreset.PRIVATE_CHAT, + invite = config.invites.map { it.userId }, + avatar = avatarUrl, + isSpace = isSpace, + ) + } } val roomId = matrixClient.createRoom(params) .onFailure { failure -> 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 9e88a7af79..0da931fa51 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 @@ -17,6 +17,7 @@ import io.element.android.libraries.permissions.api.PermissionsState import kotlinx.collections.immutable.ImmutableList data class ConfigureRoomState( + val isSpace: Boolean, val config: CreateRoomConfig, val avatarActions: ImmutableList, val createRoomAction: AsyncAction, @@ -28,5 +29,6 @@ data class ConfigureRoomState( val eventSink: (ConfigureRoomEvents) -> Unit ) { val isValid: Boolean = config.roomName?.isNotEmpty() == true && - (config.visibilityState is RoomVisibilityState.Private || roomAddressValidity == RoomAddressValidity.Valid) + (config.visibilityState is RoomVisibilityState.Private || roomAddressValidity == RoomAddressValidity.Valid) && + config.visibilityState.joinRuleItem in availableJoinRules } 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 68a1f4b43b..9c2ad76a9b 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 @@ -82,8 +82,8 @@ open class ConfigureRoomStateProvider : PreviewParameterProvider = emptyList(), createRoomAction: AsyncAction = AsyncAction.Uninitialized, @@ -134,21 +131,22 @@ fun aConfigureRoomState( roomAddressValidity: RoomAddressValidity = RoomAddressValidity.Valid, availableVisibilityOptions: List = if (config.parentSpace != null) { listOfNotNull( - JoinRuleItem.PublicVisibility.Restricted(config.parentSpace.roomId), - JoinRuleItem.PublicVisibility.AskToJoinRestricted(config.parentSpace.roomId).takeIf { isKnockFeatureEnabled }, - JoinRuleItem.Private, + JoinRuleItem.PrivateVisibility.Restricted(config.parentSpace.roomId), + JoinRuleItem.PrivateVisibility.AskToJoinRestricted(config.parentSpace.roomId).takeIf { isKnockFeatureEnabled }, + JoinRuleItem.PrivateVisibility.Private, ) } else { listOfNotNull( JoinRuleItem.PublicVisibility.Public, JoinRuleItem.PublicVisibility.AskToJoin.takeIf { isKnockFeatureEnabled }, - JoinRuleItem.Private, + JoinRuleItem.PrivateVisibility.Private, ) }, spaces: List = emptyList(), eventSink: (ConfigureRoomEvents) -> Unit = { }, ) = ConfigureRoomState( config = config, + isSpace = isSpace, avatarActions = avatarActions.toImmutableList(), createRoomAction = createRoomAction, cameraPermissionState = cameraPermissionState, 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 4ec707d73f..1ee4bcd2b5 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 @@ -78,7 +78,7 @@ fun ConfigureRoomView( onCreateRoomSuccess: (RoomId) -> Unit, modifier: Modifier = Modifier, ) { - val isSpace = state.config.isSpace + val isSpace = state.isSpace val focusManager = LocalFocusManager.current val isAvatarActionsSheetVisible = remember { mutableStateOf(false) } @@ -122,16 +122,14 @@ fun ConfigureRoomView( topic = state.config.topic.orEmpty(), onTopicChange = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) }, ) - - if (!state.config.isSpace && state.spaces.isNotEmpty()) { - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(16.dp)) + if (!state.isSpace && state.spaces.isNotEmpty()) { SelectParentSpaceOptions( spaces = state.spaces, selectedSpace = state.config.parentSpace, onSelectSpace = { state.eventSink(ConfigureRoomEvents.SetParentSpace(it)) }, ) } - RoomJoinRuleOptions( options = state.availableJoinRules, selected = state.config.visibilityState.joinRuleItem, @@ -141,20 +139,17 @@ fun ConfigureRoomView( state.eventSink(ConfigureRoomEvents.JoinRuleChanged(it)) }, ) - if (state.config.visibilityState !is RoomVisibilityState.Private) { - Column { - ListSectionHeader(title = stringResource(R.string.screen_create_room_room_address_section_title)) - RoomAddressField( - modifier = Modifier.padding(horizontal = 16.dp), - address = state.config.visibilityState.roomAddress().getOrNull().orEmpty(), - homeserverName = state.homeserverName, - addressValidity = state.roomAddressValidity, - onAddressChange = { state.eventSink(ConfigureRoomEvents.RoomAddressChanged(it)) }, - label = null, - supportingText = stringResource(R.string.screen_create_room_room_address_section_footer), - ) - } + ListSectionHeader(title = stringResource(R.string.screen_create_room_room_address_section_title)) + RoomAddressField( + modifier = Modifier.padding(horizontal = 16.dp), + address = state.config.visibilityState.roomAddress().getOrNull().orEmpty(), + homeserverName = state.homeserverName, + addressValidity = state.roomAddressValidity, + onAddressChange = { state.eventSink(ConfigureRoomEvents.RoomAddressChanged(it)) }, + label = null, + supportingText = stringResource(R.string.screen_create_room_room_address_section_footer), + ) } } } @@ -220,7 +215,9 @@ private fun RoomNameWithAvatar( verticalAlignment = Alignment.CenterVertically, ) { Box( - modifier = Modifier.padding(end = 8.dp).size(AvatarSize.EditRoomDetails.dp), + modifier = Modifier + .padding(end = 8.dp) + .size(AvatarSize.EditRoomDetails.dp), contentAlignment = Alignment.Center, ) { val avatarState = remember(avatarUri) { @@ -306,10 +303,10 @@ private fun RoomJoinRuleOptions( size = RoundedIconAtomSize.Big, imageVector = when (item) { JoinRuleItem.PublicVisibility.Public -> CompoundIcons.Public() - is JoinRuleItem.PublicVisibility.Restricted -> CompoundIcons.Space() + is JoinRuleItem.PrivateVisibility.Restricted -> CompoundIcons.Space() JoinRuleItem.PublicVisibility.AskToJoin, - is JoinRuleItem.PublicVisibility.AskToJoinRestricted -> CompoundIcons.UserAdd() - JoinRuleItem.Private -> CompoundIcons.Lock() + is JoinRuleItem.PrivateVisibility.AskToJoinRestricted -> CompoundIcons.UserAdd() + JoinRuleItem.PrivateVisibility.Private -> CompoundIcons.Lock() }, tint = if (isSelected) ElementTheme.colors.iconPrimary else ElementTheme.colors.iconSecondary, backgroundTint = Color.Transparent, @@ -318,28 +315,28 @@ private fun RoomJoinRuleOptions( headlineContent = { val title = when (item) { JoinRuleItem.PublicVisibility.Public -> stringResource(R.string.screen_create_room_room_access_section_public_option_title) - is JoinRuleItem.PublicVisibility.Restricted -> stringResource(R.string.screen_create_room_room_access_section_restricted_option_title) + is JoinRuleItem.PrivateVisibility.Restricted -> stringResource(R.string.screen_create_room_room_access_section_restricted_option_title) JoinRuleItem.PublicVisibility.AskToJoin -> stringResource(R.string.screen_create_room_room_access_section_knocking_option_title) - is JoinRuleItem.PublicVisibility.AskToJoinRestricted -> stringResource( + is JoinRuleItem.PrivateVisibility.AskToJoinRestricted -> stringResource( R.string.screen_create_room_room_access_section_knocking_restricted_option_title ) - JoinRuleItem.Private -> stringResource(R.string.screen_create_room_room_access_section_private_option_title) + JoinRuleItem.PrivateVisibility.Private -> stringResource(R.string.screen_create_room_room_access_section_private_option_title) } Text(text = title) }, supportingContent = { val description = when (item) { JoinRuleItem.PublicVisibility.Public -> stringResource(R.string.screen_create_room_room_access_section_public_option_description) - is JoinRuleItem.PublicVisibility.Restricted -> stringResource( + is JoinRuleItem.PrivateVisibility.Restricted -> stringResource( R.string.screen_create_room_room_access_section_restricted_option_description, parentSpace?.displayName.orEmpty() ) JoinRuleItem.PublicVisibility.AskToJoin -> stringResource(R.string.screen_create_room_room_access_section_knocking_option_description) - is JoinRuleItem.PublicVisibility.AskToJoinRestricted -> stringResource( + is JoinRuleItem.PrivateVisibility.AskToJoinRestricted -> stringResource( R.string.screen_create_room_room_access_section_knocking_restricted_option_description, parentSpace?.displayName.orEmpty() ) - JoinRuleItem.Private -> stringResource(R.string.screen_create_room_room_access_section_private_option_description) + JoinRuleItem.PrivateVisibility.Private -> stringResource(R.string.screen_create_room_room_access_section_private_option_description) } Text(text = description) }, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfig.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfig.kt index dc24db1516..dc9321eb91 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfig.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfig.kt @@ -14,11 +14,10 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf data class CreateRoomConfig( - val isSpace: Boolean = false, val roomName: String? = null, val topic: String? = null, val avatarUri: String? = null, val invites: ImmutableList = persistentListOf(), - val visibilityState: RoomVisibilityState = RoomVisibilityState.Private(), + val visibilityState: RoomVisibilityState = RoomVisibilityState.Private(JoinRuleItem.PrivateVisibility.Private), val parentSpace: SpaceRoom? = null, ) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt index d1d4f22322..f1d2966cd0 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt @@ -72,7 +72,9 @@ class CreateRoomConfigStore( createRoomConfigFlow.getAndUpdate { config -> config.copy( visibilityState = when (joinRule) { - JoinRuleItem.Private -> RoomVisibilityState.Private() + is JoinRuleItem.PrivateVisibility -> RoomVisibilityState.Private( + joinRuleItem = joinRule + ) is JoinRuleItem.PublicVisibility -> { val roomAliasName = roomAliasHelper.roomAliasNameFromRoomDisplayName(config.roomName.orEmpty()) RoomVisibilityState.Public( @@ -99,17 +101,16 @@ class CreateRoomConfigStore( } } - fun setIsSpace(isSpace: Boolean) { - createRoomConfigFlow.getAndUpdate { config -> - config.copy(isSpace = isSpace) - } - } - - fun setParentSpace(parentSpace: SpaceRoom?) { + fun setParentSpace(parentSpace: SpaceRoom?, updateVisibility: Boolean) { createRoomConfigFlow.getAndUpdate { config -> + val visibilityState = if (parentSpace != null && updateVisibility) { + RoomVisibilityState.Private(JoinRuleItem.PrivateVisibility.Restricted(parentSpace.roomId)) + } else { + config.visibilityState + } config.copy( parentSpace = parentSpace, - visibilityState = RoomVisibilityState.Private(), + visibilityState = visibilityState ) } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/JoinRuleItem.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/JoinRuleItem.kt index 3d785fc5c6..72e0e1e501 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/JoinRuleItem.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/JoinRuleItem.kt @@ -18,7 +18,11 @@ import kotlinx.collections.immutable.persistentListOf */ @Immutable sealed interface JoinRuleItem { - data object Private : JoinRuleItem + sealed interface PrivateVisibility : JoinRuleItem { + data object Private : PrivateVisibility + data class Restricted(val parentSpaceId: RoomId) : PrivateVisibility + data class AskToJoinRestricted(val parentSpaceId: RoomId) : PrivateVisibility + } /** * Those join rule items that represent public visibility of the room/space. @@ -27,18 +31,16 @@ sealed interface JoinRuleItem { sealed interface PublicVisibility : JoinRuleItem { data object Public : PublicVisibility data object AskToJoin : PublicVisibility - data class Restricted(val parentSpaceId: RoomId) : PublicVisibility - data class AskToJoinRestricted(val parentSpaceId: RoomId) : PublicVisibility } /** * Transforms a [JoinRuleItem] option into a [JoinRule]. */ fun toJoinRule(): JoinRule = when (this) { - Private -> JoinRule.Invite + PrivateVisibility.Private -> JoinRule.Invite + is PrivateVisibility.Restricted -> JoinRule.Restricted(persistentListOf(AllowRule.RoomMembership(parentSpaceId))) + is PrivateVisibility.AskToJoinRestricted -> JoinRule.KnockRestricted(persistentListOf(AllowRule.RoomMembership(parentSpaceId))) PublicVisibility.Public -> JoinRule.Public PublicVisibility.AskToJoin -> JoinRule.Knock - is PublicVisibility.Restricted -> JoinRule.Restricted(persistentListOf(AllowRule.RoomMembership(parentSpaceId))) - is PublicVisibility.AskToJoinRestricted -> JoinRule.KnockRestricted(persistentListOf(AllowRule.RoomMembership(parentSpaceId))) } } 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 7fd8bd888c..f312fcfa00 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 @@ -12,7 +12,7 @@ import java.util.Optional sealed interface RoomVisibilityState { val joinRuleItem: JoinRuleItem - data class Private(override val joinRuleItem: JoinRuleItem.Private = JoinRuleItem.Private) : RoomVisibilityState + data class Private(override val joinRuleItem: JoinRuleItem.PrivateVisibility) : RoomVisibilityState data class Public( val roomAddress: RoomAddress, diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt index d3150ea517..1016fea46c 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/ConfigureRoomPresenterTest.kt @@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper +import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.test.AN_AVATAR_URL @@ -89,7 +90,7 @@ class ConfigureRoomPresenterTest { assertThat(initialState.config.topic).isNull() assertThat(initialState.config.invites).isEmpty() assertThat(initialState.config.avatarUri).isNull() - assertThat(initialState.config.visibilityState).isEqualTo(RoomVisibilityState.Private()) + assertThat(initialState.config.visibilityState).isEqualTo(RoomVisibilityState.Private(JoinRuleItem.PrivateVisibility.Private)) assertThat(initialState.createRoomAction).isInstanceOf(AsyncAction.Uninitialized::class.java) assertThat(initialState.homeserverName).isEqualTo("matrix.org") } @@ -234,7 +235,8 @@ class ConfigureRoomPresenterTest { matrixClient.givenCreateRoomResult(createRoomResult) - val parentSpace = aSpaceRoom() + // Use a public parent space so AskToJoin is a valid option + val parentSpace = aSpaceRoom(joinRule = JoinRule.Public) initialState.eventSink(ConfigureRoomEvents.SetParentSpace(parentSpace)) assertThat(awaitItem().config.parentSpace).isEqualTo(parentSpace) @@ -275,7 +277,8 @@ class ConfigureRoomPresenterTest { matrixClient.givenCreateRoomResult(createRoomResult) - val parentSpace = aSpaceRoom() + // Use a public parent space so AskToJoin is a valid option + val parentSpace = aSpaceRoom(joinRule = JoinRule.Public) initialState.eventSink(ConfigureRoomEvents.SetParentSpace(parentSpace)) assertThat(awaitItem().config.parentSpace).isEqualTo(parentSpace) @@ -484,16 +487,19 @@ class ConfigureRoomPresenterTest { assertThat(awaitItem().config.visibilityState).isInstanceOf(RoomVisibilityState.Public::class.java) // Then check changing the parent space resets it to private + // (via LaunchedEffect fallback since Public is not in availableJoinRules for non-public parent) initialState.eventSink(ConfigureRoomEvents.SetParentSpace(aSpaceRoom())) - assertThat(awaitItem().config.visibilityState).isEqualTo(RoomVisibilityState.Private()) + skipItems(1) // Skip intermediate state + assertThat(awaitItem().config.visibilityState).isEqualTo(RoomVisibilityState.Private(JoinRuleItem.PrivateVisibility.Private)) // If we change the join rule back to public initialState.eventSink(ConfigureRoomEvents.JoinRuleChanged(JoinRuleItem.PublicVisibility.Public)) - assertThat(awaitItem().config.visibilityState).isInstanceOf(RoomVisibilityState.Public::class.java) + skipItems(1) // Skip intermediate state (Public is still invalid) + assertThat(awaitItem().config.visibilityState).isEqualTo(RoomVisibilityState.Private(JoinRuleItem.PrivateVisibility.Private)) - // Then remove the parent space, it'll be private again + // Then remove the parent space, the join rule stays private initialState.eventSink(ConfigureRoomEvents.SetParentSpace(null)) - assertThat(awaitItem().config.visibilityState).isEqualTo(RoomVisibilityState.Private()) + assertThat(awaitItem().config.visibilityState).isEqualTo(RoomVisibilityState.Private(JoinRuleItem.PrivateVisibility.Private)) } } diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/JoinRuleItemTest.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/JoinRuleItemTest.kt index e16e240dfc..70dfd3b54f 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/JoinRuleItemTest.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/JoinRuleItemTest.kt @@ -18,12 +18,12 @@ import org.junit.Test class JoinRuleItemTest { @Test fun `toJoinRule works as expected`() { - assertThat(JoinRuleItem.Private.toJoinRule()).isEqualTo(JoinRule.Invite) + assertThat(JoinRuleItem.PrivateVisibility.Private.toJoinRule()).isEqualTo(JoinRule.Invite) assertThat(JoinRuleItem.PublicVisibility.Public.toJoinRule()).isEqualTo(JoinRule.Public) assertThat(JoinRuleItem.PublicVisibility.AskToJoin.toJoinRule()).isEqualTo(JoinRule.Knock) - assertThat(JoinRuleItem.PublicVisibility.Restricted(A_ROOM_ID).toJoinRule()) + assertThat(JoinRuleItem.PrivateVisibility.Restricted(A_ROOM_ID).toJoinRule()) .isEqualTo(JoinRule.Restricted(persistentListOf(AllowRule.RoomMembership(A_ROOM_ID)))) - assertThat(JoinRuleItem.PublicVisibility.AskToJoinRestricted(A_ROOM_ID).toJoinRule()) + assertThat(JoinRuleItem.PrivateVisibility.AskToJoinRestricted(A_ROOM_ID).toJoinRule()) .isEqualTo(JoinRule.KnockRestricted(persistentListOf(AllowRule.RoomMembership(A_ROOM_ID)))) } }