更新
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
import com.aiosman.riderpro.data.api.LoginUserRequestBody
|
||||
import com.aiosman.riderpro.data.api.RegisterRequestBody
|
||||
import com.aiosman.riderpro.test.TestDatabase
|
||||
|
||||
data class AccountProfile(
|
||||
data class AccountProfileEntity(
|
||||
val id: Int,
|
||||
val followerCount: Int,
|
||||
val followingCount: Int,
|
||||
@@ -10,33 +13,72 @@ data class AccountProfile(
|
||||
val avatar: String,
|
||||
val bio: String,
|
||||
val country: String,
|
||||
val isFollowing: Boolean
|
||||
)
|
||||
|
||||
//{
|
||||
// "id": 1,
|
||||
// "username": "root",
|
||||
// "nickname": "rider_4351",
|
||||
// "avatar": "/api/v1/public/default_avatar.jpeg",
|
||||
// "followingCount": 1,
|
||||
// "followerCount": 0
|
||||
//}
|
||||
data class AccountProfile (
|
||||
val id: Int,
|
||||
val username: String,
|
||||
val nickname: String,
|
||||
val avatar: String,
|
||||
val followingCount: Int,
|
||||
val followerCount: Int,
|
||||
val isFollowing: Boolean
|
||||
) {
|
||||
fun toAccountProfileEntity(): AccountProfileEntity {
|
||||
return AccountProfileEntity(
|
||||
id = id,
|
||||
followerCount = followerCount,
|
||||
followingCount = followingCount,
|
||||
nickName = nickname,
|
||||
avatar = ApiClient.BASE_SERVER + avatar,
|
||||
bio = "",
|
||||
country = "Worldwide",
|
||||
isFollowing = isFollowing
|
||||
)
|
||||
}
|
||||
}
|
||||
interface AccountService {
|
||||
suspend fun getMyAccountProfile(): AccountProfile
|
||||
suspend fun getAccountProfileById(id: Int): AccountProfile
|
||||
suspend fun getMyAccountProfile(): AccountProfileEntity
|
||||
suspend fun getAccountProfileById(id: Int): AccountProfileEntity
|
||||
suspend fun getMyAccount(): UserAuth
|
||||
suspend fun loginUserWithPassword(loginName: String, password: String): UserAuth
|
||||
suspend fun logout()
|
||||
suspend fun updateAvatar(uri: String)
|
||||
suspend fun updateProfile(nickName: String, bio: String)
|
||||
suspend fun registerUserWithPassword(loginName: String, password: String)
|
||||
}
|
||||
|
||||
class TestAccountServiceImpl : AccountService {
|
||||
override suspend fun getMyAccountProfile(): AccountProfile {
|
||||
return TestDatabase.accountData.first { it.id == 1 }
|
||||
override suspend fun getMyAccountProfile(): AccountProfileEntity {
|
||||
val resp = ApiClient.api.getMyAccount()
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get account")
|
||||
return body.data.toAccountProfileEntity()
|
||||
}
|
||||
|
||||
override suspend fun getAccountProfileById(id: Int): AccountProfile {
|
||||
return TestDatabase.accountData.first { it.id == id }
|
||||
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 {
|
||||
return UserAuth(1)
|
||||
val resp = ApiClient.api.checkToken()
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get account")
|
||||
return UserAuth(body.id)
|
||||
}
|
||||
|
||||
override suspend fun loginUserWithPassword(loginName: String, password: String): UserAuth {
|
||||
return UserAuth(1, "token")
|
||||
val resp = ApiClient.api.login(LoginUserRequestBody(loginName, password))
|
||||
val body = resp.body() ?: throw ServiceException("Failed to login")
|
||||
return UserAuth(0, body.token)
|
||||
}
|
||||
|
||||
override suspend fun logout() {
|
||||
@@ -52,6 +94,7 @@ class TestAccountServiceImpl : AccountService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updateProfile(nickName: String, bio: String) {
|
||||
TestDatabase.accountData = TestDatabase.accountData.map {
|
||||
if (it.id == 1) {
|
||||
@@ -61,4 +104,8 @@ class TestAccountServiceImpl : AccountService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun registerUserWithPassword(loginName: String, password: String) {
|
||||
ApiClient.api.register(RegisterRequestBody(loginName, password))
|
||||
}
|
||||
}
|
||||
2
app/src/main/java/com/aiosman/riderpro/data/Base.kt
Normal file
2
app/src/main/java/com/aiosman/riderpro/data/Base.kt
Normal file
@@ -0,0 +1,2 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
@@ -2,38 +2,81 @@ 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.CommentRequestBody
|
||||
import com.aiosman.riderpro.test.TestDatabase
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import java.io.IOException
|
||||
import java.util.Calendar
|
||||
import kotlin.math.min
|
||||
import kotlin.random.Random
|
||||
|
||||
interface CommentService {
|
||||
suspend fun getComments(pageNumber: Int, postId: Int? = null): ListContainer<Comment>
|
||||
suspend fun createComment(postId: Int, content: String, authorId: Int): Comment
|
||||
suspend fun getComments(pageNumber: Int, postId: Int? = null): ListContainer<CommentEntity>
|
||||
suspend fun createComment(postId: Int, content: String)
|
||||
suspend fun likeComment(commentId: Int)
|
||||
suspend fun dislikeComment(commentId: Int)
|
||||
}
|
||||
|
||||
|
||||
//{
|
||||
// "id": 2,
|
||||
// "content": "123",
|
||||
// "User": {
|
||||
// "id": 1,
|
||||
// "nickName": "",
|
||||
// "avatar": "/api/v1/public/default_avatar.jpeg"
|
||||
//},
|
||||
// "likeCount": 1,
|
||||
// "isLiked": true,
|
||||
// "createdAt": "2024-08-05 02:53:48"
|
||||
//}
|
||||
data class Comment(
|
||||
@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
|
||||
) {
|
||||
fun toCommentEntity(): CommentEntity {
|
||||
return CommentEntity(
|
||||
id = id,
|
||||
name = user.nickName,
|
||||
comment = content,
|
||||
date = createdAt,
|
||||
likes = likeCount,
|
||||
replies = emptyList(),
|
||||
postId = 0,
|
||||
avatar = ApiClient.BASE_SERVER + user.avatar,
|
||||
author = user.id,
|
||||
liked = isLiked
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class CommentEntity(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val comment: String,
|
||||
val date: String,
|
||||
val likes: Int,
|
||||
val replies: List<Comment>,
|
||||
val replies: List<CommentEntity>,
|
||||
val postId: Int = 0,
|
||||
val avatar: String,
|
||||
val author: Int,
|
||||
val author: Long,
|
||||
var liked: Boolean,
|
||||
)
|
||||
|
||||
class CommentPagingSource(
|
||||
private val remoteDataSource: CommentRemoteDataSource,
|
||||
private val postId: Int? = null
|
||||
) : PagingSource<Int, Comment>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Comment> {
|
||||
) : PagingSource<Int, CommentEntity>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CommentEntity> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val comments = remoteDataSource.getComments(
|
||||
@@ -50,7 +93,7 @@ class CommentPagingSource(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, Comment>): Int? {
|
||||
override fun getRefreshKey(state: PagingState<Int, CommentEntity>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
|
||||
@@ -59,87 +102,37 @@ class CommentPagingSource(
|
||||
class CommentRemoteDataSource(
|
||||
private val commentService: CommentService,
|
||||
) {
|
||||
suspend fun getComments(pageNumber: Int, postId: Int?): ListContainer<Comment> {
|
||||
suspend fun getComments(pageNumber: Int, postId: Int?): ListContainer<CommentEntity> {
|
||||
return commentService.getComments(pageNumber, postId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestCommentServiceImpl : CommentService {
|
||||
override suspend fun getComments(pageNumber: Int, postId: Int?): ListContainer<Comment> {
|
||||
var rawList = TestDatabase.comment
|
||||
if (postId != null) {
|
||||
rawList = rawList.filter { it.postId == postId }
|
||||
}
|
||||
val from = (pageNumber - 1) * DataBatchSize
|
||||
val to = (pageNumber) * DataBatchSize
|
||||
rawList = rawList.sortedBy { -it.id }
|
||||
if (from >= rawList.size) {
|
||||
return ListContainer(
|
||||
total = rawList.size,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = emptyList()
|
||||
)
|
||||
}
|
||||
rawList = rawList.sortedBy { -it.id }
|
||||
rawList.forEach {
|
||||
val myLikeIdList = TestDatabase.likeCommentList.filter { it.second == 1 }.map { it.first }
|
||||
if (myLikeIdList.contains(it.id)) {
|
||||
it.liked = true
|
||||
}
|
||||
}
|
||||
val currentSublist = rawList.subList(from, min(to, rawList.size))
|
||||
override suspend fun getComments(pageNumber: Int, postId: Int?): ListContainer<CommentEntity> {
|
||||
val resp = ApiClient.api.getComments(pageNumber, postId)
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get comments")
|
||||
return ListContainer(
|
||||
total = rawList.size,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = currentSublist
|
||||
list = body.list.map { it.toCommentEntity() },
|
||||
page = body.page,
|
||||
total = body.total,
|
||||
pageSize = body.pageSize
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun createComment(postId: Int, content: String, authorId: Int): Comment {
|
||||
var author = TestDatabase.accountData.find { it.id == authorId }
|
||||
if (author == null) {
|
||||
author = TestDatabase.accountData.random()
|
||||
}
|
||||
TestDatabase.commentIdCounter += 1
|
||||
val newComment = Comment(
|
||||
name = author.nickName,
|
||||
comment = content,
|
||||
date = Calendar.getInstance().time.toString(),
|
||||
likes = 0,
|
||||
replies = emptyList(),
|
||||
postId = postId,
|
||||
avatar = author.avatar,
|
||||
author = author.id,
|
||||
id = TestDatabase.commentIdCounter,
|
||||
liked = false
|
||||
)
|
||||
TestDatabase.comment += newComment
|
||||
return newComment
|
||||
override suspend fun createComment(postId: Int, content: String) {
|
||||
val resp = ApiClient.api.createComment(postId, CommentRequestBody(content))
|
||||
return
|
||||
}
|
||||
|
||||
override suspend fun likeComment(commentId: Int) {
|
||||
TestDatabase.comment = TestDatabase.comment.map {
|
||||
if (it.id == commentId) {
|
||||
it.copy(likes = it.likes + 1)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
TestDatabase.likeCommentList += Pair(commentId, 1)
|
||||
val resp = ApiClient.api.likeComment(commentId)
|
||||
return
|
||||
}
|
||||
|
||||
override suspend fun dislikeComment(commentId: Int) {
|
||||
TestDatabase.comment = TestDatabase.comment.map {
|
||||
if (it.id == commentId) {
|
||||
it.copy(likes = it.likes - 1)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
TestDatabase.likeCommentList = TestDatabase.likeCommentList.filter { it.first != commentId }
|
||||
val resp = ApiClient.api.dislikeComment(commentId)
|
||||
return
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
data class DataContainer<T>(
|
||||
val data: T
|
||||
)
|
||||
9
app/src/main/java/com/aiosman/riderpro/data/Exception.kt
Normal file
9
app/src/main/java/com/aiosman/riderpro/data/Exception.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
class ServiceException(
|
||||
override val message: String,
|
||||
val code: Int = 0,
|
||||
val data: Any? = null
|
||||
) : Exception(
|
||||
message
|
||||
)
|
||||
@@ -1,9 +1,15 @@
|
||||
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>
|
||||
)
|
||||
@@ -2,28 +2,109 @@ 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.model.MomentItem
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
import com.aiosman.riderpro.model.MomentEntity
|
||||
import com.aiosman.riderpro.test.TestDatabase
|
||||
import java.io.IOException
|
||||
import kotlin.math.min
|
||||
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")
|
||||
val id: Long,
|
||||
@SerializedName("textContent")
|
||||
val textContent: String,
|
||||
@SerializedName("images")
|
||||
val images: List<Image>,
|
||||
@SerializedName("user")
|
||||
val user: User,
|
||||
@SerializedName("likeCount")
|
||||
val likeCount: Long,
|
||||
@SerializedName("isLiked")
|
||||
val isLiked: Boolean,
|
||||
@SerializedName("favoriteCount")
|
||||
val favoriteCount: Long,
|
||||
@SerializedName("isFavorite")
|
||||
val isFavorite: Boolean,
|
||||
@SerializedName("shareCount")
|
||||
val isCommented: Boolean,
|
||||
@SerializedName("commentCount")
|
||||
val commentCount: Long,
|
||||
@SerializedName("time")
|
||||
val time: String
|
||||
) {
|
||||
fun toMomentItem(): MomentEntity {
|
||||
return MomentEntity(
|
||||
id = id.toInt(),
|
||||
avatar = ApiClient.BASE_SERVER + user.avatar,
|
||||
nickname = user.nickName,
|
||||
location = "Worldwide",
|
||||
time = time,
|
||||
followStatus = false,
|
||||
momentTextContent = textContent,
|
||||
momentPicture = R.drawable.default_moment_img,
|
||||
likeCount = likeCount.toInt(),
|
||||
commentCount = commentCount.toInt(),
|
||||
shareCount = 0,
|
||||
favoriteCount = favoriteCount.toInt(),
|
||||
images = images.map { ApiClient.BASE_SERVER + it.url + "?token=${AppStore.token}" },
|
||||
authorId = user.id.toInt(),
|
||||
liked = isLiked,
|
||||
isFavorite = isFavorite
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Image(
|
||||
@SerializedName("id")
|
||||
val id: Long,
|
||||
@SerializedName("url")
|
||||
val url: String,
|
||||
@SerializedName("thumbnail")
|
||||
val thumbnail: String
|
||||
)
|
||||
|
||||
data class User(
|
||||
@SerializedName("id")
|
||||
val id: Long,
|
||||
@SerializedName("nickName")
|
||||
val nickName: String,
|
||||
@SerializedName("avatar")
|
||||
val avatar: String
|
||||
)
|
||||
data class UploadImage(
|
||||
val file: File,
|
||||
val filename: String,
|
||||
val url: String,
|
||||
val ext: String
|
||||
)
|
||||
interface MomentService {
|
||||
suspend fun getMomentById(id: Int): MomentItem
|
||||
suspend fun getMomentById(id: Int): MomentEntity
|
||||
suspend fun likeMoment(id: Int)
|
||||
suspend fun dislikeMoment(id: Int)
|
||||
suspend fun getMoments(
|
||||
pageNumber: Int,
|
||||
author: Int? = null,
|
||||
timelineId: Int? = null
|
||||
): ListContainer<MomentItem>
|
||||
): ListContainer<MomentEntity>
|
||||
|
||||
suspend fun createMoment(
|
||||
content: String,
|
||||
authorId: Int,
|
||||
imageUriList: List<String>,
|
||||
images: List<UploadImage>,
|
||||
relPostId: Int? = null
|
||||
): MomentItem
|
||||
): MomentEntity
|
||||
suspend fun favoriteMoment(id: Int)
|
||||
suspend fun unfavoriteMoment(id: Int)
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +112,8 @@ class MomentPagingSource(
|
||||
private val remoteDataSource: MomentRemoteDataSource,
|
||||
private val author: Int? = null,
|
||||
private val timelineId: Int? = null
|
||||
) : PagingSource<Int, MomentItem>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentItem> {
|
||||
) : PagingSource<Int, MomentEntity>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentEntity> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val moments = remoteDataSource.getMoments(
|
||||
@@ -51,7 +132,7 @@ class MomentPagingSource(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, MomentItem>): Int? {
|
||||
override fun getRefreshKey(state: PagingState<Int, MomentEntity>): Int? {
|
||||
return state.anchorPosition
|
||||
}
|
||||
|
||||
@@ -64,7 +145,7 @@ class MomentRemoteDataSource(
|
||||
pageNumber: Int,
|
||||
author: Int?,
|
||||
timelineId: Int?
|
||||
): ListContainer<MomentItem> {
|
||||
): ListContainer<MomentEntity> {
|
||||
return momentService.getMoments(pageNumber, author, timelineId)
|
||||
}
|
||||
}
|
||||
@@ -77,11 +158,11 @@ class TestMomentServiceImpl() : MomentService {
|
||||
pageNumber: Int,
|
||||
author: Int?,
|
||||
timelineId: Int?
|
||||
): ListContainer<MomentItem> {
|
||||
): ListContainer<MomentEntity> {
|
||||
return testMomentBackend.fetchMomentItems(pageNumber, author, timelineId)
|
||||
}
|
||||
|
||||
override suspend fun getMomentById(id: Int): MomentItem {
|
||||
override suspend fun getMomentById(id: Int): MomentEntity {
|
||||
return testMomentBackend.getMomentById(id)
|
||||
}
|
||||
|
||||
@@ -97,10 +178,18 @@ class TestMomentServiceImpl() : MomentService {
|
||||
override suspend fun createMoment(
|
||||
content: String,
|
||||
authorId: Int,
|
||||
imageUriList: List<String>,
|
||||
images: List<UploadImage>,
|
||||
relPostId: Int?
|
||||
): MomentItem {
|
||||
return testMomentBackend.createMoment(content, authorId, imageUriList, relPostId)
|
||||
): 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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -113,110 +202,63 @@ class TestMomentBackend(
|
||||
pageNumber: Int,
|
||||
author: Int? = null,
|
||||
timelineId: Int?
|
||||
): ListContainer<MomentItem> {
|
||||
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
|
||||
}
|
||||
if (it.relPostId != null) {
|
||||
it.relMoment = rawList.first { it1 -> it1.id == it.relPostId }
|
||||
}
|
||||
}
|
||||
|
||||
// delay
|
||||
kotlinx.coroutines.delay(loadDelay)
|
||||
): ListContainer<MomentEntity> {
|
||||
val resp = ApiClient.api.getPosts(
|
||||
pageSize = DataBatchSize,
|
||||
page = pageNumber,
|
||||
timelineId = timelineId,
|
||||
authorId = author
|
||||
)
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get moments")
|
||||
return ListContainer(
|
||||
total = rawList.size,
|
||||
total = body.total,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = currentSublist
|
||||
list = body.list.map { it.toMomentItem() }
|
||||
)
|
||||
}
|
||||
|
||||
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 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) {
|
||||
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)
|
||||
ApiClient.api.likePost(id)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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<String>,
|
||||
imageUriList: List<UploadImage>,
|
||||
relPostId: Int?
|
||||
): MomentItem {
|
||||
TestDatabase.momentIdCounter += 1
|
||||
val person = TestDatabase.accountData.first {
|
||||
it.id == authorId
|
||||
): MomentEntity {
|
||||
val textContent = content.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||
val imageList = imageUriList.map { item ->
|
||||
val file = item.file
|
||||
createMultipartBody(file, "image")
|
||||
}
|
||||
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,
|
||||
relPostId = relPostId
|
||||
)
|
||||
TestDatabase.momentData += newMoment
|
||||
return newMoment
|
||||
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,5 +1,6 @@
|
||||
package com.aiosman.riderpro.data
|
||||
|
||||
import com.aiosman.riderpro.data.api.ApiClient
|
||||
import com.aiosman.riderpro.test.TestDatabase
|
||||
|
||||
data class UserAuth(
|
||||
@@ -8,17 +9,26 @@ data class UserAuth(
|
||||
)
|
||||
|
||||
interface UserService {
|
||||
suspend fun getUserProfile(id: String): AccountProfile
|
||||
suspend fun getUserProfile(id: String): AccountProfileEntity
|
||||
suspend fun followUser(id: String)
|
||||
suspend fun unFollowUser(id: String)
|
||||
|
||||
}
|
||||
|
||||
class TestUserServiceImpl : UserService {
|
||||
override suspend fun getUserProfile(id: String): AccountProfile {
|
||||
TestDatabase.accountData.forEach {
|
||||
if (it.id == id.toInt()) {
|
||||
return it
|
||||
}
|
||||
}
|
||||
return AccountProfile(0, 0, 0, "", "", "", "")
|
||||
override suspend fun getUserProfile(id: String): AccountProfileEntity {
|
||||
val resp = ApiClient.api.getAccountProfileById(id.toInt())
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get account")
|
||||
return body.data.toAccountProfileEntity()
|
||||
}
|
||||
|
||||
override suspend fun followUser(id: String) {
|
||||
val resp = ApiClient.api.followUser(id.toInt())
|
||||
return
|
||||
}
|
||||
|
||||
override suspend fun unFollowUser(id: String) {
|
||||
val resp = ApiClient.api.unfollowUser(id.toInt())
|
||||
return
|
||||
}
|
||||
}
|
||||
39
app/src/main/java/com/aiosman/riderpro/data/api/ApiClient.kt
Normal file
39
app/src/main/java/com/aiosman/riderpro/data/api/ApiClient.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.aiosman.riderpro.data.api
|
||||
|
||||
import com.aiosman.riderpro.AppStore
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
class AuthInterceptor() : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val requestBuilder = chain.request().newBuilder()
|
||||
requestBuilder.addHeader("Authorization", "Bearer ${AppStore.token}")
|
||||
return chain.proceed(requestBuilder.build())
|
||||
}
|
||||
}
|
||||
|
||||
object ApiClient {
|
||||
const val BASE_SERVER = "http://192.168.31.57:8088"
|
||||
const val BASE_API_URL = "${BASE_SERVER}/api/v1"
|
||||
const val RETROFIT_URL = "${BASE_API_URL}/"
|
||||
private val okHttpClient: OkHttpClient by lazy {
|
||||
OkHttpClient.Builder()
|
||||
.addInterceptor(AuthInterceptor())
|
||||
.build()
|
||||
}
|
||||
private val retrofit: Retrofit by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(RETROFIT_URL)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
}
|
||||
|
||||
val api: RiderProAPI by lazy {
|
||||
retrofit.create(RiderProAPI::class.java)
|
||||
}
|
||||
|
||||
}
|
||||
146
app/src/main/java/com/aiosman/riderpro/data/api/RiderProAPI.kt
Normal file
146
app/src/main/java/com/aiosman/riderpro/data/api/RiderProAPI.kt
Normal file
@@ -0,0 +1,146 @@
|
||||
package com.aiosman.riderpro.data.api
|
||||
|
||||
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
|
||||
import com.aiosman.riderpro.data.Moment
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Multipart
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Part
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
data class RegisterRequestBody(
|
||||
@SerializedName("username")
|
||||
val username: String,
|
||||
@SerializedName("password")
|
||||
val password: String
|
||||
)
|
||||
|
||||
data class LoginUserRequestBody(
|
||||
@SerializedName("username")
|
||||
val username: String,
|
||||
@SerializedName("password")
|
||||
val password: String
|
||||
)
|
||||
|
||||
data class AuthResult(
|
||||
@SerializedName("code")
|
||||
val code: Int,
|
||||
@SerializedName("expire")
|
||||
val expire: String,
|
||||
@SerializedName("token")
|
||||
val token: String
|
||||
)
|
||||
|
||||
data class ValidateTokenResult(
|
||||
@SerializedName("id")
|
||||
val id: Int,
|
||||
)
|
||||
|
||||
data class CommentRequestBody(
|
||||
@SerializedName("content")
|
||||
val content: String
|
||||
)
|
||||
|
||||
interface RiderProAPI {
|
||||
@POST("register")
|
||||
suspend fun register(@Body body: RegisterRequestBody): Response<Unit>
|
||||
|
||||
@POST("login")
|
||||
suspend fun login(@Body body: LoginUserRequestBody): Response<AuthResult>
|
||||
|
||||
@GET("auth/token")
|
||||
suspend fun checkToken(): Response<ValidateTokenResult>
|
||||
|
||||
@GET("posts")
|
||||
suspend fun getPosts(
|
||||
@Query("page") page: Int = 1,
|
||||
@Query("pageSize") pageSize: Int = 20,
|
||||
@Query("timelineId") timelineId: Int? = null,
|
||||
@Query("authorId") authorId: Int? = null,
|
||||
): Response<ListContainer<Moment>>
|
||||
|
||||
@Multipart
|
||||
@POST("posts")
|
||||
suspend fun createPost(
|
||||
@Part image: List<MultipartBody.Part>,
|
||||
@Part("textContent") textContent: RequestBody,
|
||||
): Response<DataContainer<Moment>>
|
||||
|
||||
@GET("post/{id}")
|
||||
suspend fun getPost(
|
||||
@Path("id") id: Int
|
||||
): Response<DataContainer<Moment>>
|
||||
|
||||
@POST("post/{id}/like")
|
||||
suspend fun likePost(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
@POST("post/{id}/dislike")
|
||||
suspend fun dislikePost(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
@POST("post/{id}/favorite")
|
||||
suspend fun favoritePost(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
@POST("post/{id}/unfavorite")
|
||||
suspend fun unfavoritePost(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
@POST("post/{id}/comment")
|
||||
suspend fun createComment(
|
||||
@Path("id") id: Int,
|
||||
@Body body: CommentRequestBody
|
||||
): Response<Unit>
|
||||
|
||||
@POST("comment/{id}/like")
|
||||
suspend fun likeComment(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
@POST("comment/{id}/dislike")
|
||||
suspend fun dislikeComment(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
|
||||
@GET("comments")
|
||||
suspend fun getComments(
|
||||
@Query("page") page: Int = 1,
|
||||
@Query("postId") postId: Int? = null,
|
||||
@Query("pageSize") pageSize: Int = 20,
|
||||
): Response<ListContainer<Comment>>
|
||||
|
||||
@GET("account/my")
|
||||
suspend fun getMyAccount(): Response<DataContainer<AccountProfile>>
|
||||
|
||||
@GET("profile/{id}")
|
||||
suspend fun getAccountProfileById(
|
||||
@Path("id") id: Int
|
||||
): Response<DataContainer<AccountProfile>>
|
||||
|
||||
@POST("user/{id}/follow")
|
||||
suspend fun followUser(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
@POST("user/{id}/unfollow")
|
||||
suspend fun unfollowUser(
|
||||
@Path("id") id: Int
|
||||
): Response<Unit>
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user