diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index 92c8771a56..6d802e0994 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -91,6 +91,8 @@ public final class ConversationUpdateItem extends FrameLayout private final RecipientObserverManager groupObserver = new RecipientObserverManager(presentOnChange); private final GroupDataManager groupData = new GroupDataManager(); + private final PassthroughClickListener passthroughClickListener = new PassthroughClickListener(); + public ConversationUpdateItem(Context context) { super(context); } @@ -427,6 +429,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onGroupMigrationLearnMoreClicked(conversationMessage.getMessageRecord().getGroupV1MigrationMembershipChanges()); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isChatSessionRefresh() && @@ -437,6 +441,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onChatSessionRefreshLearnMoreClicked(); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isIdentityUpdate()) { @@ -445,6 +451,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onSafetyNumberLearnMoreClicked(conversationMessage.getMessageRecord().getFromRecipient()); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isGroupCall()) { @@ -473,6 +481,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onJoinGroupCallClicked(); + } else { + passthroughClickListener.onClick(v); } }); } else { @@ -485,6 +495,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onInviteFriendsToGroupClicked(conversationRecipient.requireGroupId().requireV2()); + } else { + passthroughClickListener.onClick(v); } }); } else if ((conversationMessage.getMessageRecord().isMissedAudioCall() || conversationMessage.getMessageRecord().isMissedVideoCall()) && EnableCallNotificationSettingsDialog.shouldShow(getContext())) { @@ -493,6 +505,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (eventListener != null) { eventListener.onEnableCallNotificationsClicked(); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isInMemoryMessageRecord() && ((InMemoryMessageRecord) conversationMessage.getMessageRecord()).showActionButton()) { @@ -502,6 +516,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (eventListener != null) { eventListener.onInMemoryMessageClicked(inMemoryMessageRecord); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isGroupV2DescriptionUpdate()) { @@ -510,6 +526,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (eventListener != null) { eventListener.onViewGroupDescriptionChange(conversationRecipient.getGroupId().orElse(null), conversationMessage.getMessageRecord().getGroupV2DescriptionUpdate(), isMessageRequestAccepted); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isBadDecryptType() && @@ -520,6 +538,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onBadDecryptLearnMoreClicked(conversationMessage.getMessageRecord().getFromRecipient().getId()); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isChangeNumber() && conversationMessage.getMessageRecord().getFromRecipient().isSystemContact()) { @@ -528,6 +548,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onChangeNumberUpdateContact(conversationMessage.getMessageRecord().getFromRecipient()); + } else { + passthroughClickListener.onClick(v); } }); } else if (shouldShowBlockRequestAction(conversationMessage.getMessageRecord())) { @@ -536,6 +558,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onBlockJoinRequest(conversationMessage.getMessageRecord().getFromRecipient()); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isReleaseChannelDonationRequest()) { @@ -543,6 +567,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onDonateClicked(); + } else { + passthroughClickListener.onClick(v); } }); @@ -552,6 +578,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onInviteToSignalClicked(); + } else { + passthroughClickListener.onClick(v); } }); @@ -562,6 +590,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onActivatePaymentsClicked(); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isPaymentsActivated() && !conversationMessage.getMessageRecord().isOutgoing()) { @@ -570,6 +600,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onSendPaymentClicked(conversationMessage.getMessageRecord().getFromRecipient().getId()); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isReportedSpam()) { @@ -578,6 +610,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onReportSpamLearnMoreClicked(); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isProfileChange() && !conversationMessage.getMessageRecord().getFromRecipient().isSelf()) { @@ -586,6 +620,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onChangeProfileNameUpdateContact(conversationMessage.getMessageRecord().getFromRecipient()); + } else { + passthroughClickListener.onClick(v); } }); } else if (conversationMessage.getMessageRecord().isMessageRequestAccepted()) { @@ -594,6 +630,8 @@ public final class ConversationUpdateItem extends FrameLayout actionButton.setOnClickListener(v -> { if (batchSelected.isEmpty() && eventListener != null) { eventListener.onMessageRequestAcceptOptionsClicked(); + } else { + passthroughClickListener.onClick(v); } }); } else { @@ -723,6 +761,21 @@ public final class ConversationUpdateItem extends FrameLayout } } + private class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener { + + @Override + public boolean onLongClick(View v) { + performLongClick(); + return true; + } + + @Override + public void onClick(View v) { + performClick(); + } + } + + private class InternalClickListener implements View.OnClickListener { @Nullable private final View.OnClickListener parent; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemMediaViewHolder.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemMediaViewHolder.kt index 671d69316f..03ed78e844 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemMediaViewHolder.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemMediaViewHolder.kt @@ -72,7 +72,11 @@ class V2ConversationItemMediaViewHolder>( val quoteView = binding.quoteStub.get() quoteView.setOnClickListener { - conversationContext.clickListener.onQuoteClicked(record) + if (conversationContext.selectedItems.isEmpty()) { + conversationContext.clickListener.onQuoteClicked(record) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } } binding.quoteStub.visibility = View.VISIBLE diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt index 58a96be3b1..cd4827f0be 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/items/V2ConversationItemTextOnlyViewHolder.kt @@ -145,28 +145,30 @@ open class V2ConversationItemTextOnlyViewHolder>( binding.root.onDispatchTouchEventListener = dispatchTouchEventListener - binding.reactions.setOnClickListener { - conversationContext.clickListener - .onReactionClicked( - Multiselect.getParts(conversationMessage).asSingle().singlePart, - conversationMessage.messageRecord.id, - conversationMessage.messageRecord.isMms - ) - } - binding.body.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) } binding.root.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) } - binding.root.setOnClickListener { onBubbleClicked() } + val passthroughClickListener = PassthroughClickListener() + binding.body.setOnClickListener { + if (conversationContext.selectedItems.isEmpty()) { + passthroughClickListener.onClick(it) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } + } + binding.body.setOnLongClickListener(passthroughClickListener) + binding.root.setOnClickListener { + if (conversationContext.selectedItems.isEmpty()) { + onBubbleClicked() + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } + } binding.root.setOnLongClickListener { conversationContext.clickListener.onItemLongClick(binding.root, getMultiselectPartForLatestTouch()) true } - val passthroughClickListener = PassthroughClickListener() - binding.body.setOnClickListener(passthroughClickListener) - binding.body.setOnLongClickListener(passthroughClickListener) - binding.body.isFocusable = false binding.body.setTextSize(TypedValue.COMPLEX_UNIT_SP, SignalStore.settings.messageFontSize.toFloat()) binding.body.movementMethod = LongClickMovementMethod.getInstance(context) @@ -181,7 +183,13 @@ open class V2ConversationItemTextOnlyViewHolder>( binding.bodyWrapper.layoutTransition = bodyBubbleLayoutTransition binding.footerBackground.background = footerDrawable - binding.footerDate.setOnClickListener(passthroughClickListener) + binding.footerDate.setOnClickListener { + if (conversationContext.selectedItems.isEmpty()) { + passthroughClickListener.onClick(it) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } + } binding.footerDate.setOnLongClickListener(passthroughClickListener) } @@ -465,8 +473,12 @@ open class V2ConversationItemTextOnlyViewHolder>( private val recipientId: RecipientId ) : ClickableSpan() { override fun onClick(widget: View) { - VibrateUtil.vibrateTick(context) - conversationContext.clickListener.onGroupMemberClicked(recipientId, conversationMessage.threadRecipient.requireGroupId()) + if (conversationContext.selectedItems.isEmpty()) { + VibrateUtil.vibrateTick(context) + conversationContext.clickListener.onGroupMemberClicked(recipientId, conversationMessage.threadRecipient.requireGroupId()) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } } override fun updateDrawState(ds: TextPaint) = Unit @@ -480,6 +492,8 @@ open class V2ConversationItemTextOnlyViewHolder>( conversationMessage.messageRecord.id, conversationMessage.messageRecord.isMms ) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) } } @@ -561,10 +575,14 @@ open class V2ConversationItemTextOnlyViewHolder>( binding.senderPhoto.setAvatar(conversationContext.requestManager, sender, false) binding.senderBadge.setBadgeFromRecipient(sender, conversationContext.requestManager) binding.senderPhoto.setOnClickListener { - conversationContext.clickListener.onGroupMemberClicked( - conversationMessage.messageRecord.fromRecipient.id, - conversationMessage.threadRecipient.requireGroupId() - ) + if (conversationContext.selectedItems.isEmpty()) { + conversationContext.clickListener.onGroupMemberClicked( + conversationMessage.messageRecord.fromRecipient.id, + conversationMessage.threadRecipient.requireGroupId() + ) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } } } else { binding.senderName.visible = false @@ -613,6 +631,18 @@ open class V2ConversationItemTextOnlyViewHolder>( } else { binding.reactions.setReactions(conversationMessage.messageRecord.reactions) binding.root.addOnMeasureListener(reactionMeasureListener) + binding.reactions.setOnClickListener { + if (conversationContext.selectedItems.isEmpty()) { + conversationContext.clickListener + .onReactionClicked( + Multiselect.getParts(conversationMessage).asSingle().singlePart, + conversationMessage.messageRecord.id, + conversationMessage.messageRecord.isMms + ) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } + } } } @@ -659,7 +689,11 @@ open class V2ConversationItemTextOnlyViewHolder>( binding.footerDate.setText(errorMessage) binding.footerDate.setOnClickListener { - conversationContext.clickListener.onMessageWithErrorClicked(record) + if (conversationContext.selectedItems.isEmpty()) { + conversationContext.clickListener.onMessageWithErrorClicked(record) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } } } else if (record.isRateLimited) { binding.footerDate.setText(R.string.ConversationItem_send_paused) @@ -677,7 +711,11 @@ open class V2ConversationItemTextOnlyViewHolder>( } binding.footerDate.setOnClickListener { - conversationContext.clickListener.onEditedIndicatorClicked(conversationMessage) + if (conversationContext.selectedItems.isEmpty()) { + conversationContext.clickListener.onEditedIndicatorClicked(conversationMessage) + } else { + conversationContext.clickListener.onItemClick(getMultiselectPartForLatestTouch()) + } } }