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 @@ + + + + + + + + + + + + + + + + + +