sms-translate/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/AttachmentsAdapter.kt
2022-11-06 09:51:40 +01:00

207 lines
8.7 KiB
Kotlin

package com.simplemobiletools.smsmessenger.adapters
import android.content.Intent
import android.graphics.drawable.Drawable
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity
import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.AttachmentSelection
import kotlinx.android.synthetic.main.item_attachment_media_preview.view.*
import kotlinx.android.synthetic.main.item_remove_attachment_button.view.*
class AttachmentsAdapter(
val activity: BaseSimpleActivity,
val recyclerView: RecyclerView,
val onAttachmentsRemoved: () -> Unit,
val onReady: (() -> Unit)
) : ListAdapter<AttachmentSelection, AttachmentsAdapter.ViewHolder>(AttachmentDiffCallback()) {
private val config = activity.config
private val resources = activity.resources
private val primaryColor = activity.getProperPrimaryColor()
private val imageCompressor by lazy { ImageCompressor(activity) }
val attachments = mutableListOf<AttachmentSelection>()
override fun getItemViewType(position: Int): Int {
return getItem(position).viewType
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutRes = when (viewType) {
ATTACHMENT_DOCUMENT -> R.layout.item_attachment_document_preview
ATTACHMENT_VCARD -> R.layout.item_attachment_vcard_preview
ATTACHMENT_MEDIA -> R.layout.item_attachment_media_preview
else -> throw IllegalArgumentException("Unknown view type: $viewType")
}
val view = activity.layoutInflater.inflate(layoutRes, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val attachment = getItem(position)
holder.bindView() { view, _ ->
when (attachment.viewType) {
ATTACHMENT_DOCUMENT -> {
view.setupDocumentPreview(
uri = attachment.uri,
title = attachment.filename,
mimeType = attachment.mimetype,
attachment = true,
onClick = { activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename) },
onRemoveButtonClicked = { removeAttachment(attachment) }
)
}
ATTACHMENT_VCARD -> {
view.setupVCardPreview(
activity = activity,
uri = attachment.uri,
attachment = true,
onClick = {
val intent = Intent(activity, VCardViewerActivity::class.java).also {
it.putExtra(EXTRA_VCARD_URI, attachment.uri)
}
activity.startActivity(intent)
},
onRemoveButtonClicked = { removeAttachment(attachment) }
)
}
ATTACHMENT_MEDIA -> setupMediaPreview(view, attachment)
}
}
}
fun clear() {
attachments.clear()
submitList(emptyList())
recyclerView.onGlobalLayout {
onAttachmentsRemoved()
}
}
fun addAttachment(attachment: AttachmentSelection) {
attachments.removeAll { AttachmentSelection.areItemsTheSame(it, attachment) }
attachments.add(attachment)
submitList(attachments.toList())
}
private fun removeAttachment(attachment: AttachmentSelection) {
attachments.removeAll { AttachmentSelection.areItemsTheSame(it, attachment) }
if (attachments.isEmpty()) {
clear()
} else {
submitList(attachments.toList())
}
}
private fun setupMediaPreview(view: View, attachment: AttachmentSelection) {
view.apply {
media_attachment_holder.background.applyColorFilter(primaryColor.darkenColor())
media_attachment_holder.setOnClickListener {
activity.launchViewIntent(attachment.uri, attachment.mimetype, attachment.filename)
}
remove_attachment_button.apply {
beVisible()
background.applyColorFilter(primaryColor)
setOnClickListener {
removeAttachment(attachment)
}
}
val compressImage = attachment.mimetype.isImageMimeType() && !attachment.mimetype.isGifMimeType()
if (compressImage && attachment.isPending && config.mmsFileSizeLimit != FILE_SIZE_NONE) {
thumbnail.beGone()
compression_progress.beVisible()
imageCompressor.compressImage(attachment.uri, config.mmsFileSizeLimit) { compressedUri ->
activity.runOnUiThread {
when (compressedUri) {
attachment.uri -> {
attachments.find { it.uri == attachment.uri }?.isPending = false
loadMediaPreview(view, attachment)
}
null -> {
activity.toast(R.string.compress_error)
removeAttachment(attachment)
}
else -> {
attachments.remove(attachment)
addAttachment(attachment.copy(uri = compressedUri, isPending = false))
}
}
onReady()
}
}
} else {
loadMediaPreview(view, attachment)
}
}
}
private fun loadMediaPreview(view: View, attachment: AttachmentSelection) {
val roundedCornersRadius = resources.getDimension(R.dimen.activity_margin).toInt()
val size = resources.getDimension(R.dimen.attachment_preview_size).toInt()
val options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.transform(CenterCrop(), RoundedCorners(roundedCornersRadius))
Glide.with(view.thumbnail)
.load(attachment.uri)
.transition(DrawableTransitionOptions.withCrossFade())
.override(size, size)
.apply(options)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
removeAttachment(attachment)
activity.toast(R.string.unknown_error_occurred)
return false
}
override fun onResourceReady(dr: Drawable?, a: Any?, t: Target<Drawable>?, d: DataSource?, i: Boolean): Boolean {
view.thumbnail.beVisible()
view.play_icon.beVisibleIf(attachment.mimetype.isVideoMimeType())
view.compression_progress.beGone()
return false
}
})
.into(view.thumbnail)
}
open inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindView(callback: (itemView: View, adapterPosition: Int) -> Unit): View {
return itemView.apply {
callback(this, adapterPosition)
}
}
}
}
private class AttachmentDiffCallback : DiffUtil.ItemCallback<AttachmentSelection>() {
override fun areItemsTheSame(oldItem: AttachmentSelection, newItem: AttachmentSelection): Boolean {
return AttachmentSelection.areItemsTheSame(oldItem, newItem)
}
override fun areContentsTheSame(oldItem: AttachmentSelection, newItem: AttachmentSelection): Boolean {
return AttachmentSelection.areContentsTheSame(oldItem, newItem)
}
}