impr: show images in blogposts

This commit is contained in:
Sweetbread 2025-04-23 19:57:41 +03:00
parent 99effd1e52
commit 7f613a2106
Signed by: Sweetbread
GPG Key ID: 17A5CB9A7DD85319

View File

@ -5,8 +5,12 @@
package ru.sweetbread.unn.ui.composes 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.text.util.Linkify
import android.util.Log import android.util.Log
import android.widget.TextView
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement 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.tooling.preview.Preview
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.text.HtmlCompat
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import coil.ImageLoader
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.google.android.material.textview.MaterialTextView import coil.request.ImageRequest
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow 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() val linkColor = MaterialTheme.colorScheme.primary.toArgb()
AndroidView( AndroidView(
modifier = Modifier,
factory = { factory = {
MaterialTextView(it).apply { TextView(it).apply {
movementMethod = LinkMovementMethod.getInstance()
autoLinkMask = Linkify.WEB_URLS autoLinkMask = Linkify.WEB_URLS
linksClickable = true linksClickable = true
setTextColor(textColor) setTextColor(textColor)
@ -206,7 +212,12 @@ fun PostItem(modifier: Modifier = Modifier, post: Post, extended: Boolean = fals
}, },
update = { update = {
it.maxLines = if (extended) Int.MAX_VALUE else 5 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
)
} }
) )
@ -258,3 +269,76 @@ 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
}