1package eu.siacs.conversations.ui;
2
3import android.app.PendingIntent;
4import android.content.Intent;
5import android.os.Bundle;
6import android.text.Editable;
7import android.text.TextWatcher;
8import android.view.View;
9import android.view.View.OnClickListener;
10import android.widget.AutoCompleteTextView;
11import android.widget.Button;
12import android.widget.CheckBox;
13import android.widget.CompoundButton;
14import android.widget.EditText;
15import android.widget.ImageButton;
16import android.widget.LinearLayout;
17import android.widget.CompoundButton.OnCheckedChangeListener;
18import android.widget.RelativeLayout;
19import android.widget.TextView;
20import android.widget.Toast;
21import eu.siacs.conversations.R;
22import eu.siacs.conversations.entities.Account;
23import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
24import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
25import eu.siacs.conversations.utils.UIHelper;
26import eu.siacs.conversations.utils.Validator;
27import eu.siacs.conversations.xmpp.XmppConnection.Features;
28import eu.siacs.conversations.xmpp.pep.Avatar;
29
30public class EditAccountActivity extends XmppActivity {
31
32 private AutoCompleteTextView mAccountJid;
33 private EditText mPassword;
34 private EditText mPasswordConfirm;
35 private CheckBox mRegisterNew;
36 private Button mCancelButton;
37 private Button mSaveButton;
38
39 private LinearLayout mStats;
40 private TextView mServerInfoSm;
41 private TextView mServerInfoCarbons;
42 private TextView mServerInfoPep;
43 private TextView mSessionEst;
44 private TextView mOtrFingerprint;
45 private RelativeLayout mOtrFingerprintBox;
46 private ImageButton mOtrFingerprintToClipboardButton;
47
48 private String jidToEdit;
49 private Account mAccount;
50
51 private boolean mFetchingAvatar = false;
52
53 private OnClickListener mSaveButtonClickListener = new OnClickListener() {
54
55 @Override
56 public void onClick(View v) {
57 if (mAccount != null
58 && mAccount.getStatus() == Account.STATUS_DISABLED) {
59 mAccount.setOption(Account.OPTION_DISABLED, false);
60 xmppConnectionService.updateAccount(mAccount);
61 return;
62 }
63 if (!Validator.isValidJid(mAccountJid.getText().toString())) {
64 mAccountJid.setError(getString(R.string.invalid_jid));
65 mAccountJid.requestFocus();
66 return;
67 }
68 boolean registerNewAccount = mRegisterNew.isChecked();
69 String[] jidParts = mAccountJid.getText().toString().split("@");
70 String username = jidParts[0];
71 String server;
72 if (jidParts.length >= 2) {
73 server = jidParts[1];
74 } else {
75 server = "";
76 }
77 String password = mPassword.getText().toString();
78 String passwordConfirm = mPasswordConfirm.getText().toString();
79 if (registerNewAccount) {
80 if (!password.equals(passwordConfirm)) {
81 mPasswordConfirm
82 .setError(getString(R.string.passwords_do_not_match));
83 mPasswordConfirm.requestFocus();
84 return;
85 }
86 }
87 if (mAccount != null) {
88 mAccount.setPassword(password);
89 mAccount.setUsername(username);
90 mAccount.setServer(server);
91 mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
92 xmppConnectionService.updateAccount(mAccount);
93 } else {
94 if (xmppConnectionService.findAccountByJid(mAccountJid
95 .getText().toString()) != null) {
96 mAccountJid
97 .setError(getString(R.string.account_already_exists));
98 mAccountJid.requestFocus();
99 return;
100 }
101 mAccount = new Account(username, server, password);
102 mAccount.setOption(Account.OPTION_USETLS, true);
103 mAccount.setOption(Account.OPTION_USECOMPRESSION, true);
104 mAccount.setOption(Account.OPTION_REGISTER, registerNewAccount);
105 xmppConnectionService.createAccount(mAccount);
106 }
107 if (jidToEdit != null) {
108 finish();
109 } else {
110 updateSaveButton();
111 updateAccountInformation();
112 }
113
114 }
115 };
116 private OnClickListener mCancelButtonClickListener = new OnClickListener() {
117
118 @Override
119 public void onClick(View v) {
120 finish();
121 }
122 };
123 private OnAccountUpdate mOnAccountUpdateListener = new OnAccountUpdate() {
124
125 @Override
126 public void onAccountUpdate() {
127 runOnUiThread(new Runnable() {
128
129 @Override
130 public void run() {
131 if (mAccount != null
132 && mAccount.getStatus() != Account.STATUS_ONLINE
133 && mFetchingAvatar) {
134 startActivity(new Intent(getApplicationContext(),
135 ManageAccountActivity.class));
136 finish();
137 } else if (jidToEdit == null && mAccount != null
138 && mAccount.getStatus() == Account.STATUS_ONLINE) {
139 if (!mFetchingAvatar) {
140 mFetchingAvatar = true;
141 xmppConnectionService.checkForAvatar(mAccount,
142 mAvatarFetchCallback);
143 }
144 } else {
145 updateSaveButton();
146 }
147 if (mAccount != null) {
148 updateAccountInformation();
149 }
150 }
151 });
152 }
153 };
154 private UiCallback<Avatar> mAvatarFetchCallback = new UiCallback<Avatar>() {
155
156 @Override
157 public void userInputRequried(PendingIntent pi, Avatar avatar) {
158 finishInitialSetup(avatar);
159 }
160
161 @Override
162 public void success(Avatar avatar) {
163 finishInitialSetup(avatar);
164 }
165
166 @Override
167 public void error(int errorCode, Avatar avatar) {
168 finishInitialSetup(avatar);
169 }
170 };
171 private KnownHostsAdapter mKnownHostsAdapter;
172 private TextWatcher mTextWatcher = new TextWatcher() {
173
174 @Override
175 public void onTextChanged(CharSequence s, int start, int before,
176 int count) {
177 updateSaveButton();
178 }
179
180 @Override
181 public void beforeTextChanged(CharSequence s, int start, int count,
182 int after) {
183
184 }
185
186 @Override
187 public void afterTextChanged(Editable s) {
188
189 }
190 };
191
192 protected void finishInitialSetup(final Avatar avatar) {
193 runOnUiThread(new Runnable() {
194
195 @Override
196 public void run() {
197 Intent intent;
198 if (avatar != null) {
199 intent = new Intent(getApplicationContext(),
200 StartConversationActivity.class);
201 } else {
202 intent = new Intent(getApplicationContext(),
203 PublishProfilePictureActivity.class);
204 intent.putExtra("account", mAccount.getJid());
205 intent.putExtra("setup", true);
206 }
207 startActivity(intent);
208 finish();
209 }
210 });
211 }
212
213 protected boolean inputDataDiffersFromAccount() {
214 if (mAccount == null) {
215 return true;
216 } else {
217 return (!mAccount.getJid().equals(mAccountJid.getText().toString()))
218 || (!mAccount.getPassword().equals(
219 mPassword.getText().toString()) || mAccount
220 .isOptionSet(Account.OPTION_REGISTER) != mRegisterNew
221 .isChecked());
222 }
223 }
224
225 protected void updateSaveButton() {
226 if (mAccount != null
227 && mAccount.getStatus() == Account.STATUS_CONNECTING) {
228 this.mSaveButton.setEnabled(false);
229 this.mSaveButton.setTextColor(getSecondaryTextColor());
230 this.mSaveButton.setText(R.string.account_status_connecting);
231 } else if (mAccount != null
232 && mAccount.getStatus() == Account.STATUS_DISABLED) {
233 this.mSaveButton.setEnabled(true);
234 this.mSaveButton.setTextColor(getPrimaryTextColor());
235 this.mSaveButton.setText(R.string.enable);
236 } else {
237 this.mSaveButton.setEnabled(true);
238 this.mSaveButton.setTextColor(getPrimaryTextColor());
239 if (jidToEdit != null) {
240 if (mAccount != null
241 && mAccount.getStatus() == Account.STATUS_ONLINE) {
242 this.mSaveButton.setText(R.string.save);
243 if (!accountInfoEdited()) {
244 this.mSaveButton.setEnabled(false);
245 this.mSaveButton.setTextColor(getSecondaryTextColor());
246 }
247 } else {
248 this.mSaveButton.setText(R.string.connect);
249 }
250 } else {
251 this.mSaveButton.setText(R.string.next);
252 }
253 }
254 }
255
256 protected boolean accountInfoEdited() {
257 return (!this.mAccount.getJid().equals(
258 this.mAccountJid.getText().toString()))
259 || (!this.mAccount.getPassword().equals(
260 this.mPassword.getText().toString()));
261 }
262
263 @Override
264 protected void onCreate(Bundle savedInstanceState) {
265 super.onCreate(savedInstanceState);
266 setContentView(R.layout.activity_edit_account);
267 this.mAccountJid = (AutoCompleteTextView) findViewById(R.id.account_jid);
268 this.mAccountJid.addTextChangedListener(this.mTextWatcher);
269 this.mPassword = (EditText) findViewById(R.id.account_password);
270 this.mPassword.addTextChangedListener(this.mTextWatcher);
271 this.mPasswordConfirm = (EditText) findViewById(R.id.account_password_confirm);
272 this.mRegisterNew = (CheckBox) findViewById(R.id.account_register_new);
273 this.mStats = (LinearLayout) findViewById(R.id.stats);
274 this.mSessionEst = (TextView) findViewById(R.id.session_est);
275 this.mServerInfoCarbons = (TextView) findViewById(R.id.server_info_carbons);
276 this.mServerInfoSm = (TextView) findViewById(R.id.server_info_sm);
277 this.mServerInfoPep = (TextView) findViewById(R.id.server_info_pep);
278 this.mOtrFingerprint = (TextView) findViewById(R.id.otr_fingerprint);
279 this.mOtrFingerprintBox = (RelativeLayout) findViewById(R.id.otr_fingerprint_box);
280 this.mOtrFingerprintToClipboardButton = (ImageButton) findViewById(R.id.action_copy_to_clipboard);
281 this.mSaveButton = (Button) findViewById(R.id.save_button);
282 this.mCancelButton = (Button) findViewById(R.id.cancel_button);
283 this.mSaveButton.setOnClickListener(this.mSaveButtonClickListener);
284 this.mCancelButton.setOnClickListener(this.mCancelButtonClickListener);
285 this.mRegisterNew
286 .setOnCheckedChangeListener(new OnCheckedChangeListener() {
287
288 @Override
289 public void onCheckedChanged(CompoundButton buttonView,
290 boolean isChecked) {
291 if (isChecked) {
292 mPasswordConfirm.setVisibility(View.VISIBLE);
293 } else {
294 mPasswordConfirm.setVisibility(View.GONE);
295 }
296 updateSaveButton();
297 }
298 });
299 }
300
301 @Override
302 protected void onStart() {
303 super.onStart();
304 if (getIntent() != null) {
305 this.jidToEdit = getIntent().getStringExtra("jid");
306 if (this.jidToEdit != null) {
307 this.mRegisterNew.setVisibility(View.GONE);
308 getActionBar().setTitle(jidToEdit);
309 } else {
310 getActionBar().setTitle(R.string.action_add_account);
311 }
312 }
313 }
314
315 @Override
316 protected void onStop() {
317 if (xmppConnectionServiceBound) {
318 xmppConnectionService.removeOnAccountListChangedListener();
319 }
320 super.onStop();
321 }
322
323 @Override
324 protected void onBackendConnected() {
325 this.mKnownHostsAdapter = new KnownHostsAdapter(this,
326 android.R.layout.simple_list_item_1,
327 xmppConnectionService.getKnownHosts());
328 this.xmppConnectionService
329 .setOnAccountListChangedListener(this.mOnAccountUpdateListener);
330 if (this.jidToEdit != null) {
331 this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit);
332 updateAccountInformation();
333 } else if (this.xmppConnectionService.getAccounts().size() == 0) {
334 getActionBar().setDisplayHomeAsUpEnabled(false);
335 getActionBar().setDisplayShowHomeEnabled(false);
336 this.mCancelButton.setEnabled(false);
337 this.mCancelButton.setTextColor(getSecondaryTextColor());
338 }
339 this.mAccountJid.setAdapter(this.mKnownHostsAdapter);
340 updateSaveButton();
341 }
342
343 private void updateAccountInformation() {
344 this.mAccountJid.setText(this.mAccount.getJid());
345 this.mPassword.setText(this.mAccount.getPassword());
346 if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) {
347 this.mRegisterNew.setVisibility(View.VISIBLE);
348 this.mRegisterNew.setChecked(true);
349 this.mPasswordConfirm.setText(this.mAccount.getPassword());
350 } else {
351 this.mRegisterNew.setVisibility(View.GONE);
352 this.mRegisterNew.setChecked(false);
353 }
354 if (this.mAccount.getStatus() == Account.STATUS_ONLINE
355 && !this.mFetchingAvatar) {
356 this.mStats.setVisibility(View.VISIBLE);
357 this.mSessionEst.setText(UIHelper.readableTimeDifference(
358 getApplicationContext(), this.mAccount.getXmppConnection()
359 .getLastSessionEstablished()));
360 Features features = this.mAccount.getXmppConnection().getFeatures();
361 if (features.carbons()) {
362 this.mServerInfoCarbons.setText(R.string.server_info_available);
363 } else {
364 this.mServerInfoCarbons
365 .setText(R.string.server_info_unavailable);
366 }
367 if (features.sm()) {
368 this.mServerInfoSm.setText(R.string.server_info_available);
369 } else {
370 this.mServerInfoSm.setText(R.string.server_info_unavailable);
371 }
372 if (features.pubsub()) {
373 this.mServerInfoPep.setText(R.string.server_info_available);
374 } else {
375 this.mServerInfoPep.setText(R.string.server_info_unavailable);
376 }
377 final String fingerprint = this.mAccount
378 .getOtrFingerprint(xmppConnectionService);
379 if (fingerprint != null) {
380 this.mOtrFingerprintBox.setVisibility(View.VISIBLE);
381 this.mOtrFingerprint.setText(fingerprint);
382 this.mOtrFingerprintToClipboardButton
383 .setVisibility(View.VISIBLE);
384 this.mOtrFingerprintToClipboardButton
385 .setOnClickListener(new View.OnClickListener() {
386
387 @Override
388 public void onClick(View v) {
389
390 if (copyTextToClipboard(fingerprint,R.string.otr_fingerprint)) {
391 Toast.makeText(
392 EditAccountActivity.this,
393 R.string.toast_message_otr_fingerprint,
394 Toast.LENGTH_SHORT).show();
395 }
396 }
397 });
398 } else {
399 this.mOtrFingerprintBox.setVisibility(View.GONE);
400 }
401 } else {
402 if (this.mAccount.errorStatus()) {
403 this.mAccountJid.setError(getString(this.mAccount
404 .getReadableStatusId()));
405 this.mAccountJid.requestFocus();
406 }
407 this.mStats.setVisibility(View.GONE);
408 }
409 }
410}