mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-25 14:47:20 +00:00
Fix flickering emoji and periodic emoji vanishings
Fixes #3231 Closes #3233 // FREEBIE
This commit is contained in:
parent
1251629997
commit
a3007c5906
@ -1,5 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.components.emoji;
|
package org.thoughtcrime.securesms.components.emoji;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@ -10,8 +11,9 @@ import android.graphics.Rect;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.Drawable.Callback;
|
import android.graphics.drawable.Drawable.Callback;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Handler;
|
import android.os.Build.VERSION;
|
||||||
import android.os.Looper;
|
import android.os.Build.VERSION_CODES;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -28,7 +30,6 @@ import org.thoughtcrime.securesms.util.Util;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -36,8 +37,7 @@ import java.util.regex.Pattern;
|
|||||||
public class EmojiProvider {
|
public class EmojiProvider {
|
||||||
private static final String TAG = EmojiProvider.class.getSimpleName();
|
private static final String TAG = EmojiProvider.class.getSimpleName();
|
||||||
private static volatile EmojiProvider instance = null;
|
private static volatile EmojiProvider instance = null;
|
||||||
private static final Paint paint = new Paint();
|
private static final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
|
||||||
static { paint.setFilterBitmap(true); }
|
|
||||||
|
|
||||||
private final SparseArray<DrawInfo> offsets = new SparseArray<>();
|
private final SparseArray<DrawInfo> offsets = new SparseArray<>();
|
||||||
|
|
||||||
@ -57,7 +57,6 @@ public class EmojiProvider {
|
|||||||
private final double drawWidth;
|
private final double drawWidth;
|
||||||
private final double drawHeight;
|
private final double drawHeight;
|
||||||
private final double verticalPad;
|
private final double verticalPad;
|
||||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
|
|
||||||
public static EmojiProvider getInstance(Context context) {
|
public static EmojiProvider getInstance(Context context) {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
@ -114,7 +113,7 @@ public class EmojiProvider {
|
|||||||
drawable.setBounds(0, 0, (int)(drawWidth * size), (int)(drawHeight * size));
|
drawable.setBounds(0, 0, (int)(drawWidth * size), (int)(drawHeight * size));
|
||||||
drawInfo.page.get().addListener(new FutureTaskListener<Bitmap>() {
|
drawInfo.page.get().addListener(new FutureTaskListener<Bitmap>() {
|
||||||
@Override public void onSuccess(final Bitmap result) {
|
@Override public void onSuccess(final Bitmap result) {
|
||||||
handler.post(new Runnable() {
|
Util.runOnMain(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
drawable.setBitmap(result);
|
drawable.setBitmap(result);
|
||||||
}
|
}
|
||||||
@ -129,10 +128,10 @@ public class EmojiProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class EmojiDrawable extends Drawable {
|
public class EmojiDrawable extends Drawable {
|
||||||
private final int index;
|
private final DrawInfo info;
|
||||||
private final double width;
|
private final double width;
|
||||||
private final double height;
|
private final double height;
|
||||||
private Bitmap bmp;
|
private Bitmap bmp;
|
||||||
|
|
||||||
@Override public int getIntrinsicWidth() {
|
@Override public int getIntrinsicWidth() {
|
||||||
return (int)width;
|
return (int)width;
|
||||||
@ -143,33 +142,38 @@ public class EmojiProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public EmojiDrawable(DrawInfo info, double width, double height) {
|
public EmojiDrawable(DrawInfo info, double width, double height) {
|
||||||
this.index = info.index;
|
this.info = info;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
if (bmp == null) return;
|
if (bmp == null) {
|
||||||
|
Log.w(TAG, "no-op draw(" + info.page + ", " + info.index + ")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Rect b = copyBounds();
|
final int row = info.index / EMOJI_PER_ROW;
|
||||||
|
final int row_index = info.index % EMOJI_PER_ROW;
|
||||||
final int row = index / EMOJI_PER_ROW;
|
|
||||||
final int row_index = index % EMOJI_PER_ROW;
|
|
||||||
|
|
||||||
canvas.drawBitmap(bmp,
|
canvas.drawBitmap(bmp,
|
||||||
new Rect((int)(row_index * width),
|
new Rect((int)(row_index * width),
|
||||||
(int)(row * height + row * verticalPad),
|
(int)(row * height + row * verticalPad),
|
||||||
(int)((row_index + 1) * width),
|
(int)((row_index + 1) * width),
|
||||||
(int)((row + 1) * height + row * verticalPad)),
|
(int)((row + 1) * height + row * verticalPad)),
|
||||||
b,
|
getBounds(),
|
||||||
paint);
|
paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(VERSION_CODES.HONEYCOMB_MR1)
|
||||||
public void setBitmap(Bitmap bitmap) {
|
public void setBitmap(Bitmap bitmap) {
|
||||||
Util.assertMainThread();
|
Util.assertMainThread();
|
||||||
bmp = bitmap;
|
Log.w(TAG, "setBitmap(" + info.page + ", " + info.index + ")");
|
||||||
invalidateSelf();
|
if (VERSION.SDK_INT < VERSION_CODES.HONEYCOMB_MR1 || bmp == null || !bmp.sameAs(bitmap)) {
|
||||||
|
bmp = bitmap;
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -264,5 +268,9 @@ public class EmojiProvider {
|
|||||||
throw new AssertionError("emoji sprite asset is corrupted or android decoding is broken");
|
throw new AssertionError("emoji sprite asset is corrupted or android decoding is broken");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public String toString() {
|
||||||
|
return Integer.toString(page);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.graphics.drawable.Drawable.Callback;
|
import android.graphics.drawable.Drawable.Callback;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
public class PostInvalidateCallback implements Callback {
|
public class PostInvalidateCallback implements Callback {
|
||||||
private final View view;
|
private final View view;
|
||||||
|
|
||||||
@ -12,7 +14,11 @@ public class PostInvalidateCallback implements Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public void invalidateDrawable(Drawable who) {
|
@Override public void invalidateDrawable(Drawable who) {
|
||||||
view.postInvalidate();
|
Util.runOnMain(new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
view.invalidate();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void scheduleDrawable(Drawable who, Runnable what, long when) {
|
@Override public void scheduleDrawable(Drawable who, Runnable what, long when) {
|
||||||
|
@ -296,8 +296,7 @@ public class BitmapUtil {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Looper.myLooper() == Looper.getMainLooper()) runnable.run();
|
Util.runOnMain(runnable);
|
||||||
else new Handler(Looper.getMainLooper()).post(runnable);
|
|
||||||
|
|
||||||
synchronized (result) {
|
synchronized (result) {
|
||||||
while (!created.get()) Util.wait(result, 0);
|
while (!created.get()) Util.wait(result, 0);
|
||||||
|
@ -21,10 +21,10 @@ import android.annotation.TargetApi;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Build.VERSION;
|
import android.os.Build.VERSION;
|
||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.provider.Telephony;
|
import android.provider.Telephony;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
@ -60,10 +60,11 @@ import ws.com.google.android.mms.pdu.CharacterSets;
|
|||||||
import ws.com.google.android.mms.pdu.EncodedStringValue;
|
import ws.com.google.android.mms.pdu.EncodedStringValue;
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
|
public static Handler handler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
public static String join(Collection<String> list, String delimiter) {
|
public static String join(Collection<String> list, String delimiter) {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
int i=0;
|
int i = 0;
|
||||||
|
|
||||||
for (String item : list) {
|
for (String item : list) {
|
||||||
result.append(item);
|
result.append(item);
|
||||||
@ -301,12 +302,21 @@ public class Util {
|
|||||||
return (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) || OutgoingLegacyMmsConnection.isConnectionPossible(context);
|
return (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) || OutgoingLegacyMmsConnection.isConnectionPossible(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isMainThread() {
|
||||||
|
return Looper.myLooper() == Looper.getMainLooper();
|
||||||
|
}
|
||||||
|
|
||||||
public static void assertMainThread() {
|
public static void assertMainThread() {
|
||||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
if (!isMainThread()) {
|
||||||
throw new AssertionError("Main-thread assertion failed.");
|
throw new AssertionError("Main-thread assertion failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void runOnMain(Runnable runnable) {
|
||||||
|
if (isMainThread()) runnable.run();
|
||||||
|
else handler.post(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean equals(@Nullable Object a, @Nullable Object b) {
|
public static boolean equals(@Nullable Object a, @Nullable Object b) {
|
||||||
return a == b || (a != null && a.equals(b));
|
return a == b || (a != null && a.equals(b));
|
||||||
}
|
}
|
||||||
@ -314,5 +324,4 @@ public class Util {
|
|||||||
public static int hashCode(@Nullable Object... objects) {
|
public static int hashCode(@Nullable Object... objects) {
|
||||||
return Arrays.hashCode(objects);
|
return Arrays.hashCode(objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user