set thread titles for chatview header

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2025-07-10 23:30:34 +02:00
parent 3031bf8c21
commit 91cd342cb8
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
7 changed files with 74 additions and 2 deletions

View File

@ -293,4 +293,7 @@ interface NcApiCoroutines {
@GET @GET
suspend fun getThreads(@Header("Authorization") authorization: String, @Url url: String): ThreadsOverall suspend fun getThreads(@Header("Authorization") authorization: String, @Url url: String): ThreadsOverall
@GET
suspend fun getThread(@Header("Authorization") authorization: String, @Url url: String): ThreadOverall
} }

View File

@ -148,6 +148,7 @@ import com.nextcloud.talk.models.json.chat.ReadStatus
import com.nextcloud.talk.models.json.conversations.ConversationEnums import com.nextcloud.talk.models.json.conversations.ConversationEnums
import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall
import com.nextcloud.talk.models.json.threads.ThreadInfo
import com.nextcloud.talk.polls.ui.PollCreateDialogFragment import com.nextcloud.talk.polls.ui.PollCreateDialogFragment
import com.nextcloud.talk.remotefilebrowser.activities.RemoteFileBrowserActivity import com.nextcloud.talk.remotefilebrowser.activities.RemoteFileBrowserActivity
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
@ -353,6 +354,7 @@ class ChatActivity :
var sessionIdAfterRoomJoined: String? = null var sessionIdAfterRoomJoined: String? = null
lateinit var roomToken: String lateinit var roomToken: String
var threadId: Long? = null var threadId: Long? = null
var thread: 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
@ -507,6 +509,16 @@ class ChatActivity :
threadId threadId
) )
threadId?.let{
val threadUrl = ApiUtils.getUrlForThread(
version = 1,
baseUrl = conversationUser!!.baseUrl,
token = roomToken,
threadId = it.toInt()
)
chatViewModel.getThread(credentials, threadUrl)
}
messageInputFragment = getMessageInputFragment() messageInputFragment = getMessageInputFragment()
messageInputViewModel = ViewModelProvider(this, viewModelFactory)[MessageInputViewModel::class.java] messageInputViewModel = ViewModelProvider(this, viewModelFactory)[MessageInputViewModel::class.java]
messageInputViewModel.setData(chatViewModel.getChatRepository()) messageInputViewModel.setData(chatViewModel.getChatRepository())
@ -1270,6 +1282,24 @@ class ChatActivity :
} }
} }
} }
this.lifecycleScope.launch {
chatViewModel.threadRetrieveState.collect { uiState ->
when (uiState) {
ChatViewModel.ThreadRetrieveUiState.None -> {
}
is ChatViewModel.ThreadRetrieveUiState.Error -> {
Log.e(TAG, "Error when retrieving thread")
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
}
is ChatViewModel.ThreadRetrieveUiState.Success -> {
thread = uiState.thread
}
}
}
}
} }
private fun removeUnreadMessagesMarker() { private fun removeUnreadMessagesMarker() {
@ -2637,7 +2667,7 @@ class ChatActivity :
title.text = title.text =
if (isChatThread()) { if (isChatThread()) {
"Thread $threadId" thread?.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()
@ -2649,7 +2679,13 @@ class ChatActivity :
"" ""
} }
if (currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) { if (isChatThread()) {
val repliesAmountTitle = String.format(
resources.getString(R.string.thread_replies_amount),
thread?.thread?.numReplies
)
statusMessageViewContents(repliesAmountTitle)
} else if (currentConversation?.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
var statusMessage = "" var statusMessage = ""
if (currentConversation?.statusIcon != null) { if (currentConversation?.statusIcon != null) {
statusMessage += currentConversation?.statusIcon statusMessage += currentConversation?.statusIcon

View File

@ -40,6 +40,7 @@ import com.nextcloud.talk.models.json.reminder.Reminder
import com.nextcloud.talk.models.json.threads.ThreadInfo import com.nextcloud.talk.models.json.threads.ThreadInfo
import com.nextcloud.talk.models.json.userAbsence.UserAbsenceData import com.nextcloud.talk.models.json.userAbsence.UserAbsenceData
import com.nextcloud.talk.repositories.reactions.ReactionsRepository import com.nextcloud.talk.repositories.reactions.ReactionsRepository
import com.nextcloud.talk.threadsoverview.data.ThreadsRepository
import com.nextcloud.talk.ui.PlaybackSpeed import com.nextcloud.talk.ui.PlaybackSpeed
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
@ -68,6 +69,7 @@ class ChatViewModel @Inject constructor(
private val appPreferences: AppPreferences, private val appPreferences: AppPreferences,
private val chatNetworkDataSource: ChatNetworkDataSource, private val chatNetworkDataSource: ChatNetworkDataSource,
private val chatRepository: ChatMessageRepository, private val chatRepository: ChatMessageRepository,
private val threadsRepository: ThreadsRepository,
private val conversationRepository: OfflineConversationsRepository, private val conversationRepository: OfflineConversationsRepository,
private val reactionsRepository: ReactionsRepository, private val reactionsRepository: ReactionsRepository,
private val mediaRecorderManager: MediaRecorderManager, private val mediaRecorderManager: MediaRecorderManager,
@ -162,6 +164,9 @@ class ChatViewModel @Inject constructor(
private val _threadCreationState = MutableStateFlow<ThreadCreationUiState>(ThreadCreationUiState.None) private val _threadCreationState = MutableStateFlow<ThreadCreationUiState>(ThreadCreationUiState.None)
val threadCreationState: StateFlow<ThreadCreationUiState> = _threadCreationState val threadCreationState: StateFlow<ThreadCreationUiState> = _threadCreationState
private val _threadRetrieveState = MutableStateFlow<ThreadRetrieveUiState>(ThreadRetrieveUiState.None)
val threadRetrieveState: StateFlow<ThreadRetrieveUiState> = _threadRetrieveState
val getOpenGraph: LiveData<Reference> val getOpenGraph: LiveData<Reference>
get() = _getOpenGraph get() = _getOpenGraph
private val _getOpenGraph: MutableLiveData<Reference> = MutableLiveData() private val _getOpenGraph: MutableLiveData<Reference> = MutableLiveData()
@ -435,6 +440,13 @@ class ChatViewModel @Inject constructor(
} }
} }
fun getThread(credentials: String, url: String) {
viewModelScope.launch {
val thread = threadsRepository.getThread(credentials, url)
_threadRetrieveState.value = ThreadRetrieveUiState.Success(thread.ocs?.data)
}
}
fun loadMessages(withCredentials: String, withUrl: String) { fun loadMessages(withCredentials: String, withUrl: String) {
val bundle = Bundle() val bundle = Bundle()
bundle.putString(BundleKeys.KEY_CHAT_URL, withUrl) bundle.putString(BundleKeys.KEY_CHAT_URL, withUrl)
@ -890,4 +902,10 @@ class ChatViewModel @Inject constructor(
data class Success(val thread: ThreadInfo?) : ThreadCreationUiState() data class Success(val thread: ThreadInfo?) : ThreadCreationUiState()
data class Error(val message: String) : ThreadCreationUiState() data class Error(val message: String) : ThreadCreationUiState()
} }
sealed class ThreadRetrieveUiState {
data object None : ThreadRetrieveUiState()
data class Success(val thread: ThreadInfo?) : ThreadRetrieveUiState()
data class Error(val message: String) : ThreadRetrieveUiState()
}
} }

View File

@ -7,9 +7,12 @@
package com.nextcloud.talk.threadsoverview.data package com.nextcloud.talk.threadsoverview.data
import com.nextcloud.talk.models.json.threads.ThreadOverall
import com.nextcloud.talk.models.json.threads.ThreadsOverall import com.nextcloud.talk.models.json.threads.ThreadsOverall
interface ThreadsRepository { interface ThreadsRepository {
suspend fun getThreads(credentials: String, url: String): ThreadsOverall suspend fun getThreads(credentials: String, url: String): ThreadsOverall
suspend fun getThread(credentials: String, url: String): ThreadOverall
} }

View File

@ -9,6 +9,7 @@ package com.nextcloud.talk.threadsoverview.data
import com.nextcloud.talk.api.NcApiCoroutines import com.nextcloud.talk.api.NcApiCoroutines
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.models.json.threads.ThreadOverall
import com.nextcloud.talk.models.json.threads.ThreadsOverall import com.nextcloud.talk.models.json.threads.ThreadsOverall
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import javax.inject.Inject import javax.inject.Inject
@ -24,6 +25,10 @@ class ThreadsRepositoryImpl @Inject constructor(
return ncApiCoroutines.getThreads(credentials, url) return ncApiCoroutines.getThreads(credentials, url)
} }
override suspend fun getThread(credentials: String, url: String): ThreadOverall {
return ncApiCoroutines.getThread(credentials, url)
}
companion object { companion object {
val TAG = ThreadsRepositoryImpl::class.simpleName val TAG = ThreadsRepositoryImpl::class.simpleName
} }

View File

@ -41,6 +41,8 @@ import com.nextcloud.talk.data.user.UsersRepository
import com.nextcloud.talk.data.user.UsersRepositoryImpl import com.nextcloud.talk.data.user.UsersRepositoryImpl
import com.nextcloud.talk.repositories.reactions.ReactionsRepository import com.nextcloud.talk.repositories.reactions.ReactionsRepository
import com.nextcloud.talk.repositories.reactions.ReactionsRepositoryImpl import com.nextcloud.talk.repositories.reactions.ReactionsRepositoryImpl
import com.nextcloud.talk.threadsoverview.data.ThreadsRepository
import com.nextcloud.talk.threadsoverview.data.ThreadsRepositoryImpl
import com.nextcloud.talk.ui.theme.MaterialSchemesProviderImpl import com.nextcloud.talk.ui.theme.MaterialSchemesProviderImpl
import com.nextcloud.talk.ui.theme.TalkSpecificViewThemeUtils import com.nextcloud.talk.ui.theme.TalkSpecificViewThemeUtils
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
@ -147,6 +149,9 @@ class ComposePreviewUtils private constructor(context: Context) {
userProvider userProvider
) )
val threadsRepository: ThreadsRepository
get() = ThreadsRepositoryImpl(ncApiCoroutines, userProvider)
val conversationNetworkDataSource: ConversationsNetworkDataSource val conversationNetworkDataSource: ConversationsNetworkDataSource
get() = RetrofitConversationsNetwork(ncApi) get() = RetrofitConversationsNetwork(ncApi)
@ -173,6 +178,7 @@ class ComposePreviewUtils private constructor(context: Context) {
appPreferences, appPreferences,
chatNetworkDataSource, chatNetworkDataSource,
chatRepository, chatRepository,
threadsRepository,
conversationRepository, conversationRepository,
reactionsRepository, reactionsRepository,
mediaRecorderManager, mediaRecorderManager,

View File

@ -553,6 +553,7 @@ How to translate with transifex:
<string name="reply_in_thread">Reply in thread</string> <string name="reply_in_thread">Reply in thread</string>
<string name="show_threads_overview">Show threads</string> <string name="show_threads_overview">Show threads</string>
<string name="recent_threads">Recent threads</string> <string name="recent_threads">Recent threads</string>
<string name="thread_replies_amount">%1$d replies</string>
<!-- Upload --> <!-- Upload -->
<string name="nc_add_file">Add to conversation</string> <string name="nc_add_file">Add to conversation</string>