Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.nextcloud.talk.models.json.status.predefined.PredefinedStatusOverall
import com.nextcloud.talk.models.json.testNotification.TestNotificationOverall
import com.nextcloud.talk.models.json.threads.ThreadOverall
import com.nextcloud.talk.models.json.threads.ThreadsOverall
import com.nextcloud.talk.models.json.unifiedsearch.UnifiedSearchOverall
import com.nextcloud.talk.models.json.upcomingEvents.UpcomingEventsOverall
import com.nextcloud.talk.models.json.userAbsence.UserAbsenceOverall
import okhttp3.MultipartBody
Expand Down Expand Up @@ -451,6 +452,17 @@ interface NcApiCoroutines {
@Query("reaction") reaction: String?
): ReactionsOverall

@Suppress("LongParameterList")
@GET
suspend fun performUnifiedSearch(
@Header("Authorization") authorization: String?,
@Url url: String,
@Query("term") term: String,
@Query("from") fromUrl: String?,
@Query("limit") limit: Int,
@Query("cursor") cursor: Int
): UnifiedSearchOverall

// Url is: /api/{apiVersion}/chat/{token}/read
@FormUrlEncoded
@POST
Expand Down
408 changes: 368 additions & 40 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ import kotlinx.coroutines.flow.Flow
@Suppress("TooManyFunctions")
interface ChatMessageRepository : LifecycleAwareManager {

enum class LoadMoreDirection {
OLDER,
NEWER
}

data class MessagesRange(val oldestMessageId: Long, val newestMessageId: Long)

/**
* Stream of a list of messages to be handled using the associated boolean
* false for past messages, true for future messages.
*/
val messageFlow:
Flow<
Triple<
Boolean,
Boolean,
List<ChatMessage>
>
>
val messageFlow: Flow<Triple<Boolean, Boolean, List<ChatMessage>>>

val updateMessageFlow: Flow<ChatMessage>

Expand Down Expand Up @@ -68,11 +68,12 @@ interface ChatMessageRepository : LifecycleAwareManager {
* [withNetworkParams] credentials and url
*/
suspend fun loadMoreMessages(
beforeMessageId: Long,
anchorMessageId: Long,
direction: LoadMoreDirection,
roomToken: String,
withMessageLimit: Int,
withNetworkParams: Bundle
)
): MessagesRange?

/**
* Gets a individual message.
Expand Down Expand Up @@ -160,5 +161,9 @@ interface ChatMessageRepository : LifecycleAwareManager {

suspend fun onSignalingChatMessageReceived(chatMessages: List<ChatMessageJson>)

fun observeMessages(internalConversationId: String): Flow<List<ChatMessageEntity>>
fun observeLatestMessages(internalConversationId: String): Flow<List<ChatMessageEntity>>

fun observeMessagesForAnchor(internalConversationId: String, anchorMessageId: Long): Flow<List<ChatMessageEntity>>

suspend fun loadMessageContext(messageId: Long, limit: Int, threadId: Long? = null): Result<MessagesRange>
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class OfflineFirstChatRepository @Inject constructor(
private var itIsPaused = false

lateinit var internalConversationId: String
private lateinit var roomToken: String
private lateinit var conversationModel: ConversationModel
private lateinit var credentials: String
private lateinit var urlForChatting: String
Expand All @@ -129,6 +130,7 @@ class OfflineFirstChatRepository @Inject constructor(
threadId: Long?
) {
this.currentUser = currentUser
this.roomToken = roomToken

internalConversationId = currentUser.id.toString() + "@" + roomToken
this.credentials = credentials
Expand Down Expand Up @@ -283,24 +285,34 @@ class OfflineFirstChatRepository @Inject constructor(
}

override suspend fun loadMoreMessages(
beforeMessageId: Long,
anchorMessageId: Long,
direction: ChatMessageRepository.LoadMoreDirection,
roomToken: String,
withMessageLimit: Int,
withNetworkParams: Bundle
) {
Log.d(TAG, "---- loadMoreMessages for $beforeMessageId ------------")
): ChatMessageRepository.MessagesRange? {
Log.d(TAG, "---- loadMoreMessages for $anchorMessageId ($direction) ------------")

val lookIntoFuture = direction == ChatMessageRepository.LoadMoreDirection.NEWER

val fieldMap = getFieldMap(
lookIntoFuture = false,
lookIntoFuture = lookIntoFuture,
timeout = 0,
includeLastKnown = false,
lastKnown = beforeMessageId.toInt(),
includeLastKnown = true,
lastKnown = anchorMessageId.toInt(),
limit = withMessageLimit
)
withNetworkParams.putSerializable(BundleKeys.KEY_FIELD_MAP, fieldMap)

Log.d(TAG, "Starting online request for loadMoreMessages")
getAndPersistMessages(withNetworkParams)

return getBlockOfMessage(anchorMessageId.toInt())?.let {
ChatMessageRepository.MessagesRange(
oldestMessageId = it.oldestMessageId,
newestMessageId = it.newestMessageId
)
}
}

@Suppress("LongParameterList")
Expand Down Expand Up @@ -355,6 +367,51 @@ class OfflineFirstChatRepository @Inject constructor(
)
}

@Suppress("Detekt.TooGenericExceptionCaught")
override suspend fun loadMessageContext(
messageId: Long,
limit: Int,
threadId: Long?
): Result<ChatMessageRepository.MessagesRange> =
runCatching {
val messages = network.getContextForChatMessage(
credentials = credentials,
baseUrl = currentUser.baseUrl!!,
token = roomToken,
messageId = messageId.toString(),
limit = limit,
threadId = threadId?.toInt()
)

val filteredMessages = if (threadId == null) {
messages.filter { !it.hasThread || it.threadId == it.id }
} else {
messages
}

require(filteredMessages.isNotEmpty()) { "No context messages returned" }

val persisted = persistChatMessagesAndHandleSystemMessages(filteredMessages)
val oldestId = persisted.minOf { it.id }
val newestId = persisted.maxOf { it.id }

val block = ChatBlockEntity(
internalConversationId = internalConversationId,
accountId = currentUser.id!!,
token = roomToken,
threadId = this.threadId,
oldestMessageId = oldestId,
newestMessageId = newestId,
hasHistory = true
)
updateBlocks(block)

ChatMessageRepository.MessagesRange(
oldestMessageId = oldestId,
newestMessageId = newestId
)
}

override fun observeParentMessages(parentIds: List<Long>): Flow<List<ChatMessage>> =
chatDao.getMessagesFromIds(parentIds)
.map { entities -> entities.map { it.toDomainModel() } }
Expand All @@ -381,7 +438,7 @@ class OfflineFirstChatRepository @Inject constructor(
val messages = network.getContextForChatMessage(
credentials = credentials,
baseUrl = currentUser.baseUrl!!,
token = conversationModel.token,
token = roomToken,
messageId = id.toString(),
limit = 1,
threadId = null
Expand Down Expand Up @@ -990,7 +1047,7 @@ class OfflineFirstChatRepository @Inject constructor(
return chatMessageEntities
}

override fun observeMessages(internalConversationId: String): Flow<List<ChatMessageEntity>> =
override fun observeLatestMessages(internalConversationId: String): Flow<List<ChatMessageEntity>> =
chatBlocksDao
.getLatestChatBlock(internalConversationId, threadId)
.distinctUntilChanged()
Expand All @@ -1007,6 +1064,31 @@ class OfflineFirstChatRepository @Inject constructor(
}
}

override fun observeMessagesForAnchor(
internalConversationId: String,
anchorMessageId: Long
): Flow<List<ChatMessageEntity>> =
chatBlocksDao
.getChatBlocksContainingMessageId(
internalConversationId = internalConversationId,
threadId = threadId,
messageId = anchorMessageId
)
.distinctUntilChanged()
.flatMapLatest { blocks ->
val block = blocks.firstOrNull()
if (block == null) {
flowOf(emptyList())
} else {
chatDao.getMessagesInRange(
internalConversationId = internalConversationId,
threadId = threadId,
oldestMessageId = block.oldestMessageId,
newestMessageId = block.newestMessageId
)
}
}

@Suppress("LongParameterList")
override suspend fun sendScheduledChatMessage(
credentials: String,
Expand Down
Loading
Loading