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.services.XmppConnectionService;
35import eu.siacs.conversations.utils.UIHelper;
36import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
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 EditText name;
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 editContactNameListener = new DialogInterface.OnClickListener() {
67
68 @Override
69 public void onClick(DialogInterface dialog, int which) {
70 contact.setServerName(name.getText().toString());
71 activity.xmppConnectionService.pushContactToServer(contact);
72 populateView();
73 }
74 };
75
76 private DialogInterface.OnClickListener addToPhonebook = new DialogInterface.OnClickListener() {
77
78 @Override
79 public void onClick(DialogInterface dialog, int which) {
80 Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
81 intent.setType(Contacts.CONTENT_ITEM_TYPE);
82 intent.putExtra(Intents.Insert.IM_HANDLE, contact.getJid());
83 intent.putExtra(Intents.Insert.IM_PROTOCOL,
84 CommonDataKinds.Im.PROTOCOL_JABBER);
85 intent.putExtra("finishActivityOnSaveCompleted", true);
86 activity.startActivityForResult(intent, 0);
87 }
88 };
89 private OnClickListener onBadgeClick = new OnClickListener() {
90
91 @Override
92 public void onClick(View v) {
93 AlertDialog.Builder builder = new AlertDialog.Builder(activity);
94 builder.setTitle(getString(R.string.action_add_phone_book));
95 builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid()));
96 builder.setNegativeButton(getString(R.string.cancel), null);
97 builder.setPositiveButton(getString(R.string.add), addToPhonebook);
98 builder.create().show();
99 }
100 };
101
102 private LinearLayout keys;
103
104 @Override
105 protected void onCreate(Bundle savedInstanceState) {
106 super.onCreate(savedInstanceState);
107 if (getIntent().getAction().equals(ACTION_VIEW_CONTACT)) {
108 this.accountJid = getIntent().getExtras().getString("account");
109 this.contactJid = getIntent().getExtras().getString("contact");
110 }
111 setContentView(R.layout.activity_contact_details);
112
113 contactJidTv = (TextView) findViewById(R.id.details_contactjid);
114 accountJidTv = (TextView) findViewById(R.id.details_account);
115 status = (TextView) findViewById(R.id.details_contactstatus);
116 lastseen = (TextView) findViewById(R.id.details_lastseen);
117 send = (CheckBox) findViewById(R.id.details_send_presence);
118 receive = (CheckBox) findViewById(R.id.details_receive_presence);
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 if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)){
178 send.setChecked(false);
179 } else {
180 send.setText(R.string.preemptively_grant);
181 if (contact
182 .getOption(Contact.Options.PREEMPTIVE_GRANT)) {
183 send.setChecked(true);
184 } else {
185 send.setChecked(false);
186 }
187 }
188 if (contact.getOption(Contact.Options.TO)) {
189 receive.setChecked(true);
190 } else {
191 receive.setText(R.string.ask_for_presence_updates);
192 if (contact.getOption(Contact.Options.ASKING)) {
193 receive.setChecked(true);
194 } else {
195 receive.setChecked(false);
196 }
197 }
198
199 lastseen.setText(UIHelper.lastseen(getApplicationContext(),contact.lastseen.time));
200
201 switch (contact.getMostAvailableStatus()) {
202 case Presences.CHAT:
203 status.setText(R.string.contact_status_free_to_chat);
204 status.setTextColor(0xFF83b600);
205 break;
206 case Presences.ONLINE:
207 status.setText(R.string.contact_status_online);
208 status.setTextColor(0xFF83b600);
209 break;
210 case Presences.AWAY:
211 status.setText(R.string.contact_status_away);
212 status.setTextColor(0xFFffa713);
213 break;
214 case Presences.XA:
215 status.setText(R.string.contact_status_extended_away);
216 status.setTextColor(0xFFffa713);
217 break;
218 case Presences.DND:
219 status.setText(R.string.contact_status_do_not_disturb);
220 status.setTextColor(0xFFe92727);
221 break;
222 case Presences.OFFLINE:
223 status.setText(R.string.contact_status_offline);
224 status.setTextColor(0xFFe92727);
225 break;
226 default:
227 status.setText(R.string.contact_status_offline);
228 status.setTextColor(0xFFe92727);
229 break;
230 }
231 if (contact.getPresences().size() > 1) {
232 contactJidTv.setText(contact.getJid()+" ("+contact.getPresences().size()+")");
233 } else {
234 contactJidTv.setText(contact.getJid());
235 }
236 accountJidTv.setText(contact.getAccount().getJid());
237
238 UIHelper.prepareContactBadge(this, badge, contact, getApplicationContext());
239
240 if (contact.getSystemAccount() == null) {
241 badge.setOnClickListener(onBadgeClick);
242 }
243
244 keys.removeAllViews();
245 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
246 for (Iterator<String> iterator = contact.getOtrFingerprints()
247 .iterator(); iterator.hasNext();) {
248 String otrFingerprint = iterator.next();
249 View view = (View) inflater.inflate(R.layout.contact_key, null);
250 TextView key = (TextView) view.findViewById(R.id.key);
251 TextView keyType = (TextView) view.findViewById(R.id.key_type);
252 keyType.setText("OTR Fingerprint");
253 key.setText(otrFingerprint);
254 keys.addView(view);
255 }
256 if (contact.getPgpKeyId() != 0) {
257 View view = (View) inflater.inflate(R.layout.contact_key, null);
258 TextView key = (TextView) view.findViewById(R.id.key);
259 TextView keyType = (TextView) view.findViewById(R.id.key_type);
260 keyType.setText("PGP Key ID");
261 key.setText(OpenPgpUtils.convertKeyIdToHex(contact.getPgpKeyId()));
262 view.setOnClickListener(new OnClickListener() {
263
264 @Override
265 public void onClick(View v) {
266 PgpEngine pgp = activity.xmppConnectionService.getPgpEngine();
267 if (pgp!=null) {
268 PendingIntent intent = pgp.getIntentForKey(contact);
269 if (intent!=null) {
270 try {
271 startIntentSenderForResult(intent.getIntentSender(), 0, null, 0, 0, 0);
272 } catch (SendIntentException e) {
273
274 }
275 }
276 }
277 }
278 });
279 keys.addView(view);
280 }
281 }
282
283 @Override
284 public void onBackendConnected() {
285 if ((accountJid != null)&&(contactJid != null)) {
286 Account account = xmppConnectionService.findAccountByJid(accountJid);
287 if (account==null) {
288 return;
289 }
290 this.contact = account.getRoster().getContact(contactJid);
291 populateView();
292 }
293 }
294
295 @Override
296 protected void onStop() {
297 super.onStop();
298 XmppConnectionService xcs = activity.xmppConnectionService;
299 PresencePacket packet = null;
300 boolean updated = false;
301 if (contact!=null) {
302 boolean online = contact.getAccount().getStatus() == Account.STATUS_ONLINE;
303 if (contact.getOption(Contact.Options.FROM)) {
304 if (!send.isChecked()) {
305 if (online) {
306 contact.resetOption(Contact.Options.FROM);
307 contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
308 packet = xcs.getPresenceGenerator().stopPresenceUpdatesTo(contact);
309 }
310 updated = true;
311 }
312 } else {
313 if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
314 if (!send.isChecked()) {
315 if (online) {
316 contact.resetOption(Contact.Options.PREEMPTIVE_GRANT);
317 }
318 updated = true;
319 }
320 } else {
321 if (send.isChecked()) {
322 if (online) {
323 if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
324 packet = xcs.getPresenceGenerator().sendPresenceUpdatesTo(contact);
325 } else {
326 contact.setOption(Contact.Options.PREEMPTIVE_GRANT);
327 }
328 }
329 updated = true;
330 }
331 }
332 }
333 if (contact.getOption(Contact.Options.TO)) {
334 if (!receive.isChecked()) {
335 if (online) {
336 contact.resetOption(Contact.Options.TO);
337 packet = xcs.getPresenceGenerator().stopPresenceUpdatesFrom(contact);
338 }
339 updated = true;
340 }
341 } else {
342 if (contact.getOption(Contact.Options.ASKING)) {
343 if (!receive.isChecked()) {
344 if (online) {
345 contact.resetOption(Contact.Options.ASKING);
346 packet = xcs.getPresenceGenerator().stopPresenceUpdatesFrom(contact);
347 }
348 updated = true;
349 }
350 } else {
351 if (receive.isChecked()) {
352 if (online) {
353 contact.setOption(Contact.Options.ASKING);
354 packet = xcs.getPresenceGenerator().requestPresenceUpdatesFrom(contact);
355 }
356 updated = true;
357 }
358 }
359 }
360 if (updated) {
361 if (online) {
362 if (packet!=null) {
363 xcs.sendPresencePacket(contact.getAccount(), packet);
364 }
365 Toast.makeText(getApplicationContext(), getString(R.string.subscription_updated), Toast.LENGTH_SHORT).show();
366 } else {
367 Toast.makeText(getApplicationContext(), getString(R.string.subscription_not_updated_offline), Toast.LENGTH_SHORT).show();
368 }
369 }
370 }
371 }
372
373}