Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use system emoji uniformly accross app when system emoji option is enabled #13327

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle.kts
Expand Up @@ -511,6 +511,7 @@ dependencies {
implementation(libs.androidx.profileinstaller)
implementation(libs.androidx.asynclayoutinflater)
implementation(libs.androidx.asynclayoutinflater.appcompat)
implementation(libs.androidx.emoji2)
implementation(libs.firebase.messaging) {
exclude(group = "com.google.firebase", module = "firebase-core")
exclude(group = "com.google.firebase", module = "firebase-analytics")
Expand Down
Expand Up @@ -42,11 +42,10 @@ public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EmojiTextView, 0, 0);
boolean forceCustom = a.getBoolean(R.styleable.EmojiTextView_emoji_forceCustom, false);
boolean jumboEmoji = a.getBoolean(R.styleable.EmojiTextView_emoji_forceJumbo, false);
a.recycle();

if (!isInEditMode() && (forceCustom || !SignalStore.settings().isPreferSystemEmoji())) {
if (!isInEditMode() && !SignalStore.settings().isPreferSystemEmoji()) {
setFilters(appendEmojiFilter(this.getFilters(), jumboEmoji));
setEmojiCompatEnabled(false);
}
Expand Down
Expand Up @@ -23,6 +23,7 @@
import org.thoughtcrime.securesms.emoji.EmojiPageCache;
import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.emoji.JumboEmoji;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.DeviceProperties;
import org.thoughtcrime.securesms.util.FutureTaskListener;

Expand Down Expand Up @@ -121,6 +122,10 @@ public class EmojiProvider {
return null;
}

if (SignalStore.settings().isPreferSystemEmoji()) {
return new SystemEmojiDrawable(drawInfo.getEmoji());
}

final int lowMemoryDecodeScale = DeviceProperties.isLowMemoryDevice(context) ? 2 : 1;
final EmojiSource source = EmojiSource.getLatest();
final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale);
Expand Down Expand Up @@ -202,6 +207,10 @@ public void onFailure(ExecutionException exception) {
return null;
}

if (SignalStore.settings().isPreferSystemEmoji()) {
return new SystemEmojiDrawable(drawInfo.getEmoji());
}

final int lowMemoryDecodeScale = DeviceProperties.isLowMemoryDevice(context) ? 2 : 1;
final EmojiSource source = EmojiSource.getLatest();
final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale);
Expand Down
Expand Up @@ -57,7 +57,6 @@ public class EmojiTextView extends AppCompatTextView {
private static final char ELLIPSIS = '…';
private static final float JUMBOMOJI_SCALE = 0.8f;

private boolean forceCustom;
private CharSequence previousText;
private BufferType previousBufferType;
private TransformationMethod previousTransformationMethod;
Expand Down Expand Up @@ -93,7 +92,6 @@ public EmojiTextView(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EmojiTextView, 0, 0);
scaleEmojis = a.getBoolean(R.styleable.EmojiTextView_scaleEmojis, false);
maxLength = a.getInteger(R.styleable.EmojiTextView_emoji_maxLength, -1);
forceCustom = a.getBoolean(R.styleable.EmojiTextView_emoji_forceCustom, false);
renderMentions = a.getBoolean(R.styleable.EmojiTextView_emoji_renderMentions, true);
measureLastLine = a.getBoolean(R.styleable.EmojiTextView_measureLastLine, false);
forceJumboEmoji = a.getBoolean(R.styleable.EmojiTextView_emoji_forceJumbo, false);
Expand Down Expand Up @@ -445,7 +443,7 @@ private boolean unchanged(CharSequence text, CharSequence overflowText, BufferTy
}

private boolean useSystemEmoji() {
return isInEditMode() || (!forceCustom && SignalStore.settings().isPreferSystemEmoji());
return isInEditMode() || SignalStore.settings().isPreferSystemEmoji();
}

@Override
Expand Down
@@ -0,0 +1,69 @@
package org.thoughtcrime.securesms.components.emoji

import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Matrix
import android.graphics.PixelFormat
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import androidx.core.graphics.toRectF
import androidx.core.graphics.withMatrix
import androidx.emoji2.text.EmojiCompat

/**
* [Drawable] that renders an emoji via the system font for available glyphs and EmojiCompat for
* missing glyphs.
*/
class SystemEmojiDrawable(emoji: CharSequence) : Drawable() {

private val emojiLayout: StaticLayout = getStaticLayout(getProcessedEmoji(emoji))
private val transform: Matrix = Matrix()

override fun onBoundsChange(bounds: Rect) {
super.onBoundsChange(bounds)
transform.setRectToRect(emojiLayout.getBounds(), bounds.toRectF(), Matrix.ScaleToFit.CENTER)
}

override fun draw(canvas: Canvas) {
canvas.withMatrix(transform) {
emojiLayout.draw(canvas)
}
}

override fun setAlpha(alpha: Int) {}

override fun setColorFilter(colorFilter: ColorFilter?) {}

@Deprecated(
"Deprecated in Java",
ReplaceWith("PixelFormat.TRANSLUCENT", "android.graphics.PixelFormat")
)
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT

companion object {
private val textPaint: TextPaint = TextPaint()

private fun getStaticLayout(emoji: CharSequence): StaticLayout =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
StaticLayout.Builder.obtain(emoji, 0, emoji.length, textPaint, Int.MAX_VALUE).build()
} else {
@Suppress("DEPRECATION")
StaticLayout(emoji, textPaint, Int.MAX_VALUE, Layout.Alignment.ALIGN_NORMAL, 0f, 0f, true)
}

private fun getProcessedEmoji(emoji: CharSequence): CharSequence =
try {
EmojiCompat.get().process(emoji) ?: emoji
} catch (e: IllegalStateException) {
emoji
}

private fun StaticLayout.getBounds(): RectF =
RectF(getLineLeft(0), 0f, getLineRight(0), getLineDescent(0) - getLineAscent(0).toFloat())
}
}
Expand Up @@ -2,4 +2,4 @@ package org.thoughtcrime.securesms.components.emoji.parsing

import org.thoughtcrime.securesms.emoji.EmojiPage

data class EmojiDrawInfo(val page: EmojiPage, val index: Int, private val emoji: String, val rawEmoji: String?, val jumboSheet: String?)
data class EmojiDrawInfo(val page: EmojiPage, val index: Int, val emoji: String, val rawEmoji: String?, val jumboSheet: String?)
1 change: 0 additions & 1 deletion app/src/main/res/layout/avatar_picker_fragment.xml
Expand Up @@ -34,7 +34,6 @@
android:layout_height="0dp"
android:fontFamily="sans-serif-medium"
android:gravity="center"
app:emoji_forceCustom="true"
app:emoji_forceJumbo="true"
app:layout_constraintBottom_toBottomOf="@id/avatar_picker_item_image"
app:layout_constraintEnd_toEndOf="@id/avatar_picker_item_image"
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/res/layout/avatar_picker_item.xml
Expand Up @@ -24,8 +24,7 @@
android:fontFamily="sans-serif-medium"
android:gravity="center"
tools:text="AF"
app:emoji_forceJumbo="true"
app:emoji_forceCustom="true"/>
app:emoji_forceJumbo="true"/>

<View
android:id="@+id/avatar_picker_item_fader"
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/contact_search_item.xml
Expand Up @@ -79,7 +79,6 @@
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
android:textDirection="ltr"
app:emoji_forceCustom="true"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/label"
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/contact_search_story_item.xml
Expand Up @@ -94,7 +94,6 @@
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
android:textDirection="ltr"
app:emoji_forceCustom="true"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/name"
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/contact_search_unknown_item.xml
Expand Up @@ -79,7 +79,6 @@
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
android:textDirection="ltr"
app:emoji_forceCustom="true"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/check_box"
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/conversation_header_view.xml
Expand Up @@ -81,7 +81,6 @@
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textAppearance="@style/Signal.Text.MessageRequest.Subtitle"
app:emoji_forceCustom="true"
app:layout_constraintBottom_toTopOf="@id/message_request_divider"
app:layout_constraintTop_toBottomOf="@id/message_request_title"
tools:text="Hangin' on the web" />
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/res/layout/edit_about_fragment.xml
Expand Up @@ -45,8 +45,7 @@
android:maxLines="1"
app:layout_constraintTop_toBottomOf="@id/toolbar"
app:layout_constraintStart_toEndOf="@id/edit_about_emoji"
app:layout_constraintEnd_toStartOf="@id/edit_about_clear"
app:emoji_forceCustom="true"/>
app:layout_constraintEnd_toStartOf="@id/edit_about_clear"/>

<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/edit_about_clear"
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/res/layout/edit_profile_fragment.xml
Expand Up @@ -265,7 +265,6 @@
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:textAlignment="viewStart"
app:emoji_forceCustom="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/manage_profile_about_icon"
Expand Down Expand Up @@ -304,7 +303,6 @@
android:layout_marginStart="24dp"
android:text="@string/ManageProfileFragment_badges"
android:textAlignment="viewStart"
app:emoji_forceCustom="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/manage_profile_badges_icon"
Expand Down
Expand Up @@ -64,8 +64,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences"
android:maxLines="1"
app:emoji_forceCustom="true" />
android:maxLines="1" />

</com.google.android.material.textfield.TextInputLayout>

Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/group_recipient_list_item.xml
Expand Up @@ -74,7 +74,6 @@
android:textAlignment="viewStart"
android:textAppearance="@style/Signal.Text.BodyMedium"
android:textColor="@color/signal_text_secondary"
app:emoji_forceCustom="true"
app:layout_constraintBottom_toBottomOf="@+id/recipient_avatar"
app:layout_constraintEnd_toStartOf="@+id/admin"
app:layout_constraintHorizontal_bias="0"
Expand Down
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:viewBindingIgnore="true"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
Expand All @@ -20,8 +19,7 @@
android:layout_height="20dp"
android:layout_marginEnd="4dp"
android:gravity="center"
android:textStyle="bold"
app:emoji_forceCustom="true" />
android:textStyle="bold" />

<TextView
android:id="@+id/reactions_bottom_view_emoji_item_text"
Expand Down
Expand Up @@ -51,7 +51,6 @@
android:layout_marginEnd="16dp"
android:gravity="center"
android:textSize="22dp"
app:emoji_forceCustom="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/layout/recipient_bottom_sheet.xml
Expand Up @@ -82,7 +82,6 @@
android:layout_marginEnd="@dimen/dsl_settings_gutter"
android:gravity="center"
android:textColor="@color/signal_text_secondary"
app:emoji_forceCustom="true"
app:layout_constraintTop_toBottomOf="@id/rbs_full_name"
tools:text="🕷🕷🕷 Hangin' on the web 🕷🕷🕷" />

Expand Down
Expand Up @@ -41,7 +41,6 @@
app:layout_constraintEnd_toEndOf="@id/avatar_picker_item_image"
app:layout_constraintStart_toStartOf="@id/avatar_picker_item_image"
app:layout_constraintTop_toTopOf="@id/avatar_picker_item_image"
app:emoji_forceCustom="true"
tools:ignore="SpUsage"
tools:text="AF" />
</androidx.constraintlayout.widget.ConstraintLayout>
Expand Down
1 change: 0 additions & 1 deletion app/src/main/res/values/attrs.xml
Expand Up @@ -149,7 +149,6 @@
<attr name="measureLastLine" format="boolean" />
<attr name="scaleEmojis" format="boolean" />
<attr name="emoji_maxLength" format="integer" />
<attr name="emoji_forceCustom" format="boolean" />
<attr name="emoji_renderMentions" format="boolean" />
<attr name="emoji_forceJumbo" format="boolean" />
<attr name="emoji_renderSpoilers" format="boolean" />
Expand Down
1 change: 1 addition & 0 deletions dependencies.gradle.kts
Expand Up @@ -94,6 +94,7 @@ dependencyResolutionManagement {
library("androidx-profileinstaller", "androidx.profileinstaller:profileinstaller:1.2.2")
library("androidx-asynclayoutinflater", "androidx.asynclayoutinflater:asynclayoutinflater:1.1.0-alpha01")
library("androidx-asynclayoutinflater-appcompat", "androidx.asynclayoutinflater:asynclayoutinflater-appcompat:1.1.0-alpha01")
library("androidx-emoji2", "androidx.emoji2:emoji2:1.4.0")

// Material
library("material-material", "com.google.android.material:material:1.8.0")
Expand Down