Take into account homeserver capabilities (#6507)

* Take into account homeserver capabilities: add `HomeserverCapabilitiesProvider` to check if the HS allows changing the user's display name or avatar. Also, modify the edit user profile screen to reflect these values.

* Add `/myavatar` command. Filter both `/nick` and `/myavatar` commands based on the homeserver capabilities.

* Update screenshots

* Assume the use can change their display name and avatar url if the capabilities check fails: if they try to change those, the HS will return an error anyway.

* Disable also `/myroomname` and `/myroomavatar` based on the HS capabilities.

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa 2026-04-15 14:29:41 +02:00 committed by GitHub
parent 80470b3792
commit 66513bc905
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 363 additions and 14 deletions

View file

@ -15,6 +15,7 @@ import androidx.compose.runtime.MutableState
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.saveable.rememberSaveable
@ -103,6 +104,14 @@ class EditUserProfilePresenter(
}
}
val homeserverCapabilities = matrixClient.homeserverCapabilities()
val canChangeDisplayName = produceState(true) {
value = homeserverCapabilities.canChangeDisplayName().getOrDefault(true)
}
val canChangeAvatar = produceState(true) {
value = homeserverCapabilities.canChangeAvatarUrl().getOrDefault(true)
}
val saveAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val localCoroutineScope = rememberCoroutineScope()
@ -169,6 +178,8 @@ class EditUserProfilePresenter(
saveButtonEnabled = canSave && saveAction.value !is AsyncAction.Loading,
saveAction = saveAction.value,
cameraPermissionState = cameraPermissionState,
canChangeDisplayName = canChangeDisplayName.value,
canChangeAvatarUrl = canChangeAvatar.value,
eventSink = ::handleEvent,
)
}

View file

@ -22,5 +22,7 @@ data class EditUserProfileState(
val saveButtonEnabled: Boolean,
val saveAction: AsyncAction<Unit>,
val cameraPermissionState: PermissionsState,
val canChangeDisplayName: Boolean,
val canChangeAvatarUrl: Boolean,
val eventSink: (EditUserProfileEvent) -> Unit
)

View file

@ -22,6 +22,7 @@ open class EditUserProfileStateProvider : PreviewParameterProvider<EditUserProfi
aEditUserProfileState(),
aEditUserProfileState(userAvatarUrl = "example://uri"),
aEditUserProfileState(saveAction = AsyncAction.ConfirmingCancellation),
aEditUserProfileState(canChangeAvatarUrl = false, canChangeDisplayName = false),
)
}
@ -33,6 +34,8 @@ fun aEditUserProfileState(
saveButtonEnabled: Boolean = true,
saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
cameraPermissionState: PermissionsState = aPermissionsState(showDialog = false),
canChangeDisplayName: Boolean = true,
canChangeAvatarUrl: Boolean = true,
eventSink: (EditUserProfileEvent) -> Unit = {},
) = EditUserProfileState(
userId = userId,
@ -42,5 +45,7 @@ fun aEditUserProfileState(
saveButtonEnabled = saveButtonEnabled,
saveAction = saveAction,
cameraPermissionState = cameraPermissionState,
canChangeDisplayName = canChangeDisplayName,
canChangeAvatarUrl = canChangeAvatarUrl,
eventSink = eventSink,
)

View file

@ -120,6 +120,7 @@ fun EditUserProfileView(
state = avatarPickerState,
onClick = ::onAvatarClick,
modifier = Modifier.align(Alignment.CenterHorizontally),
enabled = state.canChangeAvatarUrl,
)
Spacer(modifier = Modifier.height(16.dp))
Text(
@ -134,6 +135,7 @@ fun EditUserProfileView(
value = state.displayName,
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
singleLine = true,
enabled = state.canChangeDisplayName,
onValueChange = { state.eventSink(EditUserProfileEvent.UpdateDisplayName(it)) },
)
}