Extract views from ItemScreen
This commit is contained in:
parent
91378f0a54
commit
02a3f82b72
@ -1,12 +1,7 @@
|
|||||||
package com.readrops.app.compose.item
|
package com.readrops.app.compose.item
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Base64
|
|
||||||
import android.webkit.WebView
|
|
||||||
import android.webkit.WebViewClient
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@ -33,12 +28,10 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.toArgb
|
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.ComposeView
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@ -46,15 +39,14 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.core.widget.NestedScrollView
|
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cafe.adriel.voyager.koin.getScreenModel
|
import cafe.adriel.voyager.koin.getScreenModel
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.readrops.api.utils.DateUtils
|
import com.readrops.api.utils.DateUtils
|
||||||
import com.readrops.app.compose.R
|
import com.readrops.app.compose.R
|
||||||
import com.readrops.app.compose.util.Utils
|
import com.readrops.app.compose.item.view.ItemNestedScrollView
|
||||||
|
import com.readrops.app.compose.item.view.ItemWebView
|
||||||
import com.readrops.app.compose.util.components.AndroidScreen
|
import com.readrops.app.compose.util.components.AndroidScreen
|
||||||
import com.readrops.app.compose.util.components.CenteredProgressIndicator
|
import com.readrops.app.compose.util.components.CenteredProgressIndicator
|
||||||
import com.readrops.app.compose.util.components.IconText
|
import com.readrops.app.compose.util.components.IconText
|
||||||
@ -69,7 +61,6 @@ class ItemScreen(
|
|||||||
private val itemId: Int
|
private val itemId: Int
|
||||||
) : AndroidScreen() {
|
) : AndroidScreen() {
|
||||||
|
|
||||||
@SuppressLint("ResourceType", "SetJavaScriptEnabled")
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
@ -150,92 +141,44 @@ class ItemScreen(
|
|||||||
) {
|
) {
|
||||||
AndroidView(
|
AndroidView(
|
||||||
factory = { context ->
|
factory = { context ->
|
||||||
NestedScrollView(context).apply {
|
ItemNestedScrollView(
|
||||||
val treeObserver = viewTreeObserver
|
context = context,
|
||||||
treeObserver.addOnGlobalLayoutListener {
|
onGlobalLayoutListener = { viewHeight, contentHeight ->
|
||||||
val viewHeight = this.measuredHeight
|
|
||||||
val contentHeight = getChildAt(0).height
|
|
||||||
|
|
||||||
isScrollable = viewHeight - contentHeight < 0
|
isScrollable = viewHeight - contentHeight < 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
) {
|
||||||
addView(
|
if (item.imageLink != null) {
|
||||||
RelativeLayout(context).apply {
|
BackgroundTitle(
|
||||||
ViewCompat.setNestedScrollingEnabled(this, true)
|
itemWithFeed = itemWithFeed
|
||||||
|
)
|
||||||
val composeView = ComposeView(context).apply {
|
} else {
|
||||||
id = 1
|
val tintColor = if (itemWithFeed.bgColor != 0) {
|
||||||
|
Color(itemWithFeed.bgColor)
|
||||||
setContent {
|
} else {
|
||||||
if (item.imageLink != null) {
|
MaterialTheme.colorScheme.onBackground
|
||||||
BackgroundTitle(
|
|
||||||
itemWithFeed = itemWithFeed
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val tintColor =
|
|
||||||
if (itemWithFeed.bgColor != 0) {
|
|
||||||
Color(itemWithFeed.bgColor)
|
|
||||||
} else {
|
|
||||||
MaterialTheme.colorScheme.onBackground
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTitle(
|
|
||||||
itemWithFeed = itemWithFeed,
|
|
||||||
titleColor = tintColor,
|
|
||||||
accentColor = tintColor,
|
|
||||||
baseColor = MaterialTheme.colorScheme.onBackground,
|
|
||||||
bottomPadding = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val webView = WebView(context).apply {
|
|
||||||
id = 2
|
|
||||||
ViewCompat.setNestedScrollingEnabled(this, true)
|
|
||||||
|
|
||||||
settings.javaScriptEnabled = true
|
|
||||||
webViewClient = WebViewClient()
|
|
||||||
|
|
||||||
settings.builtInZoomControls = true
|
|
||||||
settings.displayZoomControls = false
|
|
||||||
settings.setSupportZoom(false)
|
|
||||||
|
|
||||||
isVerticalScrollBarEnabled = false
|
|
||||||
setBackgroundColor(backgroundColor.toArgb())
|
|
||||||
}
|
|
||||||
|
|
||||||
val params = RelativeLayout.LayoutParams(
|
|
||||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
||||||
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
)
|
|
||||||
|
|
||||||
params.addRule(RelativeLayout.BELOW, composeView.id)
|
|
||||||
webView.layoutParams = params
|
|
||||||
|
|
||||||
addView(composeView)
|
|
||||||
addView(webView)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
SimpleTitle(
|
||||||
|
itemWithFeed = itemWithFeed,
|
||||||
|
titleColor = tintColor,
|
||||||
|
accentColor = tintColor,
|
||||||
|
baseColor = MaterialTheme.colorScheme.onBackground,
|
||||||
|
bottomPadding = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update = { nestedScrollView ->
|
update = { nestedScrollView ->
|
||||||
val relativeLayout =
|
val relativeLayout =
|
||||||
(nestedScrollView.children.toList()[0] as RelativeLayout)
|
(nestedScrollView.children.toList()[0] as RelativeLayout)
|
||||||
val webView = relativeLayout.children.toList()[1] as WebView
|
val webView = relativeLayout.children.toList()[1] as ItemWebView
|
||||||
|
|
||||||
val string = context.getString(
|
webView.loadText(
|
||||||
R.string.webview_html_template,
|
itemWithFeed = itemWithFeed,
|
||||||
Utils.getCssColor(accentColor.toArgb()),
|
accentColor = accentColor,
|
||||||
Utils.getCssColor(onBackgroundColor.toArgb()),
|
backgroundColor = backgroundColor,
|
||||||
Utils.getCssColor(backgroundColor.toArgb()),
|
onBackgroundColor = onBackgroundColor
|
||||||
screenModel.formatText()
|
|
||||||
)
|
)
|
||||||
val data =
|
|
||||||
Base64.encodeToString(string.encodeToByteArray(), Base64.NO_PADDING)
|
|
||||||
|
|
||||||
webView.loadData(data, "text/html; charset=utf-8", "base64")
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -326,7 +269,8 @@ fun SimpleTitle(
|
|||||||
Text(
|
Text(
|
||||||
text = itemWithFeed.feedName,
|
text = itemWithFeed.feedName,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
color = baseColor
|
color = baseColor,
|
||||||
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
|
|
||||||
ShortSpacer()
|
ShortSpacer()
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.readrops.app.compose.item.view
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.widget.NestedScrollView
|
||||||
|
|
||||||
|
@SuppressLint("ResourceType")
|
||||||
|
class ItemNestedScrollView(
|
||||||
|
context: Context,
|
||||||
|
onGlobalLayoutListener: (viewHeight: Int, contentHeight: Int) -> Unit,
|
||||||
|
composeViewContent: @Composable () -> Unit
|
||||||
|
) : NestedScrollView(context) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
addView(
|
||||||
|
RelativeLayout(context).apply {
|
||||||
|
ViewCompat.setNestedScrollingEnabled(this, true)
|
||||||
|
|
||||||
|
val composeView = ComposeView(context).apply {
|
||||||
|
id = 1
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
composeViewContent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val composeViewParams = RelativeLayout.LayoutParams(
|
||||||
|
LayoutParams.MATCH_PARENT,
|
||||||
|
LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
composeViewParams.addRule(RelativeLayout.CENTER_HORIZONTAL)
|
||||||
|
composeView.layoutParams = composeViewParams
|
||||||
|
|
||||||
|
val webView = ItemWebView(context).apply {
|
||||||
|
id = 2
|
||||||
|
ViewCompat.setNestedScrollingEnabled(this, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
val webViewParams = RelativeLayout.LayoutParams(
|
||||||
|
LayoutParams.MATCH_PARENT,
|
||||||
|
LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
|
||||||
|
webViewParams.addRule(RelativeLayout.BELOW, composeView.id)
|
||||||
|
webView.layoutParams = webViewParams
|
||||||
|
|
||||||
|
addView(composeView)
|
||||||
|
addView(webView)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
viewTreeObserver.addOnGlobalLayoutListener {
|
||||||
|
val viewHeight = this.measuredHeight
|
||||||
|
val contentHeight = getChildAt(0).height
|
||||||
|
|
||||||
|
onGlobalLayoutListener(viewHeight, contentHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.readrops.app.compose.item.view
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.Base64
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.toArgb
|
||||||
|
import com.readrops.app.compose.R
|
||||||
|
import com.readrops.app.compose.util.Utils
|
||||||
|
import com.readrops.db.pojo.ItemWithFeed
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.parser.Parser
|
||||||
|
|
||||||
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
|
class ItemWebView(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet?,
|
||||||
|
) : WebView(context, attrs) {
|
||||||
|
|
||||||
|
constructor(context: Context): this(context, null)
|
||||||
|
|
||||||
|
init {
|
||||||
|
settings.javaScriptEnabled = true
|
||||||
|
settings.builtInZoomControls = true
|
||||||
|
settings.displayZoomControls = false
|
||||||
|
settings.setSupportZoom(false)
|
||||||
|
|
||||||
|
webViewClient = WebViewClient()
|
||||||
|
isVerticalScrollBarEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadText(
|
||||||
|
itemWithFeed: ItemWithFeed,
|
||||||
|
accentColor: Color,
|
||||||
|
backgroundColor: Color,
|
||||||
|
onBackgroundColor: Color
|
||||||
|
) {
|
||||||
|
val string = context.getString(
|
||||||
|
R.string.webview_html_template,
|
||||||
|
Utils.getCssColor(accentColor.toArgb()),
|
||||||
|
Utils.getCssColor(onBackgroundColor.toArgb()),
|
||||||
|
Utils.getCssColor(backgroundColor.toArgb()),
|
||||||
|
formatText(itemWithFeed)
|
||||||
|
)
|
||||||
|
|
||||||
|
val data = Base64.encodeToString(string.encodeToByteArray(), Base64.NO_PADDING)
|
||||||
|
loadData(data, "text/html; charset=utf-8", "base64")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatText(itemWithFeed: ItemWithFeed): String {
|
||||||
|
return if (itemWithFeed.item.content != null) {
|
||||||
|
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()
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user