From cc50aaee521eb7877d993fed794d9aed8070ee1f Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Wed, 18 Jun 2025 17:49:36 +0200 Subject: [PATCH] add first handling for threads (WIP) for now only added logic in IncomingTextMessageViewHolder.kt ... - add thread button for quoted messages if thread of message != current thread - open a new ChatActivity when clicked the button and pass threadId - change the title - add todos for now, the parentId was taken instead of topmostParentId (which is not available yet) Signed-off-by: Marcel Hibbe --- .../messages/IncomingTextMessageViewHolder.kt | 26 ++++++++++++++----- .../com/nextcloud/talk/chat/ChatActivity.kt | 19 ++++++++++++-- .../talk/chat/data/ChatMessageRepository.kt | 2 +- .../network/OfflineFirstChatRepository.kt | 5 +++- .../talk/chat/viewmodels/ChatViewModel.kt | 4 +-- .../nextcloud/talk/utils/bundle/BundleKeys.kt | 1 + .../res/drawable/outline_thread_unread_24.xml | 12 +++++++++ .../item_custom_incoming_text_message.xml | 1 - .../main/res/layout/item_message_quote.xml | 11 ++++++++ 9 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 app/src/main/res/drawable/outline_thread_unread_24.xml diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt index 43002a68d..7e020afbb 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt @@ -159,13 +159,19 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) } viewThemeUtils.platform.colorTextView(binding.messageTime, ColorRole.ON_SURFACE_VARIANT) + // parent message handling - if (!message.isDeleted && message.parentMessageId != null) { - processParentMessage(message) - binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE - } else { - binding.messageQuote.quotedChatMessageView.visibility = View.GONE - } + val chatActivity = commonMessageInterface as ChatActivity + binding.messageQuote.quotedChatMessageView.visibility = + // TODO replace message.parentMessageId with topmostParentId + if (chatActivity.threadId == message.parentMessageId) { + View.GONE + } else if (!message.isDeleted && message.parentMessageId != null) { + processParentMessage(message) + View.VISIBLE + } else { + View.GONE + } itemView.setTag(R.string.replyable_message_view_tag, message.replyable) @@ -362,6 +368,14 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : viewThemeUtils ) + // TODO replace message.parentMessageId!! with topmostParentId (=threadId) + binding.messageQuote.threadIcon.setOnClickListener { + chatActivity.openThread( + chatActivity.roomToken, + message.parentMessageId!! + ) + } + viewThemeUtils.talk.themeParentMessage( parentChatMessage, message, diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 5afe97ce0..8c6bc56e1 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -195,6 +195,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_RECORDING_STATE import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_START_CALL_AFTER_ROOM_SWITCH import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SWITCH_TO_ROOM +import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_THREAD_ID import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil import com.nextcloud.talk.utils.rx.DisposableSet import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder @@ -348,6 +349,7 @@ class ChatActivity : var sessionIdAfterRoomJoined: String? = null lateinit var roomToken: String + var threadId: Long? = null var conversationUser: User? = null lateinit var spreedCapabilities: SpreedCapability var chatApiVersion: Int = 1 @@ -472,7 +474,8 @@ class ChatActivity : chatViewModel.initData( credentials!!, urlForChatting, - roomToken + roomToken, + threadId ) messageInputFragment = getMessageInputFragment() @@ -526,6 +529,7 @@ class ChatActivity : val extras: Bundle? = intent.extras roomToken = extras?.getString(KEY_ROOM_TOKEN).orEmpty() + threadId = extras?.getLong(KEY_THREAD_ID) sharedText = extras?.getString(BundleKeys.KEY_SHARED_TEXT).orEmpty() @@ -2576,7 +2580,9 @@ class ChatActivity : viewThemeUtils.platform.colorTextView(title, ColorRole.ON_SURFACE) title.text = - if (currentConversation?.displayName != null) { + if (threadId != null && threadId!! > 0) { + "Thread $threadId" + } else if (currentConversation?.displayName != null) { try { EmojiCompat.get().process(currentConversation?.displayName as CharSequence).toString() } catch (e: java.lang.IllegalStateException) { @@ -4089,6 +4095,15 @@ class ChatActivity : } } + fun openThread(roomToken: String, threadId: Long) { + val bundle = Bundle() + bundle.putString(KEY_ROOM_TOKEN, roomToken) + bundle.putLong(KEY_THREAD_ID, threadId) + val chatIntent = Intent(context, ChatActivity::class.java) + chatIntent.putExtras(bundle) + startActivity(chatIntent) + } + override fun joinAudioCall() { startACall(true, false) } diff --git a/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt b/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt index 8e2e3f3ed..527885b50 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/data/ChatMessageRepository.kt @@ -44,7 +44,7 @@ interface ChatMessageRepository : LifecycleAwareManager { val removeMessageFlow: Flow - fun initData(credentials: String, urlForChatting: String, roomToken: String) + fun initData(credentials: String, urlForChatting: String, roomToken: String, threadId: Long?) fun updateConversation(conversationModel: ConversationModel) diff --git a/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt b/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt index 1fc1f9235..7c1aa1bc8 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/data/network/OfflineFirstChatRepository.kt @@ -118,11 +118,14 @@ class OfflineFirstChatRepository @Inject constructor( private lateinit var conversationModel: ConversationModel private lateinit var credentials: String private lateinit var urlForChatting: String + private var threadId: Long? = null - override fun initData(credentials: String, urlForChatting: String, roomToken: String) { + override fun initData(credentials: String, urlForChatting: String, roomToken: String, threadId: Long?) { internalConversationId = currentUser.id.toString() + "@" + roomToken this.credentials = credentials this.urlForChatting = urlForChatting + this.threadId = threadId // TODO: use this threadId in API requests when fetching messages? + + // TODO Introduce ChatBlocks for threads } override fun updateConversation(conversationModel: ConversationModel) { diff --git a/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt b/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt index 2e45755d0..c829c0542 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/viewmodels/ChatViewModel.kt @@ -272,8 +272,8 @@ class ChatViewModel @Inject constructor( val reactionDeletedViewState: LiveData get() = _reactionDeletedViewState - fun initData(credentials: String, urlForChatting: String, roomToken: String) { - chatRepository.initData(credentials, urlForChatting, roomToken) + fun initData(credentials: String, urlForChatting: String, roomToken: String, threadId: Long?) { + chatRepository.initData(credentials, urlForChatting, roomToken, threadId) } fun updateConversation(currentConversation: ConversationModel) { diff --git a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt index 1d4d61023..67713a74c 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt @@ -82,4 +82,5 @@ object BundleKeys { const val KEY_CHAT_URL: String = "KEY_CHAT_URL" const val KEY_SCROLL_TO_NOTIFICATION_CATEGORY: String = "KEY_SCROLL_TO_NOTIFICATION_CATEGORY" const val KEY_FOCUS_INPUT: String = "KEY_FOCUS_INPUT" + const val KEY_THREAD_ID = "KEY_THREAD_ID" } diff --git a/app/src/main/res/drawable/outline_thread_unread_24.xml b/app/src/main/res/drawable/outline_thread_unread_24.xml new file mode 100644 index 000000000..4c6e90af4 --- /dev/null +++ b/app/src/main/res/drawable/outline_thread_unread_24.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/app/src/main/res/layout/item_custom_incoming_text_message.xml b/app/src/main/res/layout/item_custom_incoming_text_message.xml index b025cc40f..b1367e55d 100644 --- a/app/src/main/res/layout/item_custom_incoming_text_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_text_message.xml @@ -64,7 +64,6 @@ app:layout_wrapBefore="true" tools:text="Talk to you later!" /> - + +