mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 15:17:05 +05:30
Update comments page UI (#305)
This commit is contained in:
parent
352769161b
commit
21ced135b6
9 changed files with 138 additions and 32 deletions
|
@ -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)
|
||||
|
|
9
common/src/androidMain/res/drawable/ic_web_24dp.xml
Normal file
9
common/src/androidMain/res/drawable/ic_web_24dp.xml
Normal 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>
|
|
@ -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}",
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -9,3 +9,5 @@ expect val heartIcon: Painter
|
|||
@Composable get
|
||||
expect val heartBorderIcon: Painter
|
||||
@Composable get
|
||||
expect val webIcon: Painter
|
||||
@Composable get
|
||||
|
|
|
@ -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")
|
||||
|
|
5
common/src/desktopMain/resources/web_black_24dp.svg
Normal file
5
common/src/desktopMain/resources/web_black_24dp.svg
Normal 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 |
Loading…
Add table
Add a link
Reference in a new issue