aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/values/strings.xml3
-rw-r--r--src/eu/siacs/conversations/entities/Message.java5
-rw-r--r--src/eu/siacs/conversations/generator/MessageGenerator.java3
-rw-r--r--src/eu/siacs/conversations/parser/MessageParser.java73
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java2
-rw-r--r--src/eu/siacs/conversations/ui/ConversationActivity.java9
-rw-r--r--src/eu/siacs/conversations/ui/ConversationFragment.java45
-rw-r--r--src/eu/siacs/conversations/ui/adapter/MessageAdapter.java55
8 files changed, 163 insertions, 32 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7faeeed9..89d1cc11 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -277,4 +277,7 @@
<string name="error_saving_avatar">Could not save avatar to disk</string>
<string name="or_long_press_for_default">(Or long press to bring back default)</string>
<string name="error_publish_avatar_no_server_support">Your server does not support the publication of avatars</string>
+ <string name="private_message">in private</string>
+ <string name="private_message_to">in private to %s</string>
+ <string name="send_private_message_to">Send private message to %s</string>
</resources>
diff --git a/src/eu/siacs/conversations/entities/Message.java b/src/eu/siacs/conversations/entities/Message.java
index 1fa5ce42..3fe20707 100644
--- a/src/eu/siacs/conversations/entities/Message.java
+++ b/src/eu/siacs/conversations/entities/Message.java
@@ -33,6 +33,7 @@ public class Message extends AbstractEntity {
public static final int TYPE_IMAGE = 1;
public static final int TYPE_AUDIO = 2;
public static final int TYPE_STATUS = 3;
+ public static final int TYPE_PRIVATE = 4;
public static String CONVERSATION = "conversationUuid";
public static String COUNTERPART = "counterpart";
@@ -257,4 +258,8 @@ public class Message extends AbstractEntity {
message.setConversation(conversation);
return message;
}
+
+ public void setCounterpart(String counterpart) {
+ this.counterpart = counterpart;
+ }
}
diff --git a/src/eu/siacs/conversations/generator/MessageGenerator.java b/src/eu/siacs/conversations/generator/MessageGenerator.java
index 4449a7ec..26182aad 100644
--- a/src/eu/siacs/conversations/generator/MessageGenerator.java
+++ b/src/eu/siacs/conversations/generator/MessageGenerator.java
@@ -22,6 +22,9 @@ public class MessageGenerator {
packet.setTo(message.getCounterpart());
packet.setType(MessagePacket.TYPE_CHAT);
packet.addChild("markable", "urn:xmpp:chat-markers:0");
+ } else if (message.getType() == Message.TYPE_PRIVATE) {
+ packet.setTo(message.getCounterpart());
+ packet.setType(MessagePacket.TYPE_CHAT);
} else {
packet.setTo(message.getCounterpart().split("/")[0]);
packet.setType(MessagePacket.TYPE_GROUPCHAT);
diff --git a/src/eu/siacs/conversations/parser/MessageParser.java b/src/eu/siacs/conversations/parser/MessageParser.java
index b54f6b98..44624cbe 100644
--- a/src/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/eu/siacs/conversations/parser/MessageParser.java
@@ -40,6 +40,14 @@ public class MessageParser extends AbstractParser implements
packet.getBody(), Message.ENCRYPTION_NONE,
Message.STATUS_RECIEVED);
}
+ if (conversation.getMode() == Conversation.MODE_MULTI
+ && fromParts.length >= 2) {
+ finishedMessage.setType(Message.TYPE_PRIVATE);
+ finishedMessage.setPresence(fromParts[1]);
+ finishedMessage.setTrueCounterpart(conversation.getMucOptions()
+ .getTrueCounterpart(fromParts[1]));
+
+ }
finishedMessage.setTime(getTimestamp(packet));
return finishedMessage;
}
@@ -113,7 +121,8 @@ public class MessageParser extends AbstractParser implements
private Message parseGroupchat(MessagePacket packet, Account account) {
int status;
String[] fromParts = packet.getFrom().split("/");
- if (mXmppConnectionService.find(account.pendingConferenceLeaves,account,fromParts[0]) != null) {
+ if (mXmppConnectionService.find(account.pendingConferenceLeaves,
+ account, fromParts[0]) != null) {
return null;
}
Conversation conversation = mXmppConnectionService
@@ -150,7 +159,8 @@ public class MessageParser extends AbstractParser implements
}
finishedMessage.setTime(getTimestamp(packet));
if (status == Message.STATUS_RECIEVED) {
- finishedMessage.setTrueCounterpart(conversation.getMucOptions().getTrueCounterpart(counterPart));
+ finishedMessage.setTrueCounterpart(conversation.getMucOptions()
+ .getTrueCounterpart(counterPart));
}
return finishedMessage;
}
@@ -180,7 +190,7 @@ public class MessageParser extends AbstractParser implements
}
if (status == Message.STATUS_RECIEVED) {
fullJid = message.getAttribute("from");
- if (fullJid == null ) {
+ if (fullJid == null) {
return null;
} else {
updateLastseen(message, account, true);
@@ -195,6 +205,7 @@ public class MessageParser extends AbstractParser implements
Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account, parts[0], false);
conversation.setLatestMarkableMessageId(getMarkableMessageId(packet));
+
String pgpBody = getPgpBody(message);
Message finishedMessage;
if (pgpBody != null) {
@@ -206,6 +217,16 @@ public class MessageParser extends AbstractParser implements
Message.ENCRYPTION_NONE, status);
}
finishedMessage.setTime(getTimestamp(message));
+
+ if (conversation.getMode() == Conversation.MODE_MULTI
+ && parts.length >= 2) {
+ finishedMessage.setType(Message.TYPE_PRIVATE);
+ finishedMessage.setPresence(parts[1]);
+ finishedMessage.setTrueCounterpart(conversation.getMucOptions()
+ .getTrueCounterpart(parts[1]));
+
+ }
+
return finishedMessage;
}
@@ -216,9 +237,10 @@ public class MessageParser extends AbstractParser implements
}
private void parseNormal(Element packet, Account account) {
- if (packet.hasChild("event","http://jabber.org/protocol/pubsub#event")) {
- Element event = packet.findChild("event","http://jabber.org/protocol/pubsub#event");
- parseEvent(event,packet.getAttribute("from"),account);
+ if (packet.hasChild("event", "http://jabber.org/protocol/pubsub#event")) {
+ Element event = packet.findChild("event",
+ "http://jabber.org/protocol/pubsub#event");
+ parseEvent(event, packet.getAttribute("from"), account);
}
if (packet.hasChild("displayed", "urn:xmpp:chat-markers:0")) {
String id = packet
@@ -235,8 +257,9 @@ public class MessageParser extends AbstractParser implements
updateLastseen(packet, account, false);
mXmppConnectionService.markMessage(account, fromParts[0], id,
Message.STATUS_SEND_RECEIVED);
- } else if (packet.hasChild("x","http://jabber.org/protocol/muc#user")) {
- Element x = packet.findChild("x","http://jabber.org/protocol/muc#user");
+ } else if (packet.hasChild("x", "http://jabber.org/protocol/muc#user")) {
+ Element x = packet.findChild("x",
+ "http://jabber.org/protocol/muc#user");
if (x.hasChild("invite")) {
Conversation conversation = mXmppConnectionService
.findOrCreateConversation(account,
@@ -244,15 +267,15 @@ public class MessageParser extends AbstractParser implements
if (!conversation.getMucOptions().online()) {
mXmppConnectionService.joinMuc(conversation);
mXmppConnectionService.updateConversationUi();
- }
+ }
}
} else if (packet.hasChild("x", "jabber:x:conference")) {
Element x = packet.findChild("x", "jabber:x:conference");
String jid = x.getAttribute("jid");
- if (jid!=null) {
+ if (jid != null) {
Conversation conversation = mXmppConnectionService
- .findOrCreateConversation(account,jid, true);
+ .findOrCreateConversation(account, jid, true);
if (!conversation.getMucOptions().online()) {
mXmppConnectionService.joinMuc(conversation);
mXmppConnectionService.updateConversationUi();
@@ -264,11 +287,12 @@ public class MessageParser extends AbstractParser implements
private void parseEvent(Element event, String from, Account account) {
Element items = event.findChild("items");
String node = items.getAttribute("node");
- if (node!=null) {
+ if (node != null) {
if (node.equals("urn:xmpp:avatar:metadata")) {
Avatar avatar = Avatar.parseMetadata(items);
avatar.owner = from;
- if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) {
+ if (mXmppConnectionService.getFileBackend().isAvatarCached(
+ avatar)) {
if (account.getJid().equals(from)) {
account.setAvatar(avatar.getFilename());
} else {
@@ -279,10 +303,11 @@ public class MessageParser extends AbstractParser implements
mXmppConnectionService.fetchAvatar(account, avatar);
}
} else {
- Log.d("xmppService",account.getJid()+": "+node+" from "+from);
+ Log.d("xmppService", account.getJid() + ": " + node + " from "
+ + from);
}
} else {
- Log.d("xmppService",event.toString());
+ Log.d("xmppService", event.toString());
}
}
@@ -345,8 +370,7 @@ public class MessageParser extends AbstractParser implements
message.markUnread();
} else {
message.getConversation().markRead();
- lastCarbonMessageReceived = SystemClock
- .elapsedRealtime();
+ lastCarbonMessageReceived = SystemClock.elapsedRealtime();
notify = false;
}
}
@@ -366,11 +390,15 @@ public class MessageParser extends AbstractParser implements
if ((mXmppConnectionService.confirmMessages())
&& ((packet.getId() != null))) {
if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) {
- MessagePacket receipt = mXmppConnectionService.getMessageGenerator().received(account, packet, "urn:xmpp:chat-markers:0");
+ MessagePacket receipt = mXmppConnectionService
+ .getMessageGenerator().received(account, packet,
+ "urn:xmpp:chat-markers:0");
mXmppConnectionService.sendMessagePacket(account, receipt);
}
if (packet.hasChild("request", "urn:xmpp:receipts")) {
- MessagePacket receipt = mXmppConnectionService.getMessageGenerator().received(account, packet, "urn:xmpp:receipts");
+ MessagePacket receipt = mXmppConnectionService
+ .getMessageGenerator().received(account, packet,
+ "urn:xmpp:receipts");
mXmppConnectionService.sendMessagePacket(account, receipt);
}
}
@@ -383,9 +411,10 @@ public class MessageParser extends AbstractParser implements
}
private void parseHeadline(MessagePacket packet, Account account) {
- if (packet.hasChild("event","http://jabber.org/protocol/pubsub#event")) {
- Element event = packet.findChild("event","http://jabber.org/protocol/pubsub#event");
- parseEvent(event,packet.getFrom(),account);
+ if (packet.hasChild("event", "http://jabber.org/protocol/pubsub#event")) {
+ Element event = packet.findChild("event",
+ "http://jabber.org/protocol/pubsub#event");
+ parseEvent(event, packet.getFrom(), account);
}
}
}
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index d94f20da..1c114f60 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -528,7 +528,7 @@ public class XmppConnectionService extends Service {
} else {
message.getConversation().endOtrIfNeeded();
failWaitingOtrMessages(message.getConversation());
- if (message.getConversation().getMode() == Conversation.MODE_SINGLE) {
+ if (message.getConversation().getMode() == Conversation.MODE_SINGLE || message.getType() == Message.TYPE_PRIVATE) {
message.setStatus(Message.STATUS_SEND);
}
packet = mMessageGenerator.generateChat(message);
diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java
index 80369bbf..ab7ece23 100644
--- a/src/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/eu/siacs/conversations/ui/ConversationActivity.java
@@ -4,6 +4,7 @@ import java.io.FileNotFoundException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Contact;
@@ -185,7 +186,7 @@ public class ConversationActivity extends XmppActivity {
Message latestMessage = conv.getLatestMessage();
- if (latestMessage.getType() == Message.TYPE_TEXT) {
+ if (latestMessage.getType() == Message.TYPE_TEXT || latestMessage.getType() == Message.TYPE_PRIVATE) {
if ((latestMessage.getEncryption() != Message.ENCRYPTION_PGP)
&& (latestMessage.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED)) {
convLastMsg.setText(conv.getLatestMessage().getBody());
@@ -880,7 +881,11 @@ public class ConversationActivity extends XmppActivity {
final AsyncDrawable asyncDrawable = new AsyncDrawable(
getResources(), null, task);
imageView.setImageDrawable(asyncDrawable);
- task.execute(message);
+ try {
+ task.execute(message);
+ } catch (RejectedExecutionException e) {
+ return;
+ }
}
}
}
diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java
index 925949cd..fced1e38 100644
--- a/src/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/eu/siacs/conversations/ui/ConversationFragment.java
@@ -17,6 +17,7 @@ import eu.siacs.conversations.ui.EditMessage.OnEnterPressed;
import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected;
import eu.siacs.conversations.ui.adapter.MessageAdapter;
import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked;
+import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked;
import eu.siacs.conversations.utils.UIHelper;
import android.app.AlertDialog;
import android.app.Fragment;
@@ -160,10 +161,22 @@ public class ConversationFragment extends Fragment {
private void sendMessage() {
- if (mEditMessage.getText().length() < 1)
+ if (mEditMessage.getText().length() < 1) {
+ if (this.conversation.getMode() == Conversation.MODE_MULTI) {
+ conversation.setNextPresence(null);
+ updateChatMsgHint();
+ }
return;
+ }
Message message = new Message(conversation, mEditMessage.getText()
.toString(), conversation.getNextEncryption());
+ if (conversation.getMode() == Conversation.MODE_MULTI) {
+ if (conversation.getNextPresence() != null) {
+ message.setPresence(conversation.getNextPresence());
+ message.setType(Message.TYPE_PRIVATE);
+ conversation.setNextPresence(null);
+ }
+ }
if (conversation.getNextEncryption() == Message.ENCRYPTION_OTR) {
sendOtrMessage(message);
} else if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
@@ -230,7 +243,24 @@ public class ConversationFragment extends Fragment {
@Override
public void onContactPictureClicked(Message message) {
if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
- highlightInConference(message.getCounterpart());
+ if (message.getPresence() != null) {
+ highlightInConference(message.getPresence());
+ } else {
+ highlightInConference(message.getCounterpart());
+ }
+ }
+ }
+ });
+ messageListAdapter.setOnContactPictureLongClicked(new OnContactPictureLongClicked() {
+
+ @Override
+ public void onContactPictureLongClicked(Message message) {
+ if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
+ if (message.getPresence() != null) {
+ privateMessageWith(message.getPresence());
+ } else {
+ privateMessageWith(message.getCounterpart());
+ }
}
}
});
@@ -238,6 +268,12 @@ public class ConversationFragment extends Fragment {
return view;
}
+
+ protected void privateMessageWith(String counterpart) {
+ this.mEditMessage.setHint(getString(R.string.send_private_message_to,counterpart));
+ this.mEditMessage.setText("");
+ this.conversation.setNextPresence(counterpart);
+ }
protected void highlightInConference(String nick) {
String oldString = mEditMessage.getText().toString().trim();
@@ -272,6 +308,7 @@ public class ConversationFragment extends Fragment {
}
public void onBackendConnected() {
+ this.activity = (ConversationActivity) getActivity();
this.conversation = activity.getSelectedConversation();
if (this.conversation == null) {
return;
@@ -302,6 +339,9 @@ public class ConversationFragment extends Fragment {
activity.invalidateOptionsMenu();
}
}
+ if (this.conversation.getMode() == Conversation.MODE_MULTI) {
+ conversation.setNextPresence(null);
+ }
}
private void decryptMessage(Message message) {
@@ -405,6 +445,7 @@ public class ConversationFragment extends Fragment {
messagesView.setSelection(size - 1);
}
mEditMessage.setText("");
+ updateChatMsgHint();
}
protected void updateStatusMessages() {
diff --git a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java
index a84fc01c..ca475cc9 100644
--- a/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -14,6 +14,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Typeface;
+import android.text.Html;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
@@ -40,6 +41,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
private DisplayMetrics metrics;
private OnContactPictureClicked mOnContactPictureClickedListener;
+ private OnContactPictureLongClicked mOnContactPictureLongClickedListener;
public MessageAdapter(ConversationActivity activity, List<Message> messages) {
super(activity, 0, messages);
@@ -61,6 +63,10 @@ public class MessageAdapter extends ArrayAdapter<Message> {
public void setOnContactPictureClicked(OnContactPictureClicked listener) {
this.mOnContactPictureClickedListener = listener;
}
+
+ public void setOnContactPictureLongClicked(OnContactPictureLongClicked listener) {
+ this.mOnContactPictureLongClickedListener = listener;
+ }
@Override
public int getViewTypeCount() {
@@ -120,7 +126,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
if (contact != null) {
info = contact.getDisplayName();
} else {
- info = message.getCounterpart();
+ if (message.getPresence() != null) {
+ info = message.getPresence();
+ } else {
+ info = message.getCounterpart();
+ }
}
}
break;
@@ -190,14 +200,33 @@ public class MessageAdapter extends ArrayAdapter<Message> {
viewHolder.messageBody.setTextIsSelectable(false);
}
- private void displayTextMessage(ViewHolder viewHolder, String text) {
+ private void displayTextMessage(ViewHolder viewHolder, Message message) {
if (viewHolder.download_button != null) {
viewHolder.download_button.setVisibility(View.GONE);
}
viewHolder.image.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.VISIBLE);
- if (text != null) {
- viewHolder.messageBody.setText(text.trim());
+ if (message.getBody() != null) {
+ if (message.getType() != Message.TYPE_PRIVATE) {
+ viewHolder.messageBody.setText(message.getBody().trim());
+ } else {
+ StringBuilder builder = new StringBuilder();
+ builder.append(message.getBody().trim());
+ builder.append("&nbsp;<b><i>(");
+ if (message.getStatus() <= Message.STATUS_RECIEVED) {
+ builder.append(activity.getString(R.string.private_message));
+ } else {
+ String to;
+ if (message.getPresence() != null) {
+ to = message.getPresence();
+ } else {
+ to = message.getCounterpart();
+ }
+ builder.append(activity.getString(R.string.private_message_to, to));
+ }
+ builder.append(")</i></b>");
+ viewHolder.messageBody.setText(Html.fromHtml(builder.toString()));
+ }
} else {
viewHolder.messageBody.setText("");
}
@@ -376,6 +405,18 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
});
+ viewHolder.contact_picture.setOnLongClickListener(new OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ if (MessageAdapter.this.mOnContactPictureLongClickedListener != null) {
+ MessageAdapter.this.mOnContactPictureLongClickedListener.onContactPictureLongClicked(item);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ });
}
}
@@ -426,7 +467,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
} else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
displayDecryptionFailed(viewHolder);
} else {
- displayTextMessage(viewHolder, item.getBody());
+ displayTextMessage(viewHolder, item);
}
}
@@ -474,4 +515,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
public interface OnContactPictureClicked {
public void onContactPictureClicked(Message message);
}
+
+ public interface OnContactPictureLongClicked {
+ public void onContactPictureLongClicked(Message message);
+ }
}