diff --git a/CHANGES.md b/CHANGES.md index 54e29ef660..8cb9a0023e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ Bugfix: - Fix characters erased from the Search field when the result are coming (#545) - "No connection" banner was displayed by mistake - Leaving community (from another client) has no effect on RiotX (#497) + - Embiggen messages with multiple emojis also for edited messages (#458) Translations: - diff --git a/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt b/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt index d755815595..a76091fb36 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/VectorComponent.kt @@ -27,6 +27,7 @@ import im.vector.riotx.EmojiCompatFontProvider import im.vector.riotx.EmojiCompatWrapper import im.vector.riotx.VectorApplication import im.vector.riotx.core.pushers.PushersManager +import im.vector.riotx.core.utils.DimensionConverter import im.vector.riotx.features.configuration.VectorConfiguration import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler @@ -63,6 +64,8 @@ interface VectorComponent { fun resources(): Resources + fun dimensionUtils(): DimensionConverter + fun vectorConfiguration(): VectorConfiguration fun avatarRenderer(): AvatarRenderer diff --git a/vector/src/main/java/im/vector/riotx/core/utils/DimensionUtils.kt b/vector/src/main/java/im/vector/riotx/core/utils/DimensionConverter.kt similarity index 77% rename from vector/src/main/java/im/vector/riotx/core/utils/DimensionUtils.kt rename to vector/src/main/java/im/vector/riotx/core/utils/DimensionConverter.kt index 15257f9c5d..3b8e3ed5cb 100644 --- a/vector/src/main/java/im/vector/riotx/core/utils/DimensionUtils.kt +++ b/vector/src/main/java/im/vector/riotx/core/utils/DimensionConverter.kt @@ -15,25 +15,26 @@ */ package im.vector.riotx.core.utils -import android.content.Context +import android.content.res.Resources import android.util.TypedValue +import javax.inject.Inject -object DimensionUtils { +class DimensionConverter @Inject constructor(val resources: Resources) { - fun dpToPx(dp: Int, context: Context): Int { + fun dpToPx(dp: Int): Int { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), - context.resources.displayMetrics + resources.displayMetrics ).toInt() } - fun spToPx(sp: Int, context: Context): Int { + fun spToPx(sp: Int): Int { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, sp.toFloat(), - context.resources.displayMetrics + resources.displayMetrics ).toInt() } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt index 7747336627..c7aeed645b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomKnownUsersFragment.kt @@ -36,7 +36,7 @@ import im.vector.riotx.core.extensions.hideKeyboard import im.vector.riotx.core.extensions.observeEvent import im.vector.riotx.core.extensions.setupAsSearch import im.vector.riotx.core.platform.VectorBaseFragment -import im.vector.riotx.core.utils.DimensionUtils +import im.vector.riotx.core.utils.DimensionConverter import im.vector.riotx.features.home.AvatarRenderer import kotlinx.android.synthetic.main.fragment_create_direct_room.* import javax.inject.Inject @@ -51,6 +51,7 @@ class CreateDirectRoomKnownUsersFragment : VectorBaseFragment(), KnownUsersContr @Inject lateinit var directRoomController: KnownUsersController @Inject lateinit var avatarRenderer: AvatarRenderer + @Inject lateinit var dimensionConverter: DimensionConverter private lateinit var navigationViewModel: CreateDirectRoomNavigationViewModel override fun injectWith(injector: ScreenComponent) { @@ -156,7 +157,7 @@ class CreateDirectRoomKnownUsersFragment : VectorBaseFragment(), KnownUsersContr private fun addChipToGroup(user: User, chipGroup: ChipGroup) { val chip = Chip(requireContext()) chip.setChipBackgroundColorResource(android.R.color.transparent) - chip.chipStrokeWidth = DimensionUtils.dpToPx(1, requireContext()).toFloat() + chip.chipStrokeWidth = dimensionConverter.dpToPx(1).toFloat() chip.text = if (user.displayName.isNullOrBlank()) user.userId else user.displayName chip.isClickable = true chip.isCheckable = false diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt index 080565cd16..9c4c59c46c 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt @@ -25,6 +25,7 @@ import im.vector.riotx.core.epoxy.VectorEpoxyModel import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.utils.DebouncedClickListener +import im.vector.riotx.core.utils.DimensionConverter import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem_ @@ -36,7 +37,8 @@ import javax.inject.Inject class EncryptedItemFactory @Inject constructor(private val messageInformationDataFactory: MessageInformationDataFactory, private val colorProvider: ColorProvider, private val stringProvider: StringProvider, - private val avatarRenderer: AvatarRenderer) { + private val avatarRenderer: AvatarRenderer, + private val dimensionConverter: DimensionConverter) { fun create(event: TimelineEvent, nextEvent: TimelineEvent?, @@ -69,6 +71,7 @@ class EncryptedItemFactory @Inject constructor(private val messageInformationDat .message(spannableStr) .avatarRenderer(avatarRenderer) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .informationData(informationData) .highlighted(highlight) .avatarCallback(callback) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt index 4a3f50c45e..58804f5f32 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt @@ -23,6 +23,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent import im.vector.riotx.R import im.vector.riotx.core.resources.StringProvider +import im.vector.riotx.core.utils.DimensionConverter import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.helper.senderAvatar @@ -33,7 +34,8 @@ import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_ import javax.inject.Inject class EncryptionItemFactory @Inject constructor(private val stringProvider: StringProvider, - private val avatarRenderer: AvatarRenderer) { + private val avatarRenderer: AvatarRenderer, + private val dimensionConverter: DimensionConverter) { fun create(event: TimelineEvent, highlight: Boolean, @@ -50,6 +52,7 @@ class EncryptionItemFactory @Inject constructor(private val stringProvider: Stri ) return NoticeItem_() .avatarRenderer(avatarRenderer) + .dimensionConverter(dimensionConverter) .noticeText(text) .informationData(informationData) .highlighted(highlight) 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 3c636bfa58..4819db4075 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 @@ -19,9 +19,9 @@ package im.vector.riotx.features.home.room.detail.timeline.factory import android.text.SpannableStringBuilder import android.text.Spanned import android.text.TextPaint +import android.text.style.AbsoluteSizeSpan import android.text.style.ClickableSpan import android.text.style.ForegroundColorSpan -import android.text.style.RelativeSizeSpan import android.view.View import dagger.Lazy import im.vector.matrix.android.api.permalinks.MatrixLinkify @@ -40,6 +40,8 @@ import im.vector.riotx.core.linkify.VectorLinkify import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.utils.DebouncedClickListener +import im.vector.riotx.core.utils.DimensionConverter +import im.vector.riotx.core.utils.containsOnlyEmojis import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder @@ -62,7 +64,8 @@ class MessageItemFactory @Inject constructor( private val imageContentRenderer: ImageContentRenderer, private val messageInformationDataFactory: MessageInformationDataFactory, private val contentUploadStateTrackerBinder: ContentUploadStateTrackerBinder, - private val noticeItemFactory: NoticeItemFactory) { + private val noticeItemFactory: NoticeItemFactory, + private val dimensionConverter: DimensionConverter) { fun create(event: TimelineEvent, @@ -113,6 +116,7 @@ class MessageItemFactory @Inject constructor( return MessageFileItem_() .avatarRenderer(avatarRenderer) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .informationData(informationData) .highlighted(highlight) .avatarCallback(callback) @@ -142,6 +146,7 @@ class MessageItemFactory @Inject constructor( return MessageFileItem_() .avatarRenderer(avatarRenderer) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .informationData(informationData) .highlighted(highlight) .avatarCallback(callback) @@ -171,6 +176,7 @@ class MessageItemFactory @Inject constructor( return DefaultItem_() .text(text) .avatarRenderer(avatarRenderer) + .dimensionConverter(dimensionConverter) .highlighted(highlight) .informationData(informationData) .baseCallback(callback) @@ -197,6 +203,7 @@ class MessageItemFactory @Inject constructor( return MessageImageVideoItem_() .avatarRenderer(avatarRenderer) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .imageContentRenderer(imageContentRenderer) .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder) .playable(messageContent.info?.mimeType == "image/gif") @@ -251,6 +258,7 @@ class MessageItemFactory @Inject constructor( .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder) .avatarRenderer(avatarRenderer) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .playable(true) .informationData(informationData) .highlighted(highlight) @@ -290,9 +298,11 @@ class MessageItemFactory @Inject constructor( message(linkifiedBody) } } + .useBigFont(linkifiedBody.length <= MAX_NUMBER_OF_EMOJI_FOR_BIG_FONT * 2 && containsOnlyEmojis(linkifiedBody.toString())) .avatarRenderer(avatarRenderer) .informationData(informationData) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .highlighted(highlight) .avatarCallback(callback) .urlClickCallback(callback) @@ -326,7 +336,8 @@ class MessageItemFactory @Inject constructor( editEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) - spannable.setSpan(RelativeSizeSpan(.9f), editStart, editEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + // Note: text size is set to 14sp + spannable.setSpan(AbsoluteSizeSpan(dimensionConverter.spToPx(13)), editStart, editEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) spannable.setSpan(object : ClickableSpan() { override fun onClick(widget: View?) { callback?.onEditedDecorationClicked(informationData) @@ -359,6 +370,7 @@ class MessageItemFactory @Inject constructor( .avatarRenderer(avatarRenderer) .message(message) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .informationData(informationData) .highlighted(highlight) .avatarCallback(callback) @@ -400,6 +412,7 @@ class MessageItemFactory @Inject constructor( } .avatarRenderer(avatarRenderer) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .informationData(informationData) .highlighted(highlight) .avatarCallback(callback) @@ -423,6 +436,7 @@ class MessageItemFactory @Inject constructor( return RedactedMessageItem_() .avatarRenderer(avatarRenderer) .colorProvider(colorProvider) + .dimensionConverter(dimensionConverter) .informationData(informationData) .highlighted(highlight) .avatarCallback(callback) @@ -447,4 +461,8 @@ class MessageItemFactory @Inject constructor( VectorLinkify.addLinks(spannable, true) return spannable } + + companion object { + private const val MAX_NUMBER_OF_EMOJI_FOR_BIG_FONT = 5 + } } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/NoticeItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/NoticeItemFactory.kt index f73a200133..76ac0e70f5 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/NoticeItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/NoticeItemFactory.kt @@ -17,12 +17,10 @@ package im.vector.riotx.features.home.room.detail.timeline.factory import im.vector.matrix.android.api.session.room.timeline.TimelineEvent +import im.vector.riotx.core.utils.DimensionConverter import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventFormatter -import im.vector.riotx.features.home.room.detail.timeline.helper.senderAvatar -import im.vector.riotx.features.home.room.detail.timeline.helper.senderName -import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_ import im.vector.riotx.features.home.room.detail.timeline.util.MessageInformationDataFactory @@ -30,7 +28,8 @@ import javax.inject.Inject class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEventFormatter, private val avatarRenderer: AvatarRenderer, - private val informationDataFactory: MessageInformationDataFactory) { + private val informationDataFactory: MessageInformationDataFactory, + private val dimensionConverter: DimensionConverter) { fun create(event: TimelineEvent, highlight: Boolean, @@ -40,6 +39,7 @@ class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEv return NoticeItem_() .avatarRenderer(avatarRenderer) + .dimensionConverter(dimensionConverter) .noticeText(formattedText) .highlighted(highlight) .informationData(informationData) 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 2a4142e474..8cc181bd37 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 @@ -33,7 +33,6 @@ import im.vector.matrix.android.api.session.room.send.SendState import im.vector.riotx.R import im.vector.riotx.core.resources.ColorProvider import im.vector.riotx.core.utils.DebouncedClickListener -import im.vector.riotx.core.utils.DimensionUtils.dpToPx import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.reactions.widget.ReactionButton @@ -100,7 +99,7 @@ abstract class AbsMessageItem : BaseEventItem() { super.bind(holder) if (informationData.showInformation) { holder.avatarImageView.layoutParams = holder.avatarImageView.layoutParams?.apply { - val size = dpToPx(avatarStyle.avatarSizeDP, holder.view.context) + val size = dimensionConverter.dpToPx(avatarStyle.avatarSizeDP) height = size width = size } 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 96625d16b8..561059de63 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 @@ -25,7 +25,7 @@ import im.vector.riotx.core.epoxy.VectorEpoxyHolder 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.DimensionUtils.dpToPx +import im.vector.riotx.core.utils.DimensionConverter /** * Children must override getViewType() @@ -38,10 +38,13 @@ abstract class BaseEventItem : VectorEpoxyModel @EpoxyAttribute var highlighted: Boolean = false + @EpoxyAttribute + lateinit var dimensionConverter: DimensionConverter + override fun bind(holder: H) { super.bind(holder) //optimize? - val px = dpToPx(avatarStyle.avatarSizeDP + 8, holder.view.context) + val px = dimensionConverter.dpToPx(avatarStyle.avatarSizeDP + 8) holder.leftGuideline.setGuidelineBegin(px) holder.checkableBackground.isChecked = highlighted 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 fc867b1277..3d682cdde3 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 @@ -24,7 +24,6 @@ import androidx.core.widget.TextViewCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.riotx.R -import im.vector.riotx.core.utils.containsOnlyEmojis import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController import im.vector.riotx.features.html.PillImageSpan import kotlinx.coroutines.Dispatchers @@ -39,6 +38,8 @@ abstract class MessageTextItem : AbsMessageItem() { @EpoxyAttribute var message: CharSequence? = null @EpoxyAttribute + var useBigFont: Boolean = false + @EpoxyAttribute var urlClickCallback: TimelineEventController.UrlClickCallback? = null // Better link movement methods fixes the issue when @@ -65,9 +66,7 @@ abstract class MessageTextItem : AbsMessageItem() { super.bind(holder) holder.messageView.movementMethod = mvmtMethod - - val msg = message ?: "" - if (msg.length <= 4 && containsOnlyEmojis(msg.toString())) { + if (useBigFont) { holder.messageView.textSize = 44F } else { holder.messageView.textSize = 14F diff --git a/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt index 7a7c880ca7..299f0af470 100644 --- a/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt +++ b/vector/src/main/java/im/vector/riotx/features/media/ImageContentRenderer.kt @@ -32,13 +32,14 @@ import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.glide.GlideApp import im.vector.riotx.core.glide.GlideRequest -import im.vector.riotx.core.utils.DimensionUtils.dpToPx +import im.vector.riotx.core.utils.DimensionConverter import kotlinx.android.parcel.Parcelize import timber.log.Timber import java.io.File import javax.inject.Inject -class ImageContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) { +class ImageContentRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder, + private val dimensionConverter: DimensionConverter) { @Parcelize data class Data( @@ -70,7 +71,7 @@ class ImageContentRenderer @Inject constructor(private val activeSessionHolder: createGlideRequest(data, mode, imageView, width, height) .dontAnimate() - .transform(RoundedCorners(dpToPx(8, imageView.context))) + .transform(RoundedCorners(dimensionConverter.dpToPx(8))) .thumbnail(0.3f) .into(imageView)