feat: 用户页面贴子点赞
This commit is contained in:
parent
0be799a772
commit
e711e6e4df
|
|
@ -160,6 +160,36 @@ fun SubPostList.updateAgreeStatus(
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun PostInfoList.updateAgreeStatus(
|
||||||
|
hasAgree: Int,
|
||||||
|
) = if (agree != null) {
|
||||||
|
if (hasAgree != agree.hasAgree) {
|
||||||
|
if (hasAgree == 1) {
|
||||||
|
copy(
|
||||||
|
agree = agree.copy(
|
||||||
|
agreeNum = agree.agreeNum + 1,
|
||||||
|
diffAgreeNum = agree.diffAgreeNum + 1,
|
||||||
|
hasAgree = 1
|
||||||
|
),
|
||||||
|
agree_num = agree_num + 1
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
copy(
|
||||||
|
agree = agree.copy(
|
||||||
|
agreeNum = agree.agreeNum - 1,
|
||||||
|
diffAgreeNum = agree.diffAgreeNum - 1,
|
||||||
|
hasAgree = 0
|
||||||
|
),
|
||||||
|
agree_num = agree_num - 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
private val PbContent.picUrl: String
|
private val PbContent.picUrl: String
|
||||||
get() =
|
get() =
|
||||||
ImageUtil.getUrl(
|
ImageUtil.getUrl(
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,15 @@ fun UserPostPage(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onAgreeItem = {},
|
onAgreeItem = {
|
||||||
|
viewModel.send(
|
||||||
|
UserPostUiIntent.Agree(
|
||||||
|
it.thread_id,
|
||||||
|
it.post_id,
|
||||||
|
it.agree?.hasAgree ?: 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
onClickReply = {
|
onClickReply = {
|
||||||
navigator.navigate(
|
navigator.navigate(
|
||||||
ThreadPageDestination(
|
ThreadPageDestination(
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
package com.huanchengfly.tieba.post.ui.page.user.post
|
package com.huanchengfly.tieba.post.ui.page.user.post
|
||||||
|
|
||||||
|
import com.huanchengfly.tieba.post.App
|
||||||
|
import com.huanchengfly.tieba.post.R
|
||||||
import com.huanchengfly.tieba.post.api.TiebaApi
|
import com.huanchengfly.tieba.post.api.TiebaApi
|
||||||
|
import com.huanchengfly.tieba.post.api.models.AgreeBean
|
||||||
import com.huanchengfly.tieba.post.api.models.protos.PostInfoList
|
import com.huanchengfly.tieba.post.api.models.protos.PostInfoList
|
||||||
|
import com.huanchengfly.tieba.post.api.models.protos.updateAgreeStatus
|
||||||
import com.huanchengfly.tieba.post.api.models.protos.userPost.UserPostResponse
|
import com.huanchengfly.tieba.post.api.models.protos.userPost.UserPostResponse
|
||||||
|
import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage
|
||||||
import com.huanchengfly.tieba.post.arch.BaseViewModel
|
import com.huanchengfly.tieba.post.arch.BaseViewModel
|
||||||
|
import com.huanchengfly.tieba.post.arch.CommonUiEvent
|
||||||
import com.huanchengfly.tieba.post.arch.ImmutableHolder
|
import com.huanchengfly.tieba.post.arch.ImmutableHolder
|
||||||
import com.huanchengfly.tieba.post.arch.PartialChange
|
import com.huanchengfly.tieba.post.arch.PartialChange
|
||||||
import com.huanchengfly.tieba.post.arch.PartialChangeProducer
|
import com.huanchengfly.tieba.post.arch.PartialChangeProducer
|
||||||
|
|
@ -33,6 +39,18 @@ class UserPostViewModel @Inject constructor() :
|
||||||
override fun createPartialChangeProducer(): PartialChangeProducer<UserPostUiIntent, UserPostPartialChange, UserPostUiState> =
|
override fun createPartialChangeProducer(): PartialChangeProducer<UserPostUiIntent, UserPostPartialChange, UserPostUiState> =
|
||||||
UserPostPartialChangeProducer
|
UserPostPartialChangeProducer
|
||||||
|
|
||||||
|
override fun dispatchEvent(partialChange: UserPostPartialChange): UiEvent? =
|
||||||
|
when (partialChange) {
|
||||||
|
is UserPostPartialChange.Agree.Failure -> CommonUiEvent.Toast(
|
||||||
|
App.INSTANCE.getString(
|
||||||
|
R.string.toast_agree_failed,
|
||||||
|
partialChange.error.getErrorMessage()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
private object UserPostPartialChangeProducer :
|
private object UserPostPartialChangeProducer :
|
||||||
PartialChangeProducer<UserPostUiIntent, UserPostPartialChange, UserPostUiState> {
|
PartialChangeProducer<UserPostUiIntent, UserPostPartialChange, UserPostUiState> {
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
|
@ -42,6 +60,8 @@ class UserPostViewModel @Inject constructor() :
|
||||||
.flatMapConcat { it.toPartialChangeFlow() },
|
.flatMapConcat { it.toPartialChangeFlow() },
|
||||||
intentFlow.filterIsInstance<UserPostUiIntent.LoadMore>()
|
intentFlow.filterIsInstance<UserPostUiIntent.LoadMore>()
|
||||||
.flatMapConcat { it.toPartialChangeFlow() },
|
.flatMapConcat { it.toPartialChangeFlow() },
|
||||||
|
intentFlow.filterIsInstance<UserPostUiIntent.Agree>()
|
||||||
|
.flatMapConcat { it.toPartialChangeFlow() }
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun UserPostUiIntent.Refresh.toPartialChangeFlow(): Flow<UserPostPartialChange> =
|
private fun UserPostUiIntent.Refresh.toPartialChangeFlow(): Flow<UserPostPartialChange> =
|
||||||
|
|
@ -74,6 +94,25 @@ class UserPostViewModel @Inject constructor() :
|
||||||
}
|
}
|
||||||
.onStart { emit(UserPostPartialChange.LoadMore.Start) }
|
.onStart { emit(UserPostPartialChange.LoadMore.Start) }
|
||||||
.catch { emit(UserPostPartialChange.LoadMore.Failure(it)) }
|
.catch { emit(UserPostPartialChange.LoadMore.Failure(it)) }
|
||||||
|
|
||||||
|
private fun UserPostUiIntent.Agree.toPartialChangeFlow(): Flow<UserPostPartialChange.Agree> =
|
||||||
|
TiebaApi.getInstance()
|
||||||
|
.opAgreeFlow(
|
||||||
|
threadId.toString(), postId.toString(), hasAgree, objType = 3
|
||||||
|
)
|
||||||
|
.map<AgreeBean, UserPostPartialChange.Agree> {
|
||||||
|
UserPostPartialChange.Agree.Success(threadId, postId, hasAgree xor 1)
|
||||||
|
}
|
||||||
|
.onStart {
|
||||||
|
emit(
|
||||||
|
UserPostPartialChange.Agree.Start(
|
||||||
|
threadId,
|
||||||
|
postId,
|
||||||
|
hasAgree xor 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.catch { emit(UserPostPartialChange.Agree.Failure(threadId, postId, hasAgree, it)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,6 +127,12 @@ sealed interface UserPostUiIntent : UiIntent {
|
||||||
val isThread: Boolean,
|
val isThread: Boolean,
|
||||||
val page: Int,
|
val page: Int,
|
||||||
) : UserPostUiIntent
|
) : UserPostUiIntent
|
||||||
|
|
||||||
|
data class Agree(
|
||||||
|
val threadId: Long,
|
||||||
|
val postId: Long,
|
||||||
|
val hasAgree: Int,
|
||||||
|
) : UserPostUiIntent
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface UserPostPartialChange : PartialChange<UserPostUiState> {
|
sealed interface UserPostPartialChange : PartialChange<UserPostUiState> {
|
||||||
|
|
@ -168,6 +213,75 @@ sealed interface UserPostPartialChange : PartialChange<UserPostUiState> {
|
||||||
val error: Throwable,
|
val error: Throwable,
|
||||||
) : LoadMore()
|
) : LoadMore()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class Agree : UserPostPartialChange {
|
||||||
|
private fun List<ImmutableHolder<PostInfoList>>.updateAgreeStatus(
|
||||||
|
threadId: Long,
|
||||||
|
postId: Long,
|
||||||
|
hasAgree: Int,
|
||||||
|
): ImmutableList<ImmutableHolder<PostInfoList>> {
|
||||||
|
return map {
|
||||||
|
val (postInfo) = it
|
||||||
|
if (postInfo.thread_id == threadId && postInfo.post_id == postId) {
|
||||||
|
postInfo.updateAgreeStatus(hasAgree)
|
||||||
|
} else {
|
||||||
|
postInfo
|
||||||
|
}
|
||||||
|
}.wrapImmutable()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reduce(oldState: UserPostUiState): UserPostUiState =
|
||||||
|
when (this) {
|
||||||
|
is Start -> {
|
||||||
|
oldState.copy(
|
||||||
|
posts = oldState.posts.updateAgreeStatus(
|
||||||
|
threadId,
|
||||||
|
postId,
|
||||||
|
hasAgree
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Success -> {
|
||||||
|
oldState.copy(
|
||||||
|
posts = oldState.posts.updateAgreeStatus(
|
||||||
|
threadId,
|
||||||
|
postId,
|
||||||
|
hasAgree
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Failure -> {
|
||||||
|
oldState.copy(
|
||||||
|
posts = oldState.posts.updateAgreeStatus(
|
||||||
|
threadId,
|
||||||
|
postId,
|
||||||
|
hasAgree
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Start(
|
||||||
|
val threadId: Long,
|
||||||
|
val postId: Long,
|
||||||
|
val hasAgree: Int,
|
||||||
|
) : Agree()
|
||||||
|
|
||||||
|
data class Success(
|
||||||
|
val threadId: Long,
|
||||||
|
val postId: Long,
|
||||||
|
val hasAgree: Int,
|
||||||
|
) : Agree()
|
||||||
|
|
||||||
|
data class Failure(
|
||||||
|
val threadId: Long,
|
||||||
|
val postId: Long,
|
||||||
|
val hasAgree: Int,
|
||||||
|
val error: Throwable,
|
||||||
|
) : Agree()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class UserPostUiState(
|
data class UserPostUiState(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue