新增趋势动态功能
实现了趋势动态功能,包括前端和后端支持。允许用户查看和获取趋势动态。
This commit is contained in:
@@ -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>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user