From 3ca25f900690a43b8c9ed3cea9bd8ea9d98f6539 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 9 Mar 2021 16:56:31 +0100 Subject: [PATCH] Some cleanup --- .../app/core/ui/views/SendStateImageView.kt | 61 +++++++++ .../home/room/detail/RoomDetailViewModel.kt | 127 +++++++++--------- .../helper/MessageInformationDataFactory.kt | 8 +- .../detail/timeline/item/AbsMessageItem.kt | 29 +--- .../main/res/layout/fragment_room_detail.xml | 2 +- .../res/layout/item_timeline_event_base.xml | 2 +- .../layout/view_failed_messages_warning.xml | 37 +++-- 7 files changed, 154 insertions(+), 112 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt diff --git a/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt new file mode 100644 index 0000000000..9acb82581f --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/ui/views/SendStateImageView.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 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.app.core.ui.views + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatImageView +import androidx.core.view.isVisible +import im.vector.app.R +import im.vector.app.features.home.room.detail.timeline.item.SendStateDecoration + +class SendStateImageView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AppCompatImageView(context, attrs, defStyleAttr) { + + init { + if (isInEditMode) { + render(SendStateDecoration.SENT) + } + } + + fun render(sendState: SendStateDecoration) { + isVisible = when (sendState) { + SendStateDecoration.SENDING_NON_MEDIA -> { + setImageResource(R.drawable.ic_sending_message) + contentDescription = context.getString(R.string.event_status_a11y_sending) + true + } + SendStateDecoration.SENT -> { + setImageResource(R.drawable.ic_message_sent) + contentDescription = context.getString(R.string.event_status_a11y_sent) + true + } + SendStateDecoration.FAILED -> { + setImageResource(R.drawable.ic_sending_message_failed) + contentDescription = context.getString(R.string.event_status_a11y_failed) + true + } + SendStateDecoration.SENDING_MEDIA, + SendStateDecoration.NONE -> { + false + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt index cf6862a28d..fdb7717e49 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt @@ -262,68 +262,68 @@ class RoomDetailViewModel @AssistedInject constructor( override fun handle(action: RoomDetailAction) { when (action) { - is RoomDetailAction.UserIsTyping -> handleUserIsTyping(action) - is RoomDetailAction.ComposerFocusChange -> handleComposerFocusChange(action) - is RoomDetailAction.SaveDraft -> handleSaveDraft(action) - is RoomDetailAction.SendMessage -> handleSendMessage(action) - is RoomDetailAction.SendMedia -> handleSendMedia(action) - is RoomDetailAction.SendSticker -> handleSendSticker(action) - is RoomDetailAction.TimelineEventTurnsVisible -> handleEventVisible(action) - is RoomDetailAction.TimelineEventTurnsInvisible -> handleEventInvisible(action) - is RoomDetailAction.LoadMoreTimelineEvents -> handleLoadMore(action) - is RoomDetailAction.SendReaction -> handleSendReaction(action) - is RoomDetailAction.AcceptInvite -> handleAcceptInvite() - is RoomDetailAction.RejectInvite -> handleRejectInvite() - is RoomDetailAction.RedactAction -> handleRedactEvent(action) - is RoomDetailAction.UndoReaction -> handleUndoReact(action) - is RoomDetailAction.UpdateQuickReactAction -> handleUpdateQuickReaction(action) - is RoomDetailAction.EnterRegularMode -> handleEnterRegularMode(action) - is RoomDetailAction.EnterEditMode -> handleEditAction(action) - is RoomDetailAction.EnterQuoteMode -> handleQuoteAction(action) - is RoomDetailAction.EnterReplyMode -> handleReplyAction(action) - is RoomDetailAction.DownloadOrOpen -> handleOpenOrDownloadFile(action) - is RoomDetailAction.NavigateToEvent -> handleNavigateToEvent(action) - is RoomDetailAction.HandleTombstoneEvent -> handleTombstoneEvent(action) - is RoomDetailAction.ResendMessage -> handleResendEvent(action) - is RoomDetailAction.RemoveFailedEcho -> handleRemove(action) - is RoomDetailAction.ResendAll -> handleResendAll() - is RoomDetailAction.MarkAllAsRead -> handleMarkAllAsRead() - is RoomDetailAction.ReportContent -> handleReportContent(action) - is RoomDetailAction.IgnoreUser -> handleIgnoreUser(action) + is RoomDetailAction.UserIsTyping -> handleUserIsTyping(action) + is RoomDetailAction.ComposerFocusChange -> handleComposerFocusChange(action) + is RoomDetailAction.SaveDraft -> handleSaveDraft(action) + is RoomDetailAction.SendMessage -> handleSendMessage(action) + is RoomDetailAction.SendMedia -> handleSendMedia(action) + is RoomDetailAction.SendSticker -> handleSendSticker(action) + is RoomDetailAction.TimelineEventTurnsVisible -> handleEventVisible(action) + is RoomDetailAction.TimelineEventTurnsInvisible -> handleEventInvisible(action) + is RoomDetailAction.LoadMoreTimelineEvents -> handleLoadMore(action) + is RoomDetailAction.SendReaction -> handleSendReaction(action) + is RoomDetailAction.AcceptInvite -> handleAcceptInvite() + is RoomDetailAction.RejectInvite -> handleRejectInvite() + is RoomDetailAction.RedactAction -> handleRedactEvent(action) + is RoomDetailAction.UndoReaction -> handleUndoReact(action) + is RoomDetailAction.UpdateQuickReactAction -> handleUpdateQuickReaction(action) + is RoomDetailAction.EnterRegularMode -> handleEnterRegularMode(action) + is RoomDetailAction.EnterEditMode -> handleEditAction(action) + is RoomDetailAction.EnterQuoteMode -> handleQuoteAction(action) + is RoomDetailAction.EnterReplyMode -> handleReplyAction(action) + is RoomDetailAction.DownloadOrOpen -> handleOpenOrDownloadFile(action) + is RoomDetailAction.NavigateToEvent -> handleNavigateToEvent(action) + is RoomDetailAction.HandleTombstoneEvent -> handleTombstoneEvent(action) + is RoomDetailAction.ResendMessage -> handleResendEvent(action) + is RoomDetailAction.RemoveFailedEcho -> handleRemove(action) + is RoomDetailAction.ResendAll -> handleResendAll() + is RoomDetailAction.MarkAllAsRead -> handleMarkAllAsRead() + is RoomDetailAction.ReportContent -> handleReportContent(action) + is RoomDetailAction.IgnoreUser -> handleIgnoreUser(action) is RoomDetailAction.EnterTrackingUnreadMessagesState -> startTrackingUnreadMessages() - is RoomDetailAction.ExitTrackingUnreadMessagesState -> stopTrackingUnreadMessages() - is RoomDetailAction.ReplyToOptions -> handleReplyToOptions(action) - is RoomDetailAction.AcceptVerificationRequest -> handleAcceptVerification(action) - is RoomDetailAction.DeclineVerificationRequest -> handleDeclineVerification(action) - is RoomDetailAction.RequestVerification -> handleRequestVerification(action) - is RoomDetailAction.ResumeVerification -> handleResumeRequestVerification(action) - is RoomDetailAction.ReRequestKeys -> handleReRequestKeys(action) - is RoomDetailAction.TapOnFailedToDecrypt -> handleTapOnFailedToDecrypt(action) - is RoomDetailAction.SelectStickerAttachment -> handleSelectStickerAttachment() - is RoomDetailAction.OpenIntegrationManager -> handleOpenIntegrationManager() - is RoomDetailAction.StartCallWithPhoneNumber -> handleStartCallWithPhoneNumber(action) - is RoomDetailAction.StartCall -> handleStartCall(action) - is RoomDetailAction.AcceptCall -> handleAcceptCall(action) - is RoomDetailAction.EndCall -> handleEndCall() - is RoomDetailAction.ManageIntegrations -> handleManageIntegrations() - is RoomDetailAction.AddJitsiWidget -> handleAddJitsiConference(action) - is RoomDetailAction.RemoveWidget -> handleDeleteWidget(action.widgetId) - is RoomDetailAction.EnsureNativeWidgetAllowed -> handleCheckWidgetAllowed(action) - is RoomDetailAction.CancelSend -> handleCancel(action) - is RoomDetailAction.OpenOrCreateDm -> handleOpenOrCreateDm(action) - is RoomDetailAction.JumpToReadReceipt -> handleJumpToReadReceipt(action) - RoomDetailAction.QuickActionInvitePeople -> handleInvitePeople() - RoomDetailAction.QuickActionSetAvatar -> handleQuickSetAvatar() - is RoomDetailAction.SetAvatarAction -> handleSetNewAvatar(action) - RoomDetailAction.QuickActionSetTopic -> _viewEvents.post(RoomDetailViewEvents.OpenRoomSettings) - is RoomDetailAction.ShowRoomAvatarFullScreen -> { + is RoomDetailAction.ExitTrackingUnreadMessagesState -> stopTrackingUnreadMessages() + is RoomDetailAction.ReplyToOptions -> handleReplyToOptions(action) + is RoomDetailAction.AcceptVerificationRequest -> handleAcceptVerification(action) + is RoomDetailAction.DeclineVerificationRequest -> handleDeclineVerification(action) + is RoomDetailAction.RequestVerification -> handleRequestVerification(action) + is RoomDetailAction.ResumeVerification -> handleResumeRequestVerification(action) + is RoomDetailAction.ReRequestKeys -> handleReRequestKeys(action) + is RoomDetailAction.TapOnFailedToDecrypt -> handleTapOnFailedToDecrypt(action) + is RoomDetailAction.SelectStickerAttachment -> handleSelectStickerAttachment() + is RoomDetailAction.OpenIntegrationManager -> handleOpenIntegrationManager() + is RoomDetailAction.StartCallWithPhoneNumber -> handleStartCallWithPhoneNumber(action) + is RoomDetailAction.StartCall -> handleStartCall(action) + is RoomDetailAction.AcceptCall -> handleAcceptCall(action) + is RoomDetailAction.EndCall -> handleEndCall() + is RoomDetailAction.ManageIntegrations -> handleManageIntegrations() + is RoomDetailAction.AddJitsiWidget -> handleAddJitsiConference(action) + is RoomDetailAction.RemoveWidget -> handleDeleteWidget(action.widgetId) + is RoomDetailAction.EnsureNativeWidgetAllowed -> handleCheckWidgetAllowed(action) + is RoomDetailAction.CancelSend -> handleCancel(action) + is RoomDetailAction.OpenOrCreateDm -> handleOpenOrCreateDm(action) + is RoomDetailAction.JumpToReadReceipt -> handleJumpToReadReceipt(action) + RoomDetailAction.QuickActionInvitePeople -> handleInvitePeople() + RoomDetailAction.QuickActionSetAvatar -> handleQuickSetAvatar() + is RoomDetailAction.SetAvatarAction -> handleSetNewAvatar(action) + RoomDetailAction.QuickActionSetTopic -> _viewEvents.post(RoomDetailViewEvents.OpenRoomSettings) + is RoomDetailAction.ShowRoomAvatarFullScreen -> { _viewEvents.post( RoomDetailViewEvents.ShowRoomAvatarFullScreen(action.matrixItem, action.transitionView) ) } - is RoomDetailAction.DoNotShowPreviewUrlFor -> handleDoNotShowPreviewUrlFor(action) - RoomDetailAction.RemoveAllFailedMessages -> handleRemoveAllFailedMessages() - RoomDetailAction.ResendAll -> handleResendAll() + is RoomDetailAction.DoNotShowPreviewUrlFor -> handleDoNotShowPreviewUrlFor(action) + RoomDetailAction.RemoveAllFailedMessages -> handleRemoveAllFailedMessages() + RoomDetailAction.ResendAll -> handleResendAll() }.exhaustive } @@ -663,7 +663,7 @@ class RoomDetailViewModel @AssistedInject constructor( } when (itemId) { R.id.timeline_setting -> true - R.id.invite -> state.canInvite + R.id.invite -> state.canInvite R.id.open_matrix_apps -> true R.id.voice_call, R.id.video_call -> callManager.getCallsByRoomId(state.roomId).isEmpty() @@ -816,7 +816,7 @@ class RoomDetailViewModel @AssistedInject constructor( } }.exhaustive } - is SendMode.EDIT -> { + is SendMode.EDIT -> { // is original event a reply? val inReplyTo = state.sendMode.timelineEvent.getRelationContent()?.inReplyTo?.eventId if (inReplyTo != null) { @@ -839,7 +839,7 @@ class RoomDetailViewModel @AssistedInject constructor( _viewEvents.post(RoomDetailViewEvents.MessageSent) popDraft() } - is SendMode.QUOTE -> { + is SendMode.QUOTE -> { val messageContent = state.sendMode.timelineEvent.getLastMessageContent() val textMsg = messageContent?.body @@ -860,7 +860,7 @@ class RoomDetailViewModel @AssistedInject constructor( _viewEvents.post(RoomDetailViewEvents.MessageSent) popDraft() } - is SendMode.REPLY -> { + is SendMode.REPLY -> { state.sendMode.timelineEvent.let { room.replyToMessage(it, action.text.toString(), action.autoMarkdown) _viewEvents.post(RoomDetailViewEvents.MessageSent) @@ -1441,7 +1441,10 @@ class RoomDetailViewModel @AssistedInject constructor( roomSummariesHolder.set(summary) setState { val typingMessage = typingHelper.getTypingMessage(summary.typingUsers) - copy(typingMessage = typingMessage, hasFailedSending = summary.hasFailedSending) + copy( + typingMessage = typingMessage, + hasFailedSending = summary.hasFailedSending + ) } if (summary.membership == Membership.INVITE) { summary.inviterId?.let { inviterId -> diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt index 7f7e03663b..360702e928 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt @@ -79,21 +79,21 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses // SendState Decoration val isSentByMe = event.root.senderId == session.myUserId - val isLocalEcho = LocalEcho.isLocalEchoId(event.eventId) val sendStateDecoration = if (isSentByMe) { val isMedia = when (event.root.content?.toModel()) { is MessageImageContent, is MessageVideoContent, is MessageAudioContent, - is MessageFileContent -> true - else -> false + is MessageFileContent -> true + else -> false } getSendStateDecoration( eventSendState = event.root.sendState, prevEventSendState = prevEvent?.root?.sendState, anyReadReceipts = event.readReceipts.any { it.user.userId != session.myUserId }, isMedia = isMedia, - isLocalEcho = isLocalEcho) + isLocalEcho = LocalEcho.isLocalEchoId(event.eventId) + ) } else { SendStateDecoration.NONE } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt index 3d7fe21c9a..ed61abcf6e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsMessageItem.kt @@ -26,6 +26,7 @@ import androidx.core.view.isInvisible import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import im.vector.app.R +import im.vector.app.core.ui.views.SendStateImageView import im.vector.app.core.utils.DebouncedClickListener import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.room.detail.timeline.MessageColorProvider @@ -85,30 +86,8 @@ abstract class AbsMessageItem : AbsBaseMessageItem } // Render send state indicator - holder.sendStateImageView.isVisible = true - holder.eventSendingIndicator.isVisible = false - when (attributes.informationData.sendStateDecoration) { - SendStateDecoration.SENDING_NON_MEDIA -> { - holder.sendStateImageView - .apply { setImageResource(R.drawable.ic_sending_message) } - .apply { contentDescription = context.getString(R.string.event_status_a11y_sending) } - } - SendStateDecoration.SENT -> { - holder.sendStateImageView - .apply { setImageResource(R.drawable.ic_message_sent) } - .apply { contentDescription = context.getString(R.string.event_status_a11y_sent) } - } - SendStateDecoration.FAILED -> { - holder.sendStateImageView - .apply { setImageResource(R.drawable.ic_sending_message_failed) } - .apply { contentDescription = context.getString(R.string.event_status_a11y_failed) } - } - SendStateDecoration.SENDING_MEDIA -> { - holder.sendStateImageView.isVisible = false - holder.eventSendingIndicator.isVisible = true - } - SendStateDecoration.NONE -> holder.sendStateImageView.isVisible = false - } + holder.sendStateImageView.render(attributes.informationData.sendStateDecoration) + holder.eventSendingIndicator.isVisible = attributes.informationData.sendStateDecoration == SendStateDecoration.SENDING_MEDIA } override fun unbind(holder: H) { @@ -126,7 +105,7 @@ abstract class AbsMessageItem : AbsBaseMessageItem val avatarImageView by bind(R.id.messageAvatarImageView) val memberNameView by bind(R.id.messageMemberNameView) val timeView by bind(R.id.messageTimeView) - val sendStateImageView by bind(R.id.messageSendStateImageView) + val sendStateImageView by bind(R.id.messageSendStateImageView) val eventSendingIndicator by bind(R.id.eventSendingIndicator) } diff --git a/vector/src/main/res/layout/fragment_room_detail.xml b/vector/src/main/res/layout/fragment_room_detail.xml index a6909a2893..11d97c9f4b 100644 --- a/vector/src/main/res/layout/fragment_room_detail.xml +++ b/vector/src/main/res/layout/fragment_room_detail.xml @@ -86,7 +86,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="top" - app:constraint_referenced_ids="composerLayout,notificationAreaView, failedMessagesWarningView" /> + app:constraint_referenced_ids="composerLayout,notificationAreaView,failedMessagesWarningView" /> - - + tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> - - + app:drawableStartCompat="@drawable/ic_sending_message_failed" + app:layout_constraintBottom_toBottomOf="@id/failedMessagesRetryButton" + app:layout_constraintEnd_toStartOf="@+id/failedMessagesDeleteAllButton" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="@id/failedMessagesRetryButton" /> - \ No newline at end of file + \ No newline at end of file