change(room permissions): support space management

This commit is contained in:
ganfra 2025-12-10 15:16:00 +01:00
parent 9621480ceb
commit 03dd89a77f
12 changed files with 48 additions and 28 deletions

View file

@ -34,8 +34,8 @@ internal fun AnalyticsService.trackPermissionChangeAnalytics(initial: RoomPowerL
if (updated.kick != initial?.kick) { if (updated.kick != initial?.kick) {
capture(RoomModeration(RoomModeration.Action.ChangePermissionsKickMembers, analyticsMemberRoleForPowerLevel(updated.kick))) capture(RoomModeration(RoomModeration.Action.ChangePermissionsKickMembers, analyticsMemberRoleForPowerLevel(updated.kick)))
} }
if (updated.sendEvents != initial?.sendEvents) { if (updated.eventsDefault != initial?.eventsDefault) {
capture(RoomModeration(RoomModeration.Action.ChangePermissionsSendMessages, analyticsMemberRoleForPowerLevel(updated.sendEvents))) capture(RoomModeration(RoomModeration.Action.ChangePermissionsSendMessages, analyticsMemberRoleForPowerLevel(updated.eventsDefault)))
} }
if (updated.redactEvents != initial?.redactEvents) { if (updated.redactEvents != initial?.redactEvents) {
capture(RoomModeration(RoomModeration.Action.ChangePermissionsRedactMessages, analyticsMemberRoleForPowerLevel(updated.redactEvents))) capture(RoomModeration(RoomModeration.Action.ChangePermissionsRedactMessages, analyticsMemberRoleForPowerLevel(updated.redactEvents)))

View file

@ -36,8 +36,7 @@ class ChangeRoomPermissionsPresenter(
) : Presenter<ChangeRoomPermissionsState> { ) : Presenter<ChangeRoomPermissionsState> {
companion object { companion object {
private fun itemsForSection(section: RoomPermissionsSection) = when (section) { private fun itemsForSection(section: RoomPermissionsSection) = when (section) {
RoomPermissionsSection.SpaceDetails, RoomPermissionsSection.EditDetails -> persistentListOf(
RoomPermissionsSection.RoomDetails -> persistentListOf(
RoomPermissionType.ROOM_NAME, RoomPermissionType.ROOM_NAME,
RoomPermissionType.ROOM_AVATAR, RoomPermissionType.ROOM_AVATAR,
RoomPermissionType.ROOM_TOPIC, RoomPermissionType.ROOM_TOPIC,
@ -51,14 +50,19 @@ class ChangeRoomPermissionsPresenter(
RoomPermissionType.KICK, RoomPermissionType.KICK,
RoomPermissionType.BAN, RoomPermissionType.BAN,
) )
RoomPermissionsSection.ManageSpace -> persistentListOf(
RoomPermissionType.SPACE_MANAGE_ROOMS,
RoomPermissionType.CHANGE_SETTINGS,
)
} }
private fun RoomPermissionsSection.shouldShow(isSpace: Boolean): Boolean { private fun RoomPermissionsSection.shouldShow(isSpace: Boolean): Boolean {
return when (this) { return when (this) {
RoomPermissionsSection.RoomDetails -> !isSpace RoomPermissionsSection.EditDetails -> true
RoomPermissionsSection.MembershipModeration -> true RoomPermissionsSection.MembershipModeration -> true
RoomPermissionsSection.MessagesAndContent -> !isSpace RoomPermissionsSection.MessagesAndContent -> !isSpace
RoomPermissionsSection.SpaceDetails -> isSpace RoomPermissionsSection.ManageSpace -> isSpace
} }
} }
@ -99,11 +103,13 @@ class ChangeRoomPermissionsPresenter(
RoomPermissionType.BAN -> currentPermissions?.copy(ban = powerLevel) RoomPermissionType.BAN -> currentPermissions?.copy(ban = powerLevel)
RoomPermissionType.INVITE -> currentPermissions?.copy(invite = powerLevel) RoomPermissionType.INVITE -> currentPermissions?.copy(invite = powerLevel)
RoomPermissionType.KICK -> currentPermissions?.copy(kick = powerLevel) RoomPermissionType.KICK -> currentPermissions?.copy(kick = powerLevel)
RoomPermissionType.SEND_EVENTS -> currentPermissions?.copy(sendEvents = powerLevel) RoomPermissionType.SEND_EVENTS -> currentPermissions?.copy(eventsDefault = powerLevel)
RoomPermissionType.REDACT_EVENTS -> currentPermissions?.copy(redactEvents = powerLevel) RoomPermissionType.REDACT_EVENTS -> currentPermissions?.copy(redactEvents = powerLevel)
RoomPermissionType.ROOM_NAME -> currentPermissions?.copy(roomName = powerLevel) RoomPermissionType.ROOM_NAME -> currentPermissions?.copy(roomName = powerLevel)
RoomPermissionType.ROOM_AVATAR -> currentPermissions?.copy(roomAvatar = powerLevel) RoomPermissionType.ROOM_AVATAR -> currentPermissions?.copy(roomAvatar = powerLevel)
RoomPermissionType.ROOM_TOPIC -> currentPermissions?.copy(roomTopic = powerLevel) RoomPermissionType.ROOM_TOPIC -> currentPermissions?.copy(roomTopic = powerLevel)
RoomPermissionType.SPACE_MANAGE_ROOMS -> currentPermissions?.copy(spaceChild = powerLevel)
RoomPermissionType.CHANGE_SETTINGS -> currentPermissions?.copy(stateDefault = powerLevel)
} }
} }
is ChangeRoomPermissionsEvent.Save -> coroutineScope.save() is ChangeRoomPermissionsEvent.Save -> coroutineScope.save()

View file

@ -32,11 +32,13 @@ data class ChangeRoomPermissionsState(
RoomPermissionType.BAN -> RoomMember.Role.forPowerLevel(currentPermissions.ban) RoomPermissionType.BAN -> RoomMember.Role.forPowerLevel(currentPermissions.ban)
RoomPermissionType.INVITE -> RoomMember.Role.forPowerLevel(currentPermissions.invite) RoomPermissionType.INVITE -> RoomMember.Role.forPowerLevel(currentPermissions.invite)
RoomPermissionType.KICK -> RoomMember.Role.forPowerLevel(currentPermissions.kick) RoomPermissionType.KICK -> RoomMember.Role.forPowerLevel(currentPermissions.kick)
RoomPermissionType.SEND_EVENTS -> RoomMember.Role.forPowerLevel(currentPermissions.sendEvents) RoomPermissionType.SEND_EVENTS -> RoomMember.Role.forPowerLevel(currentPermissions.eventsDefault)
RoomPermissionType.REDACT_EVENTS -> RoomMember.Role.forPowerLevel(currentPermissions.redactEvents) RoomPermissionType.REDACT_EVENTS -> RoomMember.Role.forPowerLevel(currentPermissions.redactEvents)
RoomPermissionType.ROOM_NAME -> RoomMember.Role.forPowerLevel(currentPermissions.roomName) RoomPermissionType.ROOM_NAME -> RoomMember.Role.forPowerLevel(currentPermissions.roomName)
RoomPermissionType.ROOM_AVATAR -> RoomMember.Role.forPowerLevel(currentPermissions.roomAvatar) RoomPermissionType.ROOM_AVATAR -> RoomMember.Role.forPowerLevel(currentPermissions.roomAvatar)
RoomPermissionType.ROOM_TOPIC -> RoomMember.Role.forPowerLevel(currentPermissions.roomTopic) RoomPermissionType.ROOM_TOPIC -> RoomMember.Role.forPowerLevel(currentPermissions.roomTopic)
RoomPermissionType.SPACE_MANAGE_ROOMS -> RoomMember.Role.forPowerLevel(currentPermissions.spaceChild)
RoomPermissionType.CHANGE_SETTINGS -> RoomMember.Role.forPowerLevel(currentPermissions.stateDefault)
} }
return when (role) { return when (role) {
is RoomMember.Role.Owner, is RoomMember.Role.Owner,
@ -48,10 +50,10 @@ data class ChangeRoomPermissionsState(
} }
enum class RoomPermissionsSection { enum class RoomPermissionsSection {
SpaceDetails, EditDetails,
RoomDetails,
MessagesAndContent, MessagesAndContent,
MembershipModeration, MembershipModeration,
ManageSpace
} }
enum class SelectableRole : DropdownOption { enum class SelectableRole : DropdownOption {
@ -80,5 +82,7 @@ enum class RoomPermissionType {
REDACT_EVENTS, REDACT_EVENTS,
ROOM_NAME, ROOM_NAME,
ROOM_AVATAR, ROOM_AVATAR,
ROOM_TOPIC ROOM_TOPIC,
SPACE_MANAGE_ROOMS,
CHANGE_SETTINGS,
} }

View file

@ -51,12 +51,13 @@ private fun previewPermissions(): RoomPowerLevelsValues {
ban = RoomMember.Role.User.powerLevel, ban = RoomMember.Role.User.powerLevel,
// MessagesAndContent section // MessagesAndContent section
redactEvents = RoomMember.Role.Moderator.powerLevel, redactEvents = RoomMember.Role.Moderator.powerLevel,
sendEvents = RoomMember.Role.Admin.powerLevel, eventsDefault = RoomMember.Role.Admin.powerLevel,
// RoomDetails section // RoomDetails section
roomName = RoomMember.Role.Admin.powerLevel, roomName = RoomMember.Role.Admin.powerLevel,
roomAvatar = RoomMember.Role.Moderator.powerLevel, roomAvatar = RoomMember.Role.Moderator.powerLevel,
roomTopic = RoomMember.Role.User.powerLevel, roomTopic = RoomMember.Role.User.powerLevel,
// SpaceManagement section // SpaceManagement section
spaceChild = RoomMember.Role.Moderator.powerLevel, spaceChild = RoomMember.Role.Moderator.powerLevel,
stateDefault = RoomMember.Role.Moderator.powerLevel,
) )
} }

View file

@ -110,10 +110,10 @@ fun ChangeRoomPermissionsView(
@Composable @Composable
private fun titleForSection(section: RoomPermissionsSection): String = when (section) { private fun titleForSection(section: RoomPermissionsSection): String = when (section) {
RoomPermissionsSection.SpaceDetails -> stringResource(R.string.screen_room_roles_and_permissions_space_details) RoomPermissionsSection.EditDetails -> stringResource(R.string.screen_room_change_permissions_room_details)
RoomPermissionsSection.RoomDetails -> stringResource(R.string.screen_room_roles_and_permissions_room_details) RoomPermissionsSection.MessagesAndContent -> stringResource(R.string.screen_room_change_permissions_messages_and_content)
RoomPermissionsSection.MessagesAndContent -> stringResource(R.string.screen_room_roles_and_permissions_messages_and_content) RoomPermissionsSection.MembershipModeration -> stringResource(R.string.screen_room_change_permissions_member_moderation)
RoomPermissionsSection.MembershipModeration -> stringResource(R.string.screen_room_roles_and_permissions_member_moderation) RoomPermissionsSection.ManageSpace -> stringResource(R.string.screen_room_change_permissions_manage_space)
} }
@Composable @Composable
@ -126,6 +126,8 @@ private fun titleForType(type: RoomPermissionType): String = when (type) {
RoomPermissionType.ROOM_NAME -> stringResource(R.string.screen_room_change_permissions_room_name) RoomPermissionType.ROOM_NAME -> stringResource(R.string.screen_room_change_permissions_room_name)
RoomPermissionType.ROOM_AVATAR -> stringResource(R.string.screen_room_change_permissions_room_avatar) RoomPermissionType.ROOM_AVATAR -> stringResource(R.string.screen_room_change_permissions_room_avatar)
RoomPermissionType.ROOM_TOPIC -> stringResource(R.string.screen_room_change_permissions_room_topic) RoomPermissionType.ROOM_TOPIC -> stringResource(R.string.screen_room_change_permissions_room_topic)
RoomPermissionType.SPACE_MANAGE_ROOMS -> stringResource(R.string.screen_room_change_permissions_manage_space_rooms)
RoomPermissionType.CHANGE_SETTINGS -> stringResource(R.string.screen_room_change_permissions_change_settings)
} }
@PreviewsDayNight @PreviewsDayNight

View file

@ -53,7 +53,7 @@ class ChangeRoomPermissionsPresenterTest {
presenter.present() presenter.present()
}.test { }.test {
val itemsBySection = awaitUpdatedItem().itemsBySection val itemsBySection = awaitUpdatedItem().itemsBySection
assertThat(itemsBySection[RoomPermissionsSection.RoomDetails]).containsExactly( assertThat(itemsBySection[RoomPermissionsSection.EditDetails]).containsExactly(
RoomPermissionType.ROOM_NAME, RoomPermissionType.ROOM_NAME,
RoomPermissionType.ROOM_AVATAR, RoomPermissionType.ROOM_AVATAR,
RoomPermissionType.ROOM_TOPIC, RoomPermissionType.ROOM_TOPIC,
@ -115,8 +115,9 @@ class ChangeRoomPermissionsPresenterTest {
invite = Moderator.powerLevel, invite = Moderator.powerLevel,
kick = Moderator.powerLevel, kick = Moderator.powerLevel,
ban = Moderator.powerLevel, ban = Moderator.powerLevel,
stateDefault = Moderator.powerLevel,
redactEvents = Moderator.powerLevel, redactEvents = Moderator.powerLevel,
sendEvents = Moderator.powerLevel, eventsDefault = Moderator.powerLevel,
roomName = Moderator.powerLevel, roomName = Moderator.powerLevel,
roomAvatar = Moderator.powerLevel, roomAvatar = Moderator.powerLevel,
roomTopic = Moderator.powerLevel, roomTopic = Moderator.powerLevel,

View file

@ -104,7 +104,7 @@ class ChangeRoomPermissionsViewTest {
state = aChangeRoomPermissionsState( state = aChangeRoomPermissionsState(
itemsBySection = persistentMapOf( itemsBySection = persistentMapOf(
// Makes sure there is only one item to click on // Makes sure there is only one item to click on
RoomPermissionsSection.RoomDetails to persistentListOf(RoomPermissionType.ROOM_NAME) RoomPermissionsSection.EditDetails to persistentListOf(RoomPermissionType.ROOM_NAME)
), ),
eventSink = recorder, eventSink = recorder,
) )

View file

@ -12,7 +12,8 @@ data class RoomPowerLevelsValues(
val ban: Long, val ban: Long,
val invite: Long, val invite: Long,
val kick: Long, val kick: Long,
val sendEvents: Long, val eventsDefault: Long,
val stateDefault: Long,
val redactEvents: Long, val redactEvents: Long,
val roomName: Long, val roomName: Long,
val roomAvatar: Long, val roomAvatar: Long,

View file

@ -397,10 +397,12 @@ class JoinedRustRoom(
invite = roomPowerLevelsValues.invite, invite = roomPowerLevelsValues.invite,
kick = roomPowerLevelsValues.kick, kick = roomPowerLevelsValues.kick,
redact = roomPowerLevelsValues.redactEvents, redact = roomPowerLevelsValues.redactEvents,
eventsDefault = roomPowerLevelsValues.sendEvents, stateDefault = roomPowerLevelsValues.stateDefault,
eventsDefault = roomPowerLevelsValues.eventsDefault,
roomName = roomPowerLevelsValues.roomName, roomName = roomPowerLevelsValues.roomName,
roomAvatar = roomPowerLevelsValues.roomAvatar, roomAvatar = roomPowerLevelsValues.roomAvatar,
roomTopic = roomPowerLevelsValues.roomTopic, roomTopic = roomPowerLevelsValues.roomTopic,
spaceChild = roomPowerLevelsValues.spaceChild,
) )
innerRoom.applyPowerLevelChanges(changes) innerRoom.applyPowerLevelChanges(changes)
} }

View file

@ -19,7 +19,8 @@ object RoomPowerLevelsValuesMapper {
ban = values.ban, ban = values.ban,
invite = values.invite, invite = values.invite,
kick = values.kick, kick = values.kick,
sendEvents = values.eventsDefault, eventsDefault = values.eventsDefault,
stateDefault = values.stateDefault,
redactEvents = values.redact, redactEvents = values.redact,
roomName = values.roomName, roomName = values.roomName,
roomAvatar = values.roomAvatar, roomAvatar = values.roomAvatar,

View file

@ -37,8 +37,9 @@ class RoomPowerLevelsValuesMapperTest {
ban = 1, ban = 1,
invite = 2, invite = 2,
kick = 3, kick = 3,
sendEvents = 5,
redactEvents = 4, redactEvents = 4,
eventsDefault = 5,
stateDefault = 6,
roomName = 8, roomName = 8,
roomAvatar = 9, roomAvatar = 9,
roomTopic = 10, roomTopic = 10,

View file

@ -211,10 +211,11 @@ fun defaultRoomPowerLevelValues() = RoomPowerLevelsValues(
ban = 50, ban = 50,
invite = 0, invite = 0,
kick = 50, kick = 50,
sendEvents = 0, eventsDefault = 0,
stateDefault = 50,
redactEvents = 50, redactEvents = 50,
roomName = 100, roomName = 50,
roomAvatar = 100, roomAvatar = 50,
roomTopic = 100, roomTopic = 50,
spaceChild = 100, spaceChild = 50,
) )