splitting up complex methods into smaller, easier to understand methods

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2022-03-15 18:21:01 +01:00
parent c9f230a10b
commit eed209428e
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
6 changed files with 414 additions and 339 deletions

View File

@ -158,84 +158,7 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
base64DecodedSubject base64DecodedSubject
) )
if (signatureVerification!!.signatureValid) { if (signatureVerification!!.signatureValid) {
val cipher = Cipher.getInstance("RSA/None/PKCS1Padding") decryptMessage(privateKey, base64DecodedSubject, subject, signature)
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)
}
}
} }
} catch (e1: NoSuchAlgorithmException) { } catch (e1: NoSuchAlgorithmException) {
Log.d(NotificationWorker.TAG, "No proper algorithm to decrypt the message " + e1.localizedMessage) 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( private fun checkIfCallIsActive(
signatureVerification: SignatureVerification, signatureVerification: SignatureVerification,
decryptedPushMessage: DecryptedPushMessage decryptedPushMessage: DecryptedPushMessage

View File

@ -153,24 +153,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
showVoiceMessageLoading() showVoiceMessageLoading()
WorkManager.getInstance(context!!).getWorkInfoByIdLiveData(workInfo.id) WorkManager.getInstance(context!!).getWorkInfoByIdLiveData(workInfo.id)
.observeForever { info: WorkInfo? -> .observeForever { info: WorkInfo? ->
if (info != null) { showStatus(info)
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 -> {
}
}
}
} }
} }
} }
@ -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() { private fun showPlayButton() {
binding.playPauseBtn.visibility = View.VISIBLE binding.playPauseBtn.visibility = View.VISIBLE
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
@ -203,31 +207,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
} }
if (!message.isGrouped && !message.isOneToOneConversation) { if (!message.isGrouped && !message.isOneToOneConversation) {
binding.messageUserAvatar.visibility = View.VISIBLE setAvatarOnMessage(message)
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<Drawable>(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)
}
} else { } else {
if (message.isOneToOneConversation) { if (message.isOneToOneConversation) {
binding.messageUserAvatar.visibility = View.GONE 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<Drawable>(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) { private fun colorizeMessageBubble(message: ChatMessage) {
val resources = itemView.resources val resources = itemView.resources

View File

@ -26,6 +26,7 @@ package com.nextcloud.talk.adapters.messages
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.net.Uri 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.TextMatchers
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders import com.stfalcon.chatkit.messages.MessageHolders
import java.util.HashMap
import javax.inject.Inject import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
@ -72,44 +74,10 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
override fun onBind(message: ChatMessage) { override fun onBind(message: ChatMessage) {
super.onBind(message) super.onBind(message)
sharedApplication!!.componentApplication.inject(this) sharedApplication!!.componentApplication.inject(this)
val author: String = message.actorDisplayName processAuthor(message)
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)
}
if (!message.isGrouped && !message.isOneToOneConversation) { if (!message.isGrouped && !message.isOneToOneConversation) {
binding.messageUserAvatar.visibility = View.VISIBLE showAvatarOnChatMessage(message)
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<Drawable>(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)
}
} else { } else {
if (message.isOneToOneConversation) { if (message.isOneToOneConversation) {
binding.messageUserAvatar.visibility = View.GONE binding.messageUserAvatar.visibility = View.GONE
@ -121,6 +89,53 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
val resources = itemView.resources 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) { val bgBubbleColor = if (message.isDeleted) {
ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble_deleted, null) ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble_deleted, null)
} else { } else {
@ -139,97 +154,110 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
bgBubbleColor, bubbleResource bgBubbleColor, bubbleResource
) )
ViewCompat.setBackground(bubble, bubbleDrawable) 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.messageQuote.quotedMessageAuthor
binding.messageTime.setTextColor(ResourcesCompat.getColor(resources, R.color.warm_grey_four, null)) .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<Drawable>(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) { private fun processMessageParameters(
for (key in messageParameters.keys) { messageParameters: HashMap<String, HashMap<String, String>>,
val individualHashMap = message.messageParameters[key] message: ChatMessage,
if (individualHashMap != null) { messageString: Spannable
if ( ): Spannable {
individualHashMap["type"] == "user" || var messageStringInternal = messageString
individualHashMap["type"] == "guest" || for (key in messageParameters.keys) {
individualHashMap["type"] == "call" val individualHashMap = message.messageParameters[key]
) { if (individualHashMap != null) {
if (individualHashMap["id"] == message.activeUser!!.userId) { if (
messageString = DisplayUtils.searchAndReplaceWithMentionSpan( individualHashMap["type"] == "user" ||
binding.messageText.context, individualHashMap["type"] == "guest" ||
messageString, individualHashMap["type"] == "call"
individualHashMap["id"]!!, ) {
individualHashMap["name"]!!, if (individualHashMap["id"] == message.activeUser!!.userId) {
individualHashMap["type"]!!, messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan(
message.activeUser!!, binding.messageText.context,
R.xml.chip_you messageStringInternal,
) individualHashMap["id"]!!,
} else { individualHashMap["name"]!!,
messageString = DisplayUtils.searchAndReplaceWithMentionSpan( individualHashMap["type"]!!,
binding.messageText.context, message.activeUser!!,
messageString, R.xml.chip_you
individualHashMap["id"]!!, )
individualHashMap["name"]!!, } else {
individualHashMap["type"]!!, messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan(
message.activeUser!!, binding.messageText.context,
R.xml.chip_others messageStringInternal,
) individualHashMap["id"]!!,
} individualHashMap["name"]!!,
} else if (individualHashMap["type"] == "file") { individualHashMap["type"]!!,
itemView.setOnClickListener { v -> message.activeUser!!,
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"])) R.xml.chip_others
context!!.startActivity(browserIntent) )
} }
} 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
} }
return messageStringInternal
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)
} }
companion object { companion object {

View File

@ -72,30 +72,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
layoutParams.isWrapBefore = false layoutParams.isWrapBefore = false
var textSize = context!!.resources.getDimension(R.dimen.chat_text_size) var textSize = context!!.resources.getDimension(R.dimen.chat_text_size)
if (messageParameters != null && messageParameters.size > 0) { if (messageParameters != null && messageParameters.size > 0) {
for (key in messageParameters.keys) { messageString = processMessageParameters(messageParameters, message, messageString)
val individualHashMap: HashMap<String, String>? = 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)
}
}
}
}
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) {
textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat()
layoutParams.isWrapBefore = true layoutParams.isWrapBefore = true
@ -104,59 +81,16 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
) )
realView.isSelected = true realView.isSelected = true
} }
val resources = sharedApplication!!.resources
val bgBubbleColor = if (message.isDeleted) { setBubbleOnChatMessage(message)
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)
}
binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
binding.messageTime.layoutParams = layoutParams binding.messageTime.layoutParams = layoutParams
binding.messageText.text = messageString binding.messageText.text = messageString
// parent message handling // parent message handling
if (!message.isDeleted && message.parentMessage != null) { if (!message.isDeleted && message.parentMessage != null) {
val parentChatMessage = message.parentMessage processParentMessage(message)
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)
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} else { } else {
binding.messageQuote.quotedChatMessageView.visibility = View.GONE binding.messageQuote.quotedChatMessageView.visibility = View.GONE
@ -186,6 +120,90 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable) 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<String, HashMap<String, String>>,
message: ChatMessage,
messageString: Spannable
): Spannable {
var messageString1 = messageString
for (key in messageParameters.keys) {
val individualHashMap: HashMap<String, String>? = 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 { companion object {
const val TEXT_SIZE_MULTIPLIER = 2.5 const val TEXT_SIZE_MULTIPLIER = 2.5
} }

View File

@ -87,36 +87,11 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
updateDownloadState(message) updateDownloadState(message)
binding.seekbar.max = message.voiceMessageDuration binding.seekbar.max = message.voiceMessageDuration
if (message.isPlayingVoiceMessage) { handleIsPlayingVoiceMessageState(message)
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
)
}
if (message.isDownloadingVoiceMessage) { handleIsDownloadingVoiceMessageState(message)
showVoiceMessageLoading()
} else {
binding.progressBar.visibility = View.GONE
}
if (message.resetVoiceMessage) { handleResetVoiceMessageState(message)
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
}
binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onStopTrackingTouch(seekBar: SeekBar) { override fun onStopTrackingTouch(seekBar: SeekBar) {
@ -156,6 +131,43 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
binding.checkMark.setContentDescription(readStatusContentDescriptionString) 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) { private fun updateDownloadState(message: ChatMessage) {
// check if download worker is already running // check if download worker is already running
val fileId = message.getSelectedIndividualHashMap()["id"] val fileId = message.getSelectedIndividualHashMap()["id"]

View File

@ -1,5 +1,5 @@
build: build:
maxIssues: 108 maxIssues: 99
weights: weights:
# complexity: 2 # complexity: 2
# LongParameterList: 1 # LongParameterList: 1