Gif support

This commit is contained in:
Valere 2020-07-06 09:45:42 +02:00
parent 4a2a6d34ae
commit 2d4a728af4
6 changed files with 127 additions and 12 deletions

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.riotx.attachment_viewer
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ProgressBar
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import com.bumptech.glide.request.target.CustomViewTarget
import com.bumptech.glide.request.transition.Transition
import com.github.chrisbanes.photoview.PhotoView
class AnimatedImageViewHolder constructor(itemView: View) :
BaseViewHolder(itemView) {
val touchImageView: ImageView = itemView.findViewById(R.id.imageView)
val imageLoaderProgress: ProgressBar = itemView.findViewById(R.id.imageLoaderProgress)
val customTargetView = object : CustomViewTarget<ImageView, Drawable>(touchImageView) {
override fun onResourceLoading(placeholder: Drawable?) {
imageLoaderProgress.isVisible = true
}
override fun onLoadFailed(errorDrawable: Drawable?) {
imageLoaderProgress.isVisible = false
}
override fun onResourceCleared(placeholder: Drawable?) {
touchImageView.setImageDrawable(placeholder)
}
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
imageLoaderProgress.isVisible = false
// Glide mess up the view size :/
touchImageView.updateLayoutParams {
width = LinearLayout.LayoutParams.MATCH_PARENT
height = LinearLayout.LayoutParams.MATCH_PARENT
}
touchImageView.setImageDrawable(resource)
if (resource is Animatable) {
resource.start();
}
}
}
override fun bind(attachmentInfo: AttachmentInfo) {
}
}

View file

@ -18,6 +18,7 @@ package im.vector.riotx.attachment_viewer
sealed class AttachmentInfo {
data class Image(val url: String, val data: Any?) : AttachmentInfo()
data class AnimatedImage(val url: String, val data: Any?) : AttachmentInfo()
data class Video(val url: String, val data: Any) : AttachmentInfo()
data class Audio(val url: String, val data: Any) : AttachmentInfo()
data class File(val url: String, val data: Any) : AttachmentInfo()
@ -32,5 +33,6 @@ interface AttachmentSourceProvider {
fun getAttachmentInfoAt(position: Int): AttachmentInfo
fun loadImage(holder: ImageViewHolder, info: AttachmentInfo.Image)
fun loadImage(holder: ZoomableImageViewHolder, info: AttachmentInfo.Image)
fun loadImage(holder: AnimatedImageViewHolder, info: AttachmentInfo.AnimatedImage)
}

View file

@ -60,7 +60,8 @@ class AttachmentsAdapter() : RecyclerView.Adapter<BaseViewHolder>() {
val inflater = LayoutInflater.from(parent.context)
val itemView = inflater.inflate(viewType, parent, false)
return when (viewType) {
R.layout.item_image_attachment -> ImageViewHolder(itemView)
R.layout.item_image_attachment -> ZoomableImageViewHolder(itemView)
R.layout.item_animated_image_attachment -> AnimatedImageViewHolder(itemView)
else -> AttachmentViewHolder(itemView)
}
}
@ -70,6 +71,7 @@ class AttachmentsAdapter() : RecyclerView.Adapter<BaseViewHolder>() {
return when (info) {
is AttachmentInfo.Image -> R.layout.item_image_attachment
is AttachmentInfo.Video -> R.layout.item_video_attachment
is AttachmentInfo.AnimatedImage -> R.layout.item_animated_image_attachment
is AttachmentInfo.Audio -> TODO()
is AttachmentInfo.File -> TODO()
}
@ -83,15 +85,22 @@ class AttachmentsAdapter() : RecyclerView.Adapter<BaseViewHolder>() {
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
attachmentSourceProvider?.getAttachmentInfoAt(position)?.let {
holder.bind(it)
if (it is AttachmentInfo.Image) {
attachmentSourceProvider?.loadImage(holder as ImageViewHolder, it)
when(it) {
is AttachmentInfo.Image -> {
attachmentSourceProvider?.loadImage(holder as ZoomableImageViewHolder, it)
}
is AttachmentInfo.AnimatedImage -> {
attachmentSourceProvider?.loadImage(holder as AnimatedImageViewHolder, it)
}
else -> {}
}
}
}
fun isScaled(position: Int): Boolean {
val holder = recyclerView?.findViewHolderForAdapterPosition(position)
if (holder is ImageViewHolder) {
if (holder is ZoomableImageViewHolder) {
return holder.touchImageView.attacher.scale > 1f
}
return false

View file

@ -27,7 +27,7 @@ import com.bumptech.glide.request.target.CustomViewTarget
import com.bumptech.glide.request.transition.Transition
import com.github.chrisbanes.photoview.PhotoView
class ImageViewHolder constructor(itemView: View) :
class ZoomableImageViewHolder constructor(itemView: View) :
BaseViewHolder(itemView) {
val touchImageView: PhotoView = itemView.findViewById(R.id.touchImageView)

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<ImageView
android:id="@+id/imageView"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ProgressBar
android:layout_centerInParent="true"
android:id="@+id/imageLoaderProgress"
style="?android:attr/progressBarStyle"
android:layout_width="40dp"
android:layout_height="40dp"
android:visibility="visible"
tools:visibility="gone" />
</RelativeLayout>

View file

@ -24,9 +24,10 @@ import im.vector.matrix.android.api.session.room.model.message.MessageWithAttach
import im.vector.matrix.android.api.session.room.model.message.getFileUrl
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
import im.vector.riotx.attachment_viewer.AnimatedImageViewHolder
import im.vector.riotx.attachment_viewer.AttachmentInfo
import im.vector.riotx.attachment_viewer.AttachmentSourceProvider
import im.vector.riotx.attachment_viewer.ImageViewHolder
import im.vector.riotx.attachment_viewer.ZoomableImageViewHolder
import javax.inject.Inject
class RoomAttachmentProvider(
@ -53,14 +54,27 @@ class RoomAttachmentProvider(
width = null,
height = null
)
AttachmentInfo.Image(
content?.url ?: "",
data
)
if (content?.mimeType == "image/gif") {
AttachmentInfo.AnimatedImage(
content.url ?: "",
data
)
} else {
AttachmentInfo.Image(
content?.url ?: "",
data
)
}
}
}
override fun loadImage(holder: ImageViewHolder, info: AttachmentInfo.Image) {
override fun loadImage(holder: ZoomableImageViewHolder, info: AttachmentInfo.Image) {
(info.data as? ImageContentRenderer.Data)?.let {
imageContentRenderer.render(it, holder.touchImageView, holder.customTargetView as CustomViewTarget<*, Drawable>)
}
}
override fun loadImage(holder: AnimatedImageViewHolder, info: AttachmentInfo.AnimatedImage) {
(info.data as? ImageContentRenderer.Data)?.let {
imageContentRenderer.render(it, holder.touchImageView, holder.customTargetView as CustomViewTarget<*, Drawable>)
}