diff --git a/app/src/main/java/edu/sc/snacktrack/login/NewAccountFragment.java b/app/src/main/java/edu/sc/snacktrack/login/NewAccountFragment.java index 2d338b9..080217c 100644 --- a/app/src/main/java/edu/sc/snacktrack/login/NewAccountFragment.java +++ b/app/src/main/java/edu/sc/snacktrack/login/NewAccountFragment.java @@ -8,6 +8,7 @@ import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.text.Editable; +import android.text.Html; import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; @@ -45,7 +46,8 @@ public class NewAccountFragment extends Fragment { private EditText passwordConfirmET; private TextView usernameErrorStatus; - private TextView passwordErrorStatus; + private TextView passwordMatchStatus; + private TextView passwordRequirementStatus; private RadioGroup rGroup; @@ -61,6 +63,8 @@ public class NewAccountFragment extends Fragment { private boolean loggingIn; + private static final PasswordChecker passwordChecker = new PasswordChecker(); + @Override public void onAttach(Context context) { super.onAttach(context); @@ -87,7 +91,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa passwordET = (EditText) view.findViewById(R.id.passwordEditText); passwordConfirmET = (EditText) view.findViewById(R.id.passwordConfirmEditText); usernameErrorStatus = (TextView) view.findViewById(R.id.usernameErrorStatus); - passwordErrorStatus = (TextView) view.findViewById(R.id.passwordErrorStatus); + passwordMatchStatus = (TextView) view.findViewById(R.id.passwordMatchStatus); + passwordRequirementStatus = (TextView) view.findViewById(R.id.passwordReqTextView); signUpButton = (Button) view.findViewById(R.id.signUpButton); rGroup = (RadioGroup) view.findViewById(R.id.signUpRadioGroup); existingAccountButton = (Button) view.findViewById(R.id.existingAccountButton); @@ -142,82 +147,75 @@ private void attemptSignup(){ setWidgetsEnabled(false); loggingIn = true; + final ParseUser newUser = new ParseUser(); + String username = usernameET.getText().toString(); String password = passwordET.getText().toString(); String passwordConfirm = passwordConfirmET.getText().toString(); StringBuilder usernameInvalidReason = new StringBuilder(); - StringBuilder passwordInvalidReason = new StringBuilder(); + StringBuilder passwordMatchReason = new StringBuilder(); StringBuilder selectionInvalidReason = new StringBuilder(); - // First check if the username is valid - if(isUsernameValid(username, usernameInvalidReason)){ - - // Next, check if the passwords are valid. - if(isPasswordValid(password, passwordConfirm, passwordInvalidReason)){ - - // Finally, check if a radio button was selected - if(isSelected(selectionInvalidReason)) { - final ParseUser newUser = new ParseUser(); - newUser.setUsername(username); - newUser.setPassword(password); - - String sel = isDietitian(); + if(!isUsernameValid(username, usernameInvalidReason)){ + updateToast(usernameInvalidReason.toString(), Toast.LENGTH_LONG); + setWidgetsEnabled(true); + loggingIn = false; + return; + } + if(!doPasswordsMatch(password, passwordConfirm, passwordMatchReason)){ + updateToast(passwordMatchReason.toString(), Toast.LENGTH_LONG); + setWidgetsEnabled(true); + loggingIn = false; + return; + } + if(!passwordChecker.meetsRequirements(password)){ + updateToast("Password does not meet requirements", Toast.LENGTH_LONG); + setWidgetsEnabled(true); + loggingIn = false; + return; + } + if(!isSelected(selectionInvalidReason)){ + updateToast(selectionInvalidReason.toString(), Toast.LENGTH_LONG); + setWidgetsEnabled(true); + loggingIn = false; + return; + } - if(sel.equals("true")) - newUser.put("isDietitian", true); + // If this line is reached, the provided credentials are valid, so we attempt sign up. + newUser.setUsername(username); + newUser.setPassword(password); - else - newUser.put("isDietitian", false); + String sel = isDietitian(); + if(sel.equals("true")) + newUser.put("isDietitian", true); + else + newUser.put("isDietitian", false); - newUser.signUpInBackground(new SignUpCallback() { + newUser.signUpInBackground(new SignUpCallback() { + @Override + public void done(ParseException e) { + if (e == null) { + // Sign up was successful + ParseRole role = new ParseRole("role_" + newUser.getObjectId()); + role.setACL(new ParseACL(newUser)); + role.saveInBackground(new SaveCallback() { @Override public void done(ParseException e) { - if (e == null) { - // Sign up was successful - ParseRole role = new ParseRole("role_" + newUser.getObjectId()); - role.setACL(new ParseACL(newUser)); - role.saveInBackground(new SaveCallback() { - @Override - public void done(ParseException e) { - if(e == null){ - startMainActivity(); - } else{ - updateToast(Utils.getErrorMessage(e), Toast.LENGTH_SHORT); - } - } - }); - } else { + if(e == null){ + startMainActivity(); + } else{ updateToast(Utils.getErrorMessage(e), Toast.LENGTH_SHORT); } - setWidgetsEnabled(true); - loggingIn = false; } }); + } else { + updateToast(Utils.getErrorMessage(e), Toast.LENGTH_SHORT); } - - // If no radio buttons are selected, display the reason to the user. - else { - updateToast(selectionInvalidReason.toString(), Toast.LENGTH_LONG); - setWidgetsEnabled(true); - loggingIn = false; - } - } - - // If the passwords are invalid, display the reason to the user. - else{ - updateToast(passwordInvalidReason.toString(), Toast.LENGTH_LONG); setWidgetsEnabled(true); loggingIn = false; } - } - - // If the username is invalid, display the reason to the user - else{ - updateToast(usernameInvalidReason.toString(), Toast.LENGTH_LONG); - setWidgetsEnabled(true); - loggingIn = false; - } + }); } /** @@ -341,18 +339,16 @@ private boolean isUsernameValid(String username, @Nullable StringBuilder reason) } /** - * Checks if passwords are valid. - * - * Currently this method only checks if the passwords match or if either is blank. + * Checks if a password and its confirmation match * * @param password The password * @param passwordConfirm The confirmed password - * @param reason When not null, this method will append the reason the password is invalid - * (or "OK" if the username is valid). - * @return true if the passwords are valid. false otherwise. + * @param reason When not null, this method will append the reason the passwords do not match + * (or "OK" if they do). + * @return true if the passwords match. false otherwise. */ - private boolean isPasswordValid(String password, String passwordConfirm, - @Nullable StringBuilder reason){ + private boolean doPasswordsMatch(String password, String passwordConfirm, + @Nullable StringBuilder reason){ if(password.equals("")){ if(reason != null){ reason.append("Password is blank"); @@ -411,21 +407,51 @@ private String isDietitian() { } /** - * Updates the passwordErrorStatus based on a reason returned by isPasswordValid(). + * Updates the password error status. That is, displays to the user whether or not the passwords + * match and if the password meets the strength requirements. */ private void updatePasswordErrorStatus(String password, String passwordConfirm){ - StringBuilder reason = new StringBuilder(); - String reasonString; - isPasswordValid(password, passwordConfirm, reason); - reasonString = reason.toString(); - - if(reasonString.equalsIgnoreCase("OK")){ - passwordErrorStatus.setTextColor(Color.BLACK); - passwordErrorStatus.setText(reasonString); + StringBuilder matchProblem = new StringBuilder(); + if(doPasswordsMatch(password, passwordConfirm, matchProblem)){ + passwordMatchStatus.setTextColor(Color.parseColor("#006600")); + passwordMatchStatus.setText("Passwords match"); } else{ - passwordErrorStatus.setTextColor(Color.RED); - passwordErrorStatus.setText(reasonString); + passwordMatchStatus.setTextColor(Color.RED); + passwordMatchStatus.setText(matchProblem.toString()); } + + PasswordChecker.CheckResult checkResult = PasswordChecker.checkPassword(password); + + // Color each of the requirements red (requirement not satisfied) or green (requirement + // satisfied). + passwordRequirementStatus.setText(Html.fromHtml(new StringBuilder() + .append(checkResult.hasMixedCase() && checkResult.hasNumbers() + && checkResult.length() >= passwordChecker.getMinimumLength() ? + "Your password must: " : + "Your password must: " + ) + .append(checkResult.hasMixedCase() && checkResult.hasNumbers() ? + "use " : + "use " + ) + .append(checkResult.hasLowerCase() ? + "a lowercase letter, " : + "a lowercase letter, " + ) + .append(checkResult.hasUpperCase() ? + "an uppercase letter, " : + "an uppercase letter, " + ) + .append(checkResult.hasNumbers() ? + "a number, " : + "a number, " + ) + .append(checkResult.length() >= passwordChecker.getMinimumLength() ? + "and have at least 8 characters." : + "and have at least 8 characters." + ) + .toString() + )); } /** diff --git a/app/src/main/java/edu/sc/snacktrack/login/PasswordChecker.java b/app/src/main/java/edu/sc/snacktrack/login/PasswordChecker.java new file mode 100644 index 0000000..7685e02 --- /dev/null +++ b/app/src/main/java/edu/sc/snacktrack/login/PasswordChecker.java @@ -0,0 +1,168 @@ +package edu.sc.snacktrack.login; + +/** + * This class is a tool for checking the strength of passwords. A PasswordChecker holds the + * requirements of a password and can check which of those requirements a password meets. + */ +public class PasswordChecker { + + public static final int DEFAULT_MINIMUM_LENGTH = 8; + public static final boolean DEFAULT_REQUIRE_LOWERCASE = true; + public static final boolean DEFAULT_REQUIRE_UPPERCASE = true; + public static final boolean DEFAULT_REQUIRE_NUMBERS = true; + public static final boolean DEFAULT_REQUIRE_SPECIAL_CHARS = false; + + private static final String numbers = "0123456789"; + private static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + private int minimumLength; + private boolean requireLowercase; + private boolean requireUppercase; + private boolean requireNumbers; + private boolean requireSpecial; + + /** + * Create a new password checker using the default values. + */ + public PasswordChecker(){ + minimumLength = DEFAULT_MINIMUM_LENGTH; + requireLowercase = DEFAULT_REQUIRE_LOWERCASE; + requireUppercase = DEFAULT_REQUIRE_UPPERCASE; + requireNumbers = DEFAULT_REQUIRE_NUMBERS; + requireSpecial = DEFAULT_REQUIRE_SPECIAL_CHARS; + } + + // Standard getters and setters + public int getMinimumLength() { + return minimumLength; + } + public void setMinimumLength(int minimumLength) { + this.minimumLength = minimumLength; + } + public boolean isRequireSpecial() { + return requireSpecial; + } + public void setRequireSpecial(boolean requireSpecial) { + this.requireSpecial = requireSpecial; + } + public boolean isRequireNumbers() { + return requireNumbers; + } + public void setRequireNumbers(boolean requireNumbers) { + this.requireNumbers = requireNumbers; + } + public boolean isRequireUppercase() { + return requireUppercase; + } + public void setRequireUppercase(boolean requireUppercase) { + this.requireUppercase = requireUppercase; + } + public boolean isRequireLowercase() { + return requireLowercase; + } + public void setRequireLowercase(boolean requireLowercase) { + this.requireLowercase = requireLowercase; + } + + /** + * Parses a password string and populates the fields specified in PasswordChecker.CheckResult. + * + * @param password The password to check + * @return The CheckResult + */ + public static CheckResult checkPassword(String password){ + CheckResult result = new CheckResult(); + + String passwordLowercase = password.toLowerCase(); + String passwordUppercase = password.toUpperCase(); + + result.length = password.length(); + result.hasLowerCase = !password.equals(passwordUppercase); + result.hasUpperCase = !password.equals(passwordLowercase); + + for(char c1 : passwordUppercase.toCharArray()){ + String str = Character.toString(c1); + if(alphabet.contains(str)){ + result.hasLetters = true; + } else if(numbers.contains(str)){ + result.hasNumbers = true; + } else{ + result.hasSpecialCharacters = true; + } + + // Break if all characters of interest have been found + if(result.hasLetters && result.hasSpecialCharacters && result.hasNumbers){ + break; + } + } + + return result; + } + + /** + * Checks if a password meets the requirements of this password checker. + * + * @param password The password to check + * @return true if the password meets requirements. false otherwise. + */ + public boolean meetsRequirements(String password){ + CheckResult checkResult = checkPassword(password); + if(checkResult.length() < minimumLength){ + return false; + } else if(requireLowercase && !checkResult.hasLowerCase()){ + return false; + } else if(requireUppercase && !checkResult.hasUpperCase()){ + return false; + } else if(requireNumbers && !checkResult.hasNumbers()){ + return false; + } else if(requireSpecial && !checkResult.hasSpecialCharacters()){ + return false; + } else{ + return true; + } + } + + /** + * This class holds the results of checking the strength of a password. + */ + public static class CheckResult{ + + private boolean hasLowerCase; + private boolean hasUpperCase; + private boolean hasLetters; + private boolean hasNumbers; + private boolean hasSpecialCharacters; + private int length; + + public CheckResult(){ + hasLowerCase = false; + hasUpperCase = false; + hasNumbers = false; + hasSpecialCharacters = false; + length = 0; + } + + // Standard getters + public boolean hasLowerCase(){ + return hasLetters && hasLowerCase; + } + public boolean hasUpperCase(){ + return hasLetters && hasUpperCase; + } + public boolean hasMixedCase(){ + return hasUpperCase() && hasLowerCase(); + } + public boolean hasLetters() { + return hasLetters; + } + public boolean hasNumbers(){ + return hasNumbers; + } + public boolean hasSpecialCharacters(){ + return hasSpecialCharacters; + } + public int length(){ + return length; + } + } +} diff --git a/app/src/main/java/edu/sc/snacktrack/main/settings/ChangePasswordDialog.java b/app/src/main/java/edu/sc/snacktrack/main/settings/ChangePasswordDialog.java index 078fdd6..51ed1cf 100644 --- a/app/src/main/java/edu/sc/snacktrack/main/settings/ChangePasswordDialog.java +++ b/app/src/main/java/edu/sc/snacktrack/main/settings/ChangePasswordDialog.java @@ -8,6 +8,10 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; +import android.text.Editable; +import android.text.Html; +import android.text.TextWatcher; +import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -27,16 +31,21 @@ import edu.sc.snacktrack.login.LoginActivity; import edu.sc.snacktrack.R; +import edu.sc.snacktrack.login.PasswordChecker; import edu.sc.snacktrack.utils.Utils; public class ChangePasswordDialog extends DialogFragment { private EditText passwordText; private EditText passwordConfirmText; + private TextView passwordMatchStatus; + private TextView passwordReqStatus; private Button submitButton; private Button cancelButton; public Context cont; + private static final PasswordChecker passwordChecker = new PasswordChecker(); + public ChangePasswordDialog() { //Empty constructor required } @@ -47,9 +56,59 @@ public void onAttach(Context context) { cont = context; } + /** + * Enables or disables all user input widgets. + * + * @param enabled true to enable; false to disable + */ private void setWidgetsEnabled(boolean enabled){ submitButton.setEnabled(enabled); cancelButton.setEnabled(enabled); + passwordText.setEnabled(enabled); + passwordConfirmText.setEnabled(enabled); + } + + /** + * Sets the text watchers for each of the EditTexts + */ + private void setTextWatchers(){ + passwordText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + String password = passwordText.getText().toString(); + String passwordConfirm = passwordConfirmText.getText().toString(); + updatePasswordErrorStatus(password, passwordConfirm); + } + }); + + passwordConfirmText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + String password = passwordText.getText().toString(); + String passwordConfirm = passwordConfirmText.getText().toString(); + updatePasswordErrorStatus(password, passwordConfirm); + } + }); } @Override @@ -60,9 +119,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa passwordText = (EditText) view.findViewById(R.id.password); passwordConfirmText = (EditText) view.findViewById(R.id.confirmPassword); + passwordMatchStatus = (TextView) view.findViewById(R.id.passwordMatchStatus); + passwordReqStatus = (TextView) view.findViewById(R.id.passwordReqTextView); submitButton = (Button) view.findViewById(R.id.new_password_submit); cancelButton = (Button) view.findViewById(R.id.new_password_cancel); + setTextWatchers(); + submitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -77,111 +140,20 @@ public void onClick(View v) { } }); -//// final TextView tipText = (TextView) view.findViewById(R.id.password_tip); -//// headerText = (TextView) view.findViewById(R.id.password_dialog); -//// passwordText = (EditText) view.findViewById(R.id.new_password); -// submitButton = (Button) view.findViewById(R.id.new_password_submit); -// cancelButton = (Button) view.findViewById(R.id.new_password_cancel); -// -// submitButton.setEnabled(false); -// submitButton.setTextColor(Color.parseColor("#FF6666")); -//// tipText.setVisibility(View.GONE); -//// tipText.setTextColor(Color.parseColor("#FFFFFF")); -// -// passwordText.setOnTouchListener(new View.OnTouchListener() { -// @Override -// public boolean onTouch(View v, MotionEvent event) { -// v.setFocusable(true); -// v.setFocusableInTouchMode(true); -// return false; -// } -// }); -// -// passwordText.setOnEditorActionListener(new TextView.OnEditorActionListener() { -// @Override -// public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { -// -// if (actionId == EditorInfo.IME_ACTION_DONE) -// { -// passwordText.setFocusable(false); -// -// if (passwordText.getText().length() != 0) -// { -// submitButton.setEnabled(true); -// submitButton.setTextColor(Color.parseColor("#4DFF4D")); -//// tipText.setVisibility(View.GONE); -// headerText.setPadding(20,20,20,0); -// } -// -// else -// { -// -// submitButton.setEnabled(false); -// headerText.setPadding(20,20,20,10); -//// tipText.setVisibility(View.VISIBLE); -// -// ValueAnimator anim = new ValueAnimator(); -// anim.setIntValues(Color.parseColor("#FFFFFF"), Color.parseColor("#FF6666")); -// anim.setEvaluator(new ArgbEvaluator()); -// anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { -// @Override -// public void onAnimationUpdate(ValueAnimator valueAnimator) { -//// tipText.setTextColor((Integer) valueAnimator.getAnimatedValue()); -// } -// }); -// -// anim.setDuration(900); -// anim.setRepeatCount(2); -// anim.setRepeatMode(ValueAnimator.REVERSE); -// anim.start(); -// } -// } -// -// return false; -// } -// }); -// -// //Submit changes and take user back to LoginActivity -// submitButton.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View v) { -// -// if(submitButton.isEnabled() == true) -// { -// Utils.closeSoftKeyboard(getContext(), v); -// attemptPasswordChange(); -// Intent intent = new Intent(getActivity(),LoginActivity.class); -// startActivity(intent); -// dismiss(); -// } -// } -// }); -// -// //Cancel changing password and dismiss dialogFragment -// cancelButton.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View v) { -// Utils.closeSoftKeyboard(getContext(), v); -// dismiss(); -// } -// }); - return view; } /** - * Checks if passwords are valid. - * - * Currently this method only checks if the passwords match or if either is blank. + * Checks if a password and its confirmation match * * @param password The password * @param passwordConfirm The confirmed password - * @param reason When not null, this method will append the reason the password is invalid - * (or "OK" if the username is valid). - * @return true if the passwords are valid. false otherwise. + * @param reason When not null, this method will append the reason the passwords do not match + * (or "OK" if they do). + * @return true if the passwords match. false otherwise. */ - private boolean isPasswordValid(String password, String passwordConfirm, - @Nullable StringBuilder reason){ + private boolean doPasswordsMatch(String password, String passwordConfirm, + @Nullable StringBuilder reason){ if(password.equals("")){ if(reason != null){ reason.append("Password is blank"); @@ -208,63 +180,128 @@ else if(!password.equals(passwordConfirm)){ } } + /** + * Updates the password error status. That is, displays to the user whether or not the passwords + * match and if the password meets the strength requirements. + */ + private void updatePasswordErrorStatus(String password, String passwordConfirm){ + StringBuilder matchProblem = new StringBuilder(); + if(doPasswordsMatch(password, passwordConfirm, matchProblem)){ + passwordMatchStatus.setTextColor(Color.parseColor("#006600")); + passwordMatchStatus.setText("Passwords match"); + } else{ + passwordMatchStatus.setTextColor(Color.RED); + passwordMatchStatus.setText(matchProblem.toString()); + } + + PasswordChecker.CheckResult checkResult = PasswordChecker.checkPassword(password); + + // Color each of the requirements red (requirement not satisfied) or green (requirement + // satisfied). + passwordReqStatus.setText(Html.fromHtml(new StringBuilder() + .append(checkResult.hasMixedCase() && checkResult.hasNumbers() + && checkResult.length() >= 8? + "Your password must: " : + "Your password must: " + ) + .append(checkResult.hasMixedCase() && checkResult.hasNumbers() ? + "use " : + "use " + ) + .append(checkResult.hasLowerCase() ? + "a lowercase letter, " : + "a lowercase letter, " + ) + .append(checkResult.hasUpperCase() ? + "an uppercase letter, " : + "an uppercase letter, " + ) + .append(checkResult.hasNumbers() ? + "a number, " : + "a number, " + ) + .append(checkResult.length() >= passwordChecker.getMinimumLength() ? + "and have at least 8 characters." : + "and have at least 8 characters." + ) + .toString() + )); + } + private void attemptPasswordChange() { final String password = passwordText.getText().toString(); final String confirmPassword = passwordConfirmText.getText().toString(); final ParseUser currentUser = ParseUser.getCurrentUser(); - StringBuilder invalidReason = new StringBuilder(); - - if(isPasswordValid(password, confirmPassword, invalidReason)){ - currentUser.setPassword(passwordText.getText().toString()); - setWidgetsEnabled(false); - currentUser.saveInBackground(new SaveCallback() { - @Override - public void done(ParseException e) { - if(e == null){ - ParseUser.logInInBackground(currentUser.getUsername(), password, new LogInCallback() { - @Override - public void done(ParseUser user, ParseException e) { - if(e == null){ - Toast.makeText( - cont, - "Password change successful", - Toast.LENGTH_SHORT - ).show(); - dismiss(); - } else{ - Toast.makeText( - cont, - "Please reenter your credentials", - Toast.LENGTH_LONG - ).show(); - dismiss(); - if(getActivity() != null){ - getActivity().finish(); - Intent loginIntent = new Intent(cont, LoginActivity.class); - startActivity(loginIntent); - } + StringBuilder matchProblem = new StringBuilder(); + + if(!doPasswordsMatch(password, confirmPassword, matchProblem)){ + if(cont != null){ + Toast.makeText( + cont, + matchProblem.toString(), + Toast.LENGTH_LONG + ).show(); + } + return; + } + + if(!passwordChecker.meetsRequirements(password)){ + if(cont != null){ + Toast.makeText( + cont, + "Password does not meet requirements", + Toast.LENGTH_LONG + ).show(); + } + return; + } + + // If this line is reached, the provided credentials are valid, so we attempt the password + // change. + + currentUser.setPassword(passwordText.getText().toString()); + setWidgetsEnabled(false); + currentUser.saveInBackground(new SaveCallback() { + @Override + public void done(ParseException e) { + if(e == null){ + ParseUser.logInInBackground(currentUser.getUsername(), password, new LogInCallback() { + @Override + public void done(ParseUser user, ParseException e) { + if(e == null){ + Toast.makeText( + cont, + "Password change successful", + Toast.LENGTH_SHORT + ).show(); + dismiss(); + } else{ + Toast.makeText( + cont, + "Password change successful - please reenter your new credentials", + Toast.LENGTH_LONG + ).show(); + dismiss(); + if(getActivity() != null){ + getActivity().finish(); + Intent loginIntent = new Intent(cont, LoginActivity.class); + startActivity(loginIntent); } - setWidgetsEnabled(true); } - }); - } else if(cont != null){ - Toast.makeText( - cont, - Utils.getErrorMessage(e), - Toast.LENGTH_LONG - ).show(); - setWidgetsEnabled(true); - } + setWidgetsEnabled(true); + } + }); + } else if(cont != null){ + Toast.makeText( + cont, + Utils.getErrorMessage(e), + Toast.LENGTH_LONG + ).show(); + setWidgetsEnabled(true); } - }); - } else if(cont != null){ - Toast.makeText( - cont, - invalidReason.toString(), - Toast.LENGTH_LONG - ).show(); - } + } + }); } } diff --git a/app/src/main/res/layout/fragment_new_account.xml b/app/src/main/res/layout/fragment_new_account.xml index 46f00c9..c6bfc4b 100644 --- a/app/src/main/res/layout/fragment_new_account.xml +++ b/app/src/main/res/layout/fragment_new_account.xml @@ -40,15 +40,12 @@ android:inputType="textNoSuggestions" /> + tools:text="isValid?" /> + android:inputType="textPassword" + android:layout_below="@+id/passwordEditText" + android:layout_alignRight="@+id/passwordMatchStatus" /> + + + android:minLines="2" /> diff --git a/app/src/main/res/layout/fragment_password_dialog.xml b/app/src/main/res/layout/fragment_password_dialog.xml index d69ff05..9d8dd52 100644 --- a/app/src/main/res/layout/fragment_password_dialog.xml +++ b/app/src/main/res/layout/fragment_password_dialog.xml @@ -1,6 +1,7 @@ @@ -30,6 +31,22 @@ android:layout_height="wrap_content" android:hint="Confirm new password"/> + + +