aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/services/avatar/AvatarService.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/services/avatar/AvatarService.java')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/services/avatar/AvatarService.java210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/services/avatar/AvatarService.java b/src/main/java/de/thedevstack/conversationsplus/services/avatar/AvatarService.java
new file mode 100644
index 00000000..47443488
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/services/avatar/AvatarService.java
@@ -0,0 +1,210 @@
+package de.thedevstack.conversationsplus.services.avatar;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+import de.thedevstack.android.logcat.Logging;
+import de.thedevstack.conversationsplus.ConversationsPlusApplication;
+import de.thedevstack.conversationsplus.dto.LoadAvatarFor;
+import de.thedevstack.conversationsplus.services.avatar.listener.AvatarMetadataReceived;
+import de.thedevstack.conversationsplus.services.avatar.listener.AvatarPepReceived;
+import de.thedevstack.conversationsplus.services.avatar.listener.AvatarVcardReceived;
+import de.thedevstack.conversationsplus.services.avatar.listener.PublishAvatarResponseReceived;
+import de.thedevstack.conversationsplus.services.avatar.listener.RepublishAvatarAfterMetadataReceived;
+import de.thedevstack.conversationsplus.ui.AsyncDrawable;
+import de.thedevstack.conversationsplus.ui.tasks.AvatarBitmapTask;
+import de.thedevstack.conversationsplus.utils.AvatarUtil;
+import de.thedevstack.conversationsplus.utils.XmppSendUtil;
+import de.thedevstack.conversationsplus.xmpp.avatar.AvatarPacketGenerator;
+import de.thedevstack.conversationsplus.Config;
+import de.thedevstack.conversationsplus.R;
+import de.thedevstack.conversationsplus.entities.Account;
+import de.thedevstack.conversationsplus.entities.Conversation;
+import de.thedevstack.conversationsplus.entities.Message;
+import de.thedevstack.conversationsplus.ui.UiCallback;
+import de.thedevstack.conversationsplus.utils.UIHelper;
+import de.thedevstack.conversationsplus.xmpp.OnAdvancedStreamFeaturesLoaded;
+import de.thedevstack.conversationsplus.xmpp.XmppConnection;
+import de.thedevstack.conversationsplus.xmpp.avatar.AvatarVcardPacketGenerator;
+import de.thedevstack.conversationsplus.xmpp.pep.Avatar;
+import de.thedevstack.conversationsplus.xmpp.stanzas.IqPacket;
+
+public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
+
+ private static final AvatarService INSTANCE = new AvatarService();
+
+ private final List<String> mInProgressAvatarFetches = new ArrayList<>();
+
+ public static AvatarService getInstance() {
+ return INSTANCE;
+ }
+
+ public void loadAvatar(LoadAvatarFor loadAvatarFor, ImageView imageView) {
+ if (cancelPotentialWork(imageView)) {
+ Resources resources = ConversationsPlusApplication.getAppContext().getResources();
+ int avatarSize = resources.getDimensionPixelSize(R.dimen.avatar_size);
+ final Bitmap bm;
+ if (loadAvatarFor instanceof Conversation) {
+ bm = AvatarCache.get((Conversation) loadAvatarFor, avatarSize, true);
+ } else if (loadAvatarFor instanceof Message) {
+ bm = AvatarCache.get((Message) loadAvatarFor, avatarSize, true);
+ } else {
+ bm = null;
+ }
+ int backgroundColor = 0x00000000;
+ if (bm != null) {
+ imageView.setImageBitmap(bm);
+ imageView.setBackgroundColor(backgroundColor);
+ } else {
+ if (loadAvatarFor instanceof Conversation) {
+ backgroundColor = UIHelper.getColorForName(((Conversation) loadAvatarFor).getName());
+ } else if (loadAvatarFor instanceof Message) {
+ backgroundColor = UIHelper.getColorForName(UIHelper.getMessageDisplayName((Message) loadAvatarFor));
+ }
+ imageView.setBackgroundColor(backgroundColor);
+ imageView.setImageDrawable(null);
+ final AvatarBitmapTask<LoadAvatarFor> task = new AvatarBitmapTask<>(imageView, avatarSize);
+ final AsyncDrawable asyncDrawable = new AsyncDrawable(resources, null, task);
+ imageView.setImageDrawable(asyncDrawable);
+ try {
+ task.execute(loadAvatarFor);
+ } catch (final RejectedExecutionException ignored) {
+ }
+ }
+ }
+ }
+
+ public static boolean cancelPotentialWork(ImageView imageView) {
+ return null == getBitmapWorkerTask(imageView);
+ }
+
+ private static AvatarBitmapTask<LoadAvatarFor> getBitmapWorkerTask(ImageView imageView) {
+ if (imageView != null) {
+ final Drawable drawable = imageView.getDrawable();
+ if (drawable instanceof AsyncDrawable) {
+ final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+ return asyncDrawable.getBitmapWorkerTask();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void onAdvancedStreamFeaturesAvailable(Account account) {
+ XmppConnection.Features features = account.getXmppConnection().getFeatures();
+ if (features.pep() && !features.pepPersistent()) {
+ Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": has pep but is not persistent");
+ if (account.getAvatar() != null) {
+ republishAvatarIfNeeded(account);
+ }
+ }
+ }
+
+ public void publishAvatar(final Account account,
+ final Uri image,
+ final UiCallback<Avatar> callback) {
+ final Bitmap.CompressFormat format = Config.AVATAR_FORMAT;
+ final int size = Config.AVATAR_SIZE;
+ final Avatar avatar = AvatarUtil.getPepAvatar(image, size, format);
+ if (avatar != null) {
+ avatar.height = size;
+ avatar.width = size;
+ if (format.equals(Bitmap.CompressFormat.WEBP)) {
+ avatar.type = "image/webp";
+ } else if (format.equals(Bitmap.CompressFormat.JPEG)) {
+ avatar.type = "image/jpeg";
+ } else if (format.equals(Bitmap.CompressFormat.PNG)) {
+ avatar.type = "image/png";
+ }
+ if (!AvatarUtil.save(avatar)) {
+ callback.error(R.string.error_saving_avatar, avatar);
+ return;
+ }
+ publishAvatar(avatar, account, callback);
+ } else {
+ callback.error(R.string.error_publish_avatar_converting, null);
+ }
+ }
+
+ public void republishAvatarIfNeeded(Account account) {
+ if (account.getAxolotlService().isPepBroken()) {
+ Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": skipping republication of avatar because pep is broken");
+ return;
+ }
+ IqPacket packet = AvatarPacketGenerator.generateRetrieveAvatarMetadataPacket(null);
+ XmppSendUtil.sendIqPacket(account, packet, new RepublishAvatarAfterMetadataReceived());
+ }
+
+ public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) {
+ final String KEY = generateFetchKey(account, avatar);
+ synchronized(this.mInProgressAvatarFetches) {
+ if (this.mInProgressAvatarFetches.contains(KEY)) {
+ return;
+ } else {
+ switch (avatar.origin) {
+ case PEP:
+ this.mInProgressAvatarFetches.add(KEY);
+ fetchAvatarPep(account, avatar, callback);
+ break;
+ case VCARD:
+ this.mInProgressAvatarFetches.add(KEY);
+ fetchAvatarVcard(account, avatar, callback);
+ break;
+ }
+ }
+ }
+ }
+
+ public void fetchAvatarPep(final Account account, final Avatar avatar, final UiCallback<Avatar> callback) {
+ IqPacket packet = AvatarPacketGenerator.generateRetrieveAvatarPacket(avatar);
+ XmppSendUtil.sendIqPacket(account, packet, new AvatarPepReceived(avatar, callback));
+ }
+
+ private void fetchAvatarVcard(final Account account, final Avatar avatar, final UiCallback<Avatar> callback) {
+ IqPacket packet = AvatarVcardPacketGenerator.generateRetreivePacket(avatar);
+ XmppSendUtil.sendIqPacket(account, packet, new AvatarVcardReceived(avatar, callback));
+ }
+
+ public void checkForAvatar(Account account, final UiCallback<Avatar> callback) {
+ IqPacket packet = AvatarPacketGenerator.generateRetrieveAvatarMetadataPacket(null);
+ XmppSendUtil.sendIqPacket(account, packet, new AvatarMetadataReceived(callback));
+ }
+
+ public void fetchAvatar(Account account, Avatar avatar) {
+ fetchAvatar(account, avatar, null);
+ }
+
+ public void clearFetchInProgress(Account account) {
+ synchronized (this.mInProgressAvatarFetches) {
+ for(Iterator<String> iterator = this.mInProgressAvatarFetches.iterator(); iterator.hasNext();) {
+ final String KEY = iterator.next();
+ if (KEY.startsWith(account.getJid().toBareJid()+"_")) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+
+ public void publishAvatar(final Avatar avatar, final Account account, final UiCallback callback) {
+ final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar);
+ XmppSendUtil.sendIqPacket(account, packet, new PublishAvatarResponseReceived(avatar, callback));
+ }
+
+ synchronized public void removeFromFetchInProgress(Account account, Avatar avatar) {
+ synchronized (mInProgressAvatarFetches) {
+ mInProgressAvatarFetches.remove(generateFetchKey(account, avatar));
+ }
+ }
+
+ private static String generateFetchKey(Account account, final Avatar avatar) {
+ return account.getJid().toBareJid()+"_"+avatar.owner+"_"+avatar.sha1sum;
+ }
+}