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