新增趋势动态功能

实现了趋势动态功能,包括前端和后端支持。允许用户查看和获取趋势动态。
This commit is contained in:
2024-09-01 19:39:46 +08:00
parent f2a37d21ca
commit f8becdb7de
5 changed files with 63 additions and 12 deletions

View File

@@ -112,13 +112,15 @@ interface MomentService {
* @param author 作者ID,过滤条件 * @param author 作者ID,过滤条件
* @param timelineId 用户时间线ID,指定用户 ID 的时间线 * @param timelineId 用户时间线ID,指定用户 ID 的时间线
* @param contentSearch 内容搜索,过滤条件 * @param contentSearch 内容搜索,过滤条件
* @param trend 是否趋势动态
* @return 动态列表 * @return 动态列表
*/ */
suspend fun getMoments( suspend fun getMoments(
pageNumber: Int, pageNumber: Int,
author: Int? = null, author: Int? = null,
timelineId: Int? = null, timelineId: Int? = null,
contentSearch: String? = null contentSearch: String? = null,
trend: Boolean? = false
): ListContainer<MomentEntity> ): ListContainer<MomentEntity>
/** /**

View File

@@ -102,6 +102,7 @@ interface RiderProAPI {
@Query("authorId") authorId: Int? = null, @Query("authorId") authorId: Int? = null,
@Query("contentSearch") contentSearch: String? = null, @Query("contentSearch") contentSearch: String? = null,
@Query("postUser") postUser: Int? = null, @Query("postUser") postUser: Int? = null,
@Query("trend") trend: String? = null,
): Response<ListContainer<Moment>> ): Response<ListContainer<Moment>>
@Multipart @Multipart

View File

@@ -24,7 +24,8 @@ class MomentPagingSource(
private val remoteDataSource: MomentRemoteDataSource, private val remoteDataSource: MomentRemoteDataSource,
private val author: Int? = null, private val author: Int? = null,
private val timelineId: Int? = null, private val timelineId: Int? = null,
private val contentSearch: String? = null private val contentSearch: String? = null,
private val trend: Boolean? = false
) : PagingSource<Int, MomentEntity>() { ) : PagingSource<Int, MomentEntity>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentEntity> { override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentEntity> {
return try { return try {
@@ -33,7 +34,8 @@ class MomentPagingSource(
pageNumber = currentPage, pageNumber = currentPage,
author = author, author = author,
timelineId = timelineId, timelineId = timelineId,
contentSearch = contentSearch contentSearch = contentSearch,
trend = trend
) )
LoadResult.Page( LoadResult.Page(
@@ -59,9 +61,16 @@ class MomentRemoteDataSource(
pageNumber: Int, pageNumber: Int,
author: Int?, author: Int?,
timelineId: Int?, timelineId: Int?,
contentSearch: String? contentSearch: String?,
trend: Boolean?
): ListContainer<MomentEntity> { ): ListContainer<MomentEntity> {
return momentService.getMoments(pageNumber, author, timelineId, contentSearch) return momentService.getMoments(
pageNumber = pageNumber,
author = author,
timelineId = timelineId,
contentSearch = contentSearch,
trend = trend
)
} }
} }
@@ -72,9 +81,16 @@ class MomentServiceImpl() : MomentService {
pageNumber: Int, pageNumber: Int,
author: Int?, author: Int?,
timelineId: Int?, timelineId: Int?,
contentSearch: String? contentSearch: String?,
trend: Boolean?
): ListContainer<MomentEntity> { ): ListContainer<MomentEntity> {
return momentBackend.fetchMomentItems(pageNumber, author, timelineId, contentSearch) return momentBackend.fetchMomentItems(
pageNumber = pageNumber,
author = author,
timelineId = timelineId,
contentSearch = contentSearch,
trend = trend
)
} }
override suspend fun getMomentById(id: Int): MomentEntity { override suspend fun getMomentById(id: Int): MomentEntity {
@@ -115,14 +131,16 @@ class MomentBackend {
pageNumber: Int, pageNumber: Int,
author: Int? = null, author: Int? = null,
timelineId: Int?, timelineId: Int?,
contentSearch: String? contentSearch: String?,
trend: Boolean?
): ListContainer<MomentEntity> { ): ListContainer<MomentEntity> {
val resp = ApiClient.api.getPosts( val resp = ApiClient.api.getPosts(
pageSize = DataBatchSize, pageSize = DataBatchSize,
page = pageNumber, page = pageNumber,
timelineId = timelineId, timelineId = timelineId,
authorId = author, authorId = author,
contentSearch = contentSearch contentSearch = contentSearch,
trend = if (trend == true) "true" else ""
) )
val body = resp.body() ?: throw ServiceException("Failed to get moments") val body = resp.body() ?: throw ServiceException("Failed to get moments")
return ListContainer( return ListContainer(

View File

@@ -24,13 +24,21 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@@ -52,7 +60,7 @@ import com.aiosman.riderpro.ui.post.PostViewModel
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class)
@Preview @Preview
@Composable @Composable
fun DiscoverScreen() { fun DiscoverScreen() {
@@ -66,11 +74,16 @@ fun DiscoverScreen() {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true) systemUiController.setStatusBarColor(Color.Transparent, darkIcons = true)
} }
var refreshing by remember { mutableStateOf(false) }
val state = rememberPullRefreshState(refreshing, onRefresh = {
model.refreshPager()
})
Column( Column(
modifier = Modifier modifier = Modifier
.background(Color.White) .background(Color.White)
.fillMaxSize() .fillMaxSize()
.pullRefresh(state)
.padding(bottom = navigationBarPaddings) .padding(bottom = navigationBarPaddings)
) { ) {
Spacer(modifier = Modifier.height(statusBarPaddingValues.calculateTopPadding())) Spacer(modifier = Modifier.height(statusBarPaddingValues.calculateTopPadding()))
@@ -89,9 +102,8 @@ fun DiscoverScreen() {
.weight(1f) .weight(1f)
) { ) {
DiscoverView() DiscoverView()
PullRefreshIndicator(refreshing, state, Modifier.align(Alignment.TopCenter))
} }
} }
} }

View File

@@ -11,6 +11,7 @@ import com.aiosman.riderpro.entity.MomentEntity
import com.aiosman.riderpro.entity.MomentPagingSource import com.aiosman.riderpro.entity.MomentPagingSource
import com.aiosman.riderpro.entity.MomentRemoteDataSource import com.aiosman.riderpro.entity.MomentRemoteDataSource
import com.aiosman.riderpro.entity.MomentServiceImpl import com.aiosman.riderpro.entity.MomentServiceImpl
import com.aiosman.riderpro.ui.index.tabs.moment.MomentViewModel.accountService
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@@ -28,6 +29,23 @@ object DiscoverViewModel:ViewModel() {
pagingSourceFactory = { pagingSourceFactory = {
MomentPagingSource( MomentPagingSource(
MomentRemoteDataSource(momentService), MomentRemoteDataSource(momentService),
trend = true
)
}
).flow.cachedIn(viewModelScope).collectLatest {
_discoverMomentsFlow.value = it
}
}
}
fun refreshPager() {
viewModelScope.launch {
val profile = accountService.getMyAccountProfile()
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
MomentPagingSource(
MomentRemoteDataSource(momentService),
trend = true
) )
} }
).flow.cachedIn(viewModelScope).collectLatest { ).flow.cachedIn(viewModelScope).collectLatest {