ManageAccountActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import java.util.ArrayList;
  4import java.util.List;
  5
  6import eu.siacs.conversations.R;
  7import eu.siacs.conversations.entities.Account;
  8import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
  9import eu.siacs.conversations.ui.EditAccountDialog.EditAccountListener;
 10import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
 11import eu.siacs.conversations.xmpp.XmppConnection;
 12import android.app.Activity;
 13import android.app.AlertDialog;
 14import android.content.Context;
 15import android.content.DialogInterface;
 16import android.content.DialogInterface.OnClickListener;
 17import android.content.Intent;
 18import android.os.Bundle;
 19import android.os.SystemClock;
 20import android.view.ActionMode;
 21import android.view.LayoutInflater;
 22import android.view.Menu;
 23import android.view.MenuInflater;
 24import android.view.MenuItem;
 25import android.view.View;
 26import android.view.ViewGroup;
 27import android.widget.AdapterView;
 28import android.widget.AdapterView.OnItemClickListener;
 29import android.widget.AdapterView.OnItemLongClickListener;
 30import android.widget.ArrayAdapter;
 31import android.widget.ListView;
 32import android.widget.TextView;
 33
 34public class ManageAccountActivity extends XmppActivity {
 35
 36	protected boolean isActionMode = false;
 37	protected ActionMode actionMode;
 38	protected Account selectedAccountForActionMode = null;
 39	protected ManageAccountActivity activity = this;
 40
 41	protected boolean firstrun = true;
 42
 43	protected List<Account> accountList = new ArrayList<Account>();
 44	protected ListView accountListView;
 45	protected ArrayAdapter<Account> accountListViewAdapter;
 46	protected OnAccountUpdate accountChanged = new OnAccountUpdate() {
 47
 48		@Override
 49		public void onAccountUpdate() {
 50			accountList.clear();
 51			accountList.addAll(xmppConnectionService.getAccounts());
 52			runOnUiThread(new Runnable() {
 53
 54				@Override
 55				public void run() {
 56					accountListViewAdapter.notifyDataSetChanged();
 57				}
 58			});
 59		}
 60	};
 61
 62	@Override
 63	protected void onCreate(Bundle savedInstanceState) {
 64
 65		super.onCreate(savedInstanceState);
 66
 67		setContentView(R.layout.manage_accounts);
 68
 69		accountListView = (ListView) findViewById(R.id.account_list);
 70		accountListViewAdapter = new ArrayAdapter<Account>(
 71				getApplicationContext(), R.layout.account_row, this.accountList) {
 72			@Override
 73			public View getView(int position, View view, ViewGroup parent) {
 74				Account account = getItem(position);
 75				if (view == null) {
 76					LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 77					view = (View) inflater.inflate(R.layout.account_row, null);
 78				}
 79				((TextView) view.findViewById(R.id.account_jid))
 80						.setText(account.getJid());
 81				TextView statusView = (TextView) view
 82						.findViewById(R.id.account_status);
 83				switch (account.getStatus()) {
 84				case Account.STATUS_DISABLED:
 85					statusView
 86							.setText(getString(R.string.account_status_disabled));
 87					statusView.setTextColor(0xFF1da9da);
 88					break;
 89				case Account.STATUS_ONLINE:
 90					statusView
 91							.setText(getString(R.string.account_status_online));
 92					statusView.setTextColor(0xFF83b600);
 93					break;
 94				case Account.STATUS_CONNECTING:
 95					statusView
 96							.setText(getString(R.string.account_status_connecting));
 97					statusView.setTextColor(0xFF1da9da);
 98					break;
 99				case Account.STATUS_OFFLINE:
100					statusView
101							.setText(getString(R.string.account_status_offline));
102					statusView.setTextColor(0xFFe92727);
103					break;
104				case Account.STATUS_UNAUTHORIZED:
105					statusView
106							.setText(getString(R.string.account_status_unauthorized));
107					statusView.setTextColor(0xFFe92727);
108					break;
109				case Account.STATUS_SERVER_NOT_FOUND:
110					statusView
111							.setText(getString(R.string.account_status_not_found));
112					statusView.setTextColor(0xFFe92727);
113					break;
114				case Account.STATUS_NO_INTERNET:
115					statusView
116							.setText(getString(R.string.account_status_no_internet));
117					statusView.setTextColor(0xFFe92727);
118					break;
119				case Account.STATUS_SERVER_REQUIRES_TLS:
120					statusView
121							.setText(getString(R.string.account_status_requires_tls));
122					statusView.setTextColor(0xFFe92727);
123					break;
124				case Account.STATUS_TLS_ERROR:
125					statusView
126							.setText(getString(R.string.account_status_error));
127					statusView.setTextColor(0xFFe92727);
128					break;
129				case Account.STATUS_REGISTRATION_FAILED:
130					statusView
131							.setText(getString(R.string.account_status_regis_fail));
132					statusView.setTextColor(0xFFe92727);
133					break;
134				case Account.STATUS_REGISTRATION_CONFLICT:
135					statusView
136							.setText(getString(R.string.account_status_regis_conflict));
137					statusView.setTextColor(0xFFe92727);
138					break;
139				case Account.STATUS_REGISTRATION_SUCCESSFULL:
140					statusView
141							.setText(getString(R.string.account_status_regis_success));
142					statusView.setTextColor(0xFF83b600);
143					break;
144				case Account.STATUS_REGISTRATION_NOT_SUPPORTED:
145					statusView
146							.setText(getString(R.string.account_status_regis_not_sup));
147					statusView.setTextColor(0xFFe92727);
148					break;
149				default:
150					statusView.setText("");
151					break;
152				}
153
154				return view;
155			}
156		};
157		final XmppActivity activity = this;
158		accountListView.setAdapter(this.accountListViewAdapter);
159		accountListView.setOnItemClickListener(new OnItemClickListener() {
160
161			@Override
162			public void onItemClick(AdapterView<?> arg0, View view,
163					int position, long arg3) {
164				if (!isActionMode) {
165					Account account = accountList.get(position);
166					if ((account.getStatus() == Account.STATUS_OFFLINE)
167							|| (account.getStatus() == Account.STATUS_TLS_ERROR)) {
168						activity.xmppConnectionService.reconnectAccount(
169								accountList.get(position), true);
170					} else if (account.getStatus() == Account.STATUS_ONLINE) {
171						activity.startActivity(new Intent(activity
172								.getApplicationContext(),
173								StartConversationActivity.class));
174					} else if (account.getStatus() != Account.STATUS_DISABLED) {
175						editAccount(account);
176					}
177				} else {
178					selectedAccountForActionMode = accountList.get(position);
179					actionMode.invalidate();
180				}
181			}
182		});
183		accountListView
184				.setOnItemLongClickListener(new OnItemLongClickListener() {
185
186					@Override
187					public boolean onItemLongClick(AdapterView<?> arg0,
188							View view, int position, long arg3) {
189						if (!isActionMode) {
190							accountListView
191									.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
192							accountListView.setItemChecked(position, true);
193							selectedAccountForActionMode = accountList
194									.get(position);
195							actionMode = activity
196									.startActionMode((new ActionMode.Callback() {
197
198										@Override
199										public boolean onPrepareActionMode(
200												ActionMode mode, Menu menu) {
201											if (selectedAccountForActionMode
202													.isOptionSet(Account.OPTION_DISABLED)) {
203												menu.findItem(
204														R.id.mgmt_account_enable)
205														.setVisible(true);
206												menu.findItem(
207														R.id.mgmt_account_disable)
208														.setVisible(false);
209											} else {
210												menu.findItem(
211														R.id.mgmt_account_disable)
212														.setVisible(true);
213												menu.findItem(
214														R.id.mgmt_account_enable)
215														.setVisible(false);
216											}
217											return true;
218										}
219
220										@Override
221										public void onDestroyActionMode(
222												ActionMode mode) {
223											// TODO Auto-generated method stub
224
225										}
226
227										@Override
228										public boolean onCreateActionMode(
229												ActionMode mode, Menu menu) {
230											MenuInflater inflater = mode
231													.getMenuInflater();
232											inflater.inflate(
233													R.menu.manageaccounts_context,
234													menu);
235											return true;
236										}
237
238										@Override
239										public boolean onActionItemClicked(
240												final ActionMode mode,
241												MenuItem item) {
242											if (item.getItemId() == R.id.mgmt_account_edit) {
243												editAccount(selectedAccountForActionMode);
244											} else if (item.getItemId() == R.id.mgmt_account_disable) {
245												selectedAccountForActionMode
246														.setOption(
247																Account.OPTION_DISABLED,
248																true);
249												xmppConnectionService
250														.updateAccount(selectedAccountForActionMode);
251												mode.finish();
252											} else if (item.getItemId() == R.id.mgmt_account_enable) {
253												selectedAccountForActionMode
254														.setOption(
255																Account.OPTION_DISABLED,
256																false);
257												xmppConnectionService
258														.updateAccount(selectedAccountForActionMode);
259												mode.finish();
260											} else if (item.getItemId() == R.id.mgmt_account_delete) {
261												AlertDialog.Builder builder = new AlertDialog.Builder(
262														activity);
263												builder.setTitle(getString(R.string.mgmt_account_are_you_sure));
264												builder.setIconAttribute(android.R.attr.alertDialogIcon);
265												builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text));
266												builder.setPositiveButton(
267														getString(R.string.delete),
268														new OnClickListener() {
269
270															@Override
271															public void onClick(
272																	DialogInterface dialog,
273																	int which) {
274																xmppConnectionService
275																		.deleteAccount(selectedAccountForActionMode);
276																selectedAccountForActionMode = null;
277																mode.finish();
278															}
279														});
280												builder.setNegativeButton(
281														getString(R.string.cancel),
282														null);
283												builder.create().show();
284											} else if (item.getItemId() == R.id.mgmt_account_announce_pgp) {
285												if (activity.hasPgp()) {
286													mode.finish();
287													announcePgp(
288															selectedAccountForActionMode,
289															null);
290												} else {
291													activity.showInstallPgpDialog();
292												}
293											} else if (item.getItemId() == R.id.mgmt_otr_key) {
294												AlertDialog.Builder builder = new AlertDialog.Builder(
295														activity);
296												builder.setTitle("OTR Fingerprint");
297												String fingerprintTxt = selectedAccountForActionMode
298														.getOtrFingerprint(getApplicationContext());
299												View view = (View) getLayoutInflater()
300														.inflate(
301																R.layout.otr_fingerprint,
302																null);
303												if (fingerprintTxt != null) {
304													TextView fingerprint = (TextView) view
305															.findViewById(R.id.otr_fingerprint);
306													TextView noFingerprintView = (TextView) view
307															.findViewById(R.id.otr_no_fingerprint);
308													fingerprint
309															.setText(fingerprintTxt);
310													fingerprint
311															.setVisibility(View.VISIBLE);
312													noFingerprintView
313															.setVisibility(View.GONE);
314												}
315												builder.setView(view);
316												builder.setPositiveButton(
317														getString(R.string.done),
318														null);
319												builder.create().show();
320											} else if (item.getItemId() == R.id.mgmt_account_info) {
321												AlertDialog.Builder builder = new AlertDialog.Builder(
322														activity);
323												builder.setTitle(getString(R.string.account_info));
324												if (selectedAccountForActionMode
325														.getStatus() == Account.STATUS_ONLINE) {
326													XmppConnection xmpp = selectedAccountForActionMode
327															.getXmppConnection();
328													long connectionAge = (SystemClock
329															.elapsedRealtime() - xmpp.lastConnect) / 60000;
330													long sessionAge = (SystemClock
331															.elapsedRealtime() - xmpp.lastSessionStarted) / 60000;
332													long connectionAgeHours = connectionAge / 60;
333													long sessionAgeHours = sessionAge / 60;
334													View view = (View) getLayoutInflater()
335															.inflate(
336																	R.layout.server_info,
337																	null);
338													TextView connection = (TextView) view
339															.findViewById(R.id.connection);
340													TextView session = (TextView) view
341															.findViewById(R.id.session);
342													TextView pcks_sent = (TextView) view
343															.findViewById(R.id.pcks_sent);
344													TextView pcks_received = (TextView) view
345															.findViewById(R.id.pcks_received);
346													TextView carbon = (TextView) view
347															.findViewById(R.id.carbon);
348													TextView stream = (TextView) view
349															.findViewById(R.id.stream);
350													TextView roster = (TextView) view
351															.findViewById(R.id.roster);
352													TextView presences = (TextView) view
353															.findViewById(R.id.number_presences);
354													presences.setText(selectedAccountForActionMode
355															.countPresences()
356															+ "");
357													pcks_received.setText(""
358															+ xmpp.getReceivedStanzas());
359													pcks_sent.setText(""
360															+ xmpp.getSentStanzas());
361													if (connectionAgeHours >= 2) {
362														connection
363																.setText(connectionAgeHours
364																		+ " "
365																		+ getString(R.string.hours));
366													} else {
367														connection
368																.setText(connectionAge
369																		+ " "
370																		+ getString(R.string.mins));
371													}
372													if (xmpp.hasFeatureStreamManagment()) {
373														if (sessionAgeHours >= 2) {
374															session.setText(sessionAgeHours
375																	+ " "
376																	+ getString(R.string.hours));
377														} else {
378															session.setText(sessionAge
379																	+ " "
380																	+ getString(R.string.mins));
381														}
382														stream.setText(getString(R.string.yes));
383													} else {
384														stream.setText(getString(R.string.no));
385														session.setText(connection
386																.getText());
387													}
388													if (xmpp.hasFeaturesCarbon()) {
389														carbon.setText(getString(R.string.yes));
390													} else {
391														carbon.setText(getString(R.string.no));
392													}
393													if (xmpp.hasFeatureRosterManagment()) {
394														roster.setText(getString(R.string.yes));
395													} else {
396														roster.setText(getString(R.string.no));
397													}
398													builder.setView(view);
399												} else {
400													builder.setMessage(getString(R.string.mgmt_account_account_offline));
401												}
402												builder.setPositiveButton(
403														getString(R.string.hide),
404														null);
405												builder.create().show();
406											}
407											return true;
408										}
409
410									}));
411							return true;
412						} else {
413							return false;
414						}
415					}
416				});
417	}
418
419	@Override
420	protected void onStop() {
421		if (xmppConnectionServiceBound) {
422			xmppConnectionService.removeOnAccountListChangedListener();
423		}
424		super.onStop();
425	}
426
427	@Override
428	void onBackendConnected() {
429		xmppConnectionService.setOnAccountListChangedListener(accountChanged);
430		this.accountList.clear();
431		this.accountList.addAll(xmppConnectionService.getAccounts());
432		accountListViewAdapter.notifyDataSetChanged();
433		if ((this.accountList.size() == 0) && (this.firstrun)) {
434			getActionBar().setDisplayHomeAsUpEnabled(false);
435			getActionBar().setHomeButtonEnabled(false);
436			addAccount();
437			this.firstrun = false;
438		}
439	}
440
441	@Override
442	public boolean onCreateOptionsMenu(Menu menu) {
443		getMenuInflater().inflate(R.menu.manageaccounts, menu);
444		return true;
445	}
446
447	@Override
448	public boolean onOptionsItemSelected(MenuItem item) {
449		switch (item.getItemId()) {
450		case R.id.action_add_account:
451			addAccount();
452			break;
453		default:
454			break;
455		}
456		return super.onOptionsItemSelected(item);
457	}
458
459	@Override
460	public boolean onNavigateUp() {
461		if (xmppConnectionService.getConversations().size() == 0) {
462			Intent contactsIntent = new Intent(this, StartConversationActivity.class);
463			contactsIntent.setFlags(
464			// if activity exists in stack, pop the stack and go back to it
465					Intent.FLAG_ACTIVITY_CLEAR_TOP |
466					// otherwise, make a new task for it
467							Intent.FLAG_ACTIVITY_NEW_TASK |
468							// don't use the new activity animation; finish
469							// animation runs instead
470							Intent.FLAG_ACTIVITY_NO_ANIMATION);
471			startActivity(contactsIntent);
472			finish();
473			return true;
474		} else {
475			return super.onNavigateUp();
476		}
477	}
478
479	private void editAccount(Account account) {
480		EditAccountDialog dialog = new EditAccountDialog();
481		dialog.setAccount(account);
482		dialog.setEditAccountListener(new EditAccountListener() {
483
484			@Override
485			public void onAccountEdited(Account account) {
486				xmppConnectionService.updateAccount(account);
487				if (actionMode != null) {
488					actionMode.finish();
489				}
490			}
491		});
492		dialog.show(getFragmentManager(), "edit_account");
493		dialog.setKnownHosts(xmppConnectionService.getKnownHosts(), this);
494
495	}
496
497	protected void addAccount() {
498		final Activity activity = this;
499		EditAccountDialog dialog = new EditAccountDialog();
500		dialog.setEditAccountListener(new EditAccountListener() {
501
502			@Override
503			public void onAccountEdited(Account account) {
504				xmppConnectionService.createAccount(account);
505				activity.getActionBar().setDisplayHomeAsUpEnabled(true);
506				activity.getActionBar().setHomeButtonEnabled(true);
507			}
508		});
509		dialog.show(getFragmentManager(), "add_account");
510		dialog.setKnownHosts(xmppConnectionService.getKnownHosts(), this);
511	}
512
513	@Override
514	public void onActionModeStarted(ActionMode mode) {
515		super.onActionModeStarted(mode);
516		this.isActionMode = true;
517	}
518
519	@Override
520	public void onActionModeFinished(ActionMode mode) {
521		super.onActionModeFinished(mode);
522		this.isActionMode = false;
523		accountListView.clearChoices();
524		accountListView.requestLayout();
525		accountListView.post(new Runnable() {
526			@Override
527			public void run() {
528				accountListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
529			}
530		});
531	}
532
533	@Override
534	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
535		super.onActivityResult(requestCode, resultCode, data);
536		if (resultCode == RESULT_OK) {
537			if (requestCode == REQUEST_ANNOUNCE_PGP) {
538				announcePgp(selectedAccountForActionMode, null);
539			}
540		}
541	}
542}