diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml
index 15e2fc2fbb..04ed7fcc55 100644
--- a/library/ui-styles/src/main/res/values/dimens.xml
+++ b/library/ui-styles/src/main/res/values/dimens.xml
@@ -44,6 +44,7 @@
8dp
+ 160dp
56dp
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt
index 33fc8b052b..bfba43a82d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/media/PreviewUrlData.kt
@@ -47,5 +47,9 @@ data class PreviewUrlData(
// Value of field "og:description"
val description: String?,
// Value of field "og:image"
- val mxcUrl: String?
+ val mxcUrl: String?,
+ // Value of field "og:image:width"
+ val imageWidth: Int?,
+ // Value of field "og:image:height"
+ val imageHeight: Int?
)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
index 1f45ac2a75..7a2511feac 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt
@@ -56,7 +56,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
) : RealmMigration {
companion object {
- const val SESSION_STORE_SCHEMA_VERSION = 21L
+ const val SESSION_STORE_SCHEMA_VERSION = 22L
}
/**
@@ -90,6 +90,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
if (oldVersion <= 18) migrateTo19(realm)
if (oldVersion <= 19) migrateTo20(realm)
if (oldVersion <= 20) migrateTo21(realm)
+ if (oldVersion <= 21) migrateTo22(realm)
}
private fun migrateTo1(realm: DynamicRealm) {
@@ -445,4 +446,15 @@ internal class RealmSessionStoreMigration @Inject constructor(
}
}
}
+
+ private fun migrateTo22(realm: DynamicRealm) {
+ Timber.d("Step 21 -> 22")
+
+ realm.schema.get("PreviewUrlCacheEntity")
+ ?.addField(PreviewUrlCacheEntityFields.IMAGE_WIDTH, Int::class.java)
+ ?.setNullable(PreviewUrlCacheEntityFields.IMAGE_WIDTH, true)
+ ?.addField(PreviewUrlCacheEntityFields.IMAGE_HEIGHT, Int::class.java)
+ ?.setNullable(PreviewUrlCacheEntityFields.IMAGE_HEIGHT, true)
+ }
+
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PreviewUrlCacheEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PreviewUrlCacheEntity.kt
index b1e0b64405..f19d70a1f2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PreviewUrlCacheEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/PreviewUrlCacheEntity.kt
@@ -28,7 +28,8 @@ internal open class PreviewUrlCacheEntity(
var title: String? = null,
var description: String? = null,
var mxcUrl: String? = null,
-
+ var imageWidth: Int? = null,
+ var imageHeight: Int? = null,
var lastUpdatedTimestamp: Long = 0L
) : RealmObject() {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt
index e707c2351c..32bcf3f7ca 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/GetPreviewUrlTask.kt
@@ -48,8 +48,8 @@ internal class DefaultGetPreviewUrlTask @Inject constructor(
override suspend fun execute(params: GetPreviewUrlTask.Params): PreviewUrlData {
return when (params.cacheStrategy) {
- CacheStrategy.NoCache -> doRequest(params.url, params.timestamp)
- is CacheStrategy.TtlCache -> doRequestWithCache(
+ CacheStrategy.NoCache -> doRequest(params.url, params.timestamp)
+ is CacheStrategy.TtlCache -> doRequestWithCache(
params.url,
params.timestamp,
params.cacheStrategy.validityDurationInMillis,
@@ -77,7 +77,9 @@ internal class DefaultGetPreviewUrlTask @Inject constructor(
siteName = (get("og:site_name") as? String)?.unescapeHtml(),
title = (get("og:title") as? String)?.unescapeHtml(),
description = (get("og:description") as? String)?.unescapeHtml(),
- mxcUrl = get("og:image") as? String
+ mxcUrl = get("og:image") as? String,
+ imageHeight = (get("og:image:height") as? Double)?.toInt(),
+ imageWidth = (get("og:image:width") as? Double)?.toInt(),
)
}
@@ -114,7 +116,8 @@ internal class DefaultGetPreviewUrlTask @Inject constructor(
previewUrlCacheEntity.title = data.title
previewUrlCacheEntity.description = data.description
previewUrlCacheEntity.mxcUrl = data.mxcUrl
-
+ previewUrlCacheEntity.imageHeight = data.imageHeight
+ previewUrlCacheEntity.imageWidth = data.imageWidth
previewUrlCacheEntity.lastUpdatedTimestamp = Date().time
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt
index dd1a9ead26..551dc29b92 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/media/PreviewUrlMapper.kt
@@ -27,5 +27,7 @@ internal fun PreviewUrlCacheEntity.toDomain() = PreviewUrlData(
siteName = siteName,
title = title,
description = description,
- mxcUrl = mxcUrl
+ mxcUrl = mxcUrl,
+ imageWidth = imageWidth,
+ imageHeight = imageHeight
)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt
index 60fe1a4b2c..157749ab74 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageTextItem.kt
@@ -83,12 +83,7 @@ abstract class MessageTextItem : AbsMessageItem() {
safePreviewUrlRetriever.addListener(attributes.informationData.eventId, previewUrlViewUpdater)
}
holder.previewUrlView.delegate = previewUrlCallback
- val urlPreviewBackgroundColor = if (attributes.informationData.messageLayout is TimelineMessageLayout.Bubble) {
- Color.TRANSPARENT
- } else {
- ThemeUtils.getColor(holder.view.context, R.attr.vctr_system)
- }
- holder.previewUrlView.setCardBackgroundColor(urlPreviewBackgroundColor)
+ holder.previewUrlView.render(attributes.informationData.messageLayout)
if (useBigFont) {
holder.messageView.textSize = 44F
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt
index e41f62c373..905d420463 100755
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/url/PreviewUrlView.kt
@@ -17,14 +17,20 @@
package im.vector.app.features.home.room.detail.timeline.url
import android.content.Context
+import android.content.res.ColorStateList
+import android.graphics.Color
import android.util.AttributeSet
import android.view.View
import androidx.core.view.isVisible
import com.google.android.material.card.MaterialCardView
import im.vector.app.R
import im.vector.app.core.extensions.setTextOrHide
+import im.vector.app.core.glide.GlideApp
+import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ViewUrlPreviewBinding
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
+import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
+import im.vector.app.features.home.room.detail.timeline.view.TimelineMessageLayoutRenderer
import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.themes.ThemeUtils
import org.matrix.android.sdk.api.extensions.orFalse
@@ -37,7 +43,7 @@ class PreviewUrlView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
-) : MaterialCardView(context, attrs, defStyleAttr), View.OnClickListener {
+) : MaterialCardView(context, attrs, defStyleAttr), View.OnClickListener, TimelineMessageLayoutRenderer {
private lateinit var views: ViewUrlPreviewBinding
@@ -75,6 +81,22 @@ class PreviewUrlView @JvmOverloads constructor(
}
}
+ override fun render(messageLayout: TimelineMessageLayout) {
+ when (messageLayout) {
+ is TimelineMessageLayout.Default -> {
+ val backgroundColor = ThemeUtils.getColor(context, R.attr.vctr_system)
+ setCardBackgroundColor(backgroundColor)
+ val guidelineBegin = DimensionConverter(resources).dpToPx(8)
+ views.urlPreviewStartGuideline.setGuidelineBegin(guidelineBegin)
+ }
+ is TimelineMessageLayout.Bubble -> {
+ setCardBackgroundColor(Color.TRANSPARENT)
+ rippleColor = ColorStateList.valueOf(Color.TRANSPARENT)
+ views.urlPreviewStartGuideline.setGuidelineBegin(0)
+ }
+ }
+ }
+
override fun onClick(v: View?) {
when (val finalState = state) {
is PreviewUrlUiState.Data -> delegate?.onPreviewUrlClicked(finalState.url)
@@ -126,7 +148,7 @@ class PreviewUrlView @JvmOverloads constructor(
isVisible = true
views.urlPreviewTitle.setTextOrHide(previewUrlData.title)
- views.urlPreviewImage.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, views.urlPreviewImage) }.orFalse()
+ views.urlPreviewImage.isVisible = imageContentRenderer.render(previewUrlData, views.urlPreviewImage)
views.urlPreviewDescription.setTextOrHide(previewUrlData.description)
views.urlPreviewDescription.maxLines = when {
previewUrlData.mxcUrl != null -> 2
diff --git a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt
index be9d24272d..65c99362b9 100644
--- a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt
+++ b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt
@@ -44,6 +44,7 @@ import im.vector.app.core.utils.DimensionConverter
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
+import org.matrix.android.sdk.api.session.media.PreviewUrlData
import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
import timber.log.Timber
import java.io.File
@@ -61,6 +62,9 @@ interface AttachmentData : Parcelable {
val allowNonMxcUrls: Boolean
}
+private const val URL_PREVIEW_IMAGE_MIN_FULL_WIDTH_PX = 600
+private const val URL_PREVIEW_IMAGE_MIN_FULL_HEIGHT_PX = 315
+
class ImageContentRenderer @Inject constructor(private val localFilesHelper: LocalFilesHelper,
private val activeSessionHolder: ActiveSessionHolder,
private val dimensionConverter: DimensionConverter) {
@@ -89,12 +93,20 @@ class ImageContentRenderer @Inject constructor(private val localFilesHelper: Loc
/**
* For url preview
*/
- fun render(mxcUrl: String, imageView: ImageView): Boolean {
+ fun render(previewUrlData: PreviewUrlData, imageView: ImageView): Boolean {
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
- val imageUrl = contentUrlResolver.resolveFullSize(mxcUrl) ?: return false
-
+ val imageUrl = contentUrlResolver.resolveFullSize(previewUrlData.mxcUrl) ?: return false
+ val maxHeight = dimensionConverter.resources.getDimensionPixelSize(R.dimen.preview_url_view_image_max_height)
+ val height = previewUrlData.imageHeight ?: URL_PREVIEW_IMAGE_MIN_FULL_HEIGHT_PX
+ val width = previewUrlData.imageWidth ?: URL_PREVIEW_IMAGE_MIN_FULL_WIDTH_PX
+ if (height < URL_PREVIEW_IMAGE_MIN_FULL_HEIGHT_PX || width < URL_PREVIEW_IMAGE_MIN_FULL_WIDTH_PX) {
+ imageView.scaleType = ImageView.ScaleType.CENTER_INSIDE
+ } else {
+ imageView.scaleType = ImageView.ScaleType.CENTER_CROP
+ }
GlideApp.with(imageView)
.load(imageUrl)
+ .override(width, height.coerceAtMost(maxHeight))
.into(imageView)
return true
}
diff --git a/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml b/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml
index 4bb612fedf..e2a11c7926 100644
--- a/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml
+++ b/vector/src/main/res/layout/item_timeline_event_text_message_stub.xml
@@ -17,12 +17,11 @@
+ tools:visibility="visible" />
diff --git a/vector/src/main/res/layout/view_url_preview.xml b/vector/src/main/res/layout/view_url_preview.xml
index ff4ab1ed9a..e9774207ca 100644
--- a/vector/src/main/res/layout/view_url_preview.xml
+++ b/vector/src/main/res/layout/view_url_preview.xml
@@ -1,79 +1,102 @@
-
+
+
+
+ android:orientation="vertical"
+ app:layout_constraintGuide_begin="8dp" />
-
+
+
+
-
\ No newline at end of file