From f6b46f921cd8151a2eb5c503b653b41dcbc34e43 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Mon, 2 Aug 2021 12:01:14 -0300 Subject: [PATCH] Fix issue where emojis would not appear on app launch. --- .../components/emoji/EmojiProvider.java | 49 +++++++++++++------ .../securesms/emoji/EmojiPageCache.kt | 13 +++-- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java index fa5070b662..be44e9dd12 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java @@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.emoji.EmojiPageCache; import org.thoughtcrime.securesms.emoji.EmojiSource; import org.thoughtcrime.securesms.util.DeviceProperties; import org.thoughtcrime.securesms.util.FutureTaskListener; +import org.thoughtcrime.securesms.util.ListenableFutureTask; import java.util.concurrent.ExecutionException; @@ -52,7 +53,7 @@ class EmojiProvider { SpannableStringBuilder builder = new SpannableStringBuilder(text); for (EmojiParser.Candidate candidate : matches) { - Drawable drawable = getEmojiDrawable(tv.getContext(), candidate.getDrawInfo()); + Drawable drawable = getEmojiDrawable(tv.getContext(), candidate.getDrawInfo(), tv::requestLayout); if (drawable != null) { builder.setSpan(new EmojiSpan(drawable, tv), candidate.getStartIndex(), candidate.getEndIndex(), @@ -65,10 +66,17 @@ class EmojiProvider { static @Nullable Drawable getEmojiDrawable(@NonNull Context context, @Nullable CharSequence emoji) { EmojiDrawInfo drawInfo = EmojiSource.getLatest().getEmojiTree().getEmoji(emoji, 0, emoji.length()); - return getEmojiDrawable(context, drawInfo); + return getEmojiDrawable(context, drawInfo, null); } - private static @Nullable Drawable getEmojiDrawable(@NonNull Context context, @Nullable EmojiDrawInfo drawInfo) { + /** + * Gets an EmojiDrawable from the Page Cache + * + * @param context Context object used in reading and writing from disk + * @param drawInfo Information about the emoji being displayed + * @param onEmojiLoaded Runnable which will trigger when an emoji is loaded from disk + */ + private static @Nullable Drawable getEmojiDrawable(@NonNull Context context, @Nullable EmojiDrawInfo drawInfo, @Nullable Runnable onEmojiLoaded) { if (drawInfo == null) { return null; } @@ -77,19 +85,30 @@ class EmojiProvider { final EmojiSource source = EmojiSource.getLatest(); final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale); - EmojiPageCache.INSTANCE - .load(context, drawInfo.getPage(), lowMemoryDecodeScale) - .addListener(new FutureTaskListener() { - @Override - public void onSuccess(Bitmap result) { - ThreadUtil.runOnMain(() -> drawable.setBitmap(result)); - } + EmojiPageCache.LoadResult loadResult = EmojiPageCache.INSTANCE.load(context, drawInfo.getPage(), lowMemoryDecodeScale); - @Override - public void onFailure(ExecutionException exception) { - Log.d(TAG, "Failed to load emoji bitmap resource", exception); - } - }); + if (loadResult instanceof EmojiPageCache.LoadResult.Immediate) { + ThreadUtil.runOnMain(() -> drawable.setBitmap(((EmojiPageCache.LoadResult.Immediate) loadResult).getBitmap())); + } else if (loadResult instanceof EmojiPageCache.LoadResult.Async) { + ((EmojiPageCache.LoadResult.Async) loadResult).getTask().addListener(new FutureTaskListener() { + @Override + public void onSuccess(Bitmap result) { + ThreadUtil.runOnMain(() -> { + drawable.setBitmap(result); + if (onEmojiLoaded != null) { + onEmojiLoaded.run(); + } + }); + } + + @Override + public void onFailure(ExecutionException exception) { + Log.d(TAG, "Failed to load emoji bitmap resource", exception); + } + }); + } else { + throw new IllegalStateException("Unexpected subclass " + loadResult.getClass()); + } return drawable; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiPageCache.kt b/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiPageCache.kt index 32564f1d7c..b29d19d919 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiPageCache.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/emoji/EmojiPageCache.kt @@ -21,15 +21,15 @@ object EmojiPageCache { private val tasks: HashMap> = hashMapOf() @MainThread - fun load(context: Context, emojiPage: EmojiPage, inSampleSize: Int): ListenableFutureTask { + fun load(context: Context, emojiPage: EmojiPage, inSampleSize: Int): LoadResult { val applicationContext = context.applicationContext val emojiPageRequest = EmojiPageRequest(emojiPage, inSampleSize) val bitmap: Bitmap? = cache[emojiPageRequest] val task: ListenableFutureTask? = tasks[emojiPageRequest] return when { - bitmap != null -> ListenableFutureTask(bitmap) - task != null -> task + bitmap != null -> LoadResult.Immediate(bitmap) + task != null -> LoadResult.Async(task) else -> { val newTask = ListenableFutureTask { try { @@ -56,7 +56,7 @@ object EmojiPageCache { } } - newTask + LoadResult.Async(newTask) } } } @@ -75,4 +75,9 @@ object EmojiPageCache { } private data class EmojiPageRequest(val emojiPage: EmojiPage, val inSampleSize: Int) + + sealed class LoadResult { + data class Immediate(val bitmap: Bitmap) : LoadResult() + data class Async(val task: ListenableFutureTask) : LoadResult() + } }