package cgeo.geocaching.settings; import cgeo.geocaching.Intents; import cgeo.geocaching.R; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.ui.dialog.Dialogs; import cgeo.geocaching.utils.AndroidRxUtils; import cgeo.geocaching.utils.BundleUtils; import cgeo.geocaching.utils.Log; import android.app.Activity; import android.app.ProgressDialog; import android.content.ActivityNotFoundException; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import java.util.concurrent.Callable; import butterknife.BindView; import io.reactivex.Observable; import io.reactivex.functions.Consumer; import org.apache.commons.lang3.StringUtils; public abstract class AbstractCredentialsAuthorizationActivity extends AbstractActivity { @NonNull private String connectorUsername = StringUtils.EMPTY; @NonNull private String connectorPassword = StringUtils.EMPTY; @BindView(R.id.check) protected Button checkButton; @BindView(R.id.register) protected Button registerButton; @BindView(R.id.auth_1) protected TextView auth1; @BindView(R.id.auth_2) protected TextView auth2; @BindView(R.id.username) protected EditText usernameEditText; @BindView(R.id.password) protected EditText passwordEditText; @Override public void onCreate(final Bundle savedInstanceState) { onCreate(savedInstanceState, R.layout.authorization_credentials_activity); final Bundle extras = getIntent().getExtras(); if (extras != null) { connectorUsername = BundleUtils.getString(extras, Intents.EXTRA_CREDENTIALS_AUTH_USERNAME, connectorUsername); connectorPassword = BundleUtils.getString(extras, Intents.EXTRA_CREDENTIALS_AUTH_PASSWORD, connectorPassword); } setTitle(getAuthTitle()); auth1.setText(getAuthExplainShort()); auth2.setText(getAuthExplainLong()); checkButton.setText(getAuthCheck()); checkButton.setOnClickListener(new CheckListener()); enableCheckButtonIfReady(); usernameEditText.setText(connectorUsername); passwordEditText.setText(connectorPassword); enableCheckButtonIfReady(); if (StringUtils.isEmpty(getCreateAccountUrl())) { registerButton.setVisibility(View.GONE); } else { registerButton.setText(getAuthRegister()); registerButton.setEnabled(true); registerButton.setOnClickListener(new RegisterListener()); } final EnableStartButtonWatcher enableStartButtonWatcher = new EnableStartButtonWatcher(); usernameEditText.addTextChangedListener(enableStartButtonWatcher); passwordEditText.addTextChangedListener(enableStartButtonWatcher); } @Override public void onNewIntent(final Intent intent) { setIntent(intent); } private void checkCredentials(final String username, final String password) { if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { ActivityMixin.showToast(this, R.string.err_missing_auth); return; } final String nam = StringUtils.defaultString(username); final String pwd = StringUtils.defaultString(password); final Credentials credentials = new Credentials(nam, pwd); final AbstractCredentialsAuthorizationActivity authorizationActivity = this; final ProgressDialog loginDialog = ProgressDialog.show(authorizationActivity, res.getString(R.string.init_login_popup), getAuthDialogWait(), true); loginDialog.setCancelable(false); AndroidRxUtils.bindActivity(authorizationActivity, Observable.defer(new Callable<Observable<StatusCode>>() { @Override public Observable<StatusCode> call() { return Observable.just(checkCredentials(credentials)); } })).subscribeOn(AndroidRxUtils.networkScheduler).subscribe(new Consumer<StatusCode>() { @Override public void accept(final StatusCode statusCode) { loginDialog.dismiss(); if (statusCode == StatusCode.NO_ERROR) { setCredentials(credentials); showToast(getAuthDialogCompleted()); setResult(RESULT_OK); finish(); } else { Dialogs.message(authorizationActivity, R.string.init_login_popup, res.getString(R.string.init_login_popup_failed_reason, statusCode.getErrorString(res)) ); checkButton.setText(getAuthCheckAgain()); checkButton.setOnClickListener(new CheckListener()); checkButton.setEnabled(true); } } }); } private class CheckListener implements View.OnClickListener { @Override public void onClick(final View view) { hideKeyboard(); checkButton.setEnabled(false); checkButton.setOnTouchListener(null); checkButton.setOnClickListener(null); final String username = usernameEditText.getText().toString(); final String password = passwordEditText.getText().toString(); checkCredentials(username, password); } } private class RegisterListener implements View.OnClickListener { @Override public void onClick(final View view) { final Activity activity = AbstractCredentialsAuthorizationActivity.this; try { activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getCreateAccountUrl()))); } catch (final ActivityNotFoundException e) { Log.e("Cannot find suitable activity", e); ActivityMixin.showToast(activity, R.string.err_application_no); } } } // get resources from derived class protected abstract String getCreateAccountUrl(); protected abstract void setCredentials(final Credentials credentials); protected abstract StatusCode checkCredentials(final Credentials credentials); protected abstract String getAuthTitle(); protected String getAuthDialogCompleted() { return res.getString(R.string.auth_dialog_completed_geokrety, getAuthTitle()); } protected String getAuthDialogWait() { return res.getString(R.string.auth_dialog_waiting, getAuthTitle()); } protected String getAuthExplainShort() { return res.getString(R.string.auth_credentials_explain_short, getAuthTitle()); } protected String getAuthExplainLong() { return res.getString(R.string.auth_credentials_explain_long, getAuthTitle()); } protected String getAuthCheck() { return res.getString(R.string.auth_check); } protected String getAuthCheckAgain() { return res.getString(R.string.auth_check_again); } protected String getAuthRegister() { return res.getString(R.string.auth_register); } /** * Enable or disable the start button depending on login/password field. * If both fields are not empty, button is enabled. * */ protected void enableCheckButtonIfReady() { checkButton.setEnabled(StringUtils.isNotEmpty(usernameEditText.getText().toString()) && StringUtils.isNotEmpty(passwordEditText.getText().toString())); } /** * A TextWatcher to monitor changes on usernameEditText and passwordEditText for enabling start button * dynamically. */ private class EnableStartButtonWatcher implements TextWatcher { @Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { // empty } @Override public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { // empty } @Override public void afterTextChanged(final Editable s) { enableCheckButtonIfReady(); } } public static class CredentialsAuthParameters { @Nullable public final String username; @Nullable public final String password; public CredentialsAuthParameters(@Nullable final String username, @Nullable final String password) { this.username = username; this.password = password; } public void setCredentialsAuthExtras(final Intent intent) { if (intent != null) { intent.putExtra(Intents.EXTRA_CREDENTIALS_AUTH_USERNAME, StringUtils.defaultIfBlank(username, StringUtils.EMPTY)); intent.putExtra(Intents.EXTRA_CREDENTIALS_AUTH_PASSWORD, StringUtils.defaultIfBlank(password, StringUtils.EMPTY)); } } } }