mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-24 10:25:51 +03:00
Media : start to refact renderer to be more generic
This commit is contained in:
parent
f9ca8f35bc
commit
7c4ac7b53a
5 changed files with 112 additions and 100 deletions
|
@ -2,12 +2,11 @@ package im.vector.riotredesign.features.home.room.detail.timeline
|
|||
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.features.media.MessageImageRenderer
|
||||
import im.vector.riotredesign.features.media.MediaContentRenderer
|
||||
|
||||
class MessageImageItem(
|
||||
private val messageContent: MessageImageContent,
|
||||
private val mediaData: MediaContentRenderer.Data,
|
||||
informationData: MessageInformationData
|
||||
) : AbsMessageItem(informationData, R.layout.item_timeline_event_image_message) {
|
||||
|
||||
|
@ -18,7 +17,7 @@ class MessageImageItem(
|
|||
|
||||
override fun bind() {
|
||||
super.bind()
|
||||
MessageImageRenderer.render(messageContent, imageView)
|
||||
MediaContentRenderer.render(mediaData, MediaContentRenderer.Mode.THUMBNAIL, imageView)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
|||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
|
||||
import im.vector.riotredesign.core.extensions.localDateTime
|
||||
import im.vector.riotredesign.features.media.MediaContentRenderer
|
||||
|
||||
class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatter) {
|
||||
|
||||
|
@ -28,12 +29,12 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte
|
|||
val nextDate = nextEvent?.root?.localDateTime()
|
||||
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
|
||||
val isNextMessageReceivedMoreThanOneHourAgo = nextDate?.isBefore(date.minusMinutes(60))
|
||||
?: false
|
||||
?: false
|
||||
|
||||
if (addDaySeparator
|
||||
|| nextRoomMember != roomMember
|
||||
|| nextEvent?.root?.type != EventType.MESSAGE
|
||||
|| isNextMessageReceivedMoreThanOneHourAgo) {
|
||||
|| nextRoomMember != roomMember
|
||||
|| nextEvent?.root?.type != EventType.MESSAGE
|
||||
|| isNextMessageReceivedMoreThanOneHourAgo) {
|
||||
messagesDisplayedWithInformation.add(event.root.eventId)
|
||||
}
|
||||
|
||||
|
@ -51,8 +52,19 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte
|
|||
}
|
||||
}
|
||||
|
||||
private fun buildImageMessageItem(messageContent: MessageImageContent, informationData: MessageInformationData): MessageImageItem? {
|
||||
return MessageImageItem(messageContent, informationData)
|
||||
private fun buildImageMessageItem(messageContent: MessageImageContent,
|
||||
informationData: MessageInformationData): MessageImageItem? {
|
||||
// TODO : manage maxHeight/maxWidth
|
||||
val data = MediaContentRenderer.Data(
|
||||
url = messageContent.url,
|
||||
height = messageContent.info.height,
|
||||
maxHeight = 800,
|
||||
width = messageContent.info.width,
|
||||
maxWidth = 800,
|
||||
rotation = messageContent.info.rotation,
|
||||
orientation = messageContent.info.orientation
|
||||
)
|
||||
return MessageImageItem(data, informationData)
|
||||
}
|
||||
|
||||
private fun buildTextMessageItem(messageContent: MessageTextContent,
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package im.vector.riotredesign.features.media
|
||||
|
||||
import android.media.ExifInterface
|
||||
import android.widget.ImageView
|
||||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||
import im.vector.riotredesign.core.glide.GlideApp
|
||||
|
||||
object MediaContentRenderer {
|
||||
|
||||
data class Data(
|
||||
val url: String?,
|
||||
val height: Int,
|
||||
val maxHeight: Int,
|
||||
val width: Int,
|
||||
val maxWidth: Int = width,
|
||||
val orientation: Int,
|
||||
val rotation: Int
|
||||
)
|
||||
|
||||
enum class Mode {
|
||||
FULL_SIZE,
|
||||
THUMBNAIL
|
||||
}
|
||||
|
||||
fun render(data: Data, mode: Mode, imageView: ImageView) {
|
||||
val (width, height) = processSize(data, mode)
|
||||
imageView.layoutParams.height = height
|
||||
imageView.layoutParams.width = width
|
||||
|
||||
val contentUrlResolver = Matrix.getInstance().currentSession.contentUrlResolver()
|
||||
val resolvedUrl = when (mode) {
|
||||
Mode.FULL_SIZE -> contentUrlResolver.resolveFullSize(data.url)
|
||||
Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, width, height, ContentUrlResolver.ThumbnailMethod.SCALE)
|
||||
}
|
||||
?: return
|
||||
|
||||
GlideApp
|
||||
.with(imageView)
|
||||
.load(resolvedUrl)
|
||||
.thumbnail(0.3f)
|
||||
.into(imageView)
|
||||
}
|
||||
|
||||
private fun processSize(data: Data, mode: Mode): Pair<Int, Int> {
|
||||
val maxImageWidth = data.maxWidth
|
||||
val maxImageHeight = data.maxHeight
|
||||
val rotationAngle = data.rotation
|
||||
val orientation = data.orientation
|
||||
var width = data.width
|
||||
var height = data.height
|
||||
var finalHeight = -1
|
||||
var finalWidth = -1
|
||||
|
||||
// if the image size is known
|
||||
// compute the expected height
|
||||
if (width > 0 && height > 0) {
|
||||
// swap width and height if the image is side oriented
|
||||
if (rotationAngle == 90 || rotationAngle == 270) {
|
||||
val tmp = width
|
||||
width = height
|
||||
height = tmp
|
||||
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90 || orientation == ExifInterface.ORIENTATION_ROTATE_270) {
|
||||
val tmp = width
|
||||
width = height
|
||||
height = tmp
|
||||
}
|
||||
if (mode == Mode.FULL_SIZE) {
|
||||
finalHeight = height
|
||||
finalWidth = width
|
||||
} else {
|
||||
finalHeight = Math.min(maxImageWidth * height / width, maxImageHeight)
|
||||
finalWidth = finalHeight * width / height
|
||||
}
|
||||
}
|
||||
// ensure that some values are properly initialized
|
||||
if (finalHeight < 0) {
|
||||
finalHeight = maxImageHeight
|
||||
}
|
||||
if (finalWidth < 0) {
|
||||
finalWidth = maxImageWidth
|
||||
}
|
||||
return Pair(finalWidth, finalHeight)
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package im.vector.riotredesign.features.media
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Point
|
||||
import android.media.ExifInterface
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
||||
import im.vector.riotredesign.core.glide.GlideApp
|
||||
|
||||
object MessageImageRenderer {
|
||||
|
||||
fun render(messageContent: MessageImageContent, imageView: ImageView) {
|
||||
val (maxImageWidth, maxImageHeight) = computeMaxSize(imageView.context)
|
||||
val imageInfo = messageContent.info
|
||||
val rotationAngle = imageInfo.rotation ?: 0
|
||||
val orientation = imageInfo.orientation ?: ExifInterface.ORIENTATION_NORMAL
|
||||
var width = imageInfo.width
|
||||
var height = imageInfo.height
|
||||
|
||||
var finalHeight = -1
|
||||
var finalWidth = -1
|
||||
|
||||
// if the image size is known
|
||||
// compute the expected height
|
||||
if (width > 0 && height > 0) {
|
||||
// swap width and height if the image is side oriented
|
||||
if (rotationAngle == 90 || rotationAngle == 270) {
|
||||
val tmp = width
|
||||
width = height
|
||||
height = tmp
|
||||
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90 || orientation == ExifInterface.ORIENTATION_ROTATE_270) {
|
||||
val tmp = width
|
||||
width = height
|
||||
height = tmp
|
||||
}
|
||||
finalHeight = Math.min(maxImageWidth * height / width, maxImageHeight)
|
||||
finalWidth = finalHeight * width / height
|
||||
}
|
||||
// ensure that some values are properly initialized
|
||||
if (finalHeight < 0) {
|
||||
finalHeight = maxImageHeight
|
||||
}
|
||||
if (finalWidth < 0) {
|
||||
finalWidth = maxImageWidth
|
||||
}
|
||||
imageView.layoutParams.height = finalHeight
|
||||
imageView.layoutParams.width = finalWidth
|
||||
|
||||
val contentUrlResolver = Matrix.getInstance().currentSession.contentUrlResolver()
|
||||
val resolvedUrl = contentUrlResolver.resolveThumbnail(
|
||||
messageContent.url,
|
||||
finalWidth,
|
||||
finalHeight,
|
||||
ContentUrlResolver.ThumbnailMethod.SCALE
|
||||
) ?: return
|
||||
|
||||
GlideApp
|
||||
.with(imageView)
|
||||
.load(resolvedUrl)
|
||||
.into(imageView)
|
||||
}
|
||||
|
||||
private fun computeMaxSize(context: Context): Pair<Int, Int> {
|
||||
val size = Point(0, 0)
|
||||
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
wm.defaultDisplay.getSize(size)
|
||||
val screenWidth = size.x
|
||||
val screenHeight = size.y
|
||||
val maxImageWidth: Int
|
||||
val maxImageHeight: Int
|
||||
// landscape / portrait
|
||||
if (screenWidth < screenHeight) {
|
||||
maxImageWidth = Math.round(screenWidth * 0.6f)
|
||||
maxImageHeight = Math.round(screenHeight * 0.4f)
|
||||
} else {
|
||||
maxImageWidth = Math.round(screenWidth * 0.4f)
|
||||
maxImageHeight = Math.round(screenHeight * 0.6f)
|
||||
}
|
||||
return Pair(maxImageWidth, maxImageHeight)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +1,17 @@
|
|||
package im.vector.matrix.android.api.session.room.model.message
|
||||
|
||||
import android.media.ExifInterface
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ImageInfo(
|
||||
@Json(name = "mimetype") val mimeType: String,
|
||||
@Json(name = "w") val width: Int,
|
||||
@Json(name = "h") val height: Int,
|
||||
@Json(name = "size") val size: Int,
|
||||
@Json(name = "rotation") val rotation: Int? = null,
|
||||
@Json(name = "orientation") val orientation: Int? = null,
|
||||
@Json(name = "w") val width: Int = 0,
|
||||
@Json(name = "h") val height: Int = 0,
|
||||
@Json(name = "size") val size: Int = 0,
|
||||
@Json(name = "rotation") val rotation: Int = 0,
|
||||
@Json(name = "orientation") val orientation: Int = ExifInterface.ORIENTATION_NORMAL,
|
||||
@Json(name = "thumbnail_info") val thumbnailInfo: ThumbnailInfo? = null,
|
||||
@Json(name = "thumbnail_url") val thumbnailUrl: String? = null
|
||||
)
|
Loading…
Reference in a new issue