Fix possible emoji-autocompletion crash
Thread: main, Exception: java.lang.ClassCastException: im.vector.app.features.autocomplete.AutocompleteHeaderItem$Holder cannot be cast to im.vector.app.features.autocomplete.emoji.AutocompleteEmojiItem$Holder at im.vector.app.features.autocomplete.emoji.AutocompleteEmojiItem_.handlePreBind(AutocompleteEmojiItem_.java:1) at com.airbnb.epoxy.BaseEpoxyAdapter.onBindViewHolder(BaseEpoxyAdapter.java:22) at com.airbnb.epoxy.BaseEpoxyAdapter.onBindViewHolder(BaseEpoxyAdapter.java:3) at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:43) at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:59) at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:974) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6) at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:54) at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1) at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:54) at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:400) at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:67) at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:135) at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:8) Change-Id: I4d4919c35babea2606a06b3e99b5c3b3ce08e95d
This commit is contained in:
parent
eeb4b8dc0d
commit
0faa712f23
|
@ -67,7 +67,7 @@ class AutocompleteEmojiController @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildHeaderItem(header: AutocompleteEmojiDataItem.Header) {
|
private fun buildHeaderItem(header: AutocompleteEmojiDataItem.Header) {
|
||||||
autocompleteHeaderItem {
|
autocompleteEmojiHeaderItem {
|
||||||
id("h/${header.id}")
|
id("h/${header.id}")
|
||||||
title(header.title)
|
title(header.title)
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,7 @@ class AutocompleteEmojiController @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Count of standard emoji matches - WARN: do not set to 8 or less, or epoxy/recycler will sometimes crash with some class casts,
|
// Count of standard emoji matches
|
||||||
// e.g. when repeatedly typing `:turt`, then deleting back to `:`?!?
|
|
||||||
// What makes 8 magic? Probably that no-search proposals also returns 8 results? But wtf?
|
|
||||||
const val STANDARD_EMOJI_MAX = 9
|
const val STANDARD_EMOJI_MAX = 9
|
||||||
// Count of emojis for the current room's image pack
|
// Count of emojis for the current room's image pack
|
||||||
const val CUSTOM_THIS_ROOM_MAX = 8
|
const val CUSTOM_THIS_ROOM_MAX = 8
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
* Copyright 2023 SpiritCroc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.features.autocomplete.emoji
|
||||||
|
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
|
||||||
|
// We were getting ClassCastExceptions for the holder of AutocompleteHeaderItem, which sometimes seemed to still be an AutocompleteEmojiItem...
|
||||||
|
// https://github.com/SchildiChat/SchildiChat-android-rageshakes/issues/1040
|
||||||
|
// So let's build some HeaderItem using the same holder
|
||||||
|
@EpoxyModelClass
|
||||||
|
abstract class AutocompleteEmojiHeaderItem : VectorEpoxyModel<AutocompleteEmojiItem.Holder>(R.layout.item_autocomplete_emoji) {
|
||||||
|
|
||||||
|
@EpoxyAttribute var title: String? = null
|
||||||
|
|
||||||
|
override fun bind(holder: AutocompleteEmojiItem.Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
|
||||||
|
holder.titleView.isVisible = true
|
||||||
|
holder.emojiText.isVisible = false
|
||||||
|
holder.emoteImage.isVisible = false
|
||||||
|
holder.emojiKeywordText.isVisible = false
|
||||||
|
holder.emojiNameText.isVisible = false
|
||||||
|
holder.titleView.text = title
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,8 @@ abstract class AutocompleteEmojiItem : VectorEpoxyModel<AutocompleteEmojiItem.Ho
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
|
holder.titleView.isVisible = false
|
||||||
|
holder.emojiNameText.isVisible = true
|
||||||
if (emoteUrl?.isNotEmpty().orFalse()) {
|
if (emoteUrl?.isNotEmpty().orFalse()) {
|
||||||
holder.emojiText.isVisible = false
|
holder.emojiText.isVisible = false
|
||||||
holder.emoteImage.isVisible = true
|
holder.emoteImage.isVisible = true
|
||||||
|
@ -75,5 +77,6 @@ abstract class AutocompleteEmojiItem : VectorEpoxyModel<AutocompleteEmojiItem.Ho
|
||||||
val emoteImage by bind<ImageView>(R.id.itemAutocompleteEmote)
|
val emoteImage by bind<ImageView>(R.id.itemAutocompleteEmote)
|
||||||
val emojiNameText by bind<TextView>(R.id.itemAutocompleteEmojiName)
|
val emojiNameText by bind<TextView>(R.id.itemAutocompleteEmojiName)
|
||||||
val emojiKeywordText by bind<TextView>(R.id.itemAutocompleteEmojiSubname)
|
val emojiKeywordText by bind<TextView>(R.id.itemAutocompleteEmojiSubname)
|
||||||
|
val titleView by bind<TextView>(R.id.headerItemAutocompleteTitle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
import im.vector.app.core.epoxy.onClick
|
import im.vector.app.core.epoxy.onClick
|
||||||
import im.vector.app.features.themes.ThemeUtils
|
import im.vector.app.features.themes.ThemeUtils
|
||||||
|
|
||||||
@EpoxyModelClass // Re-using item_autocomplete_emoji layout for now because I'm lazy - may want to change that if it causes troubles
|
@EpoxyModelClass // Re-using item_autocomplete_emoji to avoid class-cast exceptions like https://github.com/SchildiChat/SchildiChat-android-rageshakes/issues/1040
|
||||||
abstract class AutocompleteExpandItem : VectorEpoxyModel<AutocompleteEmojiItem.Holder>(R.layout.item_autocomplete_emoji) {
|
abstract class AutocompleteExpandItem : VectorEpoxyModel<AutocompleteEmojiItem.Holder>(R.layout.item_autocomplete_emoji) {
|
||||||
|
|
||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
|
@ -38,8 +38,10 @@ abstract class AutocompleteExpandItem : VectorEpoxyModel<AutocompleteEmojiItem.H
|
||||||
|
|
||||||
override fun bind(holder: AutocompleteEmojiItem.Holder) {
|
override fun bind(holder: AutocompleteEmojiItem.Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
|
holder.titleView.isVisible = false
|
||||||
holder.emojiText.isVisible = false
|
holder.emojiText.isVisible = false
|
||||||
holder.emoteImage.isVisible = true
|
holder.emoteImage.isVisible = true
|
||||||
|
holder.emojiNameText.isVisible = true
|
||||||
holder.emoteImage.setImageResource(R.drawable.ic_expand_more)
|
holder.emoteImage.setImageResource(R.drawable.ic_expand_more)
|
||||||
holder.emoteImage.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.emoteImage.context, R.attr.vctr_content_secondary))
|
holder.emoteImage.imageTintList = ColorStateList.valueOf(ThemeUtils.getColor(holder.emoteImage.context, R.attr.vctr_content_secondary))
|
||||||
holder.emojiText.typeface = Typeface.DEFAULT
|
holder.emojiText.typeface = Typeface.DEFAULT
|
||||||
|
@ -54,12 +56,4 @@ abstract class AutocompleteExpandItem : VectorEpoxyModel<AutocompleteEmojiItem.H
|
||||||
holder.view.onClick(onClickListener)
|
holder.view.onClick(onClickListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
|
||||||
val emojiText by bind<TextView>(R.id.itemAutocompleteEmoji)
|
|
||||||
val emoteImage by bind<ImageView>(R.id.itemAutocompleteEmote)
|
|
||||||
val emojiNameText by bind<TextView>(R.id.itemAutocompleteEmojiName)
|
|
||||||
val emojiKeywordText by bind<TextView>(R.id.itemAutocompleteEmojiSubname)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,21 @@
|
||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
tools:viewBindingIgnore="true">
|
tools:viewBindingIgnore="true">
|
||||||
|
|
||||||
|
<!-- this one is only for AutocompleteEmojiHeaderItem...
|
||||||
|
see also https://github.com/SchildiChat/SchildiChat-android-rageshakes/issues/1040
|
||||||
|
(ClassCastException when having different holder types in autocompletions) -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/headerItemAutocompleteTitle"
|
||||||
|
style="@style/Widget.Vector.TextView.Subtitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="?vctr_content_secondary"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="@string/custom_emotes_this_room" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/itemAutocompleteEmoji"
|
android:id="@+id/itemAutocompleteEmoji"
|
||||||
style="@style/Widget.Vector.TextView.Title"
|
style="@style/Widget.Vector.TextView.Title"
|
||||||
|
|
Loading…
Reference in New Issue