diff --git a/generate_bubbles.sh b/generate_bubbles.sh index 3faeaace61..98157f4fae 100755 --- a/generate_bubbles.sh +++ b/generate_bubbles.sh @@ -5,7 +5,7 @@ set -e my_dir="$(dirname "$(realpath "$0")")" pushd "$my_dir" > /dev/null -res_dir="vector/src/main/res/" +res_dir="vector/src/main/res" god_bubble="vector/src/main/res/drawable/msg_godbubble.xml" # Multiline sed -i @@ -27,6 +27,7 @@ function create_msg_bubble() { local is_rtl="$2" local is_notice="$3" local has_tail="$4" + local roundness="$5" # Out file name local out_bubble="$res_dir/drawable" @@ -34,6 +35,9 @@ function create_msg_bubble() { local out_bubble="$out_bubble-ldrtl" fi local out_bubble="$out_bubble/msg_bubble" + if [ ! -z "$roundness" ]; then + local out_bubble="${out_bubble}_$roundness" + fi if ((is_notice)); then local out_bubble="${out_bubble}_notice" else @@ -79,19 +83,25 @@ function create_msg_bubble() { if ((is_outgoing)); then sed -i 's|_incoming|_outgoing|g' "$out_bubble" fi + # Modify roundness + if [ ! -z "$roundness" ]; then + sed -i "s|sc_bubble_radius|sc_bubble_${roundness}_radius|g" "$out_bubble" + fi # Remove unneeded size, which only exists to make it look nicer in drawable preview sed -i 's|||g' "$out_bubble" } -for is_outgoing in 0 1; do - for is_rtl in 0 1; do - # Notices are handled via transparency and do not need own drawables right now - is_notice=0 - #for is_notice in 0 1; do - for has_tail in 0 1; do - create_msg_bubble "$is_outgoing" "$is_rtl" "$is_notice" "$has_tail" - done - #done +for roundness in "" "r1" "r2"; do + for is_outgoing in 0 1; do + for is_rtl in 0 1; do + # Notices are handled via transparency and do not need own drawables right now + is_notice=0 + #for is_notice in 0 1; do + for has_tail in 0 1; do + create_msg_bubble "$is_outgoing" "$is_rtl" "$is_notice" "$has_tail" "$roundness" + done + #done + done done done diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt index 233af786ac..c8252a3c7a 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageImageVideoItem.kt @@ -17,6 +17,7 @@ package im.vector.app.features.home.room.detail.timeline.item import android.content.res.Resources +import android.graphics.Bitmap import android.view.View import android.view.ViewGroup import android.widget.ImageView @@ -25,6 +26,7 @@ import androidx.core.view.ViewCompat import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import com.bumptech.glide.load.Transformation import com.bumptech.glide.load.resource.bitmap.RoundedCorners import im.vector.app.R import im.vector.app.core.epoxy.ClickListener @@ -37,7 +39,9 @@ import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLay import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners import im.vector.app.features.home.room.detail.timeline.view.ScMessageBubbleWrapView import im.vector.app.features.media.ImageContentRenderer +import im.vector.app.features.themes.defaultScBubbleAppearance import org.matrix.android.sdk.api.util.MimeTypes +import kotlin.math.round @EpoxyModelClass(layout = R.layout.item_timeline_event_base) abstract class MessageImageVideoItem : AbsMessageItem() { @@ -90,12 +94,23 @@ abstract class MessageImageVideoItem : AbsMessageItem RoundedCorners(dimensionConverter.dpToPx(3)) - is TimelineMessageLayout.Bubble -> messageLayout.cornersRadius.granularRoundedCorners() - else -> RoundedCorners(dimensionConverter.dpToPx(8)) + val cornerRoundnessDp: Int + val imageCornerTransformation: Transformation + when (messageLayout) { + is TimelineMessageLayout.ScBubble -> { + cornerRoundnessDp = round(messageLayout.bubbleAppearance.getBubbleRadiusDp(holder.view.context)).toInt() + imageCornerTransformation = RoundedCorners(dimensionConverter.dpToPx(cornerRoundnessDp)) + } + is TimelineMessageLayout.Bubble -> { + cornerRoundnessDp = 8 + imageCornerTransformation = messageLayout.cornersRadius.granularRoundedCorners() + } + else -> { + cornerRoundnessDp = 8 + imageCornerTransformation = RoundedCorners(dimensionConverter.dpToPx(cornerRoundnessDp)) + } } - imageContentRenderer.render(mediaData, effectiveMode, holder.imageView, imageCornerTransformation, onImageSizeListener) + imageContentRenderer.render(mediaData, effectiveMode, holder.imageView, cornerRoundnessDp, imageCornerTransformation, onImageSizeListener) if (!attributes.informationData.sendState.hasFailed()) { contentUploadStateTrackerBinder.bind( attributes.informationData.eventId, @@ -180,14 +195,16 @@ abstract class MessageImageVideoItem : AbsMessageItem { - // Don't show it for non-bubble layouts, don't show for Stickers, ... + // Don't show it for non-bubble layouts, don't show for Stickers, ... + // Also only supported for default corner radius + !(messageLayout.isRealBubble || messageLayout.isPseudoBubble) || mode != ImageContentRenderer.Mode.THUMBNAIL + || messageLayout.bubbleAppearance != defaultScBubbleAppearance -> { holder.mediaContentView.background = null } - attributes.informationData.sentByMe -> { + attributes.informationData.sentByMe -> { holder.mediaContentView.setBackgroundResource(R.drawable.background_image_border_outgoing) } - else -> { + else -> { holder.mediaContentView.setBackgroundResource(R.drawable.background_image_border_incoming) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt index b8573de4a0..923a034c80 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLocationItem.kt @@ -61,7 +61,7 @@ abstract class MessageLocationItem : AbsMessageItem( val messageLayout = attributes.informationData.messageLayout val dimensionConverter = DimensionConverter(holder.view.resources) val imageCornerTransformation = when (messageLayout) { - is TimelineMessageLayout.ScBubble -> RoundedCorners(dimensionConverter.dpToPx(3)) + is TimelineMessageLayout.ScBubble -> RoundedCorners(messageLayout.bubbleAppearance.getBubbleRadiusPx(holder.view.context)) is TimelineMessageLayout.Bubble -> messageLayout.cornersRadius.granularRoundedCorners() else -> RoundedCorners(dimensionConverter.dpToPx(8)) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt index 847d03e338..c4242bb3b4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt @@ -17,8 +17,9 @@ package im.vector.app.features.home.room.detail.timeline.style import android.os.Parcelable +import androidx.annotation.DrawableRes import im.vector.app.R -import im.vector.app.features.home.room.detail.timeline.item.AnonymousReadReceipt +import im.vector.app.features.themes.ScBubbleAppearance import kotlinx.parcelize.Parcelize sealed interface TimelineMessageLayout : Parcelable { @@ -68,6 +69,7 @@ sealed interface TimelineMessageLayout : Parcelable { override val showDisplayName: Boolean, override val showTimestamp: Boolean = true, override val showE2eDecoration: Boolean = false, + val bubbleAppearance: ScBubbleAppearance, val isIncoming: Boolean, val reverseBubble: Boolean, val singleSidedLayout: Boolean, @@ -79,6 +81,22 @@ sealed interface TimelineMessageLayout : Parcelable { R.layout.item_timeline_event_sc_bubble_incoming_base } else { R.layout.item_timeline_event_sc_bubble_outgoing_base + }, + @DrawableRes + val bubbleDrawable: Int = if (isPseudoBubble) { + 0 + } else if (showAvatar) { // tail + if (reverseBubble) { // outgoing + bubbleAppearance.textBubbleOutgoing + } else { // incoming + bubbleAppearance.textBubbleIncoming + } + } else { // notail + if (reverseBubble) { // outgoing + bubbleAppearance.textBubbleOutgoingNoTail + } else { // incoming + bubbleAppearance.textBubbleIncomingNoTail + } } ) : TimelineMessageLayout diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt index ff38d57909..4134387d1d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt @@ -112,6 +112,7 @@ class TimelineMessageLayoutFactory @Inject constructor(private val session: Sess // Display name still required for single sided layout if timestamp is shown (empty space looks bad otherwise) showDisplayName = showInformation && ((singleSidedLayout && showTimestamp) || !messageContent.redundantDisplayName()), showTimestamp = showTimestamp, + bubbleAppearance = bubbleThemeUtils.getBubbleAppearance(), isIncoming = !isSentByMe, isNotice = messageContent is MessageNoticeContent, reverseBubble = isSentByMe && !singleSidedLayout, @@ -168,6 +169,7 @@ class TimelineMessageLayoutFactory @Inject constructor(private val session: Sess showAvatar = false, showDisplayName = false, showTimestamp = true, + bubbleAppearance = bubbleThemeUtils.getBubbleAppearance(), isIncoming = false, isNotice = false, reverseBubble = false, diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/ScMessageBubbleWrapView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/ScMessageBubbleWrapView.kt index 85fc35f614..0574569b8c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/ScMessageBubbleWrapView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/ScMessageBubbleWrapView.kt @@ -264,21 +264,8 @@ class ScMessageBubbleWrapView @JvmOverloads constructor(context: Context, attrs: // Padding for bubble content: long for side with tail, short for other sides val longPaddingDp: Int val shortPaddingDp: Int + bubbleView.setBackgroundResource(messageLayout.bubbleDrawable) if (!messageLayout.isPseudoBubble) { - val bubbleRes = if (messageLayout.showAvatar) { // tail - if (messageLayout.reverseBubble) { // outgoing - R.drawable.msg_bubble_text_outgoing - } else { // incoming - R.drawable.msg_bubble_text_incoming - } - } else { // notail - if (messageLayout.reverseBubble) { // outgoing - R.drawable.msg_bubble_text_outgoing_notail - } else { // incoming - R.drawable.msg_bubble_text_incoming_notail - } - } - bubbleView.setBackgroundResource(bubbleRes) longPaddingDp = bubbleView.resources.getDimensionPixelSize(R.dimen.sc_bubble_inner_padding_long_side) shortPaddingDp = bubbleView.resources.getDimensionPixelSize(R.dimen.sc_bubble_inner_padding_short_side) } else { 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 00cce78010..dc1bdcb171 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 @@ -146,7 +146,7 @@ class ImageContentRenderer @Inject constructor(private val localFilesHelper: Loc .into(imageView) } - fun render(data: Data, mode: Mode, imageView: ImageView, cornerTransformation: Transformation = RoundedCorners(dimensionConverter.dpToPx(3)), onImageSizeListener: OnImageSizeListener? = null, animate: Boolean = false) { + fun render(data: Data, mode: Mode, imageView: ImageView, cornerRoundnessDp: Int = 3, cornerTransformation: Transformation = RoundedCorners(dimensionConverter.dpToPx(cornerRoundnessDp)), onImageSizeListener: OnImageSizeListener? = null, animate: Boolean = false) { val size = processSize(data, mode) imageView.updateLayoutParams { width = size.width @@ -177,8 +177,7 @@ class ImageContentRenderer @Inject constructor(private val localFilesHelper: Loc }) request = if (animate) { // Glide seems to already do some dp to px calculation for animated gifs? - // SC-TODO extract dp from cornerTransformation - request.transform(RoundedCorners(3)) + request.transform(RoundedCorners(cornerRoundnessDp)) //request.apply(RequestOptions.bitmapTransform(RoundedCorners(3))) } else { request.dontAnimate() diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBubbleAppearanceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBubbleAppearanceFragment.kt new file mode 100644 index 0000000000..29eff43f54 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsBubbleAppearanceFragment.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings + +import im.vector.app.R +import javax.inject.Inject + +class VectorSettingsBubbleAppearanceFragment @Inject constructor( + //private val vectorPreferences: VectorPreferences +) : VectorSettingsBaseFragment() { + + override var titleRes = R.string.bubble_appearance + override val preferenceXmlRes = R.xml.vector_settings_bubble_appearance + + override fun bindPref() { + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt index 026f973dd9..a316d4afea 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt @@ -43,11 +43,16 @@ class VectorSettingsPreferencesFragment @Inject constructor( private val vectorPreferences: VectorPreferences ) : VectorSettingsBaseFragment() { + companion object { + const val BUBBLE_APPEARANCE_KEY = "BUBBLE_APPEARANCE_KEY" + } + override var titleRes = R.string.settings_preferences override val preferenceXmlRes = R.xml.vector_settings_preferences //private var bubbleTimeLocationPref: VectorListPreference? = null private var alwaysShowTimestampsPref: VectorSwitchPreference? = null + private var bubbleAppearancePref: VectorPreference? = null private val selectedLanguagePreference by lazy { findPreference(VectorPreferences.SETTINGS_INTERFACE_LANGUAGE_PREFERENCE_KEY)!! @@ -104,6 +109,7 @@ class VectorSettingsPreferencesFragment @Inject constructor( } alwaysShowTimestampsPref = findPreference(VectorPreferences.SETTINGS_ALWAYS_SHOW_TIMESTAMPS_KEY) + bubbleAppearancePref = findPreference(BUBBLE_APPEARANCE_KEY) updateBubbleDependencies(bubbleStyle = bubbleStylePreference.value) findPreference(VectorPreferences.SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME)!!.let { pref -> @@ -246,6 +252,7 @@ class VectorSettingsPreferencesFragment @Inject constructor( private fun updateBubbleDependencies(bubbleStyle: String) { //bubbleTimeLocationPref?.setEnabled(BubbleThemeUtils.isBubbleTimeLocationSettingAllowed(bubbleStyle)) - alwaysShowTimestampsPref?.setEnabled(bubbleStyle in listOf(BubbleThemeUtils.BUBBLE_STYLE_NONE, BubbleThemeUtils.BUBBLE_STYLE_START)) + alwaysShowTimestampsPref?.isEnabled = bubbleStyle in listOf(BubbleThemeUtils.BUBBLE_STYLE_NONE, BubbleThemeUtils.BUBBLE_STYLE_START) + bubbleAppearancePref?.isEnabled = bubbleStyle in listOf(BubbleThemeUtils.BUBBLE_STYLE_START, BubbleThemeUtils.BUBBLE_STYLE_BOTH) } } diff --git a/vector/src/main/java/im/vector/app/features/themes/BubbleThemeUtils.kt b/vector/src/main/java/im/vector/app/features/themes/BubbleThemeUtils.kt index d0ebe7f34d..780c890032 100644 --- a/vector/src/main/java/im/vector/app/features/themes/BubbleThemeUtils.kt +++ b/vector/src/main/java/im/vector/app/features/themes/BubbleThemeUtils.kt @@ -2,9 +2,14 @@ package im.vector.app.features.themes import android.content.Context import android.graphics.Paint +import android.os.Parcelable import android.widget.TextView +import androidx.annotation.DimenRes +import androidx.annotation.DrawableRes import androidx.preference.PreferenceManager +import im.vector.app.R import im.vector.app.features.home.room.detail.timeline.item.AnonymousReadReceipt +import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import timber.log.Timber @@ -16,6 +21,11 @@ import javax.inject.Inject class BubbleThemeUtils @Inject constructor(private val context: Context) { companion object { const val BUBBLE_STYLE_KEY = "BUBBLE_STYLE_KEY" + const val BUBBLE_ROUNDNESS_KEY = "SETTINGS_SC_BUBBLE_ROUNDED_CORNERS" + const val BUBBLE_ROUNDNESS_DEFAULT = "default" + const val BUBBLE_ROUNDNESS_R1 = "r1" + const val BUBBLE_ROUNDNESS_R2 = "r2" + const val BUBBLE_TAIL_KEY = "SETTINGS_SC_BUBBLE_TAIL" const val BUBBLE_STYLE_NONE = "none" const val BUBBLE_STYLE_ELEMENT = "element" @@ -62,6 +72,22 @@ class BubbleThemeUtils @Inject constructor(private val context: Context) { PreferenceManager.getDefaultSharedPreferences(context).edit().putString(BUBBLE_STYLE_KEY, value).apply() } + fun getBubbleAppearance(): ScBubbleAppearance { + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + val baseAppearance = when (prefs.getString(BUBBLE_ROUNDNESS_KEY, BUBBLE_ROUNDNESS_DEFAULT)) { + BUBBLE_ROUNDNESS_R1 -> r1ScBubbleAppearance + BUBBLE_ROUNDNESS_R2 -> r2ScBubbleAppearance + else -> defaultScBubbleAppearance + } + return if (prefs.getBoolean(BUBBLE_TAIL_KEY, true)) { + baseAppearance + } else { + baseAppearance.copy( + textBubbleOutgoing = baseAppearance.textBubbleOutgoingNoTail, + textBubbleIncoming = baseAppearance.textBubbleIncomingNoTail + ) + } + } } fun guessTextWidth(view: TextView): Float { @@ -77,3 +103,49 @@ fun guessTextWidth(textSize: Float, text: CharSequence): Float { paint.textSize = textSize return paint.measureText(text.toString()) } + +@Parcelize +data class ScBubbleAppearance( + @DimenRes + val roundness: Int, + @DrawableRes + val textBubbleOutgoing: Int, + @DrawableRes + val textBubbleIncoming: Int, + @DrawableRes + val textBubbleOutgoingNoTail: Int, + @DrawableRes + val textBubbleIncomingNoTail: Int, +) : Parcelable { + fun getBubbleRadiusPx(context: Context): Int { + return context.resources.getDimensionPixelSize(roundness) + } + fun getBubbleRadiusDp(context: Context): Float { + return context.resources.getDimension(roundness) + } +} + +val defaultScBubbleAppearance = ScBubbleAppearance( + R.dimen.sc_bubble_radius, + R.drawable.msg_bubble_text_outgoing, + R.drawable.msg_bubble_text_incoming, + R.drawable.msg_bubble_text_outgoing_notail, + R.drawable.msg_bubble_text_incoming_notail, +) + +val r1ScBubbleAppearance = ScBubbleAppearance( + R.dimen.sc_bubble_r1_radius, + R.drawable.msg_bubble_r1_text_outgoing, + R.drawable.msg_bubble_r1_text_incoming, + R.drawable.msg_bubble_r1_text_outgoing_notail, + R.drawable.msg_bubble_r1_text_incoming_notail, +) + + +val r2ScBubbleAppearance = ScBubbleAppearance( + R.dimen.sc_bubble_r2_radius, + R.drawable.msg_bubble_r2_text_outgoing, + R.drawable.msg_bubble_r2_text_incoming, + R.drawable.msg_bubble_r2_text_outgoing_notail, + R.drawable.msg_bubble_r2_text_incoming_notail, +) diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_incoming.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_incoming.xml new file mode 100644 index 0000000000..4a3e42c64b --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_incoming.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_incoming_notail.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_incoming_notail.xml new file mode 100644 index 0000000000..31ca8fc8a0 --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_incoming_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_outgoing.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_outgoing.xml new file mode 100644 index 0000000000..cf9f23d270 --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_outgoing.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_outgoing_notail.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_outgoing_notail.xml new file mode 100644 index 0000000000..87c322fd8c --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r1_text_outgoing_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_incoming.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_incoming.xml new file mode 100644 index 0000000000..ae6cb9e02c --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_incoming.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_incoming_notail.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_incoming_notail.xml new file mode 100644 index 0000000000..da92ad8b55 --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_incoming_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_outgoing.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_outgoing.xml new file mode 100644 index 0000000000..e88276d9fc --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_outgoing.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_outgoing_notail.xml b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_outgoing_notail.xml new file mode 100644 index 0000000000..e57bb803b9 --- /dev/null +++ b/vector/src/main/res/drawable-ldrtl/msg_bubble_r2_text_outgoing_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r1_text_incoming.xml b/vector/src/main/res/drawable/msg_bubble_r1_text_incoming.xml new file mode 100644 index 0000000000..6ff25128c0 --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r1_text_incoming.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r1_text_incoming_notail.xml b/vector/src/main/res/drawable/msg_bubble_r1_text_incoming_notail.xml new file mode 100644 index 0000000000..a063054e73 --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r1_text_incoming_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r1_text_outgoing.xml b/vector/src/main/res/drawable/msg_bubble_r1_text_outgoing.xml new file mode 100644 index 0000000000..15ad2fffed --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r1_text_outgoing.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r1_text_outgoing_notail.xml b/vector/src/main/res/drawable/msg_bubble_r1_text_outgoing_notail.xml new file mode 100644 index 0000000000..6f1f14d25a --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r1_text_outgoing_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r2_text_incoming.xml b/vector/src/main/res/drawable/msg_bubble_r2_text_incoming.xml new file mode 100644 index 0000000000..15e6d40367 --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r2_text_incoming.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r2_text_incoming_notail.xml b/vector/src/main/res/drawable/msg_bubble_r2_text_incoming_notail.xml new file mode 100644 index 0000000000..0cdae4e0b8 --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r2_text_incoming_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r2_text_outgoing.xml b/vector/src/main/res/drawable/msg_bubble_r2_text_outgoing.xml new file mode 100644 index 0000000000..b2ecd4fb56 --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r2_text_outgoing.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/drawable/msg_bubble_r2_text_outgoing_notail.xml b/vector/src/main/res/drawable/msg_bubble_r2_text_outgoing_notail.xml new file mode 100644 index 0000000000..4e5900ecac --- /dev/null +++ b/vector/src/main/res/drawable/msg_bubble_r2_text_outgoing_notail.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/values/arrays_sc.xml b/vector/src/main/res/values/arrays_sc.xml index 5b9a554b0a..8205a7f6f1 100644 --- a/vector/src/main/res/values/arrays_sc.xml +++ b/vector/src/main/res/values/arrays_sc.xml @@ -14,6 +14,17 @@ none + + @string/bubble_rounded_corners_default + @string/bubble_rounded_corners_r1 + @string/bubble_rounded_corners_r2 + + + default + r1 + r2 + + @string/bubble_time_location_top @string/bubble_time_location_bottom diff --git a/vector/src/main/res/values/dimens_sc.xml b/vector/src/main/res/values/dimens_sc.xml index 143575f9ae..1413f7fdf3 100644 --- a/vector/src/main/res/values/dimens_sc.xml +++ b/vector/src/main/res/values/dimens_sc.xml @@ -20,6 +20,12 @@ 32dp + + 8dp + 12dp + @dimen/sc_bubble_radius_in_tail + @dimen/sc_bubble_radius_in_tail + 2dp 4dp diff --git a/vector/src/main/res/values/strings_sc.xml b/vector/src/main/res/values/strings_sc.xml index 6f0f4307b0..53609e7fbe 100644 --- a/vector/src/main/res/values/strings_sc.xml +++ b/vector/src/main/res/values/strings_sc.xml @@ -45,6 +45,14 @@ Top Bottom + Bubble appearance + Corners + Default + Round + Extra round + Bubble tail + Include bubble tail for a sender\'s first message + Unread counter Count muted messages Show counts for muted messages in the chat overview diff --git a/vector/src/main/res/xml/vector_settings_bubble_appearance.xml b/vector/src/main/res/xml/vector_settings_bubble_appearance.xml new file mode 100644 index 0000000000..80f8d33bcc --- /dev/null +++ b/vector/src/main/res/xml/vector_settings_bubble_appearance.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vector/src/main/res/xml/vector_settings_preferences.xml b/vector/src/main/res/xml/vector_settings_preferences.xml index b0c932bd78..ae17e7d192 100644 --- a/vector/src/main/res/xml/vector_settings_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_preferences.xml @@ -38,6 +38,10 @@ android:title="@string/settings_dark_theme" app:iconSpaceReserved="false" /> + + + +