fix: Show previews for playable audio media from accounts (#460)

Previous code showed a generic placeholder for audio media on the
account's "Media" tab.

Fix this so the preview image is shown (if it's available).

- Move the "is this attachment previewable?" code to `Attachment` so it
can be reused here.

- Restructure the logic in `AccountMediaGridAdapter` to use the new
`isPreviewable()` method when deciding whether to show a preview.

- Attachments have dedicated placeholder drawables, use those when the
preview is not available.
This commit is contained in:
Nik Clayton 2024-02-20 16:20:34 +01:00 committed by GitHub
parent 8293e90b73
commit 941f4677eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 56 additions and 67 deletions

View File

@ -216,17 +216,6 @@
column="5"/>
</issue>
<issue
id="MissingQuantity"
message="For locale &quot;ru&quot; (Russian) the following quantities should also be defined: `few` (e.g. &quot;из 2 книг за 2 дня&quot;), `many` (e.g. &quot;из 5 книг за 5 дней&quot;), `one` (e.g. &quot;из 1 книги за 1 день&quot;)"
errorLine1=" &lt;plurals name=&quot;hint_describe_for_visually_impaired&quot;>"
errorLine2=" ^">
<location
file="src/main/res/values-ru/strings.xml"
line="279"
column="5"/>
</issue>
<issue
id="MissingQuantity"
message="For locale &quot;hi&quot; (Hindi) the following quantity should also be defined: `one` (e.g. &quot;1 घंटा&quot;)"

View File

@ -897,14 +897,14 @@ abstract class StatusBaseViewHolder<T : IStatusViewData> protected constructor(i
}
companion object {
/**
* @return True if all [attachments] are previewable.
*
* @see Attachment.isPreviewable
*/
@JvmStatic
protected fun hasPreviewableAttachment(attachments: List<Attachment>): Boolean {
for (attachment in attachments) {
if (attachment.type == Attachment.Type.UNKNOWN) return false
if (attachment.meta?.original?.width == null && attachment.meta?.small?.width == null) return false
}
return true
return attachments.all { it.isPreviewable() }
}
private fun getReblogDescription(context: Context, status: IStatusViewData): CharSequence {

View File

@ -7,19 +7,18 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.setPadding
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import app.pachli.R
import app.pachli.adapter.isPlayable
import app.pachli.core.activity.decodeBlurHash
import app.pachli.core.common.extensions.hide
import app.pachli.core.common.extensions.show
import app.pachli.core.designsystem.R as DR
import app.pachli.core.common.extensions.visible
import app.pachli.core.navigation.AttachmentViewData
import app.pachli.core.network.model.Attachment
import app.pachli.databinding.ItemAccountMediaBinding
import app.pachli.util.BindingHolder
import app.pachli.util.getFormattedDescription
import app.pachli.util.iconResource
import com.bumptech.glide.Glide
import com.google.android.material.color.MaterialColors
import java.util.Random
@ -41,7 +40,7 @@ class AccountMediaGridAdapter(
) {
private val baseItemBackgroundColor = MaterialColors.getColor(context, com.google.android.material.R.attr.colorSurface, Color.BLACK)
private val videoIndicator = AppCompatResources.getDrawable(context, R.drawable.ic_play_indicator)
private val playableIcon = AppCompatResources.getDrawable(context, R.drawable.ic_play_indicator)
private val mediaHiddenDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_hide_media_24dp)
private val itemBgBaseHSV = FloatArray(3)
@ -57,59 +56,53 @@ class AccountMediaGridAdapter(
override fun onBindViewHolder(holder: BindingHolder<ItemAccountMediaBinding>, position: Int) {
val context = holder.binding.root.context
getItem(position)?.let { item ->
getItem(position)?.let { item ->
val imageView = holder.binding.accountMediaImageView
val overlay = holder.binding.accountMediaImageViewOverlay
val blurhash = item.attachment.blurhash
val placeholder = if (useBlurhash && blurhash != null) {
decodeBlurHash(context, blurhash)
} else {
null
val placeholder = item.attachment.blurhash?.let {
if (useBlurhash) decodeBlurHash(context, it) else null
}
if (item.attachment.type == Attachment.Type.AUDIO) {
overlay.hide()
imageView.setPadding(context.resources.getDimensionPixelSize(DR.dimen.profile_media_audio_icon_padding))
Glide.with(imageView)
.load(R.drawable.ic_music_box_preview_24dp)
.centerInside()
.into(imageView)
imageView.contentDescription = item.attachment.getFormattedDescription(context)
} else if (item.sensitive && !item.isRevealed) {
overlay.show()
overlay.setImageDrawable(mediaHiddenDrawable)
imageView.setPadding(0)
Glide.with(imageView)
.load(placeholder)
.centerInside()
.into(imageView)
imageView.contentDescription = imageView.context.getString(R.string.post_media_hidden_title)
} else {
if (item.attachment.type == Attachment.Type.VIDEO || item.attachment.type == Attachment.Type.GIFV) {
when {
item.sensitive && !item.isRevealed -> {
overlay.show()
overlay.setImageDrawable(videoIndicator)
} else {
overlay.hide()
overlay.setImageDrawable(mediaHiddenDrawable)
Glide.with(imageView)
.load(placeholder)
.centerInside()
.into(imageView)
imageView.contentDescription = context.getString(R.string.post_media_hidden_title)
}
imageView.setPadding(0)
item.attachment.isPreviewable() -> {
if (item.attachment.type.isPlayable()) overlay.setImageDrawable(playableIcon)
overlay.visible(item.attachment.type.isPlayable())
Glide.with(imageView)
.asBitmap()
.load(item.attachment.previewUrl)
.placeholder(placeholder)
.centerInside()
.into(imageView)
Glide.with(imageView)
.asBitmap()
.load(item.attachment.previewUrl)
.placeholder(placeholder)
.centerInside()
.into(imageView)
imageView.contentDescription = item.attachment.getFormattedDescription(context)
imageView.contentDescription = item.attachment.getFormattedDescription(context)
}
else -> {
if (item.attachment.type.isPlayable()) overlay.setImageDrawable(playableIcon)
overlay.visible(item.attachment.type.isPlayable())
Glide.with(imageView)
.load(item.attachment.iconResource())
.centerInside()
.into(imageView)
imageView.contentDescription = item.attachment.getFormattedDescription(context)
}
}
holder.binding.root.setOnClickListener {
@ -118,7 +111,7 @@ class AccountMediaGridAdapter(
holder.binding.root.setOnLongClickListener { view ->
val description = item.attachment.getFormattedDescription(view.context)
Toast.makeText(view.context, description, Toast.LENGTH_LONG).show()
Toast.makeText(context, description, Toast.LENGTH_LONG).show()
true
}
}

View File

@ -63,8 +63,6 @@
<dimen name="profile_media_spacing">3dp</dimen>
<dimen name="profile_media_audio_icon_padding">16dp</dimen>
<dimen name="preview_image_spacing">4dp</dimen>
<dimen name="graph_line_thickness">1dp</dimen>

View File

@ -103,4 +103,13 @@ data class Attachment(
return (width / height).toDouble()
}
}
/**
* @return True if this attachment can be previewed. A previewable attachment
* must be a known type and have a non-null width for the preview image.
*/
fun isPreviewable(): Boolean {
if (type == Type.UNKNOWN) return false
return !(meta?.original?.width == null && meta?.small?.width == null)
}
}