[WIP] PreviewUrl-fixes for bubble layout
- Always use maximum available width for the preview - TODO reserve footer for time - TODO fix upstream bug which comes more apparent on Schildi: fast scrolling leads to previews attached to wrong messages Change-Id: Ie8447b7a9dbace54e38c14fc7d281b7f3887736c
This commit is contained in:
parent
77bfa1a687
commit
002edb5e36
|
@ -36,7 +36,7 @@ internal object RoomSummaryEventsHelper {
|
||||||
// SC addition
|
// SC addition
|
||||||
private val previewFiltersScAll = TimelineEventFilters(
|
private val previewFiltersScAll = TimelineEventFilters(
|
||||||
filterTypes = true,
|
filterTypes = true,
|
||||||
allowedTypes = RoomSummaryConstants.PREVIEWABLE_TYPES_ALL,
|
allowedTypes = RoomSummaryConstants.PREVIEWABLE_TYPES_ALL.map { EventTypeFilter(eventType = it, stateKey = null) },
|
||||||
filterUseless = true,
|
filterUseless = true,
|
||||||
filterRedacted = false,
|
filterRedacted = false,
|
||||||
filterEdits = true
|
filterEdits = true
|
||||||
|
@ -45,7 +45,7 @@ internal object RoomSummaryEventsHelper {
|
||||||
// SC addition
|
// SC addition
|
||||||
private val previewFiltersScOriginalContent = TimelineEventFilters(
|
private val previewFiltersScOriginalContent = TimelineEventFilters(
|
||||||
filterTypes = true,
|
filterTypes = true,
|
||||||
allowedTypes = RoomSummaryConstants.PREVIEWABLE_ORIGINAL_CONTENT_TYPES,
|
allowedTypes = RoomSummaryConstants.PREVIEWABLE_ORIGINAL_CONTENT_TYPES.map { EventTypeFilter(eventType = it, stateKey = null) },
|
||||||
filterUseless = true,
|
filterUseless = true,
|
||||||
filterRedacted = true,
|
filterRedacted = true,
|
||||||
filterEdits = true
|
filterEdits = true
|
||||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.item
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.text.method.MovementMethod
|
import android.text.method.MovementMethod
|
||||||
|
import android.widget.LinearLayout
|
||||||
import androidx.core.text.PrecomputedTextCompat
|
import androidx.core.text.PrecomputedTextCompat
|
||||||
import androidx.core.widget.TextViewCompat
|
import androidx.core.widget.TextViewCompat
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
@ -59,7 +60,11 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
||||||
private val previewUrlViewUpdater = PreviewUrlViewUpdater()
|
private val previewUrlViewUpdater = PreviewUrlViewUpdater()
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
|
// Revert potential MATCH_PARENT setting for url preview, before binding previewUrlRetriever
|
||||||
|
//holder.messageLayout.layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
|
||||||
// Preview URL
|
// Preview URL
|
||||||
|
previewUrlViewUpdater.holder = holder
|
||||||
previewUrlViewUpdater.previewUrlView = holder.previewUrlView
|
previewUrlViewUpdater.previewUrlView = holder.previewUrlView
|
||||||
previewUrlViewUpdater.imageContentRenderer = imageContentRenderer
|
previewUrlViewUpdater.imageContentRenderer = imageContentRenderer
|
||||||
previewUrlRetriever?.addListener(attributes.informationData.eventId, previewUrlViewUpdater)
|
previewUrlRetriever?.addListener(attributes.informationData.eventId, previewUrlViewUpdater)
|
||||||
|
@ -109,17 +114,43 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class PreviewUrlViewUpdater : PreviewUrlRetriever.PreviewUrlRetrieverListener {
|
inner class PreviewUrlViewUpdater : PreviewUrlRetriever.PreviewUrlRetrieverListener {
|
||||||
var previewUrlView: PreviewUrlView? = null
|
var previewUrlView: PreviewUrlView? = null
|
||||||
|
var holder: Holder? = null
|
||||||
var imageContentRenderer: ImageContentRenderer? = null
|
var imageContentRenderer: ImageContentRenderer? = null
|
||||||
|
|
||||||
override fun onStateUpdated(state: PreviewUrlUiState) {
|
override fun onStateUpdated(state: PreviewUrlUiState) {
|
||||||
val safeImageContentRenderer = imageContentRenderer ?: return
|
val safeImageContentRenderer = imageContentRenderer ?: return
|
||||||
previewUrlView?.render(state, safeImageContentRenderer)
|
previewUrlView?.render(state, safeImageContentRenderer)
|
||||||
|
|
||||||
|
// Don't reserve footer space in message view, but preview view | TODO
|
||||||
|
/*
|
||||||
|
previewUrlView?.footerWidth = holder?.messageView?.footerWidth ?: 0
|
||||||
|
previewUrlView?.footerHeight = holder?.messageView?.footerHeight ?: 0
|
||||||
|
holder?.messageView?.footerWidth = 0
|
||||||
|
holder?.messageView?.footerHeight = 0
|
||||||
|
*/
|
||||||
|
// Reserve more space for URL previews
|
||||||
|
//holder?.messageLayout?.layoutParams?.width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||||
|
// 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
|
||||||
|
// TODO dis not working reliably...
|
||||||
|
/*
|
||||||
|
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 {
|
||||||
|
|
|
@ -27,10 +27,12 @@ import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.setTextOrHide
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
|
import im.vector.app.core.ui.views.FooteredTextView
|
||||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
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
|
||||||
|
@ -48,14 +50,17 @@ class PreviewUrlView @JvmOverloads constructor(
|
||||||
lateinit var imageView: ImageView
|
lateinit var imageView: ImageView
|
||||||
|
|
||||||
@BindView(R.id.url_preview_description)
|
@BindView(R.id.url_preview_description)
|
||||||
lateinit var descriptionView: TextView
|
lateinit var descriptionView: FooteredTextView
|
||||||
|
|
||||||
@BindView(R.id.url_preview_site)
|
@BindView(R.id.url_preview_site)
|
||||||
lateinit var siteView: TextView
|
lateinit var siteView: FooteredTextView
|
||||||
|
|
||||||
@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 delegate: TimelineEventController.PreviewUrlCallback? = null
|
var delegate: TimelineEventController.PreviewUrlCallback? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -102,6 +107,28 @@ class PreviewUrlView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
// Get max available width - we're faking "wrap_content" here to use all available space,
|
||||||
|
// since match_parent doesn't work here as our parent does wrap_content as well
|
||||||
|
/*
|
||||||
|
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
|
||||||
|
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
|
||||||
|
val widthLimit = if (widthMode == MeasureSpec.AT_MOST) {
|
||||||
|
widthSize.toFloat()
|
||||||
|
} else {
|
||||||
|
Float.MAX_VALUE
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//setMeasuredDimension(round(widthLimit).toInt(), measuredHeight)
|
||||||
|
|
||||||
|
// We extract the size from an AT_MOST spec, which is the width limit, but change the mode to EXACTLY
|
||||||
|
val newWidthSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY)
|
||||||
|
|
||||||
|
// We measure our children based on the now fixed width
|
||||||
|
super.onMeasure(newWidthSpec, heightMeasureSpec)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// PRIVATE METHODS ****************************************************************************************************************************************
|
// PRIVATE METHODS ****************************************************************************************************************************************
|
||||||
|
|
||||||
private fun setupView() {
|
private fun setupView() {
|
||||||
|
@ -127,6 +154,18 @@ class PreviewUrlView @JvmOverloads constructor(
|
||||||
imageView.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, imageView) }.orFalse()
|
imageView.isVisible = previewUrlData.mxcUrl?.let { imageContentRenderer.render(it, imageView) }.orFalse()
|
||||||
descriptionView.setTextOrHide(previewUrlData.description)
|
descriptionView.setTextOrHide(previewUrlData.description)
|
||||||
siteView.setTextOrHide(previewUrlData.siteName.takeIf { it != previewUrlData.title })
|
siteView.setTextOrHide(previewUrlData.siteName.takeIf { it != previewUrlData.title })
|
||||||
|
/*
|
||||||
|
if (siteView.isVisible) {
|
||||||
|
// TODO does this work
|
||||||
|
siteView.footerWidth = footerWidth
|
||||||
|
siteView.footerHeight = footerHeight
|
||||||
|
descriptionView.footerWidth = 0
|
||||||
|
descriptionView.footerHeight = 0
|
||||||
|
} else {
|
||||||
|
descriptionView.footerWidth = footerWidth
|
||||||
|
descriptionView.footerHeight = footerHeight
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,7 +33,7 @@ import javax.inject.Inject
|
||||||
|
|
||||||
class CreateRoomController @Inject constructor(
|
class CreateRoomController @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val roomAliasErrorFormatter: RoomAliasErrorFormatter
|
private val roomAliasErrorFormatter: RoomAliasErrorFormatter,
|
||||||
private val vectorPreferences: VectorPreferences
|
private val vectorPreferences: VectorPreferences
|
||||||
) : TypedEpoxyController<CreateRoomViewState>() {
|
) : TypedEpoxyController<CreateRoomViewState>() {
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ object ThemeUtils {
|
||||||
fun isLightTheme(context: Context): Boolean {
|
fun isLightTheme(context: Context): Boolean {
|
||||||
return when (getApplicationTheme(context)) {
|
return when (getApplicationTheme(context)) {
|
||||||
THEME_LIGHT_VALUE,
|
THEME_LIGHT_VALUE,
|
||||||
THEME_SC_LIGHT_VALUE,
|
THEME_SC_LIGHT_VALUE -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ object ThemeUtils {
|
||||||
val currentTheme = this.currentLightTheme.get()
|
val currentTheme = this.currentLightTheme.get()
|
||||||
return if (currentTheme == null) {
|
return if (currentTheme == null) {
|
||||||
val prefs = DefaultSharedPreferences.getInstance(context)
|
val prefs = DefaultSharedPreferences.getInstance(context)
|
||||||
val themeFromPref = prefs.getString(APPLICATION_THEME_KEY, THEME_SC_LIGHT_VALUE) ?: THEME_SC_LIGHT_VALUE
|
var themeFromPref = prefs.getString(APPLICATION_THEME_KEY, THEME_SC_LIGHT_VALUE) ?: THEME_SC_LIGHT_VALUE
|
||||||
if (themeFromPref == "status") {
|
if (themeFromPref == "status") {
|
||||||
// Migrate to light theme, which is the closest theme
|
// Migrate to light theme, which is the closest theme
|
||||||
themeFromPref = THEME_LIGHT_VALUE
|
themeFromPref = THEME_LIGHT_VALUE
|
||||||
|
@ -162,7 +162,7 @@ object ThemeUtils {
|
||||||
val currentTheme = this.currentDarkTheme.get()
|
val currentTheme = this.currentDarkTheme.get()
|
||||||
return if (currentTheme == null) {
|
return if (currentTheme == null) {
|
||||||
val prefs = DefaultSharedPreferences.getInstance(context)
|
val prefs = DefaultSharedPreferences.getInstance(context)
|
||||||
val themeFromPref = prefs.getString(APPLICATION_DARK_THEME_KEY, THEME_SC_DARK_VALUE) ?: THEME_SC_DARK_VALUE
|
var themeFromPref = prefs.getString(APPLICATION_DARK_THEME_KEY, THEME_SC_DARK_VALUE) ?: THEME_SC_DARK_VALUE
|
||||||
if (themeFromPref == "status") {
|
if (themeFromPref == "status") {
|
||||||
// Migrate to light theme, which is the closest theme
|
// Migrate to light theme, which is the closest theme
|
||||||
themeFromPref = THEME_LIGHT_VALUE
|
themeFromPref = THEME_LIGHT_VALUE
|
||||||
|
|
|
@ -138,7 +138,6 @@
|
||||||
style="@style/TimelineContentStubBaseParams"
|
style="@style/TimelineContentStubBaseParams"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:inflatedId="@id/messageTextView"
|
|
||||||
android:layout="@layout/item_timeline_event_text_message_stub"
|
android:layout="@layout/item_timeline_event_text_message_stub"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/messageTextLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/url_preview_title"
|
app:layout_constraintTop_toBottomOf="@+id/url_preview_title"
|
||||||
tools:src="@tools:sample/backgrounds/scenic" />
|
tools:src="@tools:sample/backgrounds/scenic" />
|
||||||
|
|
||||||
<TextView
|
<im.vector.app.core.ui.views.FooteredTextView
|
||||||
android:id="@+id/url_preview_description"
|
android:id="@+id/url_preview_description"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/url_preview_image"
|
app:layout_constraintTop_toBottomOf="@+id/url_preview_image"
|
||||||
tools:text="The British perfumer says removing actor John Boyega from his own advert was “utterly despicable”." />
|
tools:text="The British perfumer says removing actor John Boyega from his own advert was “utterly despicable”." />
|
||||||
|
|
||||||
<TextView
|
<im.vector.app.core.ui.views.FooteredTextView
|
||||||
android:id="@+id/url_preview_site"
|
android:id="@+id/url_preview_site"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
Loading…
Reference in New Issue