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() { companion object { private const val TAG = "MessagePagingSource" } override fun getRefreshKey(state: PagingState): 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): LoadResult { 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) } } }