1package eu.siacs.conversations.xmpp.manager;
2
3import android.util.Log;
4import androidx.annotation.NonNull;
5import com.google.common.util.concurrent.FutureCallback;
6import com.google.common.util.concurrent.Futures;
7import com.google.common.util.concurrent.ListenableFuture;
8import com.google.common.util.concurrent.MoreExecutors;
9import eu.siacs.conversations.Config;
10import eu.siacs.conversations.entities.Conversation;
11import eu.siacs.conversations.services.XmppConnectionService;
12import eu.siacs.conversations.xmpp.Jid;
13import eu.siacs.conversations.xmpp.XmppConnection;
14import im.conversations.android.xmpp.NodeConfiguration;
15import im.conversations.android.xmpp.model.mds.Displayed;
16import im.conversations.android.xmpp.model.pubsub.Items;
17import im.conversations.android.xmpp.model.unique.StanzaId;
18import java.util.Map;
19
20public class MessageDisplayedSynchronizationManager extends AbstractManager {
21
22 private final XmppConnectionService service;
23
24 public MessageDisplayedSynchronizationManager(
25 final XmppConnectionService service, XmppConnection connection) {
26 super(service, connection);
27 this.service = service;
28 }
29
30 public void handleItems(final Items items) {
31 for (final var item : items.getItemMap(Displayed.class).entrySet()) {
32 this.processMdsItem(item);
33 }
34 }
35
36 public void processMdsItem(final Map.Entry<String, Displayed> item) {
37 final var account = getAccount();
38 final Jid jid = Jid.Invalid.getNullForInvalid(Jid.ofOrInvalid(item.getKey()));
39 if (jid == null) {
40 return;
41 }
42 final var displayed = item.getValue();
43 final var stanzaId = displayed.getStanzaId();
44 final String id = stanzaId == null ? null : stanzaId.getId();
45 final Conversation conversation = this.service.find(account, jid);
46 if (id != null && conversation != null) {
47 conversation.setDisplayState(id);
48 this.service.markReadUpToStanzaId(conversation, id);
49 }
50 }
51
52 public void fetch() {
53 final var future = getManager(PepManager.class).fetchItems(Displayed.class);
54 Futures.addCallback(
55 future,
56 new FutureCallback<>() {
57 @Override
58 public void onSuccess(Map<String, Displayed> result) {
59 for (final var entry : result.entrySet()) {
60 processMdsItem(entry);
61 }
62 }
63
64 @Override
65 public void onFailure(@NonNull Throwable t) {
66 Log.d(
67 Config.LOGTAG,
68 getAccount().getJid().asBareJid()
69 + ": could not retrieve MDS items",
70 t);
71 }
72 },
73 MoreExecutors.directExecutor());
74 }
75
76 public static Displayed displayed(final String id, final Conversation conversation) {
77 final Jid by;
78 if (conversation.getMode() == Conversation.MODE_MULTI) {
79 by = conversation.getJid().asBareJid();
80 } else {
81 by = conversation.getAccount().getJid().asBareJid();
82 }
83 final var displayed = new Displayed();
84 final var stanzaId = displayed.addExtension(new StanzaId(id));
85 stanzaId.setBy(by);
86 return displayed;
87 }
88
89 public ListenableFuture<Void> publish(final Jid itemId, final Displayed displayed) {
90 return getManager(PepManager.class)
91 .publish(displayed, itemId.toString(), NodeConfiguration.WHITELIST_MAX_ITEMS);
92 }
93}