mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-24 02:39:55 +01:00
Fix emoji avatar missing after edit.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ open class SimpleEmojiTextView @JvmOverloads constructor(
|
||||
} else {
|
||||
EmojiProvider.emojify(newCandidates, newContent, this)
|
||||
}
|
||||
bufferType = BufferType.SPANNABLE
|
||||
super.setText(newText, type)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user