Add a hook to disable public rooms/spaces on UI.

This commit is contained in:
mxandreas
2026-10-05 09:30:01 +03:00
parent a6d9d27c68
commit 84fdbbe573
11 changed files with 130 additions and 13 deletions
@@ -16,6 +16,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
@@ -92,6 +93,9 @@ class ConfigureRoomPresenter(
val isKnockFeatureEnabled by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock)
}.collectAsState(initial = false)
val arePublicRoomsDisabled by produceState(false) {
value = sessionEnterpriseService.arePublicRoomsDisabledByHomeserver()
}
val roomAddressValidity = remember {
mutableStateOf<RoomAddressValidity>(RoomAddressValidity.Unknown)
}
@@ -145,12 +149,13 @@ class ConfigureRoomPresenter(
// 1. If we are creating a space.
// 2. If it has a parent space.
// 3. If knocking is enabled.
// 4. If the homeserver forbids public rooms.
val parentSpace = createRoomConfig.parentSpace
val availableJoinRules = remember(parentSpace, isSpace, isKnockFeatureEnabled) {
val availableJoinRules = remember(parentSpace, isSpace, isKnockFeatureEnabled, arePublicRoomsDisabled) {
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.Public.takeIf { !arePublicRoomsDisabled },
JoinRuleItem.PublicVisibility.AskToJoin.takeIf { !isSpace && isKnockFeatureEnabled },
JoinRuleItem.PrivateVisibility.Private,
).toImmutableList()
@@ -57,6 +57,7 @@ import io.element.android.libraries.previewutils.room.aSpaceRoom
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.matching
import io.element.android.tests.testutils.robolectric.RobolectricTest
@@ -522,7 +523,10 @@ class ConfigureRoomPresenterTest : RobolectricTest() {
@Test
fun `present - creating a private room when encryption is disabled by the HS creates it unencrypted`() = runTest {
val sessionEnterpriseService = FakeSessionEnterpriseService(isEncryptionDisabledResult = { true })
val sessionEnterpriseService = FakeSessionEnterpriseService(
isEncryptionDisabledResult = { true },
arePublicRoomsDisabledResult = { false },
)
val createRoomLambda = lambdaRecorder<CreateRoomParameters, Result<RoomId>> { Result.success(A_ROOM_ID) }
val matrixClient = createMatrixClient().apply {
createRoomResult = createRoomLambda
@@ -544,6 +548,38 @@ class ConfigureRoomPresenterTest : RobolectricTest() {
}
}
@Test
fun `present - when public rooms are disabled by the HS, the public join rule is not available`() = runTest {
val presenter = createConfigureRoomPresenter(
sessionEnterpriseService = FakeSessionEnterpriseService(
isEncryptionDisabledResult = { false },
arePublicRoomsDisabledResult = { true },
),
)
presenter.test {
val expectedJoinRules = listOf(JoinRuleItem.PublicVisibility.AskToJoin, JoinRuleItem.PrivateVisibility.Private)
val state = consumeItemsUntilPredicate { it.availableJoinRules == expectedJoinRules }.last()
assertThat(state.availableJoinRules).containsExactlyElementsIn(expectedJoinRules).inOrder()
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - when public rooms are disabled by the HS, only the private join rule is available for a space`() = runTest {
val presenter = createConfigureRoomPresenter(
isSpace = true,
sessionEnterpriseService = FakeSessionEnterpriseService(
isEncryptionDisabledResult = { false },
arePublicRoomsDisabledResult = { true },
),
)
presenter.test {
val state = consumeItemsUntilPredicate { it.availableJoinRules == listOf(JoinRuleItem.PrivateVisibility.Private) }.last()
assertThat(state.config.visibilityState).isEqualTo(RoomVisibilityState.Private(JoinRuleItem.PrivateVisibility.Private))
cancelAndIgnoreRemainingEvents()
}
}
private suspend fun TurbineTestContext<ConfigureRoomState>.initialState(): ConfigureRoomState {
skipItems(1)
return awaitItem()
@@ -579,7 +615,10 @@ class ConfigureRoomPresenterTest : RobolectricTest() {
permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(),
isKnockFeatureEnabled: Boolean = true,
mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(),
sessionEnterpriseService: FakeSessionEnterpriseService = FakeSessionEnterpriseService(isEncryptionDisabledResult = { false }),
sessionEnterpriseService: FakeSessionEnterpriseService = FakeSessionEnterpriseService(
isEncryptionDisabledResult = { false },
arePublicRoomsDisabledResult = { false },
),
) = ConfigureRoomPresenter(
isSpace = isSpace,
initialParentSpaceId = initialParenSpaceId,