点赞和评论
This commit is contained in:
@@ -12,6 +12,7 @@ interface CommentService {
|
|||||||
suspend fun getComments(pageNumber: Int, postId: Int? = null): ListContainer<Comment>
|
suspend fun getComments(pageNumber: Int, postId: Int? = null): ListContainer<Comment>
|
||||||
suspend fun createComment(postId: Int, content: String, authorId: Int): Comment
|
suspend fun createComment(postId: Int, content: String, authorId: Int): Comment
|
||||||
suspend fun likeComment(commentId: Int)
|
suspend fun likeComment(commentId: Int)
|
||||||
|
suspend fun dislikeComment(commentId: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ data class Comment(
|
|||||||
val postId: Int = 0,
|
val postId: Int = 0,
|
||||||
val avatar: String,
|
val avatar: String,
|
||||||
val author: Int,
|
val author: Int,
|
||||||
val liked: Boolean,
|
var liked: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
class CommentPagingSource(
|
class CommentPagingSource(
|
||||||
@@ -82,6 +83,12 @@ class TestCommentServiceImpl : CommentService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
rawList = rawList.sortedBy { -it.id }
|
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))
|
val currentSublist = rawList.subList(from, min(to, rawList.size))
|
||||||
return ListContainer(
|
return ListContainer(
|
||||||
total = rawList.size,
|
total = rawList.size,
|
||||||
@@ -121,7 +128,18 @@ class TestCommentServiceImpl : CommentService {
|
|||||||
it
|
it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TestDatabase.likeCommentList += Pair(commentId, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import kotlin.math.min
|
|||||||
interface MomentService {
|
interface MomentService {
|
||||||
suspend fun getMomentById(id: Int): MomentItem
|
suspend fun getMomentById(id: Int): MomentItem
|
||||||
suspend fun likeMoment(id: Int)
|
suspend fun likeMoment(id: Int)
|
||||||
|
suspend fun dislikeMoment(id: Int)
|
||||||
suspend fun getMoments(
|
suspend fun getMoments(
|
||||||
pageNumber: Int,
|
pageNumber: Int,
|
||||||
author: Int? = null,
|
author: Int? = null,
|
||||||
@@ -81,6 +82,10 @@ class TestMomentServiceImpl() : MomentService {
|
|||||||
testMomentBackend.likeMoment(id)
|
testMomentBackend.likeMoment(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun dislikeMoment(id: Int) {
|
||||||
|
testMomentBackend.dislikeMoment(id)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestMomentBackend(
|
class TestMomentBackend(
|
||||||
@@ -113,6 +118,12 @@ class TestMomentBackend(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
val currentSublist = rawList.subList(from, min(to, rawList.size))
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
// delay
|
// delay
|
||||||
kotlinx.coroutines.delay(loadDelay)
|
kotlinx.coroutines.delay(loadDelay)
|
||||||
return ListContainer(
|
return ListContainer(
|
||||||
@@ -124,7 +135,14 @@ class TestMomentBackend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMomentById(id: Int): MomentItem {
|
suspend fun getMomentById(id: Int): MomentItem {
|
||||||
return TestDatabase.momentData[id]
|
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 likeMoment(id: Int) {
|
suspend fun likeMoment(id: Int) {
|
||||||
@@ -133,6 +151,17 @@ class TestMomentBackend(
|
|||||||
}
|
}
|
||||||
val newMoment = oldMoment.copy(likeCount = oldMoment.likeCount + 1)
|
val newMoment = oldMoment.copy(likeCount = oldMoment.likeCount + 1)
|
||||||
TestDatabase.updateMomentById(id, newMoment)
|
TestDatabase.updateMomentById(id, newMoment)
|
||||||
|
TestDatabase.likeMomentList += Pair(id, 1)
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -17,5 +17,6 @@ data class MomentItem(
|
|||||||
val shareCount: Int,
|
val shareCount: Int,
|
||||||
val favoriteCount: Int,
|
val favoriteCount: Int,
|
||||||
val images: List<String> = emptyList(),
|
val images: List<String> = emptyList(),
|
||||||
val authorId: Int = 0
|
val authorId: Int = 0,
|
||||||
|
var liked: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -39,13 +39,14 @@ object TestDatabase {
|
|||||||
)
|
)
|
||||||
var followList = emptyList<Pair<Int, Int>>()
|
var followList = emptyList<Pair<Int, Int>>()
|
||||||
var likeCommentList = emptyList<Pair<Int, Int>>()
|
var likeCommentList = emptyList<Pair<Int, Int>>()
|
||||||
|
var likeMomentList = emptyList<Pair<Int, Int>>()
|
||||||
init {
|
init {
|
||||||
val faker = faker {
|
val faker = faker {
|
||||||
this.fakerConfig {
|
this.fakerConfig {
|
||||||
locale = "en"
|
locale = "en"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accountData = (0..100).toList().mapIndexed { idx, _ ->
|
accountData = (0..20).toList().mapIndexed { idx, _ ->
|
||||||
AccountProfile(
|
AccountProfile(
|
||||||
id = idx,
|
id = idx,
|
||||||
followerCount = 0,
|
followerCount = 0,
|
||||||
@@ -58,7 +59,7 @@ object TestDatabase {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
// make a random follow rel
|
// make a random follow rel
|
||||||
for (i in 0..500) {
|
for (i in 0..100) {
|
||||||
var person1 = accountData.random()
|
var person1 = accountData.random()
|
||||||
var persion2 = accountData.random()
|
var persion2 = accountData.random()
|
||||||
followList += Pair(person1.id, persion2.id)
|
followList += Pair(person1.id, persion2.id)
|
||||||
@@ -74,10 +75,11 @@ object TestDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
momentData = (0..200).toList().mapIndexed { idx, _ ->
|
momentData = (0..60).toList().mapIndexed { idx, _ ->
|
||||||
val person = accountData.random()
|
val person = accountData.random()
|
||||||
// make fake comment
|
// make fake comment
|
||||||
for (i in 0..faker.random.nextInt(0, 5)) {
|
val commentCount = faker.random.nextInt(0, 50)
|
||||||
|
for (i in 0..commentCount) {
|
||||||
commentIdCounter += 1
|
commentIdCounter += 1
|
||||||
val commentPerson = accountData.random()
|
val commentPerson = accountData.random()
|
||||||
var newComment = Comment(
|
var newComment = Comment(
|
||||||
@@ -100,6 +102,11 @@ object TestDatabase {
|
|||||||
}
|
}
|
||||||
comment += newComment
|
comment += newComment
|
||||||
}
|
}
|
||||||
|
val likeCount = faker.random.nextInt(0, 5)
|
||||||
|
for (i in 0..likeCount) {
|
||||||
|
val likePerson = accountData.random()
|
||||||
|
likeMomentList += Pair(idx, likePerson.id)
|
||||||
|
}
|
||||||
MomentItem(
|
MomentItem(
|
||||||
id = idx,
|
id = idx,
|
||||||
avatar = person.avatar,
|
avatar = person.avatar,
|
||||||
@@ -109,8 +116,8 @@ object TestDatabase {
|
|||||||
followStatus = false,
|
followStatus = false,
|
||||||
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
|
momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …",
|
||||||
momentPicture = R.drawable.default_moment_img,
|
momentPicture = R.drawable.default_moment_img,
|
||||||
likeCount = faker.random.nextInt(0, 100),
|
likeCount = likeCount,
|
||||||
commentCount = faker.random.nextInt(0, 100),
|
commentCount = commentCount + 1,
|
||||||
shareCount = faker.random.nextInt(0, 100),
|
shareCount = faker.random.nextInt(0, 100),
|
||||||
favoriteCount = faker.random.nextInt(0, 100),
|
favoriteCount = faker.random.nextInt(0, 100),
|
||||||
images = imageList.shuffled().take(3),
|
images = imageList.shuffled().take(3),
|
||||||
|
|||||||
@@ -70,10 +70,16 @@ class CommentModalViewModel(
|
|||||||
}
|
}
|
||||||
).flow.cachedIn(viewModelScope)
|
).flow.cachedIn(viewModelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentModalContent(postId: Int? = null, onDismiss: () -> Unit = {}) {
|
fun CommentModalContent(
|
||||||
|
postId: Int? = null,
|
||||||
|
onCommentAdded: () -> Unit = {},
|
||||||
|
onDismiss: () -> Unit = {}
|
||||||
|
) {
|
||||||
val model = viewModel<CommentModalViewModel>(
|
val model = viewModel<CommentModalViewModel>(
|
||||||
|
key = "CommentModalViewModel_$postId",
|
||||||
factory = object : ViewModelProvider.Factory {
|
factory = object : ViewModelProvider.Factory {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
return CommentModalViewModel(postId) as T
|
return CommentModalViewModel(postId) as T
|
||||||
@@ -102,6 +108,7 @@ fun CommentModalContent(postId: Int? = null, onDismiss: () -> Unit = {}) {
|
|||||||
commentText = ""
|
commentText = ""
|
||||||
}
|
}
|
||||||
comments.refresh()
|
comments.refresh()
|
||||||
|
onCommentAdded()
|
||||||
}
|
}
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -129,8 +136,7 @@ fun CommentModalContent(postId: Int? = null, onDismiss: () -> Unit = {}) {
|
|||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
) {
|
) {
|
||||||
CommentsSection(lazyPagingItems = comments, onLike = {
|
CommentsSection(lazyPagingItems = comments, onLike = { comment: Comment ->
|
||||||
comment: Comment ->
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
model.commentService.likeComment(comment.id)
|
model.commentService.likeComment(comment.id)
|
||||||
comments.refresh()
|
comments.refresh()
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import kotlinx.coroutines.launch
|
|||||||
@Composable
|
@Composable
|
||||||
fun AnimatedLikeIcon(
|
fun AnimatedLikeIcon(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
liked: Boolean = false,
|
||||||
onClick: (() -> Unit)? = null
|
onClick: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
var liked by remember { mutableStateOf(false) }
|
|
||||||
val animatableRotation = remember { Animatable(0f) }
|
val animatableRotation = remember { Animatable(0f) }
|
||||||
val animatedColor by animateColorAsState(targetValue = if (liked) Color(0xFFd83737) else Color.Black)
|
val animatedColor by animateColorAsState(targetValue = if (liked) Color(0xFFd83737) else Color.Black)
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -52,13 +52,11 @@ fun AnimatedLikeIcon(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.noRippleClickable {
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.noRippleClickable {
|
||||||
liked = !liked
|
|
||||||
onClick?.invoke()
|
onClick?.invoke()
|
||||||
// Trigger shake animation
|
// Trigger shake animation
|
||||||
scope.launch {
|
scope.launch {
|
||||||
shake()
|
shake()
|
||||||
}
|
}
|
||||||
|
|
||||||
}) {
|
}) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_like),
|
painter = painterResource(id = R.drawable.rider_pro_like),
|
||||||
|
|||||||
@@ -6,13 +6,16 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
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
|
||||||
@@ -22,9 +25,11 @@ import androidx.compose.ui.text.TextStyle
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EditCommentBottomModal() {
|
fun EditCommentBottomModal(onSend: (String) -> Unit = {}) {
|
||||||
|
var text by remember { mutableStateOf("") }
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -49,8 +54,10 @@ fun EditCommentBottomModal() {
|
|||||||
|
|
||||||
) {
|
) {
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
value = "",
|
value = text,
|
||||||
onValueChange = { },
|
onValueChange = {
|
||||||
|
text = it
|
||||||
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
textStyle = TextStyle(
|
textStyle = TextStyle(
|
||||||
@@ -67,10 +74,11 @@ fun EditCommentBottomModal() {
|
|||||||
contentDescription = "Send",
|
contentDescription = "Send",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(32.dp)
|
.size(32.dp)
|
||||||
|
.noRippleClickable {
|
||||||
|
onSend(text)
|
||||||
|
text = ""
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,21 +58,28 @@ import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
|||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MomentsList() {
|
fun MomentsList() {
|
||||||
val model = MomentViewModel
|
val model = MomentViewModel
|
||||||
var dataFlow = model.momentsFlow
|
var dataFlow = model.momentsFlow
|
||||||
var moments = dataFlow.collectAsLazyPagingItems()
|
var moments = dataFlow.collectAsLazyPagingItems()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
items(moments.itemCount) { idx ->
|
items(moments.itemCount) { idx ->
|
||||||
val momentItem = moments[idx] ?: return@items
|
val momentItem = moments[idx] ?: return@items
|
||||||
MomentCard(momentItem = momentItem, onLikeClick = {
|
MomentCard(momentItem = momentItem,
|
||||||
|
onAddComment = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
model.onAddComment(momentItem.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLikeClick = {
|
||||||
|
scope.launch {
|
||||||
|
if (momentItem.liked) {
|
||||||
|
model.dislikeMoment(momentItem.id)
|
||||||
|
} else {
|
||||||
model.likeMoment(momentItem.id)
|
model.likeMoment(momentItem.id)
|
||||||
// moments.refresh()
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -83,7 +90,8 @@ fun MomentsList() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun MomentCard(
|
fun MomentCard(
|
||||||
momentItem: MomentItem,
|
momentItem: MomentItem,
|
||||||
onLikeClick: () -> Unit
|
onLikeClick: () -> Unit,
|
||||||
|
onAddComment: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
Column(
|
Column(
|
||||||
@@ -103,7 +111,12 @@ fun MomentCard(
|
|||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
ModificationListHeader()
|
ModificationListHeader()
|
||||||
MomentBottomOperateRowGroup(momentOperateBtnBoxModifier, momentItem = momentItem, onLikeClick = onLikeClick)
|
MomentBottomOperateRowGroup(
|
||||||
|
momentOperateBtnBoxModifier,
|
||||||
|
momentItem = momentItem,
|
||||||
|
onLikeClick = onLikeClick,
|
||||||
|
onAddComment = onAddComment
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,8 +227,15 @@ fun MomentTopRowGroup(momentItem: MomentItem) {
|
|||||||
AsyncImage(
|
AsyncImage(
|
||||||
momentItem.avatar,
|
momentItem.avatar,
|
||||||
contentDescription = "",
|
contentDescription = "",
|
||||||
modifier = Modifier.size(40.dp).noRippleClickable {
|
modifier = Modifier
|
||||||
navController.navigate(NavigationRoute.AccountProfile.route.replace("{id}", momentItem.authorId.toString()))
|
.size(40.dp)
|
||||||
|
.noRippleClickable {
|
||||||
|
navController.navigate(
|
||||||
|
NavigationRoute.AccountProfile.route.replace(
|
||||||
|
"{id}",
|
||||||
|
momentItem.authorId.toString()
|
||||||
|
)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
contentScale = ContentScale.Crop
|
contentScale = ContentScale.Crop
|
||||||
)
|
)
|
||||||
@@ -310,6 +330,7 @@ fun MomentOperateBtn(count: String, content: @Composable () -> Unit) {
|
|||||||
fun MomentBottomOperateRowGroup(
|
fun MomentBottomOperateRowGroup(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
onLikeClick: () -> Unit = {},
|
onLikeClick: () -> Unit = {},
|
||||||
|
onAddComment: () -> Unit = {},
|
||||||
momentItem: MomentItem
|
momentItem: MomentItem
|
||||||
) {
|
) {
|
||||||
var systemUiController = rememberSystemUiController()
|
var systemUiController = rememberSystemUiController()
|
||||||
@@ -323,7 +344,10 @@ fun MomentBottomOperateRowGroup(
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
systemUiController.setNavigationBarColor(Color(0xfff7f7f7))
|
systemUiController.setNavigationBarColor(Color(0xfff7f7f7))
|
||||||
CommentModalContent(postId = momentItem.id) {
|
CommentModalContent(postId = momentItem.id, onCommentAdded = {
|
||||||
|
showCommentModal = false
|
||||||
|
onAddComment()
|
||||||
|
}) {
|
||||||
systemUiController.setNavigationBarColor(Color.Black)
|
systemUiController.setNavigationBarColor(Color.Black)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,8 +362,14 @@ fun MomentBottomOperateRowGroup(
|
|||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
MomentOperateBtn(count = momentItem.likeCount.toString()) {
|
MomentOperateBtn(count = momentItem.likeCount.toString()) {
|
||||||
AnimatedLikeIcon(modifier = Modifier.size(24.dp)) {
|
AnimatedLikeIcon(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
liked = momentItem.liked
|
||||||
|
) {
|
||||||
|
|
||||||
onLikeClick()
|
onLikeClick()
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,19 +382,28 @@ fun MomentBottomOperateRowGroup(
|
|||||||
},
|
},
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
MomentOperateBtn(icon = R.drawable.rider_pro_moment_comment, count = momentItem.commentCount.toString())
|
MomentOperateBtn(
|
||||||
|
icon = R.drawable.rider_pro_moment_comment,
|
||||||
|
count = momentItem.commentCount.toString()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
MomentOperateBtn(icon = R.drawable.rider_pro_share, count = momentItem.shareCount.toString())
|
MomentOperateBtn(
|
||||||
|
icon = R.drawable.rider_pro_share,
|
||||||
|
count = momentItem.shareCount.toString()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
MomentOperateBtn(icon = R.drawable.rider_pro_favoriate, count = momentItem.favoriteCount.toString())
|
MomentOperateBtn(
|
||||||
|
icon = R.drawable.rider_pro_favoriate,
|
||||||
|
count = momentItem.favoriteCount.toString()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,22 +31,23 @@ object MomentViewModel : ViewModel() {
|
|||||||
val profile = accountService.getMyAccountProfile()
|
val profile = accountService.getMyAccountProfile()
|
||||||
Pager(
|
Pager(
|
||||||
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
pagingSourceFactory = { MomentPagingSource(
|
pagingSourceFactory = {
|
||||||
|
MomentPagingSource(
|
||||||
MomentRemoteDataSource(momentService),
|
MomentRemoteDataSource(momentService),
|
||||||
timelineId = profile.id
|
timelineId = profile.id
|
||||||
) }
|
)
|
||||||
|
}
|
||||||
).flow.cachedIn(viewModelScope).collectLatest {
|
).flow.cachedIn(viewModelScope).collectLatest {
|
||||||
_momentsFlow.value = it
|
_momentsFlow.value = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun likeMoment(id: Int) {
|
fun updateLikeCount(id: Int) {
|
||||||
momentService.likeMoment(id)
|
|
||||||
val currentPagingData = _momentsFlow.value
|
val currentPagingData = _momentsFlow.value
|
||||||
val updatedPagingData = currentPagingData.map { momentItem ->
|
val updatedPagingData = currentPagingData.map { momentItem ->
|
||||||
if (momentItem.id == id) {
|
if (momentItem.id == id) {
|
||||||
momentItem.copy(likeCount = momentItem.likeCount + 1)
|
momentItem.copy(likeCount = momentItem.likeCount + 1, liked = true)
|
||||||
} else {
|
} else {
|
||||||
momentItem
|
momentItem
|
||||||
}
|
}
|
||||||
@@ -54,4 +55,42 @@ object MomentViewModel : ViewModel() {
|
|||||||
_momentsFlow.value = updatedPagingData
|
_momentsFlow.value = updatedPagingData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun likeMoment(id: Int) {
|
||||||
|
momentService.likeMoment(id)
|
||||||
|
updateLikeCount(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateCommentCount(id: Int) {
|
||||||
|
val currentPagingData = _momentsFlow.value
|
||||||
|
val updatedPagingData = currentPagingData.map { momentItem ->
|
||||||
|
if (momentItem.id == id) {
|
||||||
|
momentItem.copy(commentCount = momentItem.commentCount + 1)
|
||||||
|
} else {
|
||||||
|
momentItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_momentsFlow.value = updatedPagingData
|
||||||
|
}
|
||||||
|
suspend fun onAddComment(id: Int) {
|
||||||
|
val currentPagingData = _momentsFlow.value
|
||||||
|
updateCommentCount(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateDislikeMomentById(id: Int) {
|
||||||
|
val currentPagingData = _momentsFlow.value
|
||||||
|
val updatedPagingData = currentPagingData.map { momentItem ->
|
||||||
|
if (momentItem.id == id) {
|
||||||
|
momentItem.copy(likeCount = momentItem.likeCount - 1, liked = false)
|
||||||
|
} else {
|
||||||
|
momentItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_momentsFlow.value = updatedPagingData
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun dislikeMoment(id: Int) {
|
||||||
|
momentService.dislikeMoment(id)
|
||||||
|
updateDislikeMomentById(id)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -58,11 +58,17 @@ import androidx.compose.ui.text.TextStyle
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.paging.Pager
|
import androidx.paging.Pager
|
||||||
import androidx.paging.PagingConfig
|
import androidx.paging.PagingConfig
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
import androidx.paging.compose.LazyPagingItems
|
import androidx.paging.compose.LazyPagingItems
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import androidx.paging.map
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.aiosman.riderpro.LocalNavController
|
import com.aiosman.riderpro.LocalNavController
|
||||||
import com.aiosman.riderpro.R
|
import com.aiosman.riderpro.R
|
||||||
@@ -71,66 +77,154 @@ import com.aiosman.riderpro.data.AccountService
|
|||||||
import com.aiosman.riderpro.data.Comment
|
import com.aiosman.riderpro.data.Comment
|
||||||
import com.aiosman.riderpro.data.CommentPagingSource
|
import com.aiosman.riderpro.data.CommentPagingSource
|
||||||
import com.aiosman.riderpro.data.CommentRemoteDataSource
|
import com.aiosman.riderpro.data.CommentRemoteDataSource
|
||||||
|
import com.aiosman.riderpro.data.CommentService
|
||||||
import com.aiosman.riderpro.data.TestCommentServiceImpl
|
import com.aiosman.riderpro.data.TestCommentServiceImpl
|
||||||
import com.aiosman.riderpro.data.MomentService
|
import com.aiosman.riderpro.data.MomentService
|
||||||
import com.aiosman.riderpro.data.TestAccountServiceImpl
|
import com.aiosman.riderpro.data.TestAccountServiceImpl
|
||||||
import com.aiosman.riderpro.data.TestMomentServiceImpl
|
import com.aiosman.riderpro.data.TestMomentServiceImpl
|
||||||
import com.aiosman.riderpro.model.MomentItem
|
import com.aiosman.riderpro.model.MomentItem
|
||||||
|
import com.aiosman.riderpro.ui.NavigationRoute
|
||||||
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
|
||||||
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
|
||||||
import com.aiosman.riderpro.ui.composables.EditCommentBottomModal
|
import com.aiosman.riderpro.ui.composables.EditCommentBottomModal
|
||||||
|
import com.aiosman.riderpro.ui.index.tabs.moment.MomentViewModel
|
||||||
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class PostViewModel(
|
||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
val postId: String
|
||||||
@Composable
|
) : ViewModel() {
|
||||||
fun PostScreen(
|
|
||||||
id: String,
|
|
||||||
) {
|
|
||||||
var service: MomentService = TestMomentServiceImpl()
|
var service: MomentService = TestMomentServiceImpl()
|
||||||
|
var commentService: CommentService = TestCommentServiceImpl()
|
||||||
|
private var _commentsFlow = MutableStateFlow<PagingData<Comment>>(PagingData.empty())
|
||||||
|
val commentsFlow = _commentsFlow.asStateFlow()
|
||||||
|
|
||||||
var commentSource = CommentPagingSource(
|
init {
|
||||||
CommentRemoteDataSource(TestCommentServiceImpl())
|
viewModelScope.launch {
|
||||||
)
|
Pager(
|
||||||
val commentsFlow: Flow<PagingData<Comment>> = Pager(
|
|
||||||
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
|
||||||
pagingSourceFactory = { commentSource }
|
pagingSourceFactory = {
|
||||||
).flow
|
CommentPagingSource(
|
||||||
val lazyPagingItems = commentsFlow.collectAsLazyPagingItems()
|
CommentRemoteDataSource(commentService),
|
||||||
var showCollapseContent by remember { mutableStateOf(true) }
|
postId = postId.toInt()
|
||||||
val scrollState = rememberLazyListState()
|
)
|
||||||
val uiController = rememberSystemUiController()
|
}
|
||||||
var moment by remember { mutableStateOf<MomentItem?>(null) }
|
).flow.cachedIn(viewModelScope).collectLatest {
|
||||||
var accountProfile by remember { mutableStateOf<AccountProfile?>(null) }
|
_commentsFlow.value = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var accountProfile by mutableStateOf<AccountProfile?>(null)
|
||||||
|
var moment by mutableStateOf<MomentItem?>(null)
|
||||||
var accountService: AccountService = TestAccountServiceImpl()
|
var accountService: AccountService = TestAccountServiceImpl()
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
uiController.setNavigationBarColor(Color.White)
|
suspend fun initData() {
|
||||||
moment = service.getMomentById(id.toInt())
|
moment = service.getMomentById(postId.toInt())
|
||||||
moment?.let {
|
moment?.let {
|
||||||
accountProfile = accountService.getAccountProfileById(it.authorId)
|
accountProfile = accountService.getAccountProfileById(it.authorId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun likeComment(commentId: Int) {
|
||||||
|
commentService.likeComment(commentId)
|
||||||
|
val currentPagingData = commentsFlow.value
|
||||||
|
val updatedPagingData = currentPagingData.map { comment ->
|
||||||
|
if (comment.id == commentId) {
|
||||||
|
comment.copy(liked = !comment.liked)
|
||||||
|
} else {
|
||||||
|
comment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_commentsFlow.value = updatedPagingData
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun createComment(content: String) {
|
||||||
|
commentService.createComment(postId.toInt(), content, 1)
|
||||||
|
MomentViewModel.updateCommentCount(postId.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun likeMoment() {
|
||||||
|
moment?.let {
|
||||||
|
service.likeMoment(it.id)
|
||||||
|
moment = moment?.copy(likeCount = moment?.likeCount?.plus(1) ?: 0, liked = true)
|
||||||
|
MomentViewModel.updateLikeCount(it.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun dislikeMoment() {
|
||||||
|
moment?.let {
|
||||||
|
service.dislikeMoment(it.id)
|
||||||
|
moment = moment?.copy(likeCount = moment?.likeCount?.minus(1) ?: 0, liked = false)
|
||||||
|
// update home list
|
||||||
|
MomentViewModel.updateDislikeMomentById(it.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PostScreen(
|
||||||
|
id: String,
|
||||||
|
) {
|
||||||
|
val viewModel = viewModel<PostViewModel>(
|
||||||
|
key = "PostViewModel_$id",
|
||||||
|
factory = object : ViewModelProvider.Factory {
|
||||||
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
|
return PostViewModel(id) as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val commentsPagging = viewModel.commentsFlow.collectAsLazyPagingItems()
|
||||||
|
var showCollapseContent by remember { mutableStateOf(true) }
|
||||||
|
val scrollState = rememberLazyListState()
|
||||||
|
val uiController = rememberSystemUiController()
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
uiController.setNavigationBarColor(Color.White)
|
||||||
|
viewModel.initData()
|
||||||
|
}
|
||||||
StatusBarMaskLayout {
|
StatusBarMaskLayout {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
bottomBar = { BottomNavigationBar() }
|
bottomBar = {
|
||||||
|
BottomNavigationBar(
|
||||||
|
onLikeClick = {
|
||||||
|
scope.launch {
|
||||||
|
if (viewModel.moment?.liked == true) {
|
||||||
|
viewModel.dislikeMoment()
|
||||||
|
} else {
|
||||||
|
viewModel.likeMoment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCreateComment = {
|
||||||
|
scope.launch {
|
||||||
|
viewModel.createComment(it)
|
||||||
|
commentsPagging.refresh()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
momentItem = viewModel.moment
|
||||||
|
)
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
it
|
it
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
Header(accountProfile)
|
Header(viewModel.accountProfile)
|
||||||
Column(modifier = Modifier.animateContentSize()) {
|
Column(modifier = Modifier.animateContentSize()) {
|
||||||
AnimatedVisibility(visible = showCollapseContent) {
|
AnimatedVisibility(visible = showCollapseContent) {
|
||||||
// collapse content
|
// collapse content
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -140,13 +234,13 @@ fun PostScreen(
|
|||||||
) {
|
) {
|
||||||
PostImageView(
|
PostImageView(
|
||||||
id,
|
id,
|
||||||
moment?.images ?: emptyList()
|
viewModel.moment?.images ?: emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
PostDetails(
|
PostDetails(
|
||||||
id,
|
id,
|
||||||
moment
|
viewModel.moment
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,7 +250,14 @@ fun PostScreen(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|
||||||
) {
|
) {
|
||||||
CommentsSection(lazyPagingItems = lazyPagingItems, scrollState, onLike = {}) {
|
CommentsSection(
|
||||||
|
lazyPagingItems = commentsPagging,
|
||||||
|
scrollState,
|
||||||
|
onLike = { comment: Comment ->
|
||||||
|
scope.launch {
|
||||||
|
viewModel.likeComment(comment.id)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
showCollapseContent = it
|
showCollapseContent = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,7 +283,6 @@ fun Header(accountProfile: AccountProfile?) {
|
|||||||
navController.popBackStack()
|
navController.popBackStack()
|
||||||
}
|
}
|
||||||
.size(32.dp)
|
.size(32.dp)
|
||||||
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
accountProfile?.let {
|
accountProfile?.let {
|
||||||
@@ -191,7 +291,15 @@ fun Header(accountProfile: AccountProfile?) {
|
|||||||
contentDescription = "Profile Picture",
|
contentDescription = "Profile Picture",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(40.dp)
|
.size(40.dp)
|
||||||
.clip(CircleShape),
|
.clip(CircleShape)
|
||||||
|
.noRippleClickable {
|
||||||
|
navController.navigate(
|
||||||
|
NavigationRoute.AccountProfile.route.replace(
|
||||||
|
"{id}",
|
||||||
|
accountProfile.id.toString()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
contentScale = ContentScale.Crop
|
contentScale = ContentScale.Crop
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -298,11 +406,9 @@ fun PostDetails(
|
|||||||
)
|
)
|
||||||
Text(text = "12-11 发布")
|
Text(text = "12-11 发布")
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(text = "共231条评论")
|
Text(text = "${momentItem?.commentCount ?: 0} Comments")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -361,7 +467,11 @@ fun CommentItem(comment: Comment,onLike:()->Unit = {}) {
|
|||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
onLike()
|
onLike()
|
||||||
}) {
|
}) {
|
||||||
Icon(Icons.Filled.Favorite, contentDescription = "Like")
|
Icon(
|
||||||
|
Icons.Filled.Favorite,
|
||||||
|
contentDescription = "Like",
|
||||||
|
tint = if (comment.liked) Color.Red else Color.Gray
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Text(text = comment.likes.toString())
|
Text(text = comment.likes.toString())
|
||||||
}
|
}
|
||||||
@@ -379,7 +489,11 @@ fun CommentItem(comment: Comment,onLike:()->Unit = {}) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BottomNavigationBar() {
|
fun BottomNavigationBar(
|
||||||
|
onCreateComment: (String) -> Unit = {},
|
||||||
|
onLikeClick: () -> Unit = {},
|
||||||
|
momentItem: MomentItem?
|
||||||
|
) {
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
var showCommentModal by remember { mutableStateOf(false) }
|
var showCommentModal by remember { mutableStateOf(false) }
|
||||||
if (showCommentModal) {
|
if (showCommentModal) {
|
||||||
@@ -392,7 +506,10 @@ fun BottomNavigationBar() {
|
|||||||
dragHandle = {},
|
dragHandle = {},
|
||||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||||
) {
|
) {
|
||||||
EditCommentBottomModal()
|
EditCommentBottomModal() {
|
||||||
|
onCreateComment(it)
|
||||||
|
showCommentModal = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column(
|
Column(
|
||||||
@@ -427,10 +544,12 @@ fun BottomNavigationBar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { /*TODO*/ }) {
|
onClick = {
|
||||||
Icon(Icons.Filled.Favorite, contentDescription = "Send")
|
onLikeClick()
|
||||||
|
}) {
|
||||||
|
Icon(Icons.Filled.Favorite, contentDescription = "like", tint = if (momentItem?.liked == true) Color.Red else Color.Gray)
|
||||||
}
|
}
|
||||||
Text(text = "2077")
|
Text(text = momentItem?.likeCount.toString())
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { /*TODO*/ }) {
|
onClick = { /*TODO*/ }) {
|
||||||
Icon(Icons.Filled.Star, contentDescription = "Send")
|
Icon(Icons.Filled.Star, contentDescription = "Send")
|
||||||
|
|||||||
Reference in New Issue
Block a user