Tweak emoji suggestions UX.

This commit is contained in:
Cody Henthorne 2022-08-02 23:26:58 -04:00 committed by Greyson Parrelli
parent 440d041402
commit d7d923c820
7 changed files with 23 additions and 16 deletions

View file

@ -52,7 +52,7 @@ import static org.thoughtcrime.securesms.database.MentionUtil.MENTION_STARTER;
public class ComposeText extends EmojiEditText {
private static final char EMOJI_STARTER = ':';
private static final long EMOJI_KEYWORD_DELAY = TimeUnit.SECONDS.toMillis(1);
private static final long EMOJI_KEYWORD_DELAY = 1500;
private CharSequence hint;
private SpannableString subHint;
@ -322,11 +322,9 @@ public class ComposeText extends EmojiEditText {
}
private void doAfterCursorChange(@NonNull Editable text) {
removeCallbacks(keywordSearchRunnable);
if (enoughToFilter(text, false)) {
performFiltering(text, false);
} else {
postDelayed(keywordSearchRunnable, EMOJI_KEYWORD_DELAY);
clearInlineQuery();
}
}

View file

@ -2358,6 +2358,7 @@ public class ConversationParentFragment extends Fragment
composeText,
getViewLifecycleOwner()
);
inlineQueryResultsController.onOrientationChange(getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE);
recipient.observe(getViewLifecycleOwner(), r -> {
if (r.isPushV2Group() && !mentionsSuggestions.resolved()) {

View file

@ -10,7 +10,7 @@ sealed class InlineQueryReplacement(@get:JvmName("isKeywordSearch") val keywordS
class Emoji(private val emoji: String, keywordSearch: Boolean) : InlineQueryReplacement(keywordSearch) {
override fun toCharSequence(context: Context): CharSequence {
return "$emoji "
return emoji
}
}
}

View file

@ -10,7 +10,6 @@ import io.reactivex.rxjava3.kotlin.subscribeBy
import org.signal.core.util.DimensionUnit
import org.thoughtcrime.securesms.components.ComposeText
import org.thoughtcrime.securesms.util.LifecycleDisposable
import org.thoughtcrime.securesms.util.VibrateUtil
import org.thoughtcrime.securesms.util.adapter.mapping.AnyMappingModel
import org.thoughtcrime.securesms.util.doOnEachLayout
@ -30,6 +29,7 @@ class InlineQueryResultsController(
private var popup: InlineQueryResultsPopup? = null
private var previousResults: List<AnyMappingModel>? = null
private var canShow: Boolean = false
private var isLandscape: Boolean = false
init {
lifecycleDisposable.bindTo(lifecycleOwner)
@ -61,6 +61,8 @@ class InlineQueryResultsController(
}
fun onOrientationChange(isLandscape: Boolean) {
this.isLandscape = isLandscape
if (isLandscape) {
dismiss()
} else {
@ -70,7 +72,7 @@ class InlineQueryResultsController(
private fun updateList(results: List<AnyMappingModel>) {
previousResults = results
if (results.isEmpty() || !canShow) {
if (results.isEmpty() || !canShow || isLandscape) {
dismiss()
} else if (popup != null) {
popup?.setResults(results)
@ -82,7 +84,6 @@ class InlineQueryResultsController(
baseOffsetX = DimensionUnit.DP.toPixels(16f).toInt(),
callback = this
).show()
VibrateUtil.vibrateTick(context)
}
}

View file

@ -6,8 +6,8 @@ import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
import android.widget.PopupWindow
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.ViewUtil
@ -34,7 +34,11 @@ class InlineQueryResultsPopup(
private val adapter: MappingAdapter
init {
setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.signal_context_menu_background))
if (Build.VERSION.SDK_INT >= 21) {
contentView.outlineProvider = ViewOutlineProvider.BACKGROUND
contentView.clipToOutline = true
}
inputMethodMode = INPUT_METHOD_NOT_NEEDED
setOnDismissListener {

View file

@ -18,18 +18,20 @@ private const val MINIMUM_QUERY_THRESHOLD = 1
private const val MINIMUM_INLINE_QUERY_THRESHOLD = 2
private const val EMOJI_SEARCH_LIMIT = 20
private val NOT_PUNCTUATION = "[A-Za-z0-9 ]".toRegex()
class EmojiSearchRepository(private val context: Context) {
private val emojiSearchDatabase: EmojiSearchDatabase = SignalDatabase.emojiSearch
fun submitQuery(query: String, limit: Int = EMOJI_SEARCH_LIMIT): Single<List<String>> {
if (query.length < MINIMUM_INLINE_QUERY_THRESHOLD) {
return Single.just(emptyList())
val result = if (query.length >= MINIMUM_INLINE_QUERY_THRESHOLD && NOT_PUNCTUATION.matches(query.substring(query.lastIndex))) {
Single.fromCallable<List<String>> { emojiSearchDatabase.query(query, limit) }
} else {
Single.just(emptyList())
}
return Single.fromCallable<List<String>> {
emojiSearchDatabase.query(query, limit)
}.subscribeOn(Schedulers.io())
return result.subscribeOn(Schedulers.io())
}
fun submitQuery(query: String, includeRecents: Boolean, limit: Int = EMOJI_SEARCH_LIMIT, consumer: Consumer<EmojiPageModel>) {

View file

@ -2,16 +2,17 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="@drawable/signal_context_menu_background">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/inline_query_results_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingHorizontal="8dp"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</FrameLayout>