mirror of
https://github.com/element-hq/element-android
synced 2024-11-25 02:45:37 +03:00
Merge pull request #574 from vector-im/feature/big_emoji
Embiggen messages with multiple emojis also for edited messages
This commit is contained in:
commit
001711d5a3
12 changed files with 60 additions and 28 deletions
|
@ -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:
|
||||
-
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -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<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>
|
|||
@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
|
||||
|
|
|
@ -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<MessageTextItem.Holder>() {
|
|||
@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<MessageTextItem.Holder>() {
|
|||
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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue