Update comments page UI (#305)

This commit is contained in:
Sasikanth Miriyampalli 2022-02-28 21:14:49 +05:30 committed by GitHub
parent 352769161b
commit 21ced135b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 138 additions and 32 deletions

View file

@ -10,3 +10,5 @@ actual val heartIcon
@Composable get() = painterResource(R.drawable.ic_favorite_24dp)
actual val heartBorderIcon
@Composable get() = painterResource(R.drawable.ic_favorite_border_24dp)
actual val webIcon
@Composable get() = painterResource(R.drawable.ic_web_24dp)

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-0.61 0.08,-1.21 0.21,-1.78L8.99,15v1c0,1.1 0.9,2 2,2v1.93C7.06,19.43 4,16.07 4,12zM17.89,17.4c-0.26,-0.81 -1,-1.4 -1.9,-1.4h-1v-3c0,-0.55 -0.45,-1 -1,-1h-6v-2h2c0.55,0 1,-0.45 1,-1L10.99,7h2c1.1,0 2,-0.9 2,-2v-0.41C17.92,5.77 20,8.65 20,12c0,2.08 -0.81,3.98 -2.11,5.4z" />
</vector>

View file

@ -1,26 +1,35 @@
package dev.msfjarvis.claw.common.comments
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.LocalContentColor
import androidx.compose.material.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
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.PostActions
import dev.msfjarvis.claw.common.posts.PostTitle
import dev.msfjarvis.claw.common.posts.Submitter
import dev.msfjarvis.claw.common.posts.toDbModel
import dev.msfjarvis.claw.common.ui.Divider
import dev.msfjarvis.claw.common.posts.TagRow
import dev.msfjarvis.claw.common.res.webIcon
import dev.msfjarvis.claw.model.Comment
import dev.msfjarvis.claw.model.LobstersPostDetails
@ -38,17 +47,65 @@ fun ThemedRichText(
@Composable
fun CommentsHeader(
postDetails: LobstersPostDetails,
postActions: PostActions,
) {
val htmlConverter = LocalHTMLConverter.current
Surface {
Surface(color = MaterialTheme.colorScheme.background) {
Column(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(4.dp),
modifier = Modifier.padding(16.dp).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
PostDetails(
post = postDetails.toDbModel(),
PostTitle(title = postDetails.title)
TagRow(tags = postDetails.tags)
Spacer(Modifier.height(4.dp))
if (postDetails.url.isNotBlank()) {
PostLink(
link = postDetails.url,
modifier =
Modifier.clickable { postActions.viewPost(postDetails.url, postDetails.commentsUrl) }
)
Spacer(Modifier.height(4.dp))
}
if (postDetails.description.isNotBlank()) {
ThemedRichText { Markdown(htmlConverter.convertHTMLToMarkdown(postDetails.description)) }
Spacer(Modifier.height(4.dp))
}
Submitter(
text = "Submitted by ${postDetails.submitter.username}",
avatarUrl = "https://lobste.rs/${postDetails.submitter.avatarUrl}",
contentDescription = "User avatar for ${postDetails.submitter.username}",
)
}
}
}
@Composable
fun PostLink(
link: String,
modifier: Modifier = Modifier,
) {
Box(
modifier.background(
color = MaterialTheme.colorScheme.secondary,
shape = RoundedCornerShape(8.dp)
)
) {
Row(modifier = Modifier.padding(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp)) {
Icon(
painter = webIcon,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSecondary
)
Text(
text = link,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
color = MaterialTheme.colorScheme.onSecondary,
style = MaterialTheme.typography.labelLarge,
)
ThemedRichText { Markdown(htmlConverter.convertHTMLToMarkdown(postDetails.description)) }
}
}
}
@ -58,17 +115,13 @@ fun CommentEntry(
comment: Comment,
) {
val htmlConverter = LocalHTMLConverter.current
Divider()
Row(modifier = Modifier.wrapContentHeight()) {
Column(
modifier =
Modifier.padding(
start = (comment.indentLevel * 12).dp,
end = 8.dp,
top = 4.dp,
bottom = 4.dp
)
) {
Box(
modifier =
Modifier.fillMaxWidth()
.background(MaterialTheme.colorScheme.background)
.padding(start = (comment.indentLevel * 16).dp, end = 16.dp, top = 16.dp, bottom = 16.dp),
) {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Submitter(
text = comment.user.username,
avatarUrl = "https://lobste.rs/${comment.user.avatarUrl}",

View file

@ -1,36 +1,66 @@
package dev.msfjarvis.claw.common.comments
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Surface
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.common.NetworkState
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.ui.Divider
import dev.msfjarvis.claw.model.LobstersPostDetails
@Composable
private fun CommentsPageInternal(
details: LobstersPostDetails,
postActions: PostActions,
modifier: Modifier = Modifier,
) {
LazyColumn(modifier) {
item { CommentsHeader(postDetails = details) }
Surface(color = MaterialTheme.colorScheme.surfaceVariant) {
LazyColumn(modifier = modifier, contentPadding = PaddingValues(bottom = 24.dp)) {
item { CommentsHeader(postDetails = details, postActions = postActions) }
item { Spacer(modifier = Modifier.height(8.dp)) }
if (details.commentCount > 0) {
item {
Text(
text = "Comments",
style = MaterialTheme.typography.labelLarge,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)
)
}
items(details.comments) { item -> CommentEntry(item) }
item { Divider() }
itemsIndexed(details.comments) { index, item ->
if (index != 0) {
Divider()
}
CommentEntry(item)
}
} else {
item {
Text(
text = "No Comments",
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.fillMaxWidth().padding(16.dp),
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center
)
}
}
}
}
}
@ -39,6 +69,7 @@ private fun CommentsPageInternal(
fun CommentsPage(
postId: String,
getDetails: suspend (String) -> LobstersPostDetails,
postActions: PostActions,
modifier: Modifier = Modifier,
) {
val postDetails by
@ -50,7 +81,8 @@ fun CommentsPage(
is NetworkState.Success<*> -> {
CommentsPageInternal(
(postDetails as NetworkState.Success<LobstersPostDetails>).data,
modifier,
postActions,
modifier.fillMaxSize(),
)
}
is NetworkState.Error -> TODO("Handle no network scenario")

View file

@ -140,7 +140,7 @@ fun Submitter(
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
NetworkImage(
url = avatarUrl,

View file

@ -9,3 +9,5 @@ expect val heartIcon: Painter
@Composable get
expect val heartBorderIcon: Painter
@Composable get
expect val webIcon: Painter
@Composable get

View file

@ -9,3 +9,5 @@ actual val heartIcon
@Composable get() = painterResource("favorite_black_24dp.svg")
actual val heartBorderIcon
@Composable get() = painterResource("favorite_border_black_24dp.svg")
actual val webIcon
@Composable get() = painterResource("web_black_24dp.svg")

View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-.61.08-1.21.21-1.78L8.99 15v1c0 1.1.9 2 2 2v1.93C7.06 19.43 4 16.07 4 12zm13.89 5.4c-.26-.81-1-1.4-1.9-1.4h-1v-3c0-.55-.45-1-1-1h-6v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41C17.92 5.77 20 8.65 20 12c0 2.08-.81 3.98-2.11 5.4z" />
</svg>

After

Width:  |  Height:  |  Size: 474 B