Properly reserve space in URL-previews for time footer

Change-Id: Iee60d34086a8b1e2b9b70674eb77df2220dff1e5
This commit is contained in:
SpiritCroc 2020-12-22 10:49:11 +01:00
parent c01d4cdc9c
commit d3700cecc3
3 changed files with 47 additions and 45 deletions

View File

@ -24,9 +24,10 @@ class FooteredTextView @JvmOverloads constructor(
super.onMeasure(widthMeasureSpec, heightMeasureSpec) super.onMeasure(widthMeasureSpec, heightMeasureSpec)
// Get max available width // Get max available width
val widthMode = MeasureSpec.getMode(widthMeasureSpec) //val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val widthSize = MeasureSpec.getSize(widthMeasureSpec) val widthSize = MeasureSpec.getSize(widthMeasureSpec)
val widthLimit = if (widthMode == MeasureSpec.AT_MOST) { widthSize.toFloat() } else { Float.MAX_VALUE } //val widthLimit = if (widthMode == MeasureSpec.AT_MOST) { widthSize.toFloat() } else { Float.MAX_VALUE }
val widthLimit = widthSize.toFloat()
/* /*
// Sometimes, widthLimit is not the actual limit, so remember it... ? // Sometimes, widthLimit is not the actual limit, so remember it... ?
if (this.widthLimit > widthLimit) { if (this.widthLimit > widthLimit) {

View File

@ -60,10 +60,11 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
private val previewUrlViewUpdater = PreviewUrlViewUpdater() private val previewUrlViewUpdater = PreviewUrlViewUpdater()
override fun bind(holder: Holder) { // Remember footer measures for URL updates
// Revert potential MATCH_PARENT setting for url preview, before binding previewUrlRetriever private var footerWidth: Int = 0
//holder.messageLayout.layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT private var footerHeight: Int = 0
override fun bind(holder: Holder) {
// Preview URL // Preview URL
previewUrlViewUpdater.holder = holder previewUrlViewUpdater.holder = holder
previewUrlViewUpdater.previewUrlView = holder.previewUrlView previewUrlViewUpdater.previewUrlView = holder.previewUrlView
@ -120,7 +121,6 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
override fun getViewType() = STUB_ID override fun getViewType() = STUB_ID
class Holder : AbsMessageItem.Holder(STUB_ID) { class Holder : AbsMessageItem.Holder(STUB_ID) {
val messageLayout by bind<LinearLayout>(R.id.messageTextLayout) // TODO match_parent if url preview, else wrap_content
val messageView by bind<FooteredTextView>(R.id.messageTextView) val messageView by bind<FooteredTextView>(R.id.messageTextView)
val previewUrlView by bind<PreviewUrlView>(R.id.messageUrlPreview) val previewUrlView by bind<PreviewUrlView>(R.id.messageUrlPreview)
} }
@ -138,29 +138,19 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
} }
previewUrlView?.render(state, safeImageContentRenderer) previewUrlView?.render(state, safeImageContentRenderer)
// Don't reserve footer space in message view, but preview view | TODO ///* // disabled for now: just set all in reserveFooterSpace to ensure space in all scenarios
/* // Currently, all states except data imply hidden preview
previewUrlView?.footerWidth = holder?.messageView?.footerWidth ?: 0 if (state is PreviewUrlUiState.Data) {
previewUrlView?.footerHeight = holder?.messageView?.footerHeight ?: 0 // Don't reserve footer space in message view, but preview view
holder?.messageView?.footerWidth = 0 holder?.messageView?.footerWidth = 0
holder?.messageView?.footerHeight = 0 holder?.messageView?.footerHeight = 0
*/ } else {
// Reserve more space for URL previews holder?.messageView?.footerWidth = footerWidth
//holder?.messageLayout?.layoutParams?.width = LinearLayout.LayoutParams.MATCH_PARENT holder?.messageView?.footerHeight = footerHeight
// Also increase width for the viewStubContainer, as set in AbsMessageItem (using getViewStubMinimumWidth) }
// We can use an unrealistic high number here, because we reduce bubble width by margins //holder?.messageView?.invalidate()
// TODO dis not working reliably... holder?.messageView?.requestLayout()
/* //*/
holder?.viewStubContainer?.minimumWidth = 1000000
holder?.viewStubContainer?.parent?.requestLayout()
holder?.viewStubContainer?.forceLayout()
holder?.viewStubContainer?.requestLayout()
holder?.messageLayout?.forceLayout()
holder?.messageLayout?.requestLayout()
holder?.messageView?.forceLayout()
holder?.previewUrlView?.forceLayout()
*/
//holder?.viewStubContainer?.layoutParams = holder?.viewStubContainer?.layoutParams
} }
} }
companion object { companion object {
@ -180,7 +170,18 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
} }
override fun reserveFooterSpace(holder: Holder, width: Int, height: Int) { override fun reserveFooterSpace(holder: Holder, width: Int, height: Int) {
holder.messageView.footerWidth = width // Remember for PreviewUrlViewUpdater.onStateUpdated
holder.messageView.footerHeight = height footerWidth = width
footerHeight = height
// Reserve both in preview and in message
// User might close preview, so we still need place in the message
// if we don't want to change this afterwards
// This might be a race condition, but the UI-isssue if evaluated wrongly is negligible
if (!holder.previewUrlView.isVisible) {
holder.messageView.footerWidth = width
holder.messageView.footerHeight = height
} // else: will be handled in onStateUpdated
holder.previewUrlView.footerWidth = height
holder.previewUrlView.footerHeight = height
} }
} }

View File

@ -32,7 +32,6 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.ImageContentRenderer
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.media.PreviewUrlData import org.matrix.android.sdk.api.session.media.PreviewUrlData
import kotlin.math.round
/** /**
* A View to display a PreviewUrl and some other state * A View to display a PreviewUrl and some other state
@ -58,8 +57,8 @@ class PreviewUrlView @JvmOverloads constructor(
@BindView(R.id.url_preview_close) @BindView(R.id.url_preview_close)
lateinit var closeView: View lateinit var closeView: View
var footerHeight: Int = 0
var footerWidth: Int = 0 var footerWidth: Int = 0
var footerHeight: Int = 0
var delegate: TimelineEventController.PreviewUrlCallback? = null var delegate: TimelineEventController.PreviewUrlCallback? = null
@ -149,23 +148,24 @@ class PreviewUrlView @JvmOverloads constructor(
} }
private fun renderData(previewUrlData: PreviewUrlData, imageContentRenderer: ImageContentRenderer) { private fun renderData(previewUrlData: PreviewUrlData, imageContentRenderer: ImageContentRenderer) {
isVisible = true // Set footer sizes before setText() calls so they are available onMeasure
titleView.setTextOrHide(previewUrlData.title) val siteText = previewUrlData.siteName.takeIf { it != previewUrlData.title }
imageView.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, imageView) }.orFalse() val siteViewHidden = siteText == null || siteText.isBlank() // identical to setTextOrHide
descriptionView.setTextOrHide(previewUrlData.description) if (siteViewHidden) {
siteView.setTextOrHide(previewUrlData.siteName.takeIf { it != previewUrlData.title }) descriptionView.footerWidth = footerWidth
/* descriptionView.footerHeight = footerHeight
if (siteView.isVisible) { } else {
// TODO does this work
siteView.footerWidth = footerWidth siteView.footerWidth = footerWidth
siteView.footerHeight = footerHeight siteView.footerHeight = footerHeight
descriptionView.footerWidth = 0 descriptionView.footerWidth = 0
descriptionView.footerHeight = 0 descriptionView.footerHeight = 0
} else {
descriptionView.footerWidth = footerWidth
descriptionView.footerHeight = footerHeight
} }
*/
isVisible = true
titleView.setTextOrHide(previewUrlData.title)
imageView.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, imageView) }.orFalse()
descriptionView.setTextOrHide(previewUrlData.description)
siteView.setTextOrHide(siteText)
} }
/** /**