Only show reactions with an emoji key

This commit is contained in:
Benoit Marty 2019-06-28 11:28:41 +02:00
parent 83ceb36a12
commit 0a908136b6
5 changed files with 71 additions and 25 deletions

View File

@ -54,6 +54,7 @@ import im.vector.riotredesign.push.fcm.FcmHelper
import timber.log.Timber
import java.text.SimpleDateFormat
import java.util.*
import im.vector.riotredesign.core.utils.initKnownEmojiHashSet
import javax.inject.Inject

class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.Provider, androidx.work.Configuration.Provider {
@ -124,6 +125,8 @@ class VectorApplication : Application(), HasVectorInjector, MatrixConfiguration.
FcmHelper.onEnterBackground(appContext, activeSessionHolder)
}
})
//This should be done as early as possible
initKnownEmojiHashSet(appContext)
}

override fun providesMatrixConfiguration() = MatrixConfiguration(BuildConfig.FLAVOR_DESCRIPTION)

View File

@ -1,5 +1,12 @@
package im.vector.riotredesign.core.utils

import android.content.Context
import com.squareup.moshi.Moshi
import im.vector.riotredesign.R
import im.vector.riotredesign.features.reactions.EmojiDataSource
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.regex.Pattern

private val emojisPattern = Pattern.compile("((?:[\uD83C\uDF00-\uD83D\uDDFF]" +
@ -26,6 +33,34 @@ private val emojisPattern = Pattern.compile("((?:[\uD83C\uDF00-\uD83D\uDDFF]" +
"|\uD83C\uDCCF\uFE0F?" +
"|[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?))")

//A hashset from all supported emoji
private var knownEmojiSet: HashSet<String>? = null

fun initKnownEmojiHashSet(context: Context, done: (() -> Unit)? = null) {
GlobalScope.launch {
context.resources.openRawResource(R.raw.emoji_picker_datasource).use { input ->
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(EmojiDataSource.EmojiData::class.java)
val inputAsString = input.bufferedReader().use { it.readText() }
val source = jsonAdapter.fromJson(inputAsString)
knownEmojiSet = HashSet<String>()
source?.emojis?.values?.forEach {
knownEmojiSet?.add(it.emojiString())
}
done?.invoke()
}
}
}

fun isSingleEmoji(string: String): Boolean {
if (knownEmojiSet == null) {
Timber.e("Known Emoji Hashset not initialized")
//use fallback regexp
return containsOnlyEmojis(string)
}
return knownEmojiSet?.contains(string) ?: false
}

/**
* Test if a string contains emojis.
* It seems that the regex [emoji_regex]+ does not work.
@ -66,4 +101,3 @@ fun containsOnlyEmojis(str: String?): Boolean {

return res
}


View File

@ -36,6 +36,9 @@ import im.vector.riotredesign.core.resources.StringProvider
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
import org.json.JSONObject

import im.vector.riotredesign.core.utils.isSingleEmoji


data class SimpleAction(val uid: String, val titleRes: Int, val iconResId: Int?, val data: Any? = null)

data class MessageMenuState(
@ -92,7 +95,7 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M
val event = session.getRoom(state.roomId)?.getTimeLineEvent(state.eventId) ?: return state

val messageContent: MessageContent? = event.annotations?.editSummary?.aggregatedContent?.toModel()
?: event.root.content.toModel()
?: event.root.content.toModel()
val type = messageContent?.type

val actions = if (!event.sendState.isSent()) {
@ -143,8 +146,8 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M
if (messageContent is MessageImageContent) {
this.add(
SimpleAction(ACTION_SHARE,
R.string.share, R.drawable.ic_share,
session.contentUrlResolver().resolveFullSize(messageContent.url))
R.string.share, R.drawable.ic_share,
session.contentUrlResolver().resolveFullSize(messageContent.url))
)
}
//TODO
@ -212,31 +215,31 @@ class MessageMenuViewModel @AssistedInject constructor(@Assisted initialState: M
}
}

private fun canRedact(event: TimelineEvent, myUserId: String): Boolean {
//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.root.senderId == myUserId
}
private fun canRedact(event: TimelineEvent, myUserId: String): Boolean {
//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.root.senderId == myUserId
}

private fun canViewReactions(event: TimelineEvent): Boolean {
//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?.isNotEmpty() ?: false
return event.annotations?.reactionsSummary?.any { isSingleEmoji(it.key) } ?: false
}


private fun canEdit(event: TimelineEvent, myUserId: String): Boolean {
//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
val messageContent = event.root.content.toModel<MessageContent>()
return event.root.senderId == myUserId && (
messageContent?.type == MessageType.MSGTYPE_TEXT
|| messageContent?.type == MessageType.MSGTYPE_EMOTE
)
}
private fun canEdit(event: TimelineEvent, myUserId: String): Boolean {
//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
val messageContent = event.root.content.toModel<MessageContent>()
return event.root.senderId == myUserId && (
messageContent?.type == MessageType.MSGTYPE_TEXT
|| messageContent?.type == MessageType.MSGTYPE_EMOTE
)
}


private fun canCopy(type: String?): Boolean {

View File

@ -8,6 +8,7 @@ import im.vector.matrix.android.api.session.room.model.ReactionAggregatedSummary
import im.vector.matrix.rx.RxRoom
import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.core.platform.VectorViewModel
import im.vector.riotredesign.core.utils.isSingleEmoji
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
import io.reactivex.Observable
import io.reactivex.Single
@ -69,7 +70,9 @@ class ViewReactionViewModel @AssistedInject constructor(@Assisted
.flatMapSingle { summaries ->
Observable
.fromIterable(summaries)
.flatMapIterable {it.reactionsSummary}
.flatMapIterable { it.reactionsSummary
.filter { reactionAggregatedSummary -> isSingleEmoji(reactionAggregatedSummary.key) }
}
.toReactionInfoList()
}
.execute {

View File

@ -20,6 +20,7 @@ import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotredesign.core.extensions.localDateTime
import im.vector.riotredesign.core.resources.ColorProvider
import im.vector.riotredesign.core.utils.isSingleEmoji
import im.vector.riotredesign.features.home.getColorFromUserId
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineDateFormatter
import im.vector.riotredesign.features.home.room.detail.timeline.item.MessageInformationData
@ -68,9 +69,11 @@ class MessageInformationDataFactory @Inject constructor(private val timelineDate
avatarUrl = avatarUrl,
memberName = formattedMemberName,
showInformation = showInformation,
orderedReactionList = event.annotations?.reactionsSummary?.map {
ReactionInfoData(it.key, it.count, it.addedByMe, it.localEchoEvents.isEmpty())
},
orderedReactionList = event.annotations?.reactionsSummary
?.filter { isSingleEmoji(it.key) }
?.map {
ReactionInfoData(it.key, it.count, it.addedByMe, it.localEchoEvents.isEmpty())
},
hasBeenEdited = hasBeenEdited
)
}