From 0db4e48613c35c8bfc0810409e7aec66bda2b121 Mon Sep 17 00:00:00 2001 From: Sasikanth Miriyampalli Date: Sun, 20 Feb 2022 15:23:26 +0530 Subject: [PATCH] Update `LobstersCard` UI (#296) --- .../msfjarvis/claw/android/ui/LobstersApp.kt | 10 +- .../claw/android/ui/decorations/ClawAppBar.kt | 3 + .../claw/android/ui/lists/NetworkPosts.kt | 3 + .../claw/common/comments/CommentEntry.kt | 4 +- .../claw/common/posts/LobstersCard.kt | 148 ++++++++---------- 5 files changed, 81 insertions(+), 87 deletions(-) diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt index 4198aa45..7252c32a 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt @@ -5,18 +5,20 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.SideEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -57,6 +59,7 @@ fun LobstersApp( val coroutineScope = rememberCoroutineScope() val postActions = rememberPostActions(urlLauncher, navController, viewModel) val currentDestination by currentNavigationDestination(navController) + val scrollBehavior = remember { TopAppBarDefaults.enterAlwaysScrollBehavior() } val networkPosts = viewModel.pagerFlow.collectAsLazyPagingItems() val savedPosts by viewModel.savedPosts.collectAsState(emptyList()) @@ -98,10 +101,12 @@ fun LobstersApp( } Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { ClawAppBar( - backgroundColor = systemBarsColor, modifier = Modifier.statusBarsPadding(), + backgroundColor = systemBarsColor, + scrollBehavior = scrollBehavior, ) }, bottomBar = { @@ -115,7 +120,6 @@ fun LobstersApp( NavHost( navController, startDestination = Destinations.startDestination.getRoute(), - modifier = Modifier.padding(top = 8.dp), ) { composable(Destinations.Hottest.getRoute()) { setWebUri("https://lobste.rs/") diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/ClawAppBar.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/ClawAppBar.kt index 648fbda7..dfd62abf 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/ClawAppBar.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/ClawAppBar.kt @@ -3,6 +3,7 @@ package dev.msfjarvis.claw.android.ui.decorations import androidx.compose.material3.SmallTopAppBar import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -13,6 +14,7 @@ import dev.msfjarvis.claw.android.R @Composable fun ClawAppBar( backgroundColor: Color, + scrollBehavior: TopAppBarScrollBehavior? = null, modifier: Modifier = Modifier, ) { SmallTopAppBar( @@ -24,5 +26,6 @@ fun ClawAppBar( }, modifier = modifier, colors = TopAppBarDefaults.smallTopAppBarColors(containerColor = backgroundColor), + scrollBehavior = scrollBehavior, ) } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/lists/NetworkPosts.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/lists/NetworkPosts.kt index bbddf245..bd3e0045 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/lists/NetworkPosts.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/lists/NetworkPosts.kt @@ -2,6 +2,7 @@ package dev.msfjarvis.claw.android.ui.lists import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.material.Divider import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.paging.compose.LazyPagingItems @@ -31,6 +32,8 @@ fun NetworkPosts( isSaved = isSaved, postActions = postActions, ) + + Divider() } } } diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentEntry.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentEntry.kt index fa1a02c8..1ae6e3b1 100644 --- a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentEntry.kt +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentEntry.kt @@ -20,7 +20,7 @@ import com.halilibo.richtext.markdown.Markdown import com.halilibo.richtext.ui.RichTextScope import com.halilibo.richtext.ui.material.MaterialRichText import dev.msfjarvis.claw.common.posts.PostDetails -import dev.msfjarvis.claw.common.posts.SubmitterName +import dev.msfjarvis.claw.common.posts.Submitter import dev.msfjarvis.claw.common.posts.toDbModel import dev.msfjarvis.claw.model.Comment import dev.msfjarvis.claw.model.LobstersPostDetails @@ -70,7 +70,7 @@ fun CommentEntry( bottom = 4.dp ) ) { - SubmitterName( + Submitter( text = comment.user.username, avatarUrl = "https://lobste.rs/${comment.user.avatarUrl}", contentDescription = "User avatar for ${comment.user.username}", diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersCard.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersCard.kt index 6fa2703f..985069f5 100644 --- a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersCard.kt +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersCard.kt @@ -5,17 +5,21 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement 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.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredSize -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Divider +import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -27,6 +31,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.google.accompanist.flowlayout.FlowRow @@ -46,32 +51,39 @@ fun LobstersCard( ) { var localSavedState by remember(post, isSaved) { mutableStateOf(isSaved) } Box(modifier = modifier.clickable { postActions.viewPost(post.url, post.commentsUrl) }) { - Column( - modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp).fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(4.dp), + Row( + modifier = Modifier.fillMaxWidth().padding(16.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, ) { PostDetails( + modifier = Modifier.weight(1f), post = post, ) - Row( - modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.End, + Column( + modifier = Modifier.weight(0.15f).fillMaxHeight(), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.CenterHorizontally, ) { SaveButton( isSaved = localSavedState, modifier = - Modifier.clickable { + Modifier.clickable( + role = Role.Button, + indication = rememberRipple(bounded = false, radius = 24.dp), + interactionSource = remember { MutableInteractionSource() }, + ) { localSavedState = !localSavedState postActions.toggleSave(post) }, ) - Spacer( - modifier = Modifier.width(8.dp), - ) + Divider() CommentsButton( modifier = Modifier.combinedClickable( + role = Role.Button, + indication = rememberRipple(bounded = false, radius = 24.dp), + interactionSource = remember { MutableInteractionSource() }, onClick = { postActions.viewComments(post.shortId) }, onLongClick = { postActions.viewCommentsPage(post.commentsUrl) }, ), @@ -82,22 +94,17 @@ fun LobstersCard( } @Composable -fun PostDetails( - post: SavedPost, -) { - PostTitle( - title = post.title, - modifier = Modifier.padding(bottom = 4.dp), - ) - TagRow( - tags = post.tags, - modifier = Modifier.padding(bottom = 4.dp), - ) - SubmitterName( - text = "Submitted by ${post.submitterName}", - avatarUrl = "https://lobste.rs/${post.submitterAvatarUrl}", - contentDescription = "User avatar for ${post.submitterName}", - ) +fun PostDetails(post: SavedPost, modifier: Modifier = Modifier) { + Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp)) { + PostTitle(title = post.title) + TagRow(tags = post.tags) + Spacer(Modifier.height(4.dp)) + Submitter( + text = "Submitted by ${post.submitterName}", + avatarUrl = "https://lobste.rs/${post.submitterAvatarUrl}", + contentDescription = "User avatar for ${post.submitterName}", + ) + } } @Composable @@ -107,13 +114,14 @@ fun PostTitle( ) { Text( text = title, - fontWeight = FontWeight.Bold, modifier = modifier, + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold ) } @Composable -fun SubmitterName( +fun Submitter( text: String, avatarUrl: String, contentDescription: String, @@ -122,42 +130,18 @@ fun SubmitterName( Row( modifier = modifier, verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), ) { - SubmitterAvatar( - avatarUrl = avatarUrl, + NetworkImage( + url = avatarUrl, contentDescription = contentDescription, + modifier = modifier.requiredSize(24.dp).clip(CircleShape), ) - SubmitterNameText( - text = text, - modifier = Modifier.padding(start = 4.dp), - ) + + Text(text = text, modifier = modifier, style = MaterialTheme.typography.bodyMedium) } } -@Composable -fun SubmitterAvatar( - avatarUrl: String, - contentDescription: String, - modifier: Modifier = Modifier, -) { - NetworkImage( - url = avatarUrl, - contentDescription = contentDescription, - modifier = modifier.requiredSize(24.dp).clip(CircleShape), - ) -} - -@Composable -fun SubmitterNameText( - text: String, - modifier: Modifier, -) { - Text( - text = text, - modifier = modifier, - ) -} - @Composable fun SaveButton( isSaved: Boolean, @@ -168,7 +152,7 @@ fun SaveButton( painter = if (saved) heartIcon else heartBorderIcon, tint = MaterialTheme.colorScheme.secondary, contentDescription = if (saved) "Remove from saved posts" else "Add to saved posts", - modifier = modifier, + modifier = modifier.padding(12.dp), ) } } @@ -181,7 +165,7 @@ fun CommentsButton( painter = commentIcon, tint = MaterialTheme.colorScheme.secondary, contentDescription = "Open comments", - modifier = modifier, + modifier = modifier.padding(12.dp), ) } @@ -190,25 +174,25 @@ fun TagRow( tags: List, modifier: Modifier = Modifier, ) { - Box( + FlowRow( modifier = modifier, - ) { - FlowRow( - mainAxisSpacing = 8.dp, - crossAxisSpacing = 8.dp, - ) { - tags.forEach { tag -> - Text( - text = tag, - modifier = - Modifier.background( - MaterialTheme.colorScheme.secondary.copy(alpha = 0.75f), - RoundedCornerShape(8.dp) - ) - .padding(vertical = 2.dp, horizontal = 6.dp), - color = MaterialTheme.colorScheme.onSecondary, - ) - } - } - } + mainAxisSpacing = 8.dp, + crossAxisSpacing = 8.dp, + ) { tags.forEach { tag -> TagText(tag) } } +} + +@Composable +fun TagText( + tag: String, + modifier: Modifier = Modifier, +) { + Text( + text = tag, + modifier = + Modifier.background(MaterialTheme.colorScheme.tertiaryContainer, RoundedCornerShape(50)) + .padding(vertical = 4.dp, horizontal = 12.dp) + .then(modifier), + color = MaterialTheme.colorScheme.onTertiaryContainer, + style = MaterialTheme.typography.labelLarge + ) }