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 b31fa94a..e5b8b5f9 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
@@ -165,6 +165,7 @@ fun LobstersApp(
postId = postId,
getDetails = viewModel::getPostComments,
modifier = Modifier.navigationBarsPadding(),
+ postActions = postActions
)
}
}
diff --git a/common/src/androidMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt b/common/src/androidMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
index 71f1f399..e93e6314 100644
--- a/common/src/androidMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
+++ b/common/src/androidMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
@@ -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)
diff --git a/common/src/androidMain/res/drawable/ic_web_24dp.xml b/common/src/androidMain/res/drawable/ic_web_24dp.xml
new file mode 100644
index 00000000..d9911a76
--- /dev/null
+++ b/common/src/androidMain/res/drawable/ic_web_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
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 68958ff8..34d3dae5 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
@@ -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}",
diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/Comments.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/Comments.kt
index 9b834745..03498ab1 100644
--- a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/Comments.kt
+++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/Comments.kt
@@ -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).data,
- modifier,
+ postActions,
+ modifier.fillMaxSize(),
)
}
is NetworkState.Error -> TODO("Handle no network scenario")
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 b9e7eb06..92174ba6 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
@@ -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,
diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
index 39ad8f95..6bdb7e25 100644
--- a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
+++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
@@ -9,3 +9,5 @@ expect val heartIcon: Painter
@Composable get
expect val heartBorderIcon: Painter
@Composable get
+expect val webIcon: Painter
+ @Composable get
diff --git a/common/src/desktopMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt b/common/src/desktopMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
index 8a1f79fc..c7e1519e 100644
--- a/common/src/desktopMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
+++ b/common/src/desktopMain/kotlin/dev/msfjarvis/claw/common/res/drawable.kt
@@ -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")
diff --git a/common/src/desktopMain/resources/web_black_24dp.svg b/common/src/desktopMain/resources/web_black_24dp.svg
new file mode 100644
index 00000000..ff472dea
--- /dev/null
+++ b/common/src/desktopMain/resources/web_black_24dp.svg
@@ -0,0 +1,5 @@
+