diff --git a/CHANGES.md b/CHANGES.md index df550511e2..df0ddb6e64 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Features ✨: Improvements 🙌: - "Add Matrix app" menu is now always visible (#1495) + - Handle `/op`, `/deop`, and `/nick` commands (#12) Bugfix 🐛: - Fix dark theme issue on login screen (#1097) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/PowerLevelsContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/PowerLevelsContent.kt index b52f7b09bf..a14190eb47 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/PowerLevelsContent.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/PowerLevelsContent.kt @@ -35,4 +35,18 @@ data class PowerLevelsContent( @Json(name = "users") val users: MutableMap = HashMap(), @Json(name = "state_default") val stateDefault: Int = Role.Moderator.value, @Json(name = "notifications") val notifications: Map = HashMap() -) +) { + /** + * Alter this content with a new power level for the specified user + * + * @param userId the userId to alter the power level of + * @param powerLevel the new power level, or null to set the default value. + */ + fun setUserPowerLevel(userId: String, powerLevel: Int?) { + if (powerLevel == null || powerLevel == usersDefault) { + users.remove(userId) + } else { + users[userId] = powerLevel + } + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/powerlevels/PowerLevelsHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/powerlevels/PowerLevelsHelper.kt index 49141e3e86..f434859f6e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/powerlevels/PowerLevelsHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/powerlevels/PowerLevelsHelper.kt @@ -44,6 +44,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) { */ fun getUserRole(userId: String): Role { val value = getUserPowerLevelValue(userId) + // I think we should use powerLevelsContent.usersDefault, but Ganfra told me that it was like that on riot-Web return Role.fromValue(value, powerLevelsContent.eventsDefault) } diff --git a/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt b/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt index e7d2e9a62b..7c32a34aff 100644 --- a/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt +++ b/vector/src/main/java/im/vector/riotx/features/command/CommandParser.kt @@ -232,7 +232,7 @@ object CommandParser { val userId = messageParts[1] if (MatrixPatterns.isUserId(userId)) { - ParsedCommand.SetUserPowerLevel(userId, 0) + ParsedCommand.SetUserPowerLevel(userId, null) } else { ParsedCommand.ErrorSyntax(Command.SET_USER_POWER_LEVEL) } diff --git a/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt b/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt index 63e016b0b6..44ad2265e1 100644 --- a/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt +++ b/vector/src/main/java/im/vector/riotx/features/command/ParsedCommand.kt @@ -39,7 +39,7 @@ sealed class ParsedCommand { class SendRainbowEmote(val message: CharSequence) : ParsedCommand() class BanUser(val userId: String, val reason: String?) : ParsedCommand() class UnbanUser(val userId: String, val reason: String?) : ParsedCommand() - class SetUserPowerLevel(val userId: String, val powerLevel: Int) : ParsedCommand() + class SetUserPowerLevel(val userId: String, val powerLevel: Int?) : ParsedCommand() class Invite(val userId: String, val reason: String?) : ParsedCommand() class JoinRoom(val roomAlias: String, val reason: String?) : ParsedCommand() class PartRoom(val roomAlias: String, val reason: String?) : ParsedCommand() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index 3e8949e94c..b481c00be7 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -41,6 +41,7 @@ import im.vector.matrix.android.api.session.file.FileService import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilities import im.vector.matrix.android.api.session.room.members.roomMemberQueryParams import im.vector.matrix.android.api.session.room.model.Membership +import im.vector.matrix.android.api.session.room.model.PowerLevelsContent import im.vector.matrix.android.api.session.room.model.RoomMemberSummary import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.model.message.MessageContent @@ -448,8 +449,8 @@ class RoomDetailViewModel @AssistedInject constructor( popDraft() } is ParsedCommand.SetUserPowerLevel -> { - // TODO - _viewEvents.post(RoomDetailViewEvents.SlashCommandNotImplemented) + handleSetUserPowerLevel(slashCommandResult) + popDraft() } is ParsedCommand.ClearScalarToken -> { // TODO @@ -538,8 +539,8 @@ class RoomDetailViewModel @AssistedInject constructor( popDraft() } is ParsedCommand.ChangeDisplayName -> { - // TODO - _viewEvents.post(RoomDetailViewEvents.SlashCommandNotImplemented) + handleChangeDisplayNameSlashCommand(slashCommandResult) + popDraft() } is ParsedCommand.DiscardSession -> { if (room.isEncrypted()) { @@ -668,6 +669,23 @@ class RoomDetailViewModel @AssistedInject constructor( } } + private fun handleSetUserPowerLevel(setUserPowerLevel: ParsedCommand.SetUserPowerLevel) { + val currentPowerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) + ?.content + ?.toModel() ?: return + + launchSlashCommandFlow { + currentPowerLevelsContent.setUserPowerLevel(setUserPowerLevel.userId, setUserPowerLevel.powerLevel) + room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, currentPowerLevelsContent.toContent(), it) + } + } + + private fun handleChangeDisplayNameSlashCommand(changeDisplayName: ParsedCommand.ChangeDisplayName) { + launchSlashCommandFlow { + session.setDisplayName(session.myUserId, changeDisplayName.displayName, it) + } + } + private fun handleKickSlashCommand(kick: ParsedCommand.KickUser) { launchSlashCommandFlow { room.kick(kick.userId, kick.reason, it) diff --git a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt index aca584a663..6fc1facbc3 100644 --- a/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -162,7 +162,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v } else if (action.askForValidation && state.isMine) { _viewEvents.post(RoomMemberProfileViewEvents.ShowPowerLevelDemoteWarning(action.previousValue, action.newValue)) } else { - currentPowerLevelsContent.users[state.userId] = action.newValue + currentPowerLevelsContent.setUserPowerLevel(state.userId, action.newValue) viewModelScope.launch { _viewEvents.post(RoomMemberProfileViewEvents.Loading()) try {