From 043a908d24d7a1e3924927296e6b92f26e1bc979 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Thu, 28 May 2020 12:56:28 +0200 Subject: [PATCH] Same side read receipts for both side bubbles --- .../detail/timeline/item/AbsMessageItem.kt | 44 ++++-------- .../detail/timeline/item/BaseEventItem.kt | 67 +++++++++++++++++++ .../res/layout/item_timeline_event_base.xml | 11 +++ .../layout/item_timeline_event_base_state.xml | 10 +++ 4 files changed, 101 insertions(+), 31 deletions(-) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt index 02b32167c9..a686f36651 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt @@ -32,6 +32,7 @@ import androidx.annotation.IdRes import androidx.core.view.children import com.airbnb.epoxy.EpoxyAttribute import im.vector.riotx.R +import im.vector.riotx.core.ui.views.ReadReceiptsView import im.vector.riotx.core.utils.DebouncedClickListener import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.MessageColorProvider @@ -116,7 +117,6 @@ abstract class AbsMessageItem : AbsBaseMessageItem } } holder.viewStubContainer.minimumWidth = getViewStubMinimumWidth(holder, contentInBubble, attributes.informationData.showInformation) - updateMessageBubble(holder) } abstract class Holder(@IdRes stubId: Int) : AbsBaseMessageItem.Holder(stubId) { @@ -127,7 +127,6 @@ abstract class AbsMessageItem : AbsBaseMessageItem val bubbleView by bind(R.id.bubbleView) val bubbleMemberNameView by bind(R.id.bubbleMessageMemberNameView) val bubbleTimeView by bind(R.id.bubbleMessageTimeView) - val informationBottom by bind(R.id.informationBottom) val viewStubContainer by bind(R.id.viewStubContainer) } @@ -152,10 +151,6 @@ abstract class AbsMessageItem : AbsBaseMessageItem return infoInBubbles(context) && attributes.informationData.sentByMe } - open fun messageBubbleAllowed(context: Context): Boolean { - return false - } - open fun getViewStubMinimumWidth(holder: H, contentInBubble: Boolean, showInformation: Boolean): Int { return if (contentInBubble && attributes.informationData.showInformation) { // Guess text width for name and time @@ -168,13 +163,16 @@ abstract class AbsMessageItem : AbsBaseMessageItem } } - fun infoInBubbles(context: Context): Boolean { + private fun infoInBubbles(context: Context): Boolean { return messageBubbleAllowed(context) && BubbleThemeUtils.getBubbleStyle(context) == BubbleThemeUtils.BUBBLE_STYLE_BOTH } - fun updateMessageBubble(holder: H) { - val bubbleStyle = if (messageBubbleAllowed(holder.eventBaseView.context)) BubbleThemeUtils.getBubbleStyle(holder.eventBaseView.context) else BubbleThemeUtils.BUBBLE_STYLE_NONE - val reverseBubble = attributes.informationData.sentByMe && bubbleStyle == BubbleThemeUtils.BUBBLE_STYLE_BOTH + override fun shouldReverseBubble(): Boolean { + return attributes.informationData.sentByMe + } + + override fun setBubbleLayout(holder: H, bubbleStyle: String, bubbleStyleSetting: String, reverseBubble: Boolean) { + super.setBubbleLayout(holder, bubbleStyle, bubbleStyleSetting, reverseBubble) //val bubbleView = holder.eventBaseView val bubbleView = holder.bubbleView @@ -232,32 +230,16 @@ abstract class AbsMessageItem : AbsBaseMessageItem } } - val defaultRtl = holder.eventBaseView.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL; - val shouldRtl = reverseBubble != defaultRtl + val defaultDirection = holder.eventBaseView.resources.configuration.layoutDirection; + val defaultRtl = defaultDirection == View.LAYOUT_DIRECTION_RTL + val reverseDirection = if (defaultRtl) View.LAYOUT_DIRECTION_LTR else View.LAYOUT_DIRECTION_RTL /* holder.eventBaseView.layoutDirection = if (shouldRtl) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR setRtl(shouldRtl) */ (holder.bubbleView.layoutParams as FrameLayout.LayoutParams).gravity = if (reverseBubble) Gravity.END else Gravity.START //holder.informationBottom.layoutDirection = if (shouldRtl) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR - setFlatRtl(holder.informationBottom, if (shouldRtl) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR, - holder.eventBaseView.resources.configuration.layoutDirection, 2) - } - - /* - open fun setRtl(rtl: Boolean) { - // TODO subclass overrides? - } - */ - - fun setFlatRtl(layout: ViewGroup, direction: Int, childDirection: Int, depth: Int = 1) { - layout.layoutDirection = direction - for (child in layout.children) { - if (depth > 1 && child is ViewGroup) { - setFlatRtl(child, direction, childDirection, depth-1) - } else { - child.layoutDirection = childDirection - } - } + setFlatRtl(holder.reactionsContainer, if (reverseBubble) reverseDirection else defaultDirection, + holder.eventBaseView.resources.configuration.layoutDirection) } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BaseEventItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BaseEventItem.kt index aa28dd7b02..147c6dc6bc 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BaseEventItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/BaseEventItem.kt @@ -16,11 +16,15 @@ package im.vector.riotx.features.home.room.detail.timeline.item import android.content.Context +import android.view.Gravity import android.view.View +import android.view.ViewGroup import android.view.ViewStub +import android.widget.LinearLayout import android.widget.RelativeLayout import androidx.annotation.CallSuper import androidx.annotation.IdRes +import androidx.core.view.children import androidx.core.view.updateLayoutParams import com.airbnb.epoxy.EpoxyAttribute import im.vector.riotx.R @@ -29,6 +33,7 @@ import im.vector.riotx.core.epoxy.VectorEpoxyModel import im.vector.riotx.core.platform.CheckableView import im.vector.riotx.core.ui.views.ReadReceiptsView import im.vector.riotx.core.utils.DimensionConverter +import im.vector.riotx.features.themes.BubbleThemeUtils /** * Children must override getViewType() @@ -55,6 +60,8 @@ abstract class BaseEventItem : VectorEpoxyModel } } holder.checkableBackground.isChecked = highlighted + + updateMessageBubble(holder) } /** @@ -81,4 +88,64 @@ abstract class BaseEventItem : VectorEpoxyModel open fun ignoreMessageGuideline(context: Context): Boolean { return false } + + protected fun setFlatRtl(layout: ViewGroup, direction: Int, childDirection: Int, depth: Int = 1) { + layout.layoutDirection = direction + for (child in layout.children) { + if (depth > 1 && child is ViewGroup) { + setFlatRtl(child, direction, childDirection, depth-1) + } else { + child.layoutDirection = childDirection + } + } + } + + fun updateMessageBubble(holder: H) { + val bubbleStyleSetting = BubbleThemeUtils.getBubbleStyle(holder.checkableBackground.context) + val bubbleStyle = if (messageBubbleAllowed(holder.checkableBackground.context)) bubbleStyleSetting else BubbleThemeUtils.BUBBLE_STYLE_NONE + val reverseBubble = shouldReverseBubble() && bubbleStyle == BubbleThemeUtils.BUBBLE_STYLE_BOTH + + setBubbleLayout(holder, bubbleStyle, bubbleStyleSetting, reverseBubble) + } + + open fun messageBubbleAllowed(context: Context): Boolean { + return false + } + + open fun shouldReverseBubble(): Boolean { + return false + } + + @CallSuper + open fun setBubbleLayout(holder: H, bubbleStyle: String, bubbleStyleSetting: String, reverseBubble: Boolean) { + val defaultDirection = holder.readReceiptsView.resources.configuration.layoutDirection; + val defaultRtl = defaultDirection == View.LAYOUT_DIRECTION_RTL + val reverseDirection = if (defaultRtl) View.LAYOUT_DIRECTION_LTR else View.LAYOUT_DIRECTION_RTL + + // Always keep read receipts of others on other side for dual side bubbles + val dualBubbles = bubbleStyleSetting == BubbleThemeUtils.BUBBLE_STYLE_BOTH + + val receiptParent = holder.readReceiptsView.parent + if (receiptParent is LinearLayout) { + (holder.readReceiptsView.layoutParams as LinearLayout.LayoutParams).gravity = if (dualBubbles) Gravity.START else Gravity.END + + (receiptParent.layoutParams as RelativeLayout.LayoutParams).removeRule(RelativeLayout.END_OF) + (receiptParent.layoutParams as RelativeLayout.LayoutParams).removeRule(RelativeLayout.ALIGN_PARENT_START) + if (dualBubbles) { + (receiptParent.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.ALIGN_PARENT_START, RelativeLayout.TRUE) + } else { + (receiptParent.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.END_OF, R.id.messageStartGuideline) + } + } else { + if (dualBubbles) { + (holder.readReceiptsView.layoutParams as RelativeLayout.LayoutParams).removeRule(RelativeLayout.ALIGN_PARENT_END) + } else { + (holder.readReceiptsView.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.ALIGN_PARENT_END) + } + } + + // Also set rtl to have members fill from the natural side + setFlatRtl(holder.readReceiptsView, if (dualBubbles) reverseDirection else defaultDirection, defaultDirection) + } + } diff --git a/vector/src/main/res/layout/item_timeline_event_base.xml b/vector/src/main/res/layout/item_timeline_event_base.xml index f557f14e1f..13f6ea8216 100644 --- a/vector/src/main/res/layout/item_timeline_event_base.xml +++ b/vector/src/main/res/layout/item_timeline_event_base.xml @@ -235,6 +235,17 @@ + + + + + + + + +