1package eu.siacs.conversations.xmpp.manager;
2
3import android.content.Context;
4import android.util.Log;
5import com.google.common.util.concurrent.Futures;
6import com.google.common.util.concurrent.ListenableFuture;
7import com.google.common.util.concurrent.MoreExecutors;
8import eu.siacs.conversations.Config;
9import eu.siacs.conversations.xmpp.Jid;
10import eu.siacs.conversations.xmpp.XmppConnection;
11import im.conversations.android.xmpp.model.stanza.Iq;
12import im.conversations.android.xmpp.model.vcard.VCard;
13import java.util.Objects;
14
15public class VCardManager extends AbstractManager {
16
17 public VCardManager(final Context context, final XmppConnection connection) {
18 super(context, connection);
19 }
20
21 public ListenableFuture<VCard> retrieve(final Jid address) {
22 final var iq = new Iq(Iq.Type.GET, new VCard());
23 iq.setTo(address);
24 return Futures.transform(
25 this.connection.sendIqPacket(iq),
26 result -> {
27 final var vCard = result.getExtension(VCard.class);
28 if (vCard == null) {
29 throw new IllegalStateException("Result did not include vCard");
30 }
31 return vCard;
32 },
33 MoreExecutors.directExecutor());
34 }
35
36 public ListenableFuture<byte[]> retrievePhoto(final Jid address) {
37 final var vCardFuture = retrieve(address);
38 return Futures.transform(
39 vCardFuture,
40 vCard -> {
41 final var photo = vCard.getPhoto();
42 if (photo == null) {
43 throw new IllegalStateException(
44 String.format("No photo in vCard of %s", address));
45 }
46 final var binaryValue = photo.getBinaryValue();
47 if (binaryValue == null) {
48 throw new IllegalStateException(
49 String.format("Photo has no binary value in vCard of %s", address));
50 }
51 return binaryValue.asBytes();
52 },
53 MoreExecutors.directExecutor());
54 }
55
56 public ListenableFuture<Void> publish(final VCard vCard) {
57 final var iq = new Iq(Iq.Type.SET, vCard);
58 iq.setTo(getAccount().getJid().asBareJid());
59 return Futures.transform(
60 connection.sendIqPacket(iq), result -> null, MoreExecutors.directExecutor());
61 }
62
63 public ListenableFuture<Void> deletePhoto() {
64 final var vCardFuture = retrieve(getAccount().getJid().asBareJid());
65 return Futures.transformAsync(
66 vCardFuture,
67 vCard -> {
68 final var photo = vCard.getPhoto();
69 if (photo == null) {
70 return Futures.immediateFuture(null);
71 }
72 Log.d(
73 Config.LOGTAG,
74 "deleting photo from vCard. binaryValue="
75 + Objects.nonNull(photo.getBinaryValue()));
76 photo.clearChildren();
77 return publish(vCard);
78 },
79 MoreExecutors.directExecutor());
80 }
81}