received and displayed messages (xep 333) are now marked properly

This commit is contained in:
iNPUTmice 2014-06-04 18:44:15 +02:00
parent ba2ad82c7e
commit 7e4e7426ee
10 changed files with 116 additions and 67 deletions

View file

@ -19,16 +19,4 @@
<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,8 +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_confirm_messages">Confirm 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="pref_confirm_messages_summary">Let your contact know when you have received and read a 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,13 +22,11 @@
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 <CheckBoxPreference
android:key="auto_acknowledge_messages" android:key="confirm_messages"
android:title="@string/pref_auto_acknowledge_messages" android:title="@string/pref_confirm_messages"
android:summary="@string/pref_auto_acknowledge_messages_summary" android:summary="@string/pref_confirm_messages_summary"
android:entries="@array/message_acks" android:defaultValue="true"
android:entryValues="@array/message_acks_values"
android:defaultValue="2"
/> />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory

View file

@ -4,6 +4,8 @@ import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import eu.siacs.conversations.services.XmppConnectionService;
import net.java.otr4j.OtrException; import net.java.otr4j.OtrException;
import net.java.otr4j.crypto.OtrCryptoEngineImpl; import net.java.otr4j.crypto.OtrCryptoEngineImpl;
import net.java.otr4j.crypto.OtrCryptoException; import net.java.otr4j.crypto.OtrCryptoException;
@ -59,6 +61,8 @@ public class Conversation extends AbstractEntity {
private transient MucOptions mucOptions = null; private transient MucOptions mucOptions = null;
private transient String latestMarkableMessageId;
public Conversation(String name, Account account, String contactJid, public Conversation(String name, Account account, String contactJid,
int mode) { int mode) {
this(java.util.UUID.randomUUID().toString(), name, null, account this(java.util.UUID.randomUUID().toString(), name, null, account
@ -100,15 +104,26 @@ public class Conversation extends AbstractEntity {
} }
public void markRead() { public void markRead() {
if (this.messages == null) if (this.messages == null) {
return; return;
}
for (int i = this.messages.size() - 1; i >= 0; --i) { for (int i = this.messages.size() - 1; i >= 0; --i) {
if (messages.get(i).isRead()) if (messages.get(i).isRead()) {
return; break;
}
this.messages.get(i).markRead(); this.messages.get(i).markRead();
} }
} }
public void markRead(XmppConnectionService service) {
markRead();
if (service.confirmMessages() && this.latestMarkableMessageId != null) {
service.sendConfirmMessage(getAccount(), getContactJid(),
this.latestMarkableMessageId);
this.latestMarkableMessageId = null;
}
}
public Message getLatestMessage() { public Message getLatestMessage() {
if ((this.messages == null) || (this.messages.size() == 0)) { if ((this.messages == null) || (this.messages.size() == 0)) {
Message message = new Message(this, "", Message.ENCRYPTION_NONE); Message message = new Message(this, "", Message.ENCRYPTION_NONE);
@ -126,7 +141,8 @@ public class Conversation extends AbstractEntity {
} }
public String getName(boolean useSubject) { public String getName(boolean useSubject) {
if ((getMode() == MODE_MULTI) && (getMucOptions().getSubject() != null) && useSubject) { if ((getMode() == MODE_MULTI) && (getMucOptions().getSubject() != null)
&& useSubject) {
return getMucOptions().getSubject(); return getMucOptions().getSubject();
} else { } else {
return this.getContact().getDisplayName(); return this.getContact().getDisplayName();
@ -208,14 +224,15 @@ public class Conversation extends AbstractEntity {
this.mode = mode; this.mode = mode;
} }
public SessionImpl startOtrSession(Context context, String presence, boolean sendStart) { public SessionImpl startOtrSession(Context context, String presence,
boolean sendStart) {
if (this.otrSession != null) { if (this.otrSession != null) {
return this.otrSession; return this.otrSession;
} else { } else {
SessionID sessionId = new SessionID(this.getContactJid(), presence, SessionID sessionId = new SessionID(this.getContactJid(), presence,
"xmpp"); "xmpp");
this.otrSession = new SessionImpl(sessionId, getAccount().getOtrEngine( this.otrSession = new SessionImpl(sessionId, getAccount()
context)); .getOtrEngine(context));
try { try {
if (sendStart) { if (sendStart) {
this.otrSession.startSession(); this.otrSession.startSession();
@ -240,7 +257,8 @@ public class Conversation extends AbstractEntity {
public void endOtrIfNeeded() { public void endOtrIfNeeded() {
if (this.otrSession != null) { if (this.otrSession != null) {
if (this.otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) { if (this.otrSession.getSessionStatus() == SessionStatus.ENCRYPTED) {
Log.d("xmppService","ending otr session with "+getContactJid()); Log.d("xmppService", "ending otr session with "
+ getContactJid());
try { try {
this.otrSession.endSession(); this.otrSession.endSession();
this.resetOtrSession(); this.resetOtrSession();
@ -300,7 +318,8 @@ public class Conversation extends AbstractEntity {
public int getLatestEncryption() { public int getLatestEncryption() {
int latestEncryption = this.getLatestMessage().getEncryption(); int latestEncryption = this.getLatestMessage().getEncryption();
if ((latestEncryption == Message.ENCRYPTION_DECRYPTED) || (latestEncryption == Message.ENCRYPTION_DECRYPTION_FAILED)) { if ((latestEncryption == Message.ENCRYPTION_DECRYPTED)
|| (latestEncryption == Message.ENCRYPTION_DECRYPTION_FAILED)) {
return Message.ENCRYPTION_PGP; return Message.ENCRYPTION_PGP;
} else { } else {
return latestEncryption; return latestEncryption;
@ -319,7 +338,7 @@ public class Conversation extends AbstractEntity {
} }
public String getNextMessage() { public String getNextMessage() {
if (this.nextMessage==null) { if (this.nextMessage == null) {
return ""; return "";
} else { } else {
return this.nextMessage; return this.nextMessage;
@ -329,4 +348,10 @@ public class Conversation extends AbstractEntity {
public void setNextMessage(String message) { public void setNextMessage(String message) {
this.nextMessage = message; this.nextMessage = message;
} }
public void setLatestMarkableMessageId(String id) {
if (id != null) {
this.latestMarkableMessageId = id;
}
}
} }

View file

@ -20,6 +20,8 @@ public class Message extends AbstractEntity {
public static final int STATUS_SEND_FAILED = 3; public static final int STATUS_SEND_FAILED = 3;
public static final int STATUS_SEND_REJECTED = 4; public static final int STATUS_SEND_REJECTED = 4;
public static final int STATUS_OFFERED = 6; public static final int STATUS_OFFERED = 6;
public static final int STATUS_SEND_RECEIVED = 7;
public static final int STATUS_SEND_DISPLAYED = 8;
public static final int ENCRYPTION_NONE = 0; public static final int ENCRYPTION_NONE = 0;
public static final int ENCRYPTION_PGP = 1; public static final int ENCRYPTION_PGP = 1;

View file

@ -25,6 +25,7 @@ public class MessageParser {
String[] fromParts = packet.getFrom().split("/"); String[] fromParts = packet.getFrom().split("/");
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, fromParts[0], false); .findOrCreateConversation(account, fromParts[0], false);
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
String pgpBody = getPgpBody(packet); String pgpBody = getPgpBody(packet);
if (pgpBody != null) { if (pgpBody != null) {
return new Message(conversation, packet.getFrom(), pgpBody, return new Message(conversation, packet.getFrom(), pgpBody,
@ -104,6 +105,7 @@ public class MessageParser {
if ((body == null) || (body.isEmpty())) { if ((body == null) || (body.isEmpty())) {
return null; return null;
} }
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
return new Message(conversation, packet.getFrom(), body, return new Message(conversation, packet.getFrom(), body,
Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED); Message.ENCRYPTION_OTR, Message.STATUS_RECIEVED);
} catch (Exception e) { } catch (Exception e) {
@ -138,6 +140,7 @@ public class MessageParser {
status = Message.STATUS_RECIEVED; status = Message.STATUS_RECIEVED;
} }
String pgpBody = getPgpBody(packet); String pgpBody = getPgpBody(packet);
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
if (pgpBody == null) { if (pgpBody == null) {
return new Message(conversation, counterPart, packet.getBody(), return new Message(conversation, counterPart, packet.getBody(),
Message.ENCRYPTION_NONE, status); Message.ENCRYPTION_NONE, status);
@ -174,6 +177,7 @@ public class MessageParser {
String[] parts = fullJid.split("/"); String[] parts = fullJid.split("/");
Conversation conversation = mXmppConnectionService Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, parts[0], false); .findOrCreateConversation(account, parts[0], false);
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
String pgpBody = getPgpBody(message); String pgpBody = getPgpBody(message);
if (pgpBody != null) { if (pgpBody != null) {
return new Message(conversation, fullJid, pgpBody, return new Message(conversation, fullJid, pgpBody,
@ -191,12 +195,20 @@ public class MessageParser {
packet.getId(), Message.STATUS_SEND_FAILED); packet.getId(), Message.STATUS_SEND_FAILED);
} }
private String getPgpBody(Element packet) { private String getPgpBody(Element message) {
Element child = packet.findChild("x", "jabber:x:encrypted"); Element child = message.findChild("x", "jabber:x:encrypted");
if (child == null) { if (child == null) {
return null; return null;
} else { } else {
return child.getContent(); return child.getContent();
} }
} }
private String getMarkableMessageId(Element message) {
if (message.hasChild("markable", "urn:xmpp:chat-markers:0")) {
return message.getAttribute("id");
} else {
return null;
}
}
} }

View file

@ -140,7 +140,6 @@ public class XmppConnectionService extends Service {
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)) {
if ((packet.getBody() != null) if ((packet.getBody() != null)
&& (packet.getBody().startsWith("?OTR"))) { && (packet.getBody().startsWith("?OTR"))) {
@ -149,8 +148,7 @@ public class XmppConnectionService extends Service {
message.markUnread(); message.markUnread();
} }
} else if (packet.hasChild("body")) { } else if (packet.hasChild("body")) {
message = mMessageParser message = mMessageParser.parseChat(packet, account);
.parseChat(packet, account);
message.markUnread(); message.markUnread();
} else if (packet.hasChild("received") } else if (packet.hasChild("received")
|| (packet.hasChild("sent"))) { || (packet.hasChild("sent"))) {
@ -182,7 +180,16 @@ public class XmppConnectionService extends Service {
mMessageParser.parseError(packet, account); mMessageParser.parseError(packet, account);
return; return;
} else if (packet.getType() == MessagePacket.TYPE_NORMAL) { } else if (packet.getType() == MessagePacket.TYPE_NORMAL) {
if (packet.hasChild("x")) { if (packet.hasChild("displayed","urn:xmpp:chat-markers:0")) {
String id = packet.findChild("displayed","urn:xmpp:chat-markers:0").getAttribute("id");
String[] fromParts = packet.getFrom().split("/");
markMessage(account,fromParts[0], id, Message.STATUS_SEND_DISPLAYED);
Log.d(LOGTAG,"message was displayed by contact");
} else if (packet.hasChild("received","urn:xmpp:chat-markers:0")) {
String id = packet.findChild("received","urn:xmpp:chat-markers:0").getAttribute("id");
String[] fromParts = packet.getFrom().split("/");
markMessage(account,fromParts[0], id, Message.STATUS_SEND_RECEIVED);
} else if (packet.hasChild("x")) {
Element x = packet.findChild("x"); Element x = packet.findChild("x");
if (x.hasChild("invite")) { if (x.hasChild("invite")) {
findOrCreateConversation(account, packet.getFrom(), findOrCreateConversation(account, packet.getFrom(),
@ -195,7 +202,7 @@ public class XmppConnectionService extends Service {
} }
} else { } else {
// Log.d(LOGTAG, "unparsed message " + packet.toString()); //Log.d(LOGTAG, "unparsed message " + packet.toString());
} }
} }
if ((message == null) || (message.getBody() == null)) { if ((message == null) || (message.getBody() == null)) {
@ -213,9 +220,9 @@ 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))) { if ((confirmMessages()) && ((packet.getId() != null))) {
MessagePacket receivedPacket = new MessagePacket(); MessagePacket receivedPacket = new MessagePacket();
receivedPacket.setType(MessagePacket.TYPE_UNKNOWN); receivedPacket.setType(MessagePacket.TYPE_NORMAL);
receivedPacket.setTo(message.getCounterpart()); receivedPacket.setTo(message.getCounterpart());
receivedPacket.setFrom(account.getFullJid()); receivedPacket.setFrom(account.getFullJid());
if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) { if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) {
@ -416,8 +423,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()) { if (confirmMessages()) {
query.addChild("feature").setAttribute("var", "urn:xmpp:receipts"); query.addChild("feature").setAttribute("var",
"urn:xmpp:receipts");
} }
account.getXmppConnection().sendIqPacket(iqResponse, null); account.getXmppConnection().sendIqPacket(iqResponse, null);
} else { } else {
@ -968,8 +976,15 @@ public class XmppConnectionService extends Service {
Collections.sort(this.conversations, new Comparator<Conversation>() { Collections.sort(this.conversations, new Comparator<Conversation>() {
@Override @Override
public int compare(Conversation lhs, Conversation rhs) { public int compare(Conversation lhs, Conversation rhs) {
return (int) (rhs.getLatestMessage().getTimeSent() - lhs Message left = lhs.getLatestMessage();
.getLatestMessage().getTimeSent()); Message right = rhs.getLatestMessage();
if (left.getTimeSent() > right.getTimeSent()) {
return -1;
} else if (left.getTimeSent() < right.getTimeSent()) {
return 1;
} else {
return 0;
}
} }
}); });
return this.conversations; return this.conversations;
@ -1443,16 +1458,8 @@ public class XmppConnectionService extends Service {
.getDefaultSharedPreferences(getApplicationContext()); .getDefaultSharedPreferences(getApplicationContext());
} }
private boolean confirmReception() { public boolean confirmMessages() {
String autoAcks = getPreferences().getString( return getPreferences().getBoolean("confirm_messages", true);
"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) {
@ -1472,4 +1479,19 @@ public class XmppConnectionService extends Service {
} }
return null; return null;
} }
public void markRead(Conversation conversation) {
conversation.markRead(this);
}
public void sendConfirmMessage(Account account, String to, String id) {
MessagePacket receivedPacket = new MessagePacket();
receivedPacket.setType(MessagePacket.TYPE_NORMAL);
receivedPacket.setTo(to);
receivedPacket.setFrom(account.getFullJid());
Element received = receivedPacket.addChild("displayed",
"urn:xmpp:chat-markers:0");
received.setAttribute("id", id);
account.getXmppConnection().sendMessagePacket(receivedPacket);
}
} }

View file

@ -279,7 +279,7 @@ public class ConversationActivity extends XmppActivity {
getSelectedConversation().getName(useSubject)); getSelectedConversation().getName(useSubject));
invalidateOptionsMenu(); invalidateOptionsMenu();
if (!getSelectedConversation().isRead()) { if (!getSelectedConversation().isRead()) {
getSelectedConversation().markRead(); xmppConnectionService.markRead(getSelectedConversation());
UIHelper.updateNotification(getApplicationContext(), UIHelper.updateNotification(getApplicationContext(),
getConversationList(), null, false); getConversationList(), null, false);
listView.invalidateViews(); listView.invalidateViews();

View file

@ -641,7 +641,7 @@ public class ConversationFragment extends Fragment {
if (size >= 1) if (size >= 1)
messagesView.setSelection(size - 1); messagesView.setSelection(size - 1);
if (!activity.shouldPaneBeOpen()) { if (!activity.shouldPaneBeOpen()) {
conversation.markRead(); activity.xmppConnectionService.markRead(conversation);
// TODO update notifications // TODO update notifications
UIHelper.updateNotification(getActivity(), UIHelper.updateNotification(getActivity(),
activity.getConversationList(), null, false); activity.getConversationList(), null, false);

View file

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