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 package org.koitharu.kotatsu.core.ui.image
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
@@ -8,8 +10,11 @@ import android.graphics.PointF
import android.graphics.Rect import android.graphics.Rect
import android.os.Build import android.os.Build
import android.widget.TextView import android.widget.TextView
import androidx.annotation.AttrRes
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.graphics.PaintCompat 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 import org.koitharu.kotatsu.core.util.ext.hasFocusStateSpecified
class TextDrawable( class TextDrawable(
@@ -71,6 +76,17 @@ class TextDrawable(
companion object { 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? { fun compound(textView: TextView, text: String): TextDrawable? {
val drawable = TextDrawable(text) val drawable = TextDrawable(text)
drawable.textSize = textView.textSize drawable.textSize = textView.textSize

View File

@@ -1,23 +1,32 @@
package org.koitharu.kotatsu.image.ui package org.koitharu.kotatsu.image.ui
import android.content.Context import android.content.Context
import android.os.Build
import android.util.AttributeSet import android.util.AttributeSet
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.OnPreDrawListener import android.view.ViewTreeObserver.OnPreDrawListener
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.RequiresApi
import androidx.core.content.withStyledAttributes import androidx.core.content.withStyledAttributes
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.graphics.drawable.toDrawable 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.request.transformations
import coil3.size.Dimension import coil3.size.Dimension
import coil3.size.Size import coil3.size.Size
import coil3.size.ViewSizeResolver import coil3.size.ViewSizeResolver
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import okio.FileNotFoundException
import org.jsoup.HttpStatusException
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.Bookmark
import org.koitharu.kotatsu.core.image.CoilImageView import org.koitharu.kotatsu.core.image.CoilImageView
import org.koitharu.kotatsu.core.ui.image.AnimatedPlaceholderDrawable 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.ui.image.TrimTransformation
import org.koitharu.kotatsu.core.util.ext.bookmarkExtra import org.koitharu.kotatsu.core.util.ext.bookmarkExtra
import org.koitharu.kotatsu.core.util.ext.decodeRegion import org.koitharu.kotatsu.core.util.ext.decodeRegion
@@ -66,6 +75,9 @@ class CoverImageView @JvmOverloads constructor(
if (fallbackDrawable == null) { if (fallbackDrawable == null) {
fallbackDrawable = context.getThemeColor(materialR.attr.colorSurfaceContainer).toDrawable() 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) { 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( private class CoverSizeResolver(
override val view: CoverImageView, override val view: CoverImageView,
) : ViewSizeResolver<CoverImageView> { ) : ViewSizeResolver<CoverImageView> {