Commit f3224435 authored by Leonardo Aramaki's avatar Leonardo Aramaki

Showing unlimeted completion suggestions for commands and properly displaying its descriptions

parent f14e01f3
......@@ -11,7 +11,7 @@ import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
class CommandSuggestionsAdapter : SuggestionsAdapter<CommandSuggestionsViewHolder>("/") {
class CommandSuggestionsAdapter : SuggestionsAdapter<CommandSuggestionsViewHolder>("/", UNLIMITED_RESULT_COUNT) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommandSuggestionsViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.suggestion_command_item, parent,
......@@ -27,7 +27,7 @@ class CommandSuggestionsAdapter : SuggestionsAdapter<CommandSuggestionsViewHolde
val nameTextView = itemView.findViewById<TextView>(R.id.text_command_name)
val descriptionTextView = itemView.findViewById<TextView>(R.id.text_command_description)
nameTextView.text = item.text
descriptionTextView.text = item.description
descriptionTextView.text = item.description.replace("_", " ")
setOnClickListener {
itemClickListener?.onClick(item)
}
......
......@@ -495,9 +495,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
private fun setupSuggestionsView() {
suggestions_view.anchor(text_message)
.bindTokenAdapter(PeopleSuggestionsAdapter())
.bindTokenAdapter(CommandSuggestionsAdapter())
.bindTokenAdapter(RoomSuggestionsAdapter())
.registerTokenAdapter(PeopleSuggestionsAdapter())
.registerTokenAdapter(CommandSuggestionsAdapter())
.registerTokenAdapter(RoomSuggestionsAdapter())
.addSuggestionProviderAction("@") { query ->
if (query.isNotEmpty()) {
presenter.spotlight(query, PEOPLE, true)
......
......@@ -2,24 +2,25 @@ package chat.rocket.android.widget.autocompletion.strategy.regex
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import java.util.concurrent.CopyOnWriteArrayList
internal class StringMatchingCompletionStrategy : CompletionStrategy {
internal class StringMatchingCompletionStrategy(private val threshold: Int = -1) : CompletionStrategy {
private val list = CopyOnWriteArrayList<SuggestionModel>()
override fun autocompleteItems(prefix: String): List<SuggestionModel> {
return list.filter {
val result = list.filter {
it.searchList.forEach { word ->
if (word.contains(prefix, ignoreCase = true)) {
return@filter true
}
}
false
}.sortedByDescending { it.pinned }.take(5)
}.sortedByDescending { it.pinned }
return if (threshold == SuggestionsAdapter.UNLIMITED_RESULT_COUNT) result else result.take(threshold)
}
override fun addAll(list: List<SuggestionModel>) {
// this.list.removeAll { !it.pinned }
this.list.addAllAbsent(list)
}
......
......@@ -7,14 +7,23 @@ import chat.rocket.android.widget.autocompletion.strategy.regex.StringMatchingCo
import java.lang.reflect.Type
import kotlin.properties.Delegates
abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(val token: String) : RecyclerView.Adapter<VH>() {
private val strategy: CompletionStrategy = StringMatchingCompletionStrategy()
abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(val token: String, threshold: Int = MAX_RESULT_COUNT) : RecyclerView.Adapter<VH>() {
companion object {
const val UNLIMITED_RESULT_COUNT = -1
private const val MAX_RESULT_COUNT = 5
}
private var itemType: Type? = null
private var itemClickListener: ItemClickListener? = null
// Called to gather results when no results have previously matched.
private var providerExternal: ((query: String) -> Unit)? = null
private var prefix: String by Delegates.observable("", { _, _, _ ->
strategy.autocompleteItems(prefix)
notifyItemRangeChanged(0, 5)
// Maximum number of results/suggestions to display.
private var resultsThreshold: Int = if (threshold > 0) threshold else UNLIMITED_RESULT_COUNT
// The strategy used for suggesting completions.
private val strategy: CompletionStrategy = StringMatchingCompletionStrategy(resultsThreshold)
// Current input term to look up for suggestions.
private var currentTerm: String by Delegates.observable("", { _, _, newTerm ->
val items = strategy.autocompleteItems(newTerm)
notifyDataSetChanged()
})
init {
......@@ -29,21 +38,21 @@ abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(val token: Stri
holder.bind(getItem(position), itemClickListener)
}
override fun getItemCount() = strategy.autocompleteItems(prefix).size
override fun getItemCount() = strategy.autocompleteItems(currentTerm).size
private fun getItem(position: Int): SuggestionModel {
return strategy.autocompleteItems(prefix)[position]
return strategy.autocompleteItems(currentTerm)[position]
}
fun autocomplete(prefix: String) {
this.prefix = prefix.toLowerCase().trim()
fun autocomplete(newTerm: String) {
this.currentTerm = newTerm.toLowerCase().trim()
}
fun addItems(list: List<SuggestionModel>) {
strategy.addAll(list)
// Since we've just added new items we should check for possible new completion suggestions.
strategy.autocompleteItems(prefix)
notifyItemRangeChanged(0, 5)
strategy.autocompleteItems(currentTerm)
notifyDataSetChanged()
}
fun setOnClickListener(clickListener: ItemClickListener) {
......@@ -52,11 +61,24 @@ abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(val token: Stri
fun hasItemClickListener() = itemClickListener != null
fun prefix() = prefix
/**
* Return the current searched term.
*/
fun term() = this.currentTerm
/**
* Set the maximum number of results to show.
*
* @param threshold The maximum number of suggestions to display.
*/
fun setResultsThreshold(threshold: Int) {
check(threshold > 0)
resultsThreshold = threshold
}
fun cancel() {
strategy.addAll(emptyList())
strategy.autocompleteItems(prefix)
strategy.autocompleteItems(currentTerm)
notifyDataSetChanged()
}
......
......@@ -132,7 +132,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
return this
}
fun bindTokenAdapter(adapter: SuggestionsAdapter<*>): SuggestionsView {
fun registerTokenAdapter(adapter: SuggestionsAdapter<*>): SuggestionsView {
adaptersByToken.getOrPut(adapter.token, { adapter })
return this
}
......@@ -141,7 +141,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
if (list.isNotEmpty()) {
val adapter = adapter(token)
localProvidersByToken.getOrPut(token, { hashMapOf() })
.put(adapter.prefix(), list)
.put(adapter.term(), list)
if (completionStartIndex.get() > NO_STATE_INDEX && adapter.itemCount == 0) expand()
adapter.addItems(list)
}
......
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