package com.aiosman.riderpro.data import androidx.paging.PagingSource import androidx.paging.PagingState import com.aiosman.riderpro.R 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 dislikeMoment(id: Int) suspend fun getMoments( pageNumber: Int, author: Int? = null, timelineId: Int? = null ): ListContainer suspend fun createMoment( content: String, authorId: Int, imageUriList: List ): MomentItem } 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) } override suspend fun dislikeMoment(id: Int) { testMomentBackend.dislikeMoment(id) } override suspend fun createMoment( content: String, authorId: Int, imageUriList: List ): MomentItem { return testMomentBackend.createMoment(content, authorId, imageUriList) } } 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 rawList = rawList.sortedBy { it.id }.reversed() 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 || it.authorId == 1 } } 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)) currentSublist.forEach { val myLikeIdList = TestDatabase.likeMomentList.filter { it.second == 1 }.map { it.first } if (myLikeIdList.contains(it.id)) { it.liked = true } } // delay kotlinx.coroutines.delay(loadDelay) return ListContainer( total = rawList.size, page = pageNumber, pageSize = DataBatchSize, list = currentSublist ) } suspend fun getMomentById(id: Int): MomentItem { var moment = TestDatabase.momentData.first { it.id == id } val isLike = TestDatabase.likeMomentList.any { it.first == id && it.second == 1 } moment = moment.copy(liked = isLike) return moment } 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) TestDatabase.likeMomentList += Pair(id, 1) } suspend fun dislikeMoment(id: Int) { val oldMoment = TestDatabase.momentData.first { it.id == id } val newMoment = oldMoment.copy(likeCount = oldMoment.likeCount - 1) TestDatabase.updateMomentById(id, newMoment) TestDatabase.likeMomentList = TestDatabase.likeMomentList.filter { it.first != id } } suspend fun createMoment( content: String, authorId: Int, imageUriList: List ): MomentItem { TestDatabase.momentIdCounter += 1 val person = TestDatabase.accountData.first { it.id == authorId } val newMoment = MomentItem( id = TestDatabase.momentIdCounter, avatar = person.avatar, nickname = person.nickName, location = person.country, time = "2023.02.02 11:23", followStatus = false, momentTextContent = content, momentPicture = R.drawable.default_moment_img, likeCount = 0, commentCount = 0, shareCount = 0, favoriteCount = 0, images = imageUriList, authorId = person.id ) TestDatabase.momentData += newMoment return newMoment } }