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 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 activity.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(0xFF83b600);
280 break;
281 case Presences.ONLINE:
282 status.setText(R.string.contact_status_online);
283 status.setTextColor(0xFF83b600);
284 break;
285 case Presences.AWAY:
286 status.setText(R.string.contact_status_away);
287 status.setTextColor(0xFFffa713);
288 break;
289 case Presences.XA:
290 status.setText(R.string.contact_status_extended_away);
291 status.setTextColor(0xFFffa713);
292 break;
293 case Presences.DND:
294 status.setText(R.string.contact_status_do_not_disturb);
295 status.setTextColor(0xFFe92727);
296 break;
297 case Presences.OFFLINE:
298 status.setText(R.string.contact_status_offline);
299 status.setTextColor(0xFFe92727);
300 break;
301 default:
302 status.setText(R.string.contact_status_offline);
303 status.setTextColor(0xFFe92727);
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 String otrFingerprint = iterator.next();
326 View view = (View) inflater.inflate(R.layout.contact_key, null);
327 TextView key = (TextView) view.findViewById(R.id.key);
328 TextView keyType = (TextView) view.findViewById(R.id.key_type);
329 keyType.setText("OTR Fingerprint");
330 key.setText(otrFingerprint);
331 keys.addView(view);
332 }
333 if (contact.getPgpKeyId() != 0) {
334 View view = (View) inflater.inflate(R.layout.contact_key, null);
335 TextView key = (TextView) view.findViewById(R.id.key);
336 TextView keyType = (TextView) view.findViewById(R.id.key_type);
337 keyType.setText("PGP Key ID");
338 key.setText(OpenPgpUtils.convertKeyIdToHex(contact.getPgpKeyId()));
339 view.setOnClickListener(new OnClickListener() {
340
341 @Override
342 public void onClick(View v) {
343 PgpEngine pgp = activity.xmppConnectionService
344 .getPgpEngine();
345 if (pgp != null) {
346 PendingIntent intent = pgp.getIntentForKey(contact);
347 if (intent != null) {
348 try {
349 startIntentSenderForResult(
350 intent.getIntentSender(), 0, null, 0,
351 0, 0);
352 } catch (SendIntentException e) {
353
354 }
355 }
356 }
357 }
358 });
359 keys.addView(view);
360 }
361 }
362
363 @Override
364 public void onBackendConnected() {
365 xmppConnectionService.setOnRosterUpdateListener(this.rosterUpdate);
366 xmppConnectionService.setOnAccountListChangedListener(this.accountUpdate );
367 if ((accountJid != null) && (contactJid != null)) {
368 Account account = xmppConnectionService
369 .findAccountByJid(accountJid);
370 if (account == null) {
371 return;
372 }
373 this.contact = account.getRoster().getContact(contactJid);
374 populateView();
375 }
376 }
377
378 @Override
379 protected void onStop() {
380 super.onStop();
381 xmppConnectionService.removeOnRosterUpdateListener();
382 xmppConnectionService.removeOnAccountListChangedListener();
383 }
384
385}