group and collapse/expand system messages
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Родитель
e838c5addf
Коммит
e5794eb456
|
@ -0,0 +1,8 @@
|
|||
package com.nextcloud.talk.adapters.messages
|
||||
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
|
||||
interface SystemMessageInterface {
|
||||
fun expandSystemMessage(chatMessage: ChatMessage)
|
||||
fun collapseSystemMessages()
|
||||
}
|
|
@ -1,112 +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.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage;
|
||||
import com.nextcloud.talk.utils.DateUtils;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
||||
import com.stfalcon.chatkit.messages.MessageHolders;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import autodagger.AutoInjector;
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication.class)
|
||||
public class SystemMessageViewHolder extends MessageHolders.IncomingTextMessageViewHolder<ChatMessage> {
|
||||
|
||||
@Inject
|
||||
AppPreferences appPreferences;
|
||||
|
||||
@Inject
|
||||
Context context;
|
||||
|
||||
@Inject
|
||||
DateUtils dateUtils;
|
||||
|
||||
protected ViewGroup background;
|
||||
|
||||
public SystemMessageViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
|
||||
background = itemView.findViewById(R.id.container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(ChatMessage message) {
|
||||
super.onBind(message);
|
||||
|
||||
Resources resources = itemView.getResources();
|
||||
int pressedColor;
|
||||
int mentionColor;
|
||||
|
||||
pressedColor = resources.getColor(R.color.bg_message_list_incoming_bubble);
|
||||
mentionColor = resources.getColor(R.color.textColorMaxContrast);
|
||||
|
||||
Drawable bubbleDrawable = DisplayUtils.getMessageSelector(resources.getColor(R.color.transparent),
|
||||
resources.getColor(R.color.transparent),
|
||||
pressedColor,
|
||||
R.drawable.shape_grouped_incoming_message);
|
||||
ViewCompat.setBackground(background, bubbleDrawable);
|
||||
|
||||
Spannable messageString = new SpannableString(message.getText());
|
||||
|
||||
if (message.getMessageParameters() != null && message.getMessageParameters().size() > 0) {
|
||||
for (String key : message.getMessageParameters().keySet()) {
|
||||
Map<String, String> individualMap = message.getMessageParameters().get(key);
|
||||
|
||||
if (individualMap != null && individualMap.containsKey("name")) {
|
||||
String searchText;
|
||||
if ("user".equals(individualMap.get("type")) ||
|
||||
"guest".equals(individualMap.get("type")) ||
|
||||
"call".equals(individualMap.get("type"))
|
||||
) {
|
||||
searchText = "@" + individualMap.get("name");
|
||||
} else {
|
||||
searchText = individualMap.get("name");
|
||||
}
|
||||
messageString = DisplayUtils.searchAndColor(messageString, searchText, mentionColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text.setText(messageString);
|
||||
|
||||
if (time != null) {
|
||||
time.setText(dateUtils.getLocalTimeStringFromTimestamp(message.getTimestamp()));
|
||||
}
|
||||
|
||||
itemView.setTag(R.string.replyable_message_view_tag, message.getReplyable());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* 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.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.databinding.ItemSystemMessageBinding
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.utils.DateUtils
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
import com.stfalcon.chatkit.messages.MessageHolders
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class SystemMessageViewHolder(itemView: View) : MessageHolders.IncomingTextMessageViewHolder<ChatMessage>(itemView) {
|
||||
|
||||
private val binding: ItemSystemMessageBinding = ItemSystemMessageBinding.bind(itemView)
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
var appPreferences: AppPreferences? = null
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
var context: Context? = null
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
var dateUtils: DateUtils? = null
|
||||
protected var background: ViewGroup
|
||||
|
||||
lateinit var systemMessageInterface: SystemMessageInterface
|
||||
|
||||
init {
|
||||
sharedApplication!!.componentApplication.inject(this)
|
||||
background = itemView.findViewById(R.id.container)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBind(message: ChatMessage) {
|
||||
super.onBind(message)
|
||||
val resources = itemView.resources
|
||||
val pressedColor: Int = resources.getColor(R.color.bg_message_list_incoming_bubble)
|
||||
val mentionColor: Int = resources.getColor(R.color.textColorMaxContrast)
|
||||
val bubbleDrawable = DisplayUtils.getMessageSelector(
|
||||
resources.getColor(R.color.transparent),
|
||||
resources.getColor(R.color.transparent),
|
||||
pressedColor,
|
||||
R.drawable.shape_grouped_incoming_message
|
||||
)
|
||||
ViewCompat.setBackground(background, bubbleDrawable)
|
||||
var messageString: Spannable = SpannableString(message.text)
|
||||
if (message.messageParameters != null && message.messageParameters!!.size > 0) {
|
||||
for (key in message.messageParameters!!.keys) {
|
||||
val individualMap: Map<String?, String?>? = message.messageParameters!![key]
|
||||
if (individualMap != null && individualMap.containsKey("name")) {
|
||||
var searchText: String? = if ("user" == individualMap["type"] ||
|
||||
"guest" == individualMap["type"] ||
|
||||
"call" == individualMap["type"]
|
||||
) {
|
||||
"@" + individualMap["name"]
|
||||
} else {
|
||||
individualMap["name"]
|
||||
}
|
||||
messageString = DisplayUtils.searchAndColor(messageString, searchText, mentionColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.systemMessageLayout.visibility = View.VISIBLE
|
||||
binding.similarMessagesHint.visibility = View.GONE
|
||||
if (message.expandableParent) {
|
||||
binding.expandCollapseIcon.visibility = View.VISIBLE
|
||||
|
||||
if (!message.isExpanded) {
|
||||
val similarMessages = String.format(
|
||||
sharedApplication!!.resources.getString(R.string.see_similar_system_messages),
|
||||
message.expandableChildrenAmount
|
||||
)
|
||||
|
||||
binding.messageText.text = messageString
|
||||
binding.similarMessagesHint.visibility = View.VISIBLE
|
||||
binding.similarMessagesHint.text = similarMessages
|
||||
|
||||
binding.expandCollapseIcon.setImageDrawable(
|
||||
ContextCompat.getDrawable(context!!, R.drawable.baseline_unfold_more_24)
|
||||
)
|
||||
binding.systemMessageLayout.setOnClickListener { systemMessageInterface.expandSystemMessage(message) }
|
||||
binding.messageText.setOnClickListener { systemMessageInterface.expandSystemMessage(message) }
|
||||
} else {
|
||||
binding.messageText.text = messageString
|
||||
binding.similarMessagesHint.visibility = View.GONE
|
||||
binding.similarMessagesHint.text = ""
|
||||
|
||||
binding.expandCollapseIcon.setImageDrawable(
|
||||
ContextCompat.getDrawable(context!!, R.drawable.baseline_unfold_less_24)
|
||||
)
|
||||
binding.systemMessageLayout.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
|
||||
binding.messageText.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
|
||||
}
|
||||
} else if (message.hiddenByCollapse) {
|
||||
binding.systemMessageLayout.visibility = View.GONE
|
||||
} else {
|
||||
binding.expandCollapseIcon.visibility = View.GONE
|
||||
binding.messageText.text = messageString
|
||||
binding.expandCollapseIcon.setImageDrawable(null)
|
||||
binding.systemMessageLayout.setOnClickListener(null)
|
||||
}
|
||||
|
||||
if (!message.expandableParent && message.lastItemOfExpandableGroup != 0) {
|
||||
binding.systemMessageLayout.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
|
||||
binding.messageText.setOnClickListener { systemMessageInterface.collapseSystemMessages() }
|
||||
}
|
||||
|
||||
binding.messageTime.text = dateUtils!!.getLocalTimeStringFromTimestamp(message.timestamp)
|
||||
itemView.setTag(R.string.replyable_message_view_tag, message.replyable)
|
||||
}
|
||||
|
||||
fun assignSystemMessageInterface(systemMessageInterface: SystemMessageInterface) {
|
||||
this.systemMessageInterface = systemMessageInterface
|
||||
}
|
||||
}
|
|
@ -74,6 +74,9 @@ public class TalkMessagesListAdapter<M extends IMessage> extends MessagesListAda
|
|||
} else if (holder instanceof PreviewMessageViewHolder) {
|
||||
((PreviewMessageViewHolder) holder).assignPreviewMessageInterface(chatActivity);
|
||||
((PreviewMessageViewHolder) holder).assignCommonMessageInterface(chatActivity);
|
||||
|
||||
} else if (holder instanceof SystemMessageViewHolder) {
|
||||
((SystemMessageViewHolder) holder).assignSystemMessageInterface(chatActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,6 +137,7 @@ import com.nextcloud.talk.adapters.messages.OutcomingTextMessageViewHolder
|
|||
import com.nextcloud.talk.adapters.messages.OutcomingVoiceMessageViewHolder
|
||||
import com.nextcloud.talk.adapters.messages.PreviewMessageInterface
|
||||
import com.nextcloud.talk.adapters.messages.PreviewMessageViewHolder
|
||||
import com.nextcloud.talk.adapters.messages.SystemMessageInterface
|
||||
import com.nextcloud.talk.adapters.messages.SystemMessageViewHolder
|
||||
import com.nextcloud.talk.adapters.messages.TalkMessagesListAdapter
|
||||
import com.nextcloud.talk.adapters.messages.UnreadNoticeMessageViewHolder
|
||||
|
@ -264,7 +265,8 @@ class ChatActivity :
|
|||
ContentChecker<ChatMessage>,
|
||||
VoiceMessageInterface,
|
||||
CommonMessageInterface,
|
||||
PreviewMessageInterface {
|
||||
PreviewMessageInterface,
|
||||
SystemMessageInterface {
|
||||
|
||||
var active = false
|
||||
|
||||
|
@ -1891,6 +1893,45 @@ class ChatActivity :
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun collapseSystemMessages() {
|
||||
adapter?.items?.forEach {
|
||||
if (it.item is ChatMessage) {
|
||||
val chatMessage = it.item as ChatMessage
|
||||
if (isChildOfExpandableSystemMessage(chatMessage)) {
|
||||
chatMessage.hiddenByCollapse = true
|
||||
}
|
||||
chatMessage.isExpanded = false
|
||||
}
|
||||
}
|
||||
|
||||
adapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun isChildOfExpandableSystemMessage(chatMessage: ChatMessage): Boolean {
|
||||
return isSystemMessage(chatMessage) &&
|
||||
!chatMessage.expandableParent &&
|
||||
chatMessage.lastItemOfExpandableGroup != 0
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun expandSystemMessage(chatMessageToExpand: ChatMessage) {
|
||||
adapter?.items?.forEach {
|
||||
if (it.item is ChatMessage) {
|
||||
val belongsToGroupToExpand =
|
||||
(it.item as ChatMessage).lastItemOfExpandableGroup == chatMessageToExpand.lastItemOfExpandableGroup
|
||||
|
||||
if (belongsToGroupToExpand) {
|
||||
(it.item as ChatMessage).hiddenByCollapse = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chatMessageToExpand.isExpanded = true
|
||||
|
||||
adapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
@SuppressLint("LongLogTag")
|
||||
private fun downloadFileToCache(message: ChatMessage) {
|
||||
message.isDownloadingVoiceMessage = true
|
||||
|
@ -3085,7 +3126,14 @@ class ChatActivity :
|
|||
Log.d(TAG, "pullChatMessages - HTTP_CODE_OK.")
|
||||
|
||||
val chatOverall = response.body() as ChatOverall?
|
||||
val chatMessageList = handleSystemMessages(chatOverall?.ocs!!.data!!)
|
||||
|
||||
var chatMessageList = chatOverall?.ocs!!.data!!
|
||||
|
||||
chatMessageList = handleSystemMessages(chatMessageList)
|
||||
|
||||
determinePreviousMessageIds(chatMessageList)
|
||||
|
||||
handleExpandableSystemMessages(chatMessageList)
|
||||
|
||||
processHeaderChatLastGiven(response, lookIntoFuture)
|
||||
|
||||
|
@ -3100,6 +3148,8 @@ class ChatActivity :
|
|||
processMessagesFromTheFuture(chatMessageList)
|
||||
} else {
|
||||
processMessagesNotFromTheFuture(chatMessageList)
|
||||
|
||||
collapseSystemMessages()
|
||||
}
|
||||
|
||||
val newXChatLastCommonRead = response.headers()["X-Chat-Last-Common-Read"]?.let {
|
||||
|
@ -3123,6 +3173,8 @@ class ChatActivity :
|
|||
isFirstMessagesProcessing = false
|
||||
binding.progressBar.visibility = View.GONE
|
||||
binding.messagesListView.visibility = View.VISIBLE
|
||||
|
||||
collapseSystemMessages()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3188,6 +3240,7 @@ class ChatActivity :
|
|||
}
|
||||
|
||||
private fun processExpiredMessages() {
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun deleteExpiredMessages() {
|
||||
val messagesToDelete: ArrayList<ChatMessage> = ArrayList()
|
||||
val systemTime = System.currentTimeMillis() / ONE_SECOND_IN_MILLIS
|
||||
|
@ -3248,8 +3301,6 @@ class ChatActivity :
|
|||
adapter?.addToStart(unreadChatMessage, false)
|
||||
}
|
||||
|
||||
determinePreviousMessageIds(chatMessageList)
|
||||
|
||||
addMessagesToAdapter(shouldAddNewMessagesNotice, chatMessageList)
|
||||
|
||||
if (shouldAddNewMessagesNotice && adapter != null) {
|
||||
|
@ -3257,6 +3308,36 @@ class ChatActivity :
|
|||
}
|
||||
}
|
||||
|
||||
private fun processMessagesNotFromTheFuture(chatMessageList: List<ChatMessage>) {
|
||||
var countGroupedMessages = 0
|
||||
|
||||
for (i in chatMessageList.indices) {
|
||||
if (chatMessageList.size > i + 1) {
|
||||
if (isSameDayNonSystemMessages(chatMessageList[i], chatMessageList[i + 1]) &&
|
||||
chatMessageList[i + 1].actorId == chatMessageList[i].actorId &&
|
||||
countGroupedMessages < GROUPED_MESSAGES_THRESHOLD
|
||||
) {
|
||||
chatMessageList[i].isGrouped = true
|
||||
countGroupedMessages++
|
||||
} else {
|
||||
countGroupedMessages = 0
|
||||
}
|
||||
}
|
||||
|
||||
val chatMessage = chatMessageList[i]
|
||||
chatMessage.isOneToOneConversation =
|
||||
currentConversation?.type == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
|
||||
chatMessage.isFormerOneToOneConversation =
|
||||
(currentConversation?.type == ConversationType.FORMER_ONE_TO_ONE)
|
||||
chatMessage.activeUser = conversationUser
|
||||
}
|
||||
|
||||
if (adapter != null) {
|
||||
adapter?.addToEnd(chatMessageList, false)
|
||||
}
|
||||
scrollToRequestedMessageIfNeeded()
|
||||
}
|
||||
|
||||
private fun scrollToFirstUnreadMessage() {
|
||||
adapter?.let {
|
||||
layoutManager?.scrollToPositionWithOffset(
|
||||
|
@ -3286,10 +3367,8 @@ class ChatActivity :
|
|||
|
||||
adapter?.let {
|
||||
chatMessage.isGrouped = (
|
||||
it.isPreviousSameAuthor(
|
||||
chatMessage.actorId,
|
||||
-1
|
||||
) && it.getSameAuthorLastMessagesCount(chatMessage.actorId) %
|
||||
it.isPreviousSameAuthor(chatMessage.actorId, -1) &&
|
||||
it.getSameAuthorLastMessagesCount(chatMessage.actorId) %
|
||||
GROUPED_MESSAGES_SAME_AUTHOR_THRESHOLD > 0
|
||||
)
|
||||
chatMessage.isOneToOneConversation =
|
||||
|
@ -3318,37 +3397,6 @@ class ChatActivity :
|
|||
}
|
||||
}
|
||||
|
||||
private fun processMessagesNotFromTheFuture(chatMessageList: List<ChatMessage>) {
|
||||
var countGroupedMessages = 0
|
||||
determinePreviousMessageIds(chatMessageList)
|
||||
|
||||
for (i in chatMessageList.indices) {
|
||||
if (chatMessageList.size > i + 1) {
|
||||
if (isSameDayNonSystemMessages(chatMessageList[i], chatMessageList[i + 1]) &&
|
||||
chatMessageList[i + 1].actorId == chatMessageList[i].actorId &&
|
||||
countGroupedMessages < GROUPED_MESSAGES_THRESHOLD
|
||||
) {
|
||||
chatMessageList[i].isGrouped = true
|
||||
countGroupedMessages++
|
||||
} else {
|
||||
countGroupedMessages = 0
|
||||
}
|
||||
}
|
||||
|
||||
val chatMessage = chatMessageList[i]
|
||||
chatMessage.isOneToOneConversation =
|
||||
currentConversation?.type == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
|
||||
chatMessage.isFormerOneToOneConversation =
|
||||
(currentConversation?.type == ConversationType.FORMER_ONE_TO_ONE)
|
||||
chatMessage.activeUser = conversationUser
|
||||
}
|
||||
|
||||
if (adapter != null) {
|
||||
adapter?.addToEnd(chatMessageList, false)
|
||||
}
|
||||
scrollToRequestedMessageIfNeeded()
|
||||
}
|
||||
|
||||
private fun determinePreviousMessageIds(chatMessageList: List<ChatMessage>) {
|
||||
var previousMessageId = NO_PREVIOUS_MESSAGE_ID
|
||||
for (i in chatMessageList.indices.reversed()) {
|
||||
|
@ -3574,6 +3622,30 @@ class ChatActivity :
|
|||
return chatMessageMap.values.toList()
|
||||
}
|
||||
|
||||
private fun handleExpandableSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
||||
val chatMessageMap = chatMessageList.map { it.id to it }.toMap().toMutableMap()
|
||||
val chatMessageIterator = chatMessageMap.iterator()
|
||||
while (chatMessageIterator.hasNext()) {
|
||||
val currentMessage = chatMessageIterator.next()
|
||||
|
||||
val previousMessage = chatMessageMap[currentMessage.value.previousMessageId.toString()]
|
||||
if (isSystemMessage(currentMessage.value) &&
|
||||
previousMessage?.systemMessageType == currentMessage.value.systemMessageType
|
||||
) {
|
||||
previousMessage?.expandableParent = true
|
||||
currentMessage.value.expandableParent = false
|
||||
|
||||
if (currentMessage.value.lastItemOfExpandableGroup == 0) {
|
||||
currentMessage.value.lastItemOfExpandableGroup = currentMessage.value.jsonMessageId
|
||||
}
|
||||
|
||||
previousMessage?.lastItemOfExpandableGroup = currentMessage.value.lastItemOfExpandableGroup
|
||||
previousMessage?.expandableChildrenAmount = currentMessage.value.expandableChildrenAmount + 1
|
||||
}
|
||||
}
|
||||
return chatMessageMap.values.toList()
|
||||
}
|
||||
|
||||
private fun isInfoMessageAboutDeletion(currentMessage: MutableMap.MutableEntry<String, ChatMessage>): Boolean {
|
||||
return currentMessage.value.parentMessage != null && currentMessage.value.systemMessageType == ChatMessage
|
||||
.SystemMessageType.MESSAGE_DELETED
|
||||
|
|
|
@ -135,7 +135,17 @@ data class ChatMessage(
|
|||
|
||||
var voiceMessageSeekbarProgress: Int = 0,
|
||||
|
||||
var voiceMessageFloatArray: FloatArray? = null
|
||||
var voiceMessageFloatArray: FloatArray? = null,
|
||||
|
||||
var expandableParent: Boolean = false,
|
||||
|
||||
var isExpanded: Boolean = false,
|
||||
|
||||
var lastItemOfExpandableGroup: Int = 0,
|
||||
|
||||
var expandableChildrenAmount: Int = 0,
|
||||
|
||||
var hiddenByCollapse: Boolean = false
|
||||
|
||||
) : Parcelable, MessageContentType, MessageContentType.Image {
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<vector
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M7.41,18.59L8.83,20 12,16.83 15.17,20l1.41,-1.41L12,14l-4.59,4.59zM16.59,5.41L15.17,4 12,7.17 8.83,4 7.41,5.41 12,10l4.59,-4.59z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,5.83L15.17,9l1.41,-1.41L12,3 7.41,7.59 8.83,9 12,5.83zM12,18.17L8.83,15l-1.41,1.41L12,21l4.59,-4.59L15.17,15 12,18.17z"/>
|
||||
</vector>
|
|
@ -24,52 +24,88 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_marginTop="@dimen/standard_eighth_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:layout_marginBottom="@dimen/standard_eighth_margin">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:id="@id/container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/standard_half_padding"
|
||||
app:alignContent="stretch"
|
||||
app:alignItems="stretch"
|
||||
app:flexWrap="wrap"
|
||||
app:justifyContent="flex_end">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/systemMessageLayout"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_marginTop="@dimen/standard_eighth_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:layout_marginBottom="@dimen/standard_eighth_margin">
|
||||
|
||||
<androidx.emoji2.widget.EmojiTextView
|
||||
android:id="@+id/messageText"
|
||||
<ImageView
|
||||
android:id="@+id/expandCollapseIcon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="10dp"
|
||||
android:contentDescription="@null"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:id="@id/container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/textColorMaxContrast"
|
||||
android:textSize="14sp"
|
||||
app:layout_alignSelf="flex_start"
|
||||
app:layout_flexGrow="1"
|
||||
app:layout_wrapBefore="true"
|
||||
tools:text="System message" />
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/standard_half_padding"
|
||||
app:alignContent="stretch"
|
||||
app:alignItems="stretch"
|
||||
app:flexWrap="wrap"
|
||||
app:justifyContent="flex_end">
|
||||
|
||||
<androidx.emoji2.widget.EmojiTextView
|
||||
android:id="@+id/messageText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/textColorMaxContrast"
|
||||
android:textSize="14sp"
|
||||
app:layout_alignSelf="flex_start"
|
||||
app:layout_flexGrow="1"
|
||||
app:layout_wrapBefore="true"
|
||||
tools:text="System message" />
|
||||
|
||||
<TextView
|
||||
android:id="@id/messageTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/standard_half_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:gravity="end"
|
||||
android:textColor="@color/warm_grey_four"
|
||||
android:textSize="12sp"
|
||||
app:layout_alignSelf="center"
|
||||
app:layout_flexGrow="1"
|
||||
app:layout_wrapBefore="false"
|
||||
tools:text="17:30" />
|
||||
|
||||
<androidx.emoji2.widget.EmojiTextView
|
||||
android:id="@+id/similarMessagesHint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/grey_600"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp"
|
||||
app:layout_alignSelf="center"
|
||||
app:layout_flexGrow="1"
|
||||
app:layout_wrapBefore="true"
|
||||
tools:text="See 5 similar messages" />
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@id/messageTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/standard_half_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:gravity="end"
|
||||
android:textColor="@color/warm_grey_four"
|
||||
android:textSize="12sp"
|
||||
app:layout_alignSelf="center"
|
||||
app:layout_flexGrow="1"
|
||||
app:layout_wrapBefore="false"
|
||||
tools:text="17:30" />
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -376,6 +376,7 @@ How to translate with transifex:
|
|||
<string name="nc_add_attachment">Add attachment</string>
|
||||
<string name="emoji_category_recent">Recent</string>
|
||||
<string name="emoji_backspace">Backspace</string>
|
||||
<string name="see_similar_system_messages">See %1$s similar messages</string>
|
||||
|
||||
<!-- Conversation info guest access -->
|
||||
<string name="nc_guest_access">Guest access</string>
|
||||
|
|
Загрузка…
Ссылка в новой задаче