mirror of
https://github.com/nextcloud/talk-android
synced 2025-08-05 11:05:10 +01:00
Merge pull request #5187 from nextcloud/feature/3074/messageThreads2
hide thread messages in normal chat / include threadId in fieldMap ...
This commit is contained in:
commit
30de714eb7
@ -25,6 +25,7 @@ import org.junit.Assert.assertEquals
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import java.lang.Boolean
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class ChatBlocksDaoTest {
|
class ChatBlocksDaoTest {
|
||||||
@ -49,6 +50,73 @@ class ChatBlocksDaoTest {
|
|||||||
@After
|
@After
|
||||||
fun closeDb() = db.close()
|
fun closeDb() = db.close()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetChatBlocksContainingMessageId() =
|
||||||
|
runTest {
|
||||||
|
val user = createUserEntity("account1", "Account 1")
|
||||||
|
usersDao.saveUser(user)
|
||||||
|
val account1 = usersDao.getUserWithUserId("account1").blockingGet()
|
||||||
|
|
||||||
|
conversationsDao.upsertConversations(
|
||||||
|
listOf(
|
||||||
|
createConversationEntity(
|
||||||
|
accountId = account1.id,
|
||||||
|
"abc",
|
||||||
|
roomName = "Conversation One"
|
||||||
|
),
|
||||||
|
createConversationEntity(
|
||||||
|
accountId = account1.id,
|
||||||
|
"def",
|
||||||
|
roomName = "Conversation Two"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val conversation1 = conversationsDao.getConversationsForUser(account1.id).first()[0]
|
||||||
|
|
||||||
|
val chatBlock1 = ChatBlockEntity(
|
||||||
|
internalConversationId = conversation1.internalId,
|
||||||
|
accountId = conversation1.accountId,
|
||||||
|
token = conversation1.token,
|
||||||
|
threadId = 123,
|
||||||
|
oldestMessageId = 50,
|
||||||
|
newestMessageId = 60,
|
||||||
|
hasHistory = true
|
||||||
|
)
|
||||||
|
|
||||||
|
val chatBlock2 = ChatBlockEntity(
|
||||||
|
internalConversationId = conversation1.internalId,
|
||||||
|
accountId = conversation1.accountId,
|
||||||
|
token = conversation1.token,
|
||||||
|
threadId = 123,
|
||||||
|
oldestMessageId = 10,
|
||||||
|
newestMessageId = 20,
|
||||||
|
hasHistory = true
|
||||||
|
)
|
||||||
|
|
||||||
|
val chatBlock3 = ChatBlockEntity(
|
||||||
|
internalConversationId = conversation1.internalId,
|
||||||
|
accountId = conversation1.accountId,
|
||||||
|
token = conversation1.token,
|
||||||
|
threadId = null,
|
||||||
|
oldestMessageId = 50,
|
||||||
|
newestMessageId = 60,
|
||||||
|
hasHistory = true
|
||||||
|
)
|
||||||
|
|
||||||
|
chatBlocksDao.upsertChatBlock(chatBlock1)
|
||||||
|
chatBlocksDao.upsertChatBlock(chatBlock2)
|
||||||
|
chatBlocksDao.upsertChatBlock(chatBlock3)
|
||||||
|
|
||||||
|
val chatBlocksOfThread = chatBlocksDao.getChatBlocksContainingMessageId(
|
||||||
|
internalConversationId = conversation1.internalId,
|
||||||
|
threadId = 123,
|
||||||
|
messageId = 55
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(1, chatBlocksOfThread.first().size)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetConnectedChatBlocks() =
|
fun testGetConnectedChatBlocks() =
|
||||||
runTest {
|
runTest {
|
||||||
@ -266,8 +334,8 @@ class ChatBlocksDaoTest {
|
|||||||
serverVersion = null,
|
serverVersion = null,
|
||||||
clientCertificate = null,
|
clientCertificate = null,
|
||||||
externalSignalingServer = null,
|
externalSignalingServer = null,
|
||||||
current = java.lang.Boolean.FALSE,
|
current = Boolean.FALSE,
|
||||||
scheduledForDeletion = java.lang.Boolean.FALSE
|
scheduledForDeletion = Boolean.FALSE
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun createConversationEntity(accountId: Long, token: String, roomName: String) =
|
private fun createConversationEntity(accountId: Long, token: String, roomName: String) =
|
||||||
|
@ -168,7 +168,7 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
|
|||||||
binding.messageQuote.quotedChatMessageView.visibility =
|
binding.messageQuote.quotedChatMessageView.visibility =
|
||||||
if (!message.isDeleted &&
|
if (!message.isDeleted &&
|
||||||
message.parentMessageId != null &&
|
message.parentMessageId != null &&
|
||||||
message.parentMessageId != chatActivity.threadId
|
message.parentMessageId != chatActivity.conversationThreadId
|
||||||
) {
|
) {
|
||||||
processParentMessage(message)
|
processParentMessage(message)
|
||||||
View.VISIBLE
|
View.VISIBLE
|
||||||
|
@ -183,7 +183,7 @@ class OutcomingTextMessageViewHolder(itemView: View) :
|
|||||||
binding.messageQuote.quotedChatMessageView.visibility =
|
binding.messageQuote.quotedChatMessageView.visibility =
|
||||||
if (!message.isDeleted &&
|
if (!message.isDeleted &&
|
||||||
message.parentMessageId != null &&
|
message.parentMessageId != null &&
|
||||||
message.parentMessageId != chatActivity.threadId
|
message.parentMessageId != chatActivity.conversationThreadId
|
||||||
) {
|
) {
|
||||||
processParentMessage(message)
|
processParentMessage(message)
|
||||||
View.VISIBLE
|
View.VISIBLE
|
||||||
|
@ -353,8 +353,8 @@ class ChatActivity :
|
|||||||
|
|
||||||
var sessionIdAfterRoomJoined: String? = null
|
var sessionIdAfterRoomJoined: String? = null
|
||||||
lateinit var roomToken: String
|
lateinit var roomToken: String
|
||||||
var threadId: Long? = null
|
var conversationThreadId: Long? = null
|
||||||
var threadInfo: ThreadInfo? = null
|
var conversationThreadInfo: ThreadInfo? = null
|
||||||
var conversationUser: User? = null
|
var conversationUser: User? = null
|
||||||
lateinit var spreedCapabilities: SpreedCapability
|
lateinit var spreedCapabilities: SpreedCapability
|
||||||
var chatApiVersion: Int = 1
|
var chatApiVersion: Int = 1
|
||||||
@ -506,10 +506,10 @@ class ChatActivity :
|
|||||||
credentials!!,
|
credentials!!,
|
||||||
urlForChatting,
|
urlForChatting,
|
||||||
roomToken,
|
roomToken,
|
||||||
threadId
|
conversationThreadId
|
||||||
)
|
)
|
||||||
|
|
||||||
threadId?.let {
|
conversationThreadId?.let {
|
||||||
val threadUrl = ApiUtils.getUrlForThread(
|
val threadUrl = ApiUtils.getUrlForThread(
|
||||||
version = 1,
|
version = 1,
|
||||||
baseUrl = conversationUser!!.baseUrl,
|
baseUrl = conversationUser!!.baseUrl,
|
||||||
@ -571,7 +571,7 @@ class ChatActivity :
|
|||||||
|
|
||||||
roomToken = extras?.getString(KEY_ROOM_TOKEN).orEmpty()
|
roomToken = extras?.getString(KEY_ROOM_TOKEN).orEmpty()
|
||||||
|
|
||||||
threadId = if (extras?.containsKey(KEY_THREAD_ID) == true) {
|
conversationThreadId = if (extras?.containsKey(KEY_THREAD_ID) == true) {
|
||||||
extras.getLong(KEY_THREAD_ID)
|
extras.getLong(KEY_THREAD_ID)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@ -966,6 +966,7 @@ class ChatActivity :
|
|||||||
var chatMessageList = triple.third
|
var chatMessageList = triple.third
|
||||||
|
|
||||||
chatMessageList = handleSystemMessages(chatMessageList)
|
chatMessageList = handleSystemMessages(chatMessageList)
|
||||||
|
chatMessageList = handleThreadMessages(chatMessageList)
|
||||||
if (chatMessageList.isEmpty()) {
|
if (chatMessageList.isEmpty()) {
|
||||||
return@onEach
|
return@onEach
|
||||||
}
|
}
|
||||||
@ -1296,7 +1297,7 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
is ChatViewModel.ThreadRetrieveUiState.Success -> {
|
is ChatViewModel.ThreadRetrieveUiState.Success -> {
|
||||||
threadInfo = uiState.thread
|
conversationThreadInfo = uiState.thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2668,7 +2669,7 @@ class ChatActivity :
|
|||||||
|
|
||||||
title.text =
|
title.text =
|
||||||
if (isChatThread()) {
|
if (isChatThread()) {
|
||||||
threadInfo?.first?.message
|
conversationThreadInfo?.first?.message
|
||||||
} else if (currentConversation?.displayName != null) {
|
} else if (currentConversation?.displayName != null) {
|
||||||
try {
|
try {
|
||||||
EmojiCompat.get().process(currentConversation?.displayName as CharSequence).toString()
|
EmojiCompat.get().process(currentConversation?.displayName as CharSequence).toString()
|
||||||
@ -2683,7 +2684,7 @@ class ChatActivity :
|
|||||||
if (isChatThread()) {
|
if (isChatThread()) {
|
||||||
val repliesAmountTitle = String.format(
|
val repliesAmountTitle = String.format(
|
||||||
resources.getString(R.string.thread_replies_amount),
|
resources.getString(R.string.thread_replies_amount),
|
||||||
threadInfo?.thread?.numReplies
|
conversationThreadInfo?.thread?.numReplies
|
||||||
)
|
)
|
||||||
statusMessageViewContents(repliesAmountTitle)
|
statusMessageViewContents(repliesAmountTitle)
|
||||||
} else if (currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
} else if (currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||||
@ -3455,7 +3456,7 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
private fun handleSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
||||||
val chatMessageMap = chatMessageList.map { it.id to it }.toMap().toMutableMap()
|
val chatMessageMap = chatMessageList.associateBy { it.id }.toMutableMap()
|
||||||
|
|
||||||
val chatMessageIterator = chatMessageMap.iterator()
|
val chatMessageIterator = chatMessageMap.iterator()
|
||||||
while (chatMessageIterator.hasNext()) {
|
while (chatMessageIterator.hasNext()) {
|
||||||
@ -3464,7 +3465,8 @@ class ChatActivity :
|
|||||||
if (isInfoMessageAboutDeletion(currentMessage) ||
|
if (isInfoMessageAboutDeletion(currentMessage) ||
|
||||||
isReactionsMessage(currentMessage) ||
|
isReactionsMessage(currentMessage) ||
|
||||||
isPollVotedMessage(currentMessage) ||
|
isPollVotedMessage(currentMessage) ||
|
||||||
isEditMessage(currentMessage)
|
isEditMessage(currentMessage) ||
|
||||||
|
isThreadCreatedMessage(currentMessage)
|
||||||
) {
|
) {
|
||||||
chatMessageIterator.remove()
|
chatMessageIterator.remove()
|
||||||
}
|
}
|
||||||
@ -3473,7 +3475,7 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleExpandableSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
private fun handleExpandableSystemMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
||||||
val chatMessageMap = chatMessageList.map { it.id to it }.toMap().toMutableMap()
|
val chatMessageMap = chatMessageList.associateBy { it.id }.toMutableMap()
|
||||||
val chatMessageIterator = chatMessageMap.iterator()
|
val chatMessageIterator = chatMessageMap.iterator()
|
||||||
while (chatMessageIterator.hasNext()) {
|
while (chatMessageIterator.hasNext()) {
|
||||||
val currentMessage = chatMessageIterator.next()
|
val currentMessage = chatMessageIterator.next()
|
||||||
@ -3496,6 +3498,23 @@ class ChatActivity :
|
|||||||
return chatMessageMap.values.toList()
|
return chatMessageMap.values.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleThreadMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
|
||||||
|
val chatMessageMap = chatMessageList.associateBy { it.id }.toMutableMap()
|
||||||
|
|
||||||
|
if (conversationThreadId == null) {
|
||||||
|
val chatMessageIterator = chatMessageMap.iterator()
|
||||||
|
while (chatMessageIterator.hasNext()) {
|
||||||
|
val currentMessage = chatMessageIterator.next()
|
||||||
|
|
||||||
|
if (currentMessage.value.isThread) {
|
||||||
|
chatMessageIterator.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chatMessageMap.values.toList()
|
||||||
|
}
|
||||||
|
|
||||||
private fun isInfoMessageAboutDeletion(currentMessage: MutableMap.MutableEntry<String, ChatMessage>): Boolean =
|
private fun isInfoMessageAboutDeletion(currentMessage: MutableMap.MutableEntry<String, ChatMessage>): Boolean =
|
||||||
currentMessage.value.parentMessageId != null &&
|
currentMessage.value.parentMessageId != null &&
|
||||||
currentMessage.value.systemMessageType == ChatMessage
|
currentMessage.value.systemMessageType == ChatMessage
|
||||||
@ -3506,6 +3525,9 @@ class ChatActivity :
|
|||||||
currentMessage.value.systemMessageType == ChatMessage.SystemMessageType.REACTION_DELETED ||
|
currentMessage.value.systemMessageType == ChatMessage.SystemMessageType.REACTION_DELETED ||
|
||||||
currentMessage.value.systemMessageType == ChatMessage.SystemMessageType.REACTION_REVOKED
|
currentMessage.value.systemMessageType == ChatMessage.SystemMessageType.REACTION_REVOKED
|
||||||
|
|
||||||
|
private fun isThreadCreatedMessage(currentMessage: MutableMap.MutableEntry<String, ChatMessage>): Boolean =
|
||||||
|
currentMessage.value.systemMessageType == ChatMessage.SystemMessageType.THREAD_CREATED
|
||||||
|
|
||||||
private fun isEditMessage(currentMessage: MutableMap.MutableEntry<String, ChatMessage>): Boolean =
|
private fun isEditMessage(currentMessage: MutableMap.MutableEntry<String, ChatMessage>): Boolean =
|
||||||
currentMessage.value.parentMessageId != null &&
|
currentMessage.value.parentMessageId != null &&
|
||||||
currentMessage.value.systemMessageType == ChatMessage
|
currentMessage.value.systemMessageType == ChatMessage
|
||||||
@ -4202,7 +4224,7 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isChatThread(): Boolean = threadId != null && threadId!! > 0
|
private fun isChatThread(): Boolean = conversationThreadId != null && conversationThreadId!! > 0
|
||||||
|
|
||||||
fun openThread(messageId: Long) {
|
fun openThread(messageId: Long) {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
|
@ -860,7 +860,7 @@ class MessageInputFragment : Fragment() {
|
|||||||
.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.tag as Int? ?: 0
|
.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.tag as Int? ?: 0
|
||||||
|
|
||||||
if (replyMessageId == 0) {
|
if (replyMessageId == 0) {
|
||||||
replyMessageId = chatActivity.threadInfo?.thread?.id ?: 0
|
replyMessageId = chatActivity.conversationThreadInfo?.thread?.id ?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(
|
sendMessage(
|
||||||
|
@ -465,8 +465,11 @@ class OfflineFirstChatRepository @Inject constructor(
|
|||||||
fieldMap["lastCommonReadId"] = it
|
fieldMap["lastCommonReadId"] = it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
threadId?.let { fieldMap["threadId"] = it.toInt() }
|
||||||
|
|
||||||
fieldMap["timeout"] = timeout
|
fieldMap["timeout"] = timeout
|
||||||
fieldMap["limit"] = limit
|
fieldMap["limit"] = limit
|
||||||
|
|
||||||
fieldMap["lookIntoFuture"] = if (lookIntoFuture) 1 else 0
|
fieldMap["lookIntoFuture"] = if (lookIntoFuture) 1 else 0
|
||||||
fieldMap["setReadMarker"] = if (setReadMarker) 1 else 0
|
fieldMap["setReadMarker"] = if (setReadMarker) 1 else 0
|
||||||
|
|
||||||
|
@ -69,6 +69,8 @@ class ThreadsOverviewActivity : BaseActivity() {
|
|||||||
|
|
||||||
lateinit var threadsOverviewViewModel: ThreadsOverviewViewModel
|
lateinit var threadsOverviewViewModel: ThreadsOverviewViewModel
|
||||||
|
|
||||||
|
var roomToken: String = ""
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
@ -80,9 +82,7 @@ class ThreadsOverviewActivity : BaseActivity() {
|
|||||||
val colorScheme = viewThemeUtils.getColorScheme(this)
|
val colorScheme = viewThemeUtils.getColorScheme(this)
|
||||||
|
|
||||||
val extras: Bundle? = intent.extras
|
val extras: Bundle? = intent.extras
|
||||||
val roomToken = extras?.getString(KEY_ROOM_TOKEN).orEmpty()
|
roomToken = extras?.getString(KEY_ROOM_TOKEN).orEmpty()
|
||||||
|
|
||||||
threadsOverviewViewModel.init(roomToken)
|
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
val backgroundColor = colorResource(id = R.color.bg_default)
|
val backgroundColor = colorResource(id = R.color.bg_default)
|
||||||
@ -136,6 +136,7 @@ class ThreadsOverviewActivity : BaseActivity() {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
supportActionBar?.show()
|
supportActionBar?.show()
|
||||||
|
threadsOverviewViewModel.init(roomToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -152,7 +152,7 @@ class MessageActionsDialog(
|
|||||||
isOnline
|
isOnline
|
||||||
)
|
)
|
||||||
initMenuStartThread(!message.isThread)
|
initMenuStartThread(!message.isThread)
|
||||||
initMenuOpenThread(message.isThread && chatActivity.threadId == null)
|
initMenuOpenThread(message.isThread && chatActivity.conversationThreadId == null)
|
||||||
initMenuEditMessage(isMessageEditable)
|
initMenuEditMessage(isMessageEditable)
|
||||||
initMenuDeleteMessage(showMessageDeletionButton && isOnline)
|
initMenuDeleteMessage(showMessageDeletionButton && isOnline)
|
||||||
initMenuForwardMessage(
|
initMenuForwardMessage(
|
||||||
|
Loading…
Reference in New Issue
Block a user