Cleaner code: add TimelineEvent to special modes
This commit is contained in:
parent
7e8cd07e1e
commit
9a57a02996
|
@ -33,6 +33,7 @@ import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
|
@ -225,79 +226,57 @@ class RoomDetailFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
roomDetailViewModel.selectSubscribe(
|
roomDetailViewModel.selectSubscribe(RoomDetailViewState::sendMode) { mode ->
|
||||||
RoomDetailViewState::sendMode,
|
|
||||||
RoomDetailViewState::selectedEvent,
|
|
||||||
RoomDetailViewState::roomId) { mode, event, roomId ->
|
|
||||||
when (mode) {
|
when (mode) {
|
||||||
SendMode.REGULAR -> {
|
SendMode.REGULAR -> exitSpecialMode()
|
||||||
commandAutocompletePolicy.enabled = true
|
is SendMode.EDIT -> enterSpecialMode(mode.timelineEvent, R.drawable.ic_edit, true)
|
||||||
val uid = session.sessionParams.credentials.userId
|
is SendMode.QUOTE -> enterSpecialMode(mode.timelineEvent, R.drawable.ic_quote, false)
|
||||||
val meMember = session.getRoom(roomId)?.getRoomMember(uid)
|
is SendMode.REPLY -> enterSpecialMode(mode.timelineEvent, R.drawable.ic_reply, false)
|
||||||
avatarRenderer.render(meMember?.avatarUrl, uid, meMember?.displayName, composerLayout.composerAvatarImageView)
|
|
||||||
composerLayout.collapse()
|
|
||||||
}
|
|
||||||
SendMode.EDIT,
|
|
||||||
SendMode.QUOTE,
|
|
||||||
SendMode.REPLY -> {
|
|
||||||
commandAutocompletePolicy.enabled = false
|
|
||||||
if (event == null) {
|
|
||||||
//we should ignore? can this happen?
|
|
||||||
Timber.e("Enter edit mode with no event selected")
|
|
||||||
return@selectSubscribe
|
|
||||||
}
|
|
||||||
//switch to expanded bar
|
|
||||||
composerLayout.composerRelatedMessageTitle.apply {
|
|
||||||
text = event.getDisambiguatedDisplayName()
|
|
||||||
setTextColor(ContextCompat.getColor(requireContext(), getColorFromUserId(event.root.senderId)))
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO this is used at several places, find way to refactor?
|
|
||||||
val messageContent: MessageContent? =
|
|
||||||
event.annotations?.editSummary?.aggregatedContent?.toModel()
|
|
||||||
?: event.root.getClearContent().toModel()
|
|
||||||
val nonFormattedBody = messageContent?.body ?: ""
|
|
||||||
var formattedBody: CharSequence? = null
|
|
||||||
if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
|
|
||||||
val parser = Parser.builder().build()
|
|
||||||
val document = parser.parse(messageContent.formattedBody
|
|
||||||
?: messageContent.body)
|
|
||||||
formattedBody = Markwon.builder(requireContext())
|
|
||||||
.usePlugin(HtmlPlugin.create()).build().render(document)
|
|
||||||
}
|
|
||||||
composerLayout.composerRelatedMessageContent.text = formattedBody
|
|
||||||
?: nonFormattedBody
|
|
||||||
|
|
||||||
|
|
||||||
if (mode == SendMode.EDIT) {
|
|
||||||
//TODO if it's a reply we should trim the top part of message
|
|
||||||
composerLayout.composerEditText.setText(nonFormattedBody)
|
|
||||||
composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_edit))
|
|
||||||
} else if (mode == SendMode.QUOTE) {
|
|
||||||
composerLayout.composerEditText.setText("")
|
|
||||||
composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_quote))
|
|
||||||
} else if (mode == SendMode.REPLY) {
|
|
||||||
composerLayout.composerEditText.setText("")
|
|
||||||
composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_reply))
|
|
||||||
}
|
|
||||||
|
|
||||||
avatarRenderer.render(event.senderAvatar, event.root.senderId
|
|
||||||
?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
|
|
||||||
|
|
||||||
composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text.length)
|
|
||||||
composerLayout.expand {
|
|
||||||
focusComposerAndShowKeyboard()
|
|
||||||
}
|
|
||||||
composerLayout.composerRelatedMessageCloseButton.setOnClickListener {
|
|
||||||
composerLayout.composerEditText.setText("")
|
|
||||||
roomDetailViewModel.resetSendMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun exitSpecialMode() {
|
||||||
|
commandAutocompletePolicy.enabled = true
|
||||||
|
composerLayout.collapse()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun enterSpecialMode(event: TimelineEvent, @DrawableRes iconRes: Int, useText: Boolean) {
|
||||||
|
commandAutocompletePolicy.enabled = false
|
||||||
|
//switch to expanded bar
|
||||||
|
composerLayout.composerRelatedMessageTitle.apply {
|
||||||
|
text = event.getDisambiguatedDisplayName()
|
||||||
|
setTextColor(ContextCompat.getColor(requireContext(), getColorFromUserId(event.root.senderId)))
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO this is used at several places, find way to refactor?
|
||||||
|
val messageContent: MessageContent? =
|
||||||
|
event.annotations?.editSummary?.aggregatedContent?.toModel()
|
||||||
|
?: event.root.getClearContent().toModel()
|
||||||
|
val nonFormattedBody = messageContent?.body ?: ""
|
||||||
|
var formattedBody: CharSequence? = null
|
||||||
|
if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
|
||||||
|
val parser = Parser.builder().build()
|
||||||
|
val document = parser.parse(messageContent.formattedBody
|
||||||
|
?: messageContent.body)
|
||||||
|
formattedBody = Markwon.builder(requireContext())
|
||||||
|
.usePlugin(HtmlPlugin.create()).build().render(document)
|
||||||
|
}
|
||||||
|
composerLayout.composerRelatedMessageContent.text = formattedBody
|
||||||
|
?: nonFormattedBody
|
||||||
|
|
||||||
|
composerLayout.composerEditText.setText(if (useText) nonFormattedBody else "")
|
||||||
|
composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), iconRes))
|
||||||
|
|
||||||
|
avatarRenderer.render(event.senderAvatar, event.root.senderId
|
||||||
|
?: "", event.senderName, composerLayout.composerRelatedMessageAvatar)
|
||||||
|
|
||||||
|
composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text.length)
|
||||||
|
composerLayout.expand {
|
||||||
|
focusComposerAndShowKeyboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
|
@ -422,6 +401,10 @@ class RoomDetailFragment :
|
||||||
roomDetailViewModel.process(RoomDetailActions.SendMessage(textMessage, VectorPreferences.isMarkdownEnabled(requireContext())))
|
roomDetailViewModel.process(RoomDetailActions.SendMessage(textMessage, VectorPreferences.isMarkdownEnabled(requireContext())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
composerLayout.composerRelatedMessageCloseButton.setOnClickListener {
|
||||||
|
composerLayout.composerEditText.setText("")
|
||||||
|
roomDetailViewModel.resetSendMode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupAttachmentButton() {
|
private fun setupAttachmentButton() {
|
||||||
|
|
|
@ -124,11 +124,10 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enterEditMode(event: TimelineEvent) {
|
private fun enterEditMode(event: TimelineEvent) {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.EDIT,
|
sendMode = SendMode.EDIT(event)
|
||||||
selectedEvent = event
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,8 +135,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
fun resetSendMode() {
|
fun resetSendMode() {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.REGULAR,
|
sendMode = SendMode.REGULAR
|
||||||
selectedEvent = null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +163,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
private fun handleSendMessage(action: RoomDetailActions.SendMessage) {
|
private fun handleSendMessage(action: RoomDetailActions.SendMessage) {
|
||||||
withState { state ->
|
withState { state ->
|
||||||
when (state.sendMode) {
|
when (state.sendMode) {
|
||||||
SendMode.REGULAR -> {
|
SendMode.REGULAR -> {
|
||||||
val slashCommandResult = CommandParser.parseSplashCommand(action.text)
|
val slashCommandResult = CommandParser.parseSplashCommand(action.text)
|
||||||
|
|
||||||
when (slashCommandResult) {
|
when (slashCommandResult) {
|
||||||
|
@ -231,30 +229,29 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SendMode.EDIT -> {
|
is SendMode.EDIT -> {
|
||||||
val messageContent: MessageContent? =
|
val messageContent: MessageContent? =
|
||||||
state.selectedEvent?.annotations?.editSummary?.aggregatedContent.toModel()
|
state.sendMode.timelineEvent.annotations?.editSummary?.aggregatedContent.toModel()
|
||||||
?: state.selectedEvent?.root?.getClearContent().toModel()
|
?: state.sendMode.timelineEvent.root.getClearContent().toModel()
|
||||||
val nonFormattedBody = messageContent?.body ?: ""
|
val nonFormattedBody = messageContent?.body ?: ""
|
||||||
|
|
||||||
if (nonFormattedBody != action.text) {
|
if (nonFormattedBody != action.text) {
|
||||||
room.editTextMessage(state.selectedEvent?.root?.eventId
|
room.editTextMessage(state.sendMode.timelineEvent.root.eventId
|
||||||
?: "", action.text, action.autoMarkdown)
|
?: "", action.text, action.autoMarkdown)
|
||||||
} else {
|
} else {
|
||||||
Timber.w("Same message content, do not send edition")
|
Timber.w("Same message content, do not send edition")
|
||||||
}
|
}
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.REGULAR,
|
sendMode = SendMode.REGULAR
|
||||||
selectedEvent = null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
|
||||||
}
|
}
|
||||||
SendMode.QUOTE -> {
|
is SendMode.QUOTE -> {
|
||||||
val messageContent: MessageContent? =
|
val messageContent: MessageContent? =
|
||||||
state.selectedEvent?.annotations?.editSummary?.aggregatedContent.toModel()
|
state.sendMode.timelineEvent.annotations?.editSummary?.aggregatedContent.toModel()
|
||||||
?: state.selectedEvent?.root?.getClearContent().toModel()
|
?: state.sendMode.timelineEvent.root.getClearContent().toModel()
|
||||||
val textMsg = messageContent?.body
|
val textMsg = messageContent?.body
|
||||||
|
|
||||||
val finalText = legacyRiotQuoteText(textMsg, action.text)
|
val finalText = legacyRiotQuoteText(textMsg, action.text)
|
||||||
|
@ -271,19 +268,17 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
}
|
}
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.REGULAR,
|
sendMode = SendMode.REGULAR
|
||||||
selectedEvent = null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
|
||||||
}
|
}
|
||||||
SendMode.REPLY -> {
|
is SendMode.REPLY -> {
|
||||||
state.selectedEvent?.let {
|
state.sendMode.timelineEvent.let {
|
||||||
room.replyToMessage(it.root, action.text, action.autoMarkdown)
|
room.replyToMessage(it.root, action.text, action.autoMarkdown)
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.REGULAR,
|
sendMode = SendMode.REGULAR
|
||||||
selectedEvent = null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
|
_sendMessageResultLiveData.postValue(LiveEvent(SendMessageResult.MessageSent))
|
||||||
|
@ -434,8 +429,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
room.getTimeLineEvent(action.eventId)?.let {
|
room.getTimeLineEvent(action.eventId)?.let {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.QUOTE,
|
sendMode = SendMode.QUOTE(it)
|
||||||
selectedEvent = it
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,8 +439,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
room.getTimeLineEvent(action.eventId)?.let {
|
room.getTimeLineEvent(action.eventId)?.let {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.REPLY,
|
sendMode = SendMode.REPLY(it)
|
||||||
selectedEvent = it
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,11 @@ import im.vector.matrix.android.api.session.user.model.User
|
||||||
*
|
*
|
||||||
* Depending on the state the bottom toolbar will change (icons/preview/actions...)
|
* Depending on the state the bottom toolbar will change (icons/preview/actions...)
|
||||||
*/
|
*/
|
||||||
enum class SendMode {
|
sealed class SendMode {
|
||||||
REGULAR,
|
object REGULAR : SendMode()
|
||||||
QUOTE,
|
data class QUOTE(val timelineEvent: TimelineEvent) : SendMode()
|
||||||
EDIT,
|
data class EDIT(val timelineEvent: TimelineEvent) : SendMode()
|
||||||
REPLY
|
data class REPLY(val timelineEvent: TimelineEvent) : SendMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class RoomDetailViewState(
|
data class RoomDetailViewState(
|
||||||
|
@ -46,7 +46,6 @@ data class RoomDetailViewState(
|
||||||
val asyncInviter: Async<User> = Uninitialized,
|
val asyncInviter: Async<User> = Uninitialized,
|
||||||
val asyncRoomSummary: Async<RoomSummary> = Uninitialized,
|
val asyncRoomSummary: Async<RoomSummary> = Uninitialized,
|
||||||
val sendMode: SendMode = SendMode.REGULAR,
|
val sendMode: SendMode = SendMode.REGULAR,
|
||||||
val selectedEvent: TimelineEvent? = null,
|
|
||||||
val isEncrypted: Boolean = false
|
val isEncrypted: Boolean = false
|
||||||
) : MvRxState {
|
) : MvRxState {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue