From 35df965b58a9505f27be34c3a68309211c2e6d88 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sat, 26 Oct 2019 18:10:48 +0200 Subject: Bookmarks2: support retraction --- .../java/de/pixart/messenger/entities/Account.java | 56 ++++++++++++++-------- .../de/pixart/messenger/entities/Bookmark.java | 20 ++++---- .../de/pixart/messenger/generator/IqGenerator.java | 1 + .../de/pixart/messenger/parser/MessageParser.java | 28 ++++++++--- .../messenger/services/XmppConnectionService.java | 16 +++---- .../messenger/ui/ChannelDiscoveryActivity.java | 1 - .../messenger/ui/ConferenceDetailsActivity.java | 20 ++++---- .../messenger/ui/StartConversationActivity.java | 4 +- 8 files changed, 87 insertions(+), 59 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/entities/Account.java b/src/main/java/de/pixart/messenger/entities/Account.java index 0590c9d72..fe31dbf07 100644 --- a/src/main/java/de/pixart/messenger/entities/Account.java +++ b/src/main/java/de/pixart/messenger/entities/Account.java @@ -16,11 +16,12 @@ import java.security.PublicKey; import java.security.interfaces.DSAPublicKey; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import de.pixart.messenger.Config; @@ -92,7 +93,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable private XmppConnection xmppConnection = null; private long mEndGracePeriod = 0L; private String otrFingerprint; - private List bookmarks = new CopyOnWriteArrayList<>(); + private final Map bookmarks = new HashMap<>(); private Presence.Status presenceStatus = Presence.Status.ONLINE; private String presenceStatusMessage = null; @@ -502,36 +503,51 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable return this.roster; } - public List getBookmarks() { - return this.bookmarks; + public Collection getBookmarks() { + return this.bookmarks.values(); } - public void setBookmarks(final CopyOnWriteArrayList bookmarks) { - this.bookmarks = bookmarks; + public void setBookmarks(Map bookmarks) { + synchronized (this.bookmarks) { + this.bookmarks.clear(); + this.bookmarks.putAll(bookmarks); + } + } + + public void putBookmark(Bookmark bookmark) { + synchronized (this.bookmarks) { + this.bookmarks.put(bookmark.getJid(), bookmark); + } + } + + public void removeBookmark(Bookmark bookmark) { + synchronized (this.bookmarks) { + this.bookmarks.remove(bookmark.getJid()); + } + } + + public void removeBookmark(Jid jid) { + synchronized (this.bookmarks) { + this.bookmarks.remove(jid); + } } public Set getBookmarkedJids() { - final Set jids = new HashSet<>(); - for (final Bookmark bookmark : this.bookmarks) { - final Jid jid = bookmark.getJid(); - if (jid != null) { - jids.add(jid.asBareJid()); - } + synchronized (this.bookmarks) { + return new HashSet<>(this.bookmarks.keySet()); } - return jids; } - public boolean hasBookmarkFor(final Jid conferenceJid) { - return getBookmark(conferenceJid) != null; + public boolean hasBookmarkFor(final Jid jid) { + synchronized (this.bookmarks) { + return this.bookmarks.containsKey(jid.asBareJid()); + } } Bookmark getBookmark(final Jid jid) { - for (final Bookmark bookmark : this.bookmarks) { - if (bookmark.getJid() != null && jid.asBareJid().equals(bookmark.getJid().asBareJid())) { - return bookmark; - } + synchronized (this.bookmarks) { + return this.bookmarks.get(jid.asBareJid()); } - return null; } public boolean setAvatar(final String filename) { diff --git a/src/main/java/de/pixart/messenger/entities/Bookmark.java b/src/main/java/de/pixart/messenger/entities/Bookmark.java index c7f33af3e..d017eefed 100644 --- a/src/main/java/de/pixart/messenger/entities/Bookmark.java +++ b/src/main/java/de/pixart/messenger/entities/Bookmark.java @@ -7,11 +7,11 @@ import androidx.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import de.pixart.messenger.utils.Namespace; import de.pixart.messenger.utils.StringUtils; @@ -38,43 +38,43 @@ public class Bookmark extends Element implements ListItem { this.account = account; } - public static Collection parseFromStorage(Element storage, Account account) { + public static Map parseFromStorage(Element storage, Account account) { if (storage == null) { - return Collections.emptyList(); + return Collections.emptyMap(); } final HashMap bookmarks = new HashMap<>(); for (final Element item : storage.getChildren()) { if (item.getName().equals("conference")) { final Bookmark bookmark = Bookmark.parse(item, account); if (bookmark != null) { - final Bookmark old = bookmarks.put(bookmark.getJid(), bookmark); + final Bookmark old = bookmarks.put(bookmark.jid, bookmark); if (old != null && old.getBookmarkName() != null && bookmark.getBookmarkName() == null) { bookmark.setBookmarkName(old.getBookmarkName()); } } } } - return bookmarks.values(); + return bookmarks; } - public static Collection parseFromPubsub(Element pubsub, Account account) { + public static Map parseFromPubsub(Element pubsub, Account account) { if (pubsub == null) { - return Collections.emptyList(); + return Collections.emptyMap(); } final Element items = pubsub.findChild("items"); if (items != null && Namespace.BOOKMARK.equals(items.getAttribute("node"))) { - final List bookmarks = new ArrayList<>(); + final Map bookmarks = new HashMap<>(); for (Element item : items.getChildren()) { if (item.getName().equals("item")) { final Bookmark bookmark = Bookmark.parseFromItem(item, account); if (bookmark != null) { - bookmarks.add(bookmark); + bookmarks.put(bookmark.jid, bookmark); } } } return bookmarks; } - return Collections.emptyList(); + return Collections.emptyMap(); } public static Bookmark parse(Element element, Account account) { diff --git a/src/main/java/de/pixart/messenger/generator/IqGenerator.java b/src/main/java/de/pixart/messenger/generator/IqGenerator.java index bb6355688..4e9edeac9 100644 --- a/src/main/java/de/pixart/messenger/generator/IqGenerator.java +++ b/src/main/java/de/pixart/messenger/generator/IqGenerator.java @@ -147,6 +147,7 @@ public class IqGenerator extends AbstractGenerator { final Element pubsub = packet.addChild("pubsub", Namespace.PUBSUB); final Element retract = pubsub.addChild("retract"); retract.setAttribute("node", node); + retract.setAttribute("notify", "true"); retract.addChild("item").setAttribute("id", id); return packet; } diff --git a/src/main/java/de/pixart/messenger/parser/MessageParser.java b/src/main/java/de/pixart/messenger/parser/MessageParser.java index 0fc7e8bac..8e96d9b6f 100644 --- a/src/main/java/de/pixart/messenger/parser/MessageParser.java +++ b/src/main/java/de/pixart/messenger/parser/MessageParser.java @@ -12,11 +12,11 @@ import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -319,14 +319,30 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece if (account.getXmppConnection().getFeatures().bookmarksConversion()) { final Element i = items.findChild("item"); final Element storage = i == null ? null : i.findChild("storage", Namespace.BOOKMARKS); - new Thread(() -> { - Collection bookmarks = Bookmark.parseFromStorage(storage, account); - mXmppConnectionService.processBookmarksInitial(account, bookmarks, true); - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": processing bookmark PEP event"); - }).start(); + Map bookmarks = Bookmark.parseFromStorage(storage, account); + mXmppConnectionService.processBookmarksInitial(account, bookmarks, true); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": processing bookmark PEP event"); } else { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring bookmark PEP event because bookmark conversion was not detected"); } + } else if (Namespace.BOOKMARK.equals(node) && account.getJid().asBareJid().equals(from)) { + final Element item = items.findChild("item"); + final Element retract = items.findChild("retract"); + if (item != null) { + final Bookmark bookmark = Bookmark.parseFromItem(item, account); + if (bookmark != null) { + //TODO find conversation + account.putBookmark(bookmark); + //TODO handle autojoin + } + } + if (retract != null) { + final Jid id = InvalidJid.getNullForInvalid(retract.getAttributeAsJid("id")); + if (id != null) { + account.removeBookmark(id); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": deleted bookmark for " + id); + } + } } else { Log.d(Config.LOGTAG, account.getJid().asBareJid() + " received pubsub notification for node=" + node); } diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index 77f3bb78f..b47fbdf1b 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -1804,7 +1804,7 @@ public class XmppConnectionService extends Service { if (response.getType() == IqPacket.TYPE.RESULT) { final Element query1 = response.query(); final Element storage = query1.findChild("storage", "storage:bookmarks"); - Collection bookmarks = Bookmark.parseFromStorage(storage, account); + Map bookmarks = Bookmark.parseFromStorage(storage, account); processBookmarksInitial(a, bookmarks, false); } else { Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": could not fetch bookmarks"); @@ -1820,17 +1820,17 @@ public class XmppConnectionService extends Service { public void onIqPacketReceived(final Account account, final IqPacket response) { if (response.getType() == IqPacket.TYPE.RESULT) { final Element pubsub = response.findChild("pubsub", Namespace.PUBSUB); - final Collection bookmarks = Bookmark.parseFromPubsub(pubsub, account); + final Map bookmarks = Bookmark.parseFromPubsub(pubsub, account); processBookmarksInitial(account, bookmarks, true); } } }); } - public void processBookmarksInitial(Account account, Collection bookmarks, final boolean pep) { + public void processBookmarksInitial(Account account, Map bookmarks, final boolean pep) { final Set previousBookmarks = account.getBookmarkedJids(); final boolean synchronizeWithBookmarks = synchronizeWithBookmarks(); - for (Bookmark bookmark : bookmarks) { + for (Bookmark bookmark : bookmarks.values()) { previousBookmarks.remove(bookmark.getJid().asBareJid()); Conversation conversation = find(bookmark); if (conversation != null) { @@ -1857,10 +1857,11 @@ public class XmppConnectionService extends Service { } } } - account.setBookmarks(new CopyOnWriteArrayList<>(bookmarks)); + account.setBookmarks(bookmarks); } public void createBookmark(final Account account, final Bookmark bookmark) { + account.putBookmark(bookmark); final XmppConnection connection = account.getXmppConnection(); if (connection.getFeatures().bookmarks2()) { final Element item = mIqGenerator.publishBookmarkItem(bookmark); @@ -1873,6 +1874,7 @@ public class XmppConnectionService extends Service { } public void deleteBookmark(final Account account, final Bookmark bookmark) { + account.removeBookmark(bookmark); final XmppConnection connection = account.getXmppConnection(); if (connection.getFeatures().bookmarksConversion()) { IqPacket request = mIqGenerator.deleteItem(Namespace.BOOKMARK, bookmark.getJid().asBareJid().toEscapedString()); @@ -2358,12 +2360,11 @@ public class XmppConnectionService extends Service { getMessageArchiveService().kill(conversation); if (conversation.getMode() == Conversation.MODE_MULTI) { if (conversation.getAccount().getStatus() == Account.State.ONLINE) { - Bookmark bookmark = conversation.getBookmark(); + final Bookmark bookmark = conversation.getBookmark(); if (maySynchronizeWithBookmarks && bookmark != null && synchronizeWithBookmarks()) { if (conversation.getMucOptions().getError() == MucOptions.Error.DESTROYED) { Account account = bookmark.getAccount(); bookmark.setConversation(null); - account.getBookmarks().remove(bookmark); deleteBookmark(account, bookmark); } else if (bookmark.autojoin()) { bookmark.setAutojoin(false); @@ -4860,7 +4861,6 @@ public class XmppConnectionService extends Service { bookmark.setBookmarkName(name); } bookmark.setAutojoin(getPreferences().getBoolean("autojoin", getResources().getBoolean(R.bool.autojoin))); - account.getBookmarks().add(bookmark); createBookmark(account, bookmark); bookmark.setConversation(conversation); } diff --git a/src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java b/src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java index 9e4cdc680..7d28edf13 100644 --- a/src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ChannelDiscoveryActivity.java @@ -235,7 +235,6 @@ public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.O } else { bookmark = new Bookmark(account, conversation.getJid().asBareJid()); bookmark.setAutojoin(syncAutoJoin); - account.getBookmarks().add(bookmark); xmppConnectionService.createBookmark(account, bookmark); } switchToConversation(conversation); diff --git a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java index 6fdd8c50a..297467558 100644 --- a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java @@ -3,11 +3,8 @@ package de.pixart.messenger.ui; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import androidx.databinding.DataBindingUtil; import android.graphics.PorterDuff; import android.os.Bundle; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.Toolbar; import android.text.Editable; import android.text.SpannableStringBuilder; import android.text.TextWatcher; @@ -18,6 +15,10 @@ import android.view.View; import android.view.View.OnClickListener; import android.widget.Toast; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.Toolbar; +import androidx.databinding.DataBindingUtil; + import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -246,7 +247,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers final Bookmark bookmark = mConversation.getBookmark(); if (bookmark != null) { bookmark.setAutojoin(this.binding.autojoinCheckbox.isChecked()); - xmppConnectionService.pushBookmarks(bookmark.getAccount()); + xmppConnectionService.createBookmark(mConversation.getAccount(), bookmark); updateView(); } } @@ -419,13 +420,10 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } protected void deleteBookmark() { - Account account = mConversation.getAccount(); - Bookmark bookmark = mConversation.getBookmark(); - if (bookmark != null) { - account.getBookmarks().remove(bookmark); - bookmark.setConversation(null); - } - xmppConnectionService.pushBookmarks(account); + final Account account = mConversation.getAccount(); + final Bookmark bookmark = mConversation.getBookmark(); + bookmark.setConversation(null); + xmppConnectionService.deleteBookmark(account, bookmark); updateView(); } diff --git a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java index e34dacb2a..574995e36 100644 --- a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java +++ b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java @@ -471,8 +471,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne builder.setMessage(JidDialog.style(this, R.string.remove_bookmark_text, bookmark.getJid().toEscapedString())); builder.setPositiveButton(R.string.delete, (dialog, which) -> { bookmark.setConversation(null); - Account account = bookmark.getAccount(); - account.getBookmarks().remove(bookmark); + final Account account = bookmark.getAccount(); xmppConnectionService.deleteBookmark(account, bookmark); filter(mSearchEditText.getText().toString()); }); @@ -1023,7 +1022,6 @@ public class StartConversationActivity extends XmppActivity implements XmppConne if (nick != null && !nick.isEmpty() && !nick.equals(MucOptions.defaultNick(account))) { bookmark.setNick(nick); } - account.getBookmarks().add(bookmark); xmppConnectionService.createBookmark(account, bookmark); final Conversation conversation = xmppConnectionService .findOrCreateConversation(account, conferenceJid, true, true, true); -- cgit v1.2.3