diff --git a/monocles_chat.doap b/monocles_chat.doap
index e1b7a3d31..2808bb9ff 100644
--- a/monocles_chat.doap
+++ b/monocles_chat.doap
@@ -460,7 +460,7 @@
complete
- 0.2
+ 0.3.1
diff --git a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
index 225fd2340..f965b1293 100644
--- a/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/IqGenerator.java
@@ -375,12 +375,18 @@ public class IqGenerator extends AbstractGenerator {
return iq;
}
- public IqPacket generateSetBlockRequest(final Jid jid, boolean reportSpam) {
+ public IqPacket generateSetBlockRequest(final Jid jid, final boolean reportSpam, final String serverMsgId) {
final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
final Element block = iq.addChild("block", Namespace.BLOCKING);
final Element item = block.addChild("item").setAttribute("jid", jid);
if (reportSpam) {
- item.addChild("report", "urn:xmpp:reporting:0").addChild("spam");
+ final Element report = item.addChild("report", Namespace.REPORTING);
+ report.setAttribute("reason", Namespace.REPORTING_REASON_SPAM);
+ if (serverMsgId != null) {
+ final Element stanzaId = report.addChild("stanza-id", Namespace.STANZA_IDS);
+ stanzaId.setAttribute("by", jid);
+ stanzaId.setAttribute("id", serverMsgId);
+ }
}
Log.d(Config.LOGTAG, iq.toString());
return iq;
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 33a883b40..734b0d6f0 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -5798,10 +5798,10 @@ public class XmppConnectionService extends Service {
}
}
- public boolean sendBlockRequest(final Blockable blockable, boolean reportSpam) {
+ public boolean sendBlockRequest(final Blockable blockable, final boolean reportSpam, final String serverMsgId) {
if (blockable != null && blockable.getBlockedJid() != null) {
final Jid jid = blockable.getBlockedJid();
- this.sendIqPacket(blockable.getAccount(), getIqGenerator().generateSetBlockRequest(jid, reportSpam), (a, response) -> {
+ this.sendIqPacket(blockable.getAccount(), getIqGenerator().generateSetBlockRequest(jid, reportSpam, serverMsgId), (a, response) -> {
if (response.getType() == IqPacket.TYPE.RESULT) {
a.getBlocklist().add(jid);
updateBlocklistUi(OnUpdateBlocklist.Status.BLOCKED);
diff --git a/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java b/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
index a54abf1b1..e7867d9cd 100644
--- a/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
+++ b/src/main/java/eu/siacs/conversations/ui/BlockContactDialog.java
@@ -1,6 +1,7 @@
package eu.siacs.conversations.ui;
import android.view.View;
+import android.widget.Toast;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
@@ -14,13 +15,27 @@ import eu.siacs.conversations.ui.util.JidDialog;
import me.drakeet.support.toast.ToastCompat;
public final class BlockContactDialog {
+
public static void show(final XmppActivity xmppActivity, final Blockable blockable) {
+ show(xmppActivity, blockable, null);
+ }
+ public static void show(final XmppActivity xmppActivity, final Blockable blockable, final String serverMsgId) {
final AlertDialog.Builder builder = new AlertDialog.Builder(xmppActivity);
final boolean isBlocked = blockable.isBlocked();
builder.setNegativeButton(R.string.cancel, null);
DialogBlockContactBinding binding = DataBindingUtil.inflate(xmppActivity.getLayoutInflater(), R.layout.dialog_block_contact, null, false);
final boolean reporting = blockable.getAccount().getXmppConnection().getFeatures().spamReporting();
- binding.reportSpam.setVisibility(!isBlocked && reporting ? View.VISIBLE : View.GONE);
+ if (reporting && !isBlocked) {
+ binding.reportSpam.setVisibility(View.VISIBLE);
+ if (serverMsgId != null) {
+ binding.reportSpam.setChecked(true);
+ binding.reportSpam.setEnabled(false);
+ } else {
+ binding.reportSpam.setEnabled(true);
+ }
+ } else {
+ binding.reportSpam.setVisibility(View.GONE);
+ }
builder.setView(binding.getRoot());
final String value;
@@ -34,8 +49,18 @@ public final class BlockContactDialog {
value =blockable.getJid().getDomain().toEscapedString();
res = isBlocked ? R.string.unblock_domain_text : R.string.block_domain_text;
} else {
- int resBlockAction = blockable instanceof Conversation && ((Conversation) blockable).isWithStranger() ? R.string.block_stranger : R.string.action_block_contact;
- builder.setTitle(isBlocked ? R.string.action_unblock_contact : resBlockAction);
+ if (isBlocked) {
+ builder.setTitle(R.string.action_unblock_contact);
+ } else if (serverMsgId != null) {
+ builder.setTitle(R.string.report_spam_and_block);
+ } else {
+ final int resBlockAction =
+ blockable instanceof Conversation
+ && ((Conversation) blockable).isWithStranger()
+ ? R.string.block_stranger
+ : R.string.action_block_contact;
+ builder.setTitle(resBlockAction);
+ }
value = blockable.getJid().asBareJid().toEscapedString();
res = isBlocked ? R.string.unblock_contact_text : R.string.block_contact_text;
}
@@ -45,7 +70,7 @@ public final class BlockContactDialog {
xmppActivity.xmppConnectionService.sendUnblockRequest(blockable);
} else {
boolean toastShown = false;
- if (xmppActivity.xmppConnectionService.sendBlockRequest(blockable, binding.reportSpam.isChecked())) {
+ if (xmppActivity.xmppConnectionService.sendBlockRequest(blockable, binding.reportSpam.isChecked(), serverMsgId)) {
ToastCompat.makeText(xmppActivity, R.string.corresponding_conversations_closed, ToastCompat.LENGTH_SHORT).show();
toastShown = true;
}
diff --git a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
index 7e05a0d45..e5e847fdb 100644
--- a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
@@ -89,7 +89,7 @@ public class BlocklistActivity extends AbstractSearchableListItemActivity implem
dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid, x, y) -> {
Blockable blockable = new RawBlockable(account, contactJid);
- if (xmppConnectionService.sendBlockRequest(blockable, false)) {
+ if (xmppConnectionService.sendBlockRequest(blockable, false, null)) {
ToastCompat.makeText(BlocklistActivity.this, R.string.corresponding_conversations_closed, ToastCompat.LENGTH_SHORT).show();
}
return true;
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 8d25d3bae..f49744679 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -2043,6 +2043,7 @@ public class ConversationFragment extends XmppFragment
|| m.getEncryption() == Message.ENCRYPTION_PGP;
final boolean receiving = m.getStatus() == Message.STATUS_RECEIVED && (t instanceof JingleFileTransferConnection || t instanceof HttpDownloadConnection);
activity.getMenuInflater().inflate(R.menu.message_context, menu);
+ final MenuItem reportAndBlock = menu.findItem(R.id.action_report_and_block);
MenuItem openWith = menu.findItem(R.id.open_with);
MenuItem copyMessage = menu.findItem(R.id.copy_message);
MenuItem quoteMessage = menu.findItem(R.id.quote_message);
@@ -2067,6 +2068,17 @@ public class ConversationFragment extends XmppFragment
onlyThisThread.setVisible(!conversation.getLockThread() && m.getThread() != null);
final boolean unInitiatedButKnownSize = MessageUtils.unInitiatedButKnownSize(m);
final boolean showError = m.getStatus() == Message.STATUS_SEND_FAILED && m.getErrorMessage() != null && !Message.ERROR_MESSAGE_CANCELLED.equals(m.getErrorMessage());
+ final Conversational conversational = m.getConversation();
+ if (m.getStatus() == Message.STATUS_RECEIVED && conversational instanceof Conversation c) {
+ final XmppConnection connection = c.getAccount().getXmppConnection();
+ if (c.isWithStranger()
+ && m.getServerMsgId() != null
+ && !c.isBlocked()
+ && connection != null
+ && connection.getFeatures().spamReporting()) {
+ reportAndBlock.setVisible(true);
+ }
+ }
final boolean messageDeleted = m.isMessageDeleted();
deleteMessage.setVisible(true);
if (!encrypted && !m.getBody().equals("")) {
@@ -2268,6 +2280,9 @@ public class ConversationFragment extends XmppFragment
case R.id.show_error_message:
showErrorMessage(selectedMessage);
return true;
+ case R.id.action_report_and_block:
+ reportMessage(selectedMessage);
+ return true;
case R.id.open_with:
openWith(selectedMessage);
return true;
@@ -3451,6 +3466,10 @@ public class ConversationFragment extends XmppFragment
}
}
+ private void reportMessage(final Message message) {
+ BlockContactDialog.show(activity, conversation.getContact(), message.getServerMsgId());
+ }
+
private void showErrorMessage(final Message message) {
final AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setTitle(R.string.error_message);
diff --git a/src/main/java/eu/siacs/conversations/ui/util/MucDetailsContextMenuHelper.java b/src/main/java/eu/siacs/conversations/ui/util/MucDetailsContextMenuHelper.java
index 582cd8bb8..1e765ffa5 100644
--- a/src/main/java/eu/siacs/conversations/ui/util/MucDetailsContextMenuHelper.java
+++ b/src/main/java/eu/siacs/conversations/ui/util/MucDetailsContextMenuHelper.java
@@ -318,7 +318,7 @@ public final class MucDetailsContextMenuHelper {
return true;
case R.id.context_muc_contact_block_unblock:
try {
- activity.xmppConnectionService.sendBlockRequest(new RawBlockable(account, user.getFullJid()), false);
+ activity.xmppConnectionService.sendBlockRequest(new RawBlockable(account, user.getFullJid()), false,null);
activity.xmppConnectionService.leaveMuc(conversation);
activity.xmppConnectionService.joinMuc(conversation);
} catch (Exception e) {
diff --git a/src/main/java/eu/siacs/conversations/xml/Namespace.java b/src/main/java/eu/siacs/conversations/xml/Namespace.java
index 9efc2f00b..abfc38219 100644
--- a/src/main/java/eu/siacs/conversations/xml/Namespace.java
+++ b/src/main/java/eu/siacs/conversations/xml/Namespace.java
@@ -69,4 +69,6 @@ public final class Namespace {
public static final String UNIFIED_PUSH = "http://gultsch.de/xmpp/drafts/unified-push";
public static final String VCARD4 = "urn:ietf:params:xml:ns:vcard-4.0";
public static final String SDP_OFFER_ANSWER = "urn:ietf:rfc:3264";
+ public static final String REPORTING = "urn:xmpp:reporting:1";
+ public static final String REPORTING_REASON_SPAM = "urn:xmpp:reporting:spam";
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
index e0972c979..2d40b0ac7 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -2926,7 +2926,7 @@ public class XmppConnection implements Runnable {
}
public boolean spamReporting() {
- return hasDiscoFeature(account.getDomain(), "urn:xmpp:reporting:reason:spam:0");
+ return hasDiscoFeature(account.getDomain(), Namespace.REPORTING);
}
public boolean flexibleOfflineMessageRetrieval() {
diff --git a/src/main/res/menu/message_context.xml b/src/main/res/menu/message_context.xml
index c326036a2..4e66ef4c1 100644
--- a/src/main/res/menu/message_context.xml
+++ b/src/main/res/menu/message_context.xml
@@ -2,6 +2,10 @@