From 17ef53ef73eb7d7e715f6d2b62421b1c0ab73629 Mon Sep 17 00:00:00 2001 From: sonyx Date: Wed, 28 Oct 2026 21:45:55 -0300 Subject: [PATCH] feat: add software image decoding option and poster fallbacks --- .../ui/settings/SettingsGeneralScreen.kt | 10 ++++++++++ .../ImageDecodingPreferenceInterceptor.kt | 19 +++++++++++++++++++ .../cloudstream3/utils/ImageModuleCoil.kt | 12 +++++++++++- .../res/values-es/image_loading_options.xml | 7 +++++++ .../main/res/values/image_loading_options.xml | 9 +++++++++ app/src/main/res/xml/settings_general.xml | 3 +++ .../cloudstream4/DevicePreferenceStore.kt | 1 + 7 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/utils/ImageDecodingPreferenceInterceptor.kt create mode 100644 app/src/main/res/values-es/image_loading_options.xml create mode 100644 app/src/main/res/values/image_loading_options.xml diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneralScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneralScreen.kt index 6aa94fa883c..279375ba047 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneralScreen.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneralScreen.kt @@ -114,6 +114,16 @@ object SettingsGeneralScreen : SearchableSettings { }.sortedBy { fromTagToLanguageName(it) ?: it } return persistentListOf( + Preference.PreferenceGroup( + title = stringResource(R.string.image_loading_options_title), + preferenceItems = persistentListOf( + Preference.PreferenceItem.ListPreference( + preference = settings.general.imageDecodingMode, + title = stringResource(R.string.image_decoding_title), + entries = mapOf("auto" to stringResource(R.string.image_decoding_automatic), "software" to stringResource(R.string.image_decoding_software)), + ), + ), + ), Preference.PreferenceGroup(title = stringResource(R.string.extension_language), preferenceItems = persistentListOf( Preference.PreferenceItem.ListPreference( preference = settings.general.locale, diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ImageDecodingPreferenceInterceptor.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ImageDecodingPreferenceInterceptor.kt new file mode 100644 index 00000000000..770b2e6da67 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ImageDecodingPreferenceInterceptor.kt @@ -0,0 +1,19 @@ +package com.lagradost.cloudstream3.utils + +import android.graphics.Bitmap +import androidx.preference.PreferenceManager +import coil3.intercept.Interceptor +import coil3.request.ImageResult +import coil3.request.allowHardware +import coil3.request.bitmapConfig + +internal class ImageDecodingPreferenceInterceptor : Interceptor { + override suspend fun intercept(chain: Interceptor.Chain): ImageResult { + val request = chain.request + val softwareSelected = PreferenceManager.getDefaultSharedPreferences(request.context) + .getString("image_decoding_mode", "auto") == "software" + if (!softwareSelected || !request.allowHardware) return chain.proceed() + return chain.withRequest(request.newBuilder().allowHardware(false) + .bitmapConfig(Bitmap.Config.ARGB_8888).build()).proceed() + } +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ImageModuleCoil.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ImageModuleCoil.kt index 96193fe45f7..3ec67ae173d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ImageModuleCoil.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ImageModuleCoil.kt @@ -26,6 +26,9 @@ import coil3.request.ImageRequest import coil3.request.allowHardware import coil3.request.bitmapConfig import coil3.request.crossfade +import coil3.request.error +import coil3.request.fallback +import coil3.request.placeholder import coil3.util.DebugLogger import com.lagradost.cloudstream3.BuildConfig import com.lagradost.cloudstream3.USER_AGENT @@ -58,6 +61,7 @@ object ImageLoader { /** Pass interceptors with care, unnecessary passing tokens to servers or image hosting services causes unauthorized exceptions **/ .components { + add(ImageDecodingPreferenceInterceptor()) add(OkHttpNetworkFetcherFactory(callFactory = { buildDefaultClient(context) })) if (isBrokenHardware) { add(BitmapFactoryDecoder.Factory()) @@ -98,13 +102,19 @@ object ImageLoader { ) { // clear image to avoid loading & flickering issue at fast scrolling (~recycler view/lazy column) this.dispose() - if (imageData == null) return + if (imageData == null || (imageData is String && imageData.isBlank())) { + this.setImageResource(com.lagradost.cloudstream3.R.drawable.default_cover) + return + } // setImageResource is better than coil3 on resources due to attr if (imageData is Int) { this.setImageResource(imageData); return } // headers can be overridden by extensions. this.load(imageData, SingletonImageLoader.get(context)) { + placeholder { getImageFromDrawable(context, com.lagradost.cloudstream3.R.drawable.default_cover) } + error { getImageFromDrawable(context, com.lagradost.cloudstream3.R.drawable.default_cover) } + fallback { getImageFromDrawable(context, com.lagradost.cloudstream3.R.drawable.default_cover) } this.httpHeaders(NetworkHeaders.Builder().also { headerBuilder -> headerBuilder["User-Agent"] = USER_AGENT headers?.forEach { (key, value) -> diff --git a/app/src/main/res/values-es/image_loading_options.xml b/app/src/main/res/values-es/image_loading_options.xml new file mode 100644 index 00000000000..3c0d2642d1f --- /dev/null +++ b/app/src/main/res/values-es/image_loading_options.xml @@ -0,0 +1,7 @@ + + Carga de imágenes + Decodificación de imágenes + Automática + Compatibilidad por software + Choose software decoding for hardware compatibility problems. Automatic keeps the current image loader behavior. + diff --git a/app/src/main/res/values/image_loading_options.xml b/app/src/main/res/values/image_loading_options.xml new file mode 100644 index 00000000000..7775e28ae71 --- /dev/null +++ b/app/src/main/res/values/image_loading_options.xml @@ -0,0 +1,9 @@ + + Image loading + Image decoding + Automatic + Software compatibility + Choose software decoding for hardware compatibility problems. Automatic keeps the current image loader behavior. + @string/image_decoding_automatic@string/image_decoding_software + autosoftware + diff --git a/app/src/main/res/xml/settings_general.xml b/app/src/main/res/xml/settings_general.xml index f8b9b4f452f..ee4fe6c2b92 100644 --- a/app/src/main/res/xml/settings_general.xml +++ b/app/src/main/res/xml/settings_general.xml @@ -1,6 +1,9 @@ + + +