kopia lustrzana https://github.com/ryukoposting/Signal-Android
Fix issue where emojis would not appear on app launch.
rodzic
5fef0494b1
commit
f6b46f921c
|
@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.emoji.EmojiPageCache;
|
||||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||||
import org.thoughtcrime.securesms.util.DeviceProperties;
|
import org.thoughtcrime.securesms.util.DeviceProperties;
|
||||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||||
|
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ class EmojiProvider {
|
||||||
SpannableStringBuilder builder = new SpannableStringBuilder(text);
|
SpannableStringBuilder builder = new SpannableStringBuilder(text);
|
||||||
|
|
||||||
for (EmojiParser.Candidate candidate : matches) {
|
for (EmojiParser.Candidate candidate : matches) {
|
||||||
Drawable drawable = getEmojiDrawable(tv.getContext(), candidate.getDrawInfo());
|
Drawable drawable = getEmojiDrawable(tv.getContext(), candidate.getDrawInfo(), tv::requestLayout);
|
||||||
|
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
builder.setSpan(new EmojiSpan(drawable, tv), candidate.getStartIndex(), candidate.getEndIndex(),
|
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) {
|
static @Nullable Drawable getEmojiDrawable(@NonNull Context context, @Nullable CharSequence emoji) {
|
||||||
EmojiDrawInfo drawInfo = EmojiSource.getLatest().getEmojiTree().getEmoji(emoji, 0, emoji.length());
|
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) {
|
if (drawInfo == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -77,19 +85,30 @@ class EmojiProvider {
|
||||||
final EmojiSource source = EmojiSource.getLatest();
|
final EmojiSource source = EmojiSource.getLatest();
|
||||||
final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale);
|
final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale);
|
||||||
|
|
||||||
EmojiPageCache.INSTANCE
|
EmojiPageCache.LoadResult loadResult = EmojiPageCache.INSTANCE.load(context, drawInfo.getPage(), lowMemoryDecodeScale);
|
||||||
.load(context, drawInfo.getPage(), lowMemoryDecodeScale)
|
|
||||||
.addListener(new FutureTaskListener<Bitmap>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Bitmap result) {
|
|
||||||
ThreadUtil.runOnMain(() -> drawable.setBitmap(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (loadResult instanceof EmojiPageCache.LoadResult.Immediate) {
|
||||||
public void onFailure(ExecutionException exception) {
|
ThreadUtil.runOnMain(() -> drawable.setBitmap(((EmojiPageCache.LoadResult.Immediate) loadResult).getBitmap()));
|
||||||
Log.d(TAG, "Failed to load emoji bitmap resource", exception);
|
} else if (loadResult instanceof EmojiPageCache.LoadResult.Async) {
|
||||||
}
|
((EmojiPageCache.LoadResult.Async) loadResult).getTask().addListener(new FutureTaskListener<Bitmap>() {
|
||||||
});
|
@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;
|
return drawable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,15 @@ object EmojiPageCache {
|
||||||
private val tasks: HashMap<EmojiPageRequest, ListenableFutureTask<Bitmap>> = hashMapOf()
|
private val tasks: HashMap<EmojiPageRequest, ListenableFutureTask<Bitmap>> = hashMapOf()
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
fun load(context: Context, emojiPage: EmojiPage, inSampleSize: Int): ListenableFutureTask<Bitmap> {
|
fun load(context: Context, emojiPage: EmojiPage, inSampleSize: Int): LoadResult {
|
||||||
val applicationContext = context.applicationContext
|
val applicationContext = context.applicationContext
|
||||||
val emojiPageRequest = EmojiPageRequest(emojiPage, inSampleSize)
|
val emojiPageRequest = EmojiPageRequest(emojiPage, inSampleSize)
|
||||||
val bitmap: Bitmap? = cache[emojiPageRequest]
|
val bitmap: Bitmap? = cache[emojiPageRequest]
|
||||||
val task: ListenableFutureTask<Bitmap>? = tasks[emojiPageRequest]
|
val task: ListenableFutureTask<Bitmap>? = tasks[emojiPageRequest]
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
bitmap != null -> ListenableFutureTask(bitmap)
|
bitmap != null -> LoadResult.Immediate(bitmap)
|
||||||
task != null -> task
|
task != null -> LoadResult.Async(task)
|
||||||
else -> {
|
else -> {
|
||||||
val newTask = ListenableFutureTask<Bitmap> {
|
val newTask = ListenableFutureTask<Bitmap> {
|
||||||
try {
|
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)
|
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<Bitmap>) : LoadResult()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue