Unverified Commit 91763a21 authored by Filipe de Lima Brito's avatar Filipe de Lima Brito Committed by GitHub

Merge branch 'develop' into fix-random-crash-emoji-keyboard

parents a74e410c d4ced11a
......@@ -93,6 +93,7 @@ dependencies {
implementation project(':draw')
implementation project(':util')
implementation project(':core')
implementation project(':suggestions')
implementation libraries.kotlin
implementation libraries.coroutines
......
......@@ -65,7 +65,9 @@ abstract class BaseViewHolder<T : BaseUiModel<*>>(
val manager = FlexboxLayoutManager(context, FlexDirection.ROW)
recyclerView.layoutManager = manager
recyclerView.adapter = adapter
adapter.addReactions(it.reactions.filterNot { it.unicode.startsWith(":") })
adapter.addReactions(it.reactions.filterNot { reactionUiModel ->
reactionUiModel.unicode.startsWith(":") && reactionUiModel.url.isNullOrEmpty()
})
}
}
}
......
......@@ -7,9 +7,9 @@ import android.widget.TextView
import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.CommandSuggestionsAdapter.CommandSuggestionsViewHolder
import chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.android.suggestions.ui.BaseSuggestionViewHolder
import chat.rocket.android.suggestions.ui.SuggestionsAdapter
class CommandSuggestionsAdapter : SuggestionsAdapter<CommandSuggestionsViewHolder>(token = "/",
constraint = CONSTRAINT_BOUND_TO_START, threshold = RESULT_COUNT_UNLIMITED) {
......
......@@ -5,6 +5,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.chatroom.uimodel.ReactionUiModel
......@@ -13,15 +14,13 @@ import chat.rocket.android.emoji.Emoji
import chat.rocket.android.emoji.EmojiKeyboardListener
import chat.rocket.android.emoji.EmojiPickerPopup
import chat.rocket.android.emoji.EmojiReactionListener
import chat.rocket.android.emoji.internal.GlideApp
import chat.rocket.android.infrastructure.LocalRepository
import kotlinx.android.synthetic.main.item_reaction.view.*
import java.util.concurrent.CopyOnWriteArrayList
import javax.inject.Inject
class MessageReactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
private const val REACTION_VIEW_TYPE = 0
private const val ADD_REACTION_VIEW_TYPE = 1
}
private val reactions = CopyOnWriteArrayList<ReactionUiModel>()
var listener: EmojiReactionListener? = null
......@@ -74,9 +73,11 @@ class MessageReactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>()
fun contains(reactionShortname: String) =
reactions.firstOrNull { it.shortname == reactionShortname } != null
class SingleReactionViewHolder(view: View,
private val listener: EmojiReactionListener?)
: RecyclerView.ViewHolder(view), View.OnClickListener {
class SingleReactionViewHolder(
view: View,
private val listener: EmojiReactionListener?
) : RecyclerView.ViewHolder(view), View.OnClickListener {
@Inject
lateinit var localRepository: LocalRepository
@Volatile
......@@ -95,23 +96,33 @@ class MessageReactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>()
clickHandled = false
this.reaction = reaction
with(itemView) {
val emojiTextView = findViewById<TextView>(R.id.text_emoji)
val countTextView = findViewById<TextView>(R.id.text_count)
emojiTextView.text = reaction.unicode
countTextView.text = reaction.count.toString()
if (reaction.url.isNullOrEmpty()) {
text_emoji.text = reaction.unicode
view_flipper_reaction.displayedChild = 0
} else {
view_flipper_reaction.displayedChild = 1
val glideRequest = if (reaction.url!!.endsWith("gif", true)) {
GlideApp.with(context).asGif()
} else {
GlideApp.with(context).asBitmap()
}
glideRequest.load(reaction.url).into(image_emoji)
}
text_count.text = reaction.count.toString()
val myself = localRepository.get(LocalRepository.CURRENT_USERNAME_KEY)
if (reaction.usernames.contains(myself)) {
val context = itemView.context
val resources = context.resources
countTextView.setTextColor(resources.getColor(R.color.colorAccent))
text_count.setTextColor(ContextCompat.getColor(context, R.color.colorAccent))
}
emojiTextView.setOnClickListener(this@SingleReactionViewHolder)
countTextView.setOnClickListener(this@SingleReactionViewHolder)
view_flipper_reaction.setOnClickListener(this@SingleReactionViewHolder)
text_count.setOnClickListener(this@SingleReactionViewHolder)
}
}
override fun onClick(v: View?) {
override fun onClick(v: View) {
synchronized(this) {
if (!clickHandled) {
clickHandled = true
......@@ -121,8 +132,11 @@ class MessageReactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>()
}
}
class AddReactionViewHolder(view: View,
private val listener: EmojiReactionListener?) : RecyclerView.ViewHolder(view) {
class AddReactionViewHolder(
view: View,
private val listener: EmojiReactionListener?
) : RecyclerView.ViewHolder(view) {
fun bind(messageId: String) {
itemView as ImageView
itemView.setOnClickListener {
......@@ -136,4 +150,9 @@ class MessageReactionsAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>()
}
}
}
}
\ No newline at end of file
companion object {
private const val REACTION_VIEW_TYPE = 0
private const val ADD_REACTION_VIEW_TYPE = 1
}
}
......@@ -11,9 +11,9 @@ import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.PeopleSuggestionsAdapter.PeopleSuggestionViewHolder
import chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.android.suggestions.ui.BaseSuggestionViewHolder
import chat.rocket.android.suggestions.ui.SuggestionsAdapter
import com.facebook.drawee.view.SimpleDraweeView
class PeopleSuggestionsAdapter(context: Context) : SuggestionsAdapter<PeopleSuggestionViewHolder>("@") {
......
......@@ -7,9 +7,9 @@ import android.widget.TextView
import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.RoomSuggestionsAdapter.RoomSuggestionsViewHolder
import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.android.suggestions.ui.BaseSuggestionViewHolder
import chat.rocket.android.suggestions.ui.SuggestionsAdapter
class RoomSuggestionsAdapter : SuggestionsAdapter<RoomSuggestionsViewHolder>("#") {
......
......@@ -5,5 +5,6 @@ data class ReactionUiModel(
val shortname: String,
val unicode: CharSequence,
val count: Int,
val usernames: List<String> = emptyList()
val usernames: List<String> = emptyList(),
var url: String? = null
)
\ No newline at end of file
......@@ -18,6 +18,7 @@ import chat.rocket.android.chatroom.domain.MessageReply
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.emoji.EmojiParser
import chat.rocket.android.emoji.EmojiRepository
import chat.rocket.android.helper.MessageHelper
import chat.rocket.android.helper.MessageParser
import chat.rocket.android.helper.UserHelper
......@@ -504,15 +505,18 @@ class UiModelMapper @Inject constructor(
private fun getReactions(message: Message): List<ReactionUiModel> {
val reactions = message.reactions?.let {
val list = mutableListOf<ReactionUiModel>()
val customEmojis = EmojiRepository.getCustomEmojis()
it.getShortNames().forEach { shortname ->
val usernames = it.getUsernames(shortname) ?: emptyList()
val count = usernames.size
val custom = customEmojis.firstOrNull { emoji -> emoji.shortname == shortname }
list.add(
ReactionUiModel(messageId = message.id,
shortname = shortname,
unicode = EmojiParser.parse(context, shortname),
count = count,
usernames = usernames)
usernames = usernames,
url = custom?.url)
)
}
list
......
package chat.rocket.android.chatroom.uimodel.suggestion
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.suggestions.model.SuggestionModel
class ChatRoomSuggestionUiModel(text: String,
val fullName: String,
......
package chat.rocket.android.chatroom.uimodel.suggestion
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.suggestions.model.SuggestionModel
class CommandSuggestionUiModel(text: String,
val description: String,
......
package chat.rocket.android.chatroom.uimodel.suggestion
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.common.model.UserStatus
class PeopleSuggestionUiModel(val imageUri: String?,
......
......@@ -5,5 +5,5 @@
android:width="24dp"
android:height="24dp" />
<solid android:color="#efeeee" />
<corners android:radius="4dp"/>
</shape>
\ No newline at end of file
<corners android:radius="4dp" />
</shape>
......@@ -74,7 +74,7 @@
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<chat.rocket.android.widget.autocompletion.ui.SuggestionsView
<chat.rocket.android.suggestions.ui.SuggestionsView
android:id="@+id/suggestions_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="2dp"
android:layout_marginRight="2dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:descendantFocusability="beforeDescendants"
android:background="@drawable/rounded_background"
android:orientation="horizontal">
android:background="@drawable/rounded_background">
<TextView
android:id="@+id/text_emoji"
<ViewFlipper
android:id="@+id/view_flipper_reaction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingLeft="4dp"
android:paddingStart="4dp"
android:textColor="#868585"
android:textSize="16sp"
tools:text=":)" />
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/text_count"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/text_emoji"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:textColor="#868585"
android:textSize="16sp"
tools:text=":)" />
<ImageView
android:id="@+id/image_emoji"
android:layout_width="@dimen/custom_emoji_small"
android:layout_height="@dimen/custom_emoji_small"
android:layout_gravity="center"
tools:src="@tools:sample/avatars" />
</ViewFlipper>
<TextView
android:id="@+id/text_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="4dp"
android:paddingEnd="4dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingTop="4dp"
android:paddingEnd="4dp"
android:paddingRight="4dp"
android:paddingBottom="4dp"
android:textColor="#868585"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/view_flipper_reaction"
app:layout_constraintTop_toTopOf="parent"
tools:text="12" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
......@@ -41,10 +41,6 @@
<dimen name="padding_mention">4dp</dimen>
<dimen name="radius_mention">6dp</dimen>
<!-- Autocomplete Popup -->
<dimen name="popup_max_height">150dp</dimen>
<dimen name="suggestions_box_max_height">250dp</dimen>
<dimen name="viewer_toolbar_padding">16dp</dimen>
<dimen name="viewer_toolbar_title">16sp</dimen>
......
......@@ -10,7 +10,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0-rc02'
classpath 'com.android.tools.build:gradle:3.2.0-rc03'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath 'com.google.gms:google-services:4.0.2'
......
......@@ -210,7 +210,7 @@ object EmojiRepository {
}
}
internal fun getCustomEmojis(): List<Emoji> = customEmojis
fun getCustomEmojis(): List<Emoji> = customEmojis
/**
* Get all recently used emojis ordered by usage count.
......
include ':app', ':player', ':emoji', ':draw', ':util', ':core' //, ':wear'
\ No newline at end of file
include ':app', ':player', ':emoji', ':draw', ':util', ':core', ':suggestions' //, ':wear'
\ No newline at end of file
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion versions.compileSdk
buildToolsVersion versions.buildTools
defaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation libraries.kotlin
implementation libraries.recyclerview
implementation libraries.appCompat
implementation libraries.material
}
androidExtensions {
experimental = true
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package yampsample.leonardoaramaki.github.com.suggestions;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("yampsample.leonardoaramaki.github.com.suggestions.test", appContext.getPackageName());
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="chat.rocket.android.suggestions" />
package chat.rocket.android.widget.autocompletion.model
package chat.rocket.android.suggestions.model
abstract class SuggestionModel(val text: String, // This is the text key for searches, must be unique.
val searchList: List<String> = emptyList(), // Where to search for matches.
......@@ -15,4 +15,4 @@ abstract class SuggestionModel(val text: String, // This is the text key for sea
override fun hashCode(): Int {
return text.hashCode()
}
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.repository
package chat.rocket.android.suggestions.repository
interface LocalSuggestionProvider {
fun find(prefix: String)
......
package chat.rocket.android.widget.autocompletion.strategy
package chat.rocket.android.suggestions.strategy
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.suggestions.model.SuggestionModel
interface CompletionStrategy {
fun getItem(prefix: String, position: Int): SuggestionModel
......@@ -8,4 +8,4 @@ interface CompletionStrategy {
fun addAll(list: List<SuggestionModel>)
fun addPinned(list: List<SuggestionModel>)
fun size(): Int
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.strategy.regex
package chat.rocket.android.suggestions.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.Companion.RESULT_COUNT_UNLIMITED
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.android.suggestions.strategy.CompletionStrategy
import chat.rocket.android.suggestions.ui.SuggestionsAdapter.Companion.RESULT_COUNT_UNLIMITED
import java.util.concurrent.CopyOnWriteArrayList
internal class StringMatchingCompletionStrategy(private val threshold: Int = RESULT_COUNT_UNLIMITED) : CompletionStrategy {
......@@ -46,4 +46,4 @@ internal class StringMatchingCompletionStrategy(private val threshold: Int = RES
override fun size(): Int {
return list.size
}
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.strategy.trie
package chat.rocket.android.suggestions.strategy.trie
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import chat.rocket.android.widget.autocompletion.strategy.trie.data.Trie
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.android.suggestions.strategy.CompletionStrategy
import chat.rocket.android.suggestions.strategy.trie.data.Trie
class TrieCompletionStrategy : CompletionStrategy {
private val items = mutableListOf<SuggestionModel>()
......@@ -28,8 +28,7 @@ class TrieCompletionStrategy : CompletionStrategy {
}
override fun addPinned(list: List<SuggestionModel>) {
}
override fun size() = items.size
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.strategy.trie.data
package chat.rocket.android.suggestions.strategy.trie.data
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.suggestions.model.SuggestionModel
internal class Trie {
private val root = TrieNode(' ')
......@@ -67,4 +67,4 @@ internal class Trie {
}
fun getCount() = count
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.strategy.trie.data
package chat.rocket.android.suggestions.strategy.trie.data
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.suggestions.model.SuggestionModel
internal class TrieNode(internal var data: Char,
internal var parent: TrieNode? = null,
......@@ -44,4 +44,4 @@ internal class TrieNode(internal var data: Char,
}
override fun toString(): String = if (parent == null) "" else "${parent.toString()}$data"
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.ui
package chat.rocket.android.suggestions.ui
import androidx.recyclerview.widget.RecyclerView
import android.view.View
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.suggestions.model.SuggestionModel
abstract class BaseSuggestionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
abstract fun bind(item: SuggestionModel, itemClickListener: SuggestionsAdapter.ItemClickListener?)
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.ui
package chat.rocket.android.suggestions.ui
import android.content.Context
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.suggestions.R
internal class PopupRecyclerView : RecyclerView {
private var displayWidth: Int = 0
......@@ -38,4 +38,4 @@ internal class PopupRecyclerView : RecyclerView {
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l + 40, t, r - 40, b)
}
}
\ No newline at end of file
}
package chat.rocket.android.widget.autocompletion.ui
package chat.rocket.android.suggestions.ui
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import chat.rocket.android.widget.autocompletion.strategy.regex.StringMatchingCompletionStrategy
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.android.suggestions.strategy.CompletionStrategy
import chat.rocket.android.suggestions.strategy.regex.StringMatchingCompletionStrategy
import java.lang.reflect.Type
import kotlin.properties.Delegates
......@@ -32,10 +32,10 @@ abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(
// 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 ->
private var currentTerm: String by Delegates.observable("") { _, _, newTerm ->
val items = strategy.autocompleteItems(newTerm)
notifyDataSetChanged()
})
}
init {
setHasStableIds(true)
......
package chat.rocket.android.widget.autocompletion.ui
package chat.rocket.android.suggestions.ui
import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import androidx.annotation.DrawableRes
import androidx.transition.Slide
import androidx.transition.TransitionManager
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.text.Editable
import android.text.InputType
import android.text.TextWatcher
import android.transition.Slide
import android.transition.TransitionManager
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.widget.EditText
import android.widget.FrameLayout
import chat.rocket.android.R
import chat.rocket.android.widget.autocompletion.model.SuggestionModel
import chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter.Companion.CONSTRAINT_BOUND_TO_START
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.suggestions.R
import chat.rocket.android.suggestions.model.SuggestionModel
import chat.rocket.android.suggestions.ui.SuggestionsAdapter.Companion.CONSTRAINT_BOUND_TO_START
import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicInteger
......@@ -103,7 +103,8 @@ class SuggestionsView : FrameLayout, TextWatcher {
val prefixEndIndex = this.editor?.get()?.selectionStart ?: NO_STATE_INDEX
if (prefixEndIndex == NO_STATE_INDEX || prefixEndIndex < completionOffset.get()) return
val prefix = s.subSequence(completionOffset.get(), this.editor?.get()?.selectionStart ?: completionOffset.get()).toString()
val prefix = s.subSequence(completionOffset.get(), this.editor?.get()?.selectionStart
?: completionOffset.get()).toString()
recyclerView.adapter?.let {
it as SuggestionsAdapter
// we need to look up only after the '@'
......@@ -156,7 +157,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
if (list.isNotEmpty()) {
val adapter = adapter(token)
localProvidersByToken.getOrPut(token, { hashMapOf() })
.put(adapter.term(), list)
.put(adapter.term(), list)
if (completionOffset.get() > NO_STATE_INDEX && adapter.itemCount == 0) expand()
adapter.addItems(list)
}
......@@ -192,7 +193,8 @@ class SuggestionsView : FrameLayout, TextWatcher {
}
private fun adapter(token: String): SuggestionsAdapter<*> {
return adaptersByToken[token] ?: throw IllegalStateException("no adapter binds to token \"$token\"")
return adaptersByToken[token]
?: throw IllegalStateException("no adapter binds to token \"$token\"")
}
private fun cancelSuggestions(haltCompletion: Boolean) {
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="popup_max_height">150dp</dimen>
<dimen name="suggestions_box_max_height">250dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">suggestions</string>
</resources>
package yampsample.leonardoaramaki.github.com.suggestions;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
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