RoomDetail : enter/exit special mode without waiting for draft to update

This commit is contained in:
ganfra 2019-11-06 20:08:19 +01:00
parent 3af7ca9ab0
commit 54f93db632
4 changed files with 66 additions and 40 deletions

View File

@ -42,10 +42,10 @@ sealed class RoomDetailActions {
object AcceptInvite : RoomDetailActions()
object RejectInvite : RoomDetailActions()
data class EnterEditMode(val eventId: String, val draft: String) : RoomDetailActions()
data class EnterQuoteMode(val eventId: String, val draft: String) : RoomDetailActions()
data class EnterReplyMode(val eventId: String, val draft: String) : RoomDetailActions()
data class ExitSpecialMode(val draft: String) : RoomDetailActions()
data class EnterEditMode(val eventId: String, val text: String) : RoomDetailActions()
data class EnterQuoteMode(val eventId: String, val text: String) : RoomDetailActions()
data class EnterReplyMode(val eventId: String, val text: String) : RoomDetailActions()
data class ExitSpecialMode(val text: String) : RoomDetailActions()
data class ResendMessage(val eventId: String) : RoomDetailActions()
data class RemoveFailedEcho(val eventId: String) : RoomDetailActions()

View File

@ -223,7 +223,6 @@ class RoomDetailFragment :
setupToolbar(roomToolbar)
setupRecyclerView()
setupComposer()
setupAttachmentButton()
setupInviteView()
setupNotificationView()
setupJumpToReadMarkerView()
@ -601,21 +600,30 @@ class RoomDetailFragment :
})
.build()
composerLayout.sendButton.setOnClickListener {
if (lockSendButton) {
Timber.w("Send button is locked")
return@setOnClickListener
}
val textMessage = composerLayout.composerEditText.text.toString()
if (textMessage.isNotBlank()) {
lockSendButton = true
roomDetailViewModel.process(RoomDetailActions.SendMessage(textMessage, vectorPreferences.isMarkdownEnabled()))
}
}
composerLayout.composerRelatedMessageCloseButton.setOnClickListener {
roomDetailViewModel.process(RoomDetailActions.ExitSpecialMode(composerLayout.composerEditText.text.toString()))
}
composerLayout.callback = object : TextComposerView.Callback {
override fun onAddAttachment() {
if (!::attachmentTypeSelector.isInitialized) {
attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this@RoomDetailFragment)
}
attachmentTypeSelector.show(composerLayout.attachmentButton, keyboardStateUtils.isKeyboardShowing)
}
override fun onSendMessage(text: String) {
if (lockSendButton) {
Timber.w("Send button is locked")
return
}
if (text.isNotBlank()) {
lockSendButton = true
roomDetailViewModel.process(RoomDetailActions.SendMessage(text, vectorPreferences.isMarkdownEnabled()))
}
}
override fun onCloseRelatedMessage() {
roomDetailViewModel.process(RoomDetailActions.ExitSpecialMode(composerLayout.text.toString()))
}
override fun onRichContentSelected(contentUri: Uri): Boolean {
// We need WRITE_EXTERNAL permission
return if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this@RoomDetailFragment, PERMISSION_REQUEST_CODE_INCOMING_URI)) {
@ -638,15 +646,6 @@ class RoomDetailFragment :
return isHandled
}
private fun setupAttachmentButton() {
composerLayout.attachmentButton.setOnClickListener {
if (!::attachmentTypeSelector.isInitialized) {
attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this)
}
attachmentTypeSelector.show(composerLayout.attachmentButton, keyboardStateUtils.isKeyboardShowing)
}
}
private fun setupInviteView() {
inviteView.callback = this
}
@ -1114,13 +1113,13 @@ class RoomDetailFragment :
roomDetailViewModel.process(RoomDetailActions.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add))
}
is SimpleAction.Edit -> {
roomDetailViewModel.process(RoomDetailActions.EnterEditMode(action.eventId, composerLayout.composerEditText.text.toString()))
roomDetailViewModel.process(RoomDetailActions.EnterEditMode(action.eventId, composerLayout.text.toString()))
}
is SimpleAction.Quote -> {
roomDetailViewModel.process(RoomDetailActions.EnterQuoteMode(action.eventId, composerLayout.composerEditText.text.toString()))
roomDetailViewModel.process(RoomDetailActions.EnterQuoteMode(action.eventId, composerLayout.text.toString()))
}
is SimpleAction.Reply -> {
roomDetailViewModel.process(RoomDetailActions.EnterReplyMode(action.eventId, composerLayout.composerEditText.text.toString()))
roomDetailViewModel.process(RoomDetailActions.EnterReplyMode(action.eventId, composerLayout.text.toString()))
}
is SimpleAction.CopyPermalink -> {
val permalink = PermalinkFactory.createPermalink(roomDetailArgs.roomId, action.eventId)

View File

@ -520,17 +520,18 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
}
private fun handleEditAction(action: RoomDetailActions.EnterEditMode) {
saveCurrentDraft(action.draft)
saveCurrentDraft(action.text)
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
timelineEvent.root.eventId?.let {
room.saveDraft(UserDraft.EDIT(it, timelineEvent.getTextEditableContent() ?: ""))
}
setState { copy(sendMode = SendMode.EDIT(timelineEvent, action.text)) }
}
}
private fun handleQuoteAction(action: RoomDetailActions.EnterQuoteMode) {
saveCurrentDraft(action.draft)
saveCurrentDraft(action.text)
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
withState { state ->
@ -539,16 +540,16 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
if (state.sendMode is SendMode.EDIT) {
room.saveDraft(UserDraft.QUOTE(it, ""))
} else {
room.saveDraft(UserDraft.QUOTE(it, action.draft))
room.saveDraft(UserDraft.QUOTE(it, action.text))
}
}
setState { copy(sendMode = SendMode.QUOTE(timelineEvent, action.text)) }
}
}
}
private fun handleReplyAction(action: RoomDetailActions.EnterReplyMode) {
saveCurrentDraft(action.draft)
saveCurrentDraft(action.text)
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
withState { state ->
// Save a new draft and keep the previously entered text, if it was not an edit
@ -556,9 +557,10 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
if (state.sendMode is SendMode.EDIT) {
room.saveDraft(UserDraft.REPLY(it, ""))
} else {
room.saveDraft(UserDraft.REPLY(it, action.draft))
room.saveDraft(UserDraft.REPLY(it, action.text))
}
}
setState { copy(sendMode = SendMode.REPLY(timelineEvent, action.text)) }
}
}
}
@ -584,7 +586,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
room.deleteDraft()
} else {
// Save a new draft and keep the previously entered text
room.saveDraft(UserDraft.REGULAR(action.draft))
room.saveDraft(UserDraft.REGULAR(action.text))
}
}
}

View File

@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.composer
import android.content.Context
import android.net.Uri
import android.text.Editable
import android.util.AttributeSet
import android.view.ViewGroup
import android.widget.ImageButton
@ -31,6 +32,9 @@ import androidx.transition.TransitionManager
import butterknife.BindView
import butterknife.ButterKnife
import im.vector.riotx.R
import im.vector.riotx.features.home.room.detail.RoomDetailActions
import kotlinx.android.synthetic.main.merge_composer_layout.view.*
import timber.log.Timber
/**
* Encapsulate the timeline composer UX.
@ -39,7 +43,11 @@ import im.vector.riotx.R
class TextComposerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) {
interface Callback : ComposerEditText.Callback
interface Callback : ComposerEditText.Callback {
fun onCloseRelatedMessage()
fun onSendMessage(text: String)
fun onAddAttachment()
}
var callback: Callback? = null
@ -62,15 +70,32 @@ class TextComposerView @JvmOverloads constructor(context: Context, attrs: Attrib
private val animationDuration = 100L
val text: Editable?
get() = composerEditText.text
init {
inflate(context, R.layout.merge_composer_layout, this)
ButterKnife.bind(this)
collapse(false)
composerEditText.callback = object : Callback, ComposerEditText.Callback {
composerEditText.callback = object : ComposerEditText.Callback {
override fun onRichContentSelected(contentUri: Uri): Boolean {
return callback?.onRichContentSelected(contentUri) ?: false
}
}
composerRelatedMessageCloseButton.setOnClickListener {
collapse()
callback?.onCloseRelatedMessage()
}
sendButton.setOnClickListener {
val textMessage = text?.toString() ?: ""
callback?.onSendMessage(textMessage)
}
attachmentButton.setOnClickListener {
callback?.onAddAttachment()
}
}
fun collapse(animate: Boolean = true, transitionComplete: (() -> Unit)? = null) {