Description improvements (#1846)

* Increase character limit for media descriptions to 1500

It was increased in Mastodon 3.0.0 which was released in October 2019.

* Improve image description view

Since media descriptions can be longer now, we need to adjust the UI.
It is a common problem that description takes up the whole screen, it's
hard for readers and also discourages people from adding descriptions.

This commit uses bottom sheet to hide most of the description. Since we
know how much screen space it will cover, we can use darker background
which makes reading text easier.

* Adjust description handle

* Fix unable to dismiss image caption
This commit is contained in:
Ivan Kupalov 2020-08-01 21:48:51 +02:00 committed by GitHub
commit ed2918da2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 81 deletions

View file

@ -21,9 +21,11 @@ import android.annotation.SuppressLint
import android.content.Context
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.*
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
@ -57,16 +59,52 @@ class ViewImageFragment : ViewMediaFragment() {
@Volatile
private var startedTransition = false
override lateinit var descriptionView: TextView
override fun onAttach(context: Context) {
super.onAttach(context)
photoActionsListener = context as PhotoActionsListener
}
@SuppressLint("ClickableViewAccessibility")
override fun setupMediaView(url: String, previewUrl: String?) {
descriptionView = mediaDescription
override fun setupMediaView(
url: String,
previewUrl: String?,
description: String?,
showingDescription: Boolean
) {
photoView.transitionName = url
mediaDescription.text = description
captionSheet.visible(showingDescription)
startedTransition = false
loadImageFromNetwork(url, previewUrl, photoView)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
toolbar = requireActivity().toolbar
this.transition = BehaviorSubject.create()
return inflater.inflate(R.layout.fragment_view_image, container, false)
}
@SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val arguments = this.requireArguments()
val attachment = arguments.getParcelable<Attachment>(ARG_ATTACHMENT)
this.shouldStartTransition = arguments.getBoolean(ARG_START_POSTPONED_TRANSITION)
val url: String?
var description: String? = null
if (attachment != null) {
url = attachment.url
description = attachment.description
} else {
url = arguments.getString(ARG_AVATAR_URL)
if (url == null) {
throw IllegalArgumentException("attachment or avatar url has to be set")
}
}
attacher = PhotoViewAttacher(photoView).apply {
// This prevents conflicts with ViewPager
setAllowParentInterceptOnEdge(true)
@ -87,21 +125,12 @@ class ViewImageFragment : ViewMediaFragment() {
}
}
val gestureDetector = GestureDetector(requireContext(), object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
onMediaTap()
return true
}
})
var lastY = 0f
photoView.setOnTouchListener { v, event ->
// This part is for scaling/translating on vertical move.
// We use raw coordinates to get the correct ones during scaling
gestureDetector.onTouchEvent(event)
if (event.action == MotionEvent.ACTION_DOWN) {
lastY = event.rawY
} else if (event.pointerCount == 1
@ -125,36 +154,6 @@ class ViewImageFragment : ViewMediaFragment() {
attacher.onTouch(v, event)
}
startedTransition = false
loadImageFromNetwork(url, previewUrl, photoView)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
toolbar = requireActivity().toolbar
this.transition = BehaviorSubject.create()
return inflater.inflate(R.layout.fragment_view_image, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val arguments = this.requireArguments()
val attachment = arguments.getParcelable<Attachment>(ARG_ATTACHMENT)
this.shouldStartTransition = arguments.getBoolean(ARG_START_POSTPONED_TRANSITION)
val url: String?
var description: String? = null
if (attachment != null) {
url = attachment.url
description = attachment.description
} else {
url = arguments.getString(ARG_AVATAR_URL)
if (url == null) {
throw IllegalArgumentException("attachment or avatar url has to be set")
}
}
finalizeViewSetup(url, attachment?.previewUrl, description)
}
@ -176,10 +175,10 @@ class ViewImageFragment : ViewMediaFragment() {
}
isDescriptionVisible = showingDescription && visible
val alpha = if (isDescriptionVisible) 1.0f else 0.0f
descriptionView.animate().alpha(alpha)
captionSheet.animate().alpha(alpha)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
descriptionView.visible(isDescriptionVisible)
captionSheet.visible(isDescriptionVisible)
animation.removeListener(this)
}
})