feat: add comments ui
Signed-off-by: Aditya Wasan <adityawasan55@gmail.com>
This commit is contained in:
@@ -1,22 +1,46 @@
|
||||
package dev.msfjarvis.lobsters.ui.comments
|
||||
|
||||
import android.text.Html
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.msfjarvis.lobsters.model.Comment
|
||||
import dev.msfjarvis.lobsters.ui.posts.SubmitterAvatar
|
||||
|
||||
@Composable
|
||||
fun CommentEntry(
|
||||
comment: Comment,
|
||||
) {
|
||||
Row(modifier = Modifier.padding(start = (10 * (comment.indentLevel.toFloat() - 1)).dp)) {
|
||||
Text(
|
||||
text = buildAnnotatedString { @Suppress("DEPRECATION") Html.fromHtml(comment.comment) },
|
||||
)
|
||||
val indentLevel = comment.indentLevel.toInt() - 1
|
||||
val startPadding = ((10 * indentLevel) + 16).dp
|
||||
|
||||
Divider(color = Color.Gray.copy(0.4f))
|
||||
|
||||
Row(modifier = Modifier.padding(start = startPadding, end = 8.dp, top = 4.dp, bottom = 4.dp)) {
|
||||
// TODO: Compose currently does not support HTML spanned string
|
||||
val text = Html.fromHtml(comment.comment).toString().trim()
|
||||
|
||||
Column {
|
||||
Row {
|
||||
SubmitterAvatar(
|
||||
name = comment.user.username,
|
||||
avatarUrl = comment.user.avatarUrl,
|
||||
)
|
||||
Text(
|
||||
text = comment.user.username,
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
style = TextStyle(color = Color.DarkGray, fontWeight = FontWeight.Bold),
|
||||
)
|
||||
}
|
||||
Text(text = text, modifier = Modifier.padding(top = 8.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,110 @@
|
||||
package dev.msfjarvis.lobsters.ui.comments
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
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.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.msfjarvis.lobsters.model.LobstersPostDetails
|
||||
import dev.msfjarvis.lobsters.ui.posts.PostTitle
|
||||
import dev.msfjarvis.lobsters.ui.posts.SubmitterName
|
||||
import dev.msfjarvis.lobsters.ui.posts.TagRow
|
||||
|
||||
@Composable
|
||||
private fun CommentsPageInternal(
|
||||
details: LobstersPostDetails,
|
||||
private fun CommentsPageInternal(details: LobstersPostDetails, bottomPadding: Dp) {
|
||||
LazyColumn(Modifier.padding(bottom = bottomPadding)) {
|
||||
item { CommentsHeader(postDetails = details) }
|
||||
|
||||
item { Spacer(modifier = Modifier.height(8.dp)) }
|
||||
|
||||
items(details.comments) { CommentEntry(it) }
|
||||
|
||||
item { Divider(color = Color.Gray.copy(0.4f)) }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@Composable
|
||||
fun CommentsPage(
|
||||
postId: String,
|
||||
paddingValues: PaddingValues,
|
||||
getDetails: suspend (String) -> LobstersPostDetails
|
||||
) {
|
||||
LazyColumn { items(details.comments) { CommentEntry(it) } }
|
||||
var postDetails: NetworkState by remember { mutableStateOf(NetworkState.Loading) }
|
||||
|
||||
LaunchedEffect(postId) { postDetails = NetworkState.Success(getDetails(postId)) }
|
||||
|
||||
when (postDetails) {
|
||||
is NetworkState.Success<*> -> {
|
||||
CommentsPageInternal(
|
||||
(postDetails as NetworkState.Success<LobstersPostDetails>).data,
|
||||
paddingValues.calculateBottomPadding(),
|
||||
)
|
||||
}
|
||||
is NetworkState.Error -> TODO("Handle no network scenario")
|
||||
NetworkState.Loading -> ProgressBar(paddingValues.calculateBottomPadding())
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CommentsPage(postId: String, getDetails: suspend (String) -> LobstersPostDetails) {
|
||||
private fun CommentsHeader(postDetails: LobstersPostDetails) {
|
||||
Surface {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp),
|
||||
) {
|
||||
PostTitle(
|
||||
title = postDetails.title,
|
||||
modifier = Modifier.padding(bottom = 4.dp),
|
||||
)
|
||||
Row {
|
||||
TagRow(
|
||||
tags = postDetails.tags,
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
|
||||
if (postDetails.description.isNotEmpty()) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(text = postDetails.description)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
}
|
||||
|
||||
SubmitterName(
|
||||
name = postDetails.submitter.username,
|
||||
avatarUrl = postDetails.submitter.avatarUrl,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProgressBar(bottomPadding: Dp) {
|
||||
Box(
|
||||
modifier = Modifier.padding(bottom = bottomPadding).fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) { CircularProgressIndicator(color = MaterialTheme.colors.secondary) }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.msfjarvis.lobsters.ui.comments
|
||||
|
||||
sealed class NetworkState {
|
||||
class Success<T>(val data: T) : NetworkState()
|
||||
class Error(val message: String) : NetworkState()
|
||||
object Loading : NetworkState()
|
||||
}
|
||||
@@ -123,6 +123,7 @@ fun LobstersApp() {
|
||||
) { backStackEntry ->
|
||||
CommentsPage(
|
||||
postId = requireNotNull(backStackEntry.arguments?.getString("postId")),
|
||||
paddingValues = innerPadding,
|
||||
getDetails = viewModel::getPostDetails,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user