81 lines
3.6 KiB
Kotlin
81 lines
3.6 KiB
Kotlin
package chats.data.paging
|
||
|
||
import androidx.paging.PagingSource
|
||
import androidx.paging.PagingState
|
||
import core.database.data.MessageDao
|
||
import core.database.data.MessageEntity
|
||
import android.util.Log
|
||
|
||
/**
|
||
* PagingSource для загрузки сообщений из локальной базы Room
|
||
* Данные сортируются по sequenceId DESC (новые сообщения первыми)
|
||
*/
|
||
class MessagePagingSource(
|
||
private val dao: MessageDao,
|
||
private val chatId: String
|
||
) : PagingSource<Int, MessageEntity>() {
|
||
|
||
companion object {
|
||
private const val TAG = "MessagePagingSource"
|
||
}
|
||
|
||
override fun getRefreshKey(state: PagingState<Int, MessageEntity>): Int? {
|
||
Log.d(TAG, "getRefreshKey() called")
|
||
return state.anchorPosition?.let { anchorPosition ->
|
||
val anchorPage = state.closestPageToPosition(anchorPosition)
|
||
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
|
||
}
|
||
}
|
||
|
||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MessageEntity> {
|
||
Log.d(TAG, ">>> load() called with: position=${params.key}, loadSize=${params.loadSize}")
|
||
return try {
|
||
// При DESC порядке:
|
||
// - key = sequenceId последнего сообщения в текущей странице
|
||
// - APPEND = загружаем сообщения С МЕНЬШИМ sequenceId (старые)
|
||
// - PREPEND = загружаем сообщения С БОЛЬШИМ sequenceId (новые)
|
||
|
||
val position = params.key // sequenceId граничного сообщения
|
||
val loadSize = params.loadSize
|
||
|
||
Log.d(TAG, "Loading: chatId=$chatId, position=$position, loadSize=$loadSize")
|
||
|
||
val messages = if (position == null) {
|
||
// Первая загрузка - получаем самые последние сообщения (включая maxSeq)
|
||
val maxSeq = dao.getMaxSequenceId(chatId)
|
||
Log.d(TAG, "First load: maxSeq=$maxSeq")
|
||
if (maxSeq == null) {
|
||
Log.d(TAG, "No messages in database")
|
||
emptyList()
|
||
} else {
|
||
// Используем <= чтобы включить самое последнее сообщение
|
||
dao.getMessagesUpToAndIncluding(chatId, maxSeq, loadSize)
|
||
}
|
||
} else {
|
||
// Загружаем сообщения с sequenceId < position (старые)
|
||
Log.d(TAG, "Append: loading messages before sequenceId=$position")
|
||
dao.getMessagesBefore(chatId, position, loadSize)
|
||
}
|
||
|
||
Log.d(TAG, "Loaded ${messages.size} messages, first=${messages.firstOrNull()?.sequenceId}, last=${messages.lastOrNull()?.sequenceId}")
|
||
|
||
// Для DESC порядка:
|
||
// - prevKey = максимальный sequenceId в странице (для загрузки новых)
|
||
// - nextKey = минимальный sequenceId в странице (для загрузки старых)
|
||
val prevKey = messages.firstOrNull()?.sequenceId?.plus(1)
|
||
val nextKey = messages.lastOrNull()?.sequenceId?.minus(1)
|
||
|
||
Log.d(TAG, "prevKey=$prevKey, nextKey=$nextKey")
|
||
|
||
LoadResult.Page(
|
||
data = messages,
|
||
prevKey = prevKey,
|
||
nextKey = nextKey
|
||
)
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "Error loading messages", e)
|
||
LoadResult.Error(e)
|
||
}
|
||
}
|
||
}
|