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