Fix emoji avatar missing after edit.

This commit is contained in:
Lucio Maciel
2021-09-16 13:40:51 -03:00
committed by Alex Hart
parent 5e968eb831
commit 18ba5fa291
15 changed files with 181 additions and 69 deletions

View File

@@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.util.AvatarUtil;
import org.thoughtcrime.securesms.util.BlurTransformation;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.ArrayList;
import java.util.List;
@@ -207,8 +208,8 @@ public final class AvatarImageView extends AppCompatImageView {
this.chatColors = chatColors;
recipientContactPhoto = photo;
Drawable fallbackContactPhotoDrawable = size == SIZE_SMALL ? photo.recipient.getSmallFallbackContactPhotoDrawable(getContext(), inverted, fallbackPhotoProvider)
: photo.recipient.getFallbackContactPhotoDrawable(getContext(), inverted, fallbackPhotoProvider);
Drawable fallbackContactPhotoDrawable = size == SIZE_SMALL ? photo.recipient.getSmallFallbackContactPhotoDrawable(getContext(), inverted, fallbackPhotoProvider, ViewUtil.getWidth(this))
: photo.recipient.getFallbackContactPhotoDrawable(getContext(), inverted, fallbackPhotoProvider, ViewUtil.getWidth(this));
if (fixedSizeTarget != null) {
requestManager.clear(fixedSizeTarget);

View File

@@ -26,13 +26,15 @@ import org.thoughtcrime.securesms.util.FutureTaskListener;
import org.thoughtcrime.securesms.util.ListenableFutureTask;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
class EmojiProvider {
public class EmojiProvider {
private static final String TAG = Log.tag(EmojiProvider.class);
private static final Paint PAINT = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
static @Nullable EmojiParser.CandidateList getCandidates(@Nullable CharSequence text) {
public static @Nullable EmojiParser.CandidateList getCandidates(@Nullable CharSequence text) {
if (text == null) return null;
return new EmojiParser(EmojiSource.getLatest().getEmojiTree()).findCandidates(text);
}
@@ -64,6 +66,32 @@ class EmojiProvider {
return builder;
}
public static @Nullable Spannable emojify(@NonNull Context context,
@Nullable EmojiParser.CandidateList matches,
@Nullable CharSequence text,
@NonNull Paint paint,
boolean synchronous)
{
if (matches == null || text == null) return null;
SpannableStringBuilder builder = new SpannableStringBuilder(text);
for (EmojiParser.Candidate candidate : matches) {
Drawable drawable;
if (synchronous) {
drawable = getEmojiDrawableSync(context, candidate.getDrawInfo());
} else {
drawable = getEmojiDrawable(context, candidate.getDrawInfo(), null);
}
if (drawable != null) {
builder.setSpan(new EmojiSpan(context, drawable, paint), candidate.getStartIndex(), candidate.getEndIndex(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
return builder;
}
static @Nullable Drawable getEmojiDrawable(@NonNull Context context, @Nullable CharSequence emoji) {
EmojiDrawInfo drawInfo = EmojiSource.getLatest().getEmojiTree().getEmoji(emoji, 0, emoji.length());
return getEmojiDrawable(context, drawInfo, null);
@@ -113,6 +141,43 @@ class EmojiProvider {
return drawable;
}
/**
* Gets an EmojiDrawable from the Page Cache synchronously
*
* @param context Context object used in reading and writing from disk
* @param drawInfo Information about the emoji being displayed
*/
private static @Nullable Drawable getEmojiDrawableSync(@NonNull Context context, @Nullable EmojiDrawInfo drawInfo) {
ThreadUtil.assertNotMainThread();
if (drawInfo == null) {
return null;
}
final int lowMemoryDecodeScale = DeviceProperties.isLowMemoryDevice(context) ? 2 : 1;
final EmojiSource source = EmojiSource.getLatest();
final EmojiDrawable drawable = new EmojiDrawable(source, drawInfo, lowMemoryDecodeScale);
EmojiPageCache.LoadResult loadResult = EmojiPageCache.INSTANCE.load(context, drawInfo.getPage(), lowMemoryDecodeScale);
Bitmap bitmap = null;
if (loadResult instanceof EmojiPageCache.LoadResult.Immediate) {
Log.d(TAG, "Cached emoji page: " + drawInfo.getPage().getUri().toString());
bitmap = ((EmojiPageCache.LoadResult.Immediate) loadResult).getBitmap();
} else if (loadResult instanceof EmojiPageCache.LoadResult.Async) {
Log.d(TAG, "Loading emoji page: " + drawInfo.getPage().getUri().toString());
try {
bitmap = ((EmojiPageCache.LoadResult.Async) loadResult).getTask().get(2, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException exception) {
Log.d(TAG, "Failed to load emoji bitmap resource", exception);
}
} else {
throw new IllegalStateException("Unexpected subclass " + loadResult.getClass());
}
drawable.setBitmap(bitmap);
return drawable;
}
static final class EmojiDrawable extends Drawable {
private final float intrinsicWidth;
private final float intrinsicHeight;
@@ -160,7 +225,6 @@ class EmojiProvider {
}
public void setBitmap(Bitmap bitmap) {
ThreadUtil.assertMainThread();
if (bmp == null || !bmp.sameAs(bitmap)) {
bmp = bitmap;
invalidateSelf();

View File

@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.components.emoji;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
@@ -25,6 +26,15 @@ public class EmojiSpan extends AnimatingImageSpan {
getDrawable().setBounds(0, 0, size, size);
}
public EmojiSpan(@NonNull Context context, @NonNull Drawable drawable, @NonNull Paint paint) {
super(drawable, null);
fontMetrics = paint.getFontMetricsInt();
size = fontMetrics != null ? Math.abs(fontMetrics.descent) + Math.abs(fontMetrics.ascent)
: context.getResources().getDimensionPixelSize(R.dimen.conversation_item_body_text_size);
getDrawable().setBounds(0, 0, size, size);
}
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
if (fm != null && this.fontMetrics != null) {
@@ -48,6 +58,7 @@ public class EmojiSpan extends AnimatingImageSpan {
int height = bottom - top;
int centeringMargin = (height - size) / 2;
int adjustedMargin = (int) (centeringMargin * SHIFT_FACTOR);
int adjustedBottom = bottom - adjustedMargin;
super.draw(canvas, text, start, end, x, top, y, bottom - adjustedMargin, paint);
}
}

View File

@@ -33,6 +33,7 @@ open class SimpleEmojiTextView @JvmOverloads constructor(
} else {
EmojiProvider.emojify(newCandidates, newContent, this)
}
bufferType = BufferType.SPANNABLE
super.setText(newText, type)
}
}