forked from GitHub-Mirror/riotX-android
SlashCommand: implement parser
This commit is contained in:
parent
fab1d249f4
commit
eae8f993e6
@ -19,6 +19,11 @@ package im.vector.riotredesign.features.command
|
|||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the command line operations
|
||||||
|
* 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) {
|
enum class Command(val command: String, val parameters: String, @StringRes val description: Int) {
|
||||||
EMOTE("/me", "<message>", R.string.command_description_emote),
|
EMOTE("/me", "<message>", R.string.command_description_emote),
|
||||||
BAN_USER("/ban", "<user-id> [reason]", R.string.command_description_ban_user),
|
BAN_USER("/ban", "<user-id> [reason]", R.string.command_description_ban_user),
|
||||||
|
@ -16,5 +16,176 @@
|
|||||||
|
|
||||||
package im.vector.riotredesign.features.command
|
package im.vector.riotredesign.features.command
|
||||||
|
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
object CommandParser {
|
object CommandParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the text message into a Slash command.
|
||||||
|
*
|
||||||
|
* @param textMessage the text message
|
||||||
|
* @return a parsed slash command (ok or error)
|
||||||
|
*/
|
||||||
|
fun parseSplashCommand(textMessage: String): ParsedCommand {
|
||||||
|
// check if it has the Slash marker
|
||||||
|
if (!textMessage.startsWith("/")) {
|
||||||
|
return ParsedCommand.ErrorNotACommand
|
||||||
|
} else {
|
||||||
|
Timber.d("parseSplashCommand")
|
||||||
|
|
||||||
|
// "/" only
|
||||||
|
if (textMessage.length == 1) {
|
||||||
|
return ParsedCommand.ErrorEmptySlashCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude "//"
|
||||||
|
if ("/" == textMessage.substring(1, 2)) {
|
||||||
|
return ParsedCommand.ErrorNotACommand
|
||||||
|
}
|
||||||
|
|
||||||
|
var messageParts: List<String>? = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
messageParts = textMessage.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "## manageSplashCommand() : split failed " + e.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if the string cut fails
|
||||||
|
if (messageParts.isNullOrEmpty()) {
|
||||||
|
return ParsedCommand.ErrorEmptySlashCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
val slashCommand = messageParts[0]
|
||||||
|
|
||||||
|
when (slashCommand) {
|
||||||
|
Command.CHANGE_DISPLAY_NAME.command -> {
|
||||||
|
val newDisplayname = textMessage.substring(Command.CHANGE_DISPLAY_NAME.command.length).trim()
|
||||||
|
|
||||||
|
return if (newDisplayname.isNotEmpty()) {
|
||||||
|
ParsedCommand.ChangeDisplayName(newDisplayname)
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.CHANGE_DISPLAY_NAME)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.TOPIC.command -> {
|
||||||
|
val newTopic = textMessage.substring(Command.TOPIC.command.length).trim()
|
||||||
|
|
||||||
|
return if (newTopic.isNotEmpty()) {
|
||||||
|
ParsedCommand.ChangeTopic(newTopic)
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.TOPIC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.EMOTE.command -> {
|
||||||
|
val message = textMessage.substring(Command.EMOTE.command.length).trim()
|
||||||
|
|
||||||
|
return ParsedCommand.SendEmote(message)
|
||||||
|
}
|
||||||
|
Command.JOIN_ROOM.command -> {
|
||||||
|
val roomAlias = textMessage.substring(Command.JOIN_ROOM.command.length).trim()
|
||||||
|
|
||||||
|
return if (roomAlias.isNotEmpty()) {
|
||||||
|
ParsedCommand.JoinRoom(roomAlias)
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.JOIN_ROOM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.PART.command -> {
|
||||||
|
val roomAlias = textMessage.substring(Command.PART.command.length).trim()
|
||||||
|
|
||||||
|
return if (roomAlias.isNotEmpty()) {
|
||||||
|
ParsedCommand.PartRoom(roomAlias)
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.PART)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.INVITE.command -> {
|
||||||
|
return if (messageParts.size == 2) {
|
||||||
|
ParsedCommand.Invite(messageParts[1])
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.INVITE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.KICK_USER.command -> {
|
||||||
|
return if (messageParts.size >= 2) {
|
||||||
|
val user = messageParts[1]
|
||||||
|
val reason = textMessage.substring(Command.KICK_USER.command.length
|
||||||
|
+ 1
|
||||||
|
+ user.length).trim()
|
||||||
|
|
||||||
|
ParsedCommand.KickUser(user, reason)
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.KICK_USER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.BAN_USER.command -> {
|
||||||
|
return if (messageParts.size >= 2) {
|
||||||
|
val user = messageParts[1]
|
||||||
|
val reason = textMessage.substring(Command.BAN_USER.command.length
|
||||||
|
+ 1
|
||||||
|
+ user.length).trim()
|
||||||
|
|
||||||
|
ParsedCommand.BanUser(user, reason)
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.BAN_USER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.UNBAN_USER.command -> {
|
||||||
|
return if (messageParts.size == 2) {
|
||||||
|
ParsedCommand.UnbanUser(messageParts[1])
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.UNBAN_USER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.SET_USER_POWER_LEVEL.command -> {
|
||||||
|
return if (messageParts.size == 3) {
|
||||||
|
val userID = messageParts[1]
|
||||||
|
val powerLevelsAsString = messageParts[2]
|
||||||
|
|
||||||
|
try {
|
||||||
|
val powerLevelsAsInt = Integer.parseInt(powerLevelsAsString)
|
||||||
|
|
||||||
|
ParsedCommand.SetUserPowerLevel(userID, powerLevelsAsInt)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.SET_USER_POWER_LEVEL)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.SET_USER_POWER_LEVEL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.RESET_USER_POWER_LEVEL.command -> {
|
||||||
|
return if (messageParts.size == 2) {
|
||||||
|
val userId = messageParts[1]
|
||||||
|
|
||||||
|
ParsedCommand.SetUserPowerLevel(userId, 0)
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.SET_USER_POWER_LEVEL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.MARKDOWN.command -> {
|
||||||
|
return if (messageParts.size == 2) {
|
||||||
|
when {
|
||||||
|
"on".equals(messageParts[1], true) -> ParsedCommand.SetMarkdown(true)
|
||||||
|
"off".equals(messageParts[1], true) -> ParsedCommand.SetMarkdown(false)
|
||||||
|
else -> ParsedCommand.ErrorSyntax(Command.MARKDOWN)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.MARKDOWN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command.CLEAR_SCALAR_TOKEN.command -> {
|
||||||
|
return if (messageParts.size == 1) {
|
||||||
|
ParsedCommand.ClearSclalarToken
|
||||||
|
} else {
|
||||||
|
ParsedCommand.ErrorSyntax(Command.CLEAR_SCALAR_TOKEN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// Unknown command
|
||||||
|
return ParsedCommand.ErrorUnknownSlashCommand(slashCommand)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.riotredesign.features.command
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a parsed command
|
||||||
|
*/
|
||||||
|
sealed class ParsedCommand {
|
||||||
|
// This is not a Slash command
|
||||||
|
object ErrorNotACommand : ParsedCommand()
|
||||||
|
|
||||||
|
object ErrorEmptySlashCommand : ParsedCommand()
|
||||||
|
|
||||||
|
// Unknown/Unsupported slash command
|
||||||
|
class ErrorUnknownSlashCommand(val slashCommand: String) : ParsedCommand()
|
||||||
|
|
||||||
|
// A slash command is detected, but there is an error
|
||||||
|
class ErrorSyntax(val command: Command) : ParsedCommand()
|
||||||
|
|
||||||
|
// Valid commands:
|
||||||
|
|
||||||
|
class SendEmote(val message: String) : ParsedCommand()
|
||||||
|
class BanUser(val userId: String, val reason: String) : ParsedCommand()
|
||||||
|
class UnbanUser(val userId: String) : ParsedCommand()
|
||||||
|
class SetUserPowerLevel(val userId: String, val powerLevel: Int) : ParsedCommand()
|
||||||
|
class Invite(val userId: String) : ParsedCommand()
|
||||||
|
class JoinRoom(val roomAlias: String) : ParsedCommand()
|
||||||
|
class PartRoom(val roomAlias: String) : ParsedCommand()
|
||||||
|
class ChangeTopic(val topic: String) : ParsedCommand()
|
||||||
|
class KickUser(val userId: String, val reason: String) : ParsedCommand()
|
||||||
|
class ChangeDisplayName(val displayName: String) : ParsedCommand()
|
||||||
|
class SetMarkdown(val enable: Boolean) : ParsedCommand()
|
||||||
|
object ClearSclalarToken : ParsedCommand()
|
||||||
|
}
|
@ -23,6 +23,7 @@ import android.os.Parcelable
|
|||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
||||||
@ -35,9 +36,11 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
|||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
|
import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
|
||||||
|
import im.vector.riotredesign.core.extensions.observeEvent
|
||||||
import im.vector.riotredesign.core.glide.GlideApp
|
import im.vector.riotredesign.core.glide.GlideApp
|
||||||
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
||||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||||
|
import im.vector.riotredesign.core.utils.toast
|
||||||
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
|
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
|
||||||
import im.vector.riotredesign.features.autocomplete.command.CommandAutocompletePolicy
|
import im.vector.riotredesign.features.autocomplete.command.CommandAutocompletePolicy
|
||||||
import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserPresenter
|
import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserPresenter
|
||||||
@ -80,7 +83,6 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val session by inject<Session>()
|
private val session by inject<Session>()
|
||||||
// TODO Inject?
|
|
||||||
private val glideRequests by lazy {
|
private val glideRequests by lazy {
|
||||||
GlideApp.with(this)
|
GlideApp.with(this)
|
||||||
}
|
}
|
||||||
@ -104,6 +106,7 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac
|
|||||||
setupComposer()
|
setupComposer()
|
||||||
roomDetailViewModel.subscribe { renderState(it) }
|
roomDetailViewModel.subscribe { renderState(it) }
|
||||||
textComposerViewModel.subscribe { renderTextComposerState(it) }
|
textComposerViewModel.subscribe { renderTextComposerState(it) }
|
||||||
|
roomDetailViewModel.sendMessageResultLiveData.observeEvent(this) { renderSendMessageResult(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -192,8 +195,8 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac
|
|||||||
|
|
||||||
// Add the span
|
// Add the span
|
||||||
val user = session.getUser(item.userId)
|
val user = session.getUser(item.userId)
|
||||||
// FIXME avatar is not displayed
|
|
||||||
val span = PillImageSpan(glideRequests, context!!, item.userId, user)
|
val span = PillImageSpan(glideRequests, context!!, item.userId, user)
|
||||||
|
span.bind(composerEditText)
|
||||||
|
|
||||||
editable.setSpan(span, startIndex, startIndex + displayName.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
editable.setSpan(span, startIndex, startIndex + displayName.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
|
||||||
@ -209,7 +212,6 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac
|
|||||||
val textMessage = composerEditText.text.toString()
|
val textMessage = composerEditText.text.toString()
|
||||||
if (textMessage.isNotBlank()) {
|
if (textMessage.isNotBlank()) {
|
||||||
roomDetailViewModel.process(RoomDetailActions.SendMessage(textMessage))
|
roomDetailViewModel.process(RoomDetailActions.SendMessage(textMessage))
|
||||||
composerEditText.text = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,6 +238,32 @@ class RoomDetailFragment : VectorBaseFragment(), TimelineEventController.Callbac
|
|||||||
autocompleteUserPresenter.render(state.asyncUsers)
|
autocompleteUserPresenter.render(state.asyncUsers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renderSendMessageResult(sendMessageResult: SendMessageResult) {
|
||||||
|
when (sendMessageResult) {
|
||||||
|
is SendMessageResult.MessageSent, is SendMessageResult.SlashCommandHandled -> {
|
||||||
|
// Clear composer
|
||||||
|
composerEditText.text = null
|
||||||
|
}
|
||||||
|
is SendMessageResult.SlashCommandError -> {
|
||||||
|
displayError(getString(R.string.command_problem_with_parameters, sendMessageResult.command.command))
|
||||||
|
}
|
||||||
|
is SendMessageResult.SlashCommandUnknown -> {
|
||||||
|
displayError(getString(R.string.unrecognized_command, sendMessageResult.command))
|
||||||
|
}
|
||||||
|
is SendMessageResult.SlashCommandNotImplemented -> {
|
||||||
|
activity!!.toast(R.string.not_implemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun displayError(message: String) {
|
||||||
|
AlertDialog.Builder(activity!!)
|
||||||
|
.setTitle(R.string.command_error)
|
||||||
|
.setMessage(message)
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
// TimelineEventController.Callback ************************************************************
|
// TimelineEventController.Callback ************************************************************
|
||||||
|
|
||||||
override fun onUrlClicked(url: String) {
|
override fun onUrlClicked(url: String) {
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package im.vector.riotredesign.features.home.room.detail
|
package im.vector.riotredesign.features.home.room.detail
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
import com.jakewharton.rxrelay2.BehaviorRelay
|
import com.jakewharton.rxrelay2.BehaviorRelay
|
||||||
@ -24,6 +26,9 @@ import im.vector.matrix.android.api.session.Session
|
|||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
import im.vector.riotredesign.core.platform.VectorViewModel
|
import im.vector.riotredesign.core.platform.VectorViewModel
|
||||||
|
import im.vector.riotredesign.core.utils.LiveEvent
|
||||||
|
import im.vector.riotredesign.features.command.CommandParser
|
||||||
|
import im.vector.riotredesign.features.command.ParsedCommand
|
||||||
import im.vector.riotredesign.features.home.room.VisibleRoomStore
|
import im.vector.riotredesign.features.home.room.VisibleRoomStore
|
||||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
||||||
import io.reactivex.rxkotlin.subscribeBy
|
import io.reactivex.rxkotlin.subscribeBy
|
||||||
@ -63,17 +68,54 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
|
|||||||
|
|
||||||
fun process(action: RoomDetailActions) {
|
fun process(action: RoomDetailActions) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is RoomDetailActions.SendMessage -> handleSendMessage(action)
|
is RoomDetailActions.SendMessage -> handleSendMessage(action)
|
||||||
is RoomDetailActions.IsDisplayed -> handleIsDisplayed()
|
is RoomDetailActions.IsDisplayed -> handleIsDisplayed()
|
||||||
is RoomDetailActions.EventDisplayed -> handleEventDisplayed(action)
|
is RoomDetailActions.EventDisplayed -> handleEventDisplayed(action)
|
||||||
is RoomDetailActions.LoadMore -> handleLoadMore(action)
|
is RoomDetailActions.LoadMore -> handleLoadMore(action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val _sendMessageResultLiveData = MutableLiveData<LiveEvent<SendMessageResult>>()
|
||||||
|
val sendMessageResultLiveData: LiveData<LiveEvent<SendMessageResult>>
|
||||||
|
get() = _sendMessageResultLiveData
|
||||||
|
|
||||||
// PRIVATE METHODS *****************************************************************************
|
// PRIVATE METHODS *****************************************************************************
|
||||||
|
|
||||||
private fun handleSendMessage(action: RoomDetailActions.SendMessage) {
|
private fun handleSendMessage(action: RoomDetailActions.SendMessage) {
|
||||||
room.sendTextMessage(action.text, callback = object : MatrixCallback<Event> {})
|
// Handle slash command
|
||||||
|
val slashCommandResult = CommandParser.parseSplashCommand(action.text)
|
||||||
|
|
||||||
|
when (slashCommandResult) {
|
||||||
|
is ParsedCommand.ErrorNotACommand -> {
|
||||||
|
// Send the text message to the room
|
||||||
|
room.sendTextMessage(action.text, callback = object : MatrixCallback<Event> {})
|
||||||
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
|
||||||
|
}
|
||||||
|
is ParsedCommand.ErrorSyntax -> {
|
||||||
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandError(slashCommandResult.command)))
|
||||||
|
}
|
||||||
|
is ParsedCommand.ErrorEmptySlashCommand -> {
|
||||||
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandUnknown("/")))
|
||||||
|
}
|
||||||
|
is ParsedCommand.ErrorUnknownSlashCommand -> {
|
||||||
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandUnknown(slashCommandResult.slashCommand)))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
handleValidSlashCommand(slashCommandResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleValidSlashCommand(parsedCommand: ParsedCommand) {
|
||||||
|
when (parsedCommand) {
|
||||||
|
is ParsedCommand.Invite -> {
|
||||||
|
//room.invite(parsedCommand.userId)
|
||||||
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandHandled))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.SlashCommandNotImplemented))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleEventDisplayed(action: RoomDetailActions.EventDisplayed) {
|
private fun handleEventDisplayed(action: RoomDetailActions.EventDisplayed) {
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.riotredesign.features.home.room.detail
|
||||||
|
|
||||||
|
import im.vector.riotredesign.features.command.Command
|
||||||
|
|
||||||
|
sealed class SendMessageResult {
|
||||||
|
object MessageSent : SendMessageResult()
|
||||||
|
class SlashCommandError(val command: Command) : SendMessageResult()
|
||||||
|
class SlashCommandUnknown(val command: String) : SendMessageResult()
|
||||||
|
object SlashCommandHandled : SendMessageResult()
|
||||||
|
// TODO Remove
|
||||||
|
object SlashCommandNotImplemented : SendMessageResult()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user