ContactDetailsActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import java.util.Iterator;
  4
  5import org.openintents.openpgp.util.OpenPgpUtils;
  6
  7import android.app.AlertDialog;
  8import android.app.PendingIntent;
  9import android.content.Context;
 10import android.content.DialogInterface;
 11import android.content.Intent;
 12import android.content.IntentSender.SendIntentException;
 13import android.net.Uri;
 14import android.os.Bundle;
 15import android.provider.ContactsContract.CommonDataKinds;
 16import android.provider.ContactsContract.Contacts;
 17import android.provider.ContactsContract.Intents;
 18import android.view.LayoutInflater;
 19import android.view.Menu;
 20import android.view.MenuItem;
 21import android.view.View;
 22import android.view.View.OnClickListener;
 23import android.widget.CheckBox;
 24import android.widget.CompoundButton.OnCheckedChangeListener;
 25import android.widget.CompoundButton;
 26import android.widget.ImageButton;
 27import android.widget.LinearLayout;
 28import android.widget.QuickContactBadge;
 29import android.widget.TextView;
 30import eu.siacs.conversations.R;
 31import eu.siacs.conversations.crypto.PgpEngine;
 32import eu.siacs.conversations.entities.Account;
 33import eu.siacs.conversations.entities.Contact;
 34import eu.siacs.conversations.entities.Presences;
 35import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
 36import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
 37import eu.siacs.conversations.utils.UIHelper;
 38
 39public class ContactDetailsActivity extends XmppActivity {
 40	public static final String ACTION_VIEW_CONTACT = "view_contact";
 41
 42	private Contact contact;
 43
 44	private String accountJid;
 45	private String contactJid;
 46
 47	private TextView contactJidTv;
 48	private TextView accountJidTv;
 49	private TextView status;
 50	private TextView lastseen;
 51	private CheckBox send;
 52	private CheckBox receive;
 53	private QuickContactBadge badge;
 54
 55	private DialogInterface.OnClickListener removeFromRoster = new DialogInterface.OnClickListener() {
 56
 57		@Override
 58		public void onClick(DialogInterface dialog, int which) {
 59			ContactDetailsActivity.this.xmppConnectionService.deleteContactOnServer(contact);
 60			ContactDetailsActivity.this.finish();
 61		}
 62	};
 63
 64	private DialogInterface.OnClickListener addToPhonebook = new DialogInterface.OnClickListener() {
 65
 66		@Override
 67		public void onClick(DialogInterface dialog, int which) {
 68			Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
 69			intent.setType(Contacts.CONTENT_ITEM_TYPE);
 70			intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid());
 71			intent.putExtra(Intents.Insert.IM_PROTOCOL,
 72					CommonDataKinds.Im.PROTOCOL_JABBER);
 73			intent.putExtra("finishActivityOnSaveCompleted", true);
 74			ContactDetailsActivity.this.startActivityForResult(intent, 0);
 75		}
 76	};
 77	private OnClickListener onBadgeClick = new OnClickListener() {
 78
 79		@Override
 80		public void onClick(View v) {
 81			AlertDialog.Builder builder = new AlertDialog.Builder(ContactDetailsActivity.this);
 82			builder.setTitle(getString(R.string.action_add_phone_book));
 83			builder.setMessage(getString(R.string.add_phone_book_text,
 84					contact.getJid()));
 85			builder.setNegativeButton(getString(R.string.cancel), null);
 86			builder.setPositiveButton(getString(R.string.add), addToPhonebook);
 87			builder.create().show();
 88		}
 89	};
 90
 91	private LinearLayout keys;
 92
 93	private OnRosterUpdate rosterUpdate = new OnRosterUpdate() {
 94
 95		@Override
 96		public void onRosterUpdate() {
 97			runOnUiThread(new Runnable() {
 98
 99				@Override
100				public void run() {
101					populateView();
102				}
103			});
104		}
105	};
106
107	private OnCheckedChangeListener mOnSendCheckedChange = new OnCheckedChangeListener() {
108
109		@Override
110		public void onCheckedChanged(CompoundButton buttonView,
111				boolean isChecked) {
112			if (isChecked) {
113				if (contact
114						.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
115					xmppConnectionService.sendPresencePacket(contact
116							.getAccount(),
117							xmppConnectionService.getPresenceGenerator()
118									.sendPresenceUpdatesTo(contact));
119				} else {
120					contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
121				}
122			} else {
123				contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
124				xmppConnectionService.sendPresencePacket(contact.getAccount(),
125						xmppConnectionService.getPresenceGenerator()
126								.stopPresenceUpdatesTo(contact));
127			}
128		}
129	};
130
131	private OnCheckedChangeListener mOnReceiveCheckedChange = new OnCheckedChangeListener() {
132
133		@Override
134		public void onCheckedChanged(CompoundButton buttonView,
135				boolean isChecked) {
136			if (isChecked) {
137				xmppConnectionService.sendPresencePacket(contact.getAccount(),
138						xmppConnectionService.getPresenceGenerator()
139								.requestPresenceUpdatesFrom(contact));
140			} else {
141				xmppConnectionService.sendPresencePacket(contact.getAccount(),
142						xmppConnectionService.getPresenceGenerator()
143								.stopPresenceUpdatesFrom(contact));
144			}
145		}
146	};
147
148	private OnAccountUpdate accountUpdate = new OnAccountUpdate() {
149
150		@Override
151		public void onAccountUpdate() {
152			runOnUiThread(new Runnable() {
153
154				@Override
155				public void run() {
156					populateView();
157				}
158			});
159		}
160	};
161
162	@Override
163	protected void onCreate(Bundle savedInstanceState) {
164		super.onCreate(savedInstanceState);
165		if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
166			this.accountJid = getIntent().getExtras().getString("account");
167			this.contactJid = getIntent().getExtras().getString("contact");
168		}
169		setContentView(R.layout.activity_contact_details);
170
171		contactJidTv = (TextView) findViewById(R.id.details_contactjid);
172		accountJidTv = (TextView) findViewById(R.id.details_account);
173		status = (TextView) findViewById(R.id.details_contactstatus);
174		lastseen = (TextView) findViewById(R.id.details_lastseen);
175		send = (CheckBox) findViewById(R.id.details_send_presence);
176		receive = (CheckBox) findViewById(R.id.details_receive_presence);
177		badge = (QuickContactBadge) findViewById(R.id.details_contact_badge);
178		keys = (LinearLayout) findViewById(R.id.details_contact_keys);
179		getActionBar().setHomeButtonEnabled(true);
180		getActionBar().setDisplayHomeAsUpEnabled(true);
181
182	}
183
184	@Override
185	public boolean onOptionsItemSelected(MenuItem menuItem) {
186		AlertDialog.Builder builder = new AlertDialog.Builder(this);
187		builder.setNegativeButton(getString(R.string.cancel), null);
188		switch (menuItem.getItemId()) {
189		case android.R.id.home:
190			finish();
191			break;
192		case R.id.action_delete_contact:
193			builder.setTitle(getString(R.string.action_delete_contact))
194					.setMessage(
195							getString(R.string.remove_contact_text,
196									contact.getJid()))
197					.setPositiveButton(getString(R.string.delete),
198							removeFromRoster).create().show();
199			break;
200		case R.id.action_edit_contact:
201			if (contact.getSystemAccount() == null) {
202				quickEdit(contact.getDisplayName(), new OnValueEdited() {
203
204					@Override
205					public void onValueEdited(String value) {
206						contact.setServerName(value);
207						ContactDetailsActivity.this.xmppConnectionService
208								.pushContactToServer(contact);
209						populateView();
210					}
211				});
212			} else {
213				Intent intent = new Intent(Intent.ACTION_EDIT);
214				String[] systemAccount = contact.getSystemAccount().split("#");
215				long id = Long.parseLong(systemAccount[0]);
216				Uri uri = Contacts.getLookupUri(id, systemAccount[1]);
217				intent.setDataAndType(uri, Contacts.CONTENT_ITEM_TYPE);
218				intent.putExtra("finishActivityOnSaveCompleted", true);
219				startActivity(intent);
220			}
221			break;
222		}
223		return super.onOptionsItemSelected(menuItem);
224	}
225
226	@Override
227	public boolean onCreateOptionsMenu(Menu menu) {
228		getMenuInflater().inflate(R.menu.contact_details, menu);
229		return true;
230	}
231
232	private void populateView() {
233		send.setOnCheckedChangeListener(null);
234		receive.setOnCheckedChangeListener(null);
235		setTitle(contact.getDisplayName());
236		if (contact.getOption(Contact.Options.FROM)) {
237			send.setText(R.string.send_presence_updates);
238			send.setChecked(true);
239		} else if (contact
240				.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
241			send.setChecked(false);
242			send.setText(R.string.send_presence_updates);
243		} else {
244			send.setText(R.string.preemptively_grant);
245			if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
246				send.setChecked(true);
247			} else {
248				send.setChecked(false);
249			}
250		}
251		if (contact.getOption(Contact.Options.TO)) {
252			receive.setText(R.string.receive_presence_updates);
253			receive.setChecked(true);
254		} else {
255			receive.setText(R.string.ask_for_presence_updates);
256			if (contact.getOption(Contact.Options.ASKING)) {
257				receive.setChecked(true);
258			} else {
259				receive.setChecked(false);
260			}
261		}
262		if (contact.getAccount().getStatus() == Account.STATUS_ONLINE) {
263			receive.setEnabled(true);
264			send.setEnabled(true);
265		} else {
266			receive.setEnabled(false);
267			send.setEnabled(false);
268		}
269
270		send.setOnCheckedChangeListener(this.mOnSendCheckedChange);
271		receive.setOnCheckedChangeListener(this.mOnReceiveCheckedChange);
272
273		lastseen.setText(UIHelper.lastseen(getApplicationContext(),
274				contact.lastseen.time));
275
276		switch (contact.getMostAvailableStatus()) {
277		case Presences.CHAT:
278			status.setText(R.string.contact_status_free_to_chat);
279			status.setTextColor(mColorGreen);
280			break;
281		case Presences.ONLINE:
282			status.setText(R.string.contact_status_online);
283			status.setTextColor(mColorGreen);
284			break;
285		case Presences.AWAY:
286			status.setText(R.string.contact_status_away);
287			status.setTextColor(mColorOrange);
288			break;
289		case Presences.XA:
290			status.setText(R.string.contact_status_extended_away);
291			status.setTextColor(mColorOrange);
292			break;
293		case Presences.DND:
294			status.setText(R.string.contact_status_do_not_disturb);
295			status.setTextColor(mColorRed);
296			break;
297		case Presences.OFFLINE:
298			status.setText(R.string.contact_status_offline);
299			status.setTextColor(mSecondaryTextColor);
300			break;
301		default:
302			status.setText(R.string.contact_status_offline);
303			status.setTextColor(mSecondaryTextColor);
304			break;
305		}
306		if (contact.getPresences().size() > 1) {
307			contactJidTv.setText(contact.getJid() + " ("
308					+ contact.getPresences().size() + ")");
309		} else {
310			contactJidTv.setText(contact.getJid());
311		}
312		accountJidTv.setText(contact.getAccount().getJid());
313
314		UIHelper.prepareContactBadge(this, badge, contact,
315				getApplicationContext());
316
317		if (contact.getSystemAccount() == null) {
318			badge.setOnClickListener(onBadgeClick);
319		}
320
321		keys.removeAllViews();
322		LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
323		for (Iterator<String> iterator = contact.getOtrFingerprints()
324				.iterator(); iterator.hasNext();) {
325			final String otrFingerprint = iterator.next();
326			View view = (View) inflater.inflate(R.layout.contact_key, keys,
327					false);
328			TextView key = (TextView) view.findViewById(R.id.key);
329			TextView keyType = (TextView) view.findViewById(R.id.key_type);
330			ImageButton remove = (ImageButton) view
331					.findViewById(R.id.button_remove);
332			remove.setVisibility(View.VISIBLE);
333			keyType.setText("OTR Fingerprint");
334			key.setText(otrFingerprint);
335			keys.addView(view);
336			remove.setOnClickListener(new OnClickListener() {
337
338				@Override
339				public void onClick(View v) {
340					confirmToDeleteFingerprint(otrFingerprint);
341				}
342			});
343		}
344		if (contact.getPgpKeyId() != 0) {
345			View view = (View) inflater.inflate(R.layout.contact_key, keys,
346					false);
347			TextView key = (TextView) view.findViewById(R.id.key);
348			TextView keyType = (TextView) view.findViewById(R.id.key_type);
349			keyType.setText("PGP Key ID");
350			key.setText(OpenPgpUtils.convertKeyIdToHex(contact.getPgpKeyId()));
351			view.setOnClickListener(new OnClickListener() {
352
353				@Override
354				public void onClick(View v) {
355					PgpEngine pgp = ContactDetailsActivity.this.xmppConnectionService
356							.getPgpEngine();
357					if (pgp != null) {
358						PendingIntent intent = pgp.getIntentForKey(contact);
359						if (intent != null) {
360							try {
361								startIntentSenderForResult(
362										intent.getIntentSender(), 0, null, 0,
363										0, 0);
364							} catch (SendIntentException e) {
365
366							}
367						}
368					}
369				}
370			});
371			keys.addView(view);
372		}
373	}
374
375	protected void confirmToDeleteFingerprint(final String fingerprint) {
376		AlertDialog.Builder builder = new AlertDialog.Builder(this);
377		builder.setTitle(R.string.delete_fingerprint);
378		builder.setMessage(R.string.sure_delete_fingerprint);
379		builder.setNegativeButton(R.string.cancel, null);
380		builder.setPositiveButton(R.string.delete,
381				new android.content.DialogInterface.OnClickListener() {
382
383					@Override
384					public void onClick(DialogInterface dialog, int which) {
385						if (contact.deleteOtrFingerprint(fingerprint)) {
386							populateView();
387							xmppConnectionService.syncRosterToDisk(contact
388									.getAccount());
389						}
390					}
391
392				});
393		builder.create().show();
394	}
395
396	@Override
397	public void onBackendConnected() {
398		xmppConnectionService.setOnRosterUpdateListener(this.rosterUpdate);
399		xmppConnectionService
400				.setOnAccountListChangedListener(this.accountUpdate);
401		if ((accountJid != null) && (contactJid != null)) {
402			Account account = xmppConnectionService
403					.findAccountByJid(accountJid);
404			if (account == null) {
405				return;
406			}
407			this.contact = account.getRoster().getContact(contactJid);
408			populateView();
409		}
410	}
411
412	@Override
413	protected void onStop() {
414		super.onStop();
415		xmppConnectionService.removeOnRosterUpdateListener();
416		xmppConnectionService.removeOnAccountListChangedListener();
417	}
418
419}