From 1aa15ebd95ef1bd72acd88c737180d1cb0e7a979 Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Sat, 29 May 2021 23:39:34 +0200 Subject: [PATCH] differ between incoming and outcoming messages for location logic was copied from: - MagicIncomingTextMessageViewHolder.kt - MagicOutcomingTextMessageViewHolder.kt xml design was copied from: - item_custom_incoming_text_message.xml - item_custom_outcoming_text_message.xml ... and extended for location related things. because of copying there is now quite a lot of redundant code! But ViewHolders should generally be refactored in the future.. (better inheritance(?) and analyze which of Marios changes to the Chatkit lib were really necessary or if this can be done in an other way..) Signed-off-by: Marcel Hibbe --- .../IncomingLocationMessageViewHolder.kt | 322 ++++++++++++++++++ .../messages/LocationMessageViewHolder.kt | 128 ------- .../MagicIncomingTextMessageViewHolder.kt | 8 +- .../MagicPreviewMessageViewHolder.java | 2 - .../OutcomingLocationMessageViewHolder.kt | 285 ++++++++++++++++ .../talk/controllers/ChatController.kt | 11 +- .../item_custom_incoming_location_message.xml | 87 +++++ .../layout/item_custom_location_message.xml | 51 --- ...item_custom_outcoming_location_message.xml | 81 +++++ 9 files changed, 785 insertions(+), 190 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt delete mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/LocationMessageViewHolder.kt create mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt create mode 100644 app/src/main/res/layout/item_custom_incoming_location_message.xml delete mode 100644 app/src/main/res/layout/item_custom_location_message.xml create mode 100644 app/src/main/res/layout/item_custom_outcoming_location_message.xml diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt new file mode 100644 index 000000000..32e0b65ca --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt @@ -0,0 +1,322 @@ +package com.nextcloud.talk.adapters.messages + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable +import android.net.Uri +import android.text.Spannable +import android.text.SpannableString +import android.text.TextUtils +import android.util.Log +import android.util.TypedValue +import android.view.MotionEvent +import android.view.View +import android.webkit.WebView +import android.webkit.WebViewClient +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import android.widget.Toast +import androidx.core.view.ViewCompat +import androidx.emoji.widget.EmojiTextView +import autodagger.AutoInjector +import butterknife.BindView +import butterknife.ButterKnife +import coil.load +import com.amulyakhare.textdrawable.TextDrawable +import com.facebook.drawee.view.SimpleDraweeView +import com.nextcloud.talk.R +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication +import com.nextcloud.talk.models.json.chat.ChatMessage +import com.nextcloud.talk.utils.ApiUtils +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.net.URLEncoder +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +class IncomingLocationMessageViewHolder(incomingView: View) : MessageHolders +.IncomingTextMessageViewHolder(incomingView) { + + private val TAG = "LocationMessageViewHolder" + + var mapProviderUrl: String = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" + var mapProviderAttribution: String = "OpenStreetMap contributors" + + var locationLon: String? = "" + var locationLat: String? = "" + var locationName: String? = "" + var locationGeoLink: String? = "" + + @JvmField + @BindView(R.id.messageAuthor) + var messageAuthor: EmojiTextView? = null + + @JvmField + @BindView(R.id.messageText) + var messageText: EmojiTextView? = null + + @JvmField + @BindView(R.id.messageUserAvatar) + var messageUserAvatarView: SimpleDraweeView? = null + + @JvmField + @BindView(R.id.messageTime) + var messageTimeView: TextView? = null + + @JvmField + @BindView(R.id.quotedChatMessageView) + var quotedChatMessageView: RelativeLayout? = null + + @JvmField + @BindView(R.id.quotedMessageAuthor) + var quotedUserName: EmojiTextView? = null + + @JvmField + @BindView(R.id.quotedMessageImage) + var quotedMessagePreview: ImageView? = null + + @JvmField + @BindView(R.id.quotedMessage) + var quotedMessage: EmojiTextView? = null + + @JvmField + @BindView(R.id.quoteColoredView) + var quoteColoredView: View? = null + + @JvmField + @Inject + var context: Context? = null + + @JvmField + @Inject + var appPreferences: AppPreferences? = null + + @JvmField + @BindView(R.id.webview) + var webview: WebView? = null + + init { + ButterKnife.bind( + this, + itemView + ) + } + + @SuppressLint("SetTextI18n", "SetJavaScriptEnabled", "ClickableViewAccessibility") + override fun onBind(message: ChatMessage) { + super.onBind(message) + sharedApplication!!.componentApplication.inject(this) + val author: String = message.actorDisplayName + if (!TextUtils.isEmpty(author)) { + messageAuthor!!.text = author + } else { + messageAuthor!!.setText(R.string.nc_nick_guest) + } + + if (!message.isGrouped && !message.isOneToOneConversation) { + messageUserAvatarView!!.visibility = View.VISIBLE + if (message.actorType == "guests") { + // do nothing, avatar is set + } else if (message.actorType == "bots" && message.actorId == "changelog") { + val layers = arrayOfNulls(2) + layers[0] = context?.getDrawable(R.drawable.ic_launcher_background) + layers[1] = context?.getDrawable(R.drawable.ic_launcher_foreground) + val layerDrawable = LayerDrawable(layers) + messageUserAvatarView?.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable)) + } else if (message.actorType == "bots") { + val drawable = TextDrawable.builder() + .beginConfig() + .bold() + .endConfig() + .buildRound( + ">", + context!!.resources.getColor(R.color.black) + ) + messageUserAvatarView!!.visibility = View.VISIBLE + messageUserAvatarView?.setImageDrawable(drawable) + } + } else { + if (message.isOneToOneConversation) { + messageUserAvatarView!!.visibility = View.GONE + } else { + messageUserAvatarView!!.visibility = View.INVISIBLE + } + messageAuthor!!.visibility = View.GONE + } + + val resources = itemView.resources + + val bgBubbleColor = if (message.isDeleted) { + resources.getColor(R.color.bg_message_list_incoming_bubble_deleted) + } else { + resources.getColor(R.color.bg_message_list_incoming_bubble) + } + + var bubbleResource = R.drawable.shape_incoming_message + + if (message.isGrouped) { + bubbleResource = R.drawable.shape_grouped_incoming_message + } + + val bubbleDrawable = DisplayUtils.getMessageSelector( + bgBubbleColor, + resources.getColor(R.color.transparent), + bgBubbleColor, bubbleResource + ) + ViewCompat.setBackground(bubble, bubbleDrawable) + + val messageParameters = message.messageParameters + + itemView.isSelected = false + messageTimeView!!.setTextColor(context?.resources!!.getColor(R.color.warm_grey_four)) + + var messageString: Spannable = SpannableString(message.text) + + var textSize = context?.resources!!.getDimension(R.dimen.chat_text_size) + + 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( + messageText!!.context, + messageString, + individualHashMap["id"]!!, + individualHashMap["name"]!!, + individualHashMap["type"]!!, + message.activeUser!!, + R.xml.chip_you + ) + } else { + messageString = DisplayUtils.searchAndReplaceWithMentionSpan( + 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) + } + } + } + } + } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { + textSize = (textSize * 2.5).toFloat() + itemView.isSelected = true + messageAuthor!!.visibility = View.GONE + } + + messageText!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) + messageText!!.text = messageString + + // parent message handling + + if (!message.isDeleted && message.parentMessage != null) { + var parentChatMessage = message.parentMessage + parentChatMessage.activeUser = message.activeUser + parentChatMessage.imageUrl?.let { + quotedMessagePreview?.visibility = View.VISIBLE + quotedMessagePreview?.load(it) { + addHeader( + "Authorization", + ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token) + ) + } + } ?: run { + quotedMessagePreview?.visibility = View.GONE + } + quotedUserName?.text = parentChatMessage.actorDisplayName + ?: context!!.getText(R.string.nc_nick_guest) + quotedMessage?.text = parentChatMessage.text + + quotedUserName?.setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast)) + + if (parentChatMessage.actorId?.equals(message.activeUser.userId) == true) { + quoteColoredView?.setBackgroundResource(R.color.colorPrimary) + } else { + quoteColoredView?.setBackgroundResource(R.color.textColorMaxContrast) + } + + quotedChatMessageView?.visibility = View.VISIBLE + } else { + quotedChatMessageView?.visibility = View.GONE + } + + // geo-location + + if (message.messageParameters != null && message.messageParameters.size > 0) { + for (key in message.messageParameters.keys) { + val individualHashMap: Map = message.messageParameters[key]!! + if (individualHashMap["type"] == "geo-location") { + locationLon = individualHashMap["longitude"] + locationLat = individualHashMap["latitude"] + locationName = individualHashMap["name"] + locationGeoLink = individualHashMap["id"] + } + } + } + + webview?.settings?.javaScriptEnabled = true + + webview?.webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { + return if (url != null && (url.startsWith("http://") || url.startsWith("https://")) + ) { + view?.context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) + true + } else { + false + } + } + } + + val urlStringBuffer = StringBuffer("file:///android_asset/leafletMapMessagePreview.html") + urlStringBuffer.append("?mapProviderUrl=" + URLEncoder.encode(mapProviderUrl)) + urlStringBuffer.append("&mapProviderAttribution=" + URLEncoder.encode(mapProviderAttribution)) + urlStringBuffer.append("&locationLat=" + URLEncoder.encode(locationLat)) + urlStringBuffer.append("&locationLon=" + URLEncoder.encode(locationLon)) + urlStringBuffer.append("&locationName=" + URLEncoder.encode(locationName)) + urlStringBuffer.append("&locationGeoLink=" + URLEncoder.encode(locationGeoLink)) + + webview?.loadUrl(urlStringBuffer.toString()) + + webview?.setOnTouchListener(object : View.OnTouchListener { + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + when (event?.action) { + MotionEvent.ACTION_UP -> openGeoLink() + } + + return v?.onTouchEvent(event) ?: true + } + }) + } + + private fun openGeoLink() { + if (!locationGeoLink.isNullOrEmpty()) { + val geoLinkWithMarker = addMarkerToGeoLink(locationGeoLink!!) + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(geoLinkWithMarker)) + context!!.startActivity(browserIntent) + } else { + Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() + Log.e(TAG, "locationGeoLink was null or empty") + } + } + + private fun addMarkerToGeoLink(locationGeoLink: String): String { + return locationGeoLink.replace("geo:", "geo:0,0?q=") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/LocationMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/LocationMessageViewHolder.kt deleted file mode 100644 index 62da7eb85..000000000 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/LocationMessageViewHolder.kt +++ /dev/null @@ -1,128 +0,0 @@ -package com.nextcloud.talk.adapters.messages - -import android.annotation.SuppressLint -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.util.Log -import android.view.MotionEvent -import android.view.View -import android.webkit.WebView -import android.webkit.WebViewClient -import android.widget.TextView -import android.widget.Toast -import autodagger.AutoInjector -import butterknife.BindView -import butterknife.ButterKnife -import com.nextcloud.talk.R -import com.nextcloud.talk.application.NextcloudTalkApplication -import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication -import com.nextcloud.talk.models.json.chat.ChatMessage -import com.stfalcon.chatkit.messages.MessageHolders -import java.net.URLEncoder -import javax.inject.Inject - -@AutoInjector(NextcloudTalkApplication::class) -class LocationMessageViewHolder(incomingView: View) : MessageHolders -.IncomingTextMessageViewHolder(incomingView) { - - private val TAG = "LocationMessageViewHolder" - - var mapProviderUrl: String = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" - var mapProviderAttribution: String = "OpenStreetMap contributors" - - var locationLon: String? = "" - var locationLat: String? = "" - var locationName: String? = "" - var locationGeoLink: String? = "" - - @JvmField - @BindView(R.id.locationText) - var messageText: TextView? = null - - @JvmField - @BindView(R.id.webview) - var webview: WebView? = null - - @JvmField - @Inject - var context: Context? = null - - init { - ButterKnife.bind( - this, - itemView - ) - } - - @SuppressLint("SetTextI18n", "SetJavaScriptEnabled", "ClickableViewAccessibility") - override fun onBind(message: ChatMessage) { - super.onBind(message) - sharedApplication!!.componentApplication.inject(this) - // if (message.messageType == ChatMessage.MessageType.SINGLE_NC_GEOLOCATION_MESSAGE) { - // Log.d(TAG, "handle geolocation here") - // messageText!!.text = "geolocation..." - // } - if (message.messageParameters != null && message.messageParameters.size > 0) { - for (key in message.messageParameters.keys) { - val individualHashMap: Map = message.messageParameters[key]!! - if (individualHashMap["type"] == "geo-location") { - locationLon = individualHashMap["longitude"] - locationLat = individualHashMap["latitude"] - locationName = individualHashMap["name"] - locationGeoLink = individualHashMap["id"] - } - } - } - - - webview?.settings?.javaScriptEnabled = true - - webview?.webViewClient = object : WebViewClient() { - override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { - return if (url != null && (url.startsWith("http://") || url.startsWith("https://")) - ) { - view?.context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) - true - } else { - false - } - } - } - - val urlStringBuffer = StringBuffer("file:///android_asset/leafletMapMessagePreview.html") - urlStringBuffer.append("?mapProviderUrl=" + URLEncoder.encode(mapProviderUrl)) - urlStringBuffer.append("&mapProviderAttribution=" + URLEncoder.encode(mapProviderAttribution)) - urlStringBuffer.append("&locationLat=" + URLEncoder.encode(locationLat)) - urlStringBuffer.append("&locationLon=" + URLEncoder.encode(locationLon)) - urlStringBuffer.append("&locationName=" + URLEncoder.encode(locationName)) - urlStringBuffer.append("&locationGeoLink=" + URLEncoder.encode(locationGeoLink)) - - webview?.loadUrl(urlStringBuffer.toString()) - - webview?.setOnTouchListener(object : View.OnTouchListener { - override fun onTouch(v: View?, event: MotionEvent?): Boolean { - when (event?.action) { - MotionEvent.ACTION_UP -> openGeoLink() - } - - return v?.onTouchEvent(event) ?: true - } - }) - } - - private fun openGeoLink() { - if (!locationGeoLink.isNullOrEmpty()) { - val geoLinkWithMarker = addMarkerToGeoLink(locationGeoLink!!) - val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(geoLinkWithMarker)) - context!!.startActivity(browserIntent) - } else { - Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() - Log.e(TAG, "locationGeoLink was null or empty") - } - } - - private fun addMarkerToGeoLink(locationGeoLink: String): String { - return locationGeoLink.replace("geo:", "geo:0,0?q=") - } -} \ No newline at end of file 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 abf27d53a..5d7fb295b 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 @@ -101,10 +101,6 @@ class MagicIncomingTextMessageViewHolder(itemView: View) : MessageHolders @Inject var appPreferences: AppPreferences? = null - init { - ButterKnife.bind(this, itemView) - } - override fun onBind(message: ChatMessage) { super.onBind(message) sharedApplication!!.componentApplication.inject(this) @@ -258,4 +254,8 @@ class MagicIncomingTextMessageViewHolder(itemView: View) : MessageHolders itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable) } + + init { + ButterKnife.bindthis, itemView) + } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java index 7043a5cc2..47ba04486 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java @@ -177,8 +177,6 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM } catch (ExecutionException | InterruptedException e) { Log.e(TAG, "Error when checking if worker already exists", e); } - } else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_NC_GEOLOCATION_MESSAGE) { - Log.d(TAG, "handle geolocation here"); } else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE) { messageText.setText("GIPHY"); DisplayUtils.setClickableString("GIPHY", "https://giphy.com", messageText); diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt new file mode 100644 index 000000000..9e4136a43 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt @@ -0,0 +1,285 @@ +package com.nextcloud.talk.adapters.messages + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.graphics.PorterDuff +import android.net.Uri +import android.text.Spannable +import android.text.SpannableString +import android.util.Log +import android.util.TypedValue +import android.view.MotionEvent +import android.view.View +import android.webkit.WebView +import android.webkit.WebViewClient +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import android.widget.Toast +import androidx.core.view.ViewCompat +import androidx.emoji.widget.EmojiTextView +import autodagger.AutoInjector +import butterknife.BindView +import butterknife.ButterKnife +import coil.load +import com.google.android.flexbox.FlexboxLayout +import com.nextcloud.talk.R +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication +import com.nextcloud.talk.models.json.chat.ChatMessage +import com.nextcloud.talk.models.json.chat.ReadStatus +import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.DisplayUtils +import com.nextcloud.talk.utils.TextMatchers +import com.stfalcon.chatkit.messages.MessageHolders +import java.net.URLEncoder +import java.util.HashMap +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders +.OutcomingTextMessageViewHolder(incomingView) { + + private val TAG = "LocationMessageViewHolder" + + var mapProviderUrl: String = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" + var mapProviderAttribution: String = "OpenStreetMap contributors" + + var locationLon: String? = "" + var locationLat: String? = "" + var locationName: String? = "" + var locationGeoLink: String? = "" + + @JvmField + @BindView(R.id.messageText) + var messageText: EmojiTextView? = null + + @JvmField + @BindView(R.id.messageTime) + var messageTimeView: TextView? = null + + @JvmField + @BindView(R.id.quotedChatMessageView) + var quotedChatMessageView: RelativeLayout? = null + + @JvmField + @BindView(R.id.quotedMessageAuthor) + var quotedUserName: EmojiTextView? = null + + @JvmField + @BindView(R.id.quotedMessageImage) + var quotedMessagePreview: ImageView? = null + + @JvmField + @BindView(R.id.quotedMessage) + var quotedMessage: EmojiTextView? = null + + @JvmField + @BindView(R.id.quoteColoredView) + var quoteColoredView: View? = null + + @JvmField + @BindView(R.id.checkMark) + var checkMark: ImageView? = null + + @JvmField + @Inject + var context: Context? = null + + @JvmField + @BindView(R.id.webview) + var webview: WebView? = null + + private val realView: View + + @SuppressLint("SetTextI18n", "SetJavaScriptEnabled", "ClickableViewAccessibility") + override fun onBind(message: ChatMessage) { + super.onBind(message) + sharedApplication!!.componentApplication.inject(this) + val messageParameters: HashMap>? = message.messageParameters + var messageString: Spannable = SpannableString(message.text) + realView.isSelected = false + messageTimeView!!.setTextColor(context!!.resources.getColor(R.color.white60)) + val layoutParams = messageTimeView!!.layoutParams as FlexboxLayout.LayoutParams + 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 = DisplayUtils.searchAndReplaceWithMentionSpan( + messageText!!.context, + messageString, + individualHashMap["id"]!!, + individualHashMap["name"]!!, + individualHashMap["type"]!!, + message.activeUser, + R.xml.chip_others + ) + } else if (individualHashMap["type"] == "file") { + realView.setOnClickListener( + View.OnClickListener { v: View? -> + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"])) + context!!.startActivity(browserIntent) + } + ) + } + } + } + } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { + textSize = (textSize * 2.5).toFloat() + layoutParams.isWrapBefore = true + messageTimeView!!.setTextColor(context!!.resources.getColor(R.color.warm_grey_four)) + realView.isSelected = true + } + val resources = sharedApplication!!.resources + val bgBubbleColor = if (message.isDeleted) { + resources.getColor(R.color.bg_message_list_outcoming_bubble_deleted) + } else { + resources.getColor(R.color.bg_message_list_outcoming_bubble) + } + if (message.isGrouped) { + val bubbleDrawable = DisplayUtils.getMessageSelector( + bgBubbleColor, + resources.getColor(R.color.transparent), + bgBubbleColor, + R.drawable.shape_grouped_outcoming_message + ) + ViewCompat.setBackground(bubble, bubbleDrawable) + } else { + val bubbleDrawable = DisplayUtils.getMessageSelector( + bgBubbleColor, + resources.getColor(R.color.transparent), + bgBubbleColor, + R.drawable.shape_outcoming_message + ) + ViewCompat.setBackground(bubble, bubbleDrawable) + } + messageText!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) + messageTimeView!!.layoutParams = layoutParams + messageText!!.text = messageString + + // parent message handling + + if (!message.isDeleted && message.parentMessage != null) { + var parentChatMessage = message.parentMessage + parentChatMessage.activeUser = message.activeUser + parentChatMessage.imageUrl?.let { + quotedMessagePreview?.visibility = View.VISIBLE + quotedMessagePreview?.load(it) { + addHeader( + "Authorization", + ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token) + ) + } + } ?: run { + quotedMessagePreview?.visibility = View.GONE + } + quotedUserName?.text = parentChatMessage.actorDisplayName + ?: context!!.getText(R.string.nc_nick_guest) + quotedMessage?.text = parentChatMessage.text + quotedMessage?.setTextColor(context!!.resources.getColor(R.color.nc_outcoming_text_default)) + quotedUserName?.setTextColor(context!!.resources.getColor(R.color.nc_grey)) + + quoteColoredView?.setBackgroundResource(R.color.white) + + quotedChatMessageView?.visibility = View.VISIBLE + } else { + quotedChatMessageView?.visibility = View.GONE + } + + val readStatusDrawableInt = when (message.readStatus) { + ReadStatus.READ -> R.drawable.ic_check_all + ReadStatus.SENT -> R.drawable.ic_check + else -> null + } + + val readStatusContentDescriptionString = when (message.readStatus) { + ReadStatus.READ -> context?.resources?.getString(R.string.nc_message_read) + ReadStatus.SENT -> context?.resources?.getString(R.string.nc_message_sent) + else -> null + } + + readStatusDrawableInt?.let { drawableInt -> + context?.resources?.getDrawable(drawableInt, null)?.let { + it.setColorFilter(context?.resources!!.getColor(R.color.white60), PorterDuff.Mode.SRC_ATOP) + checkMark?.setImageDrawable(it) + } + } + + checkMark?.setContentDescription(readStatusContentDescriptionString) + + // geo-location + + if (message.messageParameters != null && message.messageParameters.size > 0) { + for (key in message.messageParameters.keys) { + val individualHashMap: Map = message.messageParameters[key]!! + if (individualHashMap["type"] == "geo-location") { + locationLon = individualHashMap["longitude"] + locationLat = individualHashMap["latitude"] + locationName = individualHashMap["name"] + locationGeoLink = individualHashMap["id"] + } + } + } + + webview?.settings?.javaScriptEnabled = true + + webview?.webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { + return if (url != null && (url.startsWith("http://") || url.startsWith("https://")) + ) { + view?.context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) + true + } else { + false + } + } + } + + val urlStringBuffer = StringBuffer("file:///android_asset/leafletMapMessagePreview.html") + urlStringBuffer.append("?mapProviderUrl=" + URLEncoder.encode(mapProviderUrl)) + urlStringBuffer.append("&mapProviderAttribution=" + URLEncoder.encode(mapProviderAttribution)) + urlStringBuffer.append("&locationLat=" + URLEncoder.encode(locationLat)) + urlStringBuffer.append("&locationLon=" + URLEncoder.encode(locationLon)) + urlStringBuffer.append("&locationName=" + URLEncoder.encode(locationName)) + urlStringBuffer.append("&locationGeoLink=" + URLEncoder.encode(locationGeoLink)) + + webview?.loadUrl(urlStringBuffer.toString()) + + webview?.setOnTouchListener(object : View.OnTouchListener { + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + when (event?.action) { + MotionEvent.ACTION_UP -> openGeoLink() + } + + return v?.onTouchEvent(event) ?: true + } + }) + } + + private fun openGeoLink() { + if (!locationGeoLink.isNullOrEmpty()) { + val geoLinkWithMarker = addMarkerToGeoLink(locationGeoLink!!) + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(geoLinkWithMarker)) + context!!.startActivity(browserIntent) + } else { + Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() + Log.e(TAG, "locationGeoLink was null or empty") + } + } + + private fun addMarkerToGeoLink(locationGeoLink: String): String { + return locationGeoLink.replace("geo:", "geo:0,0?q=") + } + + init { + ButterKnife.bind(this, itemView) + this.realView = itemView + } +} \ No newline at end of file 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 9c386e038..ff15e4eae 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt @@ -78,12 +78,13 @@ import com.facebook.imagepipeline.image.CloseableImage import com.google.android.flexbox.FlexboxLayout import com.nextcloud.talk.R import com.nextcloud.talk.activities.MagicCallActivity -import com.nextcloud.talk.adapters.messages.LocationMessageViewHolder +import com.nextcloud.talk.adapters.messages.IncomingLocationMessageViewHolder import com.nextcloud.talk.adapters.messages.MagicIncomingTextMessageViewHolder import com.nextcloud.talk.adapters.messages.MagicOutcomingTextMessageViewHolder import com.nextcloud.talk.adapters.messages.MagicPreviewMessageViewHolder import com.nextcloud.talk.adapters.messages.MagicSystemMessageViewHolder import com.nextcloud.talk.adapters.messages.MagicUnreadNoticeMessageViewHolder +import com.nextcloud.talk.adapters.messages.OutcomingLocationMessageViewHolder import com.nextcloud.talk.adapters.messages.TalkMessagesListAdapter import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication @@ -437,10 +438,10 @@ class ChatController(args: Bundle) : messageHolders.registerContentType( CONTENT_TYPE_LOCATION, - LocationMessageViewHolder::class.java, - R.layout.item_custom_location_message, - LocationMessageViewHolder::class.java, - R.layout.item_custom_location_message, + IncomingLocationMessageViewHolder::class.java, + R.layout.item_custom_incoming_location_message, + OutcomingLocationMessageViewHolder::class.java, + R.layout.item_custom_outcoming_location_message, this ) diff --git a/app/src/main/res/layout/item_custom_incoming_location_message.xml b/app/src/main/res/layout/item_custom_incoming_location_message.xml new file mode 100644 index 000000000..f4d7c76f3 --- /dev/null +++ b/app/src/main/res/layout/item_custom_incoming_location_message.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_custom_location_message.xml b/app/src/main/res/layout/item_custom_location_message.xml deleted file mode 100644 index 9a2ea51dd..000000000 --- a/app/src/main/res/layout/item_custom_location_message.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - diff --git a/app/src/main/res/layout/item_custom_outcoming_location_message.xml b/app/src/main/res/layout/item_custom_outcoming_location_message.xml new file mode 100644 index 000000000..2d64c54bc --- /dev/null +++ b/app/src/main/res/layout/item_custom_outcoming_location_message.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + +