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.LinearLayout;
27import android.widget.QuickContactBadge;
28import android.widget.TextView;
29import eu.siacs.conversations.R;
30import eu.siacs.conversations.crypto.PgpEngine;
31import eu.siacs.conversations.entities.Account;
32import eu.siacs.conversations.entities.Contact;
33import eu.siacs.conversations.entities.Presences;
34import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
35import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
36import eu.siacs.conversations.utils.UIHelper;
37
38public class ContactDetailsActivity extends XmppActivity {
39 public static final String ACTION_VIEW_CONTACT = "view_contact";
40
41 protected ContactDetailsActivity activity = this;
42
43 private Contact contact;
44
45 private String accountJid;
46 private String contactJid;
47
48 private TextView contactJidTv;
49 private TextView accountJidTv;
50 private TextView status;
51 private TextView lastseen;
52 private CheckBox send;
53 private CheckBox receive;
54 private QuickContactBadge badge;
55
56 private DialogInterface.OnClickListener removeFromRoster = new DialogInterface.OnClickListener() {
57
58 @Override
59 public void onClick(DialogInterface dialog, int which) {
60 activity.xmppConnectionService.deleteContactOnServer(contact);
61 activity.finish();
62 }
63 };
64
65 private DialogInterface.OnClickListener addToPhonebook = new DialogInterface.OnClickListener() {
66
67 @Override
68 public void onClick(DialogInterface dialog, int which) {
69 Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
70 intent.setType(Contacts.CONTENT_ITEM_TYPE);
71 intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid());
72 intent.putExtra(Intents.Insert.IM_PROTOCOL,
73 CommonDataKinds.Im.PROTOCOL_JABBER);
74 intent.putExtra("finishActivityOnSaveCompleted", true);
75 activity.startActivityForResult(intent, 0);
76 }
77 };
78 private OnClickListener onBadgeClick = new OnClickListener() {
79
80 @Override
81 public void onClick(View v) {
82 AlertDialog.Builder builder = new AlertDialog.Builder(activity);
83 builder.setTitle(getString(R.string.action_add_phone_book));
84 builder.setMessage(getString(R.string.add_phone_book_text,
85 contact.getJid()));
86 builder.setNegativeButton(getString(R.string.cancel), null);
87 builder.setPositiveButton(getString(R.string.add), addToPhonebook);
88 builder.create().show();
89 }
90 };
91
92 private LinearLayout keys;
93
94 private OnRosterUpdate rosterUpdate = new OnRosterUpdate() {
95
96 @Override
97 public void onRosterUpdate() {
98 runOnUiThread(new Runnable() {
99
100 @Override
101 public void run() {
102 populateView();
103 }
104 });
105 }
106 };
107
108 private OnCheckedChangeListener mOnSendCheckedChange = new OnCheckedChangeListener() {
109
110 @Override
111 public void onCheckedChanged(CompoundButton buttonView,
112 boolean isChecked) {
113 if (isChecked) {
114 if (contact.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 send.setOnCheckedChangeListener(this.mOnSendCheckedChange);
177 receive = (CheckBox) findViewById(R.id.details_receive_presence);
178 receive.setOnCheckedChangeListener(this.mOnReceiveCheckedChange);
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 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 lastseen.setText(UIHelper.lastseen(getApplicationContext(),
271 contact.lastseen.time));
272
273 switch (contact.getMostAvailableStatus()) {
274 case Presences.CHAT:
275 status.setText(R.string.contact_status_free_to_chat);
276 status.setTextColor(0xFF83b600);
277 break;
278 case Presences.ONLINE:
279 status.setText(R.string.contact_status_online);
280 status.setTextColor(0xFF83b600);
281 break;
282 case Presences.AWAY:
283 status.setText(R.string.contact_status_away);
284 status.setTextColor(0xFFffa713);
285 break;
286 case Presences.XA:
287 status.setText(R.string.contact_status_extended_away);
288 status.setTextColor(0xFFffa713);
289 break;
290 case Presences.DND:
291 status.setText(R.string.contact_status_do_not_disturb);
292 status.setTextColor(0xFFe92727);
293 break;
294 case Presences.OFFLINE:
295 status.setText(R.string.contact_status_offline);
296 status.setTextColor(0xFFe92727);
297 break;
298 default:
299 status.setText(R.string.contact_status_offline);
300 status.setTextColor(0xFFe92727);
301 break;
302 }
303 if (contact.getPresences().size() > 1) {
304 contactJidTv.setText(contact.getJid() + " ("
305 + contact.getPresences().size() + ")");
306 } else {
307 contactJidTv.setText(contact.getJid());
308 }
309 accountJidTv.setText(contact.getAccount().getJid());
310
311 UIHelper.prepareContactBadge(this, badge, contact,
312 getApplicationContext());
313
314 if (contact.getSystemAccount() == null) {
315 badge.setOnClickListener(onBadgeClick);
316 }
317
318 keys.removeAllViews();
319 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
320 for (Iterator<String> iterator = contact.getOtrFingerprints()
321 .iterator(); iterator.hasNext();) {
322 String otrFingerprint = iterator.next();
323 View view = (View) inflater.inflate(R.layout.contact_key, null);
324 TextView key = (TextView) view.findViewById(R.id.key);
325 TextView keyType = (TextView) view.findViewById(R.id.key_type);
326 keyType.setText("OTR Fingerprint");
327 key.setText(otrFingerprint);
328 keys.addView(view);
329 }
330 if (contact.getPgpKeyId() != 0) {
331 View view = (View) inflater.inflate(R.layout.contact_key, null);
332 TextView key = (TextView) view.findViewById(R.id.key);
333 TextView keyType = (TextView) view.findViewById(R.id.key_type);
334 keyType.setText("PGP Key ID");
335 key.setText(OpenPgpUtils.convertKeyIdToHex(contact.getPgpKeyId()));
336 view.setOnClickListener(new OnClickListener() {
337
338 @Override
339 public void onClick(View v) {
340 PgpEngine pgp = activity.xmppConnectionService
341 .getPgpEngine();
342 if (pgp != null) {
343 PendingIntent intent = pgp.getIntentForKey(contact);
344 if (intent != null) {
345 try {
346 startIntentSenderForResult(
347 intent.getIntentSender(), 0, null, 0,
348 0, 0);
349 } catch (SendIntentException e) {
350
351 }
352 }
353 }
354 }
355 });
356 keys.addView(view);
357 }
358 }
359
360 @Override
361 public void onBackendConnected() {
362 xmppConnectionService.setOnRosterUpdateListener(this.rosterUpdate);
363 xmppConnectionService.setOnAccountListChangedListener(this.accountUpdate );
364 if ((accountJid != null) && (contactJid != null)) {
365 Account account = xmppConnectionService
366 .findAccountByJid(accountJid);
367 if (account == null) {
368 return;
369 }
370 this.contact = account.getRoster().getContact(contactJid);
371 populateView();
372 }
373 }
374
375 @Override
376 protected void onStop() {
377 super.onStop();
378 xmppConnectionService.removeOnRosterUpdateListener();
379 xmppConnectionService.removeOnAccountListChangedListener();
380 }
381
382}