整理代码
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
import com.aiosman.riderpro.data.api.ChangePasswordRequestBody
|
||||
import com.aiosman.riderpro.data.api.GoogleRegisterRequestBody
|
||||
import com.aiosman.riderpro.data.api.LoginUserRequestBody
|
||||
import com.aiosman.riderpro.data.api.RegisterRequestBody
|
||||
import com.aiosman.riderpro.data.api.UpdateNoticeRequestBody
|
||||
import com.aiosman.riderpro.test.TestDatabase
|
||||
import com.aiosman.riderpro.entity.AccountFavouriteEntity
|
||||
import com.aiosman.riderpro.entity.AccountLikeEntity
|
||||
import com.aiosman.riderpro.entity.AccountProfileEntity
|
||||
import com.aiosman.riderpro.entity.NoticePostEntity
|
||||
import com.aiosman.riderpro.entity.NoticeUserEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.MultipartBody
|
||||
@@ -16,41 +18,29 @@ import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.asRequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.Date
|
||||
|
||||
data class AccountLikeEntity(
|
||||
val post: NoticePostEntity,
|
||||
val user: NoticeUserEntity,
|
||||
val likeTime: Date,
|
||||
)
|
||||
|
||||
data class AccountFavouriteEntity(
|
||||
val post: NoticePostEntity,
|
||||
val user: NoticeUserEntity,
|
||||
val favoriteTime: Date,
|
||||
)
|
||||
|
||||
data class AccountProfileEntity(
|
||||
val id: Int,
|
||||
val followerCount: Int,
|
||||
val followingCount: Int,
|
||||
val nickName: String,
|
||||
val avatar: String,
|
||||
val bio: String,
|
||||
val country: String,
|
||||
val isFollowing: Boolean
|
||||
)
|
||||
|
||||
/**
|
||||
* 用户资料
|
||||
*/
|
||||
data class AccountProfile(
|
||||
// 用户ID
|
||||
val id: Int,
|
||||
// 用户名
|
||||
val username: String,
|
||||
// 昵称
|
||||
val nickname: String,
|
||||
// 头像
|
||||
val avatar: String,
|
||||
// 关注数
|
||||
val followingCount: Int,
|
||||
// 粉丝数
|
||||
val followerCount: Int,
|
||||
// 是否关注
|
||||
val isFollowing: Boolean
|
||||
) {
|
||||
/**
|
||||
* 转换为Entity
|
||||
*/
|
||||
fun toAccountProfileEntity(): AccountProfileEntity {
|
||||
return AccountProfileEntity(
|
||||
id = id,
|
||||
@@ -65,23 +55,27 @@ data class AccountProfile(
|
||||
}
|
||||
}
|
||||
|
||||
data class NoticePostEntity(
|
||||
val id: Int,
|
||||
val textContent: String,
|
||||
val images: List<Image>,
|
||||
val time: Date,
|
||||
)
|
||||
|
||||
/**
|
||||
* 消息关联资料
|
||||
*/
|
||||
data class NoticePost(
|
||||
// 动态ID
|
||||
@SerializedName("id")
|
||||
val id: Int,
|
||||
// 动态内容
|
||||
@SerializedName("textContent")
|
||||
// 动态图片
|
||||
val textContent: String,
|
||||
// 动态图片
|
||||
@SerializedName("images")
|
||||
val images: List<Image>,
|
||||
// 动态时间
|
||||
@SerializedName("time")
|
||||
val time: String,
|
||||
) {
|
||||
/**
|
||||
* 转换为Entity
|
||||
*/
|
||||
fun toNoticePostEntity(): NoticePostEntity {
|
||||
return NoticePostEntity(
|
||||
id = id,
|
||||
@@ -97,20 +91,23 @@ data class NoticePost(
|
||||
}
|
||||
}
|
||||
|
||||
data class NoticeUserEntity(
|
||||
val id: Int,
|
||||
val nickName: String,
|
||||
val avatar: String,
|
||||
)
|
||||
|
||||
/**
|
||||
* 消息关联用户
|
||||
*/
|
||||
data class NoticeUser(
|
||||
// 用户ID
|
||||
@SerializedName("id")
|
||||
val id: Int,
|
||||
// 昵称
|
||||
@SerializedName("nickName")
|
||||
val nickName: String,
|
||||
// 头像
|
||||
@SerializedName("avatar")
|
||||
val avatar: String,
|
||||
) {
|
||||
/**
|
||||
* 转换为Entity
|
||||
*/
|
||||
fun toNoticeUserEntity(): NoticeUserEntity {
|
||||
return NoticeUserEntity(
|
||||
id = id,
|
||||
@@ -120,13 +117,20 @@ data class NoticeUser(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞消息通知
|
||||
*/
|
||||
data class AccountLike(
|
||||
// 是否未读
|
||||
@SerializedName("isUnread")
|
||||
val isUnread: Boolean,
|
||||
// 动态
|
||||
@SerializedName("post")
|
||||
val post: NoticePost,
|
||||
// 点赞用户
|
||||
@SerializedName("user")
|
||||
val user: NoticeUser,
|
||||
// 点赞时间
|
||||
@SerializedName("likeTime")
|
||||
val likeTime: String,
|
||||
) {
|
||||
@@ -192,108 +196,93 @@ data class AccountNotice(
|
||||
)
|
||||
|
||||
|
||||
class LikeItemPagingSource(
|
||||
private val accountService: AccountService,
|
||||
) : PagingSource<Int, AccountLikeEntity>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AccountLikeEntity> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val likes = accountService.getMyLikeNotice(
|
||||
page = currentPage,
|
||||
pageSize = 20,
|
||||
)
|
||||
|
||||
LoadResult.Page(
|
||||
data = likes.list.map {
|
||||
it.toAccountLikeEntity()
|
||||
},
|
||||
prevKey = if (currentPage == 1) null else currentPage - 1,
|
||||
nextKey = if (likes.list.isEmpty()) null else likes.page + 1
|
||||
)
|
||||
} catch (exception: IOException) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, AccountLikeEntity>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
}
|
||||
|
||||
class FavoriteItemPagingSource(
|
||||
private val accountService: AccountService,
|
||||
) : PagingSource<Int, AccountFavouriteEntity>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AccountFavouriteEntity> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val favouriteListContainer = accountService.getMyFavouriteNotice(
|
||||
page = currentPage,
|
||||
pageSize = 20,
|
||||
)
|
||||
LoadResult.Page(
|
||||
data = favouriteListContainer.list.map {
|
||||
it.toAccountFavouriteEntity()
|
||||
},
|
||||
prevKey = if (currentPage == 1) null else currentPage - 1,
|
||||
nextKey = if (favouriteListContainer.list.isEmpty()) null else favouriteListContainer.page + 1
|
||||
)
|
||||
} catch (exception: IOException) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, AccountFavouriteEntity>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
}
|
||||
|
||||
class FollowItemPagingSource(
|
||||
private val accountService: AccountService,
|
||||
) : PagingSource<Int, AccountFollow>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AccountFollow> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val followListContainer = accountService.getMyFollowNotice(
|
||||
page = currentPage,
|
||||
pageSize = 20,
|
||||
)
|
||||
|
||||
LoadResult.Page(
|
||||
data = followListContainer.list.map {
|
||||
it.copy(
|
||||
avatar = "${ApiClient.BASE_SERVER}${it.avatar}",
|
||||
)
|
||||
},
|
||||
prevKey = if (currentPage == 1) null else currentPage - 1,
|
||||
nextKey = if (followListContainer.list.isEmpty()) null else followListContainer.page + 1
|
||||
)
|
||||
} catch (exception: IOException) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, AccountFollow>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface AccountService {
|
||||
/**
|
||||
* 获取登录当前用户的资料
|
||||
*/
|
||||
suspend fun getMyAccountProfile(): AccountProfileEntity
|
||||
suspend fun getAccountProfileById(id: Int): AccountProfileEntity
|
||||
|
||||
/**
|
||||
* 获取登录的用户认证信息
|
||||
*/
|
||||
suspend fun getMyAccount(): UserAuth
|
||||
|
||||
/**
|
||||
* 使用用户名密码登录
|
||||
* @param loginName 用户名
|
||||
* @param password 密码
|
||||
*/
|
||||
suspend fun loginUserWithPassword(loginName: String, password: String): UserAuth
|
||||
|
||||
/**
|
||||
* 使用google登录
|
||||
* @param googleId googleId
|
||||
*/
|
||||
suspend fun loginUserWithGoogle(googleId: String): UserAuth
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
suspend fun logout()
|
||||
suspend fun updateAvatar(uri: String)
|
||||
|
||||
/**
|
||||
* 更新用户资料
|
||||
* @param avatar 头像
|
||||
* @param nickName 昵称
|
||||
* @param bio 简介
|
||||
*/
|
||||
suspend fun updateProfile(avatar: UploadImage?, nickName: String?, bio: String?)
|
||||
|
||||
/**
|
||||
* 注册用户
|
||||
* @param loginName 用户名
|
||||
* @param password 密码
|
||||
*/
|
||||
suspend fun registerUserWithPassword(loginName: String, password: String)
|
||||
|
||||
/**
|
||||
* 使用google账号注册
|
||||
* @param idToken googleIdToken
|
||||
*/
|
||||
suspend fun regiterUserWithGoogleAccount(idToken: String)
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param oldPassword 旧密码
|
||||
* @param newPassword 新密码
|
||||
*/
|
||||
suspend fun changeAccountPassword(oldPassword: String, newPassword: String)
|
||||
|
||||
/**
|
||||
* 获取我的点赞通知
|
||||
* @param page 页码
|
||||
* @param pageSize 每页数量
|
||||
*/
|
||||
suspend fun getMyLikeNotice(page: Int, pageSize: Int): ListContainer<AccountLike>
|
||||
|
||||
/**
|
||||
* 获取我的关注通知
|
||||
* @param page 页码
|
||||
* @param pageSize 每页数量
|
||||
*/
|
||||
suspend fun getMyFollowNotice(page: Int, pageSize: Int): ListContainer<AccountFollow>
|
||||
|
||||
/**
|
||||
* 获取我的收藏通知
|
||||
* @param page 页码
|
||||
* @param pageSize 每页数量
|
||||
*/
|
||||
suspend fun getMyFavouriteNotice(page: Int, pageSize: Int): ListContainer<AccountFavourite>
|
||||
|
||||
/**
|
||||
* 获取我的通知信息
|
||||
*/
|
||||
suspend fun getMyNoticeInfo(): AccountNotice
|
||||
|
||||
/**
|
||||
* 更新通知信息,更新最后一次查看时间
|
||||
* @param payload 通知信息
|
||||
*/
|
||||
suspend fun updateNotice(payload: UpdateNoticeRequestBody)
|
||||
}
|
||||
|
||||
@@ -304,12 +293,6 @@ class AccountServiceImpl : AccountService {
|
||||
return body.data.toAccountProfileEntity()
|
||||
}
|
||||
|
||||
override suspend fun getAccountProfileById(id: Int): AccountProfileEntity {
|
||||
val resp = ApiClient.api.getAccountProfileById(id)
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get account")
|
||||
return body.data.toAccountProfileEntity()
|
||||
}
|
||||
|
||||
override suspend fun getMyAccount(): UserAuth {
|
||||
val resp = ApiClient.api.checkToken()
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get account")
|
||||
@@ -323,7 +306,7 @@ class AccountServiceImpl : AccountService {
|
||||
}
|
||||
|
||||
override suspend fun loginUserWithGoogle(googleId: String): UserAuth {
|
||||
val resp = ApiClient.api.login(LoginUserRequestBody(googleId=googleId))
|
||||
val resp = ApiClient.api.login(LoginUserRequestBody(googleId = googleId))
|
||||
val body = resp.body() ?: throw ServiceException("Failed to login")
|
||||
return UserAuth(0, body.token)
|
||||
}
|
||||
@@ -339,15 +322,6 @@ class AccountServiceImpl : AccountService {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override suspend fun updateAvatar(uri: String) {
|
||||
TestDatabase.accountData = TestDatabase.accountData.map {
|
||||
if (it.id == 1) {
|
||||
it.copy(avatar = uri)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createMultipartBody(file: File, filename: String, name: String): MultipartBody.Part {
|
||||
val requestFile = file.asRequestBody("image/*".toMediaTypeOrNull())
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.AppStore
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
import com.aiosman.riderpro.data.api.CommentRequestBody
|
||||
import com.aiosman.riderpro.test.TestDatabase
|
||||
import com.aiosman.riderpro.entity.CommentEntity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import java.io.IOException
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* 评论相关 Service
|
||||
*/
|
||||
interface CommentService {
|
||||
/**
|
||||
* 获取动态
|
||||
* @param pageNumber 页码
|
||||
* @param postId 动态ID,过滤条件
|
||||
* @param postUser 动态作者ID,获取某个用户所有动态下的评论
|
||||
* @param selfNotice 是否是自己的通知
|
||||
* @return 评论列表
|
||||
*/
|
||||
suspend fun getComments(
|
||||
pageNumber: Int,
|
||||
postId: Int? = null,
|
||||
@@ -20,32 +24,67 @@ interface CommentService {
|
||||
selfNotice: Boolean? = null
|
||||
): ListContainer<CommentEntity>
|
||||
|
||||
/**
|
||||
* 创建评论
|
||||
* @param postId 动态ID
|
||||
* @param content 评论内容
|
||||
*/
|
||||
suspend fun createComment(postId: Int, content: String)
|
||||
|
||||
/**
|
||||
* 点赞评论
|
||||
* @param commentId 评论ID
|
||||
*/
|
||||
suspend fun likeComment(commentId: Int)
|
||||
|
||||
/**
|
||||
* 取消点赞评论
|
||||
* @param commentId 评论ID
|
||||
*/
|
||||
suspend fun dislikeComment(commentId: Int)
|
||||
|
||||
/**
|
||||
* 更新评论已读状态
|
||||
* @param commentId 评论ID
|
||||
*/
|
||||
suspend fun updateReadStatus(commentId: Int)
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论
|
||||
*/
|
||||
data class Comment(
|
||||
// 评论ID
|
||||
@SerializedName("id")
|
||||
val id: Int,
|
||||
// 评论内容
|
||||
@SerializedName("content")
|
||||
val content: String,
|
||||
// 评论用户
|
||||
@SerializedName("user")
|
||||
val user: User,
|
||||
// 点赞数
|
||||
@SerializedName("likeCount")
|
||||
val likeCount: Int,
|
||||
// 是否点赞
|
||||
@SerializedName("isLiked")
|
||||
val isLiked: Boolean,
|
||||
// 创建时间
|
||||
@SerializedName("createdAt")
|
||||
val createdAt: String,
|
||||
// 动态ID
|
||||
@SerializedName("postId")
|
||||
val postId: Int,
|
||||
// 动态
|
||||
@SerializedName("post")
|
||||
val post: NoticePost?,
|
||||
// 是否未读
|
||||
@SerializedName("isUnread")
|
||||
val isUnread: Boolean
|
||||
) {
|
||||
/**
|
||||
* 转换为Entity
|
||||
*/
|
||||
fun toCommentEntity(): CommentEntity {
|
||||
return CommentEntity(
|
||||
id = id,
|
||||
@@ -73,52 +112,6 @@ data class Comment(
|
||||
}
|
||||
}
|
||||
|
||||
data class CommentEntity(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val comment: String,
|
||||
val date: Date,
|
||||
val likes: Int,
|
||||
val replies: List<CommentEntity>,
|
||||
val postId: Int = 0,
|
||||
val avatar: String,
|
||||
val author: Long,
|
||||
var liked: Boolean,
|
||||
var unread: Boolean = false,
|
||||
var post: NoticePost?
|
||||
)
|
||||
|
||||
class CommentPagingSource(
|
||||
private val remoteDataSource: CommentRemoteDataSource,
|
||||
private val postId: Int? = null,
|
||||
private val postUser: Int? = null,
|
||||
private val selfNotice: Boolean? = null
|
||||
) : PagingSource<Int, CommentEntity>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CommentEntity> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val comments = remoteDataSource.getComments(
|
||||
pageNumber = currentPage,
|
||||
postId = postId,
|
||||
postUser = postUser,
|
||||
selfNotice = selfNotice
|
||||
)
|
||||
LoadResult.Page(
|
||||
data = comments.list,
|
||||
prevKey = if (currentPage == 1) null else currentPage - 1,
|
||||
nextKey = if (comments.list.isEmpty()) null else comments.page + 1
|
||||
)
|
||||
} catch (exception: IOException) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, CommentEntity>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CommentRemoteDataSource(
|
||||
private val commentService: CommentService,
|
||||
) {
|
||||
@@ -138,7 +131,7 @@ class CommentRemoteDataSource(
|
||||
}
|
||||
|
||||
|
||||
class TestCommentServiceImpl : CommentService {
|
||||
class CommentServiceImpl : CommentService {
|
||||
override suspend fun getComments(
|
||||
pageNumber: Int,
|
||||
postId: Int?,
|
||||
@@ -182,7 +175,4 @@ class TestCommentServiceImpl : CommentService {
|
||||
return
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DataBatchSize = 5
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
/**
|
||||
* 通用接口返回数据
|
||||
*/
|
||||
data class DataContainer<T>(
|
||||
val data: T
|
||||
)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
/**
|
||||
* 错误返回
|
||||
*/
|
||||
class ServiceException(
|
||||
override val message: String,
|
||||
val code: Int = 0,
|
||||
|
||||
@@ -3,13 +3,20 @@ package com.aiosman.riderpro.data
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
|
||||
/**
|
||||
* 通用列表接口返回
|
||||
*/
|
||||
data class ListContainer<T>(
|
||||
// 总数
|
||||
@SerializedName("total")
|
||||
val total: Int,
|
||||
// 当前页
|
||||
@SerializedName("page")
|
||||
val page: Int,
|
||||
// 每页数量
|
||||
@SerializedName("pageSize")
|
||||
val pageSize: Int,
|
||||
// 列表
|
||||
@SerializedName("list")
|
||||
val list: List<T>
|
||||
)
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +1,43 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
import com.aiosman.riderpro.model.MomentEntity
|
||||
import com.aiosman.riderpro.test.TestDatabase
|
||||
import java.io.IOException
|
||||
import com.aiosman.riderpro.entity.AccountProfileEntity
|
||||
|
||||
data class UserAuth(
|
||||
val id: Int,
|
||||
val token: String? = null
|
||||
)
|
||||
|
||||
class AccountPagingSource(
|
||||
private val userService: UserService,
|
||||
private val nickname: String? = null
|
||||
) : PagingSource<Int, AccountProfileEntity>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AccountProfileEntity> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val users = userService.getUsers(
|
||||
page = currentPage,
|
||||
nickname = nickname
|
||||
)
|
||||
LoadResult.Page(
|
||||
data = users.list,
|
||||
prevKey = if (currentPage == 1) null else currentPage - 1,
|
||||
nextKey = if (users.list.isEmpty()) null else users.page + 1
|
||||
)
|
||||
} catch (exception: IOException) {
|
||||
return LoadResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, AccountProfileEntity>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户相关 Service
|
||||
*/
|
||||
interface UserService {
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @param id 用户ID
|
||||
* @return 用户信息
|
||||
*/
|
||||
suspend fun getUserProfile(id: String): AccountProfileEntity
|
||||
|
||||
/**
|
||||
* 关注用户
|
||||
* @param id 用户ID
|
||||
*/
|
||||
suspend fun followUser(id: String)
|
||||
|
||||
/**
|
||||
* 取消关注用户
|
||||
* @param id 用户ID
|
||||
*/
|
||||
suspend fun unFollowUser(id: String)
|
||||
|
||||
/**
|
||||
* 获取用户列表
|
||||
* @param pageSize 分页大小
|
||||
* @param page 页码
|
||||
* @param nickname 昵称搜索
|
||||
* @return 用户列表
|
||||
*/
|
||||
suspend fun getUsers(
|
||||
pageSize: Int = 20,
|
||||
page: Int = 1,
|
||||
@@ -51,7 +46,7 @@ interface UserService {
|
||||
|
||||
}
|
||||
|
||||
class TestUserServiceImpl : UserService {
|
||||
class UserServiceImpl : UserService {
|
||||
override suspend fun getUserProfile(id: String): AccountProfileEntity {
|
||||
val resp = ApiClient.api.getAccountProfileById(id.toInt())
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get account")
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.aiosman.riderpro.data.AccountFollow
|
||||
import com.aiosman.riderpro.data.AccountLike
|
||||
import com.aiosman.riderpro.data.AccountNotice
|
||||
import com.aiosman.riderpro.data.AccountProfile
|
||||
import com.aiosman.riderpro.data.AccountProfileEntity
|
||||
import com.aiosman.riderpro.data.Comment
|
||||
import com.aiosman.riderpro.data.DataContainer
|
||||
import com.aiosman.riderpro.data.ListContainer
|
||||
|
||||
Reference in New Issue
Block a user