diff --git a/vector/src/main/java/im/vector/riotx/core/ui/views/WrapWidthTextView.kt b/vector/src/main/java/im/vector/riotx/core/ui/views/WrapWidthTextView.kt new file mode 100644 index 0000000000..aaf1ee3030 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/core/ui/views/WrapWidthTextView.kt @@ -0,0 +1,37 @@ +/* + * https://stackoverflow.com/questions/7439748/why-is-wrap-content-in-multiple-line-textview-filling-parent + */ + +package im.vector.riotx.core.ui.views; + +import android.content.Context +import android.text.Layout +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatTextView +import kotlin.math.ceil + +class WrapWidthTextView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AppCompatTextView(context, attrs, defStyleAttr) { + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val layout = this.layout ?: return + val width = ceil(getMaxLineWidth(layout)).toInt() + compoundPaddingLeft + compoundPaddingRight + val height = measuredHeight + setMeasuredDimension(width, height) + } + + private fun getMaxLineWidth(layout: Layout): Float { + var maxWidth = 0.0f + val lines = layout.lineCount + for (i in 0 until lines) { + if (layout.getLineWidth(i) > maxWidth) { + maxWidth = layout.getLineWidth(i) + } + } + return maxWidth + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt index ffb71a38c5..96cfcaf7cd 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -397,6 +397,8 @@ class MessageItemFactory @Inject constructor( .leftGuideline(avatarSizeProvider.leftGuideline) .attributes(attributes) .highlighted(highlight) + .outgoingMessage(informationData.sentByMe) + .incomingMessage(!informationData.sentByMe) .movementMethod(createLinkMovementMethod(callback)) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageTextItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageTextItem.kt index fabdf22d14..e544576cfb 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageTextItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageTextItem.kt @@ -16,14 +16,24 @@ package im.vector.riotx.features.home.room.detail.timeline.item +import android.content.res.ColorStateList import android.text.method.MovementMethod +import android.view.Gravity +import android.widget.FrameLayout import androidx.appcompat.widget.AppCompatTextView +import androidx.core.content.ContextCompat import androidx.core.text.PrecomputedTextCompat import androidx.core.widget.TextViewCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R import im.vector.riotx.features.home.room.detail.timeline.tools.findPillsAndProcess +import im.vector.riotx.features.themes.BubbleThemeUtils +import im.vector.riotx.features.themes.BubbleThemeUtils.BUBBLE_STYLE_BOTH +import im.vector.riotx.features.themes.BubbleThemeUtils.BUBBLE_STYLE_NONE +import im.vector.riotx.features.themes.BubbleThemeUtils.BUBBLE_STYLE_START +import im.vector.riotx.features.themes.ThemeUtils +import kotlin.math.round @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageTextItem : AbsMessageItem() { @@ -36,6 +46,10 @@ abstract class MessageTextItem : AbsMessageItem() { var useBigFont: Boolean = false @EpoxyAttribute var movementMethod: MovementMethod? = null + @EpoxyAttribute + var incomingMessage: Boolean = false + @EpoxyAttribute + var outgoingMessage: Boolean = false override fun bind(holder: Holder) { super.bind(holder) @@ -56,6 +70,35 @@ abstract class MessageTextItem : AbsMessageItem() { TextViewCompat.getTextMetricsParams(holder.messageView), null) holder.messageView.setTextFuture(textFuture) + + var bubbleStyle = if (incomingMessage || outgoingMessage) BubbleThemeUtils.getBubbleStyle(holder.messageView.context) else BUBBLE_STYLE_NONE + when (bubbleStyle) { + BUBBLE_STYLE_NONE -> { + holder.messageView.background = null + holder.messageView.setPadding(0, 0, 0, 0) + } + BUBBLE_STYLE_START, BUBBLE_STYLE_BOTH -> { + holder.messageView.setBackgroundResource(R.drawable.msg_bubble_incoming) + var tintColor = ColorStateList( + arrayOf(intArrayOf(0)), + intArrayOf(ThemeUtils.getColor(holder.messageView.context, + if (outgoingMessage) R.attr.sc_message_bg_outgoing else R.attr.sc_message_bg_incoming) + ) + ) + holder.messageView.backgroundTintList = tintColor + val density = holder.messageView.resources.displayMetrics.density + holder.messageView.setPaddingRelative( + round(20*density).toInt(), + round(8*density).toInt(), + round(8*density).toInt(), + round(8*density).toInt() + ) + } + } + if (holder.messageView.layoutParams is FrameLayout.LayoutParams) { + (holder.messageView.layoutParams as FrameLayout.LayoutParams).gravity = + if (outgoingMessage && bubbleStyle == BUBBLE_STYLE_BOTH) Gravity.END else Gravity.START + } } override fun getViewType() = STUB_ID diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsPreferencesFragment.kt index 9c240ad093..26f114cd44 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsPreferencesFragment.kt @@ -28,6 +28,7 @@ import im.vector.riotx.R import im.vector.riotx.core.preference.VectorListPreference import im.vector.riotx.core.preference.VectorPreference import im.vector.riotx.features.configuration.VectorConfiguration +import im.vector.riotx.features.themes.BubbleThemeUtils import im.vector.riotx.features.themes.ThemeUtils import javax.inject.Inject @@ -66,6 +67,11 @@ class VectorSettingsPreferencesFragment @Inject constructor( false } } + findPreference(BubbleThemeUtils.BUBBLE_STYLE_KEY)!! + .onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, _ -> + BubbleThemeUtils.invalidateBubbleStyle() + true + } // Url preview findPreference(VectorPreferences.SETTINGS_SHOW_URL_PREVIEW_KEY)!!.let { diff --git a/vector/src/main/java/im/vector/riotx/features/themes/BubbleThemeUtils.kt b/vector/src/main/java/im/vector/riotx/features/themes/BubbleThemeUtils.kt new file mode 100644 index 0000000000..bf765d0f94 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/themes/BubbleThemeUtils.kt @@ -0,0 +1,27 @@ +package im.vector.riotx.features.themes + +import android.content.Context +import androidx.preference.PreferenceManager + +/** + * Util class for managing themes. + */ +object BubbleThemeUtils { + const val BUBBLE_STYLE_KEY = "BUBBLE_STYLE_KEY" + + const val BUBBLE_STYLE_NONE = "none" + const val BUBBLE_STYLE_START = "start" + const val BUBBLE_STYLE_BOTH = "both" + private var mBubbleStyle: String = "" + + fun getBubbleStyle(context: Context): String { + if (mBubbleStyle == "") { + mBubbleStyle = PreferenceManager.getDefaultSharedPreferences(context).getString(BUBBLE_STYLE_KEY, BUBBLE_STYLE_START)!! + } + return mBubbleStyle + } + + fun invalidateBubbleStyle() { + mBubbleStyle = "" + } +} diff --git a/vector/src/main/res/drawable-hdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-hdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..7fed0a806a Binary files /dev/null and b/vector/src/main/res/drawable-hdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-ldrtl-hdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-ldrtl-hdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..8e7ccc0cc8 Binary files /dev/null and b/vector/src/main/res/drawable-ldrtl-hdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-ldrtl-mdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-ldrtl-mdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..5ca9b14d64 Binary files /dev/null and b/vector/src/main/res/drawable-ldrtl-mdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-ldrtl-xhdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-ldrtl-xhdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..52cb936a8e Binary files /dev/null and b/vector/src/main/res/drawable-ldrtl-xhdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-ldrtl-xxhdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-ldrtl-xxhdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..5d8fc747ee Binary files /dev/null and b/vector/src/main/res/drawable-ldrtl-xxhdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-ldrtl-xxxhdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-ldrtl-xxxhdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..8378db5767 Binary files /dev/null and b/vector/src/main/res/drawable-ldrtl-xxxhdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-mdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-mdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..4e7e464037 Binary files /dev/null and b/vector/src/main/res/drawable-mdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-xhdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-xhdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..0661fdba78 Binary files /dev/null and b/vector/src/main/res/drawable-xhdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-xxhdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-xxhdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..ab693b3e7c Binary files /dev/null and b/vector/src/main/res/drawable-xxhdpi/msg_bubble_incoming.9.png differ diff --git a/vector/src/main/res/drawable-xxxhdpi/msg_bubble_incoming.9.png b/vector/src/main/res/drawable-xxxhdpi/msg_bubble_incoming.9.png new file mode 100644 index 0000000000..34130fc6d1 Binary files /dev/null and b/vector/src/main/res/drawable-xxxhdpi/msg_bubble_incoming.9.png differ 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 3ae80424cc..05d0dd797e 100644 --- a/vector/src/main/res/layout/item_timeline_event_base.xml +++ b/vector/src/main/res/layout/item_timeline_event_base.xml @@ -92,6 +92,7 @@ android:id="@+id/messageContentTextStub" style="@style/TimelineContentStubBaseParams" android:layout_height="wrap_content" + android:layout_width="wrap_content" android:inflatedId="@id/messageTextView" android:layout="@layout/item_timeline_event_text_message_stub" tools:visibility="visible" /> 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 59396db0e5..6b8f08833c 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 @@ -1,8 +1,8 @@ -(Gelöschte Nachricht) + Nachrichtblasen + Keine + Selbe Seite + Beide Seiten + diff --git a/vector/src/main/res/values/arrays_sc.xml b/vector/src/main/res/values/arrays_sc.xml new file mode 100644 index 0000000000..2c5305c28e --- /dev/null +++ b/vector/src/main/res/values/arrays_sc.xml @@ -0,0 +1,15 @@ + + + + + @string/bubble_style_none + @string/bubble_style_start + @string/bubble_style_both + + + none + start + both + + + diff --git a/vector/src/main/res/values/attrs_sc.xml b/vector/src/main/res/values/attrs_sc.xml new file mode 100644 index 0000000000..cafd386c83 --- /dev/null +++ b/vector/src/main/res/values/attrs_sc.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/vector/src/main/res/values/strings_sc.xml b/vector/src/main/res/values/strings_sc.xml index a24b245bc8..abc94df2b8 100644 --- a/vector/src/main/res/values/strings_sc.xml +++ b/vector/src/main/res/values/strings_sc.xml @@ -3,4 +3,9 @@ (Deleted message) + Message bubbles + None + Same side + Both sides + diff --git a/vector/src/main/res/values/theme_dark.xml b/vector/src/main/res/values/theme_dark.xml index a2be367e55..384d693562 100644 --- a/vector/src/main/res/values/theme_dark.xml +++ b/vector/src/main/res/values/theme_dark.xml @@ -216,6 +216,9 @@ @style/VectorSnackBarButton @style/VectorSnackBarText + + #FF465561 + #FF1A2027