Display item content in ItemScreen

This commit is contained in:
Shinokuni 2024-04-10 16:56:30 +02:00
parent da51f504e4
commit c071426bbd
4 changed files with 188 additions and 12 deletions

View File

@ -1,5 +1,8 @@
package com.readrops.app.compose.item
import android.util.Base64
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
@ -20,20 +23,24 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import cafe.adriel.voyager.koin.getScreenModel
import coil.compose.AsyncImage
import com.readrops.api.utils.DateUtils
import com.readrops.app.compose.R
import com.readrops.app.compose.util.Utils
import com.readrops.app.compose.util.components.AndroidScreen
import com.readrops.app.compose.util.components.CenteredProgressIndicator
import com.readrops.app.compose.util.components.IconText
import com.readrops.app.compose.util.theme.MediumSpacer
import com.readrops.app.compose.util.theme.ShortSpacer
import com.readrops.app.compose.util.theme.VeryShortSpacer
import com.readrops.app.compose.util.theme.spacing
import com.readrops.db.pojo.ItemWithFeed
import org.koin.core.parameter.parametersOf
@ -45,12 +52,17 @@ class ItemScreen(
@Composable
override fun Content() {
val context = LocalContext.current
val screenModel =
getScreenModel<ItemScreenModel>(parameters = { parametersOf(itemId) })
val scrollState = rememberScrollState()
val state by screenModel.state.collectAsStateWithLifecycle()
val primaryColor = MaterialTheme.colorScheme.primary
val backgroundColor = MaterialTheme.colorScheme.background
val onBackgroundColor = MaterialTheme.colorScheme.onBackground
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
@ -75,10 +87,47 @@ class ItemScreen(
SimpleTitle(
itemWithFeed = itemWithFeed,
titleColor = tintColor,
tintColor = tintColor,
baseColor = MaterialTheme.colorScheme.onBackground
accentColor = tintColor,
baseColor = MaterialTheme.colorScheme.onBackground,
bottomPadding = true
)
}
AndroidView(
factory = { context ->
WebView(context).apply {
settings.javaScriptEnabled = true
webViewClient = WebViewClient()
settings.builtInZoomControls = true
settings.displayZoomControls = false
settings.setSupportZoom(false)
isVerticalScrollBarEnabled = false
setBackgroundColor(backgroundColor.toArgb())
}
},
update = { webView ->
val tintColor = if (itemWithFeed.bgColor != 0) {
Color(itemWithFeed.bgColor)
} else {
primaryColor
}
val string = context.getString(
R.string.webview_html_template,
Utils.getCssColor(tintColor.toArgb()),
Utils.getCssColor(onBackgroundColor.toArgb()),
Utils.getCssColor(backgroundColor.toArgb()),
screenModel.formatText()
)
val data =
Base64.encodeToString(string.encodeToByteArray(), Base64.NO_PADDING)
webView.loadData(data, "text/html; charset=utf-8", "base64")
}
)
} else {
CenteredProgressIndicator()
}
@ -91,7 +140,7 @@ fun BackgroundTitle(
itemWithFeed: ItemWithFeed,
) {
val onScrimColor = Color.White.copy(alpha = 0.85f)
val tintColor = if (itemWithFeed.bgColor != 0) {
val accentColor = if (itemWithFeed.bgColor != 0) {
Color(itemWithFeed.bgColor)
} else {
onScrimColor
@ -114,32 +163,42 @@ fun BackgroundTitle(
)
Surface(
color = Color.Black.copy(alpha = 0.7f),
color = Color.Black.copy(alpha = 0.6f),
modifier = Modifier
.fillMaxSize()
) {
SimpleTitle(
itemWithFeed = itemWithFeed,
titleColor = onScrimColor,
tintColor = tintColor,
baseColor = onScrimColor
accentColor = accentColor,
baseColor = onScrimColor,
bottomPadding = true
)
}
}
MediumSpacer()
}
@Composable
fun SimpleTitle(
itemWithFeed: ItemWithFeed,
titleColor: Color,
tintColor: Color,
baseColor: Color
accentColor: Color,
baseColor: Color,
bottomPadding: Boolean,
) {
val item = itemWithFeed.item
val spacing = MaterialTheme.spacing.mediumSpacing
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(MaterialTheme.spacing.mediumSpacing)
modifier = Modifier.padding(
start = spacing,
end = spacing,
top = spacing,
bottom = if (bottomPadding) spacing else 0.dp
)
) {
AsyncImage(
model = itemWithFeed.feedIconUrl,
@ -151,7 +210,7 @@ fun SimpleTitle(
.clip(CircleShape)
)
VeryShortSpacer()
ShortSpacer()
Text(
text = itemWithFeed.feedName,
@ -177,7 +236,7 @@ fun SimpleTitle(
text = itemWithFeed.item.author!!,
style = MaterialTheme.typography.labelMedium,
color = baseColor,
tint = tintColor
tint = accentColor
)
}

View File

@ -9,6 +9,8 @@ import com.readrops.db.queries.ItemSelectionQueryBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.jsoup.Jsoup
import org.jsoup.parser.Parser
class ItemScreenModel(
private val database: Database,
@ -27,6 +29,18 @@ class ItemScreenModel(
}
}
fun formatText(): String {
val itemWithFeed = state.value.itemWithFeed!!
val document = if (itemWithFeed.websiteUrl != null) Jsoup.parse(
Parser.unescapeEntities(itemWithFeed.item.text, false), itemWithFeed.websiteUrl
) else Jsoup.parse(
Parser.unescapeEntities(itemWithFeed.item.text, false)
)
document.select("div,span").forEach { it.clearAttributes() }
return document.body().html()
}
}
@Stable

View File

@ -1,5 +1,9 @@
package com.readrops.app.compose.util
import android.graphics.Color
import androidx.annotation.ColorInt
import java.util.Locale
object Utils {
private const val AVERAGE_WORDS_PER_MINUTE = 250
@ -8,4 +12,14 @@ object Utils {
val nbWords = value.split("\\s+").size
return nbWords.toDouble() / AVERAGE_WORDS_PER_MINUTE
}
fun getCssColor(@ColorInt color: Int): String {
return String.format(
Locale.US, "rgba(%d,%d,%d,%.2f)",
Color.red(color),
Color.green(color),
Color.blue(color),
Color.alpha(color) / 255.0
)
}
}

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="webview_html_template" translatable="false"><![CDATA[
<!DOCTYPE html>
<html>
<head>
<meta charset=\"UTF-8\">
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
<style type=\"text/css\">
/*
%1$s: accent color
%2$s: text color
%3$s: background color
*/
a:link, a:active, a:hover { color: %1$s }
* {
word-wrap: break-word !important;
line-height: 1.4;
}
body, blockquote, img, iframe, video, div, table, tbody, tr, td, blockquote, p, em, b, span {
max-width: 100%% !important;
}
body {
margin-left: 3%%;
margin-right: 3%%;
color: %2$s;
background-color: %3$s;
}
figure, img, iframe, video {
margin: 0px;
display: inline;
height: auto;
max-width: 100%%;
}
iframe {
margin-top: 10px;
margin-bottom: 10px;
}
h1, p, div {
margin-top: 0px;
}
pre, code {
color: #FFFFFF;
background-color: #757575;
}
pre {
padding: 6px;
overflow: auto;
border-radius: 4px;
}
code {
padding: 2px;
border-radius: 2px;
}
pre > code {
padding: 0px;
border-radius: 0px;
}
figcaption {
font-style: italic;
font-size: small;
overflow: auto;
text-align: center;
padding-left: 3px;
padding-right: 3px;
padding-bottom: 10px;
}
</style>
</head>
<body>
%4$s
</body>
</html>]]></string>
</resources>