mirror of https://github.com/NekoX-Dev/NekoX.git
1222 lines
48 KiB
Java
1222 lines
48 KiB
Java
package org.telegram.ui.Components;
|
|
|
|
import android.graphics.Canvas;
|
|
import android.graphics.ColorFilter;
|
|
import android.graphics.Paint;
|
|
import android.graphics.PixelFormat;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.PorterDuffColorFilter;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Looper;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
import android.util.LongSparseArray;
|
|
import android.util.SparseArray;
|
|
import android.view.View;
|
|
import android.view.animation.OvershootInterpolator;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
|
|
import org.telegram.SQLite.SQLiteCursor;
|
|
import org.telegram.SQLite.SQLiteDatabase;
|
|
import org.telegram.SQLite.SQLiteException;
|
|
import org.telegram.SQLite.SQLitePreparedStatement;
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.messenger.BuildVars;
|
|
import org.telegram.messenger.DocumentObject;
|
|
import org.telegram.messenger.FileLoader;
|
|
import org.telegram.messenger.FileLog;
|
|
import org.telegram.messenger.ImageLoader;
|
|
import org.telegram.messenger.ImageLocation;
|
|
import org.telegram.messenger.ImageReceiver;
|
|
import org.telegram.messenger.LiteMode;
|
|
import org.telegram.messenger.MessageObject;
|
|
import org.telegram.messenger.MessagesStorage;
|
|
import org.telegram.messenger.SharedConfig;
|
|
import org.telegram.messenger.SvgHelper;
|
|
import org.telegram.messenger.UserConfig;
|
|
import org.telegram.tgnet.ConnectionsManager;
|
|
import org.telegram.tgnet.NativeByteBuffer;
|
|
import org.telegram.tgnet.TLRPC;
|
|
import org.telegram.ui.ActionBar.Theme;
|
|
import org.telegram.ui.Components.Premium.PremiumLockIconView;
|
|
import org.telegram.ui.SelectAnimatedEmojiDialog;
|
|
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Locale;
|
|
import java.util.Objects;
|
|
|
|
public class AnimatedEmojiDrawable extends Drawable {
|
|
|
|
public static final int CACHE_TYPE_MESSAGES = 0;
|
|
public static final int CACHE_TYPE_MESSAGES_LARGE = 1;
|
|
public static final int CACHE_TYPE_KEYBOARD = 2;
|
|
public static final int CACHE_TYPE_ALERT_PREVIEW = 3;
|
|
public static final int CACHE_TYPE_ALERT_PREVIEW_LARGE = 4;
|
|
public static final int CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP = 5;
|
|
public static final int CACHE_TYPE_TAB_STRIP = 6;
|
|
public static final int CACHE_TYPE_EMOJI_STATUS = 7;
|
|
public static final int STANDARD_LOTTIE_FRAME = 8;
|
|
public static final int CACHE_TYPE_ALERT_EMOJI_STATUS = 9;
|
|
public static final int CACHE_TYPE_FORUM_TOPIC = 10;
|
|
public static final int CACHE_TYPE_FORUM_TOPIC_LARGE = 11;
|
|
public static final int CACHE_TYPE_RENDERING_VIDEO = 12;
|
|
public static final int CACHE_TYPE_ALERT_PREVIEW_STATIC = 13;
|
|
public static final int CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW = 14;
|
|
public static final int CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW2 = 15;
|
|
|
|
public int rawDrawIndex;
|
|
|
|
private static SparseArray<LongSparseArray<AnimatedEmojiDrawable>> globalEmojiCache;
|
|
private static boolean LOG_MEMORY_LEAK = false;
|
|
|
|
@NonNull
|
|
public static AnimatedEmojiDrawable make(int account, int cacheType, long documentId) {
|
|
return make(account, cacheType, documentId, null);
|
|
}
|
|
|
|
@NonNull
|
|
public static AnimatedEmojiDrawable make(int account, int cacheType, long documentId, String absolutePath) {
|
|
if (globalEmojiCache == null) {
|
|
globalEmojiCache = new SparseArray<>();
|
|
}
|
|
final int key = Objects.hash(account, cacheType);
|
|
LongSparseArray<AnimatedEmojiDrawable> cache = globalEmojiCache.get(key);
|
|
if (cache == null) {
|
|
globalEmojiCache.put(key, cache = new LongSparseArray<>());
|
|
}
|
|
AnimatedEmojiDrawable drawable = cache.get(documentId);
|
|
if (drawable == null) {
|
|
cache.put(documentId, drawable = new AnimatedEmojiDrawable(cacheType, account, documentId, absolutePath));
|
|
}
|
|
return drawable;
|
|
}
|
|
|
|
@NonNull
|
|
public static AnimatedEmojiDrawable make(int account, int cacheType, @NonNull TLRPC.Document document) {
|
|
if (globalEmojiCache == null) {
|
|
globalEmojiCache = new SparseArray<>();
|
|
}
|
|
final int key = Objects.hash(account, cacheType);
|
|
LongSparseArray<AnimatedEmojiDrawable> cache = globalEmojiCache.get(key);
|
|
if (cache == null) {
|
|
globalEmojiCache.put(key, cache = new LongSparseArray<>());
|
|
}
|
|
AnimatedEmojiDrawable drawable = cache.get(document.id);
|
|
if (drawable == null) {
|
|
cache.put(document.id, drawable = new AnimatedEmojiDrawable(cacheType, account, document));
|
|
}
|
|
return drawable;
|
|
}
|
|
|
|
public static int getCacheTypeForEnterView() {
|
|
return SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW ? CACHE_TYPE_MESSAGES : CACHE_TYPE_KEYBOARD;
|
|
}
|
|
|
|
public void setTime(long time) {
|
|
if (imageReceiver != null) {
|
|
if (cacheType == STANDARD_LOTTIE_FRAME) {
|
|
time = 0;
|
|
}
|
|
imageReceiver.setCurrentTime(time);
|
|
}
|
|
}
|
|
|
|
public void update(long time) {
|
|
if (imageReceiver != null) {
|
|
if (cacheType == STANDARD_LOTTIE_FRAME) {
|
|
time = 0;
|
|
}
|
|
if (imageReceiver.getLottieAnimation() != null) {
|
|
imageReceiver.getLottieAnimation().updateCurrentFrame(time, true);
|
|
}
|
|
if (imageReceiver.getAnimation() != null) {
|
|
imageReceiver.getAnimation().updateCurrentFrame(time, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public interface ReceivedDocument {
|
|
void run(TLRPC.Document document);
|
|
}
|
|
|
|
private static HashMap<Integer, EmojiDocumentFetcher> fetchers;
|
|
public static EmojiDocumentFetcher getDocumentFetcher(int account) {
|
|
if (fetchers == null) {
|
|
fetchers = new HashMap<>();
|
|
}
|
|
EmojiDocumentFetcher fetcher = fetchers.get(account);
|
|
if (fetcher == null) {
|
|
fetchers.put(account, fetcher = new EmojiDocumentFetcher(account));
|
|
}
|
|
return fetcher;
|
|
}
|
|
public static class EmojiDocumentFetcher {
|
|
private HashMap<Long, TLRPC.Document> emojiDocumentsCache;
|
|
private HashMap<Long, ArrayList<ReceivedDocument>> loadingDocuments;
|
|
private HashSet<Long> toFetchDocuments;
|
|
private Runnable fetchRunnable;
|
|
private final int currentAccount;
|
|
|
|
public EmojiDocumentFetcher(int account) {
|
|
currentAccount = account;
|
|
}
|
|
|
|
public void fetchDocument(long id, ReceivedDocument onDone) {
|
|
synchronized (this) {
|
|
if (emojiDocumentsCache != null) {
|
|
TLRPC.Document cacheDocument = emojiDocumentsCache.get(id);
|
|
if (cacheDocument != null) {
|
|
if (onDone != null) {
|
|
onDone.run(cacheDocument);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (!checkThread()) {
|
|
return;
|
|
}
|
|
if (loadingDocuments == null) {
|
|
loadingDocuments = new HashMap<>();
|
|
}
|
|
ArrayList<ReceivedDocument> callbacks = loadingDocuments.get(id);
|
|
if (callbacks != null) {
|
|
callbacks.add(onDone);
|
|
return;
|
|
}
|
|
callbacks = new ArrayList<>(1);
|
|
callbacks.add(onDone);
|
|
loadingDocuments.put(id, callbacks);
|
|
|
|
if (toFetchDocuments == null) {
|
|
toFetchDocuments = new HashSet<>();
|
|
}
|
|
toFetchDocuments.add(id);
|
|
if (fetchRunnable != null) {
|
|
return;
|
|
}
|
|
AndroidUtilities.runOnUIThread(fetchRunnable = () -> {
|
|
ArrayList<Long> emojiToLoad = new ArrayList<>(toFetchDocuments);
|
|
toFetchDocuments.clear();
|
|
loadFromDatabase(emojiToLoad);
|
|
fetchRunnable = null;
|
|
});
|
|
}
|
|
|
|
private boolean checkThread() {
|
|
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
|
|
if (BuildVars.DEBUG_VERSION) {
|
|
FileLog.e("EmojiDocumentFetcher", new IllegalStateException("Wrong thread"));
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void loadFromDatabase(ArrayList<Long> emojiToLoad) {
|
|
MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount);
|
|
messagesStorage.getStorageQueue().postRunnable(() -> {
|
|
SQLiteDatabase database = messagesStorage.getDatabase();
|
|
if (database == null) {
|
|
return;
|
|
}
|
|
try {
|
|
String idsStr = TextUtils.join(",", emojiToLoad);
|
|
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM animated_emoji WHERE document_id IN (%s)", idsStr));
|
|
ArrayList<Object> documents = new ArrayList<>();
|
|
HashSet<Long> loadFromServerIds = new HashSet<>(emojiToLoad);
|
|
while (cursor.next()) {
|
|
NativeByteBuffer byteBuffer = cursor.byteBufferValue(0);
|
|
try {
|
|
TLRPC.Document document = TLRPC.Document.TLdeserialize(byteBuffer, byteBuffer.readInt32(true), true);
|
|
if (document != null && document.id != 0) {
|
|
documents.add(document);
|
|
loadFromServerIds.remove(document.id);
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
if (byteBuffer != null) {
|
|
byteBuffer.reuse();
|
|
}
|
|
}
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
processDocuments(documents);
|
|
if (!loadFromServerIds.isEmpty()) {
|
|
loadFromServer(new ArrayList<>(loadFromServerIds));
|
|
}
|
|
});
|
|
cursor.dispose();
|
|
} catch (SQLiteException e) {
|
|
messagesStorage.checkSQLException(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void loadFromServer(ArrayList<Long> loadFromServerIds) {
|
|
final TLRPC.TL_messages_getCustomEmojiDocuments req = new TLRPC.TL_messages_getCustomEmojiDocuments();
|
|
req.document_id = loadFromServerIds;
|
|
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
|
|
HashSet<Long> loadedFromServer = new HashSet<>(loadFromServerIds);
|
|
if (res instanceof TLRPC.Vector) {
|
|
ArrayList<Object> objects = ((TLRPC.Vector) res).objects;
|
|
putToStorage(objects);
|
|
processDocuments(objects);
|
|
for (int i = 0; i < objects.size(); i++) {
|
|
if (objects.get(i) instanceof TLRPC.Document) {
|
|
TLRPC.Document document = (TLRPC.Document) objects.get(i);
|
|
loadedFromServer.remove(document.id);
|
|
}
|
|
}
|
|
|
|
if (!loadedFromServer.isEmpty()) {
|
|
loadFromServer(new ArrayList<>(loadedFromServer));
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
|
|
private void putToStorage(ArrayList<Object> objects) {
|
|
MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> {
|
|
SQLiteDatabase database = MessagesStorage.getInstance(currentAccount).getDatabase();
|
|
try {
|
|
SQLitePreparedStatement state = database.executeFast("REPLACE INTO animated_emoji VALUES(?, ?)");
|
|
for (int i = 0; i < objects.size(); i++) {
|
|
if (objects.get(i) instanceof TLRPC.Document) {
|
|
TLRPC.Document document = (TLRPC.Document) objects.get(i);
|
|
NativeByteBuffer data = null;
|
|
try {
|
|
data = new NativeByteBuffer(document.getObjectSize());
|
|
document.serializeToStream(data);
|
|
state.requery();
|
|
state.bindLong(1, document.id);
|
|
state.bindByteBuffer(2, data);
|
|
state.step();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
if (data != null) {
|
|
data.reuse();
|
|
}
|
|
}
|
|
}
|
|
state.dispose();
|
|
} catch (SQLiteException e) {
|
|
FileLog.e(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void processDocuments(ArrayList<?> documents) {
|
|
if (!checkThread()) {
|
|
return;
|
|
}
|
|
for (int i = 0; i < documents.size(); ++i) {
|
|
if (documents.get(i) instanceof TLRPC.Document) {
|
|
TLRPC.Document document = (TLRPC.Document) documents.get(i);
|
|
putDocument(document);
|
|
if (loadingDocuments != null) {
|
|
ArrayList<ReceivedDocument> loadingCallbacks = loadingDocuments.remove(document.id);
|
|
if (loadingCallbacks != null) {
|
|
for (int j = 0; j < loadingCallbacks.size(); ++j) {
|
|
ReceivedDocument callback = loadingCallbacks.get(j);
|
|
if (callback != null) {
|
|
callback.run(document);
|
|
}
|
|
}
|
|
loadingCallbacks.clear();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void putDocument(TLRPC.Document document) {
|
|
if (document == null) {
|
|
return;
|
|
}
|
|
synchronized (this) {
|
|
if (emojiDocumentsCache == null) {
|
|
emojiDocumentsCache = new HashMap<>();
|
|
}
|
|
emojiDocumentsCache.put(document.id, document);
|
|
}
|
|
}
|
|
|
|
public TLRPC.InputStickerSet findStickerSet(long documentId) {
|
|
synchronized (this) {
|
|
if (emojiDocumentsCache == null) {
|
|
return null;
|
|
}
|
|
TLRPC.Document document = emojiDocumentsCache.get(documentId);
|
|
if (document == null) {
|
|
return null;
|
|
}
|
|
return MessageObject.getInputStickerSet(document);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static TLRPC.Document findDocument(int account, long documentId) {
|
|
EmojiDocumentFetcher fetcher = getDocumentFetcher(account);
|
|
if (fetcher == null || fetcher.emojiDocumentsCache == null) {
|
|
return null;
|
|
}
|
|
return fetcher.emojiDocumentsCache.get(documentId);
|
|
}
|
|
|
|
public static TLRPC.InputStickerSet findStickerSet(int account, long documentId) {
|
|
TLRPC.Document document = findDocument(account, documentId);
|
|
return document == null ? null : MessageObject.getInputStickerSet(document);
|
|
}
|
|
|
|
private boolean attached;
|
|
private ArrayList<View> views;
|
|
private ArrayList<AnimatedEmojiSpan.InvalidateHolder> holders;
|
|
|
|
public int sizedp;
|
|
|
|
private TLRPC.Document document;
|
|
private long documentId;
|
|
private int cacheType;
|
|
private int currentAccount;
|
|
private String absolutePath;
|
|
|
|
private ImageReceiver imageReceiver;
|
|
private float alpha = 1f;
|
|
|
|
public AnimatedEmojiDrawable(int cacheType, int currentAccount, long documentId) {
|
|
this.currentAccount = currentAccount;
|
|
this.cacheType = cacheType;
|
|
updateSize();
|
|
this.documentId = documentId;
|
|
getDocumentFetcher(currentAccount).fetchDocument(documentId, document -> {
|
|
this.document = document;
|
|
this.initDocument(false);
|
|
});
|
|
}
|
|
|
|
public AnimatedEmojiDrawable(int cacheType, int currentAccount, long documentId, String absolutePath) {
|
|
this.currentAccount = currentAccount;
|
|
this.cacheType = cacheType;
|
|
updateSize();
|
|
this.documentId = documentId;
|
|
this.absolutePath = absolutePath;
|
|
getDocumentFetcher(currentAccount).fetchDocument(documentId, document -> {
|
|
this.document = document;
|
|
this.initDocument(false);
|
|
});
|
|
}
|
|
|
|
public AnimatedEmojiDrawable(int cacheType, int currentAccount, @NonNull TLRPC.Document document) {
|
|
this.cacheType = cacheType;
|
|
this.currentAccount = currentAccount;
|
|
this.document = document;
|
|
updateSize();
|
|
this.initDocument(false);
|
|
}
|
|
|
|
private void updateSize() {
|
|
if (this.cacheType == CACHE_TYPE_MESSAGES) {
|
|
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaint.ascent()) + Math.abs(Theme.chat_msgTextPaint.descent())) * 1.15f / AndroidUtilities.density);
|
|
} else if (this.cacheType == CACHE_TYPE_MESSAGES_LARGE || this.cacheType == CACHE_TYPE_ALERT_PREVIEW_LARGE) {
|
|
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaintEmoji[2].ascent()) + Math.abs(Theme.chat_msgTextPaintEmoji[2].descent())) * 1.15f / AndroidUtilities.density);
|
|
} else if (this.cacheType == STANDARD_LOTTIE_FRAME) {
|
|
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaintEmoji[0].ascent()) + Math.abs(Theme.chat_msgTextPaintEmoji[0].descent())) * 1.15f / AndroidUtilities.density);
|
|
} else if (cacheType == CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW || cacheType == CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW2) {
|
|
sizedp = 100;
|
|
} else {
|
|
sizedp = 34;
|
|
}
|
|
}
|
|
public long getDocumentId() {
|
|
return this.document != null ? this.document.id : this.documentId;
|
|
}
|
|
|
|
public TLRPC.Document getDocument() {
|
|
return this.document;
|
|
}
|
|
|
|
private void initDocument(boolean force) {
|
|
if (document == null || (imageReceiver != null && !force)) {
|
|
return;
|
|
}
|
|
if (imageReceiver == null) {
|
|
imageReceiver = new ImageReceiver() {
|
|
@Override
|
|
public void invalidate() {
|
|
AnimatedEmojiDrawable.this.invalidate();
|
|
super.invalidate();
|
|
}
|
|
|
|
@Override
|
|
protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache, int guid) {
|
|
AnimatedEmojiDrawable.this.invalidate();
|
|
return super.setImageBitmapByKey(drawable, key, type, memCache, guid);
|
|
}
|
|
};
|
|
};
|
|
if (cacheType == CACHE_TYPE_RENDERING_VIDEO) {
|
|
imageReceiver.ignoreNotifications = true;
|
|
}
|
|
if (colorFilterToSet != null && canOverrideColor()) {
|
|
imageReceiver.setColorFilter(colorFilterToSet);
|
|
}
|
|
if (cacheType != 0) {
|
|
int cacheType = this.cacheType;
|
|
if (cacheType == CACHE_TYPE_RENDERING_VIDEO) {
|
|
cacheType = CACHE_TYPE_KEYBOARD;
|
|
}
|
|
imageReceiver.setUniqKeyPrefix(cacheType + "_");
|
|
}
|
|
imageReceiver.setVideoThumbIsSame(true);
|
|
boolean onlyStaticPreview = SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW && cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP || cacheType == CACHE_TYPE_KEYBOARD && !LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) || cacheType == CACHE_TYPE_ALERT_PREVIEW && !LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS);
|
|
if (cacheType == CACHE_TYPE_ALERT_PREVIEW_STATIC) {
|
|
onlyStaticPreview = true;
|
|
}
|
|
String filter = sizedp + "_" + sizedp;
|
|
if (cacheType == CACHE_TYPE_RENDERING_VIDEO) {
|
|
filter += "_d_nostream";
|
|
}
|
|
if (cacheType != CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW2 && cacheType != CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW && cacheType != STANDARD_LOTTIE_FRAME && (cacheType != CACHE_TYPE_MESSAGES_LARGE || SharedConfig.getDevicePerformanceClass() < SharedConfig.PERFORMANCE_CLASS_HIGH) && cacheType != CACHE_TYPE_RENDERING_VIDEO) {
|
|
filter += "_pcache";
|
|
}
|
|
if (cacheType != CACHE_TYPE_MESSAGES && cacheType != CACHE_TYPE_MESSAGES_LARGE && cacheType != CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW && cacheType != CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW2) {
|
|
filter += "_compress";
|
|
}
|
|
if (cacheType == STANDARD_LOTTIE_FRAME) {
|
|
filter += "firstframe";
|
|
}
|
|
|
|
ImageLocation mediaLocation;
|
|
String mediaFilter;
|
|
Drawable thumbDrawable = null;
|
|
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
|
|
if ("video/webm".equals(document.mime_type)) {
|
|
mediaLocation = ImageLocation.getForDocument(document);
|
|
mediaFilter = filter + "_" + ImageLoader.AUTOPLAY_FILTER;
|
|
thumbDrawable = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
|
|
} else if ("application/x-tgsticker".equals(document.mime_type)) {
|
|
String probableCacheKey = (cacheType != 0 ? cacheType + "_" : "") + documentId + "@" + filter;
|
|
if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW || (cacheType == CACHE_TYPE_KEYBOARD || !ImageLoader.getInstance().hasLottieMemCache(probableCacheKey))) {
|
|
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
|
|
if (svgThumb != null && MessageObject.isAnimatedStickerDocument(document, true)) {
|
|
svgThumb.overrideWidthAndHeight(512, 512);
|
|
}
|
|
thumbDrawable = svgThumb;
|
|
}
|
|
mediaLocation = ImageLocation.getForDocument(document);
|
|
mediaFilter = filter;
|
|
} else {
|
|
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
|
|
if (svgThumb != null && MessageObject.isAnimatedStickerDocument(document, true)) {
|
|
svgThumb.overrideWidthAndHeight(512, 512);
|
|
}
|
|
thumbDrawable = svgThumb;
|
|
mediaLocation = null;
|
|
mediaFilter = filter;
|
|
}
|
|
|
|
if (absolutePath != null) {
|
|
imageReceiver.setImageBitmap(new AnimatedFileDrawable(new File(absolutePath), true, 0, 0, null, null, null, 0, currentAccount, true, 512, 512, null));
|
|
} else if (cacheType == STANDARD_LOTTIE_FRAME) {
|
|
imageReceiver.setImage(null, null, mediaLocation, mediaFilter, null, null, thumbDrawable, document.size, null, document, 1);
|
|
} else {
|
|
if (onlyStaticPreview || (!LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) && cacheType != CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW)) {
|
|
if ("video/webm".equals(document.mime_type)) {
|
|
imageReceiver.setImage(null, null, ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1);
|
|
} else if (MessageObject.isAnimatedStickerDocument(document, true)){
|
|
imageReceiver.setImage(mediaLocation, mediaFilter + "_firstframe", null, null, thumbDrawable, document.size, null, document, 1);
|
|
} else {
|
|
imageReceiver.setImage(ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1);
|
|
}
|
|
} else {
|
|
imageReceiver.setImage(mediaLocation, mediaFilter, ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1);
|
|
}
|
|
}
|
|
|
|
updateAutoRepeat(imageReceiver);
|
|
|
|
if (cacheType == CACHE_TYPE_ALERT_PREVIEW_STATIC || cacheType == CACHE_TYPE_ALERT_PREVIEW || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_LARGE) {
|
|
imageReceiver.setLayerNum(7);
|
|
}
|
|
if (cacheType == CACHE_TYPE_ALERT_EMOJI_STATUS) {
|
|
imageReceiver.setLayerNum(6656);
|
|
}
|
|
imageReceiver.setAspectFit(true);
|
|
if (cacheType == CACHE_TYPE_RENDERING_VIDEO || cacheType == STANDARD_LOTTIE_FRAME || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) {
|
|
imageReceiver.setAllowStartAnimation(false);
|
|
imageReceiver.setAllowStartLottieAnimation(false);
|
|
imageReceiver.setAutoRepeat(0);
|
|
} else {
|
|
imageReceiver.setAllowStartLottieAnimation(true);
|
|
imageReceiver.setAllowStartAnimation(true);
|
|
imageReceiver.setAutoRepeat(1);
|
|
}
|
|
imageReceiver.setAllowDecodeSingleFrame(true);
|
|
int roundRadius = 0;
|
|
if (cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP || cacheType == CACHE_TYPE_TAB_STRIP) {
|
|
roundRadius = AndroidUtilities.dp(6);
|
|
}
|
|
imageReceiver.setRoundRadius(roundRadius);
|
|
updateAttachState();
|
|
invalidate();
|
|
}
|
|
|
|
private void updateAutoRepeat(ImageReceiver imageReceiver) {
|
|
if (cacheType == CACHE_TYPE_EMOJI_STATUS || cacheType == CACHE_TYPE_ALERT_EMOJI_STATUS || cacheType == CACHE_TYPE_FORUM_TOPIC) {
|
|
imageReceiver.setAutoRepeatCount(2);
|
|
} else if (cacheType == CACHE_TYPE_FORUM_TOPIC_LARGE || cacheType == CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW || cacheType == CACHE_TYPE_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP) {
|
|
imageReceiver.setAutoRepeatCount(1);
|
|
}
|
|
}
|
|
|
|
void invalidate() {
|
|
if (views != null) {
|
|
for (int i = 0; i < views.size(); ++i) {
|
|
View view = views.get(i);
|
|
if (view != null) {
|
|
view.invalidate();
|
|
}
|
|
}
|
|
}
|
|
if (holders != null) {
|
|
for (int i = 0; i < holders.size(); ++i) {
|
|
AnimatedEmojiSpan.InvalidateHolder holder = holders.get(i);
|
|
if (holder != null) {
|
|
holder.invalidate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "AnimatedEmojiDrawable{" + (document == null ? "null" : MessageObject.findAnimatedEmojiEmoticon(document, null)) + "}";
|
|
}
|
|
|
|
private static Paint placeholderPaint;
|
|
public static void updatePlaceholderPaintColor() {
|
|
if (placeholderPaint != null) {
|
|
placeholderPaint.setColor(Theme.isCurrentThemeDark() ? 0x0fffffff : 0x0f000000);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void draw(@NonNull Canvas canvas) {
|
|
if (imageReceiver == null) {
|
|
return;
|
|
}
|
|
imageReceiver.setImageCoords(getBounds());
|
|
imageReceiver.setAlpha(alpha);
|
|
imageReceiver.draw(canvas);
|
|
}
|
|
|
|
public void drawRaw(Canvas canvas, boolean nextFrame, int fps) {
|
|
if (imageReceiver == null) {
|
|
return;
|
|
}
|
|
if (imageReceiver.getLottieAnimation() != null) {
|
|
RLottieDrawable rlottie = imageReceiver.getLottieAnimation();
|
|
if (nextFrame) {
|
|
int inc = (int) Math.round((float) rlottie.getFramesCount() / (rlottie.getDuration() / 1000f) / 30f);
|
|
rlottie.currentFrame = (rlottie.currentFrame + inc) % rlottie.getFramesCount();
|
|
}
|
|
rlottie.setBounds(getBounds());
|
|
rlottie.drawFrame(canvas, rlottie.currentFrame);
|
|
} else if (imageReceiver.getAnimation() != null) {
|
|
AnimatedFileDrawable webp = imageReceiver.getAnimation();
|
|
webp.drawFrame(canvas, nextFrame ? fps / 30 : 0);
|
|
} else {
|
|
imageReceiver.setImageCoords(getBounds());
|
|
imageReceiver.setAlpha(alpha);
|
|
imageReceiver.draw(canvas);
|
|
}
|
|
}
|
|
|
|
public void draw(Canvas canvas, Rect drawableBounds, float alpha) {
|
|
if (imageReceiver == null) {
|
|
return;
|
|
}
|
|
imageReceiver.setImageCoords(drawableBounds);
|
|
imageReceiver.setAlpha(alpha);
|
|
imageReceiver.draw(canvas);
|
|
}
|
|
|
|
public void draw(Canvas canvas, ImageReceiver.BackgroundThreadDrawHolder backgroundThreadDrawHolder, boolean canTranslate) {
|
|
if (imageReceiver == null) {
|
|
return;
|
|
}
|
|
imageReceiver.setAlpha(alpha);
|
|
imageReceiver.draw(canvas, backgroundThreadDrawHolder);
|
|
}
|
|
|
|
public void addView(View callback) {
|
|
if (callback instanceof SelectAnimatedEmojiDialog.EmojiListView) {
|
|
throw new RuntimeException();
|
|
}
|
|
if (views == null) {
|
|
views = new ArrayList<>(10);
|
|
}
|
|
if (!views.contains(callback)) {
|
|
views.add(callback);
|
|
}
|
|
updateAttachState();
|
|
}
|
|
|
|
public void addView(AnimatedEmojiSpan.InvalidateHolder holder) {
|
|
if (holders == null) {
|
|
holders = new ArrayList<>(10);
|
|
}
|
|
if (!holders.contains(holder)) {
|
|
holders.add(holder);
|
|
}
|
|
updateAttachState();
|
|
}
|
|
|
|
public void removeView(AnimatedEmojiSpan.InvalidateHolder holder) {
|
|
if (holders != null) {
|
|
holders.remove(holder);
|
|
}
|
|
updateAttachState();
|
|
}
|
|
|
|
public void removeView(View view) {
|
|
if (views != null) {
|
|
views.remove(view);
|
|
}
|
|
updateAttachState();
|
|
}
|
|
|
|
public static int attachedCount = 0;
|
|
public static ArrayList<AnimatedEmojiDrawable> attachedDrawable;
|
|
private void updateAttachState() {
|
|
if (imageReceiver == null) {
|
|
return;
|
|
}
|
|
boolean attach = (views != null && views.size() > 0) || (holders != null && holders.size() > 0);
|
|
if (attach != attached) {
|
|
attached = attach;
|
|
if (attached) {
|
|
imageReceiver.onAttachedToWindow();
|
|
} else {
|
|
imageReceiver.onDetachedFromWindow();
|
|
}
|
|
if (LOG_MEMORY_LEAK) {
|
|
if (attachedDrawable == null) {
|
|
attachedDrawable = new ArrayList<>();
|
|
}
|
|
if (attached) {
|
|
attachedCount++;
|
|
attachedDrawable.add(this);
|
|
} else {
|
|
attachedCount--;
|
|
attachedDrawable.remove(this);
|
|
}
|
|
Log.d("animatedDrawable", "attached count " + attachedCount);
|
|
}
|
|
}
|
|
|
|
// if (globalEmojiCache != null && (views == null || views.size() <= 0) && (holders == null || holders.size() <= 0) && globalEmojiCache.size() > 50) {
|
|
// HashMap<Long, AnimatedEmojiDrawable> cache = globalEmojiCache.get(currentAccount);
|
|
// if (cache != null) {
|
|
// cache.remove(documentId);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
private Boolean canOverrideColorCached = null;
|
|
public boolean canOverrideColor() {
|
|
if (canOverrideColorCached != null) {
|
|
return canOverrideColorCached;
|
|
}
|
|
if (document != null) {
|
|
return canOverrideColorCached = (isDefaultStatusEmoji() || MessageObject.isTextColorEmoji(document));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private Boolean isDefaultStatusEmojiCached = null;
|
|
public boolean isDefaultStatusEmoji() {
|
|
if (isDefaultStatusEmojiCached != null) {
|
|
return isDefaultStatusEmojiCached;
|
|
}
|
|
if (document != null) {
|
|
TLRPC.InputStickerSet set = MessageObject.getInputStickerSet(document);
|
|
return isDefaultStatusEmojiCached = (
|
|
set instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses ||
|
|
set instanceof TLRPC.TL_inputStickerSetID && (set.id == 773947703670341676L || set.id == 2964141614563343L)
|
|
);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static boolean isDefaultStatusEmoji(Drawable drawable) {
|
|
if (!(drawable instanceof AnimatedEmojiDrawable)) {
|
|
return false;
|
|
}
|
|
return isDefaultStatusEmoji((AnimatedEmojiDrawable) drawable);
|
|
}
|
|
|
|
public static boolean isDefaultStatusEmoji(AnimatedEmojiDrawable drawable) {
|
|
return drawable != null && drawable.isDefaultStatusEmoji();
|
|
}
|
|
|
|
@Override
|
|
public int getAlpha() {
|
|
return (int) (255 * this.alpha);
|
|
}
|
|
|
|
@Override
|
|
public void setAlpha(int alpha) {
|
|
this.alpha = alpha / 255f;
|
|
if (imageReceiver != null) {
|
|
imageReceiver.setAlpha(this.alpha);
|
|
}
|
|
}
|
|
|
|
private ColorFilter colorFilterToSet;
|
|
|
|
@Override
|
|
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
|
if (imageReceiver == null || document == null) {
|
|
colorFilterToSet = colorFilter;
|
|
} else if (canOverrideColor()) {
|
|
imageReceiver.setColorFilter(colorFilter);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
return PixelFormat.TRANSPARENT;
|
|
}
|
|
|
|
public ImageReceiver getImageReceiver() {
|
|
return imageReceiver;
|
|
}
|
|
|
|
private static HashMap<Long, Integer> dominantColors;
|
|
public static int getDominantColor(AnimatedEmojiDrawable yourDrawable) {
|
|
if (yourDrawable == null) {
|
|
return 0;
|
|
}
|
|
long documentId = yourDrawable.getDocumentId();
|
|
if (documentId == 0) {
|
|
return 0;
|
|
}
|
|
if (dominantColors == null) {
|
|
dominantColors = new HashMap<>();
|
|
}
|
|
Integer color = dominantColors.get(documentId);
|
|
if (color == null) {
|
|
if (yourDrawable.getImageReceiver() != null && yourDrawable.getImageReceiver().getBitmap() != null) {
|
|
dominantColors.put(documentId, color = PremiumLockIconView.getDominantColor(yourDrawable.getImageReceiver().getBitmap()));
|
|
}
|
|
}
|
|
return color == null ? 0 : color;
|
|
}
|
|
|
|
|
|
public static class WrapSizeDrawable extends Drawable {
|
|
|
|
private Drawable drawable;
|
|
int width, height;
|
|
|
|
public WrapSizeDrawable(Drawable drawable, int width, int height) {
|
|
this.drawable = drawable;
|
|
this.width = width;
|
|
this.height = height;
|
|
}
|
|
|
|
public Drawable getDrawable() {
|
|
return drawable;
|
|
}
|
|
|
|
@Override
|
|
public void draw(@NonNull Canvas canvas) {
|
|
if (this.drawable != null) {
|
|
this.drawable.setBounds(getBounds());
|
|
this.drawable.setAlpha(this.alpha);
|
|
this.drawable.draw(canvas);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicWidth() {
|
|
return this.width;
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicHeight() {
|
|
return this.height;
|
|
}
|
|
|
|
private int alpha = 255;
|
|
@Override
|
|
public void setAlpha(int alpha) {
|
|
this.alpha = alpha;
|
|
if (this.drawable != null) {
|
|
this.drawable.setAlpha(alpha);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
|
if (this.drawable != null) {
|
|
this.drawable.setColorFilter(colorFilter);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
if (this.drawable != null) {
|
|
return this.drawable.getOpacity();
|
|
}
|
|
return PixelFormat.TRANSPARENT;
|
|
}
|
|
}
|
|
|
|
public static class SwapAnimatedEmojiDrawable extends Drawable implements AnimatedEmojiSpan.InvalidateHolder {
|
|
|
|
public boolean center = false;
|
|
|
|
private int cacheType;
|
|
private OvershootInterpolator overshootInterpolator = new OvershootInterpolator(2f);
|
|
private AnimatedFloat changeProgress = new AnimatedFloat((View) null, 300, CubicBezierInterpolator.EASE_OUT);
|
|
private Drawable[] drawables = new Drawable[2];
|
|
private View parentView;
|
|
private View secondParent;
|
|
private boolean invalidateParent;
|
|
private int size;
|
|
private int alpha = 255;
|
|
boolean attached;
|
|
|
|
public SwapAnimatedEmojiDrawable(View parentView, int size) {
|
|
this(parentView, false, size, CACHE_TYPE_EMOJI_STATUS);
|
|
}
|
|
|
|
public SwapAnimatedEmojiDrawable(View parentView, boolean invalidateParent, int size) {
|
|
this(parentView, invalidateParent, size, CACHE_TYPE_EMOJI_STATUS);
|
|
}
|
|
|
|
public SwapAnimatedEmojiDrawable(View parentView, int size, int cacheType) {
|
|
this(parentView, false, size, cacheType);
|
|
}
|
|
|
|
public SwapAnimatedEmojiDrawable(View parentView, boolean invalidateParent, int size, int cacheType) {
|
|
changeProgress.setParent(this.parentView = parentView);
|
|
this.size = size;
|
|
this.cacheType = cacheType;
|
|
this.invalidateParent = invalidateParent;
|
|
}
|
|
|
|
public void setParentView(View parentView) {
|
|
changeProgress.setParent(parentView);
|
|
this.parentView = parentView;
|
|
}
|
|
|
|
public void play() {
|
|
if (getDrawable() instanceof AnimatedEmojiDrawable) {
|
|
AnimatedEmojiDrawable drawable = (AnimatedEmojiDrawable) getDrawable();
|
|
ImageReceiver imageReceiver = drawable.getImageReceiver();
|
|
if (imageReceiver != null) {
|
|
drawable.updateAutoRepeat(imageReceiver);
|
|
imageReceiver.startAnimation();
|
|
}
|
|
}
|
|
}
|
|
|
|
private Integer lastColor;
|
|
private ColorFilter colorFilter;
|
|
public void setColor(Integer color) {
|
|
if (lastColor == null && color == null || lastColor != null && lastColor.equals(color)) {
|
|
return;
|
|
}
|
|
lastColor = color;
|
|
colorFilter = color != null ? new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) : null;
|
|
}
|
|
|
|
public Integer getColor() {
|
|
return lastColor;
|
|
}
|
|
|
|
@Override
|
|
public void draw(@NonNull Canvas canvas) {
|
|
float progress = changeProgress.set(1);
|
|
Rect bounds = getBounds();
|
|
if (drawables[1] != null && progress < 1) {
|
|
drawables[1].setAlpha((int) (alpha * (1f - progress)));
|
|
if (drawables[1] instanceof AnimatedEmojiDrawable) {
|
|
drawables[1].setBounds(bounds);
|
|
} else if (center) {
|
|
drawables[1].setBounds(
|
|
bounds.centerX() - drawables[1].getIntrinsicWidth() / 2,
|
|
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
|
|
bounds.centerX() + drawables[1].getIntrinsicWidth() / 2,
|
|
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
|
|
);
|
|
} else { // left
|
|
drawables[1].setBounds(
|
|
bounds.left,
|
|
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
|
|
bounds.left + drawables[1].getIntrinsicWidth(),
|
|
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
|
|
);
|
|
}
|
|
drawables[1].setColorFilter(colorFilter);
|
|
drawables[1].draw(canvas);
|
|
drawables[1].setColorFilter(null);
|
|
}
|
|
if (drawables[0] != null) {
|
|
canvas.save();
|
|
if (drawables[0] instanceof AnimatedEmojiDrawable) {
|
|
if (((AnimatedEmojiDrawable) drawables[0]).imageReceiver != null) {
|
|
((AnimatedEmojiDrawable) drawables[0]).imageReceiver.setRoundRadius(AndroidUtilities.dp(4));
|
|
}
|
|
if (progress < 1) {
|
|
float scale = overshootInterpolator.getInterpolation(progress);
|
|
canvas.scale(scale, scale, bounds.centerX(), bounds.centerY());
|
|
}
|
|
drawables[0].setBounds(bounds);
|
|
} else if (center) {
|
|
if (progress < 1) {
|
|
float scale = overshootInterpolator.getInterpolation(progress);
|
|
canvas.scale(scale, scale, bounds.centerX(), bounds.centerY());
|
|
}
|
|
drawables[0].setBounds(
|
|
bounds.centerX() - drawables[0].getIntrinsicWidth() / 2,
|
|
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
|
|
bounds.centerX() + drawables[0].getIntrinsicWidth() / 2,
|
|
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
|
|
);
|
|
} else { // left
|
|
if (progress < 1) {
|
|
float scale = overshootInterpolator.getInterpolation(progress);
|
|
canvas.scale(scale, scale, bounds.left + drawables[0].getIntrinsicWidth() / 2f, bounds.centerY());
|
|
}
|
|
drawables[0].setBounds(
|
|
bounds.left,
|
|
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
|
|
bounds.left + drawables[0].getIntrinsicWidth(),
|
|
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
|
|
);
|
|
}
|
|
drawables[0].setAlpha(alpha);
|
|
drawables[0].setColorFilter(colorFilter);
|
|
drawables[0].draw(canvas);
|
|
drawables[0].setColorFilter(null);
|
|
canvas.restore();
|
|
}
|
|
}
|
|
|
|
public Drawable getDrawable() {
|
|
return drawables[0];
|
|
}
|
|
|
|
public void set(long documentId, boolean animated) {
|
|
set(documentId, cacheType, animated);
|
|
}
|
|
|
|
public void set(long documentId, int cacheType, boolean animated) {
|
|
if (drawables[0] instanceof AnimatedEmojiDrawable && ((AnimatedEmojiDrawable) drawables[0]).getDocumentId() == documentId) {
|
|
return;
|
|
}
|
|
if (animated) {
|
|
changeProgress.set(0, true);
|
|
if (drawables[1] != null) {
|
|
if (attached && drawables[1] instanceof AnimatedEmojiDrawable) {
|
|
((AnimatedEmojiDrawable) drawables[1]).removeView(this);
|
|
}
|
|
drawables[1] = null;
|
|
}
|
|
drawables[1] = drawables[0];
|
|
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, documentId);
|
|
if (attached) {
|
|
((AnimatedEmojiDrawable) drawables[0]).addView(this);
|
|
}
|
|
} else {
|
|
changeProgress.set(1, true);
|
|
boolean attachedLocal = attached;
|
|
if (attachedLocal) {
|
|
detach();
|
|
}
|
|
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, documentId);
|
|
if (attachedLocal) {
|
|
attach();
|
|
}
|
|
}
|
|
lastColor = 0xffffffff;
|
|
colorFilter = null;
|
|
play();
|
|
invalidate();
|
|
}
|
|
|
|
public void set(TLRPC.Document document, boolean animated) {
|
|
set(document, cacheType, animated);
|
|
}
|
|
|
|
public void set(TLRPC.Document document, int cacheType, boolean animated) {
|
|
if (drawables[0] instanceof AnimatedEmojiDrawable && document != null && ((AnimatedEmojiDrawable) drawables[0]).getDocumentId() == document.id) {
|
|
return;
|
|
}
|
|
if (animated) {
|
|
changeProgress.set(0, true);
|
|
if (drawables[1] != null) {
|
|
if (drawables[1] instanceof AnimatedEmojiDrawable) {
|
|
((AnimatedEmojiDrawable) drawables[1]).removeView(this);
|
|
}
|
|
drawables[1] = null;
|
|
}
|
|
drawables[1] = drawables[0];
|
|
if (document != null) {
|
|
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, document);
|
|
if (attached) {
|
|
((AnimatedEmojiDrawable) drawables[0]).addView(this);
|
|
}
|
|
} else {
|
|
drawables[0] = null;
|
|
}
|
|
} else {
|
|
changeProgress.set(1, true);
|
|
boolean attachedLocal = attached;
|
|
if (attachedLocal) {
|
|
detach();
|
|
}
|
|
if (document != null) {
|
|
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, document);
|
|
} else {
|
|
drawables[0] = null;
|
|
}
|
|
if (attachedLocal) {
|
|
attach();
|
|
}
|
|
}
|
|
lastColor = 0xffffffff;
|
|
colorFilter = null;
|
|
play();
|
|
invalidate();
|
|
}
|
|
|
|
public void set(Drawable drawable, boolean animated) {
|
|
if (drawables[0] == drawable) {
|
|
return;
|
|
}
|
|
if (animated) {
|
|
changeProgress.set(0, true);
|
|
if (drawables[1] != null) {
|
|
if (attached && drawables[1] instanceof AnimatedEmojiDrawable) {
|
|
((AnimatedEmojiDrawable) drawables[1]).removeView(this);
|
|
}
|
|
drawables[1] = null;
|
|
}
|
|
drawables[1] = drawables[0];
|
|
drawables[0] = drawable;
|
|
} else {
|
|
changeProgress.set(1, true);
|
|
boolean attachedLocal = attached;
|
|
if (attachedLocal) {
|
|
detach();
|
|
}
|
|
drawables[0] = drawable;
|
|
if (attachedLocal) {
|
|
attach();
|
|
}
|
|
}
|
|
lastColor = 0xffffffff;
|
|
colorFilter = null;
|
|
play();
|
|
invalidate();
|
|
}
|
|
|
|
public void detach() {
|
|
if (!attached) {
|
|
return;
|
|
}
|
|
attached = false;
|
|
if (drawables[0] instanceof AnimatedEmojiDrawable) {
|
|
((AnimatedEmojiDrawable) drawables[0]).removeView(this);
|
|
}
|
|
if (drawables[1] instanceof AnimatedEmojiDrawable) {
|
|
((AnimatedEmojiDrawable) drawables[1]).removeView(this);
|
|
}
|
|
}
|
|
|
|
public void attach() {
|
|
if (attached) {
|
|
return;
|
|
}
|
|
attached = true;
|
|
if (drawables[0] instanceof AnimatedEmojiDrawable) {
|
|
((AnimatedEmojiDrawable) drawables[0]).addView(this);
|
|
}
|
|
if (drawables[1] instanceof AnimatedEmojiDrawable) {
|
|
((AnimatedEmojiDrawable) drawables[1]).addView(this);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicWidth() {
|
|
return size;
|
|
}
|
|
|
|
@Override
|
|
public int getIntrinsicHeight() {
|
|
return size;
|
|
}
|
|
|
|
@Override
|
|
public void setAlpha(int i) {
|
|
alpha = i;
|
|
}
|
|
@Override
|
|
public void setColorFilter(@Nullable ColorFilter colorFilter) {}
|
|
@Override
|
|
public int getOpacity() {
|
|
return PixelFormat.TRANSPARENT;
|
|
}
|
|
|
|
@Override
|
|
public void invalidate() {
|
|
if (parentView != null) {
|
|
if (invalidateParent && parentView.getParent() instanceof View) {
|
|
((View) parentView.getParent()).invalidate();
|
|
} else {
|
|
parentView.invalidate();
|
|
}
|
|
}
|
|
if (secondParent != null) {
|
|
secondParent.invalidate();
|
|
}
|
|
invalidateSelf();
|
|
}
|
|
|
|
public void setSecondParent(View secondParent) {
|
|
this.secondParent = secondParent;
|
|
}
|
|
}
|
|
|
|
public static void updateAll() {
|
|
if (globalEmojiCache == null) {
|
|
return;
|
|
}
|
|
for (int i = 0; i < globalEmojiCache.size(); i++) {
|
|
LongSparseArray<AnimatedEmojiDrawable> map = globalEmojiCache.valueAt(i);
|
|
for (int j = 0; j < map.size(); j++) {
|
|
long documentId = map.keyAt(j);
|
|
AnimatedEmojiDrawable animatedEmojiDrawable = map.get(documentId);
|
|
if (animatedEmojiDrawable != null && animatedEmojiDrawable.attached) {
|
|
animatedEmojiDrawable.initDocument(true);
|
|
} else {
|
|
map.remove(documentId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |