Commit d8543723 authored by Leonardo Aramaki's avatar Leonardo Aramaki

Fix some errors during saving and retrieval of data from Room. This fixes tone selection

parent 30b52d33
......@@ -33,7 +33,6 @@ import chat.rocket.common.RocketChatException
import chat.rocket.common.model.UserStatus
import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.realtime.setDefaultStatus
import chat.rocket.core.internal.rest.getCustomEmojis
import chat.rocket.core.internal.rest.logout
import chat.rocket.core.internal.rest.me
......@@ -41,7 +40,6 @@ import chat.rocket.core.internal.rest.unregisterPushToken
import chat.rocket.core.model.Myself
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.withContext
import timber.log.Timber
import javax.inject.Inject
......@@ -142,7 +140,7 @@ class MainPresenter @Inject constructor(
shortnameAlternates = customEmoji.aliases,
siblings = mutableListOf(),
unicode = "",
default = true
isDefault = true
))
}
......
......@@ -13,8 +13,8 @@ data class Emoji(
@Ignore val keywords: List<String> = listOf(),
var category: String = "",
var count: Int = 0,
var siblings: List<String> = listOf(),
var siblings: MutableList<String> = mutableListOf(), // Siblings are the same emoji with different skin tones.
var fitzpatrick: String = Fitzpatrick.Default.type,
var url: String? = null, // Filled for custom emojis
var default: Boolean = true
var isDefault: Boolean = true // Tell if this is the default emoji if it has siblings (usually a yellow-toned one).
)
......@@ -2,6 +2,7 @@ package chat.rocket.android.emoji
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Typeface
import android.text.Spannable
import android.text.SpannableString
import android.text.Spanned
......@@ -33,7 +34,13 @@ class EmojiParser {
val spannable = factory?.newSpannable(unicodedText)
?: SpannableString.valueOf(unicodedText)
val typeface = EmojiRepository.cachedTypeface
val typeface = try {
EmojiRepository.cachedTypeface
} catch (ex: UninitializedPropertyAccessException) {
// swallow this exception and create typeface now
Typeface.createFromAsset(context.assets, "fonts/emojione-android.ttf")
}
// Look for groups of emojis, set a EmojiTypefaceSpan with the emojione font.
val length = spannable.length
var inEmoji = false
......@@ -47,6 +54,7 @@ class EmojiParser {
offset += count
continue
}
if (codepoint >= 0x200) {
if (!inEmoji) {
emojiStart = offset
......@@ -59,6 +67,7 @@ class EmojiParser {
}
inEmoji = false
}
offset += count
if (offset >= length && inEmoji) {
spannable.setSpan(EmojiTypefaceSpan("sans-serif", typeface),
......
......@@ -6,6 +6,7 @@ import android.graphics.Typeface
import chat.rocket.android.emoji.internal.EmojiCategory
import chat.rocket.android.emoji.internal.PREF_EMOJI_RECENTS
import chat.rocket.android.emoji.internal.db.EmojiDatabase
import chat.rocket.android.emoji.internal.isCustom
import com.bumptech.glide.Glide
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.launch
......@@ -47,10 +48,9 @@ object EmojiRepository {
for (emoji in emojis) {
val unicodeIntList = mutableListOf<Int>()
emoji.category = emoji.category.toUpperCase()
emoji.category = emoji.category
// If unicode is empty it's a custom emoji, just add it.
if (emoji.unicode.isEmpty()) {
if (emoji.isCustom()) {
allEmojis.add(emoji)
continue
}
......@@ -68,27 +68,27 @@ object EmojiRepository {
val unicodeIntArray = unicodeIntList.toIntArray()
val unicode = String(unicodeIntArray, 0, unicodeIntArray.size)
val emojiWithUnicode = emoji.copy(unicode = unicode)
emoji.unicode = unicode
if (hasFitzpatrick(emoji.shortname)) {
val matchResult = FITZPATRICK_REGEX.find(emoji.shortname)
val prefix = matchResult!!.groupValues[1] + ":"
val fitzpatrick = Fitzpatrick.valueOf(matchResult.groupValues[2])
val defaultEmoji = allEmojis.firstOrNull { it.shortname == prefix }
val emojiWithFitzpatrick = emojiWithUnicode.copy(fitzpatrick = fitzpatrick.type)
emoji.fitzpatrick = fitzpatrick.type
if (defaultEmoji != null) {
emojiWithFitzpatrick.default = false
defaultEmoji.siblings.toMutableList().add(emoji.shortname)
emoji.isDefault = if (defaultEmoji != null) {
defaultEmoji.siblings.add(emoji.shortname)
false
} else {
// This emoji doesn't have a default tone, ie. :man_in_business_suit_levitating_tone1:
// In this case, the default emoji becomes the first toned one.
allEmojis.add(emojiWithFitzpatrick)
true
}
} else {
allEmojis.add(emojiWithUnicode)
emoji.isDefault = false
}
allEmojis.add(emoji)
shortNameToUnicode.apply {
put(emoji.shortname, unicode)
emoji.shortnameAlternates.forEach { alternate -> put(alternate, unicode) }
......@@ -97,6 +97,7 @@ object EmojiRepository {
saveEmojisToDatabase(allEmojis.toList())
// Prefetch all custom emojis to make cache.
val density = context.resources.displayMetrics.density
val px = (32 * density).toInt()
......@@ -130,7 +131,7 @@ object EmojiRepository {
internal suspend fun getEmojiSequenceByCategory(category: EmojiCategory): Sequence<Emoji> {
val list = withContext(CommonPool) {
db.emojiDao().loadEmojisByCategory(category.name.toLowerCase())
db.emojiDao().loadEmojisByCategory(category.name)
}
return buildSequence {
......
......@@ -70,4 +70,4 @@ enum class EmojiCategory {
setSpan(span, 0, text.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
}
}
}
\ No newline at end of file
}
......@@ -14,10 +14,7 @@ import chat.rocket.android.emoji.EmojiParser
import chat.rocket.android.emoji.EmojiRepository
import chat.rocket.android.emoji.Fitzpatrick
import chat.rocket.android.emoji.R
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.cache.ExternalPreferredCacheDiskCacheFactory
import com.bumptech.glide.request.RequestOptions
import kotlinx.android.synthetic.main.emoji_category_layout.view.*
import kotlinx.android.synthetic.main.emoji_image_row_item.view.*
import kotlinx.android.synthetic.main.emoji_row_item.view.*
......@@ -97,26 +94,24 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
private val listener: EmojiKeyboardListener
) : RecyclerView.Adapter<EmojiRowViewHolder>() {
private val TYPE_CUSTOM = 1
private val TYPE_NORMAL = 2
private val CUSTOM = 1
private val NORMAL = 2
private val allEmojis = mutableListOf<Emoji>()
private val emojis = mutableListOf<Emoji>()
fun addEmojis(emojis: List<Emoji>) {
this.emojis.clear()
this.emojis.addAll(emojis)
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
return if (emojis[position].url != null) TYPE_CUSTOM else TYPE_NORMAL
return if (emojis[position].isCustom()) CUSTOM else NORMAL
}
suspend fun addEmojisFromSequence(emojiSequence: Sequence<Emoji>) {
withContext(CommonPool) {
emojiSequence.forEachIndexed { index, emoji ->
withContext(UI) {
emojis.add(emoji)
notifyItemInserted(index)
allEmojis.add(emoji)
if (emoji.isDefault) {
emojis.add(emoji)
notifyItemInserted(emojis.size - 1)
}
}
}
}
......@@ -130,18 +125,22 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
override fun onBindViewHolder(holder: EmojiRowViewHolder, position: Int) {
val emoji = emojis[position]
holder.bind(
emoji.siblings.find {
it.endsWith(fitzpatrick.type)
}?.let { shortname ->
emojis.firstOrNull {
it.shortname == shortname
}
} ?: emoji
if (fitzpatrick != Fitzpatrick.Default) {
emoji.siblings.find {
it.endsWith("${fitzpatrick.type}:")
}?.let { shortname ->
allEmojis.firstOrNull {
it.shortname == shortname
}
} ?: emoji
} else {
emoji
}
)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EmojiRowViewHolder {
val view = if (viewType == TYPE_CUSTOM) {
val view = if (viewType == CUSTOM) {
LayoutInflater.from(parent.context).inflate(R.layout.emoji_image_row_item, parent, false)
} else {
LayoutInflater.from(parent.context).inflate(R.layout.emoji_row_item, parent, false)
......@@ -160,6 +159,7 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
fun bind(emoji: Emoji) {
with(itemView) {
if (emoji.unicode.isNotEmpty()) {
// Handle simple emoji.
val parsedUnicode = unicodeCache[emoji.unicode]
emoji_view.setSpannableFactory(spannableFactory)
emoji_view.text = if (parsedUnicode == null) {
......@@ -171,6 +171,7 @@ internal class EmojiPagerAdapter(private val listener: EmojiKeyboardListener) :
parsedUnicode
}
} else {
// Handle custom emoji.
GlideApp.with(context)
.load(emoji.url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
......
package chat.rocket.android.emoji.internal
import chat.rocket.android.emoji.Emoji
fun Emoji.isCustom(): Boolean = this.url != null
......@@ -2,17 +2,15 @@ package chat.rocket.android.emoji.internal.db
import androidx.room.TypeConverter
internal object StringListConverter {
class StringListConverter {
@TypeConverter
@JvmStatic
fun toString(list: List<String>?): String? {
return if (list == null) null else list.joinToString(separator = ",")
fun fromStringList(list: List<String>?): String {
return list?.joinToString(separator = ",") ?: ""
}
@TypeConverter
@JvmStatic
fun toStringList(value: String?): List<String>? {
return value?.split(",")
fun fromString(value: String?): List<String> {
return value?.split(",") ?: emptyList()
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment