diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 09fd3cc70..15ec940f3 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1,12 +1,12 @@
-
+
- Mobile
- Phone
- Tablet
- Conversations
- Android
-
+
- never
- 256 KB
@@ -19,4 +19,16 @@
- 524288
- 1048576
+
+ - never
+ - when received
+ - when read
+ - when received and when read
+
+
+ - 0
+ - 1
+ - 2
+ - 3
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d3a7a91c0..d469caf30 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -145,6 +145,8 @@
Advanced Options
Never send crash reports
By sending in stack traces you are helping the ongoing development of Conversations
+ Acknowledge Messages
+ Allows your contact to know whether or not you have received or read a specific message
OpenKeychain reporeted an error
I/O Error decrypting file
Error copying image file.
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 4cc2f8222..bf304161e 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -22,6 +22,14 @@
android:entries="@array/filesizes"
android:entryValues="@array/filesizes_values"
android:defaultValue="524288"/>
+
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index 50e1fc13e..6cb5e6b08 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -97,11 +97,11 @@ public class XmppConnectionService extends Service {
private OnAccountListChangedListener accountChangedListener = null;
private OnTLSExceptionReceived tlsException = null;
private OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
-
+
@Override
public void onContactStatusChanged(Contact contact) {
Conversation conversation = findActiveConversation(contact);
- if (conversation!=null) {
+ if (conversation != null) {
conversation.endOtrIfNeeded();
}
}
@@ -139,6 +139,7 @@ public class XmppConnectionService extends Service {
"notification_grace_period_after_carbon_received", true)) {
notify = (SystemClock.elapsedRealtime() - lastCarbonMessageReceived) > CARBON_GRACE_PERIOD;
}
+
if ((packet.getType() == MessagePacket.TYPE_CHAT)) {
String pgpBody = mMessageParser.getPgpBody(packet);
@@ -217,6 +218,25 @@ public class XmppConnectionService extends Service {
Log.d(LOGTAG, "error trying to parse date" + e.getMessage());
}
}
+ if ((confirmReception()) && ((packet.getId() != null))) {
+ MessagePacket receivedPacket = new MessagePacket();
+ receivedPacket.setType(MessagePacket.TYPE_UNKNOWN);
+ receivedPacket.setTo(message.getCounterpart());
+ receivedPacket.setFrom(account.getFullJid());
+ if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) {
+ Element received = receivedPacket.addChild("received",
+ "urn:xmpp:chat-markers:0");
+ received.setAttribute("id", packet.getId());
+ account.getXmppConnection().sendMessagePacket(
+ receivedPacket);
+ } else if (packet.hasChild("request", "urn:xmpp:receipts")) {
+ Element received = receivedPacket.addChild("received",
+ "urn:xmpp:receipts");
+ received.setAttribute("id", packet.getId());
+ account.getXmppConnection().sendMessagePacket(
+ receivedPacket);
+ }
+ }
Conversation conversation = message.getConversation();
conversation.getMessages().add(message);
if (packet.getType() != MessagePacket.TYPE_ERROR) {
@@ -279,7 +299,7 @@ public class XmppConnectionService extends Service {
Conversation muc = findMuc(
packet.getAttribute("from").split("/")[0], account);
if (muc != null) {
- muc.getMucOptions().processPacket(packet,getPgpEngine());
+ muc.getMucOptions().processPacket(packet, getPgpEngine());
} else {
Log.d(LOGTAG, account.getJid()
+ ": could not find muc for received muc package "
@@ -293,7 +313,7 @@ public class XmppConnectionService extends Service {
account.getJid() + ": reading muc status packet "
+ packet.toString());
int error = muc.getMucOptions().getError();
- muc.getMucOptions().processPacket(packet,getPgpEngine());
+ muc.getMucOptions().processPacket(packet, getPgpEngine());
if ((muc.getMucOptions().getError() != error)
&& (convChangedListener != null)) {
Log.d(LOGTAG, "muc error status changed");
@@ -336,7 +356,8 @@ public class XmppConnectionService extends Service {
msg, x.getContent()));
}
}
- onContactStatusChanged.onContactStatusChanged(contact);
+ onContactStatusChanged
+ .onContactStatusChanged(contact);
}
} else if (type.equals("unavailable")) {
if (fromParts.length != 2) {
@@ -400,6 +421,9 @@ public class XmppConnectionService extends Service {
"urn:xmpp:jingle:transports:s5b:1");
query.addChild("feature").setAttribute("var",
"urn:xmpp:jingle:transports:ibb:1");
+ if (confirmReception()) {
+ query.addChild("feature").setAttribute("var", "urn:xmpp:receipts");
+ }
account.getXmppConnection().sendIqPacket(iqResponse, null);
} else {
if ((packet.getType() == IqPacket.TYPE_GET)
@@ -868,6 +892,7 @@ public class XmppConnectionService extends Service {
packet.setTo(message.getCounterpart());
packet.setFrom(account.getJid());
}
+ packet.addChild("markable", "urn:xmpp:chat-markers:0");
} else if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
packet.setType(MessagePacket.TYPE_GROUPCHAT);
packet.setBody(message.getBody());
@@ -908,7 +933,7 @@ public class XmppConnectionService extends Service {
new OnPhoneContactsLoadedListener() {
@Override
public void onPhoneContactsLoaded(List phoneContacts) {
- for(Account account : accounts) {
+ for (Account account : accounts) {
account.getRoster().clearSystemAccounts();
}
for (Bundle phoneContact : phoneContacts) {
@@ -958,7 +983,7 @@ public class XmppConnectionService extends Service {
public List getAccounts() {
return this.accounts;
}
-
+
public Conversation findActiveConversation(Contact contact) {
for (Conversation conversation : this.getConversations()) {
if (conversation.getContact() == contact) {
@@ -1133,8 +1158,7 @@ public class XmppConnectionService extends Service {
x.addChild("history").setAttribute("seconds", diff + "");
}
packet.addChild(x);
- account.getXmppConnection()
- .sendPresencePacket(packet);
+ account.getXmppConnection().sendPresencePacket(packet);
}
private OnRenameListener renameListener = null;
@@ -1167,13 +1191,13 @@ public class XmppConnectionService extends Service {
packet.setAttribute("to",
conversation.getContactJid().split("/")[0] + "/" + nick);
packet.setAttribute("from", conversation.getAccount().getFullJid());
-
+
String sig = account.getPgpSignature();
if (sig != null) {
packet.addChild("status").setContent("online");
packet.addChild("x", "jabber:x:signed").setContent(sig);
}
-
+
account.getXmppConnection().sendPresencePacket(packet, null);
} else {
String jid = conversation.getContactJid().split("/")[0] + "/"
@@ -1226,14 +1250,14 @@ public class XmppConnectionService extends Service {
public void updateMessage(Message message) {
databaseBackend.updateMessage(message);
}
-
+
protected void syncDirtyContacts(Account account) {
- for(Contact contact : account.getRoster().getContacts()) {
+ for (Contact contact : account.getRoster().getContacts()) {
if (contact.getOption(Contact.Options.DIRTY_PUSH)) {
pushContactToServer(contact);
}
if (contact.getOption(Contact.Options.DIRTY_DELETE)) {
- Log.d(LOGTAG,"dirty delete");
+ Log.d(LOGTAG, "dirty delete");
deleteContactOnServer(contact);
}
}
@@ -1423,6 +1447,18 @@ public class XmppConnectionService extends Service {
return PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
}
+
+ private boolean confirmReception() {
+ String autoAcks = getPreferences().getString(
+ "auto_acknowledge_messages", "2");
+ int autoAcksValue;
+ try {
+ autoAcksValue = Integer.parseInt(autoAcks);
+ } catch (NumberFormatException e) {
+ autoAcksValue = 0;
+ }
+ return autoAcksValue == 1 || autoAcksValue == 3;
+ }
public void updateUi(Conversation conversation, boolean notify) {
if (convChangedListener != null) {
diff --git a/src/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java b/src/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
index 941bda4f8..9086fda76 100644
--- a/src/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
+++ b/src/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java
@@ -37,6 +37,8 @@ public class MessagePacket extends AbstractStanza {
case TYPE_GROUPCHAT:
this.setAttribute("type", "groupchat");
break;
+ case TYPE_UNKNOWN:
+ break;
default:
this.setAttribute("type","chat");
break;