ManageAccountActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.app.ActionBar;
  4import android.app.AlertDialog;
  5import android.content.ActivityNotFoundException;
  6import android.content.DialogInterface;
  7import android.content.DialogInterface.OnClickListener;
  8import android.content.Intent;
  9import android.os.Bundle;
 10import android.security.KeyChain;
 11import android.security.KeyChainAliasCallback;
 12import android.view.ContextMenu;
 13import android.view.ContextMenu.ContextMenuInfo;
 14import android.view.Menu;
 15import android.view.MenuItem;
 16import android.view.View;
 17import android.widget.AdapterView;
 18import android.widget.AdapterView.AdapterContextMenuInfo;
 19import android.widget.AdapterView.OnItemClickListener;
 20import android.widget.ListView;
 21import android.widget.Toast;
 22
 23import java.util.ArrayList;
 24import java.util.List;
 25import java.util.concurrent.atomic.AtomicBoolean;
 26
 27import eu.siacs.conversations.Config;
 28import eu.siacs.conversations.R;
 29import eu.siacs.conversations.entities.Account;
 30import eu.siacs.conversations.services.XmppConnectionService;
 31import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
 32import eu.siacs.conversations.ui.adapter.AccountAdapter;
 33import org.openintents.openpgp.util.OpenPgpApi;
 34
 35public class ManageAccountActivity extends XmppActivity implements OnAccountUpdate, KeyChainAliasCallback, XmppConnectionService.OnAccountCreated {
 36
 37	protected Account selectedAccount = null;
 38
 39	protected final List<Account> accountList = new ArrayList<>();
 40	protected ListView accountListView;
 41	protected AccountAdapter mAccountAdapter;
 42	protected AtomicBoolean mInvokedAddAccount = new AtomicBoolean(false);
 43
 44	@Override
 45	public void onAccountUpdate() {
 46		refreshUi();
 47	}
 48
 49	@Override
 50	protected void refreshUiReal() {
 51		synchronized (this.accountList) {
 52			accountList.clear();
 53			accountList.addAll(xmppConnectionService.getAccounts());
 54		}
 55		ActionBar actionBar = getActionBar();
 56		if (actionBar != null) {
 57			actionBar.setHomeButtonEnabled(this.accountList.size() > 0);
 58			actionBar.setDisplayHomeAsUpEnabled(this.accountList.size() > 0);
 59		}
 60		invalidateOptionsMenu();
 61		mAccountAdapter.notifyDataSetChanged();
 62	}
 63
 64	@Override
 65	protected void onCreate(Bundle savedInstanceState) {
 66
 67		super.onCreate(savedInstanceState);
 68
 69		setContentView(R.layout.manage_accounts);
 70
 71		accountListView = (ListView) findViewById(R.id.account_list);
 72		this.mAccountAdapter = new AccountAdapter(this, accountList);
 73		accountListView.setAdapter(this.mAccountAdapter);
 74		accountListView.setOnItemClickListener(new OnItemClickListener() {
 75
 76			@Override
 77			public void onItemClick(AdapterView<?> arg0, View view,
 78									int position, long arg3) {
 79				switchToAccount(accountList.get(position));
 80			}
 81		});
 82		registerForContextMenu(accountListView);
 83	}
 84
 85	@Override
 86	public void onCreateContextMenu(ContextMenu menu, View v,
 87			ContextMenuInfo menuInfo) {
 88		super.onCreateContextMenu(menu, v, menuInfo);
 89		ManageAccountActivity.this.getMenuInflater().inflate(
 90				R.menu.manageaccounts_context, menu);
 91		AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
 92		this.selectedAccount = accountList.get(acmi.position);
 93		if (this.selectedAccount.isOptionSet(Account.OPTION_DISABLED)) {
 94			menu.findItem(R.id.mgmt_account_disable).setVisible(false);
 95			menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false);
 96			menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false);
 97		} else {
 98			menu.findItem(R.id.mgmt_account_enable).setVisible(false);
 99			menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(!Config.HIDE_PGP_IN_UI);
100		}
101		menu.setHeaderTitle(this.selectedAccount.getJid().toBareJid().toString());
102	}
103
104	@Override
105	void onBackendConnected() {
106		refreshUiReal();
107		if (Config.X509_VERIFICATION && this.accountList.size() == 0) {
108			if (mInvokedAddAccount.compareAndSet(false,true)) {
109				addAccountFromKey();
110			}
111		}
112	}
113
114	@Override
115	public boolean onCreateOptionsMenu(Menu menu) {
116		getMenuInflater().inflate(R.menu.manageaccounts, menu);
117		MenuItem enableAll = menu.findItem(R.id.action_enable_all);
118		MenuItem addAccount = menu.findItem(R.id.action_add_account);
119		MenuItem addAccountWithCertificate = menu.findItem(R.id.action_add_account_with_cert);
120
121		if (Config.X509_VERIFICATION) {
122			addAccount.setVisible(false);
123			addAccountWithCertificate.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
124		}
125
126		if (!accountsLeftToEnable()) {
127			enableAll.setVisible(false);
128		}
129		MenuItem disableAll = menu.findItem(R.id.action_disable_all);
130		if (!accountsLeftToDisable()) {
131			disableAll.setVisible(false);
132		}
133		return true;
134	}
135
136	@Override
137	public boolean onContextItemSelected(MenuItem item) {
138		switch (item.getItemId()) {
139		case R.id.mgmt_account_publish_avatar:
140			publishAvatar(selectedAccount);
141			return true;
142		case R.id.mgmt_account_disable:
143			disableAccount(selectedAccount);
144			return true;
145		case R.id.mgmt_account_enable:
146			enableAccount(selectedAccount);
147			return true;
148		case R.id.mgmt_account_delete:
149			deleteAccount(selectedAccount);
150			return true;
151		case R.id.mgmt_account_announce_pgp:
152			choosePgpSignId(selectedAccount);
153			return true;
154		default:
155			return super.onContextItemSelected(item);
156		}
157	}
158
159	@Override
160	public boolean onOptionsItemSelected(MenuItem item) {
161		switch (item.getItemId()) {
162			case R.id.action_add_account:
163				startActivity(new Intent(getApplicationContext(),
164						EditAccountActivity.class));
165				break;
166			case R.id.action_disable_all:
167				disableAllAccounts();
168				break;
169			case R.id.action_enable_all:
170				enableAllAccounts();
171				break;
172			case R.id.action_add_account_with_cert:
173				addAccountFromKey();
174				break;
175			default:
176				break;
177		}
178		return super.onOptionsItemSelected(item);
179	}
180
181	@Override
182	public boolean onNavigateUp() {
183		if (xmppConnectionService.getConversations().size() == 0) {
184			Intent contactsIntent = new Intent(this,
185					StartConversationActivity.class);
186			contactsIntent.setFlags(
187			// if activity exists in stack, pop the stack and go back to it
188					Intent.FLAG_ACTIVITY_CLEAR_TOP |
189					// otherwise, make a new task for it
190							Intent.FLAG_ACTIVITY_NEW_TASK |
191							// don't use the new activity animation; finish
192							// animation runs instead
193							Intent.FLAG_ACTIVITY_NO_ANIMATION);
194			startActivity(contactsIntent);
195			finish();
196			return true;
197		} else {
198			return super.onNavigateUp();
199		}
200	}
201
202	public void onClickTglAccountState(Account account, boolean enable) {
203		if (enable) {
204			enableAccount(account);
205		} else {
206			disableAccount(account);
207		}
208	}
209
210	private void addAccountFromKey() {
211		try {
212			KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null);
213		} catch (ActivityNotFoundException e) {
214			Toast.makeText(this,R.string.device_does_not_support_certificates,Toast.LENGTH_LONG).show();
215		}
216	}
217
218	private void publishAvatar(Account account) {
219		Intent intent = new Intent(getApplicationContext(),
220				PublishProfilePictureActivity.class);
221		intent.putExtra("account", account.getJid().toString());
222		startActivity(intent);
223	}
224
225	private void disableAllAccounts() {
226		List<Account> list = new ArrayList<>();
227		synchronized (this.accountList) {
228			for (Account account : this.accountList) {
229				if (!account.isOptionSet(Account.OPTION_DISABLED)) {
230					list.add(account);
231				}
232			}
233		}
234		for(Account account : list) {
235			disableAccount(account);
236		}
237	}
238
239	private boolean accountsLeftToDisable() {
240		synchronized (this.accountList) {
241			for (Account account : this.accountList) {
242				if (!account.isOptionSet(Account.OPTION_DISABLED)) {
243					return true;
244				}
245			}
246			return false;
247		}
248	}
249
250	private boolean accountsLeftToEnable() {
251		synchronized (this.accountList) {
252			for (Account account : this.accountList) {
253				if (account.isOptionSet(Account.OPTION_DISABLED)) {
254					return true;
255				}
256			}
257			return false;
258		}
259	}
260
261	private void enableAllAccounts() {
262		List<Account> list = new ArrayList<>();
263		synchronized (this.accountList) {
264			for (Account account : this.accountList) {
265				if (account.isOptionSet(Account.OPTION_DISABLED)) {
266					list.add(account);
267				}
268			}
269		}
270		for(Account account : list) {
271			enableAccount(account);
272		}
273	}
274
275	private void disableAccount(Account account) {
276		account.setOption(Account.OPTION_DISABLED, true);
277		xmppConnectionService.updateAccount(account);
278	}
279
280	private void enableAccount(Account account) {
281		account.setOption(Account.OPTION_DISABLED, false);
282		xmppConnectionService.updateAccount(account);
283	}
284
285	private void publishOpenPGPPublicKey(Account account) {
286		if (ManageAccountActivity.this.hasPgp()) {
287			announcePgp(account, null);
288		} else {
289			this.showInstallPgpDialog();
290		}
291	}
292
293	private void deleteAccount(final Account account) {
294		AlertDialog.Builder builder = new AlertDialog.Builder(
295				ManageAccountActivity.this);
296		builder.setTitle(getString(R.string.mgmt_account_are_you_sure));
297		builder.setIconAttribute(android.R.attr.alertDialogIcon);
298		builder.setMessage(getString(R.string.mgmt_account_delete_confirm_text));
299		builder.setPositiveButton(getString(R.string.delete),
300				new OnClickListener() {
301					@Override
302					public void onClick(DialogInterface dialog, int which) {
303						xmppConnectionService.deleteAccount(account);
304						selectedAccount = null;
305					}
306				});
307		builder.setNegativeButton(getString(R.string.cancel), null);
308		builder.create().show();
309	}
310
311	@Override
312	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
313		super.onActivityResult(requestCode, resultCode, data);
314		if (resultCode == RESULT_OK) {
315			if (requestCode == REQUEST_CHOOSE_PGP_ID) {
316				if (data.getExtras().containsKey(OpenPgpApi.EXTRA_SIGN_KEY_ID)) {
317					selectedAccount.setPgpSignId(data.getExtras().getLong(OpenPgpApi.EXTRA_SIGN_KEY_ID));
318					announcePgp(selectedAccount, null);
319				} else {
320					choosePgpSignId(selectedAccount);
321				}
322			} else if (requestCode == REQUEST_ANNOUNCE_PGP) {
323				announcePgp(selectedAccount, null);
324			}
325		}
326	}
327
328	@Override
329	public void alias(String alias) {
330		if (alias != null) {
331			xmppConnectionService.createAccountFromKey(alias, this);
332		}
333	}
334
335	@Override
336	public void onAccountCreated(Account account) {
337		switchToAccount(account, true);
338	}
339
340	@Override
341	public void informUser(final int r) {
342		runOnUiThread(new Runnable() {
343			@Override
344			public void run() {
345				Toast.makeText(ManageAccountActivity.this,r,Toast.LENGTH_LONG).show();
346			}
347		});
348	}
349}