Files
rider-pro-android-app/app/src/main/java/com/aiosman/riderpro/data/MomentService.kt

283 lines
8.2 KiB
Kotlin
Raw Normal View History

2024-07-29 00:01:09 +08:00
package com.aiosman.riderpro.data
2024-07-23 15:25:00 +08:00
import androidx.paging.PagingSource
import androidx.paging.PagingState
2024-08-11 17:15:17 +08:00
import com.aiosman.riderpro.AppStore
2024-07-30 15:49:59 +08:00
import com.aiosman.riderpro.R
2024-08-11 17:15:17 +08:00
import com.aiosman.riderpro.data.api.ApiClient
import com.aiosman.riderpro.model.MomentEntity
2024-08-17 17:40:21 +08:00
import com.aiosman.riderpro.model.MomentImageEntity
2024-07-29 00:01:09 +08:00
import com.aiosman.riderpro.test.TestDatabase
2024-08-11 17:15:17 +08:00
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
2024-07-23 15:25:00 +08:00
import java.io.IOException
2024-08-11 17:15:17 +08:00
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 {
2024-08-11 21:17:02 +08:00
val avatar = ApiClient.BASE_SERVER + user.avatar + "?token=${AppStore.token}"
2024-08-11 17:15:17 +08:00
return MomentEntity(
id = id.toInt(),
2024-08-11 21:17:02 +08:00
avatar = ApiClient.BASE_SERVER + user.avatar + "?token=${AppStore.token}",
2024-08-11 17:15:17 +08:00
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(),
2024-08-17 17:40:21 +08:00
images = images.map {
MomentImageEntity(
url = ApiClient.BASE_SERVER + it.url + "?token=${AppStore.token}",
thumbnail = ApiClient.BASE_SERVER + it.thumbnail + "?token=${AppStore.token}",
id = it.id
)
},
2024-08-11 17:15:17 +08:00
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
)
2024-07-29 16:50:07 +08:00
2024-08-11 17:15:17 +08:00
data class User(
@SerializedName("id")
val id: Long,
@SerializedName("nickName")
val nickName: String,
@SerializedName("avatar")
val avatar: String
)
2024-08-17 17:40:21 +08:00
2024-08-11 17:15:17 +08:00
data class UploadImage(
val file: File,
val filename: String,
val url: String,
val ext: String
)
2024-08-17 17:40:21 +08:00
2024-07-29 16:50:07 +08:00
interface MomentService {
2024-08-11 17:15:17 +08:00
suspend fun getMomentById(id: Int): MomentEntity
2024-07-29 16:50:07 +08:00
suspend fun likeMoment(id: Int)
2024-07-30 14:28:13 +08:00
suspend fun dislikeMoment(id: Int)
2024-07-29 16:50:07 +08:00
suspend fun getMoments(
pageNumber: Int,
author: Int? = null,
2024-08-17 17:40:21 +08:00
timelineId: Int? = null,
contentSearch: String? = null
2024-08-11 17:15:17 +08:00
): ListContainer<MomentEntity>
2024-07-30 15:49:59 +08:00
suspend fun createMoment(
content: String,
authorId: Int,
2024-08-11 17:15:17 +08:00
images: List<UploadImage>,
2024-07-31 14:50:55 +08:00
relPostId: Int? = null
2024-08-11 17:15:17 +08:00
): MomentEntity
2024-08-17 17:40:21 +08:00
2024-08-11 17:15:17 +08:00
suspend fun favoriteMoment(id: Int)
suspend fun unfavoriteMoment(id: Int)
2024-07-29 16:50:07 +08:00
}
2024-07-23 15:25:00 +08:00
class MomentPagingSource(
private val remoteDataSource: MomentRemoteDataSource,
2024-07-29 16:50:07 +08:00
private val author: Int? = null,
2024-08-17 17:40:21 +08:00
private val timelineId: Int? = null,
private val contentSearch: String? = null
2024-08-11 17:15:17 +08:00
) : PagingSource<Int, MomentEntity>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentEntity> {
2024-07-23 15:25:00 +08:00
return try {
val currentPage = params.key ?: 1
val moments = remoteDataSource.getMoments(
2024-07-29 16:50:07 +08:00
pageNumber = currentPage,
author = author,
2024-08-17 17:40:21 +08:00
timelineId = timelineId,
contentSearch = contentSearch
2024-07-23 15:25:00 +08:00
)
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)
}
}
2024-08-11 17:15:17 +08:00
override fun getRefreshKey(state: PagingState<Int, MomentEntity>): Int? {
2024-07-23 15:25:00 +08:00
return state.anchorPosition
}
}
class MomentRemoteDataSource(
private val momentService: MomentService,
) {
2024-07-29 16:50:07 +08:00
suspend fun getMoments(
pageNumber: Int,
author: Int?,
2024-08-17 17:40:21 +08:00
timelineId: Int?,
contentSearch: String?
2024-08-11 17:15:17 +08:00
): ListContainer<MomentEntity> {
2024-08-17 17:40:21 +08:00
return momentService.getMoments(pageNumber, author, timelineId, contentSearch)
2024-07-23 15:25:00 +08:00
}
}
class TestMomentServiceImpl() : MomentService {
2024-07-29 16:50:07 +08:00
val testMomentBackend = TestMomentBackend()
override suspend fun getMoments(
pageNumber: Int,
author: Int?,
2024-08-17 17:40:21 +08:00
timelineId: Int?,
contentSearch: String?
2024-08-11 17:15:17 +08:00
): ListContainer<MomentEntity> {
2024-08-17 17:40:21 +08:00
return testMomentBackend.fetchMomentItems(pageNumber, author, timelineId, contentSearch)
2024-07-23 15:25:00 +08:00
}
2024-07-28 15:07:08 +08:00
2024-08-11 17:15:17 +08:00
override suspend fun getMomentById(id: Int): MomentEntity {
2024-07-29 16:50:07 +08:00
return testMomentBackend.getMomentById(id)
2024-07-28 15:07:08 +08:00
}
2024-07-29 00:01:09 +08:00
2024-07-29 16:50:07 +08:00
2024-07-29 00:01:09 +08:00
override suspend fun likeMoment(id: Int) {
2024-07-29 16:50:07 +08:00
testMomentBackend.likeMoment(id)
2024-07-29 00:01:09 +08:00
}
2024-07-30 14:28:13 +08:00
override suspend fun dislikeMoment(id: Int) {
testMomentBackend.dislikeMoment(id)
}
2024-07-30 15:49:59 +08:00
override suspend fun createMoment(
content: String,
authorId: Int,
2024-08-11 17:15:17 +08:00
images: List<UploadImage>,
2024-07-31 14:50:55 +08:00
relPostId: Int?
2024-08-11 17:15:17 +08:00
): 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)
2024-07-30 15:49:59 +08:00
}
2024-07-23 15:25:00 +08:00
}
class TestMomentBackend(
private val loadDelay: Long = 500,
) {
val DataBatchSize = 5
2024-07-29 16:50:07 +08:00
suspend fun fetchMomentItems(
pageNumber: Int,
author: Int? = null,
2024-08-17 17:40:21 +08:00
timelineId: Int?,
contentSearch: String?
2024-08-11 17:15:17 +08:00
): ListContainer<MomentEntity> {
val resp = ApiClient.api.getPosts(
pageSize = DataBatchSize,
page = pageNumber,
timelineId = timelineId,
2024-08-17 17:40:21 +08:00
authorId = author,
contentSearch = contentSearch
2024-08-11 17:15:17 +08:00
)
val body = resp.body() ?: throw ServiceException("Failed to get moments")
2024-07-23 15:25:00 +08:00
return ListContainer(
2024-08-11 17:15:17 +08:00
total = body.total,
2024-07-23 15:25:00 +08:00
page = pageNumber,
pageSize = DataBatchSize,
2024-08-11 17:15:17 +08:00
list = body.list.map { it.toMomentItem() }
2024-07-23 15:25:00 +08:00
)
}
2024-08-11 17:15:17 +08:00
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()
2024-07-29 16:50:07 +08:00
}
suspend fun likeMoment(id: Int) {
2024-08-11 17:15:17 +08:00
ApiClient.api.likePost(id)
2024-07-30 14:28:13 +08:00
}
2024-07-30 15:49:59 +08:00
2024-07-30 14:28:13 +08:00
suspend fun dislikeMoment(id: Int) {
2024-08-11 17:15:17 +08:00
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)
2024-07-29 16:50:07 +08:00
}
2024-07-30 15:49:59 +08:00
suspend fun createMoment(
content: String,
authorId: Int,
2024-08-11 17:15:17 +08:00
imageUriList: List<UploadImage>,
2024-07-31 14:50:55 +08:00
relPostId: Int?
2024-08-11 17:15:17 +08:00
): MomentEntity {
val textContent = content.toRequestBody("text/plain".toMediaTypeOrNull())
val imageList = imageUriList.map { item ->
val file = item.file
createMultipartBody(file, "image")
2024-07-30 15:49:59 +08:00
}
2024-08-11 17:15:17 +08:00
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)
}
2024-08-17 17:40:21 +08:00
2024-08-11 17:15:17 +08:00
suspend fun unfavoriteMoment(id: Int) {
ApiClient.api.unfavoritePost(id)
2024-07-30 15:49:59 +08:00
}
2024-07-23 15:25:00 +08:00
}