diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt index ef01b4032..c4eafffe4 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt @@ -49,68 +49,143 @@ class Reaction { var remainingEmojisToDisplay = MAX_EMOJIS_TO_DISPLAY val showInfoAboutMoreEmojis = message.reactions.size > MAX_EMOJIS_TO_DISPLAY - var textColor = ContextCompat.getColor(context, R.color.white) - if (!isOutgoingMessage) { - textColor = ContextCompat.getColor(binding.root.context, R.color.high_emphasis_text) - } + val textColor = getTextColor(context, isOutgoingMessage, binding) + val amountParams = getAmountLayoutParams(context) + val wrapperParams = getWrapperLayoutParams(context) - val amountParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - amountParams.marginStart = DisplayUtils.convertDpToPixel(AMOUNT_START_MARGIN, context).toInt() - - val wrapperParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - wrapperParams.marginEnd = DisplayUtils.convertDpToPixel(EMOJI_END_MARGIN, context).toInt() + val paddingSide = DisplayUtils.convertDpToPixel(EMOJI_AND_AMOUNT_PADDING_SIDE, context).toInt() + val paddingTop = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_TOP, context).toInt() + val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt() for ((emoji, amount) in message.reactions) { - val emojiWithAmountWrapper = LinearLayout(context) - emojiWithAmountWrapper.orientation = LinearLayout.HORIZONTAL - - val reactionEmoji = EmojiTextView(context) - reactionEmoji.text = emoji - - emojiWithAmountWrapper.addView(reactionEmoji) - - val reactionAmount = TextView(context) - reactionAmount.setTextColor(textColor) - reactionAmount.text = amount.toString() - reactionAmount.layoutParams = amountParams - emojiWithAmountWrapper.addView(reactionAmount) - - emojiWithAmountWrapper.layoutParams = wrapperParams - - val paddingSide = DisplayUtils.convertDpToPixel(EMOJI_AND_AMOUNT_PADDING_SIDE, context).toInt() - val paddingTop = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_TOP, context).toInt() - val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt() - if (message.reactionsSelf != null && - message.reactionsSelf.isNotEmpty() && - message.reactionsSelf.contains(emoji) - ) { - emojiWithAmountWrapper.background = - AppCompatResources.getDrawable(context, R.drawable.reaction_self_background) - emojiWithAmountWrapper.setPaddingRelative(paddingSide, paddingTop, paddingSide, paddingBottom) - } else { - emojiWithAmountWrapper.setPaddingRelative(0, paddingTop, paddingSide, paddingBottom) - } + val emojiWithAmountWrapper = getEmojiWithAmountWrapperLayout( + context, + message, + emoji, + amount, + EmojiWithAmountWrapperLayoutInfo( + textColor, + amountParams, + wrapperParams, + paddingSide, + paddingTop, + paddingBottom + ), + ) binding.reactionsEmojiWrapper.addView(emojiWithAmountWrapper) remainingEmojisToDisplay-- if (remainingEmojisToDisplay == 0 && showInfoAboutMoreEmojis) { - val infoAboutMoreEmojis = TextView(context) - infoAboutMoreEmojis.setTextColor(textColor) - infoAboutMoreEmojis.text = EMOJI_MORE - binding.reactionsEmojiWrapper.addView(infoAboutMoreEmojis) + binding.reactionsEmojiWrapper.addView(getMoreReactionsTextView(context, textColor)) break } } } } + private fun getEmojiWithAmountWrapperLayout( + context: Context, + message: ChatMessage, + emoji: String, + amount: Int, + layoutInfo: EmojiWithAmountWrapperLayoutInfo + ): LinearLayout { + val emojiWithAmountWrapper = LinearLayout(context) + emojiWithAmountWrapper.orientation = LinearLayout.HORIZONTAL + + emojiWithAmountWrapper.addView(getEmojiTextView(context, emoji)) + emojiWithAmountWrapper.addView(getReactionCount(context, layoutInfo.textColor, amount, layoutInfo.amountParams)) + emojiWithAmountWrapper.layoutParams = layoutInfo.wrapperParams + + if (message.reactionsSelf != null && + message.reactionsSelf.isNotEmpty() && + message.reactionsSelf.contains(emoji) + ) { + emojiWithAmountWrapper.background = + AppCompatResources.getDrawable(context, R.drawable.reaction_self_background) + emojiWithAmountWrapper.setPaddingRelative( + layoutInfo.paddingSide, + layoutInfo.paddingTop, + layoutInfo.paddingSide, + layoutInfo.paddingBottom + ) + } else { + emojiWithAmountWrapper.setPaddingRelative( + 0, + layoutInfo.paddingTop, + layoutInfo.paddingSide, + layoutInfo.paddingBottom + ) + } + return emojiWithAmountWrapper + } + + private fun getMoreReactionsTextView(context: Context, textColor: Int): TextView { + val infoAboutMoreEmojis = TextView(context) + infoAboutMoreEmojis.setTextColor(textColor) + infoAboutMoreEmojis.text = EMOJI_MORE + return infoAboutMoreEmojis + } + + private fun getEmojiTextView(context: Context, emoji: String): EmojiTextView { + val reactionEmoji = EmojiTextView(context) + reactionEmoji.text = emoji + return reactionEmoji + } + + private fun getReactionCount( + context: Context, + textColor: Int, + amount: Int, + amountParams: LinearLayout.LayoutParams + ): TextView { + val reactionAmount = TextView(context) + reactionAmount.setTextColor(textColor) + reactionAmount.text = amount.toString() + reactionAmount.layoutParams = amountParams + return reactionAmount + } + + private fun getWrapperLayoutParams(context: Context): LinearLayout.LayoutParams { + val wrapperParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + wrapperParams.marginEnd = DisplayUtils.convertDpToPixel(EMOJI_END_MARGIN, context).toInt() + return wrapperParams + } + + private fun getAmountLayoutParams(context: Context): LinearLayout.LayoutParams { + val amountParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + amountParams.marginStart = DisplayUtils.convertDpToPixel(AMOUNT_START_MARGIN, context).toInt() + return amountParams + } + + private fun getTextColor( + context: Context, + isOutgoingMessage: Boolean, + binding: ReactionsInsideMessageBinding + ): Int { + var textColor = ContextCompat.getColor(context, R.color.white) + if (!isOutgoingMessage) { + textColor = ContextCompat.getColor(binding.root.context, R.color.high_emphasis_text) + } + return textColor + } + + private data class EmojiWithAmountWrapperLayoutInfo( + val textColor: Int, + val amountParams: LinearLayout.LayoutParams, + val wrapperParams: LinearLayout.LayoutParams, + val paddingSide: Int, + val paddingTop: Int, + val paddingBottom: Int + ) + companion object { const val MAX_EMOJIS_TO_DISPLAY = 4 const val AMOUNT_START_MARGIN: Float = 2F diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt index 0ecc0dc29..132123324 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt @@ -457,6 +457,7 @@ class ChatController(args: Bundle) : currentConversation?.type == Conversation.ConversationType .ROOM_TYPE_ONE_TO_ONE_CALL + @Suppress("Detekt.TooGenericExceptionCaught") override fun onViewBound(view: View) { Log.d(TAG, "onViewBound: " + System.identityHashCode(this).toString()) actionBar?.show() diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt index 58374b7e2..8a753bb28 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt @@ -336,6 +336,7 @@ class ProfileController : NewBaseController(R.layout.controller_profile) { } } + @Suppress("Detekt.TooGenericExceptionCaught") private fun setErrorMessageForMultiList(headline: String, message: String, @DrawableRes errorResource: Int) { if (activity == null) { return diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt index 39179b357..8194e2b4c 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt @@ -191,6 +191,7 @@ class ServerSelectionController : } @SuppressLint("LongLogTag") + @Suppress("Detekt.TooGenericExceptionCaught") private fun checkServerAndProceed() { dispose() try { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt index dc2b06c77..b4255ac94 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt @@ -182,6 +182,7 @@ class WebViewLoginController(args: Bundle? = null) : NewBaseController( return false } + @Suppress("Detekt.TooGenericExceptionCaught") override fun onPageFinished(view: WebView, url: String) { try { loginStep++ diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java index e3ac0445b..1a4996a8f 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java @@ -617,6 +617,14 @@ public class ChatMessage implements MessageContentType, MessageContentType.Image return "voice-message".equals(messageType); } + public boolean isCommandMessage() { + return "command".equals(messageType); + } + + public boolean isDeletedCommentMessage() { + return "comment_deleted".equals(messageType); + } + public enum MessageType { REGULAR_TEXT_MESSAGE, SYSTEM_MESSAGE, diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt index 5720c2945..da085c583 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt @@ -76,14 +76,15 @@ class MessageActionsDialog( initMenuReplyToMessage(message.replyable) initMenuReplyPrivately( message.replyable && - user?.userId?.isNotEmpty() == true && - user?.userId != "?" && - message.user.id.startsWith("users/") && - message.user.id.substring(ACTOR_LENGTH) != currentConversation?.actorId && + hasUserId(user) && + hasUserActorId(message) && currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL ) initMenuDeleteMessage(showMessageDeletionButton) - initMenuForwardMessage(ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getMessageType()) + initMenuForwardMessage( + ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getMessageType() && + !(message.isDeletedCommentMessage || message.isDeleted) + ) initMenuMarkAsUnread( message.previousMessageId > NO_PREVIOUS_MESSAGE_ID && ChatMessage.MessageType.SYSTEM_MESSAGE != message.getMessageType() && @@ -98,6 +99,15 @@ class MessageActionsDialog( behavior.state = BottomSheetBehavior.STATE_EXPANDED } + private fun hasUserId(user: UserEntity?): Boolean { + return user?.userId?.isNotEmpty() == true && user?.userId != "?" + } + + private fun hasUserActorId(message: ChatMessage): Boolean { + return message.user.id.startsWith("users/") && + message.user.id.substring(ACTOR_LENGTH) != currentConversation?.actorId + } + @SuppressLint("ClickableViewAccessibility") private fun initEmojiMore() { dialogMessageActionsBinding.emojiMore.setOnTouchListener { v, event -> @@ -153,7 +163,8 @@ class MessageActionsDialog( private fun initEmojiBar() { if (CapabilitiesUtil.hasSpreedFeatureCapability(user, "reactions") && Conversation.ConversationReadOnlyState.CONVERSATION_READ_ONLY != - currentConversation?.conversationReadOnlyState + currentConversation?.conversationReadOnlyState && + isReactableMessageType(message) ) { checkAndSetEmojiSelfReaction(dialogMessageActionsBinding.emojiThumbsUp) dialogMessageActionsBinding.emojiThumbsUp.setOnClickListener { @@ -190,6 +201,10 @@ class MessageActionsDialog( } } + private fun isReactableMessageType(message: ChatMessage): Boolean { + return !(message.isCommandMessage || message.isDeletedCommentMessage || message.isDeleted) + } + private fun checkAndSetEmojiSelfReaction(emoji: EmojiTextView) { if (emoji.text?.toString() != null && message.reactionsSelf?.contains(emoji.text?.toString()) == true) { emoji.background = AppCompatResources.getDrawable(context, R.drawable.reaction_self_bottom_sheet_background) diff --git a/detekt.yml b/detekt.yml index d1b2a89e7..46cb12370 100644 --- a/detekt.yml +++ b/detekt.yml @@ -1,5 +1,5 @@ build: - maxIssues: 95 + maxIssues: 91 weights: # complexity: 2 # LongParameterList: 1