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