RoomDetail : enter/exit special mode without waiting for draft to update
This commit is contained in:
parent
3af7ca9ab0
commit
54f93db632
@ -42,10 +42,10 @@ sealed class RoomDetailActions {
|
|||||||
object AcceptInvite : RoomDetailActions()
|
object AcceptInvite : RoomDetailActions()
|
||||||
object RejectInvite : RoomDetailActions()
|
object RejectInvite : RoomDetailActions()
|
||||||
|
|
||||||
data class EnterEditMode(val eventId: String, val draft: String) : RoomDetailActions()
|
data class EnterEditMode(val eventId: String, val text: String) : RoomDetailActions()
|
||||||
data class EnterQuoteMode(val eventId: String, val draft: String) : RoomDetailActions()
|
data class EnterQuoteMode(val eventId: String, val text: String) : RoomDetailActions()
|
||||||
data class EnterReplyMode(val eventId: String, val draft: String) : RoomDetailActions()
|
data class EnterReplyMode(val eventId: String, val text: String) : RoomDetailActions()
|
||||||
data class ExitSpecialMode(val draft: String) : RoomDetailActions()
|
data class ExitSpecialMode(val text: String) : RoomDetailActions()
|
||||||
|
|
||||||
data class ResendMessage(val eventId: String) : RoomDetailActions()
|
data class ResendMessage(val eventId: String) : RoomDetailActions()
|
||||||
data class RemoveFailedEcho(val eventId: String) : RoomDetailActions()
|
data class RemoveFailedEcho(val eventId: String) : RoomDetailActions()
|
||||||
|
@ -223,7 +223,6 @@ class RoomDetailFragment :
|
|||||||
setupToolbar(roomToolbar)
|
setupToolbar(roomToolbar)
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
setupComposer()
|
setupComposer()
|
||||||
setupAttachmentButton()
|
|
||||||
setupInviteView()
|
setupInviteView()
|
||||||
setupNotificationView()
|
setupNotificationView()
|
||||||
setupJumpToReadMarkerView()
|
setupJumpToReadMarkerView()
|
||||||
@ -601,21 +600,30 @@ class RoomDetailFragment :
|
|||||||
})
|
})
|
||||||
.build()
|
.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 {
|
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 {
|
override fun onRichContentSelected(contentUri: Uri): Boolean {
|
||||||
// We need WRITE_EXTERNAL permission
|
// We need WRITE_EXTERNAL permission
|
||||||
return if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this@RoomDetailFragment, PERMISSION_REQUEST_CODE_INCOMING_URI)) {
|
return if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this@RoomDetailFragment, PERMISSION_REQUEST_CODE_INCOMING_URI)) {
|
||||||
@ -638,15 +646,6 @@ class RoomDetailFragment :
|
|||||||
return isHandled
|
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() {
|
private fun setupInviteView() {
|
||||||
inviteView.callback = this
|
inviteView.callback = this
|
||||||
}
|
}
|
||||||
@ -1114,13 +1113,13 @@ class RoomDetailFragment :
|
|||||||
roomDetailViewModel.process(RoomDetailActions.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add))
|
roomDetailViewModel.process(RoomDetailActions.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add))
|
||||||
}
|
}
|
||||||
is SimpleAction.Edit -> {
|
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 -> {
|
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 -> {
|
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 -> {
|
is SimpleAction.CopyPermalink -> {
|
||||||
val permalink = PermalinkFactory.createPermalink(roomDetailArgs.roomId, action.eventId)
|
val permalink = PermalinkFactory.createPermalink(roomDetailArgs.roomId, action.eventId)
|
||||||
|
@ -520,17 +520,18 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleEditAction(action: RoomDetailActions.EnterEditMode) {
|
private fun handleEditAction(action: RoomDetailActions.EnterEditMode) {
|
||||||
saveCurrentDraft(action.draft)
|
saveCurrentDraft(action.text)
|
||||||
|
|
||||||
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
|
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
|
||||||
timelineEvent.root.eventId?.let {
|
timelineEvent.root.eventId?.let {
|
||||||
room.saveDraft(UserDraft.EDIT(it, timelineEvent.getTextEditableContent() ?: ""))
|
room.saveDraft(UserDraft.EDIT(it, timelineEvent.getTextEditableContent() ?: ""))
|
||||||
}
|
}
|
||||||
|
setState { copy(sendMode = SendMode.EDIT(timelineEvent, action.text)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleQuoteAction(action: RoomDetailActions.EnterQuoteMode) {
|
private fun handleQuoteAction(action: RoomDetailActions.EnterQuoteMode) {
|
||||||
saveCurrentDraft(action.draft)
|
saveCurrentDraft(action.text)
|
||||||
|
|
||||||
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
|
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
|
||||||
withState { state ->
|
withState { state ->
|
||||||
@ -539,16 +540,16 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||||||
if (state.sendMode is SendMode.EDIT) {
|
if (state.sendMode is SendMode.EDIT) {
|
||||||
room.saveDraft(UserDraft.QUOTE(it, ""))
|
room.saveDraft(UserDraft.QUOTE(it, ""))
|
||||||
} else {
|
} 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) {
|
private fun handleReplyAction(action: RoomDetailActions.EnterReplyMode) {
|
||||||
saveCurrentDraft(action.draft)
|
saveCurrentDraft(action.text)
|
||||||
|
|
||||||
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
|
room.getTimeLineEvent(action.eventId)?.let { timelineEvent ->
|
||||||
withState { state ->
|
withState { state ->
|
||||||
// Save a new draft and keep the previously entered text, if it was not an edit
|
// 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) {
|
if (state.sendMode is SendMode.EDIT) {
|
||||||
room.saveDraft(UserDraft.REPLY(it, ""))
|
room.saveDraft(UserDraft.REPLY(it, ""))
|
||||||
} else {
|
} 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()
|
room.deleteDraft()
|
||||||
} else {
|
} else {
|
||||||
// Save a new draft and keep the previously entered text
|
// Save a new draft and keep the previously entered text
|
||||||
room.saveDraft(UserDraft.REGULAR(action.draft))
|
room.saveDraft(UserDraft.REGULAR(action.text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.composer
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.text.Editable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
@ -31,6 +32,9 @@ import androidx.transition.TransitionManager
|
|||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
import im.vector.riotx.R
|
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.
|
* Encapsulate the timeline composer UX.
|
||||||
@ -39,7 +43,11 @@ import im.vector.riotx.R
|
|||||||
class TextComposerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
|
class TextComposerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
|
||||||
defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) {
|
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
|
var callback: Callback? = null
|
||||||
|
|
||||||
@ -62,15 +70,32 @@ class TextComposerView @JvmOverloads constructor(context: Context, attrs: Attrib
|
|||||||
|
|
||||||
private val animationDuration = 100L
|
private val animationDuration = 100L
|
||||||
|
|
||||||
|
val text: Editable?
|
||||||
|
get() = composerEditText.text
|
||||||
|
|
||||||
init {
|
init {
|
||||||
inflate(context, R.layout.merge_composer_layout, this)
|
inflate(context, R.layout.merge_composer_layout, this)
|
||||||
ButterKnife.bind(this)
|
ButterKnife.bind(this)
|
||||||
collapse(false)
|
collapse(false)
|
||||||
composerEditText.callback = object : Callback, ComposerEditText.Callback {
|
composerEditText.callback = object : ComposerEditText.Callback {
|
||||||
override fun onRichContentSelected(contentUri: Uri): Boolean {
|
override fun onRichContentSelected(contentUri: Uri): Boolean {
|
||||||
return callback?.onRichContentSelected(contentUri) ?: false
|
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) {
|
fun collapse(animate: Boolean = true, transitionComplete: (() -> Unit)? = null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user