impr: show images in blogposts

This commit is contained in:
Sweetbread 2025-04-23 22:57:41 +03:00
parent 6260796084
commit 95f84cafb7
Signed by: Sweetbread
GPG Key ID: 17A5CB9A7DD85319
3 changed files with 91 additions and 4 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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" }