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.OnRosterUpdate;
35import eu.siacs.conversations.utils.UIHelper;
36
37public class ContactDetailsActivity extends XmppActivity {
38 public static final String ACTION_VIEW_CONTACT = "view_contact";
39
40 protected ContactDetailsActivity activity = this;
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 activity.xmppConnectionService.deleteContactOnServer(contact);
60 activity.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 activity.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(activity);
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.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
114 xmppConnectionService.sendPresencePacket(contact
115 .getAccount(),
116 xmppConnectionService.getPresenceGenerator()
117 .sendPresenceUpdatesTo(contact));
118 } else {
119 contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
120 }
121 } else {
122 contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
123 xmppConnectionService.sendPresencePacket(contact.getAccount(),
124 xmppConnectionService.getPresenceGenerator()
125 .stopPresenceUpdatesTo(contact));
126 }
127 }
128 };
129
130 private OnCheckedChangeListener mOnReceiveCheckedChange = new OnCheckedChangeListener() {
131
132 @Override
133 public void onCheckedChanged(CompoundButton buttonView,
134 boolean isChecked) {
135 if (isChecked) {
136 xmppConnectionService.sendPresencePacket(contact.getAccount(),
137 xmppConnectionService.getPresenceGenerator()
138 .requestPresenceUpdatesFrom(contact));
139 } else {
140 xmppConnectionService.sendPresencePacket(contact.getAccount(),
141 xmppConnectionService.getPresenceGenerator()
142 .stopPresenceUpdatesFrom(contact));
143 }
144 }
145 };
146
147 @Override
148 protected void onCreate(Bundle savedInstanceState) {
149 super.onCreate(savedInstanceState);
150 if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
151 this.accountJid = getIntent().getExtras().getString("account");
152 this.contactJid = getIntent().getExtras().getString("contact");
153 }
154 setContentView(R.layout.activity_contact_details);
155
156 contactJidTv = (TextView) findViewById(R.id.details_contactjid);
157 accountJidTv = (TextView) findViewById(R.id.details_account);
158 status = (TextView) findViewById(R.id.details_contactstatus);
159 lastseen = (TextView) findViewById(R.id.details_lastseen);
160 send = (CheckBox) findViewById(R.id.details_send_presence);
161 send.setOnCheckedChangeListener(this.mOnSendCheckedChange);
162 receive = (CheckBox) findViewById(R.id.details_receive_presence);
163 receive.setOnCheckedChangeListener(this.mOnReceiveCheckedChange);
164 badge = (QuickContactBadge) findViewById(R.id.details_contact_badge);
165 keys = (LinearLayout) findViewById(R.id.details_contact_keys);
166 getActionBar().setHomeButtonEnabled(true);
167 getActionBar().setDisplayHomeAsUpEnabled(true);
168
169 }
170
171 @Override
172 public boolean onOptionsItemSelected(MenuItem menuItem) {
173 AlertDialog.Builder builder = new AlertDialog.Builder(this);
174 builder.setNegativeButton(getString(R.string.cancel), null);
175 switch (menuItem.getItemId()) {
176 case android.R.id.home:
177 finish();
178 break;
179 case R.id.action_delete_contact:
180 builder.setTitle(getString(R.string.action_delete_contact))
181 .setMessage(
182 getString(R.string.remove_contact_text,
183 contact.getJid()))
184 .setPositiveButton(getString(R.string.delete),
185 removeFromRoster).create().show();
186 break;
187 case R.id.action_edit_contact:
188 if (contact.getSystemAccount() == null) {
189 quickEdit(contact.getDisplayName(), new OnValueEdited() {
190
191 @Override
192 public void onValueEdited(String value) {
193 contact.setServerName(value);
194 activity.xmppConnectionService
195 .pushContactToServer(contact);
196 populateView();
197 }
198 });
199 } else {
200 Intent intent = new Intent(Intent.ACTION_EDIT);
201 String[] systemAccount = contact.getSystemAccount().split("#");
202 long id = Long.parseLong(systemAccount[0]);
203 Uri uri = Contacts.getLookupUri(id, systemAccount[1]);
204 intent.setDataAndType(uri, Contacts.CONTENT_ITEM_TYPE);
205 intent.putExtra("finishActivityOnSaveCompleted", true);
206 startActivity(intent);
207 }
208 break;
209 }
210 return super.onOptionsItemSelected(menuItem);
211 }
212
213 @Override
214 public boolean onCreateOptionsMenu(Menu menu) {
215 getMenuInflater().inflate(R.menu.contact_details, menu);
216 return true;
217 }
218
219 private void populateView() {
220 setTitle(contact.getDisplayName());
221 if (contact.getOption(Contact.Options.FROM)) {
222 send.setText(R.string.send_presence_updates);
223 send.setChecked(true);
224 } else if (contact
225 .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
226 send.setChecked(false);
227 send.setText(R.string.send_presence_updates);
228 } else {
229 send.setText(R.string.preemptively_grant);
230 if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
231 send.setChecked(true);
232 } else {
233 send.setChecked(false);
234 }
235 }
236 if (contact.getOption(Contact.Options.TO)) {
237 receive.setText(R.string.receive_presence_updates);
238 receive.setChecked(true);
239 } else {
240 receive.setText(R.string.ask_for_presence_updates);
241 if (contact.getOption(Contact.Options.ASKING)) {
242 receive.setChecked(true);
243 } else {
244 receive.setChecked(false);
245 }
246 }
247
248 lastseen.setText(UIHelper.lastseen(getApplicationContext(),
249 contact.lastseen.time));
250
251 switch (contact.getMostAvailableStatus()) {
252 case Presences.CHAT:
253 status.setText(R.string.contact_status_free_to_chat);
254 status.setTextColor(0xFF83b600);
255 break;
256 case Presences.ONLINE:
257 status.setText(R.string.contact_status_online);
258 status.setTextColor(0xFF83b600);
259 break;
260 case Presences.AWAY:
261 status.setText(R.string.contact_status_away);
262 status.setTextColor(0xFFffa713);
263 break;
264 case Presences.XA:
265 status.setText(R.string.contact_status_extended_away);
266 status.setTextColor(0xFFffa713);
267 break;
268 case Presences.DND:
269 status.setText(R.string.contact_status_do_not_disturb);
270 status.setTextColor(0xFFe92727);
271 break;
272 case Presences.OFFLINE:
273 status.setText(R.string.contact_status_offline);
274 status.setTextColor(0xFFe92727);
275 break;
276 default:
277 status.setText(R.string.contact_status_offline);
278 status.setTextColor(0xFFe92727);
279 break;
280 }
281 if (contact.getPresences().size() > 1) {
282 contactJidTv.setText(contact.getJid() + " ("
283 + contact.getPresences().size() + ")");
284 } else {
285 contactJidTv.setText(contact.getJid());
286 }
287 accountJidTv.setText(contact.getAccount().getJid());
288
289 UIHelper.prepareContactBadge(this, badge, contact,
290 getApplicationContext());
291
292 if (contact.getSystemAccount() == null) {
293 badge.setOnClickListener(onBadgeClick);
294 }
295
296 keys.removeAllViews();
297 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
298 for (Iterator<String> iterator = contact.getOtrFingerprints()
299 .iterator(); iterator.hasNext();) {
300 String otrFingerprint = iterator.next();
301 View view = (View) inflater.inflate(R.layout.contact_key, null);
302 TextView key = (TextView) view.findViewById(R.id.key);
303 TextView keyType = (TextView) view.findViewById(R.id.key_type);
304 keyType.setText("OTR Fingerprint");
305 key.setText(otrFingerprint);
306 keys.addView(view);
307 }
308 if (contact.getPgpKeyId() != 0) {
309 View view = (View) inflater.inflate(R.layout.contact_key, null);
310 TextView key = (TextView) view.findViewById(R.id.key);
311 TextView keyType = (TextView) view.findViewById(R.id.key_type);
312 keyType.setText("PGP Key ID");
313 key.setText(OpenPgpUtils.convertKeyIdToHex(contact.getPgpKeyId()));
314 view.setOnClickListener(new OnClickListener() {
315
316 @Override
317 public void onClick(View v) {
318 PgpEngine pgp = activity.xmppConnectionService
319 .getPgpEngine();
320 if (pgp != null) {
321 PendingIntent intent = pgp.getIntentForKey(contact);
322 if (intent != null) {
323 try {
324 startIntentSenderForResult(
325 intent.getIntentSender(), 0, null, 0,
326 0, 0);
327 } catch (SendIntentException e) {
328
329 }
330 }
331 }
332 }
333 });
334 keys.addView(view);
335 }
336 }
337
338 @Override
339 public void onBackendConnected() {
340 xmppConnectionService.setOnRosterUpdateListener(this.rosterUpdate);
341 if ((accountJid != null) && (contactJid != null)) {
342 Account account = xmppConnectionService
343 .findAccountByJid(accountJid);
344 if (account == null) {
345 return;
346 }
347 this.contact = account.getRoster().getContact(contactJid);
348 populateView();
349 }
350 }
351
352 @Override
353 protected void onStop() {
354 super.onStop();
355 xmppConnectionService.removeOnRosterUpdateListener();
356 }
357
358}