Compare commits
No commits in common. "master" and "v125010111" have entirely different histories.
master
...
v125010111
@ -1,10 +1,3 @@
|
||||
**v125010111
|
||||
|
||||
- Debug trying to fix context issues. (#174)
|
||||
- Changelog for v125010031
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
**v125010031
|
||||
|
||||
- Merge pull request 'Bump dependencies' (#173) from upgarde into master
|
||||
|
@ -118,13 +118,13 @@ class ItemCardAdapter(
|
||||
binding.itemImage.setImageDrawable(null)
|
||||
} else {
|
||||
binding.itemImage.visibility = View.VISIBLE
|
||||
c.bitmapCenterCrop(itm.getThumbnail(repository.baseUrl), binding.itemImage, appSettingsService)
|
||||
c.bitmapCenterCrop(itm.getThumbnail(repository.baseUrl), binding.itemImage)
|
||||
}
|
||||
|
||||
if (itm.getIcon(repository.baseUrl).isEmpty()) {
|
||||
binding.sourceImage.setBackgroundAndText(itm.sourcetitle.getHtmlDecoded())
|
||||
} else {
|
||||
c.circularDrawable(itm.getIcon(repository.baseUrl), binding.sourceImage, appSettingsService)
|
||||
c.circularDrawable(itm.getIcon(repository.baseUrl), binding.sourceImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ class ItemListAdapter(
|
||||
if (itm.getIcon(repository.baseUrl).isEmpty()) {
|
||||
binding.itemImage.setBackgroundAndText(itm.sourcetitle.getHtmlDecoded())
|
||||
} else {
|
||||
c.circularDrawable(itm.getIcon(repository.baseUrl), binding.itemImage, appSettingsService)
|
||||
c.circularDrawable(itm.getIcon(repository.baseUrl), binding.itemImage)
|
||||
}
|
||||
} else {
|
||||
c.circularDrawable(itm.getThumbnail(repository.baseUrl), binding.itemImage, appSettingsService)
|
||||
c.circularDrawable(itm.getThumbnail(repository.baseUrl), binding.itemImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import bou.amine.apps.readerforselfossv2.android.databinding.SourceListItemBindi
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularDrawable
|
||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -37,7 +36,6 @@ class SourcesListAdapter(
|
||||
|
||||
override val di: DI by closestDI(app)
|
||||
private val repository: Repository by instance()
|
||||
private val appSettingsService: AppSettingsService by instance()
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
@ -84,7 +82,7 @@ class SourcesListAdapter(
|
||||
if (itm.getIcon(repository.baseUrl).isEmpty()) {
|
||||
binding.itemImage.setBackgroundAndText(itm.title.getHtmlDecoded())
|
||||
} else {
|
||||
c.circularDrawable(itm.getIcon(repository.baseUrl), binding.itemImage, appSettingsService)
|
||||
c.circularDrawable(itm.getIcon(repository.baseUrl), binding.itemImage)
|
||||
}
|
||||
|
||||
if (!itm.error.isNullOrBlank()) {
|
||||
|
@ -63,7 +63,7 @@ class LoadingWorker(
|
||||
handleNewItemsNotification(apiItems, notificationManager)
|
||||
}
|
||||
}
|
||||
apiItems.map { it.preloadImages(context, appSettingsService) }
|
||||
apiItems.map { it.preloadImages(context) }
|
||||
}
|
||||
}
|
||||
return Result.success()
|
||||
|
@ -32,9 +32,7 @@ import bou.amine.apps.readerforselfossv2.android.model.ParecelableItem
|
||||
import bou.amine.apps.readerforselfossv2.android.model.toModel
|
||||
import bou.amine.apps.readerforselfossv2.android.model.toParcelable
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.acra.sendSilentlyWithAcraWithName
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapFitCenter
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.getGlideImageForResource
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.isUrlValid
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.openItemUrlInBrowserAsNewTask
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.openUrlInBrowser
|
||||
@ -48,6 +46,9 @@ import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||
import bou.amine.apps.readerforselfossv2.utils.getImages
|
||||
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
||||
import bou.amine.apps.readerforselfossv2.utils.isEmptyOrNullOrNullString
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.github.rubensousa.floatingtoolbar.FloatingToolbar
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -64,8 +65,6 @@ import java.util.Locale
|
||||
import java.util.concurrent.ExecutionException
|
||||
|
||||
private const val IMAGE_JPG = "image/jpg"
|
||||
private const val IMAGE_PNG = "image/png"
|
||||
private const val IMAGE_WEBP = "image/webp"
|
||||
|
||||
private const val WHITE_COLOR_HEX = 0xFFFFFF
|
||||
|
||||
@ -209,7 +208,12 @@ class ArticleFragment :
|
||||
|
||||
if (!contentImage.isEmptyOrNullOrNullString() && context != null) {
|
||||
binding.imageView.visibility = View.VISIBLE
|
||||
requireContext().bitmapFitCenter(contentImage, binding.imageView, appSettingsService)
|
||||
Glide
|
||||
.with(requireContext())
|
||||
.asBitmap()
|
||||
.load(contentImage)
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(binding.imageView)
|
||||
} else {
|
||||
binding.imageView.visibility = View.GONE
|
||||
}
|
||||
@ -323,7 +327,13 @@ class ArticleFragment :
|
||||
private fun handleLeadImage(leadImageUrl: String?) {
|
||||
if (!leadImageUrl.isNullOrEmpty() && context != null) {
|
||||
binding.imageView.visibility = View.VISIBLE
|
||||
requireContext().bitmapFitCenter(leadImageUrl, binding.imageView, appSettingsService)
|
||||
Glide
|
||||
.with(requireContext())
|
||||
.asBitmap()
|
||||
.load(
|
||||
leadImageUrl,
|
||||
).apply(RequestOptions.fitCenterTransform())
|
||||
.into(binding.imageView)
|
||||
} else {
|
||||
binding.imageView.visibility = View.GONE
|
||||
}
|
||||
@ -347,37 +357,78 @@ class ArticleFragment :
|
||||
false
|
||||
}
|
||||
|
||||
@Suppress("detekt:SwallowedException", "detekt:ReturnCount")
|
||||
@Suppress("detekt:LongMethod", "detekt:SwallowedException")
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun shouldInterceptRequest(
|
||||
view: WebView,
|
||||
url: String,
|
||||
): WebResourceResponse? {
|
||||
val (mime: String?, compression: Bitmap.CompressFormat) =
|
||||
if (url
|
||||
.lowercase(Locale.US)
|
||||
.contains(".jpg") ||
|
||||
url.lowercase(Locale.US).contains(".jpeg")
|
||||
) {
|
||||
Pair(IMAGE_JPG, Bitmap.CompressFormat.JPEG)
|
||||
} else if (url.lowercase(Locale.US).contains(".png")) {
|
||||
Pair(IMAGE_PNG, Bitmap.CompressFormat.PNG)
|
||||
} else if (url.lowercase(Locale.US).contains(".webp")) {
|
||||
Pair(IMAGE_WEBP, Bitmap.CompressFormat.WEBP)
|
||||
} else {
|
||||
return super.shouldInterceptRequest(view, url)
|
||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||
var glideResource: WebResourceResponse? = null
|
||||
if (url.lowercase(Locale.US).contains(".jpg") ||
|
||||
url
|
||||
.lowercase(Locale.US)
|
||||
.contains(".jpeg")
|
||||
) {
|
||||
try {
|
||||
val image =
|
||||
Glide
|
||||
.with(view)
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(url)
|
||||
.submit()
|
||||
.get()
|
||||
glideResource =
|
||||
WebResourceResponse(
|
||||
IMAGE_JPG,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, Bitmap.CompressFormat.JPEG),
|
||||
)
|
||||
} catch (e: ExecutionException) {
|
||||
// Do nothing
|
||||
}
|
||||
} else if (url.lowercase(Locale.US).contains(".png")) {
|
||||
try {
|
||||
val image =
|
||||
Glide
|
||||
.with(view)
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(url)
|
||||
.submit()
|
||||
.get()
|
||||
glideResource =
|
||||
WebResourceResponse(
|
||||
IMAGE_JPG,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, Bitmap.CompressFormat.PNG),
|
||||
)
|
||||
} catch (e: ExecutionException) {
|
||||
// Do nothing
|
||||
}
|
||||
} else if (url.lowercase(Locale.US).contains(".webp")) {
|
||||
try {
|
||||
val image =
|
||||
Glide
|
||||
.with(view)
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(url)
|
||||
.submit()
|
||||
.get()
|
||||
glideResource =
|
||||
WebResourceResponse(
|
||||
IMAGE_JPG,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, Bitmap.CompressFormat.WEBP),
|
||||
)
|
||||
} catch (e: ExecutionException) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
try {
|
||||
val image = view.getGlideImageForResource(url, appSettingsService)
|
||||
return WebResourceResponse(
|
||||
mime,
|
||||
"UTF-8",
|
||||
getBitmapInputStream(image, compression),
|
||||
)
|
||||
} catch (e: ExecutionException) {
|
||||
return super.shouldInterceptRequest(view, url)
|
||||
}
|
||||
|
||||
return glideResource ?: super.shouldInterceptRequest(view, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,11 @@ import bou.amine.apps.readerforselfossv2.android.HomeActivity
|
||||
import bou.amine.apps.readerforselfossv2.android.R
|
||||
import bou.amine.apps.readerforselfossv2.android.databinding.FilterFragmentBinding
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.acra.sendSilentlyWithAcraWithName
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.imageIntoViewTarget
|
||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import bou.amine.apps.readerforselfossv2.utils.getColorHexCode
|
||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.ViewTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
@ -42,7 +41,6 @@ class FilterSheetFragment :
|
||||
private lateinit var binding: FilterFragmentBinding
|
||||
override val di: DI by closestDI()
|
||||
private val repository: Repository by instance()
|
||||
private val appSettingsService: AppSettingsService by instance()
|
||||
|
||||
private var selectedChip: Chip? = null
|
||||
|
||||
@ -86,22 +84,23 @@ class FilterSheetFragment :
|
||||
val c = Chip(context)
|
||||
c.ellipsize = TextUtils.TruncateAt.END
|
||||
|
||||
context.imageIntoViewTarget(
|
||||
source.getIcon(repository.baseUrl),
|
||||
object : ViewTarget<Chip?, Drawable?>(c) {
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
transition: Transition<in Drawable?>?,
|
||||
) {
|
||||
try {
|
||||
c.chipIcon = resource
|
||||
} catch (e: Exception) {
|
||||
e.sendSilentlyWithAcraWithName("sources > onResourceReady")
|
||||
Glide
|
||||
.with(context)
|
||||
.load(source.getIcon(repository.baseUrl))
|
||||
.into(
|
||||
object : ViewTarget<Chip?, Drawable?>(c) {
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
transition: Transition<in Drawable?>?,
|
||||
) {
|
||||
try {
|
||||
c.chipIcon = resource
|
||||
} catch (e: Exception) {
|
||||
e.sendSilentlyWithAcraWithName("sources > onResourceReady")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
appSettingsService,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
c.text = source.title.getHtmlDecoded()
|
||||
|
||||
|
@ -6,19 +6,13 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import bou.amine.apps.readerforselfossv2.android.databinding.FragmentImageBinding
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapWithCache
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.x.closestDI
|
||||
import org.kodein.di.instance
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
|
||||
class ImageFragment :
|
||||
Fragment(),
|
||||
DIAware {
|
||||
override val di: DI by closestDI()
|
||||
private val appSettingsService: AppSettingsService by instance()
|
||||
class ImageFragment : Fragment() {
|
||||
private lateinit var imageUrl: String
|
||||
private val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||
private var _binding: FragmentImageBinding? = null
|
||||
val binding get() = _binding
|
||||
|
||||
@ -37,7 +31,12 @@ class ImageFragment :
|
||||
val view = binding?.root
|
||||
|
||||
binding!!.photoView.visibility = View.VISIBLE
|
||||
requireActivity().bitmapWithCache(imageUrl, binding!!.photoView, appSettingsService)
|
||||
Glide
|
||||
.with(requireActivity())
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(imageUrl)
|
||||
.into(binding!!.photoView)
|
||||
|
||||
return view
|
||||
}
|
||||
|
@ -3,21 +3,28 @@ package bou.amine.apps.readerforselfossv2.android.model
|
||||
import android.content.Context
|
||||
import android.webkit.URLUtil
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.acra.sendSilentlyWithAcraWithName
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.preloadImage
|
||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import bou.amine.apps.readerforselfossv2.utils.getImages
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
|
||||
fun SelfossModel.Item.preloadImages(
|
||||
context: Context,
|
||||
appSettingsService: AppSettingsService,
|
||||
): Boolean {
|
||||
private const val PRELOAD_IMAGE_TIMEOUT = 10000
|
||||
|
||||
fun SelfossModel.Item.preloadImages(context: Context): Boolean {
|
||||
val imageUrls = this.getImages()
|
||||
|
||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL).timeout(PRELOAD_IMAGE_TIMEOUT)
|
||||
|
||||
try {
|
||||
for (url in imageUrls) {
|
||||
if (URLUtil.isValidUrl(url)) {
|
||||
context.preloadImage(url, appSettingsService)
|
||||
Glide
|
||||
.with(context)
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(url)
|
||||
.submit()
|
||||
}
|
||||
}
|
||||
} catch (e: Error) {
|
||||
|
@ -2,119 +2,33 @@ package bou.amine.apps.readerforselfossv2.android.utils.glide
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.webkit.WebView
|
||||
import android.widget.ImageView
|
||||
import bou.amine.apps.readerforselfossv2.android.utils.CircleImageView
|
||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.load.model.LazyHeaders
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.bumptech.glide.request.target.ViewTarget
|
||||
import com.google.android.material.chip.Chip
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.InputStream
|
||||
import kotlin.io.encoding.Base64
|
||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
|
||||
private const val PRELOAD_IMAGE_TIMEOUT = 10000
|
||||
|
||||
@OptIn(ExperimentalEncodingApi::class)
|
||||
fun String.toGlideUrl(appSettingsService: AppSettingsService): GlideUrl {
|
||||
if (appSettingsService.getBasicUserName().isNotEmpty()) {
|
||||
val authString = "${appSettingsService.getBasicUserName()}:${appSettingsService.getBasicPassword()}"
|
||||
val authBuf = Base64.encode(authString.toByteArray(Charsets.UTF_8))
|
||||
|
||||
return GlideUrl(
|
||||
this,
|
||||
LazyHeaders
|
||||
.Builder()
|
||||
.addHeader("Authorization", "Basic $authBuf")
|
||||
.build(),
|
||||
)
|
||||
} else {
|
||||
return GlideUrl(
|
||||
this,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun WebView.getGlideImageForResource(
|
||||
url: String,
|
||||
appSettingsService: AppSettingsService,
|
||||
) = Glide
|
||||
.with(this)
|
||||
.asBitmap()
|
||||
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL))
|
||||
.load(url.toGlideUrl(appSettingsService))
|
||||
.submit()
|
||||
.get()
|
||||
|
||||
fun Context.preloadImage(
|
||||
url: String,
|
||||
appSettingsService: AppSettingsService,
|
||||
) = Glide
|
||||
.with(this)
|
||||
.asBitmap()
|
||||
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL).timeout(PRELOAD_IMAGE_TIMEOUT))
|
||||
.load(url.toGlideUrl(appSettingsService))
|
||||
.submit()
|
||||
|
||||
fun Context.imageIntoViewTarget(
|
||||
url: String,
|
||||
target: ViewTarget<Chip?, Drawable?>,
|
||||
appSettingsService: AppSettingsService,
|
||||
) = Glide
|
||||
.with(this)
|
||||
.load(url.toGlideUrl(appSettingsService))
|
||||
.into(target)
|
||||
|
||||
fun Context.bitmapWithCache(
|
||||
url: String,
|
||||
iv: ImageView,
|
||||
appSettingsService: AppSettingsService,
|
||||
) = Glide
|
||||
.with(this)
|
||||
.asBitmap()
|
||||
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL))
|
||||
.load(url.toGlideUrl(appSettingsService))
|
||||
.into(iv)
|
||||
|
||||
fun Context.bitmapCenterCrop(
|
||||
url: String,
|
||||
iv: ImageView,
|
||||
appSettingsService: AppSettingsService,
|
||||
) = Glide
|
||||
.with(this)
|
||||
.asBitmap()
|
||||
.load(url.toGlideUrl(appSettingsService))
|
||||
.load(url)
|
||||
.apply(RequestOptions.centerCropTransform())
|
||||
.into(iv)
|
||||
|
||||
fun Context.bitmapFitCenter(
|
||||
url: String,
|
||||
iv: ImageView,
|
||||
appSettingsService: AppSettingsService,
|
||||
) = Glide
|
||||
.with(this)
|
||||
.asBitmap()
|
||||
.load(url.toGlideUrl(appSettingsService))
|
||||
.apply(RequestOptions.fitCenterTransform())
|
||||
.into(iv)
|
||||
|
||||
fun Context.circularDrawable(
|
||||
url: String,
|
||||
view: CircleImageView,
|
||||
appSettingsService: AppSettingsService,
|
||||
) {
|
||||
view.textView.text = ""
|
||||
|
||||
Glide
|
||||
.with(this)
|
||||
.load(url.toGlideUrl(appSettingsService))
|
||||
.load(url)
|
||||
.into(view.imageView)
|
||||
}
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
**v125010111**
|
||||
|
||||
- Debug trying to fix context issues. (#174)
|
||||
- Changelog for v125010031
|
Loading…
x
Reference in New Issue
Block a user