Skip to content

Commit fe09506

Browse files
committed
process messages in UI
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
1 parent dd6867a commit fe09506

2 files changed

Lines changed: 154 additions & 142 deletions

File tree

app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt

Lines changed: 153 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,20 +1032,37 @@ class ChatActivity :
10321032

10331033
lifecycleScope.launch {
10341034
repeatOnLifecycle(Lifecycle.State.STARTED) {
1035-
chatViewModel.messages()
1035+
chatViewModel.observeMessages()
10361036
.collect { messages ->
10371037
Log.d("newchat", "messages.size when colleting in ChatActivity:" + messages
10381038
.size)
10391039

1040-
val transformed = messages
1040+
val transformedMessages = messages
10411041
.let(::handleSystemMessages)
10421042
.let(::handleThreadMessages)
1043-
1044-
// // determinePreviousMessageIds....
1045-
// // .let(::handleExpandableSystemMessages)
1046-
// .let(::handleExpandableSystemMessages)
1047-
1048-
renderMessages(transformed)
1043+
.let(::determinePreviousMessageIds)
1044+
.let(::handleExpandableSystemMessages)
1045+
.let(::groupAndEnrichMessages)
1046+
1047+
// TODO: pinned message handling?
1048+
// val systemMessageType = chatMessage.systemMessageType
1049+
// if (systemMessageType != null &&
1050+
// (
1051+
// systemMessageType == ChatMessage.SystemMessageType.MESSAGE_PINNED ||
1052+
// systemMessageType == ChatMessage.SystemMessageType.MESSAGE_UNPINNED
1053+
// )
1054+
// ) {
1055+
// shouldRefreshRoom = true
1056+
// }
1057+
1058+
if (adapter != null) {
1059+
// Clearing and adding everything is a temporary solution and not ideal.
1060+
// It is done to prepare to replace ChatKit and XML with Jetpack Compose.
1061+
// As we "only" add the messages from the latest chatblock, the performance is quite okay.
1062+
// With Jetpack Compose the flow will be used directly in the UI instead to clear and add everything.
1063+
adapter!!.clear()
1064+
adapter!!.addToEnd(transformedMessages, false)
1065+
}
10491066
}
10501067
}
10511068
}
@@ -1130,20 +1147,6 @@ class ChatActivity :
11301147
.collect()
11311148
}
11321149

1133-
// this.lifecycleScope.launch {
1134-
// chatViewModel.getGeneralUIFlow.onEach { key ->
1135-
// when (key) {
1136-
// NO_OFFLINE_MESSAGES_FOUND -> {
1137-
// binding.progressBar.visibility = View.GONE
1138-
// binding.messagesListView.visibility = View.GONE
1139-
// binding.offline.root.visibility = View.VISIBLE
1140-
// }
1141-
//
1142-
// else -> {}
1143-
// }
1144-
// }.collect()
1145-
// }
1146-
11471150
this.lifecycleScope.launch {
11481151
chatViewModel.mediaPlayerSeekbarObserver.onEach { msg ->
11491152
adapter?.update(msg)
@@ -1551,17 +1554,6 @@ class ChatActivity :
15511554
}
15521555
}
15531556

1554-
private fun renderMessages(messages: List<ChatMessage>) {
1555-
if (adapter == null) return
1556-
1557-
// Clearing and adding everything is a temporary solution and not ideal.
1558-
// It is done to prepare to replace ChatKit and XML with Jetpack Compose.
1559-
// As we "only" add the messages from the latest chatblock, the performance is quite okay.
1560-
// With Jetpack Compose the flow will be used directly in the UI instead to clear and add everything.
1561-
adapter!!.clear()
1562-
adapter!!.addToEnd(messages, false)
1563-
}
1564-
15651557
private fun removeUnreadMessagesMarker() {
15661558
removeMessageById(UNREAD_MESSAGES_MARKER_ID.toString())
15671559
}
@@ -3313,62 +3305,62 @@ class ChatActivity :
33133305
}
33143306
}
33153307

3316-
private fun processMessagesFromTheFuture(chatMessageList: List<ChatMessage>, setUnreadMessagesMarker: Boolean) {
3317-
binding.scrollDownButton.visibility = View.GONE
3318-
3319-
val scrollToBottom: Boolean
3320-
3321-
if (setUnreadMessagesMarker) {
3322-
scrollToBottom = false
3323-
setUnreadMessageMarker(chatMessageList)
3324-
} else {
3325-
if (isScrolledToBottom()) {
3326-
scrollToBottom = true
3327-
} else {
3328-
scrollToBottom = false
3329-
binding.unreadMessagesPopup.visibility = View.VISIBLE
3330-
// here we have the problem that the chat jumps for every update
3331-
}
3332-
}
3333-
3334-
var shouldRefreshRoom = false
3335-
3336-
for (chatMessage in chatMessageList) {
3337-
chatMessage.activeUser = conversationUser
3338-
3339-
adapter?.let {
3340-
val previousChatMessage = it.items?.getOrNull(1)?.item
3341-
if (previousChatMessage != null && previousChatMessage is ChatMessage) {
3342-
chatMessage.isGrouped = groupMessages(chatMessage, previousChatMessage)
3343-
}
3344-
chatMessage.isOneToOneConversation =
3345-
(currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
3346-
chatMessage.isFormerOneToOneConversation =
3347-
(currentConversation?.type == ConversationEnums.ConversationType.FORMER_ONE_TO_ONE)
3348-
Log.d(TAG, "chatMessage to add:" + chatMessage.message)
3349-
it.addToStart(chatMessage, scrollToBottom)
3350-
}
3351-
3352-
val systemMessageType = chatMessage.systemMessageType
3353-
if (systemMessageType != null &&
3354-
(
3355-
systemMessageType == ChatMessage.SystemMessageType.MESSAGE_PINNED ||
3356-
systemMessageType == ChatMessage.SystemMessageType.MESSAGE_UNPINNED
3357-
)
3358-
) {
3359-
shouldRefreshRoom = true
3360-
}
3361-
}
3362-
3363-
if (shouldRefreshRoom) {
3364-
chatViewModel.refreshRoom()
3365-
}
3366-
3367-
// workaround to jump back to unread messages marker
3368-
if (setUnreadMessagesMarker) {
3369-
scrollToFirstUnreadMessage()
3370-
}
3371-
}
3308+
// private fun processMessagesFromTheFuture(chatMessageList: List<ChatMessage>, setUnreadMessagesMarker: Boolean) {
3309+
// binding.scrollDownButton.visibility = View.GONE
3310+
//
3311+
// val scrollToBottom: Boolean
3312+
//
3313+
// if (setUnreadMessagesMarker) {
3314+
// scrollToBottom = false
3315+
// setUnreadMessageMarker(chatMessageList)
3316+
// } else {
3317+
// if (isScrolledToBottom()) {
3318+
// scrollToBottom = true
3319+
// } else {
3320+
// scrollToBottom = false
3321+
// binding.unreadMessagesPopup.visibility = View.VISIBLE
3322+
// // here we have the problem that the chat jumps for every update
3323+
// }
3324+
// }
3325+
//
3326+
// var shouldRefreshRoom = false
3327+
//
3328+
// for (chatMessage in chatMessageList) {
3329+
// chatMessage.activeUser = conversationUser
3330+
//
3331+
// adapter?.let {
3332+
// val previousChatMessage = it.items?.getOrNull(1)?.item
3333+
// if (previousChatMessage != null && previousChatMessage is ChatMessage) {
3334+
// chatMessage.isGrouped = groupMessages(chatMessage, previousChatMessage)
3335+
// }
3336+
// chatMessage.isOneToOneConversation =
3337+
// (currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
3338+
// chatMessage.isFormerOneToOneConversation =
3339+
// (currentConversation?.type == ConversationEnums.ConversationType.FORMER_ONE_TO_ONE)
3340+
// Log.d(TAG, "chatMessage to add:" + chatMessage.message)
3341+
// it.addToStart(chatMessage, scrollToBottom)
3342+
// }
3343+
//
3344+
// val systemMessageType = chatMessage.systemMessageType
3345+
// if (systemMessageType != null &&
3346+
// (
3347+
// systemMessageType == ChatMessage.SystemMessageType.MESSAGE_PINNED ||
3348+
// systemMessageType == ChatMessage.SystemMessageType.MESSAGE_UNPINNED
3349+
// )
3350+
// ) {
3351+
// shouldRefreshRoom = true
3352+
// }
3353+
// }
3354+
//
3355+
// if (shouldRefreshRoom) {
3356+
// chatViewModel.refreshRoom()
3357+
// }
3358+
//
3359+
// // workaround to jump back to unread messages marker
3360+
// if (setUnreadMessagesMarker) {
3361+
// scrollToFirstUnreadMessage()
3362+
// }
3363+
// }
33723364

33733365
private fun isScrolledToBottom(): Boolean {
33743366
val position = layoutManager?.findFirstVisibleItemPosition()
@@ -3395,65 +3387,34 @@ class ChatActivity :
33953387
}
33963388
}
33973389

3398-
private fun processMessagesNotFromTheFuture(chatMessageList: List<ChatMessage>) {
3399-
for (i in chatMessageList.indices) {
3400-
if (chatMessageList.size > i + 1) {
3401-
chatMessageList[i].isGrouped = groupMessages(chatMessageList[i], chatMessageList[i + 1])
3402-
}
3403-
3404-
val chatMessage = chatMessageList[i]
3405-
chatMessage.isOneToOneConversation =
3406-
currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
3407-
chatMessage.isFormerOneToOneConversation =
3408-
(currentConversation?.type == ConversationEnums.ConversationType.FORMER_ONE_TO_ONE)
3409-
chatMessage.activeUser = conversationUser
3410-
chatMessage.token = roomToken
3411-
}
3412-
3413-
if (adapter != null) {
3414-
adapter?.addToEnd(chatMessageList, false)
3415-
}
3416-
scrollToRequestedMessageIfNeeded()
3417-
}
3390+
// private fun processMessagesNotFromTheFuture(chatMessageList: List<ChatMessage>) {
3391+
// for (i in chatMessageList.indices) {
3392+
// if (chatMessageList.size > i + 1) {
3393+
// chatMessageList[i].isGrouped = groupMessages(chatMessageList[i], chatMessageList[i + 1])
3394+
// }
3395+
//
3396+
// val chatMessage = chatMessageList[i]
3397+
// chatMessage.isOneToOneConversation =
3398+
// currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
3399+
// chatMessage.isFormerOneToOneConversation =
3400+
// (currentConversation?.type == ConversationEnums.ConversationType.FORMER_ONE_TO_ONE)
3401+
// chatMessage.activeUser = conversationUser
3402+
// chatMessage.token = roomToken
3403+
// }
3404+
//
3405+
// if (adapter != null) {
3406+
// adapter?.addToEnd(chatMessageList, false)
3407+
// }
3408+
// scrollToRequestedMessageIfNeeded()
3409+
// }
34183410

34193411
private fun scrollToFirstUnreadMessage() {
34203412
adapter?.let {
34213413
scrollToAndCenterMessageWithId(UNREAD_MESSAGES_MARKER_ID.toString())
34223414
}
34233415
}
34243416

3425-
private fun groupMessages(message1: ChatMessage, message2: ChatMessage): Boolean {
3426-
val message1IsSystem = message1.systemMessage.isNotEmpty()
3427-
val message2IsSystem = message2.systemMessage.isNotEmpty()
3428-
if (message1IsSystem != message2IsSystem) {
3429-
return false
3430-
}
3431-
3432-
if (message1.actorType == "bots" && message1.actorId != "changelog") {
3433-
return false
3434-
}
3435-
3436-
if (!message1IsSystem &&
3437-
(
3438-
(message1.actorType != message2.actorType) ||
3439-
(message2.actorId != message1.actorId)
3440-
)
3441-
) {
3442-
return false
3443-
}
3444-
3445-
val timeDifference = dateUtils.getTimeDifferenceInSeconds(
3446-
message2.timestamp,
3447-
message1.timestamp
3448-
)
3449-
val isLessThan5Min = timeDifference > FIVE_MINUTES_IN_SECONDS
3450-
return isSameDayMessages(message2, message1) &&
3451-
(message2.actorId == message1.actorId) &&
3452-
(!isLessThan5Min) &&
3453-
(message2.lastEditTimestamp == 0L || message1.lastEditTimestamp == 0L)
3454-
}
3455-
3456-
private fun determinePreviousMessageIds(chatMessageList: List<ChatMessage>) {
3417+
private fun determinePreviousMessageIds(chatMessageList: List<ChatMessage>) : List<ChatMessage> {
34573418
var previousMessageId = NO_PREVIOUS_MESSAGE_ID
34583419
for (i in chatMessageList.indices.reversed()) {
34593420
val chatMessage = chatMessageList[i]
@@ -3474,6 +3435,7 @@ class ChatActivity :
34743435

34753436
previousMessageId = chatMessage.jsonMessageId
34763437
}
3438+
return chatMessageList
34773439
}
34783440

34793441
private fun getItemFromAdapter(messageId: String): Pair<ChatMessage, Int>? {
@@ -3993,6 +3955,56 @@ class ChatActivity :
39933955
return chatMessageMap.values.toList()
39943956
}
39953957

3958+
private fun groupAndEnrichMessages(chatMessageList: List<ChatMessage>): List<ChatMessage> {
3959+
fun groupMessages(message1: ChatMessage, message2: ChatMessage): Boolean {
3960+
val message1IsSystem = message1.systemMessage.isNotEmpty()
3961+
val message2IsSystem = message2.systemMessage.isNotEmpty()
3962+
if (message1IsSystem != message2IsSystem) {
3963+
return false
3964+
}
3965+
3966+
if (message1.actorType == "bots" && message1.actorId != "changelog") {
3967+
return false
3968+
}
3969+
3970+
if (!message1IsSystem &&
3971+
(
3972+
(message1.actorType != message2.actorType) ||
3973+
(message2.actorId != message1.actorId)
3974+
)
3975+
) {
3976+
return false
3977+
}
3978+
3979+
val timeDifference = dateUtils.getTimeDifferenceInSeconds(
3980+
message2.timestamp,
3981+
message1.timestamp
3982+
)
3983+
val isLessThan5Min = timeDifference > FIVE_MINUTES_IN_SECONDS
3984+
return isSameDayMessages(message2, message1) &&
3985+
(message2.actorId == message1.actorId) &&
3986+
(!isLessThan5Min) &&
3987+
(message2.lastEditTimestamp == 0L || message1.lastEditTimestamp == 0L)
3988+
}
3989+
3990+
3991+
for (i in chatMessageList.indices) {
3992+
if (chatMessageList.size > i + 1) {
3993+
chatMessageList[i].isGrouped = groupMessages(chatMessageList[i], chatMessageList[i + 1])
3994+
}
3995+
val chatMessage = chatMessageList[i]
3996+
3997+
chatMessage.isOneToOneConversation =
3998+
currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
3999+
chatMessage.isFormerOneToOneConversation =
4000+
(currentConversation?.type == ConversationEnums.ConversationType.FORMER_ONE_TO_ONE)
4001+
4002+
chatMessage.activeUser = conversationUser
4003+
chatMessage.token = roomToken
4004+
}
4005+
return chatMessageList
4006+
}
4007+
39964008
private fun groupSystemMessages(previousMessage: ChatMessage, currentMessage: ChatMessage) {
39974009
previousMessage.expandableParent = true
39984010
currentMessage.expandableParent = false

app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ class ChatViewModel @Inject constructor(
200200

201201
val viewState: StateFlow<ChatMessageViewState> = _viewState
202202

203-
fun messages(): StateFlow<List<ChatMessage>> {
203+
fun observeMessages(): StateFlow<List<ChatMessage>> {
204204
return chatRepository.observeMessages(
205205
internalConversationId
206206
)

0 commit comments

Comments
 (0)