mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 21:07:04 +05:30
common: delegate comment parsing to platforms
This commit is contained in:
parent
b0c3af7883
commit
5749b98b23
5 changed files with 28 additions and 14 deletions
|
@ -22,6 +22,10 @@ dependencies {
|
||||||
implementation(libs.androidx.lifecycle.compose)
|
implementation(libs.androidx.lifecycle.compose)
|
||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation(libs.androidx.paging.compose)
|
implementation(libs.androidx.paging.compose)
|
||||||
|
implementation(libs.compose.richtext.markdown)
|
||||||
|
implementation(libs.compose.richtext.material)
|
||||||
|
implementation(libs.compose.richtext.ui)
|
||||||
|
implementation(libs.copydown)
|
||||||
implementation(libs.dagger.hilt.android)
|
implementation(libs.dagger.hilt.android)
|
||||||
implementation(libs.sqldelight.extensions.coroutines)
|
implementation(libs.sqldelight.extensions.coroutines)
|
||||||
implementation(libs.kotlinx.serialization.json)
|
implementation(libs.kotlinx.serialization.json)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package dev.msfjarvis.claw.android.ui
|
package dev.msfjarvis.claw.android.ui
|
||||||
|
|
||||||
import android.text.Html
|
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
@ -29,10 +28,13 @@ import com.google.accompanist.insets.ProvideWindowInsets
|
||||||
import com.google.accompanist.insets.navigationBarsPadding
|
import com.google.accompanist.insets.navigationBarsPadding
|
||||||
import com.google.accompanist.insets.statusBarsPadding
|
import com.google.accompanist.insets.statusBarsPadding
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
|
import com.halilibo.richtext.markdown.Markdown
|
||||||
|
import com.halilibo.richtext.ui.material.MaterialRichText
|
||||||
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
|
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
|
||||||
import dev.msfjarvis.claw.common.comments.CommentsPage
|
import dev.msfjarvis.claw.common.comments.CommentsPage
|
||||||
import dev.msfjarvis.claw.common.theme.LobstersTheme
|
import dev.msfjarvis.claw.common.theme.LobstersTheme
|
||||||
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
||||||
|
import io.github.furstenheim.CopyDown
|
||||||
|
|
||||||
private const val ScrollDelta = 50
|
private const val ScrollDelta = 50
|
||||||
|
|
||||||
|
@ -42,6 +44,7 @@ fun LobstersApp(
|
||||||
viewModel: ClawViewModel = viewModel(),
|
viewModel: ClawViewModel = viewModel(),
|
||||||
urlLauncher: UrlLauncher,
|
urlLauncher: UrlLauncher,
|
||||||
) {
|
) {
|
||||||
|
val copydown = remember { CopyDown() }
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
val scaffoldState = rememberScaffoldState()
|
val scaffoldState = rememberScaffoldState()
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
|
@ -102,7 +105,10 @@ fun LobstersApp(
|
||||||
CommentsPage(
|
CommentsPage(
|
||||||
postId = requireNotNull(backStackEntry.arguments?.getString("postId")),
|
postId = requireNotNull(backStackEntry.arguments?.getString("postId")),
|
||||||
getDetails = viewModel::getPostComments,
|
getDetails = viewModel::getPostComments,
|
||||||
parseHtml = { source -> Html.fromHtml(source).toString().trim() },
|
renderMarkdown = { source, modifier ->
|
||||||
|
val markdown = copydown.convert(source)
|
||||||
|
MaterialRichText(modifier = modifier) { Markdown(markdown) }
|
||||||
|
},
|
||||||
paddingValues = paddingValues,
|
paddingValues = paddingValues,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,14 @@ import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.IntrinsicSize
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.material.Divider
|
import androidx.compose.material.Divider
|
||||||
import androidx.compose.material.Surface
|
import androidx.compose.material.Surface
|
||||||
import androidx.compose.material.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
@ -43,15 +41,15 @@ fun CommentsHeader(
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentEntry(
|
fun CommentEntry(
|
||||||
comment: Comment,
|
comment: Comment,
|
||||||
parseHtml: (String) -> String,
|
renderMarkdown: @Composable (comment: String, modifier: Modifier) -> Unit,
|
||||||
) {
|
) {
|
||||||
val indentLevel = comment.indentLevel.toInt() - 1
|
val indentLevel = comment.indentLevel.toInt() - 1
|
||||||
val startPadding = ((10 * indentLevel) + 16).dp
|
val startPadding = ((10 * indentLevel) + 16).dp
|
||||||
val text = parseHtml(comment.comment)
|
|
||||||
|
|
||||||
Divider(color = Color.Gray.copy(0.4f))
|
Divider(color = Color.Gray.copy(0.4f))
|
||||||
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
|
Row(modifier = Modifier.wrapContentHeight()) {
|
||||||
CommentTreeColors(indentLevel = indentLevel)
|
// Don't work without IntrinsicSize, which we cannot use with the Android markdown implementation
|
||||||
|
// CommentTreeColors(indentLevel = indentLevel)
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(start = startPadding, end = 8.dp, top = 4.dp, bottom = 4.dp)
|
modifier = Modifier.padding(start = startPadding, end = 8.dp, top = 4.dp, bottom = 4.dp)
|
||||||
) {
|
) {
|
||||||
|
@ -60,7 +58,7 @@ fun CommentEntry(
|
||||||
avatarUrl = "https://lobste.rs/${comment.user.avatarUrl}",
|
avatarUrl = "https://lobste.rs/${comment.user.avatarUrl}",
|
||||||
contentDescription = "Submitted by ${comment.user.username}",
|
contentDescription = "Submitted by ${comment.user.username}",
|
||||||
)
|
)
|
||||||
Text(text = text, modifier = Modifier.padding(top = 8.dp))
|
renderMarkdown(comment.comment, Modifier.padding(top = 8.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import dev.msfjarvis.lobsters.ui.comments.NetworkState
|
||||||
@Composable
|
@Composable
|
||||||
private fun CommentsPageInternal(
|
private fun CommentsPageInternal(
|
||||||
details: LobstersPostDetails,
|
details: LobstersPostDetails,
|
||||||
parseHtml: (String) -> String,
|
renderMarkdown: @Composable (comment: String, modifier: Modifier) -> Unit,
|
||||||
bottomPadding: Dp,
|
bottomPadding: Dp,
|
||||||
) {
|
) {
|
||||||
LazyColumn(Modifier.padding(bottom = bottomPadding)) {
|
LazyColumn(Modifier.padding(bottom = bottomPadding)) {
|
||||||
|
@ -36,7 +36,7 @@ private fun CommentsPageInternal(
|
||||||
|
|
||||||
item { Spacer(modifier = Modifier.height(8.dp)) }
|
item { Spacer(modifier = Modifier.height(8.dp)) }
|
||||||
|
|
||||||
items(details.comments) { item -> CommentEntry(item, parseHtml) }
|
items(details.comments) { item -> CommentEntry(item, renderMarkdown) }
|
||||||
|
|
||||||
item { Divider(color = Color.Gray.copy(0.4f)) }
|
item { Divider(color = Color.Gray.copy(0.4f)) }
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ private fun CommentsPageInternal(
|
||||||
fun CommentsPage(
|
fun CommentsPage(
|
||||||
postId: String,
|
postId: String,
|
||||||
getDetails: suspend (String) -> LobstersPostDetails,
|
getDetails: suspend (String) -> LobstersPostDetails,
|
||||||
parseHtml: (String) -> String,
|
renderMarkdown: @Composable (comment: String, modifier: Modifier) -> Unit,
|
||||||
paddingValues: PaddingValues,
|
paddingValues: PaddingValues,
|
||||||
) {
|
) {
|
||||||
var postDetails: NetworkState by remember { mutableStateOf(NetworkState.Loading) }
|
var postDetails: NetworkState by remember { mutableStateOf(NetworkState.Loading) }
|
||||||
|
@ -58,7 +58,7 @@ fun CommentsPage(
|
||||||
is NetworkState.Success<*> -> {
|
is NetworkState.Success<*> -> {
|
||||||
CommentsPageInternal(
|
CommentsPageInternal(
|
||||||
(postDetails as NetworkState.Success<LobstersPostDetails>).data,
|
(postDetails as NetworkState.Success<LobstersPostDetails>).data,
|
||||||
parseHtml,
|
renderMarkdown,
|
||||||
paddingValues.calculateBottomPadding(),
|
paddingValues.calculateBottomPadding(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ accompanist = "0.19.0"
|
||||||
aurora = "0.0.54-SNAPSHOT"
|
aurora = "0.0.54-SNAPSHOT"
|
||||||
coroutines = "1.5.2"
|
coroutines = "1.5.2"
|
||||||
hilt = "2.39"
|
hilt = "2.39"
|
||||||
|
richtext = "0.8.1"
|
||||||
serialization = "1.3.0"
|
serialization = "1.3.0"
|
||||||
sqldelight = "1.5.1"
|
sqldelight = "1.5.1"
|
||||||
|
|
||||||
|
@ -37,6 +38,11 @@ dagger-hilt-android = { module = "com.google.dagger:hilt-android", version.ref =
|
||||||
dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
|
dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
|
||||||
dagger-hilt-core = { module = "com.google.dagger:hilt-core", version.ref = "hilt" }
|
dagger-hilt-core = { module = "com.google.dagger:hilt-core", version.ref = "hilt" }
|
||||||
|
|
||||||
|
compose-richtext-ui = { module = "com.halilibo.compose-richtext:richtext-ui", version.ref = "richtext" }
|
||||||
|
compose-richtext-material = { module = "com.halilibo.compose-richtext:richtext-ui-material", version.ref = "richtext" }
|
||||||
|
compose-richtext-markdown = { module = "com.halilibo.compose-richtext:richtext-commonmark", version.ref = "richtext" }
|
||||||
|
copydown = "io.github.furstenheim:copy_down:1.0"
|
||||||
|
|
||||||
multiplatform-paging = "dev.msfjarvis.paging:multiplatform-paging:0.4.5-SNAPSHOT"
|
multiplatform-paging = "dev.msfjarvis.paging:multiplatform-paging:0.4.5-SNAPSHOT"
|
||||||
|
|
||||||
retrofit-lib = "com.squareup.retrofit2:retrofit:2.9.0"
|
retrofit-lib = "com.squareup.retrofit2:retrofit:2.9.0"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue