mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 00:29:11 +01:00
Fix member label emoji ignoring use system emoji preference.
This commit is contained in:
committed by
Cody Henthorne
parent
fa2b0aedb0
commit
7e605fb6de
@@ -5,11 +5,14 @@
|
||||
|
||||
package org.thoughtcrime.securesms.components.emoji
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.text.InlineTextContent
|
||||
import androidx.compose.foundation.text.appendInlineContent
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -21,10 +24,12 @@ import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.Placeholder
|
||||
import androidx.compose.ui.text.PlaceholderVerticalAlign
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.thoughtcrime.securesms.components.emoji.parsing.EmojiParser
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
|
||||
/**
|
||||
* Applies Signal or System emoji to the given content based off user settings.
|
||||
@@ -34,6 +39,7 @@ import org.signal.core.ui.compose.Previews
|
||||
@Composable
|
||||
fun Emojifier(
|
||||
text: String,
|
||||
useSystemEmoji: Boolean = !LocalInspectionMode.current && SignalStore.settings.isPreferSystemEmoji,
|
||||
content: @Composable (AnnotatedString, Map<String, InlineTextContent>) -> Unit = { annotatedText, inlineContent ->
|
||||
Text(
|
||||
text = annotatedText,
|
||||
@@ -41,38 +47,56 @@ fun Emojifier(
|
||||
)
|
||||
}
|
||||
) {
|
||||
if (LocalInspectionMode.current) {
|
||||
if (useSystemEmoji) {
|
||||
content(buildAnnotatedString { append(text) }, emptyMap())
|
||||
return
|
||||
}
|
||||
|
||||
val context = LocalContext.current
|
||||
val candidates = remember(text) { EmojiProvider.getCandidates(text) }
|
||||
val candidateMap: Map<String, InlineTextContent> = remember(text) {
|
||||
candidates?.associate { candidate ->
|
||||
candidate.drawInfo.emoji to InlineTextContent(placeholder = Placeholder(20.sp, 20.sp, PlaceholderVerticalAlign.TextCenter)) {
|
||||
Image(
|
||||
painter = rememberDrawablePainter(EmojiProvider.getEmojiDrawable(context, candidate.drawInfo.emoji)),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
} ?: emptyMap()
|
||||
val fontSize = LocalTextStyle.current.fontSize
|
||||
|
||||
val foundEmojis: List<EmojiParser.Candidate> = remember(text) {
|
||||
EmojiProvider.getCandidates(text)?.list.orEmpty()
|
||||
}
|
||||
val inlineContentByEmoji: Map<String, InlineTextContent> = remember(text, fontSize) {
|
||||
foundEmojis.associate { it.drawInfo.emoji to createInlineContent(context, it.drawInfo.emoji, fontSize) }
|
||||
}
|
||||
|
||||
val annotatedString = buildAnnotatedString {
|
||||
append(text)
|
||||
val annotatedString = remember(text) { buildAnnotatedString(text, foundEmojis) }
|
||||
content(annotatedString, inlineContentByEmoji)
|
||||
}
|
||||
|
||||
candidates?.forEach {
|
||||
addStringAnnotation(
|
||||
tag = "EMOJI",
|
||||
annotation = it.drawInfo.emoji,
|
||||
start = it.startIndex,
|
||||
end = it.endIndex
|
||||
)
|
||||
private fun createInlineContent(context: Context, emoji: String, fontSize: TextUnit): InlineTextContent {
|
||||
return InlineTextContent(
|
||||
placeholder = Placeholder(width = fontSize, height = fontSize, PlaceholderVerticalAlign.TextCenter)
|
||||
) {
|
||||
Image(
|
||||
painter = rememberDrawablePainter(EmojiProvider.getEmojiDrawable(context, emoji)),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an [AnnotatedString] from [text], substituting each emoji in [foundEmojis] with an inline content placeholder.
|
||||
*/
|
||||
private fun buildAnnotatedString(
|
||||
text: String,
|
||||
foundEmojis: List<EmojiParser.Candidate>
|
||||
): AnnotatedString = buildAnnotatedString {
|
||||
var nextSegmentStartIndex = 0
|
||||
|
||||
foundEmojis.forEach { emoji ->
|
||||
if (emoji.startIndex > nextSegmentStartIndex) {
|
||||
append(text, start = nextSegmentStartIndex, end = emoji.startIndex)
|
||||
}
|
||||
appendInlineContent(emoji.drawInfo.emoji)
|
||||
nextSegmentStartIndex = emoji.endIndex
|
||||
}
|
||||
|
||||
content(annotatedString, candidateMap)
|
||||
if (nextSegmentStartIndex < text.length) {
|
||||
append(text, start = nextSegmentStartIndex, end = text.length)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -41,6 +41,9 @@ public class EmojiParser {
|
||||
this.emojiTree = emojiTree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ordered list of every emoji occurrence found in the given text.
|
||||
*/
|
||||
public @NonNull CandidateList findCandidates(@Nullable CharSequence text) {
|
||||
List<Candidate> results = new LinkedList<>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user