AvatarManager.java

  1package eu.siacs.conversations.xmpp.manager;
  2
  3import android.util.Log;
  4import com.google.common.util.concurrent.Futures;
  5import com.google.common.util.concurrent.ListenableFuture;
  6import com.google.common.util.concurrent.MoreExecutors;
  7import eu.siacs.conversations.Config;
  8import eu.siacs.conversations.entities.Contact;
  9import eu.siacs.conversations.services.XmppConnectionService;
 10import eu.siacs.conversations.xml.Namespace;
 11import eu.siacs.conversations.xmpp.Jid;
 12import eu.siacs.conversations.xmpp.XmppConnection;
 13import eu.siacs.conversations.xmpp.pep.Avatar;
 14import im.conversations.android.xmpp.NodeConfiguration;
 15import im.conversations.android.xmpp.model.avatar.Data;
 16import im.conversations.android.xmpp.model.avatar.Info;
 17import im.conversations.android.xmpp.model.avatar.Metadata;
 18import im.conversations.android.xmpp.model.pubsub.Items;
 19
 20public class AvatarManager extends AbstractManager {
 21
 22    private final XmppConnectionService service;
 23
 24    public AvatarManager(final XmppConnectionService service, XmppConnection connection) {
 25        super(service.getApplicationContext(), connection);
 26        this.service = service;
 27    }
 28
 29    public void handleItems(final Jid from, final Items items) {
 30        final var account = getAccount();
 31        // TODO support retract
 32        final var entry = items.getFirstItemWithId(Metadata.class);
 33        Log.d(Config.LOGTAG, "<-- " + entry + " (" + from + ")");
 34        final var avatar =
 35                entry == null ? null : Avatar.parseMetadata(entry.getKey(), entry.getValue());
 36        if (avatar == null) {
 37            Log.d(Config.LOGTAG, "could not parse avatar metadata from " + from);
 38            return;
 39        }
 40        avatar.owner = from.asBareJid();
 41        if (service.getFileBackend().isAvatarCached(avatar)) {
 42            if (account.getJid().asBareJid().equals(from)) {
 43                if (account.setAvatar(avatar.getFilename())) {
 44                    service.databaseBackend.updateAccount(account);
 45                    service.notifyAccountAvatarHasChanged(account);
 46                }
 47                service.getAvatarService().clear(account);
 48                service.updateConversationUi();
 49                service.updateAccountUi();
 50            } else {
 51                final Contact contact = account.getRoster().getContact(from);
 52                if (contact.setAvatar(avatar)) {
 53                    connection.getManager(RosterManager.class).writeToDatabaseAsync();
 54                    service.getAvatarService().clear(contact);
 55                    service.updateConversationUi();
 56                    service.updateRosterUi();
 57                }
 58            }
 59        } else if (service.isDataSaverDisabled()) {
 60            // TODO use internal mechanism to fetch PEP avatars
 61            service.fetchAvatar(account, avatar);
 62        }
 63    }
 64
 65    public void handleDelete(final Jid from) {
 66        final var account = getAccount();
 67        final boolean isAccount = account.getJid().asBareJid().equals(from);
 68        if (isAccount) {
 69            account.setAvatar(null);
 70            getDatabase().updateAccount(account);
 71            service.getAvatarService().clear(account);
 72            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": deleted avatar metadata node");
 73        }
 74    }
 75
 76    public ListenableFuture<Void> publish(final Avatar avatar, final boolean open) {
 77        final NodeConfiguration configuration =
 78                open ? NodeConfiguration.OPEN : NodeConfiguration.PRESENCE;
 79        final var avatarData = new Data();
 80        avatarData.setContent(avatar.getImageAsBytes());
 81        final var future =
 82                getManager(PepManager.class).publish(avatarData, avatar.sha1sum, configuration);
 83        return Futures.transformAsync(
 84                future,
 85                v -> {
 86                    final var id = avatar.sha1sum;
 87                    final var metadata = new Metadata();
 88                    final var info = metadata.addExtension(new Info());
 89                    info.setBytes(avatar.size);
 90                    info.setId(avatar.sha1sum);
 91                    info.setHeight(avatar.height);
 92                    info.setWidth(avatar.width);
 93                    info.setType(avatar.type);
 94                    return getManager(PepManager.class).publish(metadata, id, configuration);
 95                },
 96                MoreExecutors.directExecutor());
 97    }
 98
 99    public boolean hasPepToVCardConversion() {
100        return getManager(DiscoManager.class).hasAccountFeature(Namespace.AVATAR_CONVERSION);
101    }
102}