Add option for making emojis bigger

Based on these commits by a1ba:
- beb9dd69e4
- a2fc2812060a10ae900c9284bf7777b482e0986c
This commit is contained in:
fruye 2022-11-09 10:42:13 +01:00
parent ccbf461eac
commit 083352c45f
27 changed files with 98 additions and 40 deletions

View File

@ -67,6 +67,7 @@ class AccountsInListFragment : DialogFragment(), Injectable {
private val pm by unsafeLazy { PreferenceManager.getDefaultSharedPreferences(requireContext()) } private val pm by unsafeLazy { PreferenceManager.getDefaultSharedPreferences(requireContext()) }
private val animateAvatar by unsafeLazy { pm.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) } private val animateAvatar by unsafeLazy { pm.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false) }
private val animateEmojis by unsafeLazy { pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) } private val animateEmojis by unsafeLazy { pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) }
private val bigEmojis by unsafeLazy { pm.getBoolean(PrefKeys.BIG_EMOJIS, true) }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -188,7 +189,7 @@ class AccountsInListFragment : DialogFragment(), Injectable {
override fun onBindViewHolder(holder: BindingHolder<ItemFollowRequestBinding>, position: Int) { override fun onBindViewHolder(holder: BindingHolder<ItemFollowRequestBinding>, position: Int) {
val account = getItem(position) val account = getItem(position)
holder.binding.displayNameTextView.text = account.name.emojify(account.emojis, holder.binding.displayNameTextView, animateEmojis) holder.binding.displayNameTextView.text = account.name.emojify(account.emojis, holder.binding.displayNameTextView, animateEmojis, bigEmojis)
holder.binding.usernameTextView.text = account.username holder.binding.usernameTextView.text = account.username
loadAvatar(account.avatar, holder.binding.avatar, radius, animateAvatar) loadAvatar(account.avatar, holder.binding.avatar, radius, animateAvatar)
} }
@ -227,7 +228,7 @@ class AccountsInListFragment : DialogFragment(), Injectable {
override fun onBindViewHolder(holder: BindingHolder<ItemFollowRequestBinding>, position: Int) { override fun onBindViewHolder(holder: BindingHolder<ItemFollowRequestBinding>, position: Int) {
val (account, inAList) = getItem(position) val (account, inAList) = getItem(position)
holder.binding.displayNameTextView.text = account.name.emojify(account.emojis, holder.binding.displayNameTextView, animateEmojis) holder.binding.displayNameTextView.text = account.name.emojify(account.emojis, holder.binding.displayNameTextView, animateEmojis, bigEmojis)
holder.binding.usernameTextView.text = account.username holder.binding.usernameTextView.text = account.username
loadAvatar(account.avatar, holder.binding.avatar, radius, animateAvatar) loadAvatar(account.avatar, holder.binding.avatar, radius, animateAvatar)

View File

@ -1012,11 +1012,12 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
private fun updateProfiles() { private fun updateProfiles() {
val animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) val animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
val bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true)
val profiles: MutableList<IProfile> = val profiles: MutableList<IProfile> =
accountManager.getAllAccountsOrderedByActive().map { acc -> accountManager.getAllAccountsOrderedByActive().map { acc ->
ProfileDrawerItem().apply { ProfileDrawerItem().apply {
isSelected = acc.isActive isSelected = acc.isActive
nameText = acc.displayName.emojify(acc.emojis, header, animateEmojis) nameText = acc.displayName.emojify(acc.emojis, header, animateEmojis, bigEmojis)
iconUrl = acc.profilePictureUrl iconUrl = acc.profilePictureUrl
isNameShown = true isNameShown = true
identifier = acc.id identifier = acc.id

View File

@ -41,9 +41,10 @@ class AccountSelectionAdapter(context: Context) : ArrayAdapter<AccountEntity>(co
if (account != null) { if (account != null) {
val pm = PreferenceManager.getDefaultSharedPreferences(binding.avatar.context) val pm = PreferenceManager.getDefaultSharedPreferences(binding.avatar.context)
val animateEmojis = pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) val animateEmojis = pm.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
val bigEmojis = pm.getBoolean(PrefKeys.BIG_EMOJIS, true)
binding.username.text = account.fullName binding.username.text = account.fullName
binding.displayName.text = account.displayName.emojify(account.emojis, binding.displayName, animateEmojis) binding.displayName.text = account.displayName.emojify(account.emojis, binding.displayName, animateEmojis, bigEmojis)
binding.avatarBadge.visibility = View.GONE // We never want to display the bot badge here binding.avatarBadge.visibility = View.GONE // We never want to display the bot badge here
val avatarRadius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius_42dp) val avatarRadius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius_42dp)

View File

@ -73,7 +73,8 @@ class FollowRequestViewHolder(
val emojifiedName: CharSequence = wrappedName.emojify( val emojifiedName: CharSequence = wrappedName.emojify(
account.emojis, account.emojis,
itemView, itemView,
animateEmojis animateEmojis,
true /* FIXME */
) )
binding.displayNameTextView.text = emojifiedName binding.displayNameTextView.text = emojifiedName
if (showHeader) { if (showHeader) {
@ -88,7 +89,7 @@ class FollowRequestViewHolder(
wrappedName.length, wrappedName.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
) )
}.emojify(account.emojis, itemView, animateEmojis) }.emojify(account.emojis, itemView, animateEmojis, false)
} }
binding.notificationTextView.visible(showHeader) binding.notificationTextView.visible(showHeader)
val formattedUsername = itemView.context.getString(R.string.post_username_format, account.username) val formattedUsername = itemView.context.getString(R.string.post_username_format, account.username)

View File

@ -92,7 +92,7 @@ class PollAdapter : RecyclerView.Adapter<BindingHolder<ItemPollBinding>>() {
RESULT -> { RESULT -> {
val percent = calculatePercent(option.votesCount, votersCount, voteCount) val percent = calculatePercent(option.votesCount, votersCount, voteCount)
resultTextView.text = buildDescription(option.title, percent, option.voted, resultTextView.context) resultTextView.text = buildDescription(option.title, percent, option.voted, resultTextView.context)
.emojify(emojis, resultTextView, animateEmojis) .emojify(emojis, resultTextView, animateEmojis, true /* FIXME */)
val level = percent * 100 val level = percent * 100
val optionColor = if (option.voted) { val optionColor = if (option.voted) {
@ -106,7 +106,7 @@ class PollAdapter : RecyclerView.Adapter<BindingHolder<ItemPollBinding>>() {
resultTextView.setOnClickListener(resultClickListener) resultTextView.setOnClickListener(resultClickListener)
} }
SINGLE -> { SINGLE -> {
radioButton.text = option.title.emojify(emojis, radioButton, animateEmojis) radioButton.text = option.title.emojify(emojis, radioButton, animateEmojis, true /* FIXME */)
radioButton.isChecked = option.selected radioButton.isChecked = option.selected
radioButton.setOnClickListener { radioButton.setOnClickListener {
pollOptions.forEachIndexed { index, pollOption -> pollOptions.forEachIndexed { index, pollOption ->
@ -116,7 +116,7 @@ class PollAdapter : RecyclerView.Adapter<BindingHolder<ItemPollBinding>>() {
} }
} }
MULTIPLE -> { MULTIPLE -> {
checkBox.text = option.title.emojify(emojis, checkBox, animateEmojis) checkBox.text = option.title.emojify(emojis, checkBox, animateEmojis, true /* FIXME */)
checkBox.isChecked = option.selected checkBox.isChecked = option.selected
checkBox.setOnCheckedChangeListener { _, isChecked -> checkBox.setOnCheckedChangeListener { _, isChecked ->
pollOptions[holder.bindingAdapterPosition].selected = isChecked pollOptions[holder.bindingAdapterPosition].selected = isChecked

View File

@ -70,12 +70,14 @@ class ReportNotificationViewHolder(
val reporterName = reporter.name.unicodeWrap().emojify( val reporterName = reporter.name.unicodeWrap().emojify(
reporter.emojis, reporter.emojis,
binding.root, binding.root,
animateEmojis animateEmojis,
false
) )
val reporteeName = report.targetAccount.name.unicodeWrap().emojify( val reporteeName = report.targetAccount.name.unicodeWrap().emojify(
report.targetAccount.emojis, report.targetAccount.emojis,
itemView, itemView,
animateEmojis animateEmojis,
false
) )
val icon = ContextCompat.getDrawable(binding.root.context, R.drawable.ic_flag_24dp) val icon = ContextCompat.getDrawable(binding.root.context, R.drawable.ic_flag_24dp)

View File

@ -191,7 +191,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
protected void setDisplayName(String name, List<Emoji> customEmojis, StatusDisplayOptions statusDisplayOptions) { protected void setDisplayName(String name, List<Emoji> customEmojis, StatusDisplayOptions statusDisplayOptions) {
CharSequence emojifiedName = CustomEmojiHelper.emojify( CharSequence emojifiedName = CustomEmojiHelper.emojify(
name, customEmojis, displayName, statusDisplayOptions.animateEmojis() name, customEmojis, displayName, statusDisplayOptions.animateEmojis(), false
); );
displayName.setText(emojifiedName); displayName.setText(emojifiedName);
} }
@ -219,7 +219,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
if (sensitive) { if (sensitive) {
CharSequence emojiSpoiler = CustomEmojiHelper.emojify( CharSequence emojiSpoiler = CustomEmojiHelper.emojify(
spoilerText, emojis, contentWarningDescription, statusDisplayOptions.animateEmojis() spoilerText, emojis, contentWarningDescription, statusDisplayOptions.animateEmojis(), statusDisplayOptions.bigEmojis()
); );
contentWarningDescription.setText(emojiSpoiler); contentWarningDescription.setText(emojiSpoiler);
contentWarningDescription.setVisibility(View.VISIBLE); contentWarningDescription.setVisibility(View.VISIBLE);
@ -274,7 +274,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
PollViewData poll = PollViewDataKt.toViewData(actionable.getPoll()); PollViewData poll = PollViewDataKt.toViewData(actionable.getPoll());
if (expanded) { if (expanded) {
CharSequence emojifiedText = CustomEmojiHelper.emojify(content, emojis, this.content, statusDisplayOptions.animateEmojis()); CharSequence emojifiedText = CustomEmojiHelper.emojify(content, emojis, this.content, statusDisplayOptions.animateEmojis(), statusDisplayOptions.bigEmojis());
LinkHelper.setClickableText(this.content, emojifiedText, mentions, tags, listener); LinkHelper.setClickableText(this.content, emojifiedText, mentions, tags, listener);
for (int i = 0; i < mediaLabels.length; ++i) { for (int i = 0; i < mediaLabels.length; ++i) {
updateMediaLabel(i, sensitive, true); updateMediaLabel(i, sensitive, true);

View File

@ -98,7 +98,7 @@ public class StatusViewHolder extends StatusBaseViewHolder {
CharSequence wrappedName = StringUtils.unicodeWrap(name); CharSequence wrappedName = StringUtils.unicodeWrap(name);
CharSequence boostedText = context.getString(R.string.post_boosted_format, wrappedName); CharSequence boostedText = context.getString(R.string.post_boosted_format, wrappedName);
CharSequence emojifiedText = CustomEmojiHelper.emojify( CharSequence emojifiedText = CustomEmojiHelper.emojify(
boostedText, accountEmoji, statusInfo, statusDisplayOptions.animateEmojis() boostedText, accountEmoji, statusInfo, statusDisplayOptions.animateEmojis(), false
); );
statusInfo.setText(emojifiedText); statusInfo.setText(emojifiedText);
statusInfo.setVisibility(View.VISIBLE); statusInfo.setVisibility(View.VISIBLE);

View File

@ -132,6 +132,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
private var animateAvatar: Boolean = false private var animateAvatar: Boolean = false
private var animateEmojis: Boolean = false private var animateEmojis: Boolean = false
private var bigEmojis: Boolean = false
// fields for scroll animation // fields for scroll animation
private var hideFab: Boolean = false private var hideFab: Boolean = false
@ -175,6 +176,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this) val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
animateAvatar = sharedPrefs.getBoolean("animateGifAvatars", false) animateAvatar = sharedPrefs.getBoolean("animateGifAvatars", false)
animateEmojis = sharedPrefs.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) animateEmojis = sharedPrefs.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
bigEmojis = sharedPrefs.getBoolean(PrefKeys.BIG_EMOJIS, true)
hideFab = sharedPrefs.getBoolean("fabHide", false) hideFab = sharedPrefs.getBoolean("fabHide", false)
handleWindowInsets() handleWindowInsets()
@ -451,7 +453,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
val usernameFormatted = getString(R.string.post_username_format, account.username) val usernameFormatted = getString(R.string.post_username_format, account.username)
binding.accountUsernameTextView.text = usernameFormatted binding.accountUsernameTextView.text = usernameFormatted
binding.accountDisplayNameTextView.text = account.name.emojify(account.emojis, binding.accountDisplayNameTextView, animateEmojis) binding.accountDisplayNameTextView.text = account.name.emojify(account.emojis, binding.accountDisplayNameTextView, animateEmojis, bigEmojis)
// Long press on username to copy it to clipboard // Long press on username to copy it to clipboard
for (view in listOf(binding.accountUsernameTextView, binding.accountDisplayNameTextView)) { for (view in listOf(binding.accountUsernameTextView, binding.accountDisplayNameTextView)) {
@ -467,7 +469,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
} }
} }
val emojifiedNote = account.note.parseAsMastodonHtml().emojify(account.emojis, binding.accountNoteTextView, animateEmojis) val emojifiedNote = account.note.parseAsMastodonHtml().emojify(account.emojis, binding.accountNoteTextView, animateEmojis, bigEmojis)
setClickableText(binding.accountNoteTextView, emojifiedNote, emptyList(), null, this) setClickableText(binding.accountNoteTextView, emojifiedNote, emptyList(), null, this)
accountFieldAdapter.fields = account.fields.orEmpty() accountFieldAdapter.fields = account.fields.orEmpty()
@ -546,7 +548,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
*/ */
private fun updateToolbar() { private fun updateToolbar() {
loadedAccount?.let { account -> loadedAccount?.let { account ->
supportActionBar?.title = account.name.emojify(account.emojis, binding.accountToolbar, animateEmojis) supportActionBar?.title = account.name.emojify(account.emojis, binding.accountToolbar, animateEmojis, false)
supportActionBar?.subtitle = String.format(getString(R.string.post_username_format), account.username) supportActionBar?.subtitle = String.format(getString(R.string.post_username_format), account.username)
} }
} }

View File

@ -48,10 +48,10 @@ class AccountFieldAdapter(
val nameTextView = holder.binding.accountFieldName val nameTextView = holder.binding.accountFieldName
val valueTextView = holder.binding.accountFieldValue val valueTextView = holder.binding.accountFieldValue
val emojifiedName = field.name.emojify(emojis, nameTextView, animateEmojis) val emojifiedName = field.name.emojify(emojis, nameTextView, animateEmojis, true /* FIXME */)
nameTextView.text = emojifiedName nameTextView.text = emojifiedName
val emojifiedValue = field.value.parseAsMastodonHtml().emojify(emojis, valueTextView, animateEmojis) val emojifiedValue = field.value.parseAsMastodonHtml().emojify(emojis, valueTextView, animateEmojis, true /* FIXME */)
setClickableText(valueTextView, emojifiedValue, emptyList(), null, linkListener) setClickableText(valueTextView, emojifiedValue, emptyList(), null, linkListener)
if (field.verifiedAt != null) { if (field.verifiedAt != null) {

View File

@ -48,7 +48,7 @@ class BlocksAdapter(
val binding = viewHolder.binding val binding = viewHolder.binding
val context = binding.root.context val context = binding.root.context
val emojifiedName = account.name.emojify(account.emojis, binding.blockedUserDisplayName, animateEmojis) val emojifiedName = account.name.emojify(account.emojis, binding.blockedUserDisplayName, animateEmojis, true /* FIXME */)
binding.blockedUserDisplayName.text = emojifiedName binding.blockedUserDisplayName.text = emojifiedName
val formattedUsername = context.getString(R.string.post_username_format, account.username) val formattedUsername = context.getString(R.string.post_username_format, account.username)
binding.blockedUserUsername.text = formattedUsername binding.blockedUserUsername.text = formattedUsername

View File

@ -53,7 +53,7 @@ class MutesAdapter(
val mutingNotifications = mutingNotificationsMap[account.id] val mutingNotifications = mutingNotificationsMap[account.id]
val emojifiedName = account.name.emojify(account.emojis, binding.mutedUserDisplayName, animateEmojis) val emojifiedName = account.name.emojify(account.emojis, binding.mutedUserDisplayName, animateEmojis, true /* FIXME */)
binding.mutedUserDisplayName.text = emojifiedName binding.mutedUserDisplayName.text = emojifiedName
val formattedUsername = context.getString(R.string.post_username_format, account.username) val formattedUsername = context.getString(R.string.post_username_format, account.username)

View File

@ -62,7 +62,7 @@ class AnnouncementAdapter(
val chips = holder.binding.chipGroup val chips = holder.binding.chipGroup
val addReactionChip = holder.binding.addReactionChip val addReactionChip = holder.binding.addReactionChip
val emojifiedText: CharSequence = item.content.parseAsMastodonHtml().emojify(item.emojis, text, animateEmojis) val emojifiedText: CharSequence = item.content.parseAsMastodonHtml().emojify(item.emojis, text, animateEmojis, true /* FIXME */)
setClickableText(text, emojifiedText, item.mentions, item.tags, listener) setClickableText(text, emojifiedText, item.mentions, item.tags, listener)

View File

@ -107,7 +107,7 @@ class ComposeAutoCompleteAdapter(
val accountResult = getItem(position) as AutocompleteResult.AccountResult val accountResult = getItem(position) as AutocompleteResult.AccountResult
val account = accountResult.account val account = accountResult.account
binding.username.text = context.getString(R.string.post_username_format, account.username) binding.username.text = context.getString(R.string.post_username_format, account.username)
binding.displayName.text = account.name.emojify(account.emojis, binding.displayName, animateEmojis) binding.displayName.text = account.name.emojify(account.emojis, binding.displayName, animateEmojis, true /* FIXME */)
val avatarRadius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius_42dp) val avatarRadius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius_42dp)
loadAvatar( loadAvatar(
account.avatar, account.avatar,

View File

@ -111,7 +111,8 @@ class ConversationsFragment :
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false), animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false), showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false),
showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia, showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia,
openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler,
bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true)
) )
adapter = ConversationAdapter(statusDisplayOptions, this) adapter = ConversationAdapter(statusDisplayOptions, this)

View File

@ -159,7 +159,8 @@ class PreferencesActivity :
} }
"statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars", "useBlurhash", "statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars", "useBlurhash",
"showSelfUsername", "showCardsInTimelines", "confirmReblogs", "confirmFavourites", "showSelfUsername", "showCardsInTimelines", "confirmReblogs", "confirmFavourites",
"enableSwipeForTabs", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR, PrefKeys.SHOW_STATS_INLINE -> { "enableSwipeForTabs", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR, PrefKeys.SHOW_STATS_INLINE,
PrefKeys.BIG_EMOJIS -> {
restartActivitiesOnBackPressedCallback.isEnabled = true restartActivitiesOnBackPressedCallback.isEnabled = true
} }
} }

View File

@ -194,6 +194,13 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
isSingleLineTitle = false isSingleLineTitle = false
} }
switchPreference {
setDefaultValue(true)
key = PrefKeys.BIG_EMOJIS
setTitle(R.string.pref_title_enable_big_emojis)
isSingleLineTitle = false
}
switchPreference { switchPreference {
setDefaultValue(true) setDefaultValue(true)
key = PrefKeys.USE_BLURHASH key = PrefKeys.USE_BLURHASH

View File

@ -111,7 +111,7 @@ class StatusViewHolder(
binding.statusContentWarningButton.hide() binding.statusContentWarningButton.hide()
binding.statusContentWarningDescription.hide() binding.statusContentWarningDescription.hide()
} else { } else {
val emojiSpoiler = viewdata.spoilerText.emojify(viewdata.status.emojis, binding.statusContentWarningDescription, statusDisplayOptions.animateEmojis) val emojiSpoiler = viewdata.spoilerText.emojify(viewdata.status.emojis, binding.statusContentWarningDescription, statusDisplayOptions.animateEmojis, statusDisplayOptions.bigEmojis)
binding.statusContentWarningDescription.text = emojiSpoiler binding.statusContentWarningDescription.text = emojiSpoiler
binding.statusContentWarningDescription.show() binding.statusContentWarningDescription.show()
binding.statusContentWarningButton.show() binding.statusContentWarningButton.show()
@ -147,7 +147,7 @@ class StatusViewHolder(
listener: LinkListener listener: LinkListener
) { ) {
if (expanded) { if (expanded) {
val emojifiedText = content.emojify(emojis, binding.statusContent, statusDisplayOptions.animateEmojis) val emojifiedText = content.emojify(emojis, binding.statusContent, statusDisplayOptions.animateEmojis, statusDisplayOptions.bigEmojis)
setClickableText(binding.statusContent, emojifiedText, mentions, tags, listener) setClickableText(binding.statusContent, emojifiedText, mentions, tags, listener)
} else { } else {
setClickableMentions(binding.statusContent, mentions, listener) setClickableMentions(binding.statusContent, mentions, listener)

View File

@ -159,7 +159,8 @@ class ReportStatusesFragment :
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false), animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false), showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false),
showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia, showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia,
openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler,
bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true)
) )
adapter = StatusesAdapter(statusDisplayOptions, viewModel.statusViewState, this) adapter = StatusesAdapter(statusDisplayOptions, viewModel.statusViewState, this)

View File

@ -90,7 +90,8 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false), animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false), showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false),
showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia, showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia,
openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler,
bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true)
) )
binding.searchRecyclerView.addItemDecoration(DividerItemDecoration(binding.searchRecyclerView.context, DividerItemDecoration.VERTICAL)) binding.searchRecyclerView.addItemDecoration(DividerItemDecoration(binding.searchRecyclerView.context, DividerItemDecoration.VERTICAL))

View File

@ -198,7 +198,8 @@ class TimelineFragment :
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false), animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false), showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false),
showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia, showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia,
openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler,
bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true)
) )
adapter = TimelinePagingAdapter( adapter = TimelinePagingAdapter(
statusDisplayOptions, statusDisplayOptions,

View File

@ -114,7 +114,8 @@ class ViewThreadFragment :
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false), animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false), showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false),
showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia, showSensitiveMedia = accountManager.activeAccount!!.alwaysShowSensitiveMedia,
openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler openSpoiler = accountManager.activeAccount!!.alwaysOpenSpoiler,
bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true)
) )
adapter = ThreadAdapter(statusDisplayOptions, this) adapter = ThreadAdapter(statusDisplayOptions, this)
} }

View File

@ -68,6 +68,7 @@ object PrefKeys {
const val ENABLE_SWIPE_FOR_TABS = "enableSwipeForTabs" const val ENABLE_SWIPE_FOR_TABS = "enableSwipeForTabs"
const val ANIMATE_CUSTOM_EMOJIS = "animateCustomEmojis" const val ANIMATE_CUSTOM_EMOJIS = "animateCustomEmojis"
const val SHOW_STATS_INLINE = "showStatsInline" const val SHOW_STATS_INLINE = "showStatsInline"
const val BIG_EMOJIS = "bigEmojis"
const val CUSTOM_TABS = "customTabs" const val CUSTOM_TABS = "customTabs"
const val WELLBEING_LIMITED_NOTIFICATIONS = "wellbeingModeLimitedNotifications" const val WELLBEING_LIMITED_NOTIFICATIONS = "wellbeingModeLimitedNotifications"

View File

@ -37,9 +37,10 @@ import java.util.regex.Pattern
* @receiver the text containing custom emojis * @receiver the text containing custom emojis
* @param emojis a list of the custom emojis (nullable for backward compatibility with old mastodon instances) * @param emojis a list of the custom emojis (nullable for backward compatibility with old mastodon instances)
* @param view a reference to the a view the emojis will be shown in (should be the TextView, but parents of the TextView are also acceptable) * @param view a reference to the a view the emojis will be shown in (should be the TextView, but parents of the TextView are also acceptable)
* @param bigEmojis whether custom emojis should be displayed bigger (should be used only in the status content)
* @return the text with the shortcodes replaced by EmojiSpans * @return the text with the shortcodes replaced by EmojiSpans
*/ */
fun CharSequence.emojify(emojis: List<Emoji>?, view: View, animate: Boolean): CharSequence { fun CharSequence.emojify(emojis: List<Emoji>?, view: View, animate: Boolean, bigEmojis: Boolean = false): CharSequence {
if (emojis.isNullOrEmpty()) { if (emojis.isNullOrEmpty()) {
return this return this
} }
@ -51,7 +52,11 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View, animate: Boolean): Ch
.matcher(this) .matcher(this)
while (matcher.find()) { while (matcher.find()) {
val span = EmojiSpan(WeakReference(view)) val span = if (bigEmojis) {
BigEmojiSpan(WeakReference(view))
} else {
EmojiSpan(WeakReference(view))
}
builder.setSpan(span, matcher.start(), matcher.end(), 0) builder.setSpan(span, matcher.start(), matcher.end(), 0)
Glide.with(view) Glide.with(view)
@ -63,7 +68,7 @@ fun CharSequence.emojify(emojis: List<Emoji>?, view: View, animate: Boolean): Ch
return builder return builder
} }
class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan() { open class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan() {
var imageDrawable: Drawable? = null var imageDrawable: Drawable? = null
override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int { override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
@ -85,7 +90,7 @@ class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan()
canvas.save() canvas.save()
// start with a width relative to the text size // start with a width relative to the text size
var emojiWidth = paint.textSize * 1.1 var emojiWidth = getSize(paint, text, start, end, null).toDouble()
// calculate the height, keeping the aspect ratio correct // calculate the height, keeping the aspect ratio correct
val drawableWidth = drawable.intrinsicWidth val drawableWidth = drawable.intrinsicWidth
@ -142,3 +147,21 @@ class EmojiSpan(val viewWeakReference: WeakReference<View>) : ReplacementSpan()
} }
} }
} }
class BigEmojiSpan(viewWeakReference: WeakReference<View>)
: EmojiSpan(viewWeakReference) {
override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
if (fm != null) {
/* update FontMetricsInt or otherwise span does not get drawn when
* it covers the whole text */
val metrics = paint.fontMetricsInt
fm.top = (metrics.top * 1.3f).toInt()
fm.ascent = (metrics.ascent * 1.3f).toInt()
fm.descent = (metrics.descent * 2.0f).toInt()
fm.bottom = (metrics.bottom * 3.5f).toInt()
}
return (paint.textSize * 2.0).toInt()
}
}

View File

@ -47,7 +47,9 @@ data class StatusDisplayOptions(
@get:JvmName("showSensitiveMedia") @get:JvmName("showSensitiveMedia")
val showSensitiveMedia: Boolean, val showSensitiveMedia: Boolean,
@get:JvmName("openSpoiler") @get:JvmName("openSpoiler")
val openSpoiler: Boolean val openSpoiler: Boolean,
@get:JvmName("bigEmojis")
val bigEmojis: Boolean,
) { ) {
/** /**
@ -91,6 +93,9 @@ data class StatusDisplayOptions(
PrefKeys.ALWAYS_OPEN_SPOILER -> copy( PrefKeys.ALWAYS_OPEN_SPOILER -> copy(
openSpoiler = account.alwaysOpenSpoiler openSpoiler = account.alwaysOpenSpoiler
) )
PrefKeys.BIG_EMOJIS -> copy (
bigEmojis = preferences.getBoolean(key, true)
)
else -> { this } else -> { this }
} }
@ -107,7 +112,8 @@ data class StatusDisplayOptions(
PrefKeys.MEDIA_PREVIEW_ENABLED, PrefKeys.MEDIA_PREVIEW_ENABLED,
PrefKeys.SHOW_BOT_OVERLAY, PrefKeys.SHOW_BOT_OVERLAY,
PrefKeys.USE_BLURHASH, PrefKeys.USE_BLURHASH,
PrefKeys.WELLBEING_HIDE_STATS_POSTS PrefKeys.WELLBEING_HIDE_STATS_POSTS,
PrefKeys.BIG_EMOJIS,
) )
fun from(preferences: SharedPreferences, account: AccountEntity) = StatusDisplayOptions( fun from(preferences: SharedPreferences, account: AccountEntity) = StatusDisplayOptions(
@ -123,7 +129,8 @@ data class StatusDisplayOptions(
hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false), hideStats = preferences.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false),
showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false), showStatsInline = preferences.getBoolean(PrefKeys.SHOW_STATS_INLINE, false),
showSensitiveMedia = account.alwaysShowSensitiveMedia, showSensitiveMedia = account.alwaysShowSensitiveMedia,
openSpoiler = account.alwaysOpenSpoiler openSpoiler = account.alwaysOpenSpoiler,
bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true),
) )
} }
} }

View File

@ -318,7 +318,7 @@ class StatusViewHelper(private val itemView: View) {
val percent = calculatePercent(options[i].votesCount, poll.votersCount, poll.votesCount) val percent = calculatePercent(options[i].votesCount, poll.votersCount, poll.votesCount)
val pollOptionText = buildDescription(options[i].title, percent, options[i].voted, pollResults[i].context) val pollOptionText = buildDescription(options[i].title, percent, options[i].voted, pollResults[i].context)
pollResults[i].text = pollOptionText.emojify(emojis, pollResults[i], animateEmojis) pollResults[i].text = pollOptionText.emojify(emojis, pollResults[i], animateEmojis, true /* FIXME */)
pollResults[i].visibility = View.VISIBLE pollResults[i].visibility = View.VISIBLE
val level = percent * 100 val level = percent * 100

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pref_title_enable_big_emojis">Enable bigger custom emojis</string>
</resources>