aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/de/gultsch/chat/entities/Contact.java1
-rw-r--r--src/de/gultsch/chat/entities/Message.java1
-rw-r--r--src/de/gultsch/chat/services/XmppConnectionService.java53
-rw-r--r--src/de/gultsch/chat/ui/ConversationActivity.java23
-rw-r--r--src/de/gultsch/chat/ui/ConversationFragment.java97
-rw-r--r--src/de/gultsch/chat/ui/DialogContactDetails.java65
-rw-r--r--src/de/gultsch/chat/utils/MessageParser.java15
-rw-r--r--src/de/gultsch/chat/utils/UIHelper.java22
-rw-r--r--src/de/gultsch/chat/xmpp/MessagePacket.java3
9 files changed, 204 insertions, 76 deletions
diff --git a/src/de/gultsch/chat/entities/Contact.java b/src/de/gultsch/chat/entities/Contact.java
index c899603fc..eff46e53b 100644
--- a/src/de/gultsch/chat/entities/Contact.java
+++ b/src/de/gultsch/chat/entities/Contact.java
@@ -44,6 +44,7 @@ public class Contact extends AbstractEntity implements Serializable {
} else {
this.accountUuid = account.getUuid();
}
+ this.account = account;
this.displayName = displayName;
this.jid = jid;
this.photoUri = photoUri;
diff --git a/src/de/gultsch/chat/entities/Message.java b/src/de/gultsch/chat/entities/Message.java
index 73a6e46cc..9b308c754 100644
--- a/src/de/gultsch/chat/entities/Message.java
+++ b/src/de/gultsch/chat/entities/Message.java
@@ -12,6 +12,7 @@ public class Message extends AbstractEntity {
public static final int STATUS_RECIEVED = 0;
public static final int STATUS_UNSEND = 1;
public static final int STATUS_SEND = 2;
+ public static final int STATUS_ERROR = 3;
public static final int ENCRYPTION_NONE = 0;
public static final int ENCRYPTION_PGP = 1;
diff --git a/src/de/gultsch/chat/services/XmppConnectionService.java b/src/de/gultsch/chat/services/XmppConnectionService.java
index 7111d94a2..2bff2af42 100644
--- a/src/de/gultsch/chat/services/XmppConnectionService.java
+++ b/src/de/gultsch/chat/services/XmppConnectionService.java
@@ -103,6 +103,8 @@ public class XmppConnectionService extends Service {
if (message != null) {
notify = (message.getStatus() == Message.STATUS_RECIEVED);
}
+ } else if (packet.getType() == MessagePacket.TYPE_ERROR) {
+ message = MessageParser.parseError(packet,account,service);
} else {
Log.d(LOGTAG, "unparsed message " + packet.toString());
}
@@ -126,7 +128,9 @@ public class XmppConnectionService extends Service {
}
Conversation conversation = message.getConversation();
conversation.getMessages().add(message);
- databaseBackend.createMessage(message);
+ if (packet.getType() != MessagePacket.TYPE_ERROR) {
+ databaseBackend.createMessage(message);
+ }
if (convChangedListener != null) {
convChangedListener.onConversationListChanged();
} else {
@@ -171,7 +175,7 @@ public class XmppConnectionService extends Service {
Contact contact = findContact(account, fromParts[0]);
if (contact == null) {
// most likely muc, self or roster not synced
- // Log.d(LOGTAG,"got presence for non contact "+packet.toString());
+ Log.d(LOGTAG,"got presence for non contact "+packet.toString());
return;
}
String type = packet.getAttribute("type");
@@ -197,7 +201,7 @@ public class XmppConnectionService extends Service {
databaseBackend.updateContact(contact);
}
}
- replaceContactInConversation(contact);
+ replaceContactInConversation(contact.getJid(),contact);
}
};
@@ -233,21 +237,21 @@ public class XmppConnectionService extends Service {
} else {
if (subscription.equals("remove")) {
databaseBackend.deleteContact(contact);
+ replaceContactInConversation(contact.getJid(), null);
} else {
contact.setSubscription(subscription);
databaseBackend.updateContact(contact);
- replaceContactInConversation(contact);
+ replaceContactInConversation(contact.getJid(),contact);
}
}
}
}
}
- private void replaceContactInConversation(Contact contact) {
+ private void replaceContactInConversation(String jid, Contact contact) {
List<Conversation> conversations = getConversations();
for (int i = 0; i < conversations.size(); ++i) {
- if ((conversations.get(i).getContact() != null)
- && (conversations.get(i).getContact().equals(contact))) {
+ if ((conversations.get(i).getContactJid().equals(jid))) {
conversations.get(i).setContact(contact);
break;
}
@@ -458,6 +462,7 @@ public class XmppConnectionService extends Service {
List<Contact> contactsToDelete = databaseBackend.getContats(mWhere.toString());
for(Contact contact : contactsToDelete) {
databaseBackend.deleteContact(contact);
+ replaceContactInConversation(contact.getJid(), null);
}
}
mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
@@ -517,10 +522,6 @@ public class XmppConnectionService extends Service {
});
}
- public void addConversation(Conversation conversation) {
- databaseBackend.createConversation(conversation);
- }
-
public List<Conversation> getConversations() {
if (this.conversations == null) {
Hashtable<String, Account> accountLookupTable = new Hashtable<String, Account>();
@@ -629,6 +630,20 @@ public class XmppConnectionService extends Service {
if (accountChangedListener != null)
accountChangedListener.onAccountListChangedListener();
}
+
+ public void deleteContact(Contact contact) {
+ IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+ Element query = new Element("query");
+ query.setAttribute("xmlns", "jabber:iq:roster");
+ Element item = new Element("item");
+ item.setAttribute("jid", contact.getJid());
+ item.setAttribute("subscription", "remove");
+ query.addChild(item);
+ iq.addChild(query);
+ contact.getAccount().getXmppConnection().sendIqPacket(iq, null);
+ replaceContactInConversation(contact.getJid(), null);
+ databaseBackend.deleteContact(contact);
+ }
public void updateAccount(Account account) {
databaseBackend.updateAccount(account);
@@ -735,4 +750,20 @@ public class XmppConnectionService extends Service {
public void updateContact(Contact contact) {
databaseBackend.updateContact(contact);
}
+
+ public void createContact(Contact contact) {
+ IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
+ Element query = new Element("query");
+ query.setAttribute("xmlns", "jabber:iq:roster");
+ Element item = new Element("item");
+ item.setAttribute("jid", contact.getJid());
+ item.setAttribute("name", contact.getJid());
+ query.addChild(item);
+ iq.addChild(query);
+ Account account = contact.getAccount();
+ Log.d(LOGTAG,account.getJid()+": adding "+contact.getJid()+" to roster");
+ account.getXmppConnection().sendIqPacket(iq, null);
+ replaceContactInConversation(contact.getJid(), contact);
+ databaseBackend.createContact(contact);
+ }
} \ No newline at end of file
diff --git a/src/de/gultsch/chat/ui/ConversationActivity.java b/src/de/gultsch/chat/ui/ConversationActivity.java
index 464054ad9..f9a924ecf 100644
--- a/src/de/gultsch/chat/ui/ConversationActivity.java
+++ b/src/de/gultsch/chat/ui/ConversationActivity.java
@@ -7,15 +7,18 @@ import java.util.List;
import de.gultsch.chat.R;
import de.gultsch.chat.R.id;
+import de.gultsch.chat.entities.Account;
import de.gultsch.chat.entities.Contact;
import de.gultsch.chat.entities.Conversation;
import de.gultsch.chat.entities.Message;
import de.gultsch.chat.utils.UIHelper;
import android.net.Uri;
import android.os.Bundle;
+import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Typeface;
import android.support.v4.widget.SlidingPaneLayout;
@@ -82,6 +85,18 @@ public class ConversationActivity extends XmppActivity {
});
}
};
+
+ private DialogInterface.OnClickListener addToRoster = new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String jid = getSelectedConversation().getContactJid();
+ Account account = getSelectedConversation().getAccount();
+ String name = jid.split("@")[0];
+ Contact contact = new Contact(account, name, jid, null);
+ xmppConnectionService.createContact(contact);
+ }
+ };
private boolean contactInserted = false;
@@ -288,7 +303,13 @@ public class ConversationActivity extends XmppActivity {
details.setContact(contact);
details.show(getFragmentManager(), "details");
} else {
- Log.d("xmppService","contact was null - means not in roster");
+ String jid = getSelectedConversation().getContactJid();
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(jid);
+ builder.setMessage("The contact is not in your roster. Would you like to add it.");
+ builder.setNegativeButton("Cancel", null);
+ builder.setPositiveButton("Add",addToRoster);
+ builder.create().show();
}
break;
case R.id.action_security:
diff --git a/src/de/gultsch/chat/ui/ConversationFragment.java b/src/de/gultsch/chat/ui/ConversationFragment.java
index 0d2116e62..1770e7bd7 100644
--- a/src/de/gultsch/chat/ui/ConversationFragment.java
+++ b/src/de/gultsch/chat/ui/ConversationFragment.java
@@ -8,6 +8,8 @@ import java.util.Hashtable;
import java.util.List;
import java.util.Set;
+import javax.crypto.spec.PSource;
+
import net.java.otr4j.OtrException;
import net.java.otr4j.session.SessionStatus;
@@ -53,6 +55,8 @@ public class ConversationFragment extends Fragment {
protected BitmapCache mBitmapCache = new BitmapCache();
private EditText chatMsg;
+
+ protected Bitmap selfBitmap;
private OnClickListener sendMsgListener = new OnClickListener() {
@@ -105,47 +109,26 @@ public class ConversationFragment extends Fragment {
sendButton.setOnClickListener(this.sendMsgListener);
messagesView = (ListView) view.findViewById(R.id.messages_view);
-
- SharedPreferences sharedPref = PreferenceManager
- .getDefaultSharedPreferences(getActivity()
- .getApplicationContext());
- boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
- "show_phone_selfcontact_picture", true);
-
- Bitmap self;
-
- if (showPhoneSelfContactPicture) {
- Uri selfiUri = PhoneHelper.getSefliUri(getActivity());
- try {
- self = BitmapFactory.decodeStream(getActivity()
- .getContentResolver().openInputStream(selfiUri));
- } catch (FileNotFoundException e) {
- self = UIHelper.getUnknownContactPicture(conversation
- .getAccount().getJid(), 200);
- }
- } else {
- self = UIHelper.getUnknownContactPicture(conversation.getAccount()
- .getJid(), 200);
- }
-
- final Bitmap selfBitmap = self;
-
+
messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
.getApplicationContext(), R.layout.message_sent,
this.messageList) {
private static final int SENT = 0;
private static final int RECIEVED = 1;
+ private static final int ERROR = 2;
@Override
public int getViewTypeCount() {
- return 2;
+ return 3;
}
@Override
public int getItemViewType(int position) {
if (getItem(position).getStatus() == Message.STATUS_RECIEVED) {
return RECIEVED;
+ } else if (getItem(position).getStatus() == Message.STATUS_ERROR) {
+ return ERROR;
} else {
return SENT;
}
@@ -167,7 +150,6 @@ public class ConversationFragment extends Fragment {
viewHolder.imageView.setImageBitmap(selfBitmap);
break;
case RECIEVED:
- viewHolder = new ViewHolder();
view = (View) inflater.inflate(
R.layout.message_recieved, null);
viewHolder.imageView = (ImageView) view
@@ -185,6 +167,12 @@ public class ConversationFragment extends Fragment {
}
}
break;
+ case ERROR:
+ view = (View) inflater.inflate(R.layout.message_error, null);
+ viewHolder.imageView = (ImageView) view
+ .findViewById(R.id.message_photo);
+ viewHolder.imageView.setImageBitmap(mBitmapCache.getError());
+ break;
default:
viewHolder = null;
break;
@@ -193,7 +181,6 @@ public class ConversationFragment extends Fragment {
.findViewById(R.id.message_body);
viewHolder.time = (TextView) view
.findViewById(R.id.message_time);
-
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
@@ -238,31 +225,47 @@ public class ConversationFragment extends Fragment {
return view;
}
+ protected Bitmap findSelfPicture() {
+ SharedPreferences sharedPref = PreferenceManager
+ .getDefaultSharedPreferences(getActivity()
+ .getApplicationContext());
+ boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
+ "show_phone_selfcontact_picture", true);
+
+ Bitmap self;
+
+ if (showPhoneSelfContactPicture) {
+ Uri selfiUri = PhoneHelper.getSefliUri(getActivity());
+ try {
+ self = BitmapFactory.decodeStream(getActivity()
+ .getContentResolver().openInputStream(selfiUri));
+ } catch (FileNotFoundException e) {
+ self = UIHelper.getUnknownContactPicture(conversation
+ .getAccount().getJid(), 200);
+ }
+ } else {
+ self = UIHelper.getUnknownContactPicture(conversation.getAccount()
+ .getJid(), 200);
+ }
+
+ final Bitmap selfBitmap = self;
+ return selfBitmap;
+ }
+
@Override
public void onStart() {
super.onStart();
- final ConversationActivity activity = (ConversationActivity) getActivity();
+ ConversationActivity activity = (ConversationActivity) getActivity();
if (activity.xmppConnectionServiceBound) {
- this.conversation = activity.getSelectedConversation();
- updateMessages();
- // rendering complete. now go tell activity to close pane
- if (!activity.shouldPaneBeOpen()) {
- activity.getSlidingPaneLayout().closePane();
- activity.getActionBar().setDisplayHomeAsUpEnabled(true);
- activity.getActionBar().setTitle(conversation.getName());
- activity.invalidateOptionsMenu();
- if (!conversation.isRead()) {
- conversation.markRead();
- activity.updateConversationList();
- }
- }
+ this.onBackendConnected();
}
}
public void onBackendConnected() {
final ConversationActivity activity = (ConversationActivity) getActivity();
this.conversation = activity.getSelectedConversation();
+ this.selfBitmap = findSelfPicture();
updateMessages();
// rendering complete. now go tell activity to close pane
if (!activity.shouldPaneBeOpen()) {
@@ -353,7 +356,7 @@ public class ConversationFragment extends Fragment {
} else {
presences = null;
}
- if ((presences != null) && (presences.size() == 0)) {
+ if ((presences == null) || (presences.size() == 0)) {
AlertDialog.Builder builder = new AlertDialog.Builder(
getActivity());
builder.setTitle("Contact is offline");
@@ -412,6 +415,7 @@ public class ConversationFragment extends Fragment {
private class BitmapCache {
private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
+ private Bitmap error = null;
public Bitmap get(String name, Uri uri) {
if (bitmaps.containsKey(name)) {
@@ -432,5 +436,12 @@ public class ConversationFragment extends Fragment {
return bm;
}
}
+
+ public Bitmap getError() {
+ if (error == null) {
+ error = UIHelper.getErrorPicture(200);
+ }
+ return error;
+ }
}
}
diff --git a/src/de/gultsch/chat/ui/DialogContactDetails.java b/src/de/gultsch/chat/ui/DialogContactDetails.java
index 88bded870..20be4b397 100644
--- a/src/de/gultsch/chat/ui/DialogContactDetails.java
+++ b/src/de/gultsch/chat/ui/DialogContactDetails.java
@@ -9,7 +9,6 @@ import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
@@ -18,7 +17,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
-import android.widget.ImageView;
import android.widget.QuickContactBadge;
import android.widget.TextView;
@@ -27,13 +25,53 @@ public class DialogContactDetails extends DialogFragment {
private Contact contact = null;
boolean displayingInRoster = false;
+ private DialogContactDetails mDetailsDialog = this;
+ private XmppActivity activity;
+
+ private DialogInterface.OnClickListener askRemoveFromRoster = new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle("Delete from roster");
+ builder.setMessage("Do you want to delete "+contact.getJid()+" from your roster. The conversation assoziated with this account will not be removed.");
+ builder.setNegativeButton("Cancel", null);
+ builder.setPositiveButton("Delete",removeFromRoster);
+ builder.create().show();
+ }
+ };
+
+ private DialogInterface.OnClickListener removeFromRoster = new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ activity.xmppConnectionService.deleteContact(contact);
+ mDetailsDialog.dismiss();
+ }
+ };
+
+ private DialogInterface.OnClickListener addToPhonebook = new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ intent.setType(Contacts.CONTENT_ITEM_TYPE);
+ intent.putExtra(Intents.Insert.IM_HANDLE,contact.getJid());
+ intent.putExtra(Intents.Insert.IM_PROTOCOL,CommonDataKinds.Im.PROTOCOL_JABBER);
+ intent.putExtra("finishActivityOnSaveCompleted", true);
+ getActivity().startActivityForResult(intent,ConversationActivity.INSERT_CONTACT);
+ mDetailsDialog.dismiss();
+ }
+ };
+
public void setContact(Contact contact) {
this.contact = contact;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ this.activity = (XmppActivity) getActivity();
+ AlertDialog.Builder builder = new AlertDialog.Builder(this.activity);
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_contact_details, null);
TextView contactJid = (TextView) view.findViewById(R.id.details_contactjid);
@@ -96,28 +134,15 @@ public class DialogContactDetails extends DialogFragment {
UIHelper.prepareContactBadge(getActivity(), badge, contact);
if (contact.getSystemAccount()==null) {
- final DialogContactDetails details = this;
badge.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle("Add to contacts");
- builder.setMessage("Do you want to add "+contact.getJid()+" to your contact list?");
+ builder.setTitle("Add to phone book");
+ builder.setMessage("Do you want to add "+contact.getJid()+" to your phones contact list?");
builder.setNegativeButton("Cancel", null);
- builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.setType(Contacts.CONTENT_ITEM_TYPE);
- intent.putExtra(Intents.Insert.IM_HANDLE,contact.getJid());
- intent.putExtra(Intents.Insert.IM_PROTOCOL,CommonDataKinds.Im.PROTOCOL_JABBER);
- intent.putExtra("finishActivityOnSaveCompleted", true);
- getActivity().startActivityForResult(intent,ConversationActivity.INSERT_CONTACT);
- details.dismiss();
- }
- });
+ builder.setPositiveButton("Add",addToPhonebook);
builder.create().show();
}
});
@@ -127,7 +152,7 @@ public class DialogContactDetails extends DialogFragment {
builder.setTitle(contact.getDisplayName());
builder.setNeutralButton("Done", null);
- builder.setPositiveButton("Remove from roster", null);
+ builder.setPositiveButton("Remove from roster", this.askRemoveFromRoster);
return builder.create();
}
}
diff --git a/src/de/gultsch/chat/utils/MessageParser.java b/src/de/gultsch/chat/utils/MessageParser.java
index aec492c84..1dca73432 100644
--- a/src/de/gultsch/chat/utils/MessageParser.java
+++ b/src/de/gultsch/chat/utils/MessageParser.java
@@ -116,4 +116,19 @@ public class MessageParser {
Conversation conversation = service.findOrCreateConversation(account, parts[0],false);
return new Message(conversation,fullJid, message.findChild("body").getContent(), Message.ENCRYPTION_NONE,status);
}
+
+ public static Message parseError(MessagePacket packet, Account account, XmppConnectionService service) {
+
+ String[] fromParts = packet.getFrom().split("/");
+ Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false);
+ Element error = packet.findChild("error");
+ String errorName = error.getChildren().get(0).getName();
+ String displayError;
+ if (errorName.equals("service-unavailable")) {
+ displayError = "Contact is offline and does not have offline storage";
+ } else {
+ displayError = errorName.replace("-", " ");
+ }
+ return new Message(conversation, packet.getFrom(), displayError, Message.ENCRYPTION_NONE, Message.STATUS_ERROR);
+ }
}
diff --git a/src/de/gultsch/chat/utils/UIHelper.java b/src/de/gultsch/chat/utils/UIHelper.java
index 52292a0f4..5e81f0990 100644
--- a/src/de/gultsch/chat/utils/UIHelper.java
+++ b/src/de/gultsch/chat/utils/UIHelper.java
@@ -54,7 +54,7 @@ public class UIHelper {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
return sdf.format(date);
} else {
- SimpleDateFormat sdf = new SimpleDateFormat("M/D");
+ SimpleDateFormat sdf = new SimpleDateFormat("MM/dd");
return sdf.format(date);
}
}
@@ -85,6 +85,26 @@ public class UIHelper {
return bitmap;
}
+
+ public static Bitmap getErrorPicture(int size) {
+ Bitmap bitmap = Bitmap
+ .createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+
+ bitmap.eraseColor(0xFFe92727);
+
+ Paint paint = new Paint();
+ paint.setColor(0xffe5e5e5);
+ paint.setTextSize((float) (size * 0.9));
+ paint.setAntiAlias(true);
+ Rect rect = new Rect();
+ paint.getTextBounds("!", 0, 1, rect);
+ float width = paint.measureText("!");
+ canvas.drawText("!", (size / 2) - (width / 2), (size / 2)
+ + (rect.height() / 2), paint);
+
+ return bitmap;
+ }
public static Notification getUnreadMessageNotification(Context context,
Conversation conversation) {
diff --git a/src/de/gultsch/chat/xmpp/MessagePacket.java b/src/de/gultsch/chat/xmpp/MessagePacket.java
index 0d4d07d7d..160a8c0ad 100644
--- a/src/de/gultsch/chat/xmpp/MessagePacket.java
+++ b/src/de/gultsch/chat/xmpp/MessagePacket.java
@@ -7,6 +7,7 @@ public class MessagePacket extends Element {
public static final int TYPE_UNKNOWN = 1;
public static final int TYPE_NO = 2;
public static final int TYPE_GROUPCHAT = 3;
+ public static final int TYPE_ERROR = 4;
private MessagePacket(String name) {
super(name);
@@ -71,6 +72,8 @@ public class MessagePacket extends Element {
return TYPE_CHAT;
} else if (type.equals("groupchat")) {
return TYPE_GROUPCHAT;
+ } else if (type.equals("error")) {
+ return TYPE_ERROR;
} else {
return TYPE_UNKNOWN;
}