package com.aiosman.riderpro.data import androidx.paging.PagingSource import androidx.paging.PagingState import com.aiosman.riderpro.model.MomentItem import com.aiosman.riderpro.test.TestDatabase import java.io.IOException import kotlin.math.min interface MomentService { suspend fun getMomentById(id: Int): MomentItem suspend fun likeMoment(id: Int) suspend fun getMoments( pageNumber: Int, author: Int? = null, timelineId: Int? = null ): ListContainer } class MomentPagingSource( private val remoteDataSource: MomentRemoteDataSource, private val author: Int? = null, private val timelineId: Int? = null ) : PagingSource() { override suspend fun load(params: LoadParams): LoadResult { return try { val currentPage = params.key ?: 1 val moments = remoteDataSource.getMoments( pageNumber = currentPage, author = author, timelineId = timelineId ) LoadResult.Page( data = moments.list, prevKey = if (currentPage == 1) null else currentPage - 1, nextKey = if (moments.list.isEmpty()) null else moments.page + 1 ) } catch (exception: IOException) { return LoadResult.Error(exception) } } override fun getRefreshKey(state: PagingState): Int? { return state.anchorPosition } } class MomentRemoteDataSource( private val momentService: MomentService, ) { suspend fun getMoments( pageNumber: Int, author: Int?, timelineId: Int? ): ListContainer { return momentService.getMoments(pageNumber, author, timelineId) } } class TestMomentServiceImpl() : MomentService { val testMomentBackend = TestMomentBackend() override suspend fun getMoments( pageNumber: Int, author: Int?, timelineId: Int? ): ListContainer { return testMomentBackend.fetchMomentItems(pageNumber, author, timelineId) } override suspend fun getMomentById(id: Int): MomentItem { return testMomentBackend.getMomentById(id) } override suspend fun likeMoment(id: Int) { testMomentBackend.likeMoment(id) } } class TestMomentBackend( private val loadDelay: Long = 500, ) { val DataBatchSize = 5 suspend fun fetchMomentItems( pageNumber: Int, author: Int? = null, timelineId: Int? ): ListContainer { var rawList = TestDatabase.momentData if (author != null) { rawList = rawList.filter { it.authorId == author } } if (timelineId != null) { val followIdList = TestDatabase.followList.filter { it.first == timelineId }.map { it.second } rawList = rawList.filter { it.authorId in followIdList } } val from = (pageNumber - 1) * DataBatchSize val to = (pageNumber) * DataBatchSize if (from >= rawList.size) { return ListContainer( total = rawList.size, page = pageNumber, pageSize = DataBatchSize, list = emptyList() ) } val currentSublist = rawList.subList(from, min(to, rawList.size)) // delay kotlinx.coroutines.delay(loadDelay) return ListContainer( total = rawList.size, page = pageNumber, pageSize = DataBatchSize, list = currentSublist ) } suspend fun getMomentById(id: Int): MomentItem { return TestDatabase.momentData[id] } suspend fun likeMoment(id: Int) { val oldMoment = TestDatabase.momentData.first { it.id == id } val newMoment = oldMoment.copy(likeCount = oldMoment.likeCount + 1) TestDatabase.updateMomentById(id, newMoment) } }