整理代码
This commit is contained in:
176
app/src/main/java/com/aiosman/riderpro/entity/Account.kt
Normal file
176
app/src/main/java/com/aiosman/riderpro/entity/Account.kt
Normal file
@@ -0,0 +1,176 @@
|
||||
package com.aiosman.riderpro.entity
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.data.AccountFollow
|
||||
import com.aiosman.riderpro.data.AccountService
|
||||
import com.aiosman.riderpro.data.Image
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
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(
|
||||
// 用户ID
|
||||
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 NoticePostEntity(
|
||||
// 动态ID
|
||||
val id: Int,
|
||||
// 动态内容
|
||||
val textContent: String,
|
||||
// 动态图片
|
||||
val images: List<Image>,
|
||||
// 时间
|
||||
val time: Date,
|
||||
)
|
||||
|
||||
/**
|
||||
* 消息关联的用户
|
||||
*/
|
||||
data class NoticeUserEntity(
|
||||
// 用户ID
|
||||
val id: Int,
|
||||
// 昵称
|
||||
val nickName: String,
|
||||
// 头像
|
||||
val avatar: String,
|
||||
)
|
||||
|
||||
/**
|
||||
* 用户点赞消息分页数据加载器
|
||||
*/
|
||||
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
|
||||
}
|
||||
}
|
||||
54
app/src/main/java/com/aiosman/riderpro/entity/Comment.kt
Normal file
54
app/src/main/java/com/aiosman/riderpro/entity/Comment.kt
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.aiosman.riderpro.entity
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.data.CommentRemoteDataSource
|
||||
import com.aiosman.riderpro.data.NoticePost
|
||||
import java.io.IOException
|
||||
import java.util.Date
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
236
app/src/main/java/com/aiosman/riderpro/entity/Moment.kt
Normal file
236
app/src/main/java/com/aiosman/riderpro/entity/Moment.kt
Normal file
@@ -0,0 +1,236 @@
|
||||
package com.aiosman.riderpro.entity
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.data.ListContainer
|
||||
import com.aiosman.riderpro.data.MomentService
|
||||
import com.aiosman.riderpro.data.ServiceException
|
||||
import com.aiosman.riderpro.data.UploadImage
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
import com.aiosman.riderpro.entity.MomentEntity
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* 动态分页加载器
|
||||
*/
|
||||
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 MomentServiceImpl() : MomentService {
|
||||
val momentBackend = MomentBackend()
|
||||
|
||||
override suspend fun getMoments(
|
||||
pageNumber: Int,
|
||||
author: Int?,
|
||||
timelineId: Int?,
|
||||
contentSearch: String?
|
||||
): ListContainer<MomentEntity> {
|
||||
return momentBackend.fetchMomentItems(pageNumber, author, timelineId, contentSearch)
|
||||
}
|
||||
|
||||
override suspend fun getMomentById(id: Int): MomentEntity {
|
||||
return momentBackend.getMomentById(id)
|
||||
}
|
||||
|
||||
|
||||
override suspend fun likeMoment(id: Int) {
|
||||
momentBackend.likeMoment(id)
|
||||
}
|
||||
|
||||
override suspend fun dislikeMoment(id: Int) {
|
||||
momentBackend.dislikeMoment(id)
|
||||
}
|
||||
|
||||
override suspend fun createMoment(
|
||||
content: String,
|
||||
authorId: Int,
|
||||
images: List<UploadImage>,
|
||||
relPostId: Int?
|
||||
): MomentEntity {
|
||||
return momentBackend.createMoment(content, authorId, images, relPostId)
|
||||
}
|
||||
|
||||
override suspend fun favoriteMoment(id: Int) {
|
||||
momentBackend.favoriteMoment(id)
|
||||
}
|
||||
|
||||
override suspend fun unfavoriteMoment(id: Int) {
|
||||
momentBackend.unfavoriteMoment(id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MomentBackend {
|
||||
val DataBatchSize = 20
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态图片
|
||||
*/
|
||||
data class MomentImageEntity(
|
||||
// 图片ID
|
||||
val id: Long,
|
||||
// 图片URL
|
||||
val url: String,
|
||||
// 缩略图URL
|
||||
val thumbnail: String,
|
||||
// 图片BlurHash
|
||||
val blurHash: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 动态
|
||||
*/
|
||||
data class MomentEntity(
|
||||
// 动态ID
|
||||
val id: Int,
|
||||
// 作者头像
|
||||
val avatar: String,
|
||||
// 作者昵称
|
||||
val nickname: String,
|
||||
// 区域
|
||||
val location: String,
|
||||
// 动态时间
|
||||
val time: Date,
|
||||
// 是否关注
|
||||
val followStatus: Boolean,
|
||||
// 动态内容
|
||||
val momentTextContent: String,
|
||||
// 动态图片
|
||||
@DrawableRes val momentPicture: Int,
|
||||
// 点赞数
|
||||
val likeCount: Int,
|
||||
// 评论数
|
||||
val commentCount: Int,
|
||||
// 分享数
|
||||
val shareCount: Int,
|
||||
// 收藏数
|
||||
val favoriteCount: Int,
|
||||
// 动态图片列表
|
||||
val images: List<MomentImageEntity> = emptyList(),
|
||||
// 作者ID
|
||||
val authorId: Int = 0,
|
||||
// 是否点赞
|
||||
var liked: Boolean = false,
|
||||
// 关联动态ID
|
||||
var relPostId: Int? = null,
|
||||
// 关联动态
|
||||
var relMoment: MomentEntity? = null,
|
||||
// 是否收藏
|
||||
var isFavorite: Boolean = false
|
||||
)
|
||||
36
app/src/main/java/com/aiosman/riderpro/entity/User.kt
Normal file
36
app/src/main/java/com/aiosman/riderpro/entity/User.kt
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.aiosman.riderpro.entity
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.riderpro.data.UserService
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* 用户信息分页加载器
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user