From f35bde65a21f3f42b3640a15771bc881a83ebf83 Mon Sep 17 00:00:00 2001 From: AllenTom Date: Sun, 28 Jul 2024 15:07:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=9A=E5=8A=A1=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 + .../data/comment/CommentPagingSource.kt | 98 +++++ .../data/moment/MomentPagingSource.kt | 15 +- .../com/aiosman/riderpro/model/MomentItem.kt | 3 +- .../riderpro/ui/comment/CommentModal.kt | 26 +- .../ui/composables/EditCommentBottomModal.kt | 76 ++++ .../riderpro/ui/index/tabs/moment/Moment.kt | 39 +- .../java/com/aiosman/riderpro/ui/post/Post.kt | 356 ++++++------------ 8 files changed, 355 insertions(+), 260 deletions(-) create mode 100644 app/src/main/java/com/aiosman/riderpro/data/comment/CommentPagingSource.kt create mode 100644 app/src/main/java/com/aiosman/riderpro/ui/composables/EditCommentBottomModal.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1659d8f..f604ee9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,6 +78,8 @@ dependencies { debugImplementation(libs.androidx.ui.test.manifest) implementation (libs.places) implementation(libs.androidx.animation) + implementation("io.coil-kt:coil-compose:2.7.0") + implementation("io.coil-kt:coil:2.7.0") } \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/data/comment/CommentPagingSource.kt b/app/src/main/java/com/aiosman/riderpro/data/comment/CommentPagingSource.kt new file mode 100644 index 0000000..7559842 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/data/comment/CommentPagingSource.kt @@ -0,0 +1,98 @@ +package com.aiosman.riderpro.data.comment + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import com.aiosman.riderpro.data.ListContainer +import java.io.IOException +import kotlin.random.Random + +data class Comment( + val name: String, + val comment: String, + val date: String, + val likes: Int, + val replies: List +) + +class CommentPagingSource( + private val remoteDataSource: CommentRemoteDataSource, +) : PagingSource() { + + override suspend fun load(params: LoadParams): LoadResult { + return try { + val currentPage = params.key ?: 1 + val comments = remoteDataSource.getComments( + pageNumber = currentPage + ) + + LoadResult.Page( + data = comments.list, + prevKey = if (currentPage == 1) null else currentPage - 1, + nextKey = if (comments.list.isEmpty()) null else comments.page + 1 + ) + } catch (exception: IOException) { + return LoadResult.Error(exception) + } + } + + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition + } + +} + +class CommentRemoteDataSource( + private val commentService: CommentService, +) { + suspend fun getComments(pageNumber: Int): ListContainer { + return commentService.getComments(pageNumber) + } +} + +interface CommentService { + suspend fun getComments(pageNumber: Int): ListContainer +} + +class TestCommentServiceImpl : CommentService { + private val mockData = generateMockComments(100) + override suspend fun getComments(pageNumber: Int): ListContainer { + val from = pageNumber * DataBatchSize + val to = (pageNumber + 1) * DataBatchSize + val currentSublist = mockData.subList(from, to) + return ListContainer( + total = mockData.size, + page = pageNumber, + pageSize = DataBatchSize, + list = currentSublist + ) + } + + private fun generateMockComments(count: Int): List { + return (0 until count).map { + Comment( + name = "User $it", + comment = "This is comment $it", + date = "2023-02-02 11:23", + likes = Random.nextInt(0, 100), + replies = generateMockReplies() + ) + } + } + + private fun generateMockReplies(): List { + val replyCount = Random.nextInt(0, 6) + return (0 until replyCount).map { + Comment( + name = "Reply User $it", + comment = "This is reply $it", + date = "2023-02-02 11:23", + likes = Random.nextInt(0, 100), + replies = emptyList() + ) + } + } + + companion object { + const val DataBatchSize = 5 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/data/moment/MomentPagingSource.kt b/app/src/main/java/com/aiosman/riderpro/data/moment/MomentPagingSource.kt index 70c83d8..1c0e493 100644 --- a/app/src/main/java/com/aiosman/riderpro/data/moment/MomentPagingSource.kt +++ b/app/src/main/java/com/aiosman/riderpro/data/moment/MomentPagingSource.kt @@ -1,12 +1,12 @@ package com.aiosman.riderpro.data.moment -import android.net.http.HttpException import androidx.paging.PagingSource import androidx.paging.PagingState import com.aiosman.riderpro.R import com.aiosman.riderpro.data.ListContainer import com.aiosman.riderpro.model.MomentItem import java.io.IOException +import kotlin.random.Random class MomentPagingSource( private val remoteDataSource: MomentRemoteDataSource, @@ -45,9 +45,15 @@ class MomentRemoteDataSource( interface MomentService { suspend fun getMoments(pageNumber: Int): ListContainer + suspend fun getMomentById(id: Int): MomentItem } class TestMomentServiceImpl() : MomentService { + var imageList = listOf( + "https://img.freepik.com/free-photo/white-billboard-template_23-2147726635.jpg?t=st=1722150015~exp=1722153615~hmac=5540620196d7898215d822be26353c87a63d51bbfb2b814e032626e1948a1583&w=740", + "https://img.freepik.com/free-photo/minimal-clothing-label-fashion-brands_53876-111053.jpg?w=1060&t=st=1722150122~exp=1722150722~hmac=67f8a2b6abfe3d08714cf0cc0085485c3221e1ba00dda14378b03753dce39153", + "https://img.freepik.com/free-photo/marketing-strategy-planning-strategy-concept_53876-42950.jpg" + ) val mockData = (0..300).toList().mapIndexed { idx, _ -> MomentItem( id = idx, @@ -61,13 +67,18 @@ class TestMomentServiceImpl() : MomentService { likeCount = 21, commentCount = 43, shareCount = 33, - favoriteCount = 211 + favoriteCount = 211, + images = imageList.shuffled().take(3), ) } val testMomentBackend = TestMomentBackend(mockData) override suspend fun getMoments(pageNumber: Int): ListContainer { return testMomentBackend.fetchMomentItems(pageNumber) } + + override suspend fun getMomentById(id: Int): MomentItem { + return mockData[id] + } } class TestMomentBackend( diff --git a/app/src/main/java/com/aiosman/riderpro/model/MomentItem.kt b/app/src/main/java/com/aiosman/riderpro/model/MomentItem.kt index b061fea..967456a 100644 --- a/app/src/main/java/com/aiosman/riderpro/model/MomentItem.kt +++ b/app/src/main/java/com/aiosman/riderpro/model/MomentItem.kt @@ -15,7 +15,8 @@ data class MomentItem( val likeCount: Int, val commentCount: Int, val shareCount: Int, - val favoriteCount: Int + val favoriteCount: Int, + val images: List = emptyList() ) val momentTestItem = MomentItem( diff --git a/app/src/main/java/com/aiosman/riderpro/ui/comment/CommentModal.kt b/app/src/main/java/com/aiosman/riderpro/ui/comment/CommentModal.kt index 77f8168..ee889bd 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/comment/CommentModal.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/comment/CommentModal.kt @@ -35,13 +35,32 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import androidx.paging.compose.collectAsLazyPagingItems import com.aiosman.riderpro.ui.post.CommentsSection import com.aiosman.riderpro.R +import com.aiosman.riderpro.data.comment.Comment +import com.aiosman.riderpro.data.comment.CommentPagingSource +import com.aiosman.riderpro.data.comment.CommentRemoteDataSource +import com.aiosman.riderpro.data.comment.TestCommentServiceImpl +import com.aiosman.riderpro.model.MomentItem +import com.aiosman.riderpro.ui.index.tabs.moment.MomentViewModel.momentListPagingSource +import kotlinx.coroutines.flow.Flow @Preview @Composable fun CommentModalContent(onDismiss: () -> Unit = {}) { + var commentSource = CommentPagingSource( + CommentRemoteDataSource(TestCommentServiceImpl()) + ) + val commentsFlow: Flow> = Pager( + config = PagingConfig(pageSize = 5, enablePlaceholders = false), + pagingSourceFactory = { commentSource } + ).flow + val comments = commentsFlow.collectAsLazyPagingItems() val insets = WindowInsets val imePadding = insets.ime.getBottom(density = LocalDensity.current) var bottomPadding by remember { mutableStateOf(0.dp) } @@ -80,7 +99,11 @@ fun CommentModalContent(onDismiss: () -> Unit = {}) { .padding(horizontal = 16.dp) .weight(1f) ) { - CommentsSection{} + + CommentsSection(lazyPagingItems = comments) { + + } + } Box( modifier = Modifier @@ -131,7 +154,6 @@ fun CommentModalContent(onDismiss: () -> Unit = {}) { } - } } diff --git a/app/src/main/java/com/aiosman/riderpro/ui/composables/EditCommentBottomModal.kt b/app/src/main/java/com/aiosman/riderpro/ui/composables/EditCommentBottomModal.kt new file mode 100644 index 0000000..d9e4a98 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/ui/composables/EditCommentBottomModal.kt @@ -0,0 +1,76 @@ +package com.aiosman.riderpro.ui.composables + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.aiosman.riderpro.R + +@Composable +fun EditCommentBottomModal() { + Box( + modifier = Modifier + .fillMaxWidth() + .background(Color(0xfff7f7f7)) + .padding(horizontal = 16.dp, vertical = 8.dp) + + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.Center), + verticalAlignment = Alignment.CenterVertically + ) { + // rounded + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .clip(RoundedCornerShape(20.dp)) + .background(Color(0xffe5e5e5)) + .padding(horizontal = 16.dp, vertical = 12.dp) + + ) { + BasicTextField( + value = "", + onValueChange = { }, + modifier = Modifier + .fillMaxWidth(), + textStyle = TextStyle( + color = Color.Black, + fontWeight = FontWeight.Normal + ), + minLines = 5 + ) + + } + Spacer(modifier = Modifier.width(16.dp)) + Image( + painter = painterResource(id = R.drawable.rider_pro_send), + contentDescription = "Send", + modifier = Modifier + .size(32.dp) + + ) + } + + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt index 3c4cd64..ccd201e 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/Moment.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize @@ -36,6 +37,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight @@ -43,6 +45,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.paging.compose.collectAsLazyPagingItems +import coil.compose.AsyncImage import com.aiosman.riderpro.LocalAnimatedContentScope import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.LocalSharedTransitionScope @@ -251,34 +254,30 @@ fun MomentTopRowGroup(momentItem: MomentItem) { fun MomentContentGroup( momentItem: MomentItem, ) { - val sharedTransitionScope = LocalSharedTransitionScope.current - val animatedContentScope = LocalAnimatedContentScope.current - with(sharedTransitionScope) { - Text( - text = momentItem.momentTextContent, +// val sharedTransitionScope = LocalSharedTransitionScope.current +// val animatedContentScope = LocalAnimatedContentScope.current + val displayImageUrl = momentItem.images.firstOrNull() + Text( + text = momentItem.momentTextContent, + modifier = Modifier + .fillMaxWidth() + .padding(top = 22.dp, bottom = 16.dp, start = 24.dp, end = 24.dp), + fontSize = 16.sp + ) + displayImageUrl?.let { + AsyncImage( + it, modifier = Modifier - .sharedElement( - sharedTransitionScope.rememberSharedContentState(key = "text-${momentItem.id}"), - animatedVisibilityScope = animatedContentScope - ) .fillMaxWidth() - .padding(top = 22.dp, bottom = 16.dp, start = 24.dp, end = 24.dp), - fontSize = 16.sp - ) - Image( - modifier = Modifier - .sharedElement( - sharedTransitionScope.rememberSharedContentState(key = "image-${momentItem.id}"), - animatedVisibilityScope = animatedContentScope - ) - .fillMaxWidth(), - painter = painterResource(id = momentItem.momentPicture), + .aspectRatio(1f), + contentScale = ContentScale.Crop, contentDescription = "" ) } } + @Composable fun MomentOperateBtn(@DrawableRes icon: Int, count: String) { Row(verticalAlignment = Alignment.CenterVertically) { diff --git a/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt b/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt index 7daa9a8..a83ed72 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/post/Post.kt @@ -36,8 +36,10 @@ import androidx.compose.material.icons.filled.Star import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -56,36 +58,66 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import androidx.paging.compose.LazyPagingItems +import androidx.paging.compose.collectAsLazyPagingItems +import coil.compose.AsyncImage import com.aiosman.riderpro.LocalAnimatedContentScope +import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.LocalSharedTransitionScope import com.aiosman.riderpro.R +import com.aiosman.riderpro.data.comment.Comment +import com.aiosman.riderpro.data.comment.CommentPagingSource +import com.aiosman.riderpro.data.comment.CommentRemoteDataSource +import com.aiosman.riderpro.data.comment.TestCommentServiceImpl +import com.aiosman.riderpro.data.moment.MomentService +import com.aiosman.riderpro.data.moment.TestMomentServiceImpl +import com.aiosman.riderpro.model.MomentItem +import com.aiosman.riderpro.ui.comment.CommentModalContent import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder +import com.aiosman.riderpro.ui.composables.EditCommentBottomModal +import com.aiosman.riderpro.ui.modifiers.noRippleClickable +import com.google.accompanist.systemuicontroller.rememberSystemUiController +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch -fun makeMockImages(): List { - return listOf( - PostImage(R.drawable.default_moment_img, "Image 1"), - PostImage(R.drawable.default_avatar, "Image 2"), - PostImage(R.drawable.rider_pro_moment_demo_1, "Image 3") - ) -} - @OptIn(ExperimentalSharedTransitionApi::class) @Composable fun PostScreen( id: String, ) { + var service: MomentService = TestMomentServiceImpl() + + var commentSource = CommentPagingSource( + CommentRemoteDataSource(TestCommentServiceImpl()) + ) + val commentsFlow: Flow> = Pager( + config = PagingConfig(pageSize = 5, enablePlaceholders = false), + pagingSourceFactory = { commentSource } + ).flow + val lazyPagingItems = commentsFlow.collectAsLazyPagingItems() var showCollapseContent by remember { mutableStateOf(true) } val scrollState = rememberLazyListState() + val uiController = rememberSystemUiController() + var moment by remember { mutableStateOf(null) } + LaunchedEffect(Unit) { + uiController.setNavigationBarColor(Color.White) + moment = service.getMomentById(id.toInt()) + } StatusBarMaskLayout { Scaffold( modifier = Modifier.fillMaxSize(), bottomBar = { BottomNavigationBar() } ) { it - Column(modifier = Modifier.fillMaxSize()) { + Column( + modifier = Modifier + .fillMaxSize() + ) { Header() Column(modifier = Modifier.animateContentSize()) { AnimatedVisibility(visible = showCollapseContent) { @@ -99,12 +131,13 @@ fun PostScreen( ) { PostImageView( id, - makeMockImages(), + moment?.images ?: emptyList() ) } PostDetails( id, + moment ) } } @@ -114,18 +147,18 @@ fun PostScreen( .fillMaxWidth() ) { - CommentsSection(scrollState) { + CommentsSection(lazyPagingItems = lazyPagingItems, scrollState) { showCollapseContent = it } } } } } - } @Composable fun Header() { + val navController = LocalNavController.current Row( modifier = Modifier .fillMaxWidth() @@ -136,6 +169,9 @@ fun Header() { painter = painterResource(id = R.drawable.rider_pro_nav_back), // Replace with your image resource contentDescription = "Back", modifier = Modifier + .noRippleClickable { + navController.popBackStack() + } .size(32.dp) ) @@ -171,257 +207,97 @@ fun Header() { } } -data class PostImage( - val imgRes: Int, - val description: String -) -@OptIn(ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class) +@OptIn(ExperimentalFoundationApi::class) @Composable fun PostImageView( postId: String, - images: List, + images: List, ) { - val sharedTransitionScope = LocalSharedTransitionScope.current - val animatedContentScope = LocalAnimatedContentScope.current val pagerState = rememberPagerState(pageCount = { images.size }) - with(sharedTransitionScope) { - Column { - HorizontalPager( - state = pagerState, + Column { + HorizontalPager( + state = pagerState, + modifier = Modifier + .weight(1f) + .fillMaxWidth(), + ) { page -> + val image = images[page] + AsyncImage( + image, + contentDescription = "Image", + contentScale = ContentScale.Crop, modifier = Modifier - .weight(1f) - .fillMaxWidth() - ) { page -> - Image( - painter = painterResource(id = images[page].imgRes), - contentDescription = images[page].description, - contentScale = ContentScale.Crop, - modifier = Modifier.Companion - .sharedElement( - sharedTransitionScope.rememberSharedContentState(key = "image-$postId"), - animatedVisibilityScope = animatedContentScope - ) - .fillMaxSize() - ) - } + .fillMaxSize() + ) + } - // Indicator container - Row( - modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - images.forEachIndexed { index, _ -> - Box( - modifier = Modifier - .size(8.dp) - .clip(CircleShape) + // Indicator container + Row( + modifier = Modifier + .padding(8.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + images.forEachIndexed { index, _ -> + Box( + modifier = Modifier + .size(8.dp) + .clip(CircleShape) - .background( - if (pagerState.currentPage == index) Color.Red else Color.Gray.copy( - alpha = 0.5f - ) + .background( + if (pagerState.currentPage == index) Color.Red else Color.Gray.copy( + alpha = 0.5f ) - .padding(4.dp) + ) + .padding(4.dp) - ) - Spacer(modifier = Modifier.width(8.dp)) - } + ) + Spacer(modifier = Modifier.width(8.dp)) } } } + } @OptIn(ExperimentalSharedTransitionApi::class) @Composable fun PostDetails( postId: String, + momentItem: MomentItem? ) { - val sharedTransitionScope = LocalSharedTransitionScope.current - val animatedContentScope = LocalAnimatedContentScope.current - with(sharedTransitionScope) { - Column(modifier = Modifier.padding(16.dp)) { + momentItem?.let { + Column(modifier = Modifier.padding(16.dp)) { - Text(text = "By strongarming Ducati into giving him the factory seat.Marquez effectively …", fontSize = 16.sp, fontWeight = FontWeight.Bold, modifier = Modifier.Companion.sharedElement( - sharedTransitionScope.rememberSharedContentState(key = "text-$postId"), - animatedVisibilityScope = animatedContentScope - )) - Text(text = "12-11 发布") - Spacer(modifier = Modifier.height(8.dp)) - Text(text = "共231条评论") - } -} -} - -fun MakeMockComments(): List { - return listOf( - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = listOf( - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ) + Text( + text = momentItem.momentTextContent, + fontSize = 16.sp, + fontWeight = FontWeight.Bold, ) - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ), - Comment( - name = "Diego Morata", - comment = "这里太适合骑行了", - date = "3 days ago", - likes = 200, - replies = emptyList() - ) - ) + Text(text = "12-11 发布") + Spacer(modifier = Modifier.height(8.dp)) + Text(text = "共231条评论") + } + } + + } @Composable fun CommentsSection( + lazyPagingItems: LazyPagingItems, scrollState: LazyListState = rememberLazyListState(), onWillCollapse: (Boolean) -> Unit ) { - val items = MakeMockComments() LazyColumn( state = scrollState, modifier = Modifier .padding(start = 16.dp, end = 16.dp) .fillMaxHeight() ) { - items(items) { comment -> - CommentItem(comment) + items(lazyPagingItems.itemCount) { idx -> + val item = lazyPagingItems[idx] ?: return@items + CommentItem(item) } } @@ -437,14 +313,6 @@ fun CommentsSection( } } -data class Comment( - val name: String, - val comment: String, - val date: String, - val likes: Int, - val replies: List -) - @Composable fun CommentItem(comment: Comment) { @@ -485,6 +353,21 @@ fun CommentItem(comment: Comment) { @OptIn(ExperimentalMaterial3Api::class) @Composable fun BottomNavigationBar() { + val systemUiController = rememberSystemUiController() + var showCommentModal by remember { mutableStateOf(false) } + if (showCommentModal) { + ModalBottomSheet( + onDismissRequest = { showCommentModal = false }, + containerColor = Color.White, + sheetState = rememberModalBottomSheetState( + skipPartiallyExpanded = true + ), + dragHandle = {}, + shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), + ) { + EditCommentBottomModal() + } + } Column( modifier = Modifier.background(Color.White) ) { @@ -503,6 +386,9 @@ fun BottomNavigationBar() { .weight(1f) .height(31.dp) .padding(8.dp) + .noRippleClickable { + showCommentModal = true + } ) { Row( verticalAlignment = Alignment.CenterVertically