Use cached preview as thumbnail in ViewImageFragment, fix #1267 (#1344)

* Use cached preview as thumbnail in ViewImageFragment, fix #1267

* Use cached preview as thumbnail in ViewImageFragment, fix #1267
This commit is contained in:
Ivan Kupalov 2019-08-04 20:22:57 +02:00 committed by Konrad Pozniak
commit 9805a985b2
7 changed files with 165 additions and 112 deletions

View file

@ -30,14 +30,15 @@ import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.github.chrisbanes.photoview.PhotoViewAttacher
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.visible
import io.reactivex.subjects.BehaviorSubject
import kotlinx.android.synthetic.main.activity_view_media.*
import kotlinx.android.synthetic.main.fragment_view_image.*
import kotlin.math.abs
class ViewImageFragment : ViewMediaFragment() {
interface PhotoActionsListener {
@ -49,35 +50,35 @@ class ViewImageFragment : ViewMediaFragment() {
private lateinit var attacher: PhotoViewAttacher
private lateinit var photoActionsListener: PhotoActionsListener
private lateinit var toolbar: View
override lateinit var descriptionView: TextView
private var transition = BehaviorSubject.create<Unit>()
override lateinit var descriptionView: TextView
override fun onAttach(context: Context) {
super.onAttach(context)
photoActionsListener = context as PhotoActionsListener
}
override fun setupMediaView(url: String) {
override fun setupMediaView(url: String, previewUrl: String?) {
descriptionView = mediaDescription
photoView.transitionName = url
attacher = PhotoViewAttacher(photoView)
attacher = PhotoViewAttacher(photoView).apply {
// Clicking outside the photo closes the viewer.
setOnOutsidePhotoTapListener { photoActionsListener.onDismiss() }
setOnClickListener { onMediaTap() }
// Clicking outside the photo closes the viewer.
attacher.setOnOutsidePhotoTapListener { photoActionsListener.onDismiss() }
attacher.setOnClickListener { onMediaTap() }
/* A vertical swipe motion also closes the viewer. This is especially useful when the photo
* mostly fills the screen so clicking outside is difficult. */
attacher.setOnSingleFlingListener { _, _, velocityX, velocityY ->
var result = false
if (Math.abs(velocityY) > Math.abs(velocityX)) {
photoActionsListener.onDismiss()
result = true
/* A vertical swipe motion also closes the viewer. This is especially useful when the photo
* mostly fills the screen so clicking outside is difficult. */
setOnSingleFlingListener { _, _, velocityX, velocityY ->
var result = false
if (abs(velocityY) > abs(velocityX)) {
photoActionsListener.onDismiss()
result = true
}
result
}
result
}
loadImageFromNetwork(url, photoView)
loadImageFromNetwork(url, previewUrl, photoView)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@ -103,7 +104,7 @@ class ViewImageFragment : ViewMediaFragment() {
}
}
finalizeViewSetup(url, description)
finalizeViewSetup(url, attachment?.previewUrl, description)
}
private fun onMediaTap() {
@ -131,49 +132,71 @@ class ViewImageFragment : ViewMediaFragment() {
super.onDestroyView()
}
private fun loadImageFromNetwork(url: String, photoView: ImageView) =
//Request image from the any cache
Glide.with(this)
.load(url)
.dontAnimate()
.onlyRetrieveFromCache(true)
.error(
//Request image from the network on fail load image from cache
Glide.with(this)
.load(url)
.centerInside()
.addListener(ImageRequestListener(false))
)
.centerInside()
.addListener(ImageRequestListener(true))
.into(photoView)
private fun loadImageFromNetwork(url: String, previewUrl: String?, photoView: ImageView) {
val glide = Glide.with(this)
// Request image from the any cache
glide
.load(url)
.dontAnimate()
.onlyRetrieveFromCache(true)
.let {
if (previewUrl != null)
it.thumbnail(glide
.load(previewUrl)
.dontAnimate()
.onlyRetrieveFromCache(true)
.centerInside()
.addListener(ImageRequestListener(true, isThumnailRequest = true)))
else it
}
//Request image from the network on fail load image from cache
.error(glide.load(url)
.centerInside()
.addListener(ImageRequestListener(false, isThumnailRequest = false))
)
.centerInside()
.addListener(ImageRequestListener(true, isThumnailRequest = false))
.into(photoView)
}
/**
* @param isCacheRequest - is this listener for request image from cache or from the network
*/
private inner class ImageRequestListener(private val isCacheRequest: Boolean) : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
if (isCacheRequest) //Complete the transition on failed image from cache
completeTransition()
else
progressBar?.hide() //Hide progress bar only on fail request from internet
private inner class ImageRequestListener(
private val isCacheRequest: Boolean,
private val isThumnailRequest: Boolean) : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any, target: Target<Drawable>,
isFirstResource: Boolean): Boolean {
// If cache for full image failed, complete transition
if (isCacheRequest && !isThumnailRequest) photoActionsListener.onBringUp()
// Hide progress bar only on fail request from internet
if (!isCacheRequest) progressBar?.hide()
return false
}
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
progressBar?.hide() //Always hide the progress bar on success
resource?.let {
target?.onResourceReady(resource, null)
if (isCacheRequest) completeTransition() //Complete transition on cache request only, because transition already completed on Network request
override fun onResourceReady(resource: Drawable, model: Any, target: Target<Drawable>,
dataSource: DataSource, isFirstResource: Boolean): Boolean {
progressBar?.hide() // Always hide the progress bar on success
if (isThumnailRequest) {
photoView.post {
target.onResourceReady(resource, null)
photoActionsListener.onBringUp()
}
} else {
transition
.take(1)
.subscribe {
target.onResourceReady(resource, null)
photoActionsListener.onBringUp()
}
}
return true
}
return false
}
}
private fun completeTransition() {
attacher.update()
photoActionsListener.onBringUp()
override fun onTransitionEnd() {
this.transition.onNext(Unit)
}
}