Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Droneshare login field validation and keyboard release #1422

Merged
merged 4 commits into from
Mar 4, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.util.Pair;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
Expand All @@ -24,7 +28,7 @@
public class DroneshareLoginFragment extends Fragment {

private static final String DRONESHARE_PROMPT_ACTION = "droneshare_prompt";

private static final short DRONESHARE_MIN_PASSWORD = 7;
private final DroneshareClient dshareClient = new DroneshareClient();
private DroidPlannerPrefs prefs;

Expand Down Expand Up @@ -75,9 +79,15 @@ public void onViewCreated(View root, Bundle savedInstanceState) {
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String usernameText = username.getText().toString();
final String passwordText = password.getText().toString();
new AsyncConnect(false).execute(usernameText, passwordText);
// Validate required fields
if (validateField(username) && validateField(password)) {
final String usernameText = username.getText().toString();
final String passwordText = password.getText().toString();

// Hide the soft keyboard, otherwise can remain after logging in.
hideSoftInput();
new AsyncConnect(false).execute(usernameText, passwordText);
}
}
});

Expand All @@ -96,10 +106,17 @@ public void onClick(View v) {
signupButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String usernameText = username.getText().toString();
final String passwordText = password.getText().toString();
final String emailText = email.getText().toString();
new AsyncConnect(true).execute(usernameText, passwordText, emailText);
// If we have all required fields...
if (validateField(username) && validateField(password) && validateField(email)) {
final String usernameText = username.getText().toString();
final String passwordText = password.getText().toString();
final String emailText = email.getText().toString();

// Hide the soft keyboard, otherwise can remain after logging in.
hideSoftInput();

new AsyncConnect(true).execute(usernameText, passwordText, emailText);
}
}
});

Expand All @@ -116,6 +133,42 @@ public void onClick(View v) {
password.setText(prefs.getDronesharePassword());
email.setText(prefs.getDroneshareEmail());

// Field validation - we need to add these after the fields have been set
// otherwise validation will fail on empty fields (ugly).
username.addTextChangedListener(new TextValidator(username) {
@Override public void validate(TextView textView, String text) {
// TODO: validate on acceptable characters, etc
if(text.length() == 0)
textView.setError("Please enter a username");
else
textView.setError(null);
}
});

password.addTextChangedListener(new TextValidator(password) {
@Override public void validate(TextView textView, String text) {
if(loginSection.getVisibility() == View.VISIBLE && (
text.length() < 1))
// Since some accounts have been created with < 7 and no digits, allow login
textView.setError("Please enter a password");
else if(loginSection.getVisibility() == View.GONE && (
text.length() < DRONESHARE_MIN_PASSWORD || !text.matches(".*\\d+.*")))
// New accounts require at least 7 characters and digit
textView.setError("Use at least 7 characters and one digit");
else
textView.setError(null);
}
});

email.addTextChangedListener(new TextValidator(email) {
@Override public void validate(TextView textView, String text) {
if(text.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(text).matches())
textView.setError("Please enter a valid email");
else
textView.setError(null);
}
});

// Save to prefs on save
// builder.setView(root)
// // Add action buttons
Expand Down Expand Up @@ -159,6 +212,50 @@ public void onClick(View v) {
// GAUtils.sendEvent(eventBuilder);
// }

private void hideSoftInput() {
// Hide the soft keyboard and unfocus any active inputs.
final Activity activity = getActivity();
View view = activity.getCurrentFocus();
if (view != null) {
final InputMethodManager inputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputManager != null)
inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}

private Boolean validateField(EditText field) {
// Trigger text changed to see if we have any errors:
field.setText(field.getText());
if (field.getError() != null) {
return false; // Invalid, the text field will display an error
} else {
return true; // Valid
}
}

private static abstract class TextValidator implements TextWatcher {
// Wrapper for TextWatcher, providing a shorthand method of field specific validations
private final TextView textView;

public TextValidator(TextView textView) {
this.textView = textView;
}

public abstract void validate(TextView textView, String text);

@Override
final public void afterTextChanged(Editable s) {
String text = textView.getText().toString();
validate(textView, text);
}

@Override
final public void beforeTextChanged(CharSequence s, int start, int count, int after) { /* Don't care */ }

@Override
final public void onTextChanged(CharSequence s, int start, int before, int count) { /* Don't care */ }
}

private class AsyncConnect extends AsyncTask<String, Void, Pair<Boolean, String>> {

private final boolean isSignup;
Expand Down