Some progress on replies

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2020-01-13 11:15:20 +01:00
parent 0613254e08
commit 2613c1f074
No known key found for this signature in database
GPG Key ID: CDE0BBD2738C4CC0
17 changed files with 633 additions and 431 deletions

View File

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

View File

@ -1,206 +0,0 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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<ChatMessage> {
@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<String, HashMap<String, String>> 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<String, String> 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);
}
}

View File

@ -0,0 +1,252 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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<ChatMessage>(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<Drawable>(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
}
}
}

View File

@ -1,140 +0,0 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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<ChatMessage> {
@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<String, HashMap<String, String>> 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<String, String> 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);
}
}

View File

@ -0,0 +1,182 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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<ChatMessage>(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<String, HashMap<String, String>>? = 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<String, String>? = 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
}
}

View File

@ -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<BrowserFile> browserFileList = (List<BrowserFile>) davResponse.getData();
if (davResponse.data != null) {
List<BrowserFile> browserFileList = (List<BrowserFile>) 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))));
}
}
}

View File

@ -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<String, String> individualHashMap = message.getMessageParameters().get(key);
if (message.messageParameters != null && message.messageParameters.size() > 0) {
for (String key : message.messageParameters.keySet()) {
Map<String, String> 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);
}

View File

@ -25,6 +25,6 @@ import lombok.Data;
@Data
public class DavResponse {
Response response;
Object data;
public Response response;
public Object data;
}

View File

@ -28,6 +28,6 @@ import org.parceler.Parcel;
@Data
@Parcel
public class SignatureVerification {
boolean signatureValid;
UserEntity userEntity;
public boolean signatureValid;
public UserEntity userEntity;
}

View File

@ -52,9 +52,6 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
public Map<String, String> selectedIndividualHashMap;
@JsonIgnore
public boolean isLinkPreviewAllowed;
List<MessageType> 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<String, HashMap<String, String>> messageParameters;
@JsonField(name = "systemMessage", typeConverter = EnumSystemMessageTypeConverter.class)
public SystemMessageType systemMessageType;
@JsonField(name = "isReplyable")
public boolean replyable;
@JsonField(name = "parent")
public ChatMessage parentMessage;
@JsonIgnore
List<MessageType> 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) {

View File

@ -20,72 +20,58 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:layout_marginStart="16dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="2dp">
<RelativeLayout
<com.google.android.flexbox.FlexboxLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/messageUserAvatar">
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">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@id/image"
android:layout_width="@dimen/minimum_file_preview_size"
android:layout_height="@dimen/minimum_file_preview_size"
android:adjustViewBounds="true"
app:actualImageScaleType="fitCenter" />
<com.google.android.flexbox.FlexboxLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/image"
android:layout_alignStart="@+id/image"
android:layout_alignEnd="@id/image"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
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"/>
<androidx.emoji.widget.EmojiTextView
android:id="@id/messageText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="none"
android:textColor="@color/warm_grey_four"
android:textColorLink="@color/warm_grey_four"
android:textIsSelectable="true"
android:textSize="12sp"
app:layout_alignSelf="flex_start"
app:layout_flexGrow="1"
app:layout_wrapBefore="true" />
<androidx.emoji.widget.EmojiTextView
android:id="@id/messageText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="none"
android:textColor="@color/warm_grey_four"
android:textColorLink="@color/warm_grey_four"
android:textIsSelectable="true"
android:textSize="12sp"
app:layout_alignSelf="flex_start"
app:layout_flexGrow="1"
app:layout_wrapBefore="true" />
<TextView
android:id="@id/messageTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginStart="8dp"
android:textColor="@color/warm_grey_four"
app:layout_alignSelf="center" />
</com.google.android.flexbox.FlexboxLayout>
</RelativeLayout>
<com.facebook.drawee.view.SimpleDraweeView
android:id="@id/messageUserAvatar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="8dp"
app:roundAsCircle="true" />
<TextView
android:id="@id/messageTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginStart="8dp"
android:textColor="@color/warm_grey_four"
app:layout_alignSelf="center" />
</com.google.android.flexbox.FlexboxLayout>
</RelativeLayout>

View File

@ -47,6 +47,8 @@
app:flexWrap="wrap"
app:justifyContent="flex_end">
<include layout="@layout/item_message_quote" android:visibility="gone"/>
<androidx.emoji.widget.EmojiTextView
android:id="@+id/messageAuthor"
android:layout_width="match_parent"

View File

@ -20,35 +20,38 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:layout_marginStart="16dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="2dp">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@id/image"
android:layout_width="@dimen/minimum_file_preview_size"
android:layout_height="@dimen/minimum_file_preview_size"
android:layout_alignParentEnd="true"
android:adjustViewBounds="true"
app:actualImageScaleType="fitCenter" />
<com.google.android.flexbox.FlexboxLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/image"
android:layout_alignStart="@+id/image"
android:layout_alignEnd="@id/image"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
android:layout_alignParentEnd="true"
app:alignContent="stretch"
app:alignItems="stretch"
app:flexWrap="wrap"
app:justifyContent="flex_end">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:layout_flexGrow="1"
app:layout_wrapBefore="true"
app:layout_alignSelf="flex_start"
app:actualImageScaleType="fitCenter"
tools:src="@tools:sample/backgrounds/scenic"/>
<androidx.emoji.widget.EmojiTextView
android:id="@id/messageText"
android:layout_width="wrap_content"
@ -67,6 +70,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginStart="8dp"
android:textColor="@color/warm_grey_four"
app:layout_alignSelf="center" />
</com.google.android.flexbox.FlexboxLayout>

View File

@ -38,6 +38,8 @@
app:flexWrap="wrap"
app:justifyContent="flex_end">
<include layout="@layout/item_message_quote" android:visibility="gone"/>
<androidx.emoji.widget.EmojiTextView
android:id="@id/messageText"
android:layout_width="wrap_content"

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/quotedChatMessageView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/quoteColoredView"
android:layout_width="2dp"
android:layout_height="match_parent"
android:layout_alignBottom="@id/flexboxQuoted"
android:layout_alignParentStart="true"
android:layout_marginEnd="4dp"
android:background="@color/colorPrimary"></View>
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/quotedUserAvatar"
android:layout_width="8dp"
android:layout_height="8dp"
android:scaleType="centerInside"
android:adjustViewBounds="true"
app:roundAsCircle="true"
android:layout_alignParentTop="true"
android:layout_toEndOf="@id/quoteColoredView"
android:layout_marginEnd="4dp"
tools:src="@tools:sample/avatars[0]" />
<androidx.emoji.widget.EmojiTextView
android:id="@+id/quotedMessageAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/quotedUserAvatar"
android:layout_toEndOf="@id/quotedUserAvatar"
android:ellipsize="end"
android:layout_marginEnd="8dp"
android:textSize="12sp"
tools:text="Mario" />
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/flexboxQuoted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/quotedUserAvatar"
android:layout_alignStart="@id/quotedUserAvatar"
android:layout_marginTop="4dp"
android:orientation="vertical"
app:alignContent="stretch"
app:alignItems="stretch"
app:flexWrap="wrap"
app:justifyContent="flex_end">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/quotedMessageImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerInside"
app:layout_alignSelf="flex_start"
app:layout_flexGrow="1"
app:layout_wrapBefore="true"
tools:src="@tools:sample/backgrounds/scenic" />
<androidx.emoji.widget.EmojiTextView
android:id="@+id/quotedMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_below="@id/quotedMessageImage"
android:layout_alignStart="@id/quotedUserAvatar"
android:lineSpacingMultiplier="1.2"
app:layout_alignSelf="flex_start"
app:layout_flexGrow="1"
app:layout_wrapBefore="true"
tools:text="Hello, this is me!" />
<TextView
android:id="@+id/quotedMessageTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textSize="12sp"
app:layout_alignSelf="center"
tools:text="16:08" />
/>
</com.google.android.flexbox.FlexboxLayout>
</RelativeLayout>

View File

@ -19,9 +19,9 @@
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/rv_item_view_height"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="@dimen/double_margin_between_elements"
android:background="@color/bg_default">

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Nextcloud Talk application
~
~ @author Mario Danic
~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
~
~ 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 <http://www.gnu.org/licenses/>.
-->
<resources>
<integer name="password_strike">320</integer>
</resources>