answer to xep 184 message receipts. fixes #95

This commit is contained in:
iNPUTmice 2014-06-03 15:48:51 +02:00
parent 99793fa909
commit cedc1f40b3
5 changed files with 76 additions and 16 deletions

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<array name="resources"> <string-array name="resources">
<item>Mobile</item> <item>Mobile</item>
<item>Phone</item> <item>Phone</item>
<item>Tablet</item> <item>Tablet</item>
<item>Conversations</item> <item>Conversations</item>
<item>Android</item> <item>Android</item>
</array> </string-array>
<string-array name="filesizes"> <string-array name="filesizes">
<item>never</item> <item>never</item>
<item>256 KB</item> <item>256 KB</item>
@ -19,4 +19,16 @@
<item>524288</item> <item>524288</item>
<item>1048576</item> <item>1048576</item>
</string-array> </string-array>
<string-array name="message_acks">
<item>never</item>
<item>when received</item>
<item>when read</item>
<item>when received and when read</item>
</string-array>
<string-array name="message_acks_values">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
</resources> </resources>

View file

@ -145,6 +145,8 @@
<string name="pref_advanced_options">Advanced Options</string> <string name="pref_advanced_options">Advanced Options</string>
<string name="pref_never_send_crash">Never send crash reports</string> <string name="pref_never_send_crash">Never send crash reports</string>
<string name="pref_never_send_crash_summary">By sending in stack traces you are helping the ongoing development of Conversations</string> <string name="pref_never_send_crash_summary">By sending in stack traces you are helping the ongoing development of Conversations</string>
<string name="pref_auto_acknowledge_messages">Acknowledge Messages</string>
<string name="pref_auto_acknowledge_messages_summary">Allows your contact to know whether or not you have received or read a specific message</string>
<string name="openpgp_error">OpenKeychain reporeted an error</string> <string name="openpgp_error">OpenKeychain reporeted an error</string>
<string name="error_decrypting_file">I/O Error decrypting file</string> <string name="error_decrypting_file">I/O Error decrypting file</string>
<string name="error_copying_image_file">Error copying image file.</string> <string name="error_copying_image_file">Error copying image file.</string>

View file

@ -22,6 +22,14 @@
android:entries="@array/filesizes" android:entries="@array/filesizes"
android:entryValues="@array/filesizes_values" android:entryValues="@array/filesizes_values"
android:defaultValue="524288"/> android:defaultValue="524288"/>
<ListPreference
android:key="auto_acknowledge_messages"
android:title="@string/pref_auto_acknowledge_messages"
android:summary="@string/pref_auto_acknowledge_messages_summary"
android:entries="@array/message_acks"
android:entryValues="@array/message_acks_values"
android:defaultValue="2"
/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:title="@string/pref_notification_settings"> android:title="@string/pref_notification_settings">

View file

@ -97,11 +97,11 @@ public class XmppConnectionService extends Service {
private OnAccountListChangedListener accountChangedListener = null; private OnAccountListChangedListener accountChangedListener = null;
private OnTLSExceptionReceived tlsException = null; private OnTLSExceptionReceived tlsException = null;
private OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() { private OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
@Override @Override
public void onContactStatusChanged(Contact contact) { public void onContactStatusChanged(Contact contact) {
Conversation conversation = findActiveConversation(contact); Conversation conversation = findActiveConversation(contact);
if (conversation!=null) { if (conversation != null) {
conversation.endOtrIfNeeded(); conversation.endOtrIfNeeded();
} }
} }
@ -139,6 +139,7 @@ public class XmppConnectionService extends Service {
"notification_grace_period_after_carbon_received", true)) { "notification_grace_period_after_carbon_received", true)) {
notify = (SystemClock.elapsedRealtime() - lastCarbonMessageReceived) > CARBON_GRACE_PERIOD; notify = (SystemClock.elapsedRealtime() - lastCarbonMessageReceived) > CARBON_GRACE_PERIOD;
} }
if ((packet.getType() == MessagePacket.TYPE_CHAT)) { if ((packet.getType() == MessagePacket.TYPE_CHAT)) {
String pgpBody = mMessageParser.getPgpBody(packet); String pgpBody = mMessageParser.getPgpBody(packet);
@ -217,6 +218,25 @@ public class XmppConnectionService extends Service {
Log.d(LOGTAG, "error trying to parse date" + e.getMessage()); 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 conversation = message.getConversation();
conversation.getMessages().add(message); conversation.getMessages().add(message);
if (packet.getType() != MessagePacket.TYPE_ERROR) { if (packet.getType() != MessagePacket.TYPE_ERROR) {
@ -279,7 +299,7 @@ public class XmppConnectionService extends Service {
Conversation muc = findMuc( Conversation muc = findMuc(
packet.getAttribute("from").split("/")[0], account); packet.getAttribute("from").split("/")[0], account);
if (muc != null) { if (muc != null) {
muc.getMucOptions().processPacket(packet,getPgpEngine()); muc.getMucOptions().processPacket(packet, getPgpEngine());
} else { } else {
Log.d(LOGTAG, account.getJid() Log.d(LOGTAG, account.getJid()
+ ": could not find muc for received muc package " + ": could not find muc for received muc package "
@ -293,7 +313,7 @@ public class XmppConnectionService extends Service {
account.getJid() + ": reading muc status packet " account.getJid() + ": reading muc status packet "
+ packet.toString()); + packet.toString());
int error = muc.getMucOptions().getError(); int error = muc.getMucOptions().getError();
muc.getMucOptions().processPacket(packet,getPgpEngine()); muc.getMucOptions().processPacket(packet, getPgpEngine());
if ((muc.getMucOptions().getError() != error) if ((muc.getMucOptions().getError() != error)
&& (convChangedListener != null)) { && (convChangedListener != null)) {
Log.d(LOGTAG, "muc error status changed"); Log.d(LOGTAG, "muc error status changed");
@ -336,7 +356,8 @@ public class XmppConnectionService extends Service {
msg, x.getContent())); msg, x.getContent()));
} }
} }
onContactStatusChanged.onContactStatusChanged(contact); onContactStatusChanged
.onContactStatusChanged(contact);
} }
} else if (type.equals("unavailable")) { } else if (type.equals("unavailable")) {
if (fromParts.length != 2) { if (fromParts.length != 2) {
@ -400,6 +421,9 @@ public class XmppConnectionService extends Service {
"urn:xmpp:jingle:transports:s5b:1"); "urn:xmpp:jingle:transports:s5b:1");
query.addChild("feature").setAttribute("var", query.addChild("feature").setAttribute("var",
"urn:xmpp:jingle:transports:ibb:1"); "urn:xmpp:jingle:transports:ibb:1");
if (confirmReception()) {
query.addChild("feature").setAttribute("var", "urn:xmpp:receipts");
}
account.getXmppConnection().sendIqPacket(iqResponse, null); account.getXmppConnection().sendIqPacket(iqResponse, null);
} else { } else {
if ((packet.getType() == IqPacket.TYPE_GET) if ((packet.getType() == IqPacket.TYPE_GET)
@ -868,6 +892,7 @@ public class XmppConnectionService extends Service {
packet.setTo(message.getCounterpart()); packet.setTo(message.getCounterpart());
packet.setFrom(account.getJid()); packet.setFrom(account.getJid());
} }
packet.addChild("markable", "urn:xmpp:chat-markers:0");
} else if (message.getConversation().getMode() == Conversation.MODE_MULTI) { } else if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
packet.setType(MessagePacket.TYPE_GROUPCHAT); packet.setType(MessagePacket.TYPE_GROUPCHAT);
packet.setBody(message.getBody()); packet.setBody(message.getBody());
@ -908,7 +933,7 @@ public class XmppConnectionService extends Service {
new OnPhoneContactsLoadedListener() { new OnPhoneContactsLoadedListener() {
@Override @Override
public void onPhoneContactsLoaded(List<Bundle> phoneContacts) { public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
for(Account account : accounts) { for (Account account : accounts) {
account.getRoster().clearSystemAccounts(); account.getRoster().clearSystemAccounts();
} }
for (Bundle phoneContact : phoneContacts) { for (Bundle phoneContact : phoneContacts) {
@ -958,7 +983,7 @@ public class XmppConnectionService extends Service {
public List<Account> getAccounts() { public List<Account> getAccounts() {
return this.accounts; return this.accounts;
} }
public Conversation findActiveConversation(Contact contact) { public Conversation findActiveConversation(Contact contact) {
for (Conversation conversation : this.getConversations()) { for (Conversation conversation : this.getConversations()) {
if (conversation.getContact() == contact) { if (conversation.getContact() == contact) {
@ -1133,8 +1158,7 @@ public class XmppConnectionService extends Service {
x.addChild("history").setAttribute("seconds", diff + ""); x.addChild("history").setAttribute("seconds", diff + "");
} }
packet.addChild(x); packet.addChild(x);
account.getXmppConnection() account.getXmppConnection().sendPresencePacket(packet);
.sendPresencePacket(packet);
} }
private OnRenameListener renameListener = null; private OnRenameListener renameListener = null;
@ -1167,13 +1191,13 @@ public class XmppConnectionService extends Service {
packet.setAttribute("to", packet.setAttribute("to",
conversation.getContactJid().split("/")[0] + "/" + nick); conversation.getContactJid().split("/")[0] + "/" + nick);
packet.setAttribute("from", conversation.getAccount().getFullJid()); packet.setAttribute("from", conversation.getAccount().getFullJid());
String sig = account.getPgpSignature(); String sig = account.getPgpSignature();
if (sig != null) { if (sig != null) {
packet.addChild("status").setContent("online"); packet.addChild("status").setContent("online");
packet.addChild("x", "jabber:x:signed").setContent(sig); packet.addChild("x", "jabber:x:signed").setContent(sig);
} }
account.getXmppConnection().sendPresencePacket(packet, null); account.getXmppConnection().sendPresencePacket(packet, null);
} else { } else {
String jid = conversation.getContactJid().split("/")[0] + "/" String jid = conversation.getContactJid().split("/")[0] + "/"
@ -1226,14 +1250,14 @@ public class XmppConnectionService extends Service {
public void updateMessage(Message message) { public void updateMessage(Message message) {
databaseBackend.updateMessage(message); databaseBackend.updateMessage(message);
} }
protected void syncDirtyContacts(Account account) { protected void syncDirtyContacts(Account account) {
for(Contact contact : account.getRoster().getContacts()) { for (Contact contact : account.getRoster().getContacts()) {
if (contact.getOption(Contact.Options.DIRTY_PUSH)) { if (contact.getOption(Contact.Options.DIRTY_PUSH)) {
pushContactToServer(contact); pushContactToServer(contact);
} }
if (contact.getOption(Contact.Options.DIRTY_DELETE)) { if (contact.getOption(Contact.Options.DIRTY_DELETE)) {
Log.d(LOGTAG,"dirty delete"); Log.d(LOGTAG, "dirty delete");
deleteContactOnServer(contact); deleteContactOnServer(contact);
} }
} }
@ -1423,6 +1447,18 @@ public class XmppConnectionService extends Service {
return PreferenceManager return PreferenceManager
.getDefaultSharedPreferences(getApplicationContext()); .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) { public void updateUi(Conversation conversation, boolean notify) {
if (convChangedListener != null) { if (convChangedListener != null) {

View file

@ -37,6 +37,8 @@ public class MessagePacket extends AbstractStanza {
case TYPE_GROUPCHAT: case TYPE_GROUPCHAT:
this.setAttribute("type", "groupchat"); this.setAttribute("type", "groupchat");
break; break;
case TYPE_UNKNOWN:
break;
default: default:
this.setAttribute("type","chat"); this.setAttribute("type","chat");
break; break;