From 83a6c27c56dc99fd8d0d1ee7a98fd40494acfef5 Mon Sep 17 00:00:00 2001 From: Fawkes100 Date: Sun, 19 Jan 2025 08:02:46 +0100 Subject: [PATCH] WIP: LoginFormValidation --- .../notevault/ui/login/LoginDialog.java | 109 ++++++++++++++---- .../notevault/ui/login/LoginFormState.java | 37 ++++++ .../notevault/ui/login/LoginViewModel.java | 34 ++++++ .../main/res/layout/fragment_login_dialog.xml | 18 ++- 4 files changed, 172 insertions(+), 26 deletions(-) create mode 100644 app/src/main/java/com/stormtales/notevault/ui/login/LoginFormState.java diff --git a/app/src/main/java/com/stormtales/notevault/ui/login/LoginDialog.java b/app/src/main/java/com/stormtales/notevault/ui/login/LoginDialog.java index 1d9949a..b7b6995 100644 --- a/app/src/main/java/com/stormtales/notevault/ui/login/LoginDialog.java +++ b/app/src/main/java/com/stormtales/notevault/ui/login/LoginDialog.java @@ -4,20 +4,23 @@ import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; import android.util.Log; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; +import android.view.inputmethod.EditorInfo; +import android.widget.*; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; +import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import com.stormtales.notevault.R; import com.stormtales.notevault.network.APICallback; import com.stormtales.notevault.network.auth.AuthService; +import org.jetbrains.annotations.NotNull; public class LoginDialog extends DialogFragment { @@ -25,6 +28,12 @@ public class LoginDialog extends DialogFragment { private boolean isLoginMode = true; private Dialog dialog; + private Button loginButton; + private ProgressBar loadingProgressBar; + private EditText editTextUsername; + private EditText editTextPassword; + private EditText editTextEmail; + @Override public void onAttach(Context context) { super.onAttach(context); @@ -43,43 +52,93 @@ public class LoginDialog extends DialogFragment { View view = inflater.inflate(R.layout.fragment_login_dialog, null); TextView textViewTitle = view.findViewById(R.id.textViewTitle); - EditText editTextUsername = view.findViewById(R.id.editTextUsername); - EditText editTextEmail = view.findViewById(R.id.editTextEmail); - EditText editTextPassword = view.findViewById(R.id.editTextPassword); - Button buttonAction = view.findViewById(R.id.buttonAction); + editTextUsername = view.findViewById(R.id.editTextUsername); + editTextEmail = view.findViewById(R.id.editTextEmail); + editTextPassword = view.findViewById(R.id.editTextPassword); + loginButton = view.findViewById(R.id.buttonAction); TextView textViewSwitch = view.findViewById(R.id.textViewSwitch); - + loadingProgressBar = view.findViewById(R.id.loading); // Handle action button click - buttonAction.setOnClickListener(v -> { - if (isLoginMode) { - // Handle login logic - String email = editTextEmail.getText().toString(); - String password = editTextPassword.getText().toString(); - this.loginViewModel.performLogin(email, password, this::onSuccessFullLogin); - } else { - // Handle registration logic - String email = editTextEmail.getText().toString(); - String password = editTextPassword.getText().toString(); - String username = editTextUsername.getText().toString(); - AuthService authRepository = new AuthService(this.getContext()); - //authRepository.performRegistration(email, username, password, registerCallback); - } - }); + // Toggle between Login and Registration textViewSwitch.setOnClickListener(v -> { isLoginMode = !isLoginMode; textViewTitle.setText(isLoginMode ? "Login" : "Register"); editTextUsername.setVisibility(isLoginMode ? View.GONE : View.VISIBLE); - buttonAction.setText(isLoginMode ? "Login" : "Register"); + loginButton.setText(isLoginMode ? "Login" : "Register"); textViewSwitch.setText(isLoginMode ? "Don't have an account? Register" : "Already have an account? Login"); }); builder.setView(view); dialog = builder.create(); + + + + TextWatcher afterTextChangedListener = 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) { + loginViewModel.updateLoginData(editTextUsername.getText().toString(), editTextPassword.getText().toString()); + } + }; + + editTextUsername.addTextChangedListener(afterTextChangedListener); + editTextPassword.addTextChangedListener(afterTextChangedListener); + editTextPassword.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if(actionId == EditorInfo.IME_ACTION_DONE) { + loginViewModel.performLogin(editTextUsername.getText().toString(), editTextPassword.getText().toString(), LoginDialog.this::onSuccessFullLogin); + } + return false; + } + }); + + loginButton.setOnClickListener(v -> { + loadingProgressBar.setVisibility(View.VISIBLE); + String email = editTextEmail.getText().toString(); + String password = editTextPassword.getText().toString(); + if (isLoginMode) { + // Handle login logic + this.loginViewModel.performLogin(email, password, this::onSuccessFullLogin); + } else { + // Handle registration logic + String username = editTextUsername.getText().toString(); + AuthService authRepository = new AuthService(this.getContext()); + //authRepository.performRegistration(email, username, password, registerCallback); + } + }); return dialog; } + @Override + public void onViewCreated(@NonNull @NotNull View view, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + loginViewModel.getLoginFormState().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(LoginFormState loginFormState) { + if(loginFormState == null) return; + loginButton.setEnabled(loginFormState.isDataValid()); + if(loginFormState.getUsernameError() != null) { + editTextUsername.setError(getString(loginFormState.getUsernameError())); + } + if(loginFormState.getPasswordError() != null) { + editTextPassword.setError(getString(loginFormState.getPasswordError())); + } + } + }); + } + void onSuccessFullLogin() { this.dialog.dismiss(); } diff --git a/app/src/main/java/com/stormtales/notevault/ui/login/LoginFormState.java b/app/src/main/java/com/stormtales/notevault/ui/login/LoginFormState.java new file mode 100644 index 0000000..17c2714 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/ui/login/LoginFormState.java @@ -0,0 +1,37 @@ +package com.stormtales.notevault.ui.login; + +import androidx.annotation.Nullable; + +public class LoginFormState { + @Nullable + private Integer usernameError; + @Nullable + private Integer passwordError; + private boolean isDataValid; + + LoginFormState(@Nullable Integer usernameError, @Nullable Integer passwordError) { + this.usernameError = usernameError; + this.passwordError = passwordError; + this.isDataValid = false; + } + + LoginFormState(boolean isDataValid) { + this.usernameError = null; + this.passwordError = null; + this.isDataValid = isDataValid; + } + + @Nullable + Integer getUsernameError() { + return usernameError; + } + + @Nullable + Integer getPasswordError() { + return passwordError; + } + + boolean isDataValid() { + return isDataValid; + } +} diff --git a/app/src/main/java/com/stormtales/notevault/ui/login/LoginViewModel.java b/app/src/main/java/com/stormtales/notevault/ui/login/LoginViewModel.java index 3f3a675..7d20ca7 100644 --- a/app/src/main/java/com/stormtales/notevault/ui/login/LoginViewModel.java +++ b/app/src/main/java/com/stormtales/notevault/ui/login/LoginViewModel.java @@ -1,9 +1,11 @@ package com.stormtales.notevault.ui.login; import android.util.Log; +import android.util.Patterns; import android.widget.Toast; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; +import com.stormtales.notevault.R; import com.stormtales.notevault.network.auth.AuthService; import com.stormtales.notevault.network.auth.LoginResponse; @@ -11,6 +13,7 @@ public class LoginViewModel extends ViewModel { private final MutableLiveData username; private final MutableLiveData isLoggedIn; + private MutableLiveData loginFormState = new MutableLiveData<>(); private AuthService authService; public LoginViewModel() { @@ -38,6 +41,16 @@ public class LoginViewModel extends ViewModel { return username; } + public void updateLoginData(String username, String password) { + if(!isUserNameValid(username)) { + loginFormState.setValue(new LoginFormState(R.string.invalid_username, null)); + } else if(!isPasswordValid(password)) { + loginFormState.setValue(new LoginFormState(null, R.string.invalid_password)); + } else { + loginFormState.setValue(new LoginFormState(true)); + } + } + public class LoginCallBackImpl implements AuthService.LoginCallback { private final SuccessFullLoginCallback successFullLoginCallback; @@ -62,4 +75,25 @@ public class LoginViewModel extends ViewModel { public interface SuccessFullLoginCallback { void onSuccess(); } + + public MutableLiveData getLoginFormState() { + return loginFormState; + } + + // A placeholder username validation check + private boolean isUserNameValid(String username) { + if (username == null) { + return false; + } + if (username.contains("@")) { + return Patterns.EMAIL_ADDRESS.matcher(username).matches(); + } else { + return !username.trim().isEmpty(); + } + } + + // A placeholder password validation check + private boolean isPasswordValid(String password) { + return password != null && password.trim().length() > 5; + } } diff --git a/app/src/main/res/layout/fragment_login_dialog.xml b/app/src/main/res/layout/fragment_login_dialog.xml index da64177..479a356 100644 --- a/app/src/main/res/layout/fragment_login_dialog.xml +++ b/app/src/main/res/layout/fragment_login_dialog.xml @@ -1,7 +1,7 @@ + +