impr: show images in blogposts
This commit is contained in:
parent
6260796084
commit
95f84cafb7
@ -116,6 +116,7 @@ dependencies {
|
||||
implementation(libs.ktor.client.logging)
|
||||
implementation(libs.ktor.client.android)
|
||||
implementation(libs.coil.compose)
|
||||
implementation(libs.glide)
|
||||
|
||||
implementation(libs.androidx.datastore.preferences)
|
||||
implementation(libs.splitties.base)
|
||||
|
@ -5,8 +5,12 @@
|
||||
|
||||
package ru.sweetbread.unn.ui.composes
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.Html
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.util.Linkify
|
||||
import android.util.Log
|
||||
import android.widget.TextView
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@ -43,11 +47,11 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil.ImageLoader
|
||||
import coil.compose.AsyncImage
|
||||
import com.google.android.material.textview.MaterialTextView
|
||||
import coil.request.ImageRequest
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
@ -196,8 +200,10 @@ fun PostItem(modifier: Modifier = Modifier, post: Post, extended: Boolean = fals
|
||||
val linkColor = MaterialTheme.colorScheme.primary.toArgb()
|
||||
|
||||
AndroidView(
|
||||
modifier = Modifier,
|
||||
factory = {
|
||||
MaterialTextView(it).apply {
|
||||
TextView(it).apply {
|
||||
movementMethod = LinkMovementMethod.getInstance()
|
||||
autoLinkMask = Linkify.WEB_URLS
|
||||
linksClickable = true
|
||||
setTextColor(textColor)
|
||||
@ -206,7 +212,12 @@ fun PostItem(modifier: Modifier = Modifier, post: Post, extended: Boolean = fals
|
||||
},
|
||||
update = {
|
||||
it.maxLines = if (extended) Int.MAX_VALUE else 5
|
||||
it.text = HtmlCompat.fromHtml(html, 0)
|
||||
it.text = Html.fromHtml(
|
||||
html,
|
||||
Html.FROM_HTML_MODE_LEGACY,
|
||||
CoilImageGetter(it),
|
||||
null
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@ -257,4 +268,77 @@ fun PostItemPreview() {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CoilImageGetter(
|
||||
private val textView: TextView,
|
||||
private val maxImageWidth: Int = textView.width
|
||||
) : Html.ImageGetter {
|
||||
|
||||
override fun getDrawable(source: String): Drawable {
|
||||
val urlDrawable = UrlDrawable()
|
||||
|
||||
if (maxImageWidth <= 0)
|
||||
textView.post { updateImage(source, urlDrawable, textView.width) }
|
||||
else
|
||||
updateImage(source, urlDrawable, maxImageWidth)
|
||||
|
||||
return urlDrawable
|
||||
}
|
||||
|
||||
private fun updateImage(source: String, urlDrawable: UrlDrawable, maxWidth: Int) {
|
||||
val imageLoader = ImageLoader.Builder(textView.context)
|
||||
.build()
|
||||
|
||||
val request = ImageRequest.Builder(textView.context)
|
||||
.data(source)
|
||||
.target { drawable ->
|
||||
val (scaledWidth, scaledHeight) = calculateScaledSize(
|
||||
drawable.intrinsicWidth,
|
||||
drawable.intrinsicHeight,
|
||||
maxWidth
|
||||
)
|
||||
|
||||
drawable.setBounds(0, 0, scaledWidth, scaledHeight)
|
||||
urlDrawable.drawable = drawable
|
||||
urlDrawable.setBounds(0, 0, scaledWidth, scaledHeight)
|
||||
|
||||
textView.text = textView.text
|
||||
}
|
||||
.build()
|
||||
|
||||
imageLoader.enqueue(request)
|
||||
}
|
||||
|
||||
private fun calculateScaledSize(
|
||||
originalWidth: Int,
|
||||
originalHeight: Int,
|
||||
maxWidth: Int
|
||||
): Pair<Int, Int> {
|
||||
if (originalWidth <= maxWidth)
|
||||
return Pair(originalWidth, originalHeight)
|
||||
|
||||
val ratio = maxWidth.toFloat() / originalWidth.toFloat()
|
||||
return Pair(
|
||||
maxWidth,
|
||||
(originalHeight * ratio).toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class UrlDrawable() : Drawable() {
|
||||
var drawable: Drawable? = null
|
||||
set(value) {
|
||||
field = value
|
||||
invalidateSelf()
|
||||
}
|
||||
|
||||
override fun draw(canvas: android.graphics.Canvas) {
|
||||
drawable?.draw(canvas)
|
||||
}
|
||||
|
||||
override fun setAlpha(alpha: Int) {}
|
||||
override fun setColorFilter(colorFilter: android.graphics.ColorFilter?) {}
|
||||
override fun getOpacity(): Int = android.graphics.PixelFormat.TRANSLUCENT
|
||||
}
|
@ -7,6 +7,7 @@ compose = "1.8.0"
|
||||
coreSplashscreen = "1.0.1"
|
||||
datastorePreferences = "1.1.5"
|
||||
desugar_jdk_libs = "2.1.5"
|
||||
glide = "4.16.0"
|
||||
kotlin = "2.1.20"
|
||||
coreKtx = "1.16.0"
|
||||
junitVersion = "1.2.1"
|
||||
@ -51,6 +52,7 @@ androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-man
|
||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
||||
ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktor" }
|
||||
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
|
||||
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
||||
|
Loading…
x
Reference in New Issue
Block a user