EditAccountActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.app.AlertDialog.Builder;
  4import android.app.PendingIntent;
  5import android.content.DialogInterface;
  6import android.content.Intent;
  7import android.os.Bundle;
  8import android.text.Editable;
  9import android.text.TextWatcher;
 10import android.view.Menu;
 11import android.view.MenuItem;
 12import android.view.View;
 13import android.view.View.OnClickListener;
 14import android.widget.AutoCompleteTextView;
 15import android.widget.Button;
 16import android.widget.CheckBox;
 17import android.widget.CompoundButton;
 18import android.widget.CompoundButton.OnCheckedChangeListener;
 19import android.widget.EditText;
 20import android.widget.ImageButton;
 21import android.widget.ImageView;
 22import android.widget.LinearLayout;
 23import android.widget.RelativeLayout;
 24import android.widget.TableLayout;
 25import android.widget.TextView;
 26import android.widget.Toast;
 27
 28import java.util.Set;
 29
 30import eu.siacs.conversations.Config;
 31import eu.siacs.conversations.R;
 32import eu.siacs.conversations.crypto.axolotl.AxolotlService;
 33import eu.siacs.conversations.entities.Account;
 34import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
 35import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
 36import eu.siacs.conversations.utils.CryptoHelper;
 37import eu.siacs.conversations.utils.UIHelper;
 38import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
 39import eu.siacs.conversations.xmpp.XmppConnection.Features;
 40import eu.siacs.conversations.xmpp.jid.InvalidJidException;
 41import eu.siacs.conversations.xmpp.jid.Jid;
 42import eu.siacs.conversations.xmpp.pep.Avatar;
 43
 44public class EditAccountActivity extends XmppActivity implements OnAccountUpdate, OnKeyStatusUpdated {
 45
 46	private AutoCompleteTextView mAccountJid;
 47	private EditText mPassword;
 48	private EditText mPasswordConfirm;
 49	private CheckBox mRegisterNew;
 50	private Button mCancelButton;
 51	private Button mSaveButton;
 52	private TableLayout mMoreTable;
 53
 54	private LinearLayout mStats;
 55	private TextView mServerInfoSm;
 56	private TextView mServerInfoRosterVersion;
 57	private TextView mServerInfoCarbons;
 58	private TextView mServerInfoMam;
 59	private TextView mServerInfoCSI;
 60	private TextView mServerInfoBlocking;
 61	private TextView mServerInfoPep;
 62	private TextView mServerInfoHttpUpload;
 63	private TextView mSessionEst;
 64	private TextView mOtrFingerprint;
 65	private TextView mAxolotlFingerprint;
 66	private TextView mAccountJidLabel;
 67	private ImageView mAvatar;
 68	private RelativeLayout mOtrFingerprintBox;
 69	private RelativeLayout mAxolotlFingerprintBox;
 70	private ImageButton mOtrFingerprintToClipboardButton;
 71	private ImageButton mAxolotlFingerprintToClipboardButton;
 72	private ImageButton mRegenerateAxolotlKeyButton;
 73	private LinearLayout keys;
 74	private LinearLayout keysCard;
 75
 76	private Jid jidToEdit;
 77	private Account mAccount;
 78	private String messageFingerprint;
 79
 80	private boolean mFetchingAvatar = false;
 81
 82	private final OnClickListener mSaveButtonClickListener = new OnClickListener() {
 83
 84		@Override
 85		public void onClick(final View v) {
 86			if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED && !accountInfoEdited()) {
 87				mAccount.setOption(Account.OPTION_DISABLED, false);
 88				xmppConnectionService.updateAccount(mAccount);
 89				return;
 90			}
 91			final boolean registerNewAccount = mRegisterNew.isChecked() && !Config.DISALLOW_REGISTRATION_IN_UI;
 92			if (Config.DOMAIN_LOCK != null && mAccountJid.getText().toString().contains("@")) {
 93				mAccountJid.setError(getString(R.string.invalid_username));
 94				mAccountJid.requestFocus();
 95				return;
 96			}
 97			final Jid jid;
 98			try {
 99				if (Config.DOMAIN_LOCK != null) {
100					jid = Jid.fromParts(mAccountJid.getText().toString(),Config.DOMAIN_LOCK,null);
101				} else {
102					jid = Jid.fromString(mAccountJid.getText().toString());
103				}
104			} catch (final InvalidJidException e) {
105				if (Config.DOMAIN_LOCK != null) {
106					mAccountJid.setError(getString(R.string.invalid_username));
107				} else {
108					mAccountJid.setError(getString(R.string.invalid_jid));
109				}
110				mAccountJid.requestFocus();
111				return;
112			}
113			if (jid.isDomainJid()) {
114				if (Config.DOMAIN_LOCK != null) {
115					mAccountJid.setError(getString(R.string.invalid_username));
116				} else {
117					mAccountJid.setError(getString(R.string.invalid_jid));
118				}
119				mAccountJid.requestFocus();
120				return;
121			}
122			final String password = mPassword.getText().toString();
123			final String passwordConfirm = mPasswordConfirm.getText().toString();
124			if (registerNewAccount) {
125				if (!password.equals(passwordConfirm)) {
126					mPasswordConfirm.setError(getString(R.string.passwords_do_not_match));
127					mPasswordConfirm.requestFocus();
128					return;
129				}
130			}
131			if (mAccount != null) {
132				try {
133					mAccount.setUsername(jid.hasLocalpart() ? jid.getLocalpart() : "");
134					mAccount.setServer(jid.getDomainpart());
135				} catch (final InvalidJidException ignored) {
136					return;
137				}
138				mAccountJid.setError(null);
139				mPasswordConfirm.setError(null);
140				mAccount.setPassword(password);
141				mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
142				xmppConnectionService.updateAccount(mAccount);
143			} else {
144				if (xmppConnectionService.findAccountByJid(jid) != null) {
145					mAccountJid.setError(getString(R.string.account_already_exists));
146					mAccountJid.requestFocus();
147					return;
148				}
149				mAccount = new Account(jid.toBareJid(), password);
150				mAccount.setOption(Account.OPTION_USETLS, true);
151				mAccount.setOption(Account.OPTION_USECOMPRESSION, true);
152				mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
153				xmppConnectionService.createAccount(mAccount);
154			}
155			if (jidToEdit != null && !mAccount.isOptionSet(Account.OPTION_DISABLED)) {
156				finish();
157			} else {
158				updateSaveButton();
159				updateAccountInformation(true);
160			}
161
162		}
163	};
164	private final OnClickListener mCancelButtonClickListener = new OnClickListener() {
165
166		@Override
167		public void onClick(final View v) {
168			finish();
169		}
170	};
171
172	public void refreshUiReal() {
173		invalidateOptionsMenu();
174		if (mAccount != null
175				&& mAccount.getStatus() != Account.State.ONLINE
176				&& mFetchingAvatar) {
177			startActivity(new Intent(getApplicationContext(),
178						ManageAccountActivity.class));
179			finish();
180		} else if (jidToEdit == null && mAccount != null
181				&& mAccount.getStatus() == Account.State.ONLINE) {
182			if (!mFetchingAvatar) {
183				mFetchingAvatar = true;
184				xmppConnectionService.checkForAvatar(mAccount,
185						mAvatarFetchCallback);
186			}
187		} else {
188			updateSaveButton();
189		}
190		if (mAccount != null) {
191			updateAccountInformation(false);
192		}
193	}
194
195	@Override
196	public void onAccountUpdate() {
197		refreshUi();
198	}
199	private final UiCallback<Avatar> mAvatarFetchCallback = new UiCallback<Avatar>() {
200
201		@Override
202		public void userInputRequried(final PendingIntent pi, final Avatar avatar) {
203			finishInitialSetup(avatar);
204		}
205
206		@Override
207		public void success(final Avatar avatar) {
208			finishInitialSetup(avatar);
209		}
210
211		@Override
212		public void error(final int errorCode, final Avatar avatar) {
213			finishInitialSetup(avatar);
214		}
215	};
216	private final TextWatcher mTextWatcher = new TextWatcher() {
217
218		@Override
219		public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
220			updateSaveButton();
221		}
222
223		@Override
224		public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
225		}
226
227		@Override
228		public void afterTextChanged(final Editable s) {
229
230		}
231	};
232
233	private final OnClickListener mAvatarClickListener = new OnClickListener() {
234		@Override
235		public void onClick(final View view) {
236			if (mAccount != null) {
237				final Intent intent = new Intent(getApplicationContext(),
238						PublishProfilePictureActivity.class);
239				intent.putExtra("account", mAccount.getJid().toBareJid().toString());
240				startActivity(intent);
241			}
242		}
243	};
244
245	protected void finishInitialSetup(final Avatar avatar) {
246		runOnUiThread(new Runnable() {
247
248			@Override
249			public void run() {
250				final Intent intent;
251				if (avatar != null) {
252					intent = new Intent(getApplicationContext(),
253							StartConversationActivity.class);
254					if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) {
255						intent.putExtra("init", true);
256					}
257				} else {
258					intent = new Intent(getApplicationContext(),
259							PublishProfilePictureActivity.class);
260					intent.putExtra("account", mAccount.getJid().toBareJid().toString());
261					intent.putExtra("setup", true);
262				}
263				startActivity(intent);
264				finish();
265			}
266		});
267	}
268
269	protected void updateSaveButton() {
270		if (accountInfoEdited() && jidToEdit != null) {
271			this.mSaveButton.setText(R.string.save);
272			this.mSaveButton.setEnabled(true);
273			this.mSaveButton.setTextColor(getPrimaryTextColor());
274		} else if (mAccount != null && (mAccount.getStatus() == Account.State.CONNECTING || mFetchingAvatar)) {
275			this.mSaveButton.setEnabled(false);
276			this.mSaveButton.setTextColor(getSecondaryTextColor());
277			this.mSaveButton.setText(R.string.account_status_connecting);
278		} else if (mAccount != null && mAccount.getStatus() == Account.State.DISABLED) {
279			this.mSaveButton.setEnabled(true);
280			this.mSaveButton.setTextColor(getPrimaryTextColor());
281			this.mSaveButton.setText(R.string.enable);
282		} else {
283			this.mSaveButton.setEnabled(true);
284			this.mSaveButton.setTextColor(getPrimaryTextColor());
285			if (jidToEdit != null) {
286				if (mAccount != null && mAccount.isOnlineAndConnected()) {
287					this.mSaveButton.setText(R.string.save);
288					if (!accountInfoEdited()) {
289						this.mSaveButton.setEnabled(false);
290						this.mSaveButton.setTextColor(getSecondaryTextColor());
291					}
292				} else {
293					this.mSaveButton.setText(R.string.connect);
294				}
295			} else {
296				this.mSaveButton.setText(R.string.next);
297			}
298		}
299	}
300
301	protected boolean accountInfoEdited() {
302		if (this.mAccount == null) {
303			return false;
304		}
305		final String unmodified;
306		if (Config.DOMAIN_LOCK != null) {
307			unmodified = this.mAccount.getJid().getLocalpart();
308		} else {
309			unmodified = this.mAccount.getJid().toBareJid().toString();
310		}
311		return !unmodified.equals(this.mAccountJid.getText().toString()) ||
312				!this.mAccount.getPassword().equals(this.mPassword.getText().toString());
313	}
314
315	@Override
316	protected String getShareableUri() {
317		if (mAccount!=null) {
318			return mAccount.getShareableUri();
319		} else {
320			return "";
321		}
322	}
323
324	@Override
325	protected void onCreate(final Bundle savedInstanceState) {
326		super.onCreate(savedInstanceState);
327		setContentView(R.layout.activity_edit_account);
328		this.mAccountJid = (AutoCompleteTextView) findViewById(R.id.account_jid);
329		this.mAccountJid.addTextChangedListener(this.mTextWatcher);
330		this.mAccountJidLabel = (TextView) findViewById(R.id.account_jid_label);
331		if (Config.DOMAIN_LOCK != null) {
332			this.mAccountJidLabel.setText(R.string.username);
333			this.mAccountJid.setHint(R.string.username_hint);
334		}
335		this.mPassword = (EditText) findViewById(R.id.account_password);
336		this.mPassword.addTextChangedListener(this.mTextWatcher);
337		this.mPasswordConfirm = (EditText) findViewById(R.id.account_password_confirm);
338		this.mAvatar = (ImageView) findViewById(R.id.avater);
339		this.mAvatar.setOnClickListener(this.mAvatarClickListener);
340		this.mRegisterNew = (CheckBox) findViewById(R.id.account_register_new);
341		this.mStats = (LinearLayout) findViewById(R.id.stats);
342		this.mSessionEst = (TextView) findViewById(R.id.session_est);
343		this.mServerInfoRosterVersion = (TextView) findViewById(R.id.server_info_roster_version);
344		this.mServerInfoCarbons = (TextView) findViewById(R.id.server_info_carbons);
345		this.mServerInfoMam = (TextView) findViewById(R.id.server_info_mam);
346		this.mServerInfoCSI = (TextView) findViewById(R.id.server_info_csi);
347		this.mServerInfoBlocking = (TextView) findViewById(R.id.server_info_blocking);
348		this.mServerInfoSm = (TextView) findViewById(R.id.server_info_sm);
349		this.mServerInfoPep = (TextView) findViewById(R.id.server_info_pep);
350		this.mServerInfoHttpUpload = (TextView) findViewById(R.id.server_info_http_upload);
351		this.mOtrFingerprint = (TextView) findViewById(R.id.otr_fingerprint);
352		this.mOtrFingerprintBox = (RelativeLayout) findViewById(R.id.otr_fingerprint_box);
353		this.mOtrFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_to_clipboard);
354		this.mAxolotlFingerprint = (TextView) findViewById(R.id.axolotl_fingerprint);
355		this.mAxolotlFingerprintBox = (RelativeLayout) findViewById(R.id.axolotl_fingerprint_box);
356		this.mAxolotlFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_axolotl_to_clipboard);
357		this.mRegenerateAxolotlKeyButton = (ImageButton) findViewById(R.id.action_regenerate_axolotl_key);
358		this.keysCard = (LinearLayout) findViewById(R.id.other_device_keys_card);
359		this.keys = (LinearLayout) findViewById(R.id.other_device_keys);
360		this.mSaveButton = (Button) findViewById(R.id.save_button);
361		this.mCancelButton = (Button) findViewById(R.id.cancel_button);
362		this.mSaveButton.setOnClickListener(this.mSaveButtonClickListener);
363		this.mCancelButton.setOnClickListener(this.mCancelButtonClickListener);
364		this.mMoreTable = (TableLayout) findViewById(R.id.server_info_more);
365		final OnCheckedChangeListener OnCheckedShowConfirmPassword = new OnCheckedChangeListener() {
366			@Override
367			public void onCheckedChanged(final CompoundButton buttonView,
368					final boolean isChecked) {
369				if (isChecked) {
370					mPasswordConfirm.setVisibility(View.VISIBLE);
371				} else {
372					mPasswordConfirm.setVisibility(View.GONE);
373				}
374				updateSaveButton();
375			}
376		};
377		this.mRegisterNew.setOnCheckedChangeListener(OnCheckedShowConfirmPassword);
378		if (Config.DISALLOW_REGISTRATION_IN_UI) {
379			this.mRegisterNew.setVisibility(View.GONE);
380		}
381	}
382
383	@Override
384	public boolean onCreateOptionsMenu(final Menu menu) {
385		super.onCreateOptionsMenu(menu);
386		getMenuInflater().inflate(R.menu.editaccount, menu);
387		final MenuItem showQrCode = menu.findItem(R.id.action_show_qr_code);
388		final MenuItem showBlocklist = menu.findItem(R.id.action_show_block_list);
389		final MenuItem showMoreInfo = menu.findItem(R.id.action_server_info_show_more);
390		final MenuItem changePassword = menu.findItem(R.id.action_change_password_on_server);
391		final MenuItem clearDevices = menu.findItem(R.id.action_clear_devices);
392		if (mAccount != null && mAccount.isOnlineAndConnected()) {
393			if (!mAccount.getXmppConnection().getFeatures().blocking()) {
394				showBlocklist.setVisible(false);
395			}
396			if (!mAccount.getXmppConnection().getFeatures().register()) {
397				changePassword.setVisible(false);
398			}
399			Set<Integer> otherDevices = mAccount.getAxolotlService().getOwnDeviceIds();
400			if (otherDevices == null || otherDevices.isEmpty()) {
401				clearDevices.setVisible(false);
402			}
403		} else {
404			showQrCode.setVisible(false);
405			showBlocklist.setVisible(false);
406			showMoreInfo.setVisible(false);
407			changePassword.setVisible(false);
408			clearDevices.setVisible(false);
409		}
410		return true;
411	}
412
413	@Override
414	protected void onStart() {
415		super.onStart();
416		if (getIntent() != null) {
417			try {
418				this.jidToEdit = Jid.fromString(getIntent().getStringExtra("jid"));
419			} catch (final InvalidJidException | NullPointerException ignored) {
420				this.jidToEdit = null;
421			}
422			this.messageFingerprint = getIntent().getStringExtra("fingerprint");
423			if (this.jidToEdit != null) {
424				this.mRegisterNew.setVisibility(View.GONE);
425				if (getActionBar() != null) {
426					getActionBar().setTitle(getString(R.string.account_details));
427				}
428			} else {
429				this.mAvatar.setVisibility(View.GONE);
430				if (getActionBar() != null) {
431					getActionBar().setTitle(R.string.action_add_account);
432				}
433			}
434		}
435	}
436
437	@Override
438	protected void onBackendConnected() {
439		if (this.jidToEdit != null) {
440			this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit);
441			updateAccountInformation(true);
442		} else if (this.xmppConnectionService.getAccounts().size() == 0) {
443			if (getActionBar() != null) {
444				getActionBar().setDisplayHomeAsUpEnabled(false);
445				getActionBar().setDisplayShowHomeEnabled(false);
446				getActionBar().setHomeButtonEnabled(false);
447			}
448			this.mCancelButton.setEnabled(false);
449			this.mCancelButton.setTextColor(getSecondaryTextColor());
450		}
451		if (Config.DOMAIN_LOCK == null) {
452			final KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this,
453					android.R.layout.simple_list_item_1,
454					xmppConnectionService.getKnownHosts());
455			this.mAccountJid.setAdapter(mKnownHostsAdapter);
456		}
457		updateSaveButton();
458	}
459
460	@Override
461	public boolean onOptionsItemSelected(final MenuItem item) {
462		switch (item.getItemId()) {
463			case R.id.action_show_block_list:
464				final Intent showBlocklistIntent = new Intent(this, BlocklistActivity.class);
465				showBlocklistIntent.putExtra("account", mAccount.getJid().toString());
466				startActivity(showBlocklistIntent);
467				break;
468			case R.id.action_server_info_show_more:
469				mMoreTable.setVisibility(item.isChecked() ? View.GONE : View.VISIBLE);
470				item.setChecked(!item.isChecked());
471				break;
472			case R.id.action_change_password_on_server:
473				final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class);
474				changePasswordIntent.putExtra("account", mAccount.getJid().toString());
475				startActivity(changePasswordIntent);
476				break;
477			case R.id.action_clear_devices:
478				showWipePepDialog();
479				break;
480		}
481		return super.onOptionsItemSelected(item);
482	}
483
484	private void updateAccountInformation(boolean init) {
485		if (init) {
486			if (Config.DOMAIN_LOCK != null) {
487				this.mAccountJid.setText(this.mAccount.getJid().getLocalpart());
488			} else {
489				this.mAccountJid.setText(this.mAccount.getJid().toBareJid().toString());
490			}
491			this.mPassword.setText(this.mAccount.getPassword());
492		}
493		if (this.jidToEdit != null) {
494			this.mAvatar.setVisibility(View.VISIBLE);
495			this.mAvatar.setImageBitmap(avatarService().get(this.mAccount, getPixel(72)));
496		}
497		if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) {
498			this.mRegisterNew.setVisibility(View.VISIBLE);
499			this.mRegisterNew.setChecked(true);
500			this.mPasswordConfirm.setText(this.mAccount.getPassword());
501		} else {
502			this.mRegisterNew.setVisibility(View.GONE);
503			this.mRegisterNew.setChecked(false);
504		}
505		if (this.mAccount.isOnlineAndConnected() && !this.mFetchingAvatar) {
506			this.mStats.setVisibility(View.VISIBLE);
507			this.mSessionEst.setText(UIHelper.readableTimeDifferenceFull(this, this.mAccount.getXmppConnection()
508						.getLastSessionEstablished()));
509			Features features = this.mAccount.getXmppConnection().getFeatures();
510			if (features.rosterVersioning()) {
511				this.mServerInfoRosterVersion.setText(R.string.server_info_available);
512			} else {
513				this.mServerInfoRosterVersion.setText(R.string.server_info_unavailable);
514			}
515			if (features.carbons()) {
516				this.mServerInfoCarbons.setText(R.string.server_info_available);
517			} else {
518				this.mServerInfoCarbons
519					.setText(R.string.server_info_unavailable);
520			}
521			if (features.mam()) {
522				this.mServerInfoMam.setText(R.string.server_info_available);
523			} else {
524				this.mServerInfoMam.setText(R.string.server_info_unavailable);
525			}
526			if (features.csi()) {
527				this.mServerInfoCSI.setText(R.string.server_info_available);
528			} else {
529				this.mServerInfoCSI.setText(R.string.server_info_unavailable);
530			}
531			if (features.blocking()) {
532				this.mServerInfoBlocking.setText(R.string.server_info_available);
533			} else {
534				this.mServerInfoBlocking.setText(R.string.server_info_unavailable);
535			}
536			if (features.sm()) {
537				this.mServerInfoSm.setText(R.string.server_info_available);
538			} else {
539				this.mServerInfoSm.setText(R.string.server_info_unavailable);
540			}
541			if (features.pep()) {
542				AxolotlService axolotlService = this.mAccount.getAxolotlService();
543				if (axolotlService != null && axolotlService.isPepBroken()) {
544					this.mServerInfoPep.setText(R.string.server_info_broken);
545				} else {
546					this.mServerInfoPep.setText(R.string.server_info_available);
547				}
548			} else {
549				this.mServerInfoPep.setText(R.string.server_info_unavailable);
550			}
551			if (features.httpUpload()) {
552				this.mServerInfoHttpUpload.setText(R.string.server_info_available);
553			} else {
554				this.mServerInfoHttpUpload.setText(R.string.server_info_unavailable);
555			}
556			final String otrFingerprint = this.mAccount.getOtrFingerprint();
557			if (otrFingerprint != null) {
558				this.mOtrFingerprintBox.setVisibility(View.VISIBLE);
559				this.mOtrFingerprint.setText(CryptoHelper.prettifyFingerprint(otrFingerprint));
560				this.mOtrFingerprintToClipboardButton
561					.setVisibility(View.VISIBLE);
562				this.mOtrFingerprintToClipboardButton
563					.setOnClickListener(new View.OnClickListener() {
564
565						@Override
566						public void onClick(final View v) {
567
568							if (copyTextToClipboard(otrFingerprint, R.string.otr_fingerprint)) {
569								Toast.makeText(
570										EditAccountActivity.this,
571										R.string.toast_message_otr_fingerprint,
572										Toast.LENGTH_SHORT).show();
573							}
574						}
575					});
576			} else {
577				this.mOtrFingerprintBox.setVisibility(View.GONE);
578			}
579			final String axolotlFingerprint = this.mAccount.getAxolotlService().getOwnFingerprint();
580			if (axolotlFingerprint != null) {
581				this.mAxolotlFingerprintBox.setVisibility(View.VISIBLE);
582				this.mAxolotlFingerprint.setText(CryptoHelper.prettifyFingerprint(axolotlFingerprint));
583				this.mAxolotlFingerprintToClipboardButton
584						.setVisibility(View.VISIBLE);
585				this.mAxolotlFingerprintToClipboardButton
586						.setOnClickListener(new View.OnClickListener() {
587
588							@Override
589							public void onClick(final View v) {
590
591								if (copyTextToClipboard(axolotlFingerprint, R.string.omemo_fingerprint)) {
592									Toast.makeText(
593											EditAccountActivity.this,
594											R.string.toast_message_omemo_fingerprint,
595											Toast.LENGTH_SHORT).show();
596								}
597							}
598						});
599				if (Config.SHOW_REGENERATE_AXOLOTL_KEYS_BUTTON) {
600					this.mRegenerateAxolotlKeyButton
601							.setVisibility(View.VISIBLE);
602					this.mRegenerateAxolotlKeyButton
603							.setOnClickListener(new View.OnClickListener() {
604
605								@Override
606								public void onClick(final View v) {
607									showRegenerateAxolotlKeyDialog();
608								}
609							});
610				}
611			} else {
612				this.mAxolotlFingerprintBox.setVisibility(View.GONE);
613			}
614			final String ownFingerprint = mAccount.getAxolotlService().getOwnFingerprint();
615			boolean hasKeys = false;
616			keys.removeAllViews();
617			for (final String fingerprint : mAccount.getAxolotlService().getFingerprintsForOwnSessions()) {
618				if(ownFingerprint.equals(fingerprint)) {
619					continue;
620				}
621				boolean highlight = fingerprint.equals(messageFingerprint);
622				hasKeys |= addFingerprintRow(keys, mAccount, fingerprint, highlight);
623			}
624			if (hasKeys) {
625				keysCard.setVisibility(View.VISIBLE);
626			} else {
627				keysCard.setVisibility(View.GONE);
628			}
629		} else {
630			if (this.mAccount.errorStatus()) {
631				this.mAccountJid.setError(getString(this.mAccount.getStatus().getReadableId()));
632				if (init || !accountInfoEdited()) {
633					this.mAccountJid.requestFocus();
634				}
635			} else {
636				this.mAccountJid.setError(null);
637			}
638			this.mStats.setVisibility(View.GONE);
639		}
640	}
641
642	public void showRegenerateAxolotlKeyDialog() {
643		Builder builder = new Builder(this);
644		builder.setTitle("Regenerate Key");
645		builder.setIconAttribute(android.R.attr.alertDialogIcon);
646		builder.setMessage("Are you sure you want to regenerate your Identity Key? (This will also wipe all established sessions and contact Identity Keys)");
647		builder.setNegativeButton(getString(R.string.cancel), null);
648		builder.setPositiveButton("Yes",
649				new DialogInterface.OnClickListener() {
650					@Override
651					public void onClick(DialogInterface dialog, int which) {
652						mAccount.getAxolotlService().regenerateKeys();
653					}
654				});
655		builder.create().show();
656	}
657
658	public void showWipePepDialog() {
659		Builder builder = new Builder(this);
660		builder.setTitle(getString(R.string.clear_other_devices));
661		builder.setIconAttribute(android.R.attr.alertDialogIcon);
662		builder.setMessage(getString(R.string.clear_other_devices_desc));
663		builder.setNegativeButton(getString(R.string.cancel), null);
664		builder.setPositiveButton(getString(R.string.accept),
665				new DialogInterface.OnClickListener() {
666					@Override
667					public void onClick(DialogInterface dialog, int which) {
668						mAccount.getAxolotlService().wipeOtherPepDevices();
669					}
670				});
671		builder.create().show();
672	}
673
674	@Override
675	public void onKeyStatusUpdated() {
676		refreshUi();
677	}
678}