From 2613c1f0749df0230d9032b732e19104841b3904 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Mon, 13 Jan 2020 11:15:20 +0100 Subject: [PATCH] Some progress on replies Signed-off-by: Mario Danic --- app/build.gradle | 4 +- .../MagicIncomingTextMessageViewHolder.java | 206 -------------- .../MagicIncomingTextMessageViewHolder.kt | 252 ++++++++++++++++++ .../MagicOutcomingTextMessageViewHolder.java | 140 ---------- .../MagicOutcomingTextMessageViewHolder.kt | 182 +++++++++++++ .../MagicPreviewMessageViewHolder.java | 16 +- .../MagicSystemMessageViewHolder.java | 6 +- .../filebrowser/models/DavResponse.java | 4 +- .../talk/models/SignatureVerification.java | 4 +- .../talk/models/json/chat/ChatMessage.java | 12 +- .../item_custom_incoming_preview_message.xml | 90 +++---- .../item_custom_incoming_text_message.xml | 2 + .../item_custom_outcoming_preview_message.xml | 28 +- .../item_custom_outcoming_text_message.xml | 2 + .../main/res/layout/item_message_quote.xml | 90 +++++++ .../main/res/layout/rv_item_browser_file.xml | 2 +- app/src/main/res/values/ints.xml | 24 ++ 17 files changed, 633 insertions(+), 431 deletions(-) delete mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java create mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt delete mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java create mode 100644 app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt create mode 100644 app/src/main/res/layout/item_message_quote.xml create mode 100644 app/src/main/res/values/ints.xml diff --git a/app/build.gradle b/app/build.gradle index b056bd7c7..078ede281 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,8 +39,8 @@ android { targetSdkVersion 28 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - versionCode 122 - versionName "7.0.8" + versionCode 115 + versionName "8" flavorDimensions "default" renderscriptTargetApi 19 diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java deleted file mode 100644 index 9855e8dfb..000000000 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017-2018 Mario Danic - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.nextcloud.talk.adapters.messages; - -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; -import android.net.Uri; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.TextUtils; -import android.util.TypedValue; -import android.view.View; -import android.widget.TextView; -import androidx.core.view.ViewCompat; -import androidx.emoji.widget.EmojiTextView; - -import autodagger.AutoInjector; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.amulyakhare.textdrawable.TextDrawable; -import com.facebook.drawee.view.SimpleDraweeView; -import com.google.android.flexbox.FlexboxLayout; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.models.json.chat.ChatMessage; -import com.nextcloud.talk.utils.DisplayUtils; -import com.nextcloud.talk.utils.TextMatchers; -import com.nextcloud.talk.utils.database.user.UserUtils; -import com.nextcloud.talk.utils.preferences.AppPreferences; -import com.stfalcon.chatkit.messages.MessageHolders; -import com.vanniktech.emoji.emoji.Emoji; - -import javax.inject.Inject; -import java.util.HashMap; -import java.util.Map; - -@AutoInjector(NextcloudTalkApplication.class) -public class MagicIncomingTextMessageViewHolder - extends MessageHolders.IncomingTextMessageViewHolder { - - @BindView(R.id.messageAuthor) - EmojiTextView messageAuthor; - - @BindView(R.id.messageText) - EmojiTextView messageText; - - @BindView(R.id.messageUserAvatar) - SimpleDraweeView messageUserAvatarView; - - @BindView(R.id.messageTime) - TextView messageTimeView; - - @Inject - UserUtils userUtils; - - @Inject - Context context; - - @Inject - AppPreferences appPreferences; - - private View itemView; - - public MagicIncomingTextMessageViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); - - this.itemView = itemView; - } - - - @Override - public void onBind(ChatMessage message) { - super.onBind(message); - String author; - - if (!TextUtils.isEmpty(author = message.getActorDisplayName())) { - messageAuthor.setText(author); - } else { - messageAuthor.setText(R.string.nc_nick_guest); - } - - if (!message.isGrouped() && !message.isOneToOneConversation()) { - messageUserAvatarView.setVisibility(View.VISIBLE); - if (message.getActorType().equals("guests")) { - // do nothing, avatar is set - } else if (message.getActorType().equals("bots") && message.getActorId().equals("changelog")) { - messageUserAvatarView.setController(null); - Drawable[] layers = new Drawable[2]; - layers[0] = context.getDrawable(R.drawable.ic_launcher_background); - layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground); - LayerDrawable layerDrawable = new LayerDrawable(layers); - - messageUserAvatarView.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable)); - } else if (message.getActorType().equals("bots")) { - messageUserAvatarView.setController(null); - TextDrawable drawable = TextDrawable.builder().beginConfig().bold().endConfig().buildRound(">", - context.getResources().getColor(R.color.black)); - messageUserAvatarView.setVisibility(View.VISIBLE); - messageUserAvatarView.getHierarchy().setPlaceholderImage(drawable); - } - } else { - if (message.isOneToOneConversation()) { - messageUserAvatarView.setVisibility(View.GONE); - } else { - messageUserAvatarView.setVisibility(View.INVISIBLE); - } - messageAuthor.setVisibility(View.GONE); - } - - Resources resources = itemView.getResources(); - - int bg_bubble_color = resources.getColor(R.color.bg_message_list_incoming_bubble); - - int bubbleResource = R.drawable.shape_incoming_message; - - if (message.isGrouped) { - bubbleResource = R.drawable.shape_grouped_incoming_message; - } - - Drawable bubbleDrawable = DisplayUtils.getMessageSelector(bg_bubble_color, - resources.getColor(R.color.transparent), - bg_bubble_color, bubbleResource); - ViewCompat.setBackground(bubble, bubbleDrawable); - - HashMap> messageParameters = message.getMessageParameters(); - - itemView.setSelected(false); - messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four)); - - FlexboxLayout.LayoutParams layoutParams = (FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams(); - layoutParams.setWrapBefore(false); - - Spannable messageString = new SpannableString(message.getText()); - - float textSize = context.getResources().getDimension(R.dimen.chat_text_size); - - if (messageParameters != null && messageParameters.size() > 0) { - for (String key : messageParameters.keySet()) { - Map individualHashMap = message.getMessageParameters().get(key); - if (individualHashMap != null) { - if (individualHashMap.get("type").equals("user") || individualHashMap.get("type").equals("guest") || individualHashMap.get("type").equals("call")) { - if (individualHashMap.get("id").equals(message.getActiveUser().getUserId())) { - messageString = - DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(), - messageString, - individualHashMap.get("id"), - individualHashMap.get("name"), - individualHashMap.get("type"), - userUtils.getUserById(message.getActiveUser().getUserId()), - R.xml.chip_you); - } else { - messageString = - DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(), - messageString, - individualHashMap.get("id"), - individualHashMap.get("name"), - individualHashMap.get("type"), - userUtils.getUserById(message.getActiveUser().getUserId()), - R.xml.chip_others); - } - - } else if (individualHashMap.get("type").equals("file")) { - itemView.setOnClickListener(v -> { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap.get("link"))); - context.startActivity(browserIntent); - }); - - } - } - } - - } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.getText())) { - textSize = (float) (textSize * 2.5); - layoutParams.setWrapBefore(true); - itemView.setSelected(true); - messageAuthor.setVisibility(View.GONE); - } - - messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); - messageTimeView.setLayoutParams(layoutParams); - messageText.setText(messageString); - } -} \ 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 new file mode 100644 index 000000000..bd6412a27 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt @@ -0,0 +1,252 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.adapters.messages + +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.TypedValue +import android.view.View +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.core.view.ViewCompat +import androidx.emoji.widget.EmojiTextView +import autodagger.AutoInjector +import butterknife.BindView +import butterknife.ButterKnife +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.DisplayUtils +import com.nextcloud.talk.utils.TextMatchers +import com.nextcloud.talk.utils.preferences.AppPreferences +import com.stfalcon.chatkit.messages.MessageHolders +import com.stfalcon.chatkit.utils.DateFormatter +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders +.IncomingTextMessageViewHolder(incomingView) { + + @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.quotedUserAvatar) + var quotedUserAvatar: SimpleDraweeView? = null + + @JvmField + @BindView(R.id.quotedMessageAuthor) + var quotedUserName: EmojiTextView? = null + + @JvmField + @BindView(R.id.quotedMessageImage) + var quotedMessagePreview: SimpleDraweeView? = null + + @JvmField + @BindView(R.id.quotedMessage) + var quotedMessage: EmojiTextView? = null + + @JvmField + @BindView(R.id.quotedMessageTime) + var quotedMessageTime: TextView? = null + + @JvmField + @BindView(R.id.quoteColoredView) + var quoteColoredView: View? = null + + @JvmField + @Inject + var context: Context? = null + + @JvmField + @Inject + var appPreferences: AppPreferences? = null + + init { + ButterKnife.bind( + this, + itemView + ) + } + + 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 bg_bubble_color = 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( + bg_bubble_color, + resources.getColor(R.color.transparent), + bg_bubble_color, 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 + + message.parentMessage?.let { parentChatMessage -> + parentChatMessage.activeUser = message.activeUser + imageLoader.loadImage(quotedUserAvatar!!, parentChatMessage.user.avatar, null) + parentChatMessage.imageUrl?.let{ + quotedMessagePreview?.visibility = View.VISIBLE + imageLoader.loadImage(quotedMessagePreview, it, null) + } ?: 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.colorPrimary)) + + quotedMessageTime?.text = DateFormatter.format(parentChatMessage.createdAt, DateFormatter.Template.TIME) + quotedMessageTime?.setTextColor(context!!.resources.getColor(R.color.warm_grey_four)) + quoteColoredView?.setBackgroundResource(R.color.colorPrimary) + quotedChatMessageView?.visibility = View.VISIBLE + } ?: run { + quotedChatMessageView?.visibility = View.GONE + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java deleted file mode 100644 index aa91bfc27..000000000 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017-2018 Mario Danic - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.nextcloud.talk.adapters.messages; - -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.text.Spannable; -import android.text.SpannableString; -import android.util.TypedValue; -import android.view.View; -import android.widget.TextView; -import androidx.core.view.ViewCompat; -import androidx.emoji.widget.EmojiTextView; - -import autodagger.AutoInjector; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.google.android.flexbox.FlexboxLayout; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.models.json.chat.ChatMessage; -import com.nextcloud.talk.utils.DisplayUtils; -import com.nextcloud.talk.utils.TextMatchers; -import com.nextcloud.talk.utils.database.user.UserUtils; -import com.stfalcon.chatkit.messages.MessageHolders; - -import javax.inject.Inject; -import java.util.HashMap; -import java.util.Map; - -@AutoInjector(NextcloudTalkApplication.class) -public class MagicOutcomingTextMessageViewHolder extends MessageHolders.OutcomingTextMessageViewHolder { - @BindView(R.id.messageText) - EmojiTextView messageText; - - @BindView(R.id.messageTime) - TextView messageTimeView; - - @Inject - UserUtils userUtils; - - @Inject - Context context; - - private View itemView; - - public MagicOutcomingTextMessageViewHolder(View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); - - this.itemView = itemView; - } - - @Override - public void onBind(ChatMessage message) { - super.onBind(message); - - HashMap> messageParameters = message.getMessageParameters(); - - Spannable messageString = new SpannableString(message.getText()); - - itemView.setSelected(false); - messageTimeView.setTextColor(context.getResources().getColor(R.color.white60)); - - FlexboxLayout.LayoutParams layoutParams = (FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams(); - layoutParams.setWrapBefore(false); - - float textSize = context.getResources().getDimension(R.dimen.chat_text_size); - - if (messageParameters != null && messageParameters.size() > 0) { - for (String key : messageParameters.keySet()) { - Map individualHashMap = message.getMessageParameters().get(key); - if (individualHashMap != null) { - if (individualHashMap.get("type").equals("user") || individualHashMap.get("type").equals("guest") || individualHashMap.get("type").equals("call")) { - messageString = - DisplayUtils.searchAndReplaceWithMentionSpan(messageText.getContext(), - messageString, - individualHashMap.get("id"), - individualHashMap.get("name"), - individualHashMap.get("type"), - userUtils.getUserById(message.getActiveUser().getUserId()), - R.xml.chip_others); - } else if (individualHashMap.get("type").equals("file")) { - itemView.setOnClickListener(v -> { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap.get("link"))); - context.startActivity(browserIntent); - }); - - } - } - } - - } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.getText())) { - textSize = (float) (textSize * 2.5); - layoutParams.setWrapBefore(true); - messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four)); - itemView.setSelected(true); - } - - Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources(); - if (message.isGrouped) { - Drawable bubbleDrawable = - DisplayUtils.getMessageSelector(resources.getColor(R.color.bg_message_list_outcoming_bubble), - resources.getColor(R.color.transparent), - resources.getColor(R.color.bg_message_list_outcoming_bubble), R.drawable.shape_grouped_outcoming_message); - ViewCompat.setBackground(bubble, bubbleDrawable); - } else { - Drawable bubbleDrawable = DisplayUtils.getMessageSelector(resources.getColor(R.color.bg_message_list_outcoming_bubble), - resources.getColor(R.color.transparent), - resources.getColor(R.color.bg_message_list_outcoming_bubble), R.drawable.shape_outcoming_message); - ViewCompat.setBackground(bubble, bubbleDrawable); - } - - messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); - messageTimeView.setLayoutParams(layoutParams); - messageText.setText(messageString); - } -} diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt new file mode 100644 index 000000000..ab06e8c50 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt @@ -0,0 +1,182 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.nextcloud.talk.adapters.messages + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.text.Spannable +import android.text.SpannableString +import android.util.TypedValue +import android.view.View +import android.widget.ImageView +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.core.view.ViewCompat +import androidx.emoji.widget.EmojiTextView +import autodagger.AutoInjector +import butterknife.BindView +import butterknife.ButterKnife +import com.facebook.drawee.view.SimpleDraweeView +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.utils.DisplayUtils.getMessageSelector +import com.nextcloud.talk.utils.DisplayUtils.searchAndReplaceWithMentionSpan +import com.nextcloud.talk.utils.TextMatchers +import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder +import com.stfalcon.chatkit.utils.DateFormatter +import java.util.* +import javax.inject.Inject + +@AutoInjector(NextcloudTalkApplication::class) +class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewHolder(itemView) { + @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.quotedUserAvatar) + var quotedUserAvatar: SimpleDraweeView? = null + + @JvmField + @BindView(R.id.quotedMessageAuthor) + var quotedUserName: EmojiTextView? = null + + @JvmField + @BindView(R.id.quotedMessageImage) + var quotedMessagePreview: SimpleDraweeView? = null + + @JvmField + @BindView(R.id.quotedMessage) + var quotedMessage: EmojiTextView? = null + + @JvmField + @BindView(R.id.quotedMessageTime) + var quotedMessageTime: TextView? = null + + @JvmField + @BindView(R.id.quoteColoredView) + var quoteColoredView: View? = null + + @JvmField + @Inject + var context: Context? = null + + private val realView: View + 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 = 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 + if (message.isGrouped) { + val bubbleDrawable = getMessageSelector( + resources.getColor(R.color.bg_message_list_outcoming_bubble), + resources.getColor(R.color.transparent), + resources.getColor(R.color.bg_message_list_outcoming_bubble), + R.drawable.shape_grouped_outcoming_message) + ViewCompat.setBackground(bubble, bubbleDrawable) + } else { + val bubbleDrawable = getMessageSelector( + resources.getColor(R.color.bg_message_list_outcoming_bubble), + resources.getColor(R.color.transparent), + resources.getColor(R.color.bg_message_list_outcoming_bubble), + 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 + + message.parentMessage?.let { parentChatMessage -> + parentChatMessage.activeUser = message.activeUser + imageLoader.loadImage(quotedUserAvatar, parentChatMessage.user.avatar, null) + parentChatMessage.imageUrl?.let{ + quotedMessagePreview?.visibility = View.VISIBLE + imageLoader.loadImage(quotedMessagePreview, it, null) + } ?: 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)) + + quotedMessageTime?.text = DateFormatter.format(parentChatMessage.createdAt, DateFormatter.Template.TIME) + quotedMessageTime?.setTextColor(context!!.resources.getColor(R.color.white60)) + quoteColoredView?.setBackgroundResource(R.color.white) + + quotedChatMessageView?.visibility = View.VISIBLE + } ?: run { + quotedChatMessageView?.visibility = View.GONE + } + + } + + init { + ButterKnife.bind(this, itemView) + this.realView = itemView + } +} \ No newline at end of file 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 455ca5375..826611432 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 @@ -81,8 +81,8 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM public void onBind(ChatMessage message) { super.onBind(message); if (userAvatar != null) { - if (message.isGrouped || message.isOneToOneConversation()) { - if (message.isOneToOneConversation()) { + if (message.isGrouped || message.isOneToOneConversation) { + if (message.isOneToOneConversation) { userAvatar.setVisibility(View.GONE); } else { userAvatar.setVisibility(View.INVISIBLE); @@ -90,7 +90,7 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM } else { userAvatar.setVisibility(View.VISIBLE); - if ("bots".equals(message.getActorType()) && "changelog".equals(message.getActorId())) { + if ("bots".equals(message.actorType) && "changelog".equals(message.actorId)) { Drawable[] layers = new Drawable[2]; layers[0] = context.getDrawable(R.drawable.ic_launcher_background); layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground); @@ -108,13 +108,13 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM if (message.getSelectedIndividualHashMap().containsKey("mimetype")) { image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(message.getSelectedIndividualHashMap().get("mimetype")))); } else { - fetchFileInformation("/" + message.getSelectedIndividualHashMap().get("path"), message.getActiveUser()); + fetchFileInformation("/" + message.getSelectedIndividualHashMap().get("path"), message.activeUser); } image.setOnClickListener(v -> { String accountString = - message.getActiveUser().getUsername() + "@" + message.getActiveUser().getBaseUrl().replace("https://", "").replace("http://", ""); + message.activeUser.getUsername() + "@" + message.activeUser.getBaseUrl().replace("https://", "").replace("http://", ""); if (AccountUtils.INSTANCE.canWeOpenFilesApp(context, accountString)) { Intent filesAppIntent = new Intent(Intent.ACTION_VIEW, null); @@ -167,10 +167,10 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM @Override public void onSuccess(ReadFilesystemOperation readFilesystemOperation) { DavResponse davResponse = readFilesystemOperation.readRemotePath(); - if (davResponse.getData() != null) { - List browserFileList = (List) davResponse.getData(); + if (davResponse.data != null) { + List browserFileList = (List) davResponse.data; if (!browserFileList.isEmpty()) { - new Handler(context.getMainLooper()).post(() -> image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFileList.get(0).getMimeType())))); + new Handler(context.getMainLooper()).post(() -> image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFileList.get(0).mimeType)))); } } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java index 0340e6fd7..2e688c841 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java @@ -72,9 +72,9 @@ public class MagicSystemMessageViewHolder extends MessageHolders.IncomingTextMes Spannable messageString = new SpannableString(message.getText()); - if (message.getMessageParameters() != null && message.getMessageParameters().size() > 0) { - for (String key : message.getMessageParameters().keySet()) { - Map individualHashMap = message.getMessageParameters().get(key); + if (message.messageParameters != null && message.messageParameters.size() > 0) { + for (String key : message.messageParameters.keySet()) { + Map individualHashMap = message.messageParameters.get(key); if (individualHashMap != null && (individualHashMap.get("type").equals("user") || individualHashMap.get("type").equals("guest") || individualHashMap.get("type").equals("call"))) { messageString = DisplayUtils.searchAndColor(messageString, "@" + individualHashMap.get("name"), mentionColor); } diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/models/DavResponse.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/models/DavResponse.java index 5e3e53ea3..bc2c1ef0e 100644 --- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/models/DavResponse.java +++ b/app/src/main/java/com/nextcloud/talk/components/filebrowser/models/DavResponse.java @@ -25,6 +25,6 @@ import lombok.Data; @Data public class DavResponse { - Response response; - Object data; + public Response response; + public Object data; } diff --git a/app/src/main/java/com/nextcloud/talk/models/SignatureVerification.java b/app/src/main/java/com/nextcloud/talk/models/SignatureVerification.java index 8a979c604..d308f9c34 100644 --- a/app/src/main/java/com/nextcloud/talk/models/SignatureVerification.java +++ b/app/src/main/java/com/nextcloud/talk/models/SignatureVerification.java @@ -28,6 +28,6 @@ import org.parceler.Parcel; @Data @Parcel public class SignatureVerification { - boolean signatureValid; - UserEntity userEntity; + public boolean signatureValid; + public UserEntity userEntity; } diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java index 798974d10..3aa4fc304 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java @@ -52,9 +52,6 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent public Map selectedIndividualHashMap; @JsonIgnore public boolean isLinkPreviewAllowed; - List messageTypesToIgnore = Arrays.asList(MessageType.REGULAR_TEXT_MESSAGE, - MessageType.SYSTEM_MESSAGE, MessageType.SINGLE_LINK_VIDEO_MESSAGE, - MessageType.SINGLE_LINK_AUDIO_MESSAGE, MessageType.SINGLE_LINK_MESSAGE); @JsonField(name = "id") public int jsonMessageId; @JsonField(name = "token") @@ -76,6 +73,15 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent public HashMap> messageParameters; @JsonField(name = "systemMessage", typeConverter = EnumSystemMessageTypeConverter.class) public SystemMessageType systemMessageType; + @JsonField(name = "isReplyable") + public boolean replyable; + @JsonField(name = "parent") + public ChatMessage parentMessage; + + @JsonIgnore + List messageTypesToIgnore = Arrays.asList(MessageType.REGULAR_TEXT_MESSAGE, + MessageType.SYSTEM_MESSAGE, MessageType.SINGLE_LINK_VIDEO_MESSAGE, + MessageType.SINGLE_LINK_AUDIO_MESSAGE, MessageType.SINGLE_LINK_MESSAGE); private boolean hasFileAttachment() { if (messageParameters != null && messageParameters.size() > 0) { diff --git a/app/src/main/res/layout/item_custom_incoming_preview_message.xml b/app/src/main/res/layout/item_custom_incoming_preview_message.xml index 0c1066d68..f39f8796a 100644 --- a/app/src/main/res/layout/item_custom_incoming_preview_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_preview_message.xml @@ -20,72 +20,58 @@ - + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp" + android:orientation="vertical" + android:layout_alignParentStart="true" + app:alignContent="stretch" + app:alignItems="stretch" + app:flexWrap="wrap" + app:justifyContent="flex_end"> - - + android:adjustViewBounds="true" + android:scaleType="fitCenter" + app:layout_flexGrow="1" + app:layout_wrapBefore="true" + app:layout_alignSelf="flex_start" + tools:src="@tools:sample/backgrounds/scenic"/> - + - - - - - - - + + diff --git a/app/src/main/res/layout/item_custom_incoming_text_message.xml b/app/src/main/res/layout/item_custom_incoming_text_message.xml index b4bb55a17..327e37f06 100644 --- a/app/src/main/res/layout/item_custom_incoming_text_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_text_message.xml @@ -47,6 +47,8 @@ app:flexWrap="wrap" app:justifyContent="flex_end"> + + - - + + diff --git a/app/src/main/res/layout/item_custom_outcoming_text_message.xml b/app/src/main/res/layout/item_custom_outcoming_text_message.xml index 0105cc449..f53991c2c 100644 --- a/app/src/main/res/layout/item_custom_outcoming_text_message.xml +++ b/app/src/main/res/layout/item_custom_outcoming_text_message.xml @@ -38,6 +38,8 @@ app:flexWrap="wrap" app:justifyContent="flex_end"> + + + + + + + + + + + + + + + + + + /> + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/rv_item_browser_file.xml b/app/src/main/res/layout/rv_item_browser_file.xml index dc454c227..4b56835d6 100644 --- a/app/src/main/res/layout/rv_item_browser_file.xml +++ b/app/src/main/res/layout/rv_item_browser_file.xml @@ -19,9 +19,9 @@ --> diff --git a/app/src/main/res/values/ints.xml b/app/src/main/res/values/ints.xml new file mode 100644 index 000000000..6c9c7e33b --- /dev/null +++ b/app/src/main/res/values/ints.xml @@ -0,0 +1,24 @@ + + + + + 320 + \ No newline at end of file