整理代码

This commit is contained in:
2024-08-24 23:11:20 +08:00
parent 367d1c9f3a
commit b4004663cd
40 changed files with 898 additions and 801 deletions

View File

@@ -1,23 +1,11 @@
package com.aiosman.riderpro.data
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.aiosman.riderpro.AppStore
import com.aiosman.riderpro.R
import com.aiosman.riderpro.data.api.ApiClient
import com.aiosman.riderpro.model.MomentEntity
import com.aiosman.riderpro.model.MomentImageEntity
import com.aiosman.riderpro.test.TestDatabase
import com.aiosman.riderpro.entity.MomentEntity
import com.aiosman.riderpro.entity.MomentImageEntity
import com.google.gson.annotations.SerializedName
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.net.URL
data class Moment(
@SerializedName("id")
@@ -100,9 +88,32 @@ data class UploadImage(
)
interface MomentService {
/**
* 获取动态详情
* @param id 动态ID
*/
suspend fun getMomentById(id: Int): MomentEntity
/**
* 点赞动态
* @param id 动态ID
*/
suspend fun likeMoment(id: Int)
/**
* 取消点赞动态
* @param id 动态ID
*/
suspend fun dislikeMoment(id: Int)
/**
* 获取动态列表
* @param pageNumber 页码
* @param author 作者ID,过滤条件
* @param timelineId 用户时间线ID,指定用户 ID 的时间线
* @param contentSearch 内容搜索,过滤条件
* @return 动态列表
*/
suspend fun getMoments(
pageNumber: Int,
author: Int? = null,
@@ -110,6 +121,13 @@ interface MomentService {
contentSearch: String? = null
): ListContainer<MomentEntity>
/**
* 创建动态
* @param content 动态内容
* @param authorId 作者ID
* @param images 图片列表
* @param relPostId 关联动态ID
*/
suspend fun createMoment(
content: String,
authorId: Int,
@@ -117,169 +135,17 @@ interface MomentService {
relPostId: Int? = null
): MomentEntity
/**
* 收藏动态
* @param id 动态ID
*/
suspend fun favoriteMoment(id: Int)
/**
* 取消收藏动态
* @param id 动态ID
*/
suspend fun unfavoriteMoment(id: Int)
}
class MomentPagingSource(
private val remoteDataSource: MomentRemoteDataSource,
private val author: Int? = null,
private val timelineId: Int? = null,
private val contentSearch: String? = null
) : PagingSource<Int, MomentEntity>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentEntity> {
return try {
val currentPage = params.key ?: 1
val moments = remoteDataSource.getMoments(
pageNumber = currentPage,
author = author,
timelineId = timelineId,
contentSearch = contentSearch
)
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, MomentEntity>): Int? {
return state.anchorPosition
}
}
class MomentRemoteDataSource(
private val momentService: MomentService,
) {
suspend fun getMoments(
pageNumber: Int,
author: Int?,
timelineId: Int?,
contentSearch: String?
): ListContainer<MomentEntity> {
return momentService.getMoments(pageNumber, author, timelineId, contentSearch)
}
}
class TestMomentServiceImpl() : MomentService {
val testMomentBackend = TestMomentBackend()
override suspend fun getMoments(
pageNumber: Int,
author: Int?,
timelineId: Int?,
contentSearch: String?
): ListContainer<MomentEntity> {
return testMomentBackend.fetchMomentItems(pageNumber, author, timelineId, contentSearch)
}
override suspend fun getMomentById(id: Int): MomentEntity {
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,
images: List<UploadImage>,
relPostId: Int?
): MomentEntity {
return testMomentBackend.createMoment(content, authorId, images, relPostId)
}
override suspend fun favoriteMoment(id: Int) {
testMomentBackend.favoriteMoment(id)
}
override suspend fun unfavoriteMoment(id: Int) {
testMomentBackend.unfavoriteMoment(id)
}
}
class TestMomentBackend(
private val loadDelay: Long = 500,
) {
val DataBatchSize = 5
suspend fun fetchMomentItems(
pageNumber: Int,
author: Int? = null,
timelineId: Int?,
contentSearch: String?
): ListContainer<MomentEntity> {
val resp = ApiClient.api.getPosts(
pageSize = DataBatchSize,
page = pageNumber,
timelineId = timelineId,
authorId = author,
contentSearch = contentSearch
)
val body = resp.body() ?: throw ServiceException("Failed to get moments")
return ListContainer(
total = body.total,
page = pageNumber,
pageSize = DataBatchSize,
list = body.list.map { it.toMomentItem() }
)
}
suspend fun getMomentById(id: Int): MomentEntity {
var resp = ApiClient.api.getPost(id)
var body = resp.body()?.data ?: throw ServiceException("Failed to get moment")
return body.toMomentItem()
}
suspend fun likeMoment(id: Int) {
ApiClient.api.likePost(id)
}
suspend fun dislikeMoment(id: Int) {
ApiClient.api.dislikePost(id)
}
fun createMultipartBody(file: File, name: String): MultipartBody.Part {
val requestFile = RequestBody.create("image/*".toMediaTypeOrNull(), file)
return MultipartBody.Part.createFormData(name, file.name, requestFile)
}
suspend fun createMoment(
content: String,
authorId: Int,
imageUriList: List<UploadImage>,
relPostId: Int?
): MomentEntity {
val textContent = content.toRequestBody("text/plain".toMediaTypeOrNull())
val imageList = imageUriList.map { item ->
val file = item.file
createMultipartBody(file, "image")
}
val response = ApiClient.api.createPost(imageList, textContent = textContent)
val body = response.body()?.data ?: throw ServiceException("Failed to create moment")
return body.toMomentItem()
}
suspend fun favoriteMoment(id: Int) {
ApiClient.api.favoritePost(id)
}
suspend fun unfavoriteMoment(id: Int) {
ApiClient.api.unfavoritePost(id)
}
}