update fork #128

Manually merged
tristan merged 181 commits from mirror/monocles_chat_clean:master into master 2026-01-23 14:02:38 +01:00
6 changed files with 77 additions and 8 deletions
Showing only changes of commit 9c3aaad22f - Show all commits

Refactor feed subscription to use IQ stanzas and allow following any contact

Arne 2026-01-15 21:37:51 +01:00

View file

@ -954,4 +954,24 @@ public class IqGenerator extends AbstractGenerator {
retract.addChild("item").setAttribute("id", id);
return packet;
}
public Iq generateSubscriptionIq(final Jid to, final String node, final Jid from) {
final Iq iq = new Iq(Iq.Type.SET);
iq.setTo(to);
final Element pubsub = iq.addChild("pubsub", Namespace.PUBSUB);
final Element subscribe = pubsub.addChild("subscribe");
subscribe.setAttribute("node", node);
subscribe.setAttribute("jid", from.asBareJid().toString());
return iq;
}
public Iq generateUnsubscriptionIq(final Jid to, final String node, final Jid from) {
final Iq iq = new Iq(Iq.Type.SET);
iq.setTo(to);
final Element pubsub = iq.addChild("pubsub", Namespace.PUBSUB);
final Element unsubscribe = pubsub.addChild("unsubscribe");
unsubscribe.setAttribute("node", node);
unsubscribe.setAttribute("jid", from.asBareJid().toString());
return iq;
}
}

View file

@ -8330,4 +8330,14 @@ public class XmppConnectionService extends Service {
listener.onPostRetracted(postId);
}
}
public void subscribeTo(final Account account, final Jid to, final String node, final Consumer<Iq> callback) {
final Iq iq = getIqGenerator().generateSubscriptionIq(to, node, account.getJid());
sendIqPacket(account, iq, callback);
}
public void unsubscribeFrom(final Account account, final Jid to, final String node, final Consumer<Iq> callback) {
final Iq iq = getIqGenerator().generateUnsubscriptionIq(to, node, account.getJid());
sendIqPacket(account, iq, callback);
}
}

View file

@ -100,6 +100,8 @@ import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.XmppConnection;
import im.conversations.android.xmpp.model.stanza.Iq;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -185,8 +187,31 @@ public class ContactDetailsActivity extends OmemoActivity
private final OnCheckedChangeListener mOnFollowFeedCheckedChange =
(buttonView, isChecked) -> {
if (contact != null) {
contact.setFollowed(isChecked);
xmppConnectionService.updateContact(contact);
if (isChecked) {
xmppConnectionService.subscribeTo(contact.getAccount(), contact.getJid(), "urn:xmpp:microblog:0", packet -> {
runOnUiThread(() -> {
if (packet.getType() == Iq.Type.RESULT) {
contact.setFollowed(true);
xmppConnectionService.updateContact(contact);
} else {
mFollowFeedSwitch.setChecked(false);
Toast.makeText(ContactDetailsActivity.this, R.string.error_subscribing_to_feed, Toast.LENGTH_SHORT).show();
}
});
});
} else {
xmppConnectionService.unsubscribeFrom(contact.getAccount(), contact.getJid(), "urn:xmpp:microblog:0", packet -> {
runOnUiThread(() -> {
if (packet.getType() == Iq.Type.RESULT) {
contact.setFollowed(false);
xmppConnectionService.updateContact(contact);
} else {
mFollowFeedSwitch.setChecked(true);
Toast.makeText(ContactDetailsActivity.this, R.string.error_unsubscribing_from_feed, Toast.LENGTH_SHORT).show();
}
});
});
}
}
};

View file

@ -246,7 +246,7 @@ public class PostsActivity extends XmppActivity implements XmppConnectionService
for (Contact contact : account.getRoster().getContacts()) {
if (contact.isFollowed()) {
sourcesToFetch.add(contact.getJid().asBareJid());
} else if (contact.showInRoster() && (contact.resourceWhichSupport(Namespace.PUBSUB_SOCIAL_FEED) != null || contact.resourceWhichSupport("urn:xmpp:microblog:0") != null)) {
} else if (contact.showInRoster()) {
mFollowSuggestions.add(contact);
}
}

View file

@ -7,6 +7,7 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@ -14,10 +15,12 @@ import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.PostsActivity;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import im.conversations.android.xmpp.model.stanza.Iq;
public class FollowSuggestionAdapter extends RecyclerView.Adapter<FollowSuggestionAdapter.ViewHolder> {
@ -45,11 +48,20 @@ public class FollowSuggestionAdapter extends RecyclerView.Adapter<FollowSuggesti
AvatarWorkerTask.loadAvatar(contact, holder.mAvatar, R.dimen.feed_suggestions_avatar_size);
holder.mAvatar.setOnClickListener(v -> mPostsActivity.switchToContactDetails(contact));
holder.mFollowButton.setOnClickListener(v -> {
contact.setFollowed(true);
mXmppConnectionService.updateContact(contact);
mContacts.remove(contact);
notifyDataSetChanged();
mPostsActivity.loadPosts(); // Refresh posts to show new content
final Account account = contact.getAccount();
mXmppConnectionService.subscribeTo(account, contact.getJid(), "urn:xmpp:microblog:0", packet -> {
mPostsActivity.runOnUiThread(() -> {
if (packet.getType() == Iq.Type.RESULT) {
contact.setFollowed(true);
mXmppConnectionService.updateContact(contact);
mContacts.remove(contact);
notifyDataSetChanged();
mPostsActivity.loadPosts();
} else {
Toast.makeText(mPostsActivity, R.string.error_subscribing_to_feed, Toast.LENGTH_SHORT).show();
}
});
});
});
}

View file

@ -1628,6 +1628,8 @@
<string name="follow_suggestions">Suggestions</string>
<string name="toggle_suggestions">Toggle suggestions</string>
<string name="forward">Forward</string>
<string name="error_subscribing_to_feed">Could not subscribe to feed</string>
<string name="error_unsubscribing_from_feed">Could not unsubscribe from feed</string>
<plurals name="publishing_to_x_contacts">
<item quantity="one">Publishing to %d contact</item>
<item quantity="other">Publishing to %d contacts</item>