Implement emoji autocompleting

This commit is contained in:
Phillip Thelen 2019-02-28 16:43:36 +01:00
parent 48b04962c7
commit d0da491922
5 changed files with 69 additions and 23 deletions

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/spacing_medium"
android:paddingBottom="@dimen/spacing_medium"
android:paddingStart="@dimen/spacing_large"
android:paddingEnd="@dimen/spacing_large">
<net.pherth.android.emoji_library.EmojiTextView
android:id="@+id/emoji_textview"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginEnd="@dimen/spacing_large"
android:layout_gravity="center_vertical"/>
<TextView
android:id="@+id/label"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</LinearLayout>

View file

@ -101,7 +101,7 @@
android:layout_marginBottom="8dp"
android:lineSpacingMultiplier="1.0"
tools:text="This is the chat message"
android:textColor="@color/gray_10"/>
android:textColor="@color/gray_10" />
<com.nex3z.flowlayout.FlowLayout
android:id="@+id/buttons_wrapper"
android:layout_width="match_parent"

View file

@ -19,6 +19,6 @@ class FindUsernameResult {
get() = if (username != null) "@$username" else null
override fun toString(): String {
return authentication?.localAuthentication?.username ?: ""
return "@${authentication?.localAuthentication?.username ?: ""}"
}
}

View file

@ -9,21 +9,35 @@ import android.widget.Filterable
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.extensions.dpToPx
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.social.FindUsernameResult
import com.habitrpg.android.habitica.ui.views.social.UsernameLabel
import net.pherth.android.emoji_library.EmojiMap
import net.pherth.android.emoji_library.EmojiParser
import net.pherth.android.emoji_library.EmojiTextView
class AutocompleteAdapter(val context: Context, val socialRepository: SocialRepository, var autocompleteContext: String, var groupID: String?) : BaseAdapter(), Filterable {
private var results: List<FindUsernameResult> = arrayListOf()
private var userResults: List<FindUsernameResult> = arrayListOf()
private var emojiResults: List<String> = arrayListOf()
private var isAutocompletingUsers = true
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val filterResults = FilterResults()
if (constraint != null && constraint.isNotEmpty()) {
results = socialRepository.findUsernames(constraint.toString(), autocompleteContext, groupID).blockingFirst(arrayListOf())
filterResults.values = results
filterResults.count = results.size
if (constraint[0] == '@') {
isAutocompletingUsers = true
userResults = socialRepository.findUsernames(constraint.toString().drop(1), autocompleteContext, groupID).blockingFirst(arrayListOf())
filterResults.values = userResults
filterResults.count = userResults.size
} else {
isAutocompletingUsers = false
emojiResults = EmojiMap.invertedEmojiMap.keys.filter { it.startsWith(constraint) }
filterResults.values = emojiResults
filterResults.count = emojiResults.size
}
}
return filterResults
}
@ -39,25 +53,35 @@ class AutocompleteAdapter(val context: Context, val socialRepository: SocialRepo
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view = parent?.inflate(R.layout.autocomplete_username)
val result = getItem(position)
val displaynameView = view?.findViewById<UsernameLabel>(R.id.display_name_view)
displaynameView?.username = result.username
displaynameView?.tier = result.contributor?.level ?: 0
view?.findViewById<TextView>(R.id.username_view)?.text = result.formattedUsername
return view ?: View(context)
return if (isAutocompletingUsers) {
val view = parent?.inflate(R.layout.autocomplete_username)
val result = getItem(position) as? FindUsernameResult
val displaynameView = view?.findViewById<UsernameLabel>(R.id.display_name_view)
displaynameView?.username = result?.username
displaynameView?.tier = result?.contributor?.level ?: 0
view?.findViewById<TextView>(R.id.username_view)?.text = result?.formattedUsername
view
} else {
val view = parent?.inflate(R.layout.autocomplete_emoji)
val result = getItem(position) as? String
val emojiTextView = view?.findViewById<EmojiTextView>(R.id.emoji_textview)
emojiTextView?.setEmojiconSize(24.dpToPx(context))
emojiTextView?.text = EmojiParser.parseEmojis(result)
view?.findViewById<TextView>(R.id.label)?.text = result
view
} ?: View(context)
}
override fun getItem(position: Int): FindUsernameResult {
return results[position]
override fun getItem(position: Int): Any {
return if (isAutocompletingUsers) userResults[position] else emojiResults[position]
}
override fun getItemId(position: Int): Long {
return getItem(position).id.hashCode().toLong()
return getItem(position).hashCode().toLong()
}
override fun getCount(): Int {
return results.size
return if (isAutocompletingUsers) userResults.size else emojiResults.size
}

View file

@ -11,15 +11,16 @@ class ChatInputTokenizer : MultiAutoCompleteTextView.Tokenizer {
override fun findTokenStart(text: CharSequence, cursor: Int): Int {
var i = cursor
while (i > 0 && text[i - 1] != '@') {
while (i > 0 && text[i - 1] != '@' && text[i - 1] != ':') {
i--
}
//Check if token really started with @, else we don't have a valid token
return if (i < 1 || text[i - 1] != '@') {
return if (i < 1 || (text[i - 1] != '@' && text[i - 1] != ':')) {
cursor
} else i
} else {
i - 1
}
}
override fun findTokenEnd(text: CharSequence, cursor: Int): Int {
@ -48,12 +49,12 @@ class ChatInputTokenizer : MultiAutoCompleteTextView.Tokenizer {
text
} else {
if (text is Spanned) {
val sp = SpannableString(text.toString() + " ")
val sp = SpannableString("$text ")
TextUtils.copySpansFrom(text, 0, text.length,
Any::class.java, sp, 0)
sp
} else {
text.toString() + " "
"$text "
}
}
}