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.crypto.PgpEngine;
  8import eu.siacs.conversations.crypto.PgpEngine.UserInputRequiredException;
  9import eu.siacs.conversations.entities.Account;
 10import eu.siacs.conversations.ui.EditAccount.EditAccountListener;
 11import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
 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.content.IntentSender.SendIntentException;
 19import android.os.Bundle;
 20import android.util.Log;
 21import android.view.ActionMode;
 22import android.view.LayoutInflater;
 23import android.view.Menu;
 24import android.view.MenuInflater;
 25import android.view.MenuItem;
 26import android.view.View;
 27import android.view.ViewGroup;
 28import android.widget.AdapterView;
 29import android.widget.AdapterView.OnItemClickListener;
 30import android.widget.AdapterView.OnItemLongClickListener;
 31import android.widget.ArrayAdapter;
 32import android.widget.ListView;
 33import android.widget.TextView;
 34
 35public class ManageAccountActivity extends XmppActivity {
 36
 37	public static final int REQUEST_ANNOUNCE_PGP = 0x73731;
 38	
 39	protected boolean isActionMode = false;
 40	protected ActionMode actionMode;
 41	protected Account selectedAccountForActionMode = null;
 42	protected ManageAccountActivity activity = this;
 43	
 44	protected List<Account> accountList = new ArrayList<Account>();
 45	protected ListView accountListView;
 46	protected ArrayAdapter<Account> accountListViewAdapter;
 47	protected OnAccountListChangedListener accountChanged = new OnAccountListChangedListener() {
 48
 49		@Override
 50		public void onAccountListChangedListener() {
 51			Log.d("xmppService", "ui on account list changed listener");
 52			accountList.clear();
 53			accountList.addAll(xmppConnectionService.getAccounts());
 54			runOnUiThread(new Runnable() {
 55
 56				@Override
 57				public void run() {
 58					accountListViewAdapter.notifyDataSetChanged();
 59				}
 60			});
 61		}
 62	};
 63	
 64	protected OnTLSExceptionReceived tlsExceptionReceived = new OnTLSExceptionReceived() {
 65		
 66		@Override
 67		public void onTLSExceptionReceived(final String fingerprint, final Account account) {
 68			activity.runOnUiThread(new Runnable() {
 69				
 70				@Override
 71				public void run() {
 72					AlertDialog.Builder builder = new AlertDialog.Builder(activity);
 73					builder.setTitle("Untrusted Certificate");
 74					builder.setIconAttribute(android.R.attr.alertDialogIcon);
 75					View view = (View) getLayoutInflater().inflate(R.layout.cert_warning, null);
 76					TextView sha = (TextView) view.findViewById(R.id.sha);
 77					TextView hint = (TextView) view.findViewById(R.id.hint);
 78					StringBuilder humanReadableSha = new StringBuilder();
 79					humanReadableSha.append(fingerprint);
 80					for(int i = 2; i < 58; i += 3) {
 81						humanReadableSha.insert(i, ":");
 82					}
 83					hint.setText(account.getServer()+" presented you with an unstrusted, possible self signed, certificate.\nThe SHA1 fingerprint is");
 84					sha.setText(humanReadableSha.toString());
 85					builder.setView(view);
 86					//builder.setMessage(server+" presented you with an unstrusted, possible self signed, certificate. The SHA1 fingerprint is "+fingerprint+" Do not connect unless you know exactly what you are doing");
 87					builder.setNegativeButton("Don't connect", null);
 88					builder.setPositiveButton("Trust certificate", new OnClickListener() {
 89						
 90						@Override
 91						public void onClick(DialogInterface dialog, int which) {
 92							account.setSSLCertFingerprint(fingerprint);
 93							activity.xmppConnectionService.updateAccount(account);
 94						}
 95					});
 96					builder.create().show();
 97				}
 98			});
 99			
100		}
101	};
102
103	@Override
104	protected void onCreate(Bundle savedInstanceState) {
105
106		super.onCreate(savedInstanceState);
107
108		setContentView(R.layout.manage_accounts);
109
110		accountListView = (ListView) findViewById(R.id.account_list);
111		accountListViewAdapter = new ArrayAdapter<Account>(
112				getApplicationContext(), R.layout.account_row, this.accountList) {
113			@Override
114			public View getView(int position, View view, ViewGroup parent) {
115				Account account = getItem(position);
116				if (view == null) {
117					LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
118					view = (View) inflater.inflate(R.layout.account_row, null);
119				}
120				((TextView) view.findViewById(R.id.account_jid))
121						.setText(account.getJid());
122				TextView statusView = (TextView) view
123						.findViewById(R.id.account_status);
124				switch (account.getStatus()) {
125				case Account.STATUS_DISABLED:
126					statusView.setText("temporarily disabled");
127					statusView.setTextColor(0xFF1da9da);
128					break;
129				case Account.STATUS_ONLINE:
130					statusView.setText("online");
131					statusView.setTextColor(0xFF83b600);
132					break;
133				case Account.STATUS_CONNECTING:
134					statusView.setText("connecting\u2026");
135					statusView.setTextColor(0xFF1da9da);
136					break;
137				case Account.STATUS_OFFLINE:
138					statusView.setText("offline");
139					statusView.setTextColor(0xFFe92727);
140					break;
141				case Account.STATUS_UNAUTHORIZED:
142					statusView.setText("unauthorized");
143					statusView.setTextColor(0xFFe92727);
144					break;
145				case Account.STATUS_SERVER_NOT_FOUND:
146					statusView.setText("server not found");
147					statusView.setTextColor(0xFFe92727);
148					break;
149				case Account.STATUS_NO_INTERNET:
150					statusView.setText("no internet");
151					statusView.setTextColor(0xFFe92727);
152					break;
153				case Account.STATUS_SERVER_REQUIRES_TLS:
154					statusView.setText("server requires TLS");
155					statusView.setTextColor(0xFFe92727);
156					break;
157				case Account.STATUS_TLS_ERROR:
158					statusView.setText("untrusted cerficate");
159					statusView.setTextColor(0xFFe92727);
160					break;
161				default:
162					break;
163				}
164
165				return view;
166			}
167		};
168		final XmppActivity activity = this;
169		accountListView.setAdapter(this.accountListViewAdapter);
170		accountListView.setOnItemClickListener(new OnItemClickListener() {
171
172			@Override
173			public void onItemClick(AdapterView<?> arg0, View view,
174					int position, long arg3) {
175				if (!isActionMode) {
176					Account account = accountList.get(position);
177					if ((account.getStatus() != Account.STATUS_ONLINE)&&(account.getStatus() != Account.STATUS_CONNECTING)&&(!account.isOptionSet(Account.OPTION_DISABLED))) {
178						activity.xmppConnectionService.reconnectAccount(accountList.get(position));
179					} else if (account.getStatus() == Account.STATUS_ONLINE) {
180						activity.startActivity(new Intent(activity.getApplicationContext(),NewConversationActivity.class));
181					}
182					
183					Log.d("gultsch","clicked on account "+accountList.get(position).getJid());
184				} else {
185					selectedAccountForActionMode = accountList.get(position);
186					actionMode.invalidate();
187				}
188			}
189		});
190		accountListView.setOnItemLongClickListener(new OnItemLongClickListener() {
191
192			@Override
193			public boolean onItemLongClick(AdapterView<?> arg0, View view,
194					int position, long arg3) {
195				if (!isActionMode) {
196					accountListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
197					accountListView.setItemChecked(position,true);
198					selectedAccountForActionMode = accountList.get(position);
199					actionMode = activity.startActionMode((new ActionMode.Callback() {
200						
201						@Override
202						public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
203							if (selectedAccountForActionMode.isOptionSet(Account.OPTION_DISABLED)) {
204					        	menu.findItem(R.id.mgmt_account_enable).setVisible(true);
205					        	menu.findItem(R.id.mgmt_account_disable).setVisible(false);
206					        } else {
207					        	menu.findItem(R.id.mgmt_account_disable).setVisible(true);
208					        	menu.findItem(R.id.mgmt_account_enable).setVisible(false);
209					        }
210							return true;
211						}
212						
213						@Override
214						public void onDestroyActionMode(ActionMode mode) {
215							// TODO Auto-generated method stub
216							
217						}
218						
219						@Override
220						public boolean onCreateActionMode(ActionMode mode, Menu menu) {
221							MenuInflater inflater = mode.getMenuInflater();
222					        inflater.inflate(R.menu.manageaccounts_context, menu);
223							return true;
224						}
225						
226						@Override
227						public boolean onActionItemClicked(final ActionMode mode, MenuItem item) {
228							if (item.getItemId()==R.id.mgmt_account_edit) {
229								EditAccount dialog = new EditAccount();
230								dialog.setAccount(selectedAccountForActionMode);
231								dialog.setEditAccountListener(new EditAccountListener() {
232				
233									@Override
234									public void onAccountEdited(Account account) {
235										xmppConnectionService.updateAccount(account);
236										actionMode.finish();
237									}
238								});
239								dialog.show(getFragmentManager(), "edit_account");
240							} else if (item.getItemId()==R.id.mgmt_account_disable) {
241								selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, true);
242								xmppConnectionService.updateAccount(selectedAccountForActionMode);
243								mode.finish();
244							} else if (item.getItemId()==R.id.mgmt_account_enable) {
245								selectedAccountForActionMode.setOption(Account.OPTION_DISABLED, false);
246								xmppConnectionService.updateAccount(selectedAccountForActionMode);
247								mode.finish();
248							} else if (item.getItemId()==R.id.mgmt_account_delete) {
249								AlertDialog.Builder builder = new AlertDialog.Builder(activity);
250								builder.setTitle("Are you sure?");
251								builder.setIconAttribute(android.R.attr.alertDialogIcon);
252								builder.setMessage("If you delete your account your entire conversation history will be lost");
253								builder.setPositiveButton("Delete", new OnClickListener() {
254									
255									@Override
256									public void onClick(DialogInterface dialog, int which) {
257										xmppConnectionService.deleteAccount(selectedAccountForActionMode);
258										selectedAccountForActionMode = null;
259										mode.finish();
260									}
261								});
262								builder.setNegativeButton("Cancel",null);
263								builder.create().show();
264							} else if (item.getItemId()==R.id.mgmt_account_announce_pgp) {
265								if (activity.hasPgp()) {
266									mode.finish();
267									try {
268										xmppConnectionService.generatePgpAnnouncement(selectedAccountForActionMode);
269									} catch (PgpEngine.UserInputRequiredException e) {
270										try {
271											startIntentSenderForResult(e.getPendingIntent().getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0);
272										} catch (SendIntentException e1) {
273											Log.d("gultsch","sending intent failed");
274										}
275									}
276								}
277							}
278							return true;
279						}
280					}));
281					return true;
282				} else {
283					return false;
284				}
285			}
286		});
287	}
288
289	@Override
290	protected void onStop() {
291		if (xmppConnectionServiceBound) {
292			xmppConnectionService.removeOnAccountListChangedListener();
293			xmppConnectionService.removeOnTLSExceptionReceivedListener();
294		}
295		super.onStop();
296	}
297
298	@Override
299	void onBackendConnected() {
300		xmppConnectionService.setOnAccountListChangedListener(accountChanged);
301		xmppConnectionService.setOnTLSExceptionReceivedListener(tlsExceptionReceived);
302		this.accountList.clear();
303		this.accountList.addAll(xmppConnectionService.getAccounts());
304		accountListViewAdapter.notifyDataSetChanged();
305		if (this.accountList.size() == 0) {
306			getActionBar().setDisplayHomeAsUpEnabled(false);
307			addAccount();
308		}
309	}
310
311	@Override
312	public boolean onCreateOptionsMenu(Menu menu) {
313		getMenuInflater().inflate(R.menu.manageaccounts, menu);
314		return true;
315	}
316
317	@Override
318	public boolean onOptionsItemSelected(MenuItem item) {
319		switch (item.getItemId()) {
320		case R.id.action_settings:
321			startActivity(new Intent(this, SettingsActivity.class));
322			break;
323		case R.id.action_add_account:
324			addAccount();
325			break;
326		default:
327			break;
328		}
329		return super.onOptionsItemSelected(item);
330	}
331
332	protected void addAccount() {
333		final Activity activity = this;
334		EditAccount dialog = new EditAccount();
335		dialog.setEditAccountListener(new EditAccountListener() {
336
337			@Override
338			public void onAccountEdited(Account account) {
339				xmppConnectionService.createAccount(account);
340				activity.getActionBar().setDisplayHomeAsUpEnabled(true);
341			}
342		});
343		dialog.show(getFragmentManager(), "add_account");
344	}
345
346	
347	@Override
348	public void onActionModeStarted(ActionMode mode) {
349		super.onActionModeStarted(mode);
350		this.isActionMode = true;
351	}
352	
353	@Override
354	public void onActionModeFinished(ActionMode mode) {
355		super.onActionModeFinished(mode);
356		this.isActionMode = false;
357		accountListView.clearChoices();
358		accountListView.requestLayout();
359		accountListView.post(new Runnable() {
360            @Override
361            public void run() {
362                accountListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
363            }
364        });
365	}
366	
367	 @Override
368	 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
369		 super.onActivityResult(requestCode, resultCode, data);
370		 if (resultCode == RESULT_OK) {
371			if (requestCode == REQUEST_ANNOUNCE_PGP) {
372				 try {
373					xmppConnectionService.generatePgpAnnouncement(selectedAccountForActionMode);
374				} catch (UserInputRequiredException e) {
375					Log.d("gultsch","already came back. ignoring");
376				}
377			 }
378		 }
379	 }
380}