diff --git a/changelog.d/4865.misc b/changelog.d/4865.misc new file mode 100644 index 00000000000..291c4a099f1 --- /dev/null +++ b/changelog.d/4865.misc @@ -0,0 +1 @@ +"/kick" command is replaced with "/remove". Also replaced all occurrences in string resources diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt index 198d6677a0b..d5bc65c1429 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/members/MembershipService.kt @@ -75,9 +75,12 @@ interface MembershipService { suspend fun unban(userId: String, reason: String? = null) /** - * Kick a user from the room + * Remove a user from the room */ - suspend fun kick(userId: String, reason: String? = null) + suspend fun remove(userId: String, reason: String? = null) + + @Deprecated("Use remove instead", ReplaceWith("remove(userId, reason)")) + suspend fun kick(userId: String, reason: String? = null) = remove(userId, reason) /** * Join the room, or accept an invitation. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt index 6cf82dde44d..49b58aa7655 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/DefaultMembershipService.kt @@ -125,7 +125,7 @@ internal class DefaultMembershipService @AssistedInject constructor( membershipAdminTask.execute(params) } - override suspend fun kick(userId: String, reason: String?) { + override suspend fun remove(userId: String, reason: String?) { val params = MembershipAdminTask.Params(MembershipAdminTask.Type.KICK, roomId, userId, reason) membershipAdminTask.execute(params) } diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandPresenter.kt index 5ad31aeaa63..9888f1e35e0 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandPresenter.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/command/AutocompleteCommandPresenter.kt @@ -50,7 +50,7 @@ class AutocompleteCommandPresenter @Inject constructor(context: Context, if (query.isNullOrEmpty()) { true } else { - it.command.startsWith(query, 1, true) + it.startsWith(query) } } controller.setData(data) diff --git a/vector/src/main/java/im/vector/app/features/command/Command.kt b/vector/src/main/java/im/vector/app/features/command/Command.kt index 1950038691c..f7390282f27 100644 --- a/vector/src/main/java/im/vector/app/features/command/Command.kt +++ b/vector/src/main/java/im/vector/app/features/command/Command.kt @@ -24,42 +24,50 @@ import im.vector.app.R * the user can write theses messages to perform some actions * the list will be displayed in this order */ -enum class Command(val command: String, val parameters: String, @StringRes val description: Int, val isDevCommand: Boolean) { - EMOTE("/me", "", R.string.command_description_emote, false), - BAN_USER("/ban", " [reason]", R.string.command_description_ban_user, false), - UNBAN_USER("/unban", " [reason]", R.string.command_description_unban_user, false), - IGNORE_USER("/ignore", " [reason]", R.string.command_description_ignore_user, false), - UNIGNORE_USER("/unignore", "", R.string.command_description_unignore_user, false), - SET_USER_POWER_LEVEL("/op", " []", R.string.command_description_op_user, false), - RESET_USER_POWER_LEVEL("/deop", "", R.string.command_description_deop_user, false), - ROOM_NAME("/roomname", "", R.string.command_description_room_name, false), - INVITE("/invite", " [reason]", R.string.command_description_invite_user, false), - JOIN_ROOM("/join", " [reason]", R.string.command_description_join_room, false), - PART("/part", "[]", R.string.command_description_part_room, false), - TOPIC("/topic", "", R.string.command_description_topic, false), - KICK_USER("/kick", " [reason]", R.string.command_description_kick_user, false), - CHANGE_DISPLAY_NAME("/nick", "", R.string.command_description_nick, false), - CHANGE_DISPLAY_NAME_FOR_ROOM("/myroomnick", "", R.string.command_description_nick_for_room, false), - ROOM_AVATAR("/roomavatar", "", R.string.command_description_room_avatar, true /* Since user has to know the mxc url */), - CHANGE_AVATAR_FOR_ROOM("/myroomavatar", "", R.string.command_description_avatar_for_room, true /* Since user has to know the mxc url */), - MARKDOWN("/markdown", "", R.string.command_description_markdown, false), - RAINBOW("/rainbow", "", R.string.command_description_rainbow, false), - RAINBOW_EMOTE("/rainbowme", "", R.string.command_description_rainbow_emote, false), - CLEAR_SCALAR_TOKEN("/clear_scalar_token", "", R.string.command_description_clear_scalar_token, false), - SPOILER("/spoiler", "", R.string.command_description_spoiler, false), - SHRUG("/shrug", "", R.string.command_description_shrug, false), - LENNY("/lenny", "", R.string.command_description_lenny, false), - PLAIN("/plain", "", R.string.command_description_plain, false), - WHOIS("/whois", "", R.string.command_description_whois, false), - DISCARD_SESSION("/discardsession", "", R.string.command_description_discard_session, false), - CONFETTI("/confetti", "", R.string.command_confetti, false), - SNOWFALL("/snowfall", "", R.string.command_snow, false), - CREATE_SPACE("/createspace", " *", R.string.command_description_create_space, true), - ADD_TO_SPACE("/addToSpace", "spaceId", R.string.command_description_add_to_space, true), - JOIN_SPACE("/joinSpace", "spaceId", R.string.command_description_join_space, true), - LEAVE_ROOM("/leave", "", R.string.command_description_leave_room, true), - UPGRADE_ROOM("/upgraderoom", "newVersion", R.string.command_description_upgrade_room, true); +enum class Command(val command: String, + val aliases: Array?, + val parameters: String, + @StringRes val description: Int, + val isDevCommand: Boolean) { + EMOTE("/me", null, "", R.string.command_description_emote, false), + BAN_USER("/ban", null, " [reason]", R.string.command_description_ban_user, false), + UNBAN_USER("/unban", null, " [reason]", R.string.command_description_unban_user, false), + IGNORE_USER("/ignore", null, " [reason]", R.string.command_description_ignore_user, false), + UNIGNORE_USER("/unignore", null, "", R.string.command_description_unignore_user, false), + SET_USER_POWER_LEVEL("/op", null, " []", R.string.command_description_op_user, false), + RESET_USER_POWER_LEVEL("/deop", null, "", R.string.command_description_deop_user, false), + ROOM_NAME("/roomname", null, "", R.string.command_description_room_name, false), + INVITE("/invite", null, " [reason]", R.string.command_description_invite_user, false), + JOIN_ROOM("/join", arrayOf("/j", "/goto"), " [reason]", R.string.command_description_join_room, false), + PART("/part", null, "[]", R.string.command_description_part_room, false), + TOPIC("/topic", null, "", R.string.command_description_topic, false), + REMOVE_USER("/remove", arrayOf("/kick"), " [reason]", R.string.command_description_kick_user, false), + CHANGE_DISPLAY_NAME("/nick", null, "", R.string.command_description_nick, false), + CHANGE_DISPLAY_NAME_FOR_ROOM("/myroomnick", arrayOf("/roomnick"), "", R.string.command_description_nick_for_room, false), + ROOM_AVATAR("/roomavatar", null, "", R.string.command_description_room_avatar, true /* Since user has to know the mxc url */), + CHANGE_AVATAR_FOR_ROOM("/myroomavatar", null, "", R.string.command_description_avatar_for_room, true /* Since user has to know the mxc url */), + MARKDOWN("/markdown", null, "", R.string.command_description_markdown, false), + RAINBOW("/rainbow", null, "", R.string.command_description_rainbow, false), + RAINBOW_EMOTE("/rainbowme", null, "", R.string.command_description_rainbow_emote, false), + CLEAR_SCALAR_TOKEN("/clear_scalar_token", null, "", R.string.command_description_clear_scalar_token, false), + SPOILER("/spoiler", null, "", R.string.command_description_spoiler, false), + SHRUG("/shrug", null, "", R.string.command_description_shrug, false), + LENNY("/lenny", null, "", R.string.command_description_lenny, false), + PLAIN("/plain", null, "", R.string.command_description_plain, false), + WHOIS("/whois", null, "", R.string.command_description_whois, false), + DISCARD_SESSION("/discardsession", null, "", R.string.command_description_discard_session, false), + CONFETTI("/confetti", null, "", R.string.command_confetti, false), + SNOWFALL("/snowfall", null, "", R.string.command_snow, false), + CREATE_SPACE("/createspace", null, " *", R.string.command_description_create_space, true), + ADD_TO_SPACE("/addToSpace", null, "spaceId", R.string.command_description_add_to_space, true), + JOIN_SPACE("/joinSpace", null, "spaceId", R.string.command_description_join_space, true), + LEAVE_ROOM("/leave", null, "", R.string.command_description_leave_room, true), + UPGRADE_ROOM("/upgraderoom", null, "newVersion", R.string.command_description_upgrade_room, true); - val length - get() = command.length + 1 + val allAliases = arrayOf(command, *aliases.orEmpty()) + + fun matches(inputCommand: CharSequence) = allAliases.any { it.contentEquals(inputCommand, true) } + + fun startsWith(input: CharSequence) = + allAliases.any { it.startsWith(input, 1, true) } } diff --git a/vector/src/main/java/im/vector/app/features/command/CommandParser.kt b/vector/src/main/java/im/vector/app/features/command/CommandParser.kt index 4b2a4aa28ca..f5861c7c535 100644 --- a/vector/src/main/java/im/vector/app/features/command/CommandParser.kt +++ b/vector/src/main/java/im/vector/app/features/command/CommandParser.kt @@ -32,12 +32,12 @@ object CommandParser { * @param textMessage the text message * @return a parsed slash command (ok or error) */ - fun parseSplashCommand(textMessage: CharSequence): ParsedCommand { + fun parseSlashCommand(textMessage: CharSequence): ParsedCommand { // check if it has the Slash marker if (!textMessage.startsWith("/")) { return ParsedCommand.ErrorNotACommand } else { - Timber.v("parseSplashCommand") + Timber.v("parseSlashCommand") // "/" only if (textMessage.length == 1) { @@ -52,7 +52,7 @@ object CommandParser { val messageParts = try { textMessage.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() } } catch (e: Exception) { - Timber.e(e, "## manageSplashCommand() : split failed") + Timber.e(e, "## manageSlashCommand() : split failed") null } @@ -61,35 +61,32 @@ object CommandParser { return ParsedCommand.ErrorEmptySlashCommand } - return when (val slashCommand = messageParts.first()) { - Command.PLAIN.command -> { - val text = textMessage.substring(Command.PLAIN.command.length).trim() + val slashCommand = messageParts.first() + val message = textMessage.substring(slashCommand.length).trim() - if (text.isNotEmpty()) { - ParsedCommand.SendPlainText(text) + return when { + Command.PLAIN.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.SendPlainText(message = message) } else { ParsedCommand.ErrorSyntax(Command.PLAIN) } } - Command.CHANGE_DISPLAY_NAME.command -> { - val newDisplayName = textMessage.substring(Command.CHANGE_DISPLAY_NAME.command.length).trim() - - if (newDisplayName.isNotEmpty()) { - ParsedCommand.ChangeDisplayName(newDisplayName) + Command.CHANGE_DISPLAY_NAME.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.ChangeDisplayName(displayName = message) } else { ParsedCommand.ErrorSyntax(Command.CHANGE_DISPLAY_NAME) } } - Command.CHANGE_DISPLAY_NAME_FOR_ROOM.command -> { - val newDisplayName = textMessage.substring(Command.CHANGE_DISPLAY_NAME_FOR_ROOM.command.length).trim() - - if (newDisplayName.isNotEmpty()) { - ParsedCommand.ChangeDisplayNameForRoom(newDisplayName) + Command.CHANGE_DISPLAY_NAME_FOR_ROOM.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.ChangeDisplayNameForRoom(displayName = message) } else { ParsedCommand.ErrorSyntax(Command.CHANGE_DISPLAY_NAME_FOR_ROOM) } } - Command.ROOM_AVATAR.command -> { + Command.ROOM_AVATAR.matches(slashCommand) -> { if (messageParts.size == 2) { val url = messageParts[1] @@ -102,7 +99,7 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.ROOM_AVATAR) } } - Command.CHANGE_AVATAR_FOR_ROOM.command -> { + Command.CHANGE_AVATAR_FOR_ROOM.matches(slashCommand) -> { if (messageParts.size == 2) { val url = messageParts[1] @@ -115,40 +112,42 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.CHANGE_AVATAR_FOR_ROOM) } } - Command.TOPIC.command -> { - val newTopic = textMessage.substring(Command.TOPIC.command.length).trim() - - if (newTopic.isNotEmpty()) { - ParsedCommand.ChangeTopic(newTopic) + Command.TOPIC.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.ChangeTopic(topic = message) } else { ParsedCommand.ErrorSyntax(Command.TOPIC) } } - Command.EMOTE.command -> { - val message = textMessage.subSequence(Command.EMOTE.command.length, textMessage.length).trim() - - ParsedCommand.SendEmote(message) + Command.EMOTE.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.SendEmote(message) + } else { + ParsedCommand.ErrorSyntax(Command.EMOTE) + } } - Command.RAINBOW.command -> { - val message = textMessage.subSequence(Command.RAINBOW.command.length, textMessage.length).trim() - - ParsedCommand.SendRainbow(message) + Command.RAINBOW.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.SendRainbow(message) + } else { + ParsedCommand.ErrorSyntax(Command.RAINBOW) + } } - Command.RAINBOW_EMOTE.command -> { - val message = textMessage.subSequence(Command.RAINBOW_EMOTE.command.length, textMessage.length).trim() - - ParsedCommand.SendRainbowEmote(message) + Command.RAINBOW_EMOTE.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.SendRainbowEmote(message) + } else { + ParsedCommand.ErrorSyntax(Command.RAINBOW_EMOTE) + } } - Command.JOIN_ROOM.command -> { + Command.JOIN_ROOM.matches(slashCommand) -> { if (messageParts.size >= 2) { val roomAlias = messageParts[1] if (roomAlias.isNotEmpty()) { ParsedCommand.JoinRoom( roomAlias, - textMessage.substring(Command.JOIN_ROOM.length + roomAlias.length) - .trim() - .takeIf { it.isNotBlank() } + trimParts(textMessage, messageParts.take(2)) ) } else { ParsedCommand.ErrorSyntax(Command.JOIN_ROOM) @@ -157,23 +156,21 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.JOIN_ROOM) } } - Command.PART.command -> { + Command.PART.matches(slashCommand) -> { when (messageParts.size) { 1 -> ParsedCommand.PartRoom(null) 2 -> ParsedCommand.PartRoom(messageParts[1]) else -> ParsedCommand.ErrorSyntax(Command.PART) } } - Command.ROOM_NAME.command -> { - val newRoomName = textMessage.substring(Command.ROOM_NAME.command.length).trim() - - if (newRoomName.isNotEmpty()) { - ParsedCommand.ChangeRoomName(newRoomName) + Command.ROOM_NAME.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.ChangeRoomName(name = message) } else { ParsedCommand.ErrorSyntax(Command.ROOM_NAME) } } - Command.INVITE.command -> { + Command.INVITE.matches(slashCommand) -> { if (messageParts.size >= 2) { val userId = messageParts[1] @@ -181,9 +178,7 @@ object CommandParser { MatrixPatterns.isUserId(userId) -> { ParsedCommand.Invite( userId, - textMessage.substring(Command.INVITE.length + userId.length) - .trim() - .takeIf { it.isNotBlank() } + trimParts(textMessage, messageParts.take(2)) ) } userId.isEmail() -> { @@ -200,34 +195,30 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.INVITE) } } - Command.KICK_USER.command -> { + Command.REMOVE_USER.matches(slashCommand) -> { if (messageParts.size >= 2) { val userId = messageParts[1] if (MatrixPatterns.isUserId(userId)) { - ParsedCommand.KickUser( + ParsedCommand.RemoveUser( userId, - textMessage.substring(Command.KICK_USER.length + userId.length) - .trim() - .takeIf { it.isNotBlank() } + trimParts(textMessage, messageParts.take(2)) ) } else { - ParsedCommand.ErrorSyntax(Command.KICK_USER) + ParsedCommand.ErrorSyntax(Command.REMOVE_USER) } } else { - ParsedCommand.ErrorSyntax(Command.KICK_USER) + ParsedCommand.ErrorSyntax(Command.REMOVE_USER) } } - Command.BAN_USER.command -> { + Command.BAN_USER.matches(slashCommand) -> { if (messageParts.size >= 2) { val userId = messageParts[1] if (MatrixPatterns.isUserId(userId)) { ParsedCommand.BanUser( userId, - textMessage.substring(Command.BAN_USER.length + userId.length) - .trim() - .takeIf { it.isNotBlank() } + trimParts(textMessage, messageParts.take(2)) ) } else { ParsedCommand.ErrorSyntax(Command.BAN_USER) @@ -236,16 +227,14 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.BAN_USER) } } - Command.UNBAN_USER.command -> { + Command.UNBAN_USER.matches(slashCommand) -> { if (messageParts.size >= 2) { val userId = messageParts[1] if (MatrixPatterns.isUserId(userId)) { ParsedCommand.UnbanUser( userId, - textMessage.substring(Command.UNBAN_USER.length + userId.length) - .trim() - .takeIf { it.isNotBlank() } + trimParts(textMessage, messageParts.take(2)) ) } else { ParsedCommand.ErrorSyntax(Command.UNBAN_USER) @@ -254,7 +243,7 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.UNBAN_USER) } } - Command.IGNORE_USER.command -> { + Command.IGNORE_USER.matches(slashCommand) -> { if (messageParts.size == 2) { val userId = messageParts[1] @@ -267,7 +256,7 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.IGNORE_USER) } } - Command.UNIGNORE_USER.command -> { + Command.UNIGNORE_USER.matches(slashCommand) -> { if (messageParts.size == 2) { val userId = messageParts[1] @@ -280,7 +269,7 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.UNIGNORE_USER) } } - Command.SET_USER_POWER_LEVEL.command -> { + Command.SET_USER_POWER_LEVEL.matches(slashCommand) -> { if (messageParts.size == 3) { val userId = messageParts[1] if (MatrixPatterns.isUserId(userId)) { @@ -300,7 +289,7 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.SET_USER_POWER_LEVEL) } } - Command.RESET_USER_POWER_LEVEL.command -> { + Command.RESET_USER_POWER_LEVEL.matches(slashCommand) -> { if (messageParts.size == 2) { val userId = messageParts[1] @@ -313,7 +302,7 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.SET_USER_POWER_LEVEL) } } - Command.MARKDOWN.command -> { + Command.MARKDOWN.matches(slashCommand) -> { if (messageParts.size == 2) { when { "on".equals(messageParts[1], true) -> ParsedCommand.SetMarkdown(true) @@ -324,31 +313,34 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.MARKDOWN) } } - Command.CLEAR_SCALAR_TOKEN.command -> { + Command.CLEAR_SCALAR_TOKEN.matches(slashCommand) -> { if (messageParts.size == 1) { ParsedCommand.ClearScalarToken } else { ParsedCommand.ErrorSyntax(Command.CLEAR_SCALAR_TOKEN) } } - Command.SPOILER.command -> { - val message = textMessage.substring(Command.SPOILER.command.length).trim() - ParsedCommand.SendSpoiler(message) + Command.SPOILER.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.SendSpoiler(message) + } else { + ParsedCommand.ErrorSyntax(Command.SPOILER) + } } - Command.SHRUG.command -> { - val message = textMessage.substring(Command.SHRUG.command.length).trim() - + Command.SHRUG.matches(slashCommand) -> { ParsedCommand.SendShrug(message) } - Command.LENNY.command -> { - val message = textMessage.substring(Command.LENNY.command.length).trim() - + Command.LENNY.matches(slashCommand) -> { ParsedCommand.SendLenny(message) } - Command.DISCARD_SESSION.command -> { - ParsedCommand.DiscardSession + Command.DISCARD_SESSION.matches(slashCommand) -> { + if (messageParts.size == 1) { + ParsedCommand.DiscardSession + } else { + ParsedCommand.ErrorSyntax(Command.DISCARD_SESSION) + } } - Command.WHOIS.command -> { + Command.WHOIS.matches(slashCommand) -> { if (messageParts.size == 2) { val userId = messageParts[1] @@ -361,57 +353,57 @@ object CommandParser { ParsedCommand.ErrorSyntax(Command.WHOIS) } } - Command.CONFETTI.command -> { - val message = textMessage.substring(Command.CONFETTI.command.length).trim() + Command.CONFETTI.matches(slashCommand) -> { ParsedCommand.SendChatEffect(ChatEffect.CONFETTI, message) } - Command.SNOWFALL.command -> { - val message = textMessage.substring(Command.SNOWFALL.command.length).trim() + Command.SNOWFALL.matches(slashCommand) -> { ParsedCommand.SendChatEffect(ChatEffect.SNOWFALL, message) } - Command.CREATE_SPACE.command -> { - val rawCommand = textMessage.substring(Command.CREATE_SPACE.command.length).trim() - val split = rawCommand.split(" ").map { it.trim() } - if (split.isEmpty()) { - ParsedCommand.ErrorSyntax(Command.CREATE_SPACE) - } else { + Command.CREATE_SPACE.matches(slashCommand) -> { + if (messageParts.size >= 2) { ParsedCommand.CreateSpace( - split[0], - split.subList(1, split.size) + messageParts[1], + messageParts.drop(2) ) + } else { + ParsedCommand.ErrorSyntax(Command.CREATE_SPACE) } } - Command.ADD_TO_SPACE.command -> { - val rawCommand = textMessage.substring(Command.ADD_TO_SPACE.command.length).trim() - ParsedCommand.AddToSpace( - rawCommand - ) - } - Command.JOIN_SPACE.command -> { - val spaceIdOrAlias = textMessage.substring(Command.JOIN_SPACE.command.length).trim() - ParsedCommand.JoinSpace( - spaceIdOrAlias - ) - } - Command.LEAVE_ROOM.command -> { - val spaceIdOrAlias = textMessage.substring(Command.LEAVE_ROOM.command.length).trim() - ParsedCommand.LeaveRoom( - spaceIdOrAlias - ) - } - Command.UPGRADE_ROOM.command -> { - val newVersion = textMessage.substring(Command.UPGRADE_ROOM.command.length).trim() - if (newVersion.isEmpty()) { - ParsedCommand.ErrorSyntax(Command.UPGRADE_ROOM) + Command.ADD_TO_SPACE.matches(slashCommand) -> { + if (messageParts.size == 1) { + ParsedCommand.AddToSpace(spaceId = message) } else { - ParsedCommand.UpgradeRoom(newVersion) + ParsedCommand.ErrorSyntax(Command.ADD_TO_SPACE) } } - else -> { + Command.JOIN_SPACE.matches(slashCommand) -> { + if (messageParts.size == 1) { + ParsedCommand.JoinSpace(spaceIdOrAlias = message) + } else { + ParsedCommand.ErrorSyntax(Command.JOIN_SPACE) + } + } + Command.LEAVE_ROOM.matches(slashCommand) -> { + ParsedCommand.LeaveRoom(roomId = message) + } + Command.UPGRADE_ROOM.matches(slashCommand) -> { + if (message.isNotEmpty()) { + ParsedCommand.UpgradeRoom(newVersion = message) + } else { + ParsedCommand.ErrorSyntax(Command.UPGRADE_ROOM) + } + } + else -> { // Unknown command ParsedCommand.ErrorUnknownSlashCommand(slashCommand) } } } } + + private fun trimParts(message: CharSequence, messageParts: List): String? { + val partsSize = messageParts.sumOf { it.length } + val gapsNumber = messageParts.size - 1 + return message.substring(partsSize + gapsNumber).trim().takeIf { it.isNotEmpty() } + } } diff --git a/vector/src/main/java/im/vector/app/features/command/ParsedCommand.kt b/vector/src/main/java/im/vector/app/features/command/ParsedCommand.kt index 4f8d19abb63..584272f3f4c 100644 --- a/vector/src/main/java/im/vector/app/features/command/ParsedCommand.kt +++ b/vector/src/main/java/im/vector/app/features/command/ParsedCommand.kt @@ -51,7 +51,7 @@ sealed class ParsedCommand { class JoinRoom(val roomAlias: String, val reason: String?) : ParsedCommand() class PartRoom(val roomAlias: String?) : ParsedCommand() class ChangeTopic(val topic: String) : ParsedCommand() - class KickUser(val userId: String, val reason: String?) : ParsedCommand() + class RemoveUser(val userId: String, val reason: String?) : ParsedCommand() class ChangeDisplayName(val displayName: String) : ParsedCommand() class ChangeDisplayNameForRoom(val displayName: String) : ParsedCommand() class ChangeRoomAvatar(val url: String) : ParsedCommand() diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index 566cb2d2ded..eaa684dea16 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -2098,7 +2098,7 @@ class RoomDetailFragment @Inject constructor( userId == session.myUserId) { // Empty composer, current user: start an emote views.composerLayout.views.composerEditText.setText(Command.EMOTE.command + " ") - views.composerLayout.views.composerEditText.setSelection(Command.EMOTE.length) + views.composerLayout.views.composerEditText.setSelection(Command.EMOTE.command.length + 1) } else { val roomMember = roomDetailViewModel.getMember(userId) // TODO move logic outside of fragment diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt index a63a06928a2..e907db03281 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt @@ -161,7 +161,7 @@ class MessageComposerViewModel @AssistedInject constructor( withState { state -> when (state.sendMode) { is SendMode.Regular -> { - when (val slashCommandResult = CommandParser.parseSplashCommand(action.text)) { + when (val slashCommandResult = CommandParser.parseSlashCommand(action.text)) { is ParsedCommand.ErrorNotACommand -> { // Send the text message to the room room.sendTextMessage(action.text, autoMarkdown = action.autoMarkdown) @@ -217,8 +217,8 @@ class MessageComposerViewModel @AssistedInject constructor( is ParsedCommand.UnignoreUser -> { handleUnignoreSlashCommand(slashCommandResult) } - is ParsedCommand.KickUser -> { - handleKickSlashCommand(slashCommandResult) + is ParsedCommand.RemoveUser -> { + handleRemoveSlashCommand(slashCommandResult) } is ParsedCommand.JoinRoom -> { handleJoinToAnotherRoomSlashCommand(slashCommandResult) @@ -576,9 +576,9 @@ class MessageComposerViewModel @AssistedInject constructor( } } - private fun handleKickSlashCommand(kick: ParsedCommand.KickUser) { + private fun handleRemoveSlashCommand(removeUser: ParsedCommand.RemoveUser) { launchSlashCommandFlowSuspendable { - room.kick(kick.userId, kick.reason) + room.remove(removeUser.userId, removeUser.reason) } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index 4f3d9d0776e..d6ba11d929a 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -254,7 +254,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor( viewModelScope.launch { try { _viewEvents.post(RoomMemberProfileViewEvents.Loading()) - room.kick(initialState.userId, action.reason) + room.remove(initialState.userId, action.reason) _viewEvents.post(RoomMemberProfileViewEvents.OnKickActionSuccess) } catch (failure: Throwable) { _viewEvents.post(RoomMemberProfileViewEvents.Failure(failure)) diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index dbdf104dfff..265758c6737 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -25,8 +25,9 @@ You left the room %1$s rejected the invitation You rejected the invitation - %1$s kicked %2$s - You kicked %1$s + + %1$s removed %2$s + You removed %1$s %1$s unbanned %2$s You unbanned %1$s %1$s banned %2$s @@ -229,8 +230,8 @@ You left. Reason: %1$s %1$s rejected the invitation. Reason: %2$s You rejected the invitation. Reason: %1$s - %1$s kicked %2$s. Reason: %3$s - You kicked %1$s. Reason: %2$s + %1$s removed %2$s. Reason: %3$s + You removed %1$s. Reason: %2$s %1$s unbanned %2$s. Reason: %3$s You unbanned %1$s. Reason: %2$s %1$s banned %2$s. Reason: %3$s @@ -884,7 +885,7 @@ Remove from this room Ban Unban - Kick + Remove from chat Reset to normal user Make moderator Make admin @@ -908,15 +909,15 @@ Cancel invite Are you sure you want to cancel the invite for this user? - Kick user - Reason to kick - kicking user will remove them from this room.\n\nTo prevent them from joining again, you should ban them instead. - kicking user will remove them from this space.\n\nTo prevent them from joining again, you should ban them instead. + Remove user + Reason to remove + The user will be removed from this room.\n\nTo prevent them from joining again, you should ban them instead. + The user will be removed from this space.\n\nTo prevent them from joining again, you should ban them instead. Ban user Reason to ban Unban user - Banning user will kick them from this room and prevent them from joining again. - Banning user will kick them from this space and prevent them from joining again. + Banning user will remove them from this room and prevent them from joining again. + Banning user will remove them from this space and prevent them from joining again. Unbanning user will allow them to join the room again. Unbanning user will allow them to join the space again. @@ -996,7 +997,7 @@ Send messages Invite users Change settings - Kick users + Remove users Ban users Remove messages sent by others Notify everyone @@ -1323,9 +1324,9 @@ Show room member state events Show chat effects Use /confetti command or send a message containing ❄️ or 🎉 - Includes invite/join/left/kick/ban events and avatar/display name changes. + Includes invite/join/left/remove/ban events and avatar/display name changes. Show join and leave events - Invites, kicks, and bans are unaffected. + Invites, removes, and bans are unaffected. Show account events Includes avatar and display name changes. Vibrate when mentioning a user @@ -1853,7 +1854,7 @@ Joins room with given address Leave room Set the room topic - Kicks user with given id + Removes user with given id from this room Changes your display nickname Changes your display nickname in the current room only Changes the avatar of the current room @@ -1903,7 +1904,7 @@ The community admin has not provided a long description for this community. - You have been kicked from %1$s by %2$s + You have been removed from %1$s by %2$s You have been banned from %1$s by %2$s Reason: %1$s Rejoin