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.EditText;
25import android.widget.LinearLayout;
26import android.widget.QuickContactBadge;
27import android.widget.TextView;
28import android.widget.Toast;
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.utils.UIHelper;
35
36public class ContactDetailsActivity extends XmppActivity {
37 public static final String ACTION_VIEW_CONTACT = "view_contact";
38
39 protected ContactDetailsActivity activity = this;
40
41 private Contact contact;
42
43 private String accountJid;
44 private String contactJid;
45
46 private EditText name;
47 private TextView contactJidTv;
48 private TextView accountJidTv;
49 private TextView status;
50 private TextView askAgain;
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 editContactNameListener = new DialogInterface.OnClickListener() {
66
67 @Override
68 public void onClick(DialogInterface dialog, int which) {
69 contact.setServerName(name.getText().toString());
70 activity.xmppConnectionService.pushContactToServer(contact);
71 populateView();
72 }
73 };
74
75 private DialogInterface.OnClickListener addToPhonebook = new DialogInterface.OnClickListener() {
76
77 @Override
78 public void onClick(DialogInterface dialog, int which) {
79 Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
80 intent.setType(Contacts.CONTENT_ITEM_TYPE);
81 intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid());
82 intent.putExtra(Intents.Insert.IM_PROTOCOL,
83 CommonDataKinds.Im.PROTOCOL_JABBER);
84 intent.putExtra("finishActivityOnSaveCompleted", true);
85 activity.startActivityForResult(intent, 0);
86 }
87 };
88 private OnClickListener onBadgeClick = new OnClickListener() {
89
90 @Override
91 public void onClick(View v) {
92 AlertDialog.Builder builder = new AlertDialog.Builder(activity);
93 builder.setTitle(getString(R.string.action_add_phone_book));
94 builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid()));
95 builder.setNegativeButton(getString(R.string.cancel), null);
96 builder.setPositiveButton(getString(R.string.add), addToPhonebook);
97 builder.create().show();
98 }
99 };
100
101 private LinearLayout keys;
102
103 @Override
104 protected void onCreate(Bundle savedInstanceState) {
105 super.onCreate(savedInstanceState);
106 if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
107 this.accountJid = getIntent().getExtras().getString("account");
108 this.contactJid = getIntent().getExtras().getString("contact");
109 }
110 setContentView(R.layout.activity_contact_details);
111
112 contactJidTv = (TextView) findViewById(R.id.details_contactjid);
113 accountJidTv = (TextView) findViewById(R.id.details_account);
114 status = (TextView) findViewById(R.id.details_contactstatus);
115 lastseen = (TextView) findViewById(R.id.details_lastseen);
116 send = (CheckBox) findViewById(R.id.details_send_presence);
117 receive = (CheckBox) findViewById(R.id.details_receive_presence);
118 askAgain = (TextView) findViewById(R.id.ask_again);
119 badge = (QuickContactBadge) findViewById(R.id.details_contact_badge);
120 keys = (LinearLayout) findViewById(R.id.details_contact_keys);
121 getActionBar().setHomeButtonEnabled(true);
122 getActionBar().setDisplayHomeAsUpEnabled(true);
123
124 }
125
126 @Override
127 public boolean onOptionsItemSelected(MenuItem menuItem) {
128 AlertDialog.Builder builder = new AlertDialog.Builder(this);
129 builder.setNegativeButton(getString(R.string.cancel), null);
130 switch (menuItem.getItemId()) {
131 case android.R.id.home:
132 finish();
133 break;
134 case R.id.action_delete_contact:
135 builder.setTitle(getString(R.string.action_delete_contact))
136 .setMessage(
137 getString(R.string.remove_contact_text,
138 contact.getJid()))
139 .setPositiveButton(getString(R.string.delete), removeFromRoster).create()
140 .show();
141 break;
142 case R.id.action_edit_contact:
143 if (contact.getSystemAccount() == null) {
144
145 View view = (View) getLayoutInflater().inflate(
146 R.layout.edit_contact_name, null);
147 name = (EditText) view.findViewById(R.id.editText1);
148 name.setText(contact.getDisplayName());
149 builder.setView(view).setTitle(contact.getJid())
150 .setPositiveButton(getString(R.string.edit), editContactNameListener)
151 .create().show();
152
153 } else {
154 Intent intent = new Intent(Intent.ACTION_EDIT);
155 String[] systemAccount = contact.getSystemAccount().split("#");
156 long id = Long.parseLong(systemAccount[0]);
157 Uri uri = Contacts.getLookupUri(id, systemAccount[1]);
158 intent.setDataAndType(uri, Contacts.CONTENT_ITEM_TYPE);
159 intent.putExtra("finishActivityOnSaveCompleted", true);
160 startActivity(intent);
161 }
162 break;
163 }
164 return super.onOptionsItemSelected(menuItem);
165 }
166
167 @Override
168 public boolean onCreateOptionsMenu(Menu menu) {
169 getMenuInflater().inflate(R.menu.contact_details, menu);
170 return true;
171 }
172
173 private void populateView() {
174 setTitle(contact.getDisplayName());
175 if (contact.getOption(Contact.Options.FROM)) {
176 send.setChecked(true);
177 } else {
178 send.setText(R.string.preemptively_grant);
179 if (contact
180 .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
181 send.setChecked(true);
182 } else {
183 send.setChecked(false);
184 }
185 }
186 if (contact.getOption(Contact.Options.TO)) {
187 receive.setChecked(true);
188 } else {
189 receive.setText(R.string.ask_for_presence_updates);
190 askAgain.setVisibility(View.VISIBLE);
191 askAgain.setOnClickListener(new OnClickListener() {
192
193 @Override
194 public void onClick(View v) {
195 Toast.makeText(getApplicationContext(), getString(R.string.asked_for_presence_updates),
196 Toast.LENGTH_SHORT).show();
197 xmppConnectionService.requestPresenceUpdatesFrom(contact);
198
199 }
200 });
201 if (contact.getOption(Contact.Options.ASKING)) {
202 receive.setChecked(true);
203 } else {
204 receive.setChecked(false);
205 }
206 }
207
208 lastseen.setText(UIHelper.lastseen(getApplicationContext(),contact.lastseen.time));
209
210 switch (contact.getMostAvailableStatus()) {
211 case Presences.CHAT:
212 status.setText(R.string.contact_status_free_to_chat);
213 status.setTextColor(0xFF83b600);
214 break;
215 case Presences.ONLINE:
216 status.setText(R.string.contact_status_online);
217 status.setTextColor(0xFF83b600);
218 break;
219 case Presences.AWAY:
220 status.setText(R.string.contact_status_away);
221 status.setTextColor(0xFFffa713);
222 break;
223 case Presences.XA:
224 status.setText(R.string.contact_status_extended_away);
225 status.setTextColor(0xFFffa713);
226 break;
227 case Presences.DND:
228 status.setText(R.string.contact_status_do_not_disturb);
229 status.setTextColor(0xFFe92727);
230 break;
231 case Presences.OFFLINE:
232 status.setText(R.string.contact_status_offline);
233 status.setTextColor(0xFFe92727);
234 break;
235 default:
236 status.setText(R.string.contact_status_offline);
237 status.setTextColor(0xFFe92727);
238 break;
239 }
240 if (contact.getPresences().size() > 1) {
241 contactJidTv.setText(contact.getJid()+" ("+contact.getPresences().size()+")");
242 } else {
243 contactJidTv.setText(contact.getJid());
244 }
245 accountJidTv.setText(contact.getAccount().getJid());
246
247 UIHelper.prepareContactBadge(this, badge, contact, getApplicationContext());
248
249 if (contact.getSystemAccount() == null) {
250 badge.setOnClickListener(onBadgeClick);
251 }
252
253 keys.removeAllViews();
254 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
255 for (Iterator<String> iterator = contact.getOtrFingerprints()
256 .iterator(); iterator.hasNext();) {
257 String otrFingerprint = iterator.next();
258 View view = (View) inflater.inflate(R.layout.contact_key, null);
259 TextView key = (TextView) view.findViewById(R.id.key);
260 TextView keyType = (TextView) view.findViewById(R.id.key_type);
261 keyType.setText("OTR Fingerprint");
262 key.setText(otrFingerprint);
263 keys.addView(view);
264 }
265 if (contact.getPgpKeyId() != 0) {
266 View view = (View) inflater.inflate(R.layout.contact_key, null);
267 TextView key = (TextView) view.findViewById(R.id.key);
268 TextView keyType = (TextView) view.findViewById(R.id.key_type);
269 keyType.setText("PGP Key ID");
270 key.setText(OpenPgpUtils.convertKeyIdToHex(contact.getPgpKeyId()));
271 view.setOnClickListener(new OnClickListener() {
272
273 @Override
274 public void onClick(View v) {
275 PgpEngine pgp = activity.xmppConnectionService.getPgpEngine();
276 if (pgp!=null) {
277 PendingIntent intent = pgp.getIntentForKey(contact);
278 if (intent!=null) {
279 try {
280 startIntentSenderForResult(intent.getIntentSender(), 0, null, 0, 0, 0);
281 } catch (SendIntentException e) {
282
283 }
284 }
285 }
286 }
287 });
288 keys.addView(view);
289 }
290 }
291
292 @Override
293 public void onBackendConnected() {
294 if ((accountJid != null)&&(contactJid != null)) {
295 Account account = xmppConnectionService.findAccountByJid(accountJid);
296 if (account==null) {
297 return;
298 }
299 this.contact = account.getRoster().getContact(contactJid);
300 populateView();
301 }
302 }
303
304 @Override
305 protected void onStop() {
306 super.onStop();
307 boolean updated = false;
308 if (contact!=null) {
309 boolean online = contact.getAccount().getStatus() == Account.STATUS_ONLINE;
310 if (contact.getOption(Contact.Options.FROM)) {
311 if (!send.isChecked()) {
312 if (online) {
313 contact.resetOption(Contact.Options.FROM);
314 contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
315 activity.xmppConnectionService.stopPresenceUpdatesTo(contact);
316 }
317 updated = true;
318 }
319 } else {
320 if (contact
321 .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
322 if (!send.isChecked()) {
323 if (online) {
324 contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
325 }
326 updated = true;
327 }
328 } else {
329 if (send.isChecked()) {
330 if (online) {
331 contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
332 }
333 updated = true;
334 }
335 }
336 }
337 if (contact.getOption(Contact.Options.TO)) {
338 if (!receive.isChecked()) {
339 if (online) {
340 contact.resetOption(Contact.Options.TO);
341 activity.xmppConnectionService.stopPresenceUpdatesFrom(contact);
342 }
343 updated = true;
344 }
345 } else {
346 if (contact.getOption(Contact.Options.ASKING)) {
347 if (!receive.isChecked()) {
348 if (online) {
349 contact.resetOption(Contact.Options.ASKING);
350 activity.xmppConnectionService
351 .stopPresenceUpdatesFrom(contact);
352 }
353 updated = true;
354 }
355 } else {
356 if (receive.isChecked()) {
357 if (online) {
358 contact.setOption(Contact.Options.ASKING);
359 activity.xmppConnectionService
360 .requestPresenceUpdatesFrom(contact);
361 }
362 updated = true;
363 }
364 }
365 }
366 if (updated) {
367 if (online) {
368 Toast.makeText(getApplicationContext(), getString(R.string.subscription_updated), Toast.LENGTH_SHORT).show();
369 } else {
370 Toast.makeText(getApplicationContext(), getString(R.string.subscription_not_updated_offline), Toast.LENGTH_SHORT).show();
371 }
372 }
373 }
374 }
375
376}