Animated emoji support (#2064)

* Animated emoji support

* Try to query preference only once

* Revert to using SpannableStringBuilder
This commit is contained in:
Alibek Omarov 2021-02-06 10:14:51 +03:00 committed by GitHub
commit 9580870445
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 225 additions and 120 deletions

View file

@ -42,7 +42,8 @@ interface AnnouncementActionListener: LinkListener {
class AnnouncementAdapter(
private var items: List<Announcement> = emptyList(),
private val listener: AnnouncementActionListener,
private val wellbeingEnabled: Boolean = false
private val wellbeingEnabled: Boolean = false,
private val animateEmojis: Boolean = false
) : RecyclerView.Adapter<AnnouncementAdapter.AnnouncementViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AnnouncementViewHolder {
@ -99,7 +100,8 @@ class AnnouncementAdapter(
reaction.staticUrl ?: "",
null
)),
this
this,
animateEmojis
)
isChecked = reaction.me

View file

@ -82,8 +82,9 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
val preferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
val wellbeingEnabled = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false)
val animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
adapter = AnnouncementAdapter(emptyList(), this, wellbeingEnabled)
adapter = AnnouncementAdapter(emptyList(), this, wellbeingEnabled, animateEmojis)
announcementsList.adapter = adapter

View file

@ -69,6 +69,7 @@ import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.Emoji
import com.keylesspalace.tusky.entity.NewPoll
import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.*
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
@ -160,7 +161,7 @@ class ComposeActivity : BaseActivity(),
composeScheduleView.setDateTime(composeOptions?.scheduledAt)
}
setupComposeField(viewModel.startingText)
setupComposeField(preferences, viewModel.startingText)
setupContentWarningField(composeOptions?.contentWarning)
setupPollView()
applyShareIntent(intent, savedInstanceState)
@ -245,13 +246,18 @@ class ComposeActivity : BaseActivity(),
composeContentWarningField.onTextChanged { _, _, _, _ -> updateVisibleCharactersLeft() }
}
private fun setupComposeField(startingText: String?) {
private fun setupComposeField(preferences: SharedPreferences, startingText: String?) {
composeEditField.setOnCommitContentListener(this)
composeEditField.setOnKeyListener { _, keyCode, event -> this.onKeyDown(keyCode, event) }
composeEditField.setAdapter(
ComposeAutoCompleteAdapter(this))
ComposeAutoCompleteAdapter(
this,
preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false),
preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
)
)
composeEditField.setTokenizer(ComposeTokenizer())
composeEditField.setText(startingText)

View file

@ -53,11 +53,15 @@ public class ComposeAutoCompleteAdapter extends BaseAdapter
private final ArrayList<AutocompleteResult> resultList;
private final AutocompletionProvider autocompletionProvider;
private final boolean animateAvatar;
private final boolean animateEmojis;
public ComposeAutoCompleteAdapter(AutocompletionProvider autocompletionProvider) {
public ComposeAutoCompleteAdapter(AutocompletionProvider autocompletionProvider, boolean animateAvatar, boolean animateEmojis) {
super();
resultList = new ArrayList<>();
this.autocompletionProvider = autocompletionProvider;
this.animateAvatar = animateAvatar;
this.animateEmojis = animateEmojis;
}
@Override
@ -147,15 +151,12 @@ public class ComposeAutoCompleteAdapter extends BaseAdapter
);
accountViewHolder.username.setText(formattedUsername);
CharSequence emojifiedName = CustomEmojiHelper.emojify(account.getName(),
account.getEmojis(), accountViewHolder.displayName);
account.getEmojis(), accountViewHolder.displayName, animateEmojis);
accountViewHolder.displayName.setText(emojifiedName);
int avatarRadius = accountViewHolder.avatar.getContext().getResources()
.getDimensionPixelSize(R.dimen.avatar_radius_42dp);
boolean animateAvatar = PreferenceManager.getDefaultSharedPreferences(accountViewHolder.avatar.getContext())
.getBoolean("animateGifAvatars", false);
ImageLoadingHelper.loadAvatar(
account.getAvatar(),
accountViewHolder.avatar,

View file

@ -75,7 +75,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
setupCollapsedState(status.getCollapsible(), status.getCollapsed(), status.getExpanded(), status.getSpoilerText(), listener);
setDisplayName(account.getDisplayName(), account.getEmojis());
setDisplayName(account.getDisplayName(), account.getEmojis(), statusDisplayOptions);
setUsername(account.getUsername());
setCreatedAt(status.getCreatedAt(), statusDisplayOptions);
setIsReply(status.getInReplyToId() != null);

View file

@ -67,8 +67,8 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable, Res
useBlurhash = preferences.getBoolean("useBlurhash", true),
cardViewMode = CardViewMode.NONE,
confirmReblogs = preferences.getBoolean("confirmReblogs", true),
hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false)
hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false),
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
)
adapter = ConversationAdapter(statusDisplayOptions, this, ::onTopLoaded, viewModel::retry)

View file

@ -174,6 +174,13 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
setTitle(R.string.pref_title_enable_swipe_for_tabs)
isSingleLineTitle = false
}
switchPreference {
setDefaultValue(false)
key = PrefKeys.ANIMATE_CUSTOM_EMOJIS
setTitle(R.string.pref_title_animate_custom_emojis)
isSingleLineTitle = false
}
}
preferenceCategory(R.string.pref_title_browser_settings) {

View file

@ -75,7 +75,7 @@ class StatusViewHolder(
sensitive, previewListener, viewState.isMediaShow(status.id, status.sensitive),
mediaViewHeight)
statusViewHelper.setupPollReadonly(status.poll.toViewData(), status.emojis, statusDisplayOptions.useAbsoluteTime)
statusViewHelper.setupPollReadonly(status.poll.toViewData(), status.emojis, statusDisplayOptions)
setCreatedAt(status.createdAt)
}
@ -89,7 +89,7 @@ class StatusViewHolder(
itemView.statusContentWarningButton.hide()
itemView.statusContentWarningDescription.hide()
} else {
val emojiSpoiler = status.spoilerText.emojify(status.emojis, itemView.statusContentWarningDescription)
val emojiSpoiler = status.spoilerText.emojify(status.emojis, itemView.statusContentWarningDescription, statusDisplayOptions.animateEmojis)
itemView.statusContentWarningDescription.text = emojiSpoiler
itemView.statusContentWarningDescription.show()
itemView.statusContentWarningButton.show()
@ -122,7 +122,7 @@ class StatusViewHolder(
emojis: List<Emoji>,
listener: LinkListener) {
if (expanded) {
val emojifiedText = content.emojify(emojis, itemView.statusContent)
val emojifiedText = content.emojify(emojis, itemView.statusContent, statusDisplayOptions.animateEmojis)
LinkHelper.setClickableText(itemView.statusContent, emojifiedText, mentions, listener)
} else {
LinkHelper.setClickableMentions(itemView.statusContent, mentions, listener)

View file

@ -111,7 +111,8 @@ class ReportStatusesFragment : Fragment(R.layout.fragment_report_statuses), Inje
useBlurhash = preferences.getBoolean("useBlurhash", true),
cardViewMode = CardViewMode.NONE,
confirmReblogs = preferences.getBoolean("confirmReblogs", true),
hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false)
hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false),
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
)
adapter = StatusesAdapter(statusDisplayOptions,

View file

@ -25,7 +25,7 @@ import com.keylesspalace.tusky.adapter.AccountViewHolder
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.interfaces.LinkListener
class SearchAccountsAdapter(private val linkListener: LinkListener)
class SearchAccountsAdapter(private val linkListener: LinkListener, private val animateAvatars: Boolean, private val animateEmojis: Boolean)
: PagedListAdapter<Account, RecyclerView.ViewHolder>(ACCOUNT_COMPARATOR) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
@ -37,7 +37,7 @@ class SearchAccountsAdapter(private val linkListener: LinkListener)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
getItem(position)?.let { item ->
(holder as AccountViewHolder).apply {
setupWithAccount(item)
setupWithAccount(item, animateAvatars, animateEmojis)
setupLinkListener(linkListener)
}
}

View file

@ -18,12 +18,23 @@ package com.keylesspalace.tusky.components.search.fragments
import androidx.lifecycle.LiveData
import androidx.paging.PagedList
import androidx.paging.PagedListAdapter
import androidx.preference.PreferenceManager
import com.keylesspalace.tusky.components.search.adapter.SearchAccountsAdapter
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.NetworkState
import kotlinx.android.synthetic.main.fragment_search.*
class SearchAccountsFragment : SearchFragment<Account>() {
override fun createAdapter(): PagedListAdapter<Account, *> = SearchAccountsAdapter(this)
override fun createAdapter(): PagedListAdapter<Account, *> {
val preferences = PreferenceManager.getDefaultSharedPreferences(searchRecyclerView.context)
return SearchAccountsAdapter(
this,
preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false),
preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
)
}
override val networkStateRefresh: LiveData<NetworkState>
get() = viewModel.networkStateAccountRefresh

View file

@ -87,7 +87,8 @@ class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.Concre
useBlurhash = preferences.getBoolean("useBlurhash", true),
cardViewMode = CardViewMode.NONE,
confirmReblogs = preferences.getBoolean("confirmReblogs", true),
hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false)
hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false),
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
)
searchRecyclerView.addItemDecoration(DividerItemDecoration(searchRecyclerView.context, DividerItemDecoration.VERTICAL))