Merge pull request #325 from vector-im/feature/non_unicode_reaction
Accept non unicode reactions
This commit is contained in:
commit
a51d96bf00
|
@ -5,10 +5,10 @@ Features:
|
|||
- Display read receipts in timeline (#81)
|
||||
|
||||
Improvements:
|
||||
-
|
||||
- Reactions: Reinstate the ability to react with non-unicode keys (#307)
|
||||
|
||||
Other changes:
|
||||
-
|
||||
-
|
||||
|
||||
Bugfix:
|
||||
- Fix text diff linebreak display (#441)
|
||||
|
|
|
@ -318,6 +318,8 @@ dependencies {
|
|||
|
||||
implementation 'diff_match_patch:diff_match_patch:current'
|
||||
|
||||
implementation "androidx.emoji:emoji-appcompat:1.0.0"
|
||||
|
||||
// TESTS
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
|
|
|
@ -19,10 +19,13 @@ package im.vector.riotx
|
|||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import androidx.core.provider.FontRequest
|
||||
import androidx.core.provider.FontsContractCompat
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
import androidx.emoji.text.FontRequestEmojiCompatConfig
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
|
@ -105,6 +108,23 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
|
|||
)
|
||||
FontsContractCompat.requestFont(this, fontRequest, emojiCompatFontProvider, getFontThreadHandler())
|
||||
vectorConfiguration.initConfiguration()
|
||||
|
||||
//Use emoji compat for the benefit of emoji spans
|
||||
val config = FontRequestEmojiCompatConfig(this, fontRequest)
|
||||
.setReplaceAll(true) // we want to replace all emojis with selected font
|
||||
// .setEmojiSpanIndicatorEnabled(true)
|
||||
// .setEmojiSpanIndicatorColor(Color.GREEN)
|
||||
EmojiCompat.init(config)
|
||||
.registerInitCallback(object : EmojiCompat.InitCallback() {
|
||||
override fun onInitialized() {
|
||||
Timber.v("Emoji compat onInitialized success ")
|
||||
}
|
||||
|
||||
override fun onFailed(throwable: Throwable?) {
|
||||
Timber.e(throwable,"Failed to init EmojiCompat")
|
||||
}
|
||||
})
|
||||
|
||||
NotificationUtils.createNotificationChannels(applicationContext)
|
||||
if (authenticator.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
|
||||
val lastAuthenticatedSession = authenticator.getLastAuthenticatedSession()!!
|
||||
|
|
|
@ -35,7 +35,6 @@ import im.vector.riotx.R
|
|||
import im.vector.riotx.core.extensions.canReact
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.core.utils.isSingleEmoji
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||
|
||||
|
||||
|
@ -244,7 +243,7 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M
|
|||
//Only event of type Event.EVENT_TYPE_MESSAGE are supported for the moment
|
||||
if (event.root.getClearType() != EventType.MESSAGE) return false
|
||||
//TODO if user is admin or moderator
|
||||
return event.annotations?.reactionsSummary?.any { isSingleEmoji(it.key) } ?: false
|
||||
return event.annotations?.reactionsSummary?.isNotEmpty() ?: false
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,12 +38,8 @@ abstract class ReactionInfoSimpleItem : EpoxyModelWithHolder<ReactionInfoSimpleI
|
|||
@EpoxyAttribute
|
||||
var timeStamp: CharSequence? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var emojiTypeFace: Typeface? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
holder.emojiReactionView.text = reactionKey
|
||||
holder.emojiReactionView.typeface = emojiTypeFace ?: Typeface.DEFAULT
|
||||
holder.displayNameView.text = authorDisplayName
|
||||
timeStamp?.let {
|
||||
holder.timeStampView.text = it
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.airbnb.epoxy.EpoxyRecyclerView
|
|||
import com.airbnb.mvrx.MvRx
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.riotx.EmojiCompatFontProvider
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.di.ScreenComponent
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||
|
@ -43,13 +42,12 @@ class ViewReactionBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
private val viewModel: ViewReactionViewModel by fragmentViewModel(ViewReactionViewModel::class)
|
||||
|
||||
@Inject lateinit var viewReactionViewModelFactory: ViewReactionViewModel.Factory
|
||||
@Inject lateinit var emojiCompatFontProvider: EmojiCompatFontProvider
|
||||
|
||||
@BindView(R.id.bottom_sheet_display_reactions_list)
|
||||
lateinit var epoxyRecyclerView: EpoxyRecyclerView
|
||||
|
||||
private val epoxyController by lazy {
|
||||
ViewReactionsEpoxyController(requireContext(), emojiCompatFontProvider.typeface)
|
||||
ViewReactionsEpoxyController(requireContext())
|
||||
}
|
||||
|
||||
override fun injectWith(screenComponent: ScreenComponent) {
|
||||
|
|
|
@ -90,7 +90,7 @@ class ViewReactionViewModel @AssistedInject constructor(@Assisted
|
|||
.flatMapSingle { summaries ->
|
||||
Observable
|
||||
.fromIterable(summaries.reactionsSummary)
|
||||
.filter { reactionAggregatedSummary -> isSingleEmoji(reactionAggregatedSummary.key) }
|
||||
//.filter { reactionAggregatedSummary -> isSingleEmoji(reactionAggregatedSummary.key) }
|
||||
.toReactionInfoList()
|
||||
}
|
||||
.execute {
|
||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.riotx.features.home.room.detail.timeline.action
|
|||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.text.format.DateUtils
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Incomplete
|
||||
|
@ -30,7 +31,7 @@ import im.vector.riotx.core.ui.list.genericLoaderItem
|
|||
/**
|
||||
* Epoxy controller for reaction event list
|
||||
*/
|
||||
class ViewReactionsEpoxyController(private val context: Context, private val emojiCompatTypeface: Typeface?)
|
||||
class ViewReactionsEpoxyController(private val context: Context)
|
||||
: TypedEpoxyController<DisplayReactionsViewState>() {
|
||||
|
||||
override fun buildModels(state: DisplayReactionsViewState) {
|
||||
|
@ -50,9 +51,8 @@ class ViewReactionsEpoxyController(private val context: Context, private val emo
|
|||
state.mapReactionKeyToMemberList()?.forEach {
|
||||
reactionInfoSimpleItem {
|
||||
id(it.eventId)
|
||||
emojiTypeFace(emojiCompatTypeface)
|
||||
timeStamp(it.timestamp)
|
||||
reactionKey(it.reactionKey)
|
||||
reactionKey(EmojiCompat.get().process(it.reactionKey))
|
||||
authorDisplayName(it.authorName ?: it.authorId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
|
|||
idToRefInFlow.add(reactionButton.id)
|
||||
reactionButton.reactionString = reaction.key
|
||||
reactionButton.reactionCount = reaction.count
|
||||
reactionButton.emojiTypeFace = emojiTypeFace
|
||||
//reactionButton.emojiTypeFace = emojiTypeFace
|
||||
reactionButton.setChecked(reaction.addedByMe)
|
||||
reactionButton.isEnabled = reaction.synced
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses
|
|||
memberName = formattedMemberName,
|
||||
showInformation = showInformation,
|
||||
orderedReactionList = event.annotations?.reactionsSummary
|
||||
?.filter { isSingleEmoji(it.key) }
|
||||
//?.filter { isSingleEmoji(it.key) }
|
||||
?.map {
|
||||
ReactionInfoData(it.key, it.count, it.addedByMe, it.localEchoEvents.isEmpty())
|
||||
},
|
||||
|
|
|
@ -35,6 +35,7 @@ import android.widget.TextView
|
|||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.utils.TextUtils
|
||||
|
||||
|
@ -58,12 +59,6 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
|
||||
private var reactionSelector: View? = null
|
||||
|
||||
var emojiTypeFace: Typeface? = null
|
||||
set(value) {
|
||||
field = value
|
||||
emojiView?.typeface = value ?: Typeface.DEFAULT
|
||||
}
|
||||
|
||||
private var dotsView: DotsView
|
||||
private var circleView: CircleView
|
||||
var reactedListener: ReactedListener? = null
|
||||
|
@ -82,7 +77,9 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
var reactionString = "😀"
|
||||
set(value) {
|
||||
field = value
|
||||
emojiView?.text = field
|
||||
//maybe cache this for performances?
|
||||
val emojiSpanned = EmojiCompat.get().process(value)
|
||||
emojiView?.text = emojiSpanned
|
||||
}
|
||||
|
||||
private var animationScaleFactor: Float = 0.toFloat()
|
||||
|
@ -104,7 +101,7 @@ class ReactionButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
|
||||
countTextView?.text = TextUtils.formatCountToShortDecimal(reactionCount)
|
||||
|
||||
emojiView?.typeface = this.emojiTypeFace ?: Typeface.DEFAULT
|
||||
// emojiView?.typeface = this.emojiTypeFace ?: Typeface.DEFAULT
|
||||
|
||||
val array = context.obtainStyledAttributes(attrs, R.styleable.ReactionButton, defStyleAttr, 0)
|
||||
|
||||
|
|
|
@ -37,20 +37,23 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/reactionText"
|
||||
android:layout_width="20dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:minWidth="20dp"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="13sp"
|
||||
android:maxEms="10"
|
||||
android:ellipsize="middle"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/reactionCount"
|
||||
tools:text="👍" />
|
||||
tools:text="* Party Parrot Again * 👀" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reactionCount"
|
||||
|
@ -58,8 +61,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintBaseline_toBaselineOf="@id/reactionText"
|
||||
android:layout_marginStart="-4dp"
|
||||
android:layout_marginLeft="-4dp"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:gravity="center"
|
||||
|
|
Loading…
Reference in New Issue