From eed209428edeb547992db1cc40f856944d7334b2 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Tue, 15 Mar 2022 18:21:01 +0100 Subject: [PATCH] splitting up complex methods into smaller, easier to understand methods Signed-off-by: Andy Scherzinger --- .../firebase/MagicFirebaseMessagingService.kt | 165 +++++------ .../IncomingVoiceMessageViewHolder.kt | 94 ++++--- .../MagicIncomingTextMessageViewHolder.kt | 264 ++++++++++-------- .../MagicOutcomingTextMessageViewHolder.kt | 160 ++++++----- .../OutcomingVoiceMessageViewHolder.kt | 68 +++-- detekt.yml | 2 +- 6 files changed, 414 insertions(+), 339 deletions(-) diff --git a/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt b/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt index ae700105c..e8679e84f 100644 --- a/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt +++ b/app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt @@ -158,84 +158,7 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() { base64DecodedSubject ) if (signatureVerification!!.signatureValid) { - val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") - cipher.init(Cipher.DECRYPT_MODE, privateKey) - val decryptedSubject = cipher.doFinal(base64DecodedSubject) - decryptedPushMessage = LoganSquare.parse( - String(decryptedSubject), - DecryptedPushMessage::class.java - ) - decryptedPushMessage?.apply { - Log.d(TAG, this.toString()) - timestamp = System.currentTimeMillis() - if (delete) { - cancelExistingNotificationWithId( - applicationContext, - signatureVerification!!.userEntity, - notificationId - ) - } else if (deleteAll) { - cancelAllNotificationsForAccount(applicationContext, signatureVerification!!.userEntity) - } else if (deleteMultiple) { - notificationIds!!.forEach { - cancelExistingNotificationWithId( - applicationContext, - signatureVerification!!.userEntity, - it - ) - } - } else if (type == "call") { - val fullScreenIntent = Intent(applicationContext, CallNotificationActivity::class.java) - val bundle = Bundle() - bundle.putString(BundleKeys.KEY_ROOM_ID, decryptedPushMessage!!.id) - bundle.putParcelable(KEY_USER_ENTITY, signatureVerification!!.userEntity) - bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, true) - fullScreenIntent.putExtras(bundle) - - fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK - val fullScreenPendingIntent = PendingIntent.getActivity( - this@MagicFirebaseMessagingService, - 0, - fullScreenIntent, - PendingIntent.FLAG_UPDATE_CURRENT - ) - - val soundUri = getCallRingtoneUri(applicationContext!!, appPreferences!!) - val notificationChannelId = NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V4 - val uri = Uri.parse(signatureVerification!!.userEntity.baseUrl) - val baseUrl = uri.host - - val notification = - NotificationCompat.Builder(this@MagicFirebaseMessagingService, notificationChannelId) - .setPriority(NotificationCompat.PRIORITY_HIGH) - .setCategory(NotificationCompat.CATEGORY_CALL) - .setSmallIcon(R.drawable.ic_call_black_24dp) - .setSubText(baseUrl) - .setShowWhen(true) - .setWhen(decryptedPushMessage!!.timestamp) - .setContentTitle(EmojiCompat.get().process(decryptedPushMessage!!.subject)) - .setAutoCancel(true) - .setOngoing(true) - // .setTimeoutAfter(45000L) - .setContentIntent(fullScreenPendingIntent) - .setFullScreenIntent(fullScreenPendingIntent, true) - .setSound(soundUri) - .build() - notification.flags = notification.flags or Notification.FLAG_INSISTENT - isServiceInForeground = true - checkIfCallIsActive(signatureVerification!!, decryptedPushMessage!!) - startForeground(decryptedPushMessage!!.timestamp.toInt(), notification) - } else { - val messageData = Data.Builder() - .putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, subject) - .putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, signature) - .build() - val pushNotificationWork = - OneTimeWorkRequest.Builder(NotificationWorker::class.java).setInputData(messageData) - .build() - WorkManager.getInstance().enqueue(pushNotificationWork) - } - } + decryptMessage(privateKey, base64DecodedSubject, subject, signature) } } catch (e1: NoSuchAlgorithmException) { Log.d(NotificationWorker.TAG, "No proper algorithm to decrypt the message " + e1.localizedMessage) @@ -249,6 +172,92 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() { } } + private fun decryptMessage( + privateKey: PrivateKey, + base64DecodedSubject: ByteArray?, + subject: String, + signature: String + ) { + val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") + cipher.init(Cipher.DECRYPT_MODE, privateKey) + val decryptedSubject = cipher.doFinal(base64DecodedSubject) + decryptedPushMessage = LoganSquare.parse( + String(decryptedSubject), + DecryptedPushMessage::class.java + ) + decryptedPushMessage?.apply { + Log.d(TAG, this.toString()) + timestamp = System.currentTimeMillis() + if (delete) { + cancelExistingNotificationWithId( + applicationContext, + signatureVerification!!.userEntity, + notificationId + ) + } else if (deleteAll) { + cancelAllNotificationsForAccount(applicationContext, signatureVerification!!.userEntity) + } else if (deleteMultiple) { + notificationIds!!.forEach { + cancelExistingNotificationWithId( + applicationContext, + signatureVerification!!.userEntity, + it + ) + } + } else if (type == "call") { + val fullScreenIntent = Intent(applicationContext, CallNotificationActivity::class.java) + val bundle = Bundle() + bundle.putString(BundleKeys.KEY_ROOM_ID, decryptedPushMessage!!.id) + bundle.putParcelable(KEY_USER_ENTITY, signatureVerification!!.userEntity) + bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, true) + fullScreenIntent.putExtras(bundle) + + fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK + val fullScreenPendingIntent = PendingIntent.getActivity( + this@MagicFirebaseMessagingService, + 0, + fullScreenIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ) + + val soundUri = getCallRingtoneUri(applicationContext!!, appPreferences!!) + val notificationChannelId = NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V4 + val uri = Uri.parse(signatureVerification!!.userEntity.baseUrl) + val baseUrl = uri.host + + val notification = + NotificationCompat.Builder(this@MagicFirebaseMessagingService, notificationChannelId) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setCategory(NotificationCompat.CATEGORY_CALL) + .setSmallIcon(R.drawable.ic_call_black_24dp) + .setSubText(baseUrl) + .setShowWhen(true) + .setWhen(decryptedPushMessage!!.timestamp) + .setContentTitle(EmojiCompat.get().process(decryptedPushMessage!!.subject)) + .setAutoCancel(true) + .setOngoing(true) + // .setTimeoutAfter(45000L) + .setContentIntent(fullScreenPendingIntent) + .setFullScreenIntent(fullScreenPendingIntent, true) + .setSound(soundUri) + .build() + notification.flags = notification.flags or Notification.FLAG_INSISTENT + isServiceInForeground = true + checkIfCallIsActive(signatureVerification!!, decryptedPushMessage!!) + startForeground(decryptedPushMessage!!.timestamp.toInt(), notification) + } else { + val messageData = Data.Builder() + .putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, subject) + .putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, signature) + .build() + val pushNotificationWork = + OneTimeWorkRequest.Builder(NotificationWorker::class.java).setInputData(messageData) + .build() + WorkManager.getInstance().enqueue(pushNotificationWork) + } + } + } + private fun checkIfCallIsActive( signatureVerification: SignatureVerification, decryptedPushMessage: DecryptedPushMessage diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt index f03b19839..81cd661e2 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt @@ -153,24 +153,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message showVoiceMessageLoading() WorkManager.getInstance(context!!).getWorkInfoByIdLiveData(workInfo.id) .observeForever { info: WorkInfo? -> - if (info != null) { - when (info.state) { - WorkInfo.State.RUNNING -> { - Log.d(TAG, "WorkInfo.State.RUNNING in ViewHolder") - showVoiceMessageLoading() - } - WorkInfo.State.SUCCEEDED -> { - Log.d(TAG, "WorkInfo.State.SUCCEEDED in ViewHolder") - showPlayButton() - } - WorkInfo.State.FAILED -> { - Log.d(TAG, "WorkInfo.State.FAILED in ViewHolder") - showPlayButton() - } - else -> { - } - } - } + showStatus(info) } } } @@ -181,6 +164,27 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message } } + private fun showStatus(info: WorkInfo?) { + if (info != null) { + when (info.state) { + WorkInfo.State.RUNNING -> { + Log.d(TAG, "WorkInfo.State.RUNNING in ViewHolder") + showVoiceMessageLoading() + } + WorkInfo.State.SUCCEEDED -> { + Log.d(TAG, "WorkInfo.State.SUCCEEDED in ViewHolder") + showPlayButton() + } + WorkInfo.State.FAILED -> { + Log.d(TAG, "WorkInfo.State.FAILED in ViewHolder") + showPlayButton() + } + else -> { + } + } + } + } + private fun showPlayButton() { binding.playPauseBtn.visibility = View.VISIBLE binding.progressBar.visibility = View.GONE @@ -203,31 +207,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message } if (!message.isGrouped && !message.isOneToOneConversation) { - binding.messageUserAvatar.visibility = View.VISIBLE - if (message.actorType == "guests") { - // do nothing, avatar is set - } else if (message.actorType == "bots" && message.actorId == "changelog") { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val layers = arrayOfNulls(2) - layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background) - layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground) - val layerDrawable = LayerDrawable(layers) - binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable)) - } else { - binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher) - } - } else if (message.actorType == "bots") { - val drawable = TextDrawable.builder() - .beginConfig() - .bold() - .endConfig() - .buildRound( - ">", - ResourcesCompat.getColor(context!!.resources, R.color.black, null) - ) - binding.messageUserAvatar.visibility = View.VISIBLE - binding.messageUserAvatar.setImageDrawable(drawable) - } + setAvatarOnMessage(message) } else { if (message.isOneToOneConversation) { binding.messageUserAvatar.visibility = View.GONE @@ -238,6 +218,34 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message } } + private fun setAvatarOnMessage(message: ChatMessage) { + binding.messageUserAvatar.visibility = View.VISIBLE + if (message.actorType == "guests") { + // do nothing, avatar is set + } else if (message.actorType == "bots" && message.actorId == "changelog") { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val layers = arrayOfNulls(2) + layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background) + layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground) + val layerDrawable = LayerDrawable(layers) + binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable)) + } else { + binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher) + } + } else if (message.actorType == "bots") { + val drawable = TextDrawable.builder() + .beginConfig() + .bold() + .endConfig() + .buildRound( + ">", + ResourcesCompat.getColor(context!!.resources, R.color.black, null) + ) + binding.messageUserAvatar.visibility = View.VISIBLE + binding.messageUserAvatar.setImageDrawable(drawable) + } + } + private fun colorizeMessageBubble(message: ChatMessage) { val resources = itemView.resources diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt index db0ebb1ee..56b49b37f 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt @@ -26,6 +26,7 @@ package com.nextcloud.talk.adapters.messages import android.content.Context import android.content.Intent +import android.content.res.Resources import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.net.Uri @@ -53,6 +54,7 @@ import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.TextMatchers import com.nextcloud.talk.utils.preferences.AppPreferences import com.stfalcon.chatkit.messages.MessageHolders +import java.util.HashMap import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) @@ -72,44 +74,10 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message override fun onBind(message: ChatMessage) { super.onBind(message) sharedApplication!!.componentApplication.inject(this) - val author: String = message.actorDisplayName - if (!TextUtils.isEmpty(author)) { - binding.messageAuthor.text = author - binding.messageUserAvatar.setOnClickListener { - (payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context) - } - } else { - binding.messageAuthor.setText(R.string.nc_nick_guest) - } + processAuthor(message) if (!message.isGrouped && !message.isOneToOneConversation) { - binding.messageUserAvatar.visibility = View.VISIBLE - if (message.actorType == "guests") { - // do nothing, avatar is set - } else if (message.actorType == "bots" && message.actorId == "changelog") { - if (context != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val layers = arrayOfNulls(2) - layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background) - layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground) - val layerDrawable = LayerDrawable(layers) - binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable)) - } else { - binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher) - } - } - } else if (message.actorType == "bots") { - val drawable = TextDrawable.builder() - .beginConfig() - .bold() - .endConfig() - .buildRound( - ">", - ResourcesCompat.getColor(context!!.resources, R.color.black, null) - ) - binding.messageUserAvatar.visibility = View.VISIBLE - binding.messageUserAvatar.setImageDrawable(drawable) - } + showAvatarOnChatMessage(message) } else { if (message.isOneToOneConversation) { binding.messageUserAvatar.visibility = View.GONE @@ -121,6 +89,53 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message val resources = itemView.resources + setBubbleOnChatMessage(message, resources) + + itemView.isSelected = false + binding.messageTime.setTextColor(ResourcesCompat.getColor(resources, R.color.warm_grey_four, null)) + + var messageString: Spannable = SpannableString(message.text) + + var textSize = context?.resources!!.getDimension(R.dimen.chat_text_size) + + val messageParameters = message.messageParameters + if (messageParameters != null && messageParameters.size > 0) { + messageString = processMessageParameters(messageParameters, message, messageString) + } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { + textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() + itemView.isSelected = true + binding.messageAuthor.visibility = View.GONE + } + + binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) + binding.messageText.text = messageString + + // parent message handling + if (!message.isDeleted && message.parentMessage != null) { + processParentMessage(message) + binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE + } else { + binding.messageQuote.quotedChatMessageView.visibility = View.GONE + } + + itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable) + } + + private fun processAuthor(message: ChatMessage) { + if (!TextUtils.isEmpty(message.actorDisplayName)) { + binding.messageAuthor.text = message.actorDisplayName + binding.messageUserAvatar.setOnClickListener { + (payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context) + } + } else { + binding.messageAuthor.setText(R.string.nc_nick_guest) + } + } + + private fun setBubbleOnChatMessage( + message: ChatMessage, + resources: Resources + ) { val bgBubbleColor = if (message.isDeleted) { ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble_deleted, null) } else { @@ -139,97 +154,110 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message bgBubbleColor, bubbleResource ) ViewCompat.setBackground(bubble, bubbleDrawable) + } - val messageParameters = message.messageParameters + private fun processParentMessage(message: ChatMessage) { + val parentChatMessage = message.parentMessage + parentChatMessage.activeUser = message.activeUser + parentChatMessage.imageUrl?.let { + binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE + binding.messageQuote.quotedMessageImage.load(it) { + addHeader( + "Authorization", + ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token) + ) + } + } ?: run { + binding.messageQuote.quotedMessageImage.visibility = View.GONE + } + binding.messageQuote.quotedMessageAuthor.text = if (parentChatMessage.actorDisplayName.isNullOrEmpty()) + context!!.getText(R.string.nc_nick_guest) else parentChatMessage.actorDisplayName + binding.messageQuote.quotedMessage.text = parentChatMessage.text - itemView.isSelected = false - binding.messageTime.setTextColor(ResourcesCompat.getColor(resources, R.color.warm_grey_four, null)) + binding.messageQuote.quotedMessageAuthor + .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast)) - var messageString: Spannable = SpannableString(message.text) + if (parentChatMessage.actorId?.equals(message.activeUser.userId) == true) { + binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) + } else { + binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) + } + } - var textSize = context?.resources!!.getDimension(R.dimen.chat_text_size) + private fun showAvatarOnChatMessage(message: ChatMessage) { + binding.messageUserAvatar.visibility = View.VISIBLE + if (message.actorType == "guests") { + // do nothing, avatar is set + } else if (message.actorType == "bots" && message.actorId == "changelog") { + if (context != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val layers = arrayOfNulls(2) + layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background) + layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground) + val layerDrawable = LayerDrawable(layers) + binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable)) + } else { + binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher) + } + } + } else if (message.actorType == "bots") { + val drawable = TextDrawable.builder() + .beginConfig() + .bold() + .endConfig() + .buildRound( + ">", + ResourcesCompat.getColor(context!!.resources, R.color.black, null) + ) + binding.messageUserAvatar.visibility = View.VISIBLE + binding.messageUserAvatar.setImageDrawable(drawable) + } + } - if (messageParameters != null && messageParameters.size > 0) { - for (key in messageParameters.keys) { - val individualHashMap = message.messageParameters[key] - if (individualHashMap != null) { - if ( - individualHashMap["type"] == "user" || - individualHashMap["type"] == "guest" || - individualHashMap["type"] == "call" - ) { - if (individualHashMap["id"] == message.activeUser!!.userId) { - messageString = DisplayUtils.searchAndReplaceWithMentionSpan( - binding.messageText.context, - messageString, - individualHashMap["id"]!!, - individualHashMap["name"]!!, - individualHashMap["type"]!!, - message.activeUser!!, - R.xml.chip_you - ) - } else { - messageString = DisplayUtils.searchAndReplaceWithMentionSpan( - binding.messageText.context, - messageString, - individualHashMap["id"]!!, - individualHashMap["name"]!!, - individualHashMap["type"]!!, - message.activeUser!!, - R.xml.chip_others - ) - } - } else if (individualHashMap["type"] == "file") { - itemView.setOnClickListener { v -> - val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"])) - context!!.startActivity(browserIntent) - } + private fun processMessageParameters( + messageParameters: HashMap>, + message: ChatMessage, + messageString: Spannable + ): Spannable { + var messageStringInternal = messageString + for (key in messageParameters.keys) { + val individualHashMap = message.messageParameters[key] + if (individualHashMap != null) { + if ( + individualHashMap["type"] == "user" || + individualHashMap["type"] == "guest" || + individualHashMap["type"] == "call" + ) { + if (individualHashMap["id"] == message.activeUser!!.userId) { + messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan( + binding.messageText.context, + messageStringInternal, + individualHashMap["id"]!!, + individualHashMap["name"]!!, + individualHashMap["type"]!!, + message.activeUser!!, + R.xml.chip_you + ) + } else { + messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan( + binding.messageText.context, + messageStringInternal, + individualHashMap["id"]!!, + individualHashMap["name"]!!, + individualHashMap["type"]!!, + message.activeUser!!, + R.xml.chip_others + ) + } + } else if (individualHashMap["type"] == "file") { + itemView.setOnClickListener { v -> + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"])) + context!!.startActivity(browserIntent) } } } - } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { - textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() - itemView.isSelected = true - binding.messageAuthor.visibility = View.GONE } - - binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) - binding.messageText.text = messageString - - // parent message handling - if (!message.isDeleted && message.parentMessage != null) { - val parentChatMessage = message.parentMessage - parentChatMessage.activeUser = message.activeUser - parentChatMessage.imageUrl?.let { - binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE - binding.messageQuote.quotedMessageImage.load(it) { - addHeader( - "Authorization", - ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token) - ) - } - } ?: run { - binding.messageQuote.quotedMessageImage.visibility = View.GONE - } - binding.messageQuote.quotedMessageAuthor.text = if (parentChatMessage.actorDisplayName.isNullOrEmpty()) - context!!.getText(R.string.nc_nick_guest) else parentChatMessage.actorDisplayName - binding.messageQuote.quotedMessage.text = parentChatMessage.text - - binding.messageQuote.quotedMessageAuthor - .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast)) - - if (parentChatMessage.actorId?.equals(message.activeUser.userId) == true) { - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) - } else { - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) - } - - binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE - } else { - binding.messageQuote.quotedChatMessageView.visibility = View.GONE - } - - itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable) + return messageStringInternal } companion object { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt index 13ceaa622..b14c7e251 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt @@ -72,30 +72,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage layoutParams.isWrapBefore = false var textSize = context!!.resources.getDimension(R.dimen.chat_text_size) if (messageParameters != null && messageParameters.size > 0) { - for (key in messageParameters.keys) { - val individualHashMap: HashMap? = message.messageParameters[key] - if (individualHashMap != null) { - if (individualHashMap["type"] == "user" || - individualHashMap["type"] == "guest" || - individualHashMap["type"] == "call" - ) { - messageString = searchAndReplaceWithMentionSpan( - binding.messageText.context, - messageString, - individualHashMap["id"]!!, - individualHashMap["name"]!!, - individualHashMap["type"]!!, - message.activeUser, - R.xml.chip_others - ) - } else if (individualHashMap["type"] == "file") { - realView.setOnClickListener { v: View? -> - val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"])) - context!!.startActivity(browserIntent) - } - } - } - } + messageString = processMessageParameters(messageParameters, message, messageString) } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() layoutParams.isWrapBefore = true @@ -104,59 +81,16 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage ) realView.isSelected = true } - val resources = sharedApplication!!.resources - val bgBubbleColor = if (message.isDeleted) { - ResourcesCompat.getColor(resources, R.color.bg_message_list_outcoming_bubble_deleted, null) - } else { - ResourcesCompat.getColor(resources, R.color.bg_message_list_outcoming_bubble, null) - } - if (message.isGrouped) { - val bubbleDrawable = getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_grouped_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } else { - val bubbleDrawable = getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } + + setBubbleOnChatMessage(message) + binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageTime.layoutParams = layoutParams binding.messageText.text = messageString // parent message handling - if (!message.isDeleted && message.parentMessage != null) { - val parentChatMessage = message.parentMessage - parentChatMessage.activeUser = message.activeUser - parentChatMessage.imageUrl?.let { - binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE - binding.messageQuote.quotedMessageImage.load(it) { - addHeader( - "Authorization", - ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token) - ) - } - } ?: run { - binding.messageQuote.quotedMessageImage.visibility = View.GONE - } - binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName - ?: context!!.getText(R.string.nc_nick_guest) - binding.messageQuote.quotedMessage.text = parentChatMessage.text - binding.messageQuote.quotedMessage.setTextColor( - ContextCompat.getColor(context!!, R.color.nc_outcoming_text_default) - ) - binding.messageQuote.quotedMessageAuthor.setTextColor(ContextCompat.getColor(context!!, R.color.nc_grey)) - - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.white) - + processParentMessage(message) binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE } else { binding.messageQuote.quotedChatMessageView.visibility = View.GONE @@ -186,6 +120,90 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable) } + private fun processParentMessage(message: ChatMessage) { + val parentChatMessage = message.parentMessage + parentChatMessage.activeUser = message.activeUser + parentChatMessage.imageUrl?.let { + binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE + binding.messageQuote.quotedMessageImage.load(it) { + addHeader( + "Authorization", + ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token) + ) + } + } ?: run { + binding.messageQuote.quotedMessageImage.visibility = View.GONE + } + binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName + ?: context!!.getText(R.string.nc_nick_guest) + binding.messageQuote.quotedMessage.text = parentChatMessage.text + binding.messageQuote.quotedMessage.setTextColor( + ContextCompat.getColor(context!!, R.color.nc_outcoming_text_default) + ) + binding.messageQuote.quotedMessageAuthor.setTextColor(ContextCompat.getColor(context!!, R.color.nc_grey)) + + binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.white) + } + + private fun setBubbleOnChatMessage(message: ChatMessage) { + val resources = sharedApplication!!.resources + val bgBubbleColor = if (message.isDeleted) { + ResourcesCompat.getColor(resources, R.color.bg_message_list_outcoming_bubble_deleted, null) + } else { + ResourcesCompat.getColor(resources, R.color.bg_message_list_outcoming_bubble, null) + } + if (message.isGrouped) { + val bubbleDrawable = getMessageSelector( + bgBubbleColor, + ResourcesCompat.getColor(resources, R.color.transparent, null), + bgBubbleColor, + R.drawable.shape_grouped_outcoming_message + ) + ViewCompat.setBackground(bubble, bubbleDrawable) + } else { + val bubbleDrawable = getMessageSelector( + bgBubbleColor, + ResourcesCompat.getColor(resources, R.color.transparent, null), + bgBubbleColor, + R.drawable.shape_outcoming_message + ) + ViewCompat.setBackground(bubble, bubbleDrawable) + } + } + + private fun processMessageParameters( + messageParameters: HashMap>, + message: ChatMessage, + messageString: Spannable + ): Spannable { + var messageString1 = messageString + for (key in messageParameters.keys) { + val individualHashMap: HashMap? = message.messageParameters[key] + if (individualHashMap != null) { + if (individualHashMap["type"] == "user" || + individualHashMap["type"] == "guest" || + individualHashMap["type"] == "call" + ) { + messageString1 = searchAndReplaceWithMentionSpan( + binding.messageText.context, + messageString1, + individualHashMap["id"]!!, + individualHashMap["name"]!!, + individualHashMap["type"]!!, + message.activeUser, + R.xml.chip_others + ) + } else if (individualHashMap["type"] == "file") { + realView.setOnClickListener { v: View? -> + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"])) + context!!.startActivity(browserIntent) + } + } + } + } + return messageString1 + } + companion object { const val TEXT_SIZE_MULTIPLIER = 2.5 } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt index 335940f1e..5cef4fecb 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt @@ -87,36 +87,11 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders updateDownloadState(message) binding.seekbar.max = message.voiceMessageDuration - if (message.isPlayingVoiceMessage) { - showPlayButton() - binding.playPauseBtn.icon = ContextCompat.getDrawable( - context!!, - R.drawable.ic_baseline_pause_voice_message_24 - ) - binding.seekbar.progress = message.voiceMessagePlayedSeconds - } else { - binding.playPauseBtn.visibility = View.VISIBLE - binding.playPauseBtn.icon = ContextCompat.getDrawable( - context!!, - R.drawable.ic_baseline_play_arrow_voice_message_24 - ) - } + handleIsPlayingVoiceMessageState(message) - if (message.isDownloadingVoiceMessage) { - showVoiceMessageLoading() - } else { - binding.progressBar.visibility = View.GONE - } + handleIsDownloadingVoiceMessageState(message) - if (message.resetVoiceMessage) { - binding.playPauseBtn.visibility = View.VISIBLE - binding.playPauseBtn.icon = ContextCompat.getDrawable( - context!!, - R.drawable.ic_baseline_play_arrow_voice_message_24 - ) - binding.seekbar.progress = SEEKBAR_START - message.resetVoiceMessage = false - } + handleResetVoiceMessageState(message) binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onStopTrackingTouch(seekBar: SeekBar) { @@ -156,6 +131,43 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders binding.checkMark.setContentDescription(readStatusContentDescriptionString) } + private fun handleResetVoiceMessageState(message: ChatMessage) { + if (message.resetVoiceMessage) { + binding.playPauseBtn.visibility = View.VISIBLE + binding.playPauseBtn.icon = ContextCompat.getDrawable( + context!!, + R.drawable.ic_baseline_play_arrow_voice_message_24 + ) + binding.seekbar.progress = SEEKBAR_START + message.resetVoiceMessage = false + } + } + + private fun handleIsDownloadingVoiceMessageState(message: ChatMessage) { + if (message.isDownloadingVoiceMessage) { + showVoiceMessageLoading() + } else { + binding.progressBar.visibility = View.GONE + } + } + + private fun handleIsPlayingVoiceMessageState(message: ChatMessage) { + if (message.isPlayingVoiceMessage) { + showPlayButton() + binding.playPauseBtn.icon = ContextCompat.getDrawable( + context!!, + R.drawable.ic_baseline_pause_voice_message_24 + ) + binding.seekbar.progress = message.voiceMessagePlayedSeconds + } else { + binding.playPauseBtn.visibility = View.VISIBLE + binding.playPauseBtn.icon = ContextCompat.getDrawable( + context!!, + R.drawable.ic_baseline_play_arrow_voice_message_24 + ) + } + } + private fun updateDownloadState(message: ChatMessage) { // check if download worker is already running val fileId = message.getSelectedIndividualHashMap()["id"] diff --git a/detekt.yml b/detekt.yml index 6f52592b1..ee704fefa 100644 --- a/detekt.yml +++ b/detekt.yml @@ -1,5 +1,5 @@ build: - maxIssues: 108 + maxIssues: 99 weights: # complexity: 2 # LongParameterList: 1