<commit_before>package fi.bitrite.android.ws.ui;

import android.accounts.Account;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import fi.bitrite.android.ws.R;
import fi.bitrite.android.ws.auth.AccountManager;
import fi.bitrite.android.ws.auth.AuthToken;
import fi.bitrite.android.ws.di.Injectable;
import fi.bitrite.android.ws.ui.util.ProgressDialog;
import fi.bitrite.android.ws.ui.view.AccountAuthenticatorFragmentActivity;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.BehaviorSubject;

/**
 * The activity responsible for getting Warmshowers credentials from the user,
 * verifying them against the Warmshowers web service and storing
 * them on the device using Android's custom account facilities.
 */
public class AuthenticatorActivity extends AccountAuthenticatorFragmentActivity
        implements Injectable {

    @Inject AccountManager mAuthenticationManager;

    @BindView(R.id.auth_txt_username) EditText mTxtUsername;
    @BindView(R.id.auth_txt_password) EditText mTxtPassword;
    @BindView(R.id.auth_btn_login) Button mBtnLogin;

    private final TextWatcher mTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            setLoginButtonEnabled(areAllInputsNotEmpty());
        }
    };

    private Disposable mProgressDisposable;

    private Disposable mResumePauseDisposable;
    private BehaviorSubject<LoginResult> mLoginResult = BehaviorSubject.create();

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_authentication);
        ButterKnife.bind(this);

        // Deactivates login button to prevent requests from being made with incomplete login data
        setLoginButtonEnabled(areAllInputsNotEmpty());
        mTxtUsername.addTextChangedListener(mTextWatcher);
        mTxtPassword.addTextChangedListener(mTextWatcher);

        // If we do a re-login (to obtain a new auth token), the username is provided by the caller.
        String providedUsername =
                getIntent().getStringExtra(android.accounts.AccountManager.KEY_ACCOUNT_NAME);
        if (!TextUtils.isEmpty(providedUsername)) {
            mTxtUsername.setText(providedUsername);
            disableEditText(mTxtUsername);

            // The username is set -> we set the focus on the password field.
            mTxtPassword.requestFocus();
        }

        // Shows the keyboard
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // We only listen to login results as long as the app is in the foreground. If it was in the
        // background when the result appeared we catch up on taking care of it as the very next
        // thing.
        mResumePauseDisposable = mLoginResult
                .filter(result -> !result.isHandled)
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(result -> {
                    result.isHandled = true;

                    if (result.throwable != null) {
                        mProgressDisposable.dispose();
                        Toast.makeText(this, R.string.http_server_access_failure, Toast.LENGTH_LONG)
                                .show();
                    } else if (result.response != null) {
                        // The following we add for usage in MainActivity::onActivityResult().
                        Intent intent = new Intent();
                        intent.putExtras(result.response);
                        setResult(0, intent);
                        setAccountAuthenticatorResult(result.response);
                        finish();
                    } else {
                        mProgressDisposable.dispose();
                        Toast.makeText(this, R.string.authentication_failed, Toast.LENGTH_LONG)
                                .show();
                    }
                });
    }

    @Override
    protected void onPause() {
        mResumePauseDisposable.dispose();
        super.onPause();
    }

    /**
     * Changes the enabled state of the login button<commit_msg>Fix toast not being created on the main thread<commit_after>package fi.bitrite.android.ws.ui;

import android.accounts.Account;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import fi.bitrite.android.ws.R;
import fi.bitrite.android.ws.auth.AccountManager;
import fi.bitrite.android.ws.auth.AuthToken;
import fi.bitrite.android.ws.di.Injectable;
import fi.bitrite.android.ws.ui.util.ProgressDialog;
import fi.bitrite.android.ws.ui.view.AccountAuthenticatorFragmentActivity;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.BehaviorSubject;

/**
 * The activity responsible for getting Warmshowers credentials from the user,
 * verifying them against the Warmshowers web service and storing
 * them on the device using Android's custom account facilities.
 */
public class AuthenticatorActivity extends AccountAuthenticatorFragmentActivity
        implements Injectable {

    @Inject AccountManager mAuthenticationManager;

    @BindView(R.id.auth_txt_username) EditText mTxtUsername;
    @BindView(R.id.auth_txt_password) EditText mTxtPassword;
    @BindView(R.id.auth_btn_login) Button mBtnLogin;

    private final TextWatcher mTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            setLoginButtonEnabled(areAllInputsNotEmpty());
        }
    };

    private Disposable mProgressDisposable;

    private Disposable mResumePauseDisposable;
    private BehaviorSubject<LoginResult> mLoginResult = BehaviorSubject.create();

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_authentication);
        ButterKnife.bind(this);

        // Deactivates login button to prevent requests from being made with incomplete login data
        setLoginButtonEnabled(areAllInputsNotEmpty());
        mTxtUsername.addTextChangedListener(mTextWatcher);
        mTxtPassword.addTextChangedListener(mTextWatcher);

        // If we do a re-login (to obtain a new auth token), the username is provided by the caller.
        String providedUsername =
                getIntent().getStringExtra(android.accounts.AccountManager.KEY_ACCOUNT_NAME);
        if (!TextUtils.isEmpty(providedUsername)) {
            mTxtUsername.setText(providedUsername);
            disableEditText(mTxtUsername);

            // The username is set -> we set the focus on the password field.
            mTxtPassword.requestFocus();
        }

        // Shows the keyboard
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // We only listen to login results as long as the app is in the foreground. If it was in the
        // background when the result appeared we catch up on taking care of it as the very next
        // thing.
        mResumePauseDisposable = mLoginResult
                .filter(result -> !result.isHandled)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(result -> {
                    result.isHandled = true;

                    if (result.throwable != null) {
                        mProgressDisposable.dispose();
                        Toast.makeText(this, R.string.http_server_access_failure, Toast.LENGTH_LONG)
                                .show();
                    } else if (result.response != null) {
                        // The following we add for usage in MainActivity::onActivityResult().
                        Intent intent = new Intent();
                        intent.putExtras(result.response);
                        setResult(0, intent);
                        setAccountAuthenticatorResult(result.response);
                        finish();
                    } else {
                        mProgressDisposable.dispose();
                        Toast.makeText(this, R.string.authentication_failed, Toast.LENGTH_LONG)
                                .show();
                    }
                });
    }

    @Override
    protected void onPause() {
        mResumePauseDisposable.dispose();
        super.onPause();
    }

    /**
     * Changes the enabled state of the login button
{'fraction_non_alphanumeric': 0.0798014888337469, 'fraction_numerical': 0.0009925558312655087, 'mean_word_length': 2.5616825733474724, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1793519', 'n_tokens_mistral': 2702, 'n_tokens_neox': 2585, 'n_words': 633}