Show error codes on covers

This commit is contained in:
Koitharu
2025-06-22 19:54:39 +03:00
parent 2797ea6a99
commit 18466a2c1a
2 changed files with 61 additions and 0 deletions

View File

@@ -1,5 +1,7 @@
package org.koitharu.kotatsu.core.ui.image
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Canvas
import android.graphics.Color
@@ -8,8 +10,11 @@ import android.graphics.PointF
import android.graphics.Rect
import android.os.Build
import android.widget.TextView
import androidx.annotation.AttrRes
import androidx.annotation.RequiresApi
import androidx.core.graphics.PaintCompat
import com.google.android.material.resources.TextAppearance
import org.koitharu.kotatsu.core.util.ext.getThemeResId
import org.koitharu.kotatsu.core.util.ext.hasFocusStateSpecified
class TextDrawable(
@@ -71,6 +76,17 @@ class TextDrawable(
companion object {
@SuppressLint("RestrictedApi")
fun create(context: Context, text: String, @AttrRes textAppearanceAttr: Int): TextDrawable {
val drawable = TextDrawable(text)
val textAppearance = TextAppearance(context, context.getThemeResId(textAppearanceAttr, androidx.appcompat.R.style.TextAppearance_AppCompat))
drawable.textSize = textAppearance.textSize
drawable.textColor = textAppearance.textColor ?: drawable.textColor
drawable.paint.typeface = textAppearance.getFont(context)
drawable.paint.letterSpacing = textAppearance.letterSpacing
return drawable
}
fun compound(textView: TextView, text: String): TextDrawable? {
val drawable = TextDrawable(text)
drawable.textSize = textView.textSize

View File

@@ -1,23 +1,32 @@
package org.koitharu.kotatsu.image.ui
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.OnPreDrawListener
import androidx.annotation.AttrRes
import androidx.annotation.RequiresApi
import androidx.core.content.withStyledAttributes
import androidx.core.graphics.ColorUtils
import androidx.core.graphics.drawable.toDrawable
import coil3.network.HttpException
import coil3.request.ErrorResult
import coil3.request.ImageRequest
import coil3.request.SuccessResult
import coil3.request.transformations
import coil3.size.Dimension
import coil3.size.Size
import coil3.size.ViewSizeResolver
import kotlinx.coroutines.suspendCancellableCoroutine
import okio.FileNotFoundException
import org.jsoup.HttpStatusException
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
import org.koitharu.kotatsu.core.image.CoilImageView
import org.koitharu.kotatsu.core.ui.image.AnimatedPlaceholderDrawable
import org.koitharu.kotatsu.core.ui.image.TextDrawable
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
import org.koitharu.kotatsu.core.util.ext.bookmarkExtra
import org.koitharu.kotatsu.core.util.ext.decodeRegion
@@ -66,6 +75,9 @@ class CoverImageView @JvmOverloads constructor(
if (fallbackDrawable == null) {
fallbackDrawable = context.getThemeColor(materialR.attr.colorSurfaceContainer).toDrawable()
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
addImageRequestListener(ErrorForegroundListener())
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
@@ -149,6 +161,39 @@ class CoverImageView @JvmOverloads constructor(
}
}
@RequiresApi(Build.VERSION_CODES.M)
private inner class ErrorForegroundListener : ImageRequest.Listener {
override fun onSuccess(request: ImageRequest, result: SuccessResult) {
super.onSuccess(request, result)
foreground = null
}
override fun onCancel(request: ImageRequest) {
super.onCancel(request)
foreground = null
}
override fun onStart(request: ImageRequest) {
super.onStart(request)
foreground = null
}
override fun onError(request: ImageRequest, result: ErrorResult) {
super.onError(request, result)
foreground = result.throwable.getShortMessage()?.let { text ->
TextDrawable.create(context, text, materialR.attr.textAppearanceTitleSmall)
}
}
private fun Throwable.getShortMessage(): String? = when (this) {
is HttpException -> response.code.toString()
is HttpStatusException -> statusCode.toString()
is FileNotFoundException -> "404"
else -> cause?.getShortMessage()
}
}
private class CoverSizeResolver(
override val view: CoverImageView,
) : ViewSizeResolver<CoverImageView> {