feat(security&privacy) : clean code

This commit is contained in:
ganfra 2025-01-28 14:39:27 +01:00
parent 876d06f510
commit d992f38fa5
17 changed files with 35 additions and 46 deletions

View file

@ -11,9 +11,9 @@ sealed interface SecurityAndPrivacyEvents {
data object EditRoomAddress : SecurityAndPrivacyEvents
data object Save : SecurityAndPrivacyEvents
data class ChangeRoomAccess(val roomAccess: SecurityAndPrivacyRoomAccess) : SecurityAndPrivacyEvents
data object ToggleEncryptionState: SecurityAndPrivacyEvents
data object ToggleEncryptionState : SecurityAndPrivacyEvents
data object CancelEnableEncryption : SecurityAndPrivacyEvents
data object ConfirmEnableEncryption: SecurityAndPrivacyEvents
data object ConfirmEnableEncryption : SecurityAndPrivacyEvents
data class ChangeHistoryVisibility(val historyVisibility: SecurityAndPrivacyHistoryVisibility) : SecurityAndPrivacyEvents
data object ToggleRoomVisibility : SecurityAndPrivacyEvents
data object DismissSaveError : SecurityAndPrivacyEvents

View file

@ -36,7 +36,6 @@ class SecurityAndPrivacyFlowNode @AssistedInject constructor(
buildContext = buildContext,
plugins = plugins,
) {
sealed interface NavTarget : Parcelable {
@Parcelize
data object SecurityAndPrivacy : NavTarget

View file

@ -24,7 +24,6 @@ class SecurityAndPrivacyNode @AssistedInject constructor(
@Assisted plugins: List<Plugin>,
presenterFactory: SecurityAndPrivacyPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
private val navigator = plugins<SecurityAndPrivacyNavigator>().first()
private val presenter = presenterFactory.create(navigator)

View file

@ -60,7 +60,9 @@ class SecurityAndPrivacyPresenter @AssistedInject constructor(
val roomInfo by room.roomInfoFlow.collectAsState(null)
val savedIsVisibleInRoomDirectory = remember { mutableStateOf<AsyncData<Boolean>>(AsyncData.Uninitialized) }
IsRoomVisibleInRoomDirectoryEffect(savedIsVisibleInRoomDirectory)
LaunchedEffect(Unit) {
isRoomVisibleInRoomDirectory(savedIsVisibleInRoomDirectory)
}
val savedSettings by remember {
derivedStateOf {
@ -159,12 +161,9 @@ class SecurityAndPrivacyPresenter @AssistedInject constructor(
return state
}
@Composable
private fun IsRoomVisibleInRoomDirectoryEffect(isRoomVisible: MutableState<AsyncData<Boolean>>) {
LaunchedEffect(Unit) {
isRoomVisible.runUpdatingState {
room.getRoomVisibility().map { it == RoomVisibility.Public }
}
private fun CoroutineScope.isRoomVisibleInRoomDirectory(isRoomVisible: MutableState<AsyncData<Boolean>>) = launch {
isRoomVisible.runUpdatingState {
room.getRoomVisibility().map { it == RoomVisibility.Public }
}
}
@ -264,7 +263,6 @@ private fun RoomHistoryVisibility?.map(): SecurityAndPrivacyHistoryVisibility {
RoomHistoryVisibility.Shared,
is RoomHistoryVisibility.Custom,
null -> SecurityAndPrivacyHistoryVisibility.SinceSelection
}
}
@ -279,4 +277,3 @@ private fun SecurityAndPrivacyHistoryVisibility.map(): RoomHistoryVisibility {
private fun MatrixRoomInfo.firstDisplayableAlias(serverName: String): RoomAlias? {
return aliases.firstOrNull { it.matchesServer(serverName) } ?: aliases.firstOrNull()
}

View file

@ -10,6 +10,7 @@ package io.element.android.features.roomdetails.impl.securityandprivacy
import io.element.android.features.roomdetails.impl.securityandprivacy.permissions.SecurityAndPrivacyPermissions
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData
import kotlinx.collections.immutable.toImmutableSet
data class SecurityAndPrivacyState(
// the settings that are currently applied on the room.
@ -22,9 +23,6 @@ data class SecurityAndPrivacyState(
private val permissions: SecurityAndPrivacyPermissions,
val eventSink: (SecurityAndPrivacyEvents) -> Unit
) {
val canBeSaved = savedSettings != editedSettings
val availableHistoryVisibilities = buildSet {
@ -34,15 +32,12 @@ data class SecurityAndPrivacyState(
} else {
add(SecurityAndPrivacyHistoryVisibility.SinceInvite)
}
}
}.toImmutableSet()
val showRoomAccessSection = permissions.canChangeRoomAccess
val showRoomVisibilitySections = permissions.canChangeRoomVisibility && editedSettings.roomAccess != SecurityAndPrivacyRoomAccess.InviteOnly
val showHistoryVisibilitySection = permissions.canChangeHistoryVisibility
val showEncryptionSection = permissions.canChangeEncryption
override fun toString(): String {
return "SecurityAndPrivacyState(savedSettings=$savedSettings, editedSettings=$editedSettings, homeserverName='$homeserverName', showEncryptionConfirmation=$showEncryptionConfirmation, saveAction=$saveAction, canBeSaved=$canBeSaved)"
}
}
data class SecurityAndPrivacySettings(
@ -54,7 +49,9 @@ data class SecurityAndPrivacySettings(
)
enum class SecurityAndPrivacyHistoryVisibility {
SinceSelection, SinceInvite, Anyone;
SinceSelection,
SinceInvite,
Anyone;
/**
* Returns the fallback visibility when the current visibility is not available.
@ -69,7 +66,10 @@ enum class SecurityAndPrivacyHistoryVisibility {
}
enum class SecurityAndPrivacyRoomAccess {
InviteOnly, AskToJoin, Anyone, SpaceMember
InviteOnly,
AskToJoin,
Anyone,
SpaceMember
}
sealed class SecurityAndPrivacyFailures : Exception() {

View file

@ -49,6 +49,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableSet
@Composable
fun SecurityAndPrivacyView(
@ -81,7 +82,7 @@ fun SecurityAndPrivacyView(
modifier = Modifier.padding(top = 24.dp),
edited = state.editedSettings.roomAccess,
saved = state.savedSettings.roomAccess,
onSelected = { state.eventSink(SecurityAndPrivacyEvents.ChangeRoomAccess(it)) },
onSelectOption = { state.eventSink(SecurityAndPrivacyEvents.ChangeRoomAccess(it)) },
)
}
if (state.showRoomVisibilitySections) {
@ -111,7 +112,7 @@ fun SecurityAndPrivacyView(
editedOption = state.editedSettings.historyVisibility,
savedOptions = state.savedSettings.historyVisibility,
availableOptions = state.availableHistoryVisibilities,
onSelected = { state.eventSink(SecurityAndPrivacyEvents.ChangeHistoryVisibility(it)) },
onSelectOption = { state.eventSink(SecurityAndPrivacyEvents.ChangeHistoryVisibility(it)) },
)
}
}
@ -180,7 +181,7 @@ private fun SecurityAndPrivacySection(
private fun RoomAccessSection(
edited: SecurityAndPrivacyRoomAccess,
saved: SecurityAndPrivacyRoomAccess,
onSelected: (SecurityAndPrivacyRoomAccess) -> Unit,
onSelectOption: (SecurityAndPrivacyRoomAccess) -> Unit,
modifier: Modifier = Modifier,
) {
SecurityAndPrivacySection(
@ -191,19 +192,19 @@ private fun RoomAccessSection(
headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_invite_only_option_title)) },
supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_invite_only_option_description)) },
trailingContent = ListItemContent.RadioButton(selected = edited == SecurityAndPrivacyRoomAccess.InviteOnly),
onClick = { onSelected(SecurityAndPrivacyRoomAccess.InviteOnly) },
onClick = { onSelectOption(SecurityAndPrivacyRoomAccess.InviteOnly) },
)
ListItem(
headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_ask_to_join_option_title)) },
supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_ask_to_join_option_description)) },
trailingContent = ListItemContent.RadioButton(selected = edited == SecurityAndPrivacyRoomAccess.AskToJoin),
onClick = { onSelected(SecurityAndPrivacyRoomAccess.AskToJoin) },
onClick = { onSelectOption(SecurityAndPrivacyRoomAccess.AskToJoin) },
)
ListItem(
headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_anyone_option_title)) },
supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_anyone_option_description)) },
trailingContent = ListItemContent.RadioButton(selected = edited == SecurityAndPrivacyRoomAccess.Anyone),
onClick = { onSelected(SecurityAndPrivacyRoomAccess.Anyone) },
onClick = { onSelectOption(SecurityAndPrivacyRoomAccess.Anyone) },
)
if (saved == SecurityAndPrivacyRoomAccess.SpaceMember) {
ListItem(
@ -333,8 +334,8 @@ private fun EncryptionSection(
private fun HistoryVisibilitySection(
editedOption: SecurityAndPrivacyHistoryVisibility?,
savedOptions: SecurityAndPrivacyHistoryVisibility?,
availableOptions: Set<SecurityAndPrivacyHistoryVisibility>,
onSelected: (SecurityAndPrivacyHistoryVisibility) -> Unit,
availableOptions: ImmutableSet<SecurityAndPrivacyHistoryVisibility>,
onSelectOption: (SecurityAndPrivacyHistoryVisibility) -> Unit,
modifier: Modifier = Modifier,
) {
SecurityAndPrivacySection(
@ -347,7 +348,7 @@ private fun HistoryVisibilitySection(
HistoryVisibilityItem(
option = availableOption,
isSelected = isSelected,
onSelected = onSelected,
onSelectOption = onSelectOption,
)
}
if (savedOptions != null && !availableOptions.contains(savedOptions)) {
@ -355,7 +356,7 @@ private fun HistoryVisibilitySection(
option = savedOptions,
isSelected = true,
isEnabled = false,
onSelected = {},
onSelectOption = {},
)
}
}
@ -365,7 +366,7 @@ private fun HistoryVisibilitySection(
private fun HistoryVisibilityItem(
option: SecurityAndPrivacyHistoryVisibility,
isSelected: Boolean,
onSelected: (SecurityAndPrivacyHistoryVisibility) -> Unit,
onSelectOption: (SecurityAndPrivacyHistoryVisibility) -> Unit,
modifier: Modifier = Modifier,
isEnabled: Boolean = true,
) {
@ -377,7 +378,7 @@ private fun HistoryVisibilityItem(
ListItem(
headlineContent = { Text(text = headlineText) },
trailingContent = ListItemContent.RadioButton(selected = isSelected, enabled = isEnabled),
onClick = { onSelected(option) },
onClick = { onSelectOption(option) },
enabled = isEnabled,
modifier = modifier,
)
@ -401,4 +402,3 @@ private fun ContentToPreview(state: SecurityAndPrivacyState) {
onBackClick = {},
)
}

View file

@ -25,7 +25,6 @@ class EditRoomAddressNode @AssistedInject constructor(
@Assisted plugins: List<Plugin>,
presenterFactory: EditRoomAddressPresenter.Factory,
) : Node(buildContext, plugins = plugins) {
private val navigator = plugins<SecurityAndPrivacyNavigator>().first()
private val presenter = presenterFactory.create(navigator)

View file

@ -86,7 +86,6 @@ fun EditRoomAddressView(
onRetry = { state.eventSink(EditRoomAddressEvents.Save) },
onErrorDismiss = { state.eventSink(EditRoomAddressEvents.DismissError) },
)
}
}

View file

@ -47,4 +47,3 @@ fun MatrixRoom.securityAndPrivacyPermissionsAsState(updateKey: Long): State<Secu
)
}
}

View file

@ -30,7 +30,6 @@ import kotlinx.coroutines.test.runTest
import org.junit.Test
class SecurityAndPrivacyPresenterTest {
@Test
fun `present - initial states`() = runTest {
val presenter = createSecurityAndPrivacyPresenter()

View file

@ -31,7 +31,6 @@ import org.junit.Test
import java.util.Optional
class EditRoomAddressPresenterTest {
@Test
fun `present - initial state no address`() = runTest {
val presenter = createEditRoomAddressPresenter()

View file

@ -10,7 +10,6 @@ package io.element.android.features.roomdetails.securityandprivacy.editroomaddre
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTextInput
import androidx.test.ext.junit.runners.AndroidJUnit4
@ -104,8 +103,6 @@ class EditRoomAddressViewTest {
rule.clickOn(CommonStrings.action_retry)
recorder.assertSingle(EditRoomAddressEvents.Save)
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setEditRoomAddressView(

View file

@ -433,6 +433,7 @@ interface MatrixRoom : Closeable {
* directory and can be found using it.
*/
suspend fun getRoomVisibility(): Result<RoomVisibility>
/**
* Publish a new room alias for this room in the room directory.
*
@ -442,6 +443,7 @@ interface MatrixRoom : Closeable {
* published.
*/
suspend fun publishRoomAliasInRoomDirectory(roomAlias: RoomAlias): Result<Boolean>
/**
* Remove an existing room alias for this room in the room directory.
*

View file

@ -104,6 +104,7 @@ import org.matrix.rustcomponents.sdk.KnockRequest as InnerKnockRequest
import org.matrix.rustcomponents.sdk.Room as InnerRoom
import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline
@Suppress("LargeClass")
class RustMatrixRoom(
override val sessionId: SessionId,
private val deviceId: DeviceId,

View file

@ -34,8 +34,8 @@ import kotlinx.collections.immutable.toPersistentList
import org.junit.Test
import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
class MatrixRoomInfoMapperTest {
@Test

View file

@ -64,7 +64,7 @@ fun RoomAddressField(
@PreviewsDayNight
@Composable
fun RoomAddressFieldPreview() = ElementPreview {
internal fun RoomAddressFieldPreview() = ElementPreview {
RoomAddressField(
address = "room",
homeserverName = "element.io",

View file

@ -117,5 +117,4 @@ object TestTags {
*
*/
val roomAddressField = TestTag("room_address_field")
}