feat(security&privacy) : start handling edition of room address
This commit is contained in:
parent
8406840169
commit
e56fe4fb38
6 changed files with 160 additions and 15 deletions
|
|
@ -9,4 +9,5 @@ package io.element.android.features.roomdetails.impl.securityandprivacy.editroom
|
||||||
|
|
||||||
sealed interface EditRoomAddressEvents {
|
sealed interface EditRoomAddressEvents {
|
||||||
data object Save : EditRoomAddressEvents
|
data object Save : EditRoomAddressEvents
|
||||||
|
data class RoomAddressChanged(val roomAddress: String) : EditRoomAddressEvents
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ class EditRoomAddressNode @AssistedInject constructor(
|
||||||
val state = presenter.present()
|
val state = presenter.present()
|
||||||
EditRoomAddressView(
|
EditRoomAddressView(
|
||||||
state = state,
|
state = state,
|
||||||
|
onBackClick = ::navigateUp,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,22 +8,80 @@
|
||||||
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||||
|
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||||
|
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidityEffect
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class EditRoomAddressPresenter @Inject constructor() : Presenter<EditRoomAddressState> {
|
class EditRoomAddressPresenter @Inject constructor(
|
||||||
|
private val client: MatrixClient,
|
||||||
|
private val room: MatrixRoom,
|
||||||
|
private val roomAliasHelper: RoomAliasHelper,
|
||||||
|
) : Presenter<EditRoomAddressState> {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): EditRoomAddressState {
|
override fun present(): EditRoomAddressState {
|
||||||
|
val homeserverName = remember { client.userIdServerName() }
|
||||||
|
val roomAddressValidity = remember {
|
||||||
|
mutableStateOf<RoomAddressValidity>(RoomAddressValidity.Unknown)
|
||||||
|
}
|
||||||
|
val savedRoomAddress = remember {
|
||||||
|
room.firstAliasMatching(homeserverName)?.roomAddress()
|
||||||
|
}
|
||||||
|
var currentRoomAddress by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
savedRoomAddress ?: roomAliasHelper.roomAliasNameFromRoomDisplayName(room.displayName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun handleEvents(event: EditRoomAddressEvents) {
|
fun handleEvents(event: EditRoomAddressEvents) {
|
||||||
when (event) {
|
when (event) {
|
||||||
EditRoomAddressEvents.Save -> Unit
|
EditRoomAddressEvents.Save -> Unit
|
||||||
|
is EditRoomAddressEvents.RoomAddressChanged -> {
|
||||||
|
currentRoomAddress = event.roomAddress
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RoomAddressValidityEffect(
|
||||||
|
client = client,
|
||||||
|
roomAliasHelper = roomAliasHelper,
|
||||||
|
newRoomAddress = currentRoomAddress,
|
||||||
|
knownRoomAddress = savedRoomAddress
|
||||||
|
) { newRoomAddressValidity ->
|
||||||
|
roomAddressValidity.value = newRoomAddressValidity
|
||||||
|
}
|
||||||
|
|
||||||
return EditRoomAddressState(
|
return EditRoomAddressState(
|
||||||
|
homeserverName = homeserverName,
|
||||||
|
roomAddressValidity = roomAddressValidity.value,
|
||||||
|
roomAddress = currentRoomAddress,
|
||||||
eventSink = ::handleEvents
|
eventSink = ::handleEvents
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MatrixRoom.firstAliasMatching(serverName: String): RoomAlias? {
|
||||||
|
// Check if the canonical alias matches the homeserver
|
||||||
|
if (this.alias?.matchesServer(serverName) == true) {
|
||||||
|
return this.alias
|
||||||
|
}
|
||||||
|
return this.alternativeAliases.firstOrNull { it.value.contains(serverName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RoomAlias.roomAddress(): String {
|
||||||
|
return value.drop(1).split(":").first()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RoomAlias.matchesServer(serverName: String): Boolean {
|
||||||
|
return value.contains(serverName)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,13 @@
|
||||||
|
|
||||||
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||||
|
|
||||||
data class EditRoomAddressState(
|
data class EditRoomAddressState(
|
||||||
|
val homeserverName: String,
|
||||||
|
val roomAddress: String,
|
||||||
|
val roomAddressValidity: RoomAddressValidity,
|
||||||
val eventSink: (EditRoomAddressEvents) -> Unit
|
val eventSink: (EditRoomAddressEvents) -> Unit
|
||||||
)
|
) {
|
||||||
|
val canBeSaved = roomAddressValidity == RoomAddressValidity.Valid
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
|
||||||
|
|
||||||
open class EditRoomAddressStateProvider : PreviewParameterProvider<EditRoomAddressState> {
|
open class EditRoomAddressStateProvider : PreviewParameterProvider<EditRoomAddressState> {
|
||||||
override val values: Sequence<EditRoomAddressState>
|
override val values: Sequence<EditRoomAddressState>
|
||||||
|
|
@ -17,6 +18,14 @@ open class EditRoomAddressStateProvider : PreviewParameterProvider<EditRoomAddre
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun aEditRoomAddressState() = EditRoomAddressState(
|
fun aEditRoomAddressState(
|
||||||
eventSink = {}
|
roomAddress: String = "therapy",
|
||||||
|
roomAddressValidity: RoomAddressValidity = RoomAddressValidity.Unknown,
|
||||||
|
homeserverName: String = ":myserver.org",
|
||||||
|
eventSink: (EditRoomAddressEvents) -> Unit = {}
|
||||||
|
) = EditRoomAddressState(
|
||||||
|
roomAddress = roomAddress,
|
||||||
|
roomAddressValidity = roomAddressValidity,
|
||||||
|
homeserverName = homeserverName,
|
||||||
|
eventSink = eventSink
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,32 +8,100 @@
|
||||||
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
package io.element.android.features.roomdetails.impl.securityandprivacy.editroomaddress
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.imePadding
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.element.android.compound.theme.ElementTheme
|
||||||
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
|
import io.element.android.libraries.matrix.ui.room.address.RoomAddressField
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EditRoomAddressView(
|
fun EditRoomAddressView(
|
||||||
state: EditRoomAddressState,
|
state: EditRoomAddressState,
|
||||||
|
onBackClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Box(
|
Scaffold(
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier,
|
||||||
contentAlignment = Alignment.Center
|
topBar = {
|
||||||
) {
|
EditRoomAddressTopBar(
|
||||||
Text(
|
isSaveActionEnabled = state.canBeSaved,
|
||||||
"EditRoomAddress feature view",
|
onBackClick = onBackClick,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
onSaveClick = {
|
||||||
)
|
state.eventSink(EditRoomAddressEvents.Save)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { padding ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(padding)
|
||||||
|
.imePadding()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.consumeWindowInsets(padding)
|
||||||
|
) {
|
||||||
|
RoomAddressField(
|
||||||
|
address = state.roomAddress,
|
||||||
|
homeserverName = state.homeserverName,
|
||||||
|
addressValidity = state.roomAddressValidity,
|
||||||
|
onAddressChange = {
|
||||||
|
state.eventSink(EditRoomAddressEvents.RoomAddressChanged(it))
|
||||||
|
},
|
||||||
|
label = stringResource(CommonStrings.screen_edit_room_address_title),
|
||||||
|
supportingText = stringResource(CommonStrings.screen_edit_room_address_room_address_section_footer),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(all = 16.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
private fun EditRoomAddressTopBar(
|
||||||
|
isSaveActionEnabled: Boolean,
|
||||||
|
onBackClick: () -> Unit,
|
||||||
|
onSaveClick: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
TopAppBar(
|
||||||
|
modifier = modifier,
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(CommonStrings.screen_edit_room_address_title),
|
||||||
|
style = ElementTheme.typography.aliasScreenTitle,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||||
|
actions = {
|
||||||
|
TextButton(
|
||||||
|
text = stringResource(CommonStrings.action_save),
|
||||||
|
enabled = isSaveActionEnabled,
|
||||||
|
onClick = onSaveClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun EditRoomAddressViewPreview(
|
internal fun EditRoomAddressViewPreview(
|
||||||
|
|
@ -41,5 +109,6 @@ internal fun EditRoomAddressViewPreview(
|
||||||
) = ElementPreview {
|
) = ElementPreview {
|
||||||
EditRoomAddressView(
|
EditRoomAddressView(
|
||||||
state = state,
|
state = state,
|
||||||
|
onBackClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue