* Use cached preview as thumbnail in ViewImageFragment, fix #1267 * Use cached preview as thumbnail in ViewImageFragment, fix #1267
This commit is contained in:
parent
70b3ce7487
commit
9805a985b2
7 changed files with 164 additions and 111 deletions
|
@ -29,21 +29,22 @@ import android.graphics.Color
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import androidx.core.content.FileProvider
|
import android.transition.Transition
|
||||||
import androidx.viewpager.widget.ViewPager
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.viewpager.widget.PagerAdapter
|
||||||
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.FutureTarget
|
import com.bumptech.glide.request.FutureTarget
|
||||||
import com.keylesspalace.tusky.BuildConfig.APPLICATION_ID
|
import com.keylesspalace.tusky.BuildConfig.APPLICATION_ID
|
||||||
import com.keylesspalace.tusky.entity.Attachment
|
import com.keylesspalace.tusky.entity.Attachment
|
||||||
import com.keylesspalace.tusky.fragment.ViewImageFragment
|
import com.keylesspalace.tusky.fragment.ViewImageFragment
|
||||||
|
|
||||||
import com.keylesspalace.tusky.pager.AvatarImagePagerAdapter
|
import com.keylesspalace.tusky.pager.AvatarImagePagerAdapter
|
||||||
import com.keylesspalace.tusky.pager.ImagePagerAdapter
|
import com.keylesspalace.tusky.pager.ImagePagerAdapter
|
||||||
import com.keylesspalace.tusky.util.getTemporaryMediaFilename
|
import com.keylesspalace.tusky.util.getTemporaryMediaFilename
|
||||||
|
@ -53,14 +54,14 @@ import com.uber.autodispose.autoDisposable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
import kotlinx.android.synthetic.main.activity_view_media.*
|
import kotlinx.android.synthetic.main.activity_view_media.*
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
|
|
||||||
|
typealias ToolbarVisibilityListener = (isVisible: Boolean) -> Unit
|
||||||
|
|
||||||
class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener {
|
class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -84,25 +85,18 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isToolbarVisible = true
|
||||||
|
private set
|
||||||
|
|
||||||
private var attachments: ArrayList<AttachmentViewData>? = null
|
private var attachments: ArrayList<AttachmentViewData>? = null
|
||||||
|
private val toolbarVisibilityListeners = mutableListOf<ToolbarVisibilityListener>()
|
||||||
private var toolbarVisible = true
|
|
||||||
private val toolbarVisibilityListeners = ArrayList<ToolbarVisibilityListener>()
|
|
||||||
|
|
||||||
interface ToolbarVisibilityListener {
|
|
||||||
fun onToolbarVisiblityChanged(isVisible: Boolean)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addToolbarVisibilityListener(listener: ToolbarVisibilityListener): Function0<Boolean> {
|
fun addToolbarVisibilityListener(listener: ToolbarVisibilityListener): Function0<Boolean> {
|
||||||
this.toolbarVisibilityListeners.add(listener)
|
this.toolbarVisibilityListeners.add(listener)
|
||||||
listener.onToolbarVisiblityChanged(toolbarVisible)
|
listener(isToolbarVisible)
|
||||||
return { toolbarVisibilityListeners.remove(listener) }
|
return { toolbarVisibilityListeners.remove(listener) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isToolbarVisible(): Boolean {
|
|
||||||
return toolbarVisible
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_view_media)
|
setContentView(R.layout.activity_view_media)
|
||||||
|
@ -113,7 +107,10 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
||||||
attachments = intent.getParcelableArrayListExtra(EXTRA_ATTACHMENTS)
|
attachments = intent.getParcelableArrayListExtra(EXTRA_ATTACHMENTS)
|
||||||
val initialPosition = intent.getIntExtra(EXTRA_ATTACHMENT_INDEX, 0)
|
val initialPosition = intent.getIntExtra(EXTRA_ATTACHMENT_INDEX, 0)
|
||||||
|
|
||||||
val adapter = if (attachments != null) {
|
// Adapter is actually of existential type PageAdapter & SharedElementsTransitionListener
|
||||||
|
// but it cannot be expressed and if I don't specify type explicitly compilation fails
|
||||||
|
// (probably a bug in compiler)
|
||||||
|
val adapter: PagerAdapter = if (attachments != null) {
|
||||||
val realAttachs = attachments!!.map(AttachmentViewData::attachment)
|
val realAttachs = attachments!!.map(AttachmentViewData::attachment)
|
||||||
// Setup the view pager.
|
// Setup the view pager.
|
||||||
ImagePagerAdapter(supportFragmentManager, realAttachs, initialPosition)
|
ImagePagerAdapter(supportFragmentManager, realAttachs, initialPosition)
|
||||||
|
@ -154,6 +151,12 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
||||||
|
|
||||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE
|
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE
|
||||||
window.statusBarColor = Color.BLACK
|
window.statusBarColor = Color.BLACK
|
||||||
|
window.sharedElementEnterTransition.addListener(object : NoopTransitionListener {
|
||||||
|
override fun onTransitionEnd(transition: Transition) {
|
||||||
|
(adapter as SharedElementTransitionListener).onTransitionEnd()
|
||||||
|
window.sharedElementEnterTransition.removeListener(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
@ -178,20 +181,12 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPhotoTap() {
|
override fun onPhotoTap() {
|
||||||
toolbarVisible = !toolbarVisible
|
isToolbarVisible = !isToolbarVisible
|
||||||
for (listener in toolbarVisibilityListeners) {
|
for (listener in toolbarVisibilityListeners) {
|
||||||
listener.onToolbarVisiblityChanged(toolbarVisible)
|
listener(isToolbarVisible)
|
||||||
}
|
|
||||||
val visibility = if (toolbarVisible) {
|
|
||||||
View.VISIBLE
|
|
||||||
} else {
|
|
||||||
View.INVISIBLE
|
|
||||||
}
|
|
||||||
val alpha = if (toolbarVisible) {
|
|
||||||
1.0f
|
|
||||||
} else {
|
|
||||||
0.0f
|
|
||||||
}
|
}
|
||||||
|
val visibility = if (isToolbarVisible) View.VISIBLE else View.INVISIBLE
|
||||||
|
val alpha = if (isToolbarVisible) 1.0f else 0.0f
|
||||||
|
|
||||||
toolbar.animate().alpha(alpha)
|
toolbar.animate().alpha(alpha)
|
||||||
.setListener(object : AnimatorListenerAdapter() {
|
.setListener(object : AnimatorListenerAdapter() {
|
||||||
|
@ -327,3 +322,24 @@ class ViewMediaActivity : BaseActivity(), ViewImageFragment.PhotoActionsListener
|
||||||
shareFile(file, mimeType)
|
shareFile(file, mimeType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SharedElementTransitionListener {
|
||||||
|
fun onTransitionEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoopTransitionListener : Transition.TransitionListener {
|
||||||
|
override fun onTransitionEnd(transition: Transition) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTransitionResume(transition: Transition) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTransitionPause(transition: Transition) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTransitionCancel(transition: Transition) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTransitionStart(transition: Transition) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,14 +30,15 @@ import com.bumptech.glide.load.DataSource
|
||||||
import com.bumptech.glide.load.engine.GlideException
|
import com.bumptech.glide.load.engine.GlideException
|
||||||
import com.bumptech.glide.request.RequestListener
|
import com.bumptech.glide.request.RequestListener
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
|
|
||||||
import com.github.chrisbanes.photoview.PhotoViewAttacher
|
import com.github.chrisbanes.photoview.PhotoViewAttacher
|
||||||
import com.keylesspalace.tusky.R
|
import com.keylesspalace.tusky.R
|
||||||
import com.keylesspalace.tusky.entity.Attachment
|
import com.keylesspalace.tusky.entity.Attachment
|
||||||
import com.keylesspalace.tusky.util.hide
|
import com.keylesspalace.tusky.util.hide
|
||||||
import com.keylesspalace.tusky.util.visible
|
import com.keylesspalace.tusky.util.visible
|
||||||
|
import io.reactivex.subjects.BehaviorSubject
|
||||||
import kotlinx.android.synthetic.main.activity_view_media.*
|
import kotlinx.android.synthetic.main.activity_view_media.*
|
||||||
import kotlinx.android.synthetic.main.fragment_view_image.*
|
import kotlinx.android.synthetic.main.fragment_view_image.*
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
class ViewImageFragment : ViewMediaFragment() {
|
class ViewImageFragment : ViewMediaFragment() {
|
||||||
interface PhotoActionsListener {
|
interface PhotoActionsListener {
|
||||||
|
@ -49,35 +50,35 @@ class ViewImageFragment : ViewMediaFragment() {
|
||||||
private lateinit var attacher: PhotoViewAttacher
|
private lateinit var attacher: PhotoViewAttacher
|
||||||
private lateinit var photoActionsListener: PhotoActionsListener
|
private lateinit var photoActionsListener: PhotoActionsListener
|
||||||
private lateinit var toolbar: View
|
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) {
|
override fun onAttach(context: Context) {
|
||||||
super.onAttach(context)
|
super.onAttach(context)
|
||||||
photoActionsListener = context as PhotoActionsListener
|
photoActionsListener = context as PhotoActionsListener
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupMediaView(url: String) {
|
override fun setupMediaView(url: String, previewUrl: String?) {
|
||||||
descriptionView = mediaDescription
|
descriptionView = mediaDescription
|
||||||
photoView.transitionName = url
|
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.
|
/* A vertical swipe motion also closes the viewer. This is especially useful when the photo
|
||||||
attacher.setOnOutsidePhotoTapListener { photoActionsListener.onDismiss() }
|
* mostly fills the screen so clicking outside is difficult. */
|
||||||
|
setOnSingleFlingListener { _, _, velocityX, velocityY ->
|
||||||
attacher.setOnClickListener { onMediaTap() }
|
var result = false
|
||||||
|
if (abs(velocityY) > abs(velocityX)) {
|
||||||
/* A vertical swipe motion also closes the viewer. This is especially useful when the photo
|
photoActionsListener.onDismiss()
|
||||||
* mostly fills the screen so clicking outside is difficult. */
|
result = true
|
||||||
attacher.setOnSingleFlingListener { _, _, velocityX, velocityY ->
|
}
|
||||||
var result = false
|
result
|
||||||
if (Math.abs(velocityY) > Math.abs(velocityX)) {
|
|
||||||
photoActionsListener.onDismiss()
|
|
||||||
result = true
|
|
||||||
}
|
}
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadImageFromNetwork(url, photoView)
|
loadImageFromNetwork(url, previewUrl, photoView)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
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() {
|
private fun onMediaTap() {
|
||||||
|
@ -131,49 +132,71 @@ class ViewImageFragment : ViewMediaFragment() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadImageFromNetwork(url: String, photoView: ImageView) =
|
private fun loadImageFromNetwork(url: String, previewUrl: String?, photoView: ImageView) {
|
||||||
//Request image from the any cache
|
val glide = Glide.with(this)
|
||||||
Glide.with(this)
|
// Request image from the any cache
|
||||||
.load(url)
|
glide
|
||||||
.dontAnimate()
|
.load(url)
|
||||||
.onlyRetrieveFromCache(true)
|
.dontAnimate()
|
||||||
.error(
|
.onlyRetrieveFromCache(true)
|
||||||
//Request image from the network on fail load image from cache
|
.let {
|
||||||
Glide.with(this)
|
if (previewUrl != null)
|
||||||
.load(url)
|
it.thumbnail(glide
|
||||||
.centerInside()
|
.load(previewUrl)
|
||||||
.addListener(ImageRequestListener(false))
|
.dontAnimate()
|
||||||
)
|
.onlyRetrieveFromCache(true)
|
||||||
.centerInside()
|
.centerInside()
|
||||||
.addListener(ImageRequestListener(true))
|
.addListener(ImageRequestListener(true, isThumnailRequest = true)))
|
||||||
.into(photoView)
|
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
|
* @param isCacheRequest - is this listener for request image from cache or from the network
|
||||||
*/
|
*/
|
||||||
private inner class ImageRequestListener(private val isCacheRequest: Boolean) : RequestListener<Drawable> {
|
private inner class ImageRequestListener(
|
||||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
|
private val isCacheRequest: Boolean,
|
||||||
if (isCacheRequest) //Complete the transition on failed image from cache
|
private val isThumnailRequest: Boolean) : RequestListener<Drawable> {
|
||||||
completeTransition()
|
|
||||||
else
|
override fun onLoadFailed(e: GlideException?, model: Any, target: Target<Drawable>,
|
||||||
progressBar?.hide() //Hide progress bar only on fail request from internet
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
|
override fun onResourceReady(resource: Drawable, model: Any, target: Target<Drawable>,
|
||||||
progressBar?.hide() //Always hide the progress bar on success
|
dataSource: DataSource, isFirstResource: Boolean): Boolean {
|
||||||
resource?.let {
|
progressBar?.hide() // Always hide the progress bar on success
|
||||||
target?.onResourceReady(resource, null)
|
if (isThumnailRequest) {
|
||||||
if (isCacheRequest) completeTransition() //Complete transition on cache request only, because transition already completed on Network request
|
photoView.post {
|
||||||
|
target.onResourceReady(resource, null)
|
||||||
|
photoActionsListener.onBringUp()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
transition
|
||||||
|
.take(1)
|
||||||
|
.subscribe {
|
||||||
|
target.onResourceReady(resource, null)
|
||||||
|
photoActionsListener.onBringUp()
|
||||||
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun completeTransition() {
|
override fun onTransitionEnd() {
|
||||||
attacher.update()
|
this.transition.onNext(Unit)
|
||||||
photoActionsListener.onBringUp()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,25 +18,29 @@ package com.keylesspalace.tusky.fragment
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import com.keylesspalace.tusky.SharedElementTransitionListener
|
||||||
|
|
||||||
import com.keylesspalace.tusky.ViewMediaActivity
|
import com.keylesspalace.tusky.ViewMediaActivity
|
||||||
import com.keylesspalace.tusky.entity.Attachment
|
import com.keylesspalace.tusky.entity.Attachment
|
||||||
import com.keylesspalace.tusky.util.visible
|
import com.keylesspalace.tusky.util.visible
|
||||||
|
|
||||||
abstract class ViewMediaFragment : BaseFragment() {
|
abstract class ViewMediaFragment : BaseFragment(), SharedElementTransitionListener {
|
||||||
private var toolbarVisibiltyDisposable: Function0<Boolean>? = null
|
private var toolbarVisibiltyDisposable: Function0<Boolean>? = null
|
||||||
|
|
||||||
abstract fun setupMediaView(url: String)
|
abstract fun setupMediaView(url: String, previewUrl: String?)
|
||||||
abstract fun onToolbarVisibilityChange(visible: Boolean)
|
abstract fun onToolbarVisibilityChange(visible: Boolean)
|
||||||
abstract val descriptionView : TextView
|
abstract val descriptionView: TextView
|
||||||
|
|
||||||
protected var showingDescription = false
|
protected var showingDescription = false
|
||||||
protected var isDescriptionVisible = false
|
protected var isDescriptionVisible = false
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic protected val ARG_START_POSTPONED_TRANSITION = "startPostponedTransition"
|
@JvmStatic
|
||||||
@JvmStatic protected val ARG_ATTACHMENT = "attach"
|
protected val ARG_START_POSTPONED_TRANSITION = "startPostponedTransition"
|
||||||
@JvmStatic protected val ARG_AVATAR_URL = "avatarUrl"
|
@JvmStatic
|
||||||
|
protected val ARG_ATTACHMENT = "attach"
|
||||||
|
@JvmStatic
|
||||||
|
protected val ARG_AVATAR_URL = "avatarUrl"
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun newInstance(attachment: Attachment, shouldStartPostponedTransition: Boolean): ViewMediaFragment {
|
fun newInstance(attachment: Attachment, shouldStartPostponedTransition: Boolean): ViewMediaFragment {
|
||||||
|
@ -66,21 +70,20 @@ abstract class ViewMediaFragment : BaseFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun finalizeViewSetup(url: String, description: String?) {
|
protected fun finalizeViewSetup(url: String, previewUrl: String?, description: String?) {
|
||||||
val mediaActivity = activity as ViewMediaActivity
|
val mediaActivity = activity as ViewMediaActivity
|
||||||
setupMediaView(url)
|
setupMediaView(url, previewUrl)
|
||||||
|
|
||||||
descriptionView.text = description ?: ""
|
descriptionView.text = description ?: ""
|
||||||
showingDescription = !TextUtils.isEmpty(description)
|
showingDescription = !TextUtils.isEmpty(description)
|
||||||
isDescriptionVisible = showingDescription
|
isDescriptionVisible = showingDescription
|
||||||
|
|
||||||
descriptionView.visible(showingDescription && mediaActivity.isToolbarVisible())
|
descriptionView.visible(showingDescription && mediaActivity.isToolbarVisible)
|
||||||
|
|
||||||
toolbarVisibiltyDisposable = (activity as ViewMediaActivity).addToolbarVisibilityListener(object: ViewMediaActivity.ToolbarVisibilityListener {
|
toolbarVisibiltyDisposable = (activity as ViewMediaActivity)
|
||||||
override fun onToolbarVisiblityChanged(isVisible: Boolean) {
|
.addToolbarVisibilityListener { isVisible ->
|
||||||
onToolbarVisibilityChange(isVisible)
|
onToolbarVisibilityChange(isVisible)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -26,7 +26,6 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.MediaController
|
import android.widget.MediaController
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
|
||||||
import com.keylesspalace.tusky.R
|
import com.keylesspalace.tusky.R
|
||||||
import com.keylesspalace.tusky.ViewMediaActivity
|
import com.keylesspalace.tusky.ViewMediaActivity
|
||||||
import com.keylesspalace.tusky.entity.Attachment
|
import com.keylesspalace.tusky.entity.Attachment
|
||||||
|
@ -56,7 +55,7 @@ class ViewVideoFragment : ViewMediaFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isVisibleToUser) {
|
if (isVisibleToUser) {
|
||||||
if (mediaActivity.isToolbarVisible()) {
|
if (mediaActivity.isToolbarVisible) {
|
||||||
handler.postDelayed(hideToolbar, TOOLBAR_HIDE_DELAY_MS)
|
handler.postDelayed(hideToolbar, TOOLBAR_HIDE_DELAY_MS)
|
||||||
}
|
}
|
||||||
videoPlayer.start()
|
videoPlayer.start()
|
||||||
|
@ -68,7 +67,7 @@ class ViewVideoFragment : ViewMediaFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun setupMediaView(url: String) {
|
override fun setupMediaView(url: String, previewUrl: String?) {
|
||||||
descriptionView = mediaDescription
|
descriptionView = mediaDescription
|
||||||
val videoView = videoPlayer
|
val videoView = videoPlayer
|
||||||
videoView.transitionName = url
|
videoView.transitionName = url
|
||||||
|
@ -114,7 +113,7 @@ class ViewVideoFragment : ViewMediaFragment() {
|
||||||
throw IllegalArgumentException("attachment has to be set")
|
throw IllegalArgumentException("attachment has to be set")
|
||||||
}
|
}
|
||||||
url = attachment.url
|
url = attachment.url
|
||||||
finalizeViewSetup(url, attachment.description)
|
finalizeViewSetup(url, attachment.previewUrl, attachment.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onToolbarVisibilityChange(visible: Boolean) {
|
override fun onToolbarVisibilityChange(visible: Boolean) {
|
||||||
|
@ -139,4 +138,7 @@ class ViewVideoFragment : ViewMediaFragment() {
|
||||||
handler.removeCallbacks(hideToolbar)
|
handler.removeCallbacks(hideToolbar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onTransitionEnd() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,10 @@ package com.keylesspalace.tusky.pager
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentPagerAdapter
|
import androidx.fragment.app.FragmentPagerAdapter
|
||||||
|
import com.keylesspalace.tusky.SharedElementTransitionListener
|
||||||
import com.keylesspalace.tusky.fragment.ViewMediaFragment
|
import com.keylesspalace.tusky.fragment.ViewMediaFragment
|
||||||
import java.lang.IllegalStateException
|
|
||||||
|
|
||||||
class AvatarImagePagerAdapter(fragmentManager: FragmentManager, private val avatarUrl: String) : FragmentPagerAdapter(fragmentManager) {
|
|
||||||
|
|
||||||
|
class AvatarImagePagerAdapter(fragmentManager: FragmentManager, private val avatarUrl: String) : FragmentPagerAdapter(fragmentManager), SharedElementTransitionListener {
|
||||||
override fun getItem(position: Int): Fragment {
|
override fun getItem(position: Int): Fragment {
|
||||||
return if (position == 0) {
|
return if (position == 0) {
|
||||||
ViewMediaFragment.newAvatarInstance(avatarUrl)
|
ViewMediaFragment.newAvatarInstance(avatarUrl)
|
||||||
|
@ -19,4 +17,6 @@ class AvatarImagePagerAdapter(fragmentManager: FragmentManager, private val avat
|
||||||
|
|
||||||
override fun getCount() = 1
|
override fun getCount() = 1
|
||||||
|
|
||||||
|
override fun onTransitionEnd() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
package com.keylesspalace.tusky.pager
|
package com.keylesspalace.tusky.pager
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||||
|
import com.keylesspalace.tusky.SharedElementTransitionListener
|
||||||
import com.keylesspalace.tusky.entity.Attachment
|
import com.keylesspalace.tusky.entity.Attachment
|
||||||
import com.keylesspalace.tusky.fragment.ViewMediaFragment
|
import com.keylesspalace.tusky.fragment.ViewMediaFragment
|
||||||
import java.lang.IllegalStateException
|
import java.util.*
|
||||||
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
class ImagePagerAdapter(
|
class ImagePagerAdapter(
|
||||||
fragmentManager: FragmentManager,
|
fragmentManager: FragmentManager,
|
||||||
private val attachments: List<Attachment>,
|
private val attachments: List<Attachment>,
|
||||||
private val initialPosition: Int
|
private val initialPosition: Int
|
||||||
) : FragmentStatePagerAdapter(fragmentManager) {
|
) : FragmentStatePagerAdapter(fragmentManager), SharedElementTransitionListener {
|
||||||
|
|
||||||
|
private var primaryItem: ViewMediaFragment? = null
|
||||||
|
|
||||||
|
override fun setPrimaryItem(container: ViewGroup, position: Int, item: Any) {
|
||||||
|
super.setPrimaryItem(container, position, item)
|
||||||
|
this.primaryItem = item as ViewMediaFragment
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItem(position: Int): Fragment {
|
override fun getItem(position: Int): Fragment {
|
||||||
return if (position >= 0 && position < attachments.size) {
|
return if (position >= 0 && position < attachments.size) {
|
||||||
|
@ -31,4 +37,8 @@ class ImagePagerAdapter(
|
||||||
override fun getPageTitle(position: Int): CharSequence {
|
override fun getPageTitle(position: Int): CharSequence {
|
||||||
return String.format(Locale.getDefault(), "%d/%d", position + 1, attachments.size)
|
return String.format(Locale.getDefault(), "%d/%d", position + 1, attachments.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onTransitionEnd() {
|
||||||
|
primaryItem?.onTransitionEnd()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import com.google.gson.Gson
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.keylesspalace.tusky.db.*
|
import com.keylesspalace.tusky.db.*
|
||||||
import com.keylesspalace.tusky.entity.*
|
import com.keylesspalace.tusky.entity.*
|
||||||
import com.keylesspalace.tusky.entity.Status
|
|
||||||
import com.keylesspalace.tusky.network.MastodonApi
|
import com.keylesspalace.tusky.network.MastodonApi
|
||||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.DISK
|
import com.keylesspalace.tusky.repository.TimelineRequestMode.DISK
|
||||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.NETWORK
|
import com.keylesspalace.tusky.repository.TimelineRequestMode.NETWORK
|
||||||
|
|
Loading…
Reference in a new issue