Skip to content
This repository was archived by the owner on Feb 20, 2019. It is now read-only.
Open
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ dependencies {
compile 'com.android.support:appcompat-v7:25.3.0'
compile 'com.android.support:design:25.3.0'
testCompile 'junit:junit:4.12'

compile 'org.greenrobot:eventbus:3.0.0'
}
156 changes: 47 additions & 109 deletions app/src/main/java/edu/galileo/mvp/LoginActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,29 @@

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import edu.galileo.mvp.event.CanceledEvent;
import edu.galileo.mvp.event.PasswordErrorEvent;
import edu.galileo.mvp.event.SuccessEvent;

/**
* A login screen that offers login via email/password.
*/
public class LoginActivity extends AppCompatActivity {
public class LoginActivity extends AppCompatActivity implements LoginView {

/**
* A dummy authentication store containing known user names and passwords.
* TODO: remove after connecting to a real authentication system.
*/
private static final String[] DUMMY_CREDENTIALS = new String[] {
"test@galileo.edu", "testtest"
};
/**
* Keep track of the login task to ensure we can cancel it if requested.
*/
private UserLoginTask mAuthTask = null;
private LoginPresenter loginPresenter;

// UI references.
private AutoCompleteTextView mEmailView;
Expand Down Expand Up @@ -56,6 +52,8 @@ public void onClick(View view) {

mLoginFormView = findViewById(R.id.login_form);
mProgressView = findViewById(R.id.login_progress);

loginPresenter = new LoginPresenterImpl(this);
}

/**
Expand All @@ -64,10 +62,6 @@ public void onClick(View view) {
* errors are presented and no actual login attempt is made.
*/
private void attemptLogin() {
if (mAuthTask != null) {
return;
}

// Reset errors.
mEmailView.setError(null);
mPasswordView.setError(null);
Expand All @@ -76,53 +70,13 @@ private void attemptLogin() {
String email = mEmailView.getText().toString();
String password = mPasswordView.getText().toString();

boolean cancel = false;
View focusView = null;

// Check for a valid password, if the user entered one.
if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
mPasswordView.setError(getString(R.string.error_invalid_password));
focusView = mPasswordView;
cancel = true;
}

// Check for a valid email address.
if (TextUtils.isEmpty(email)) {
mEmailView.setError(getString(R.string.error_field_required));
focusView = mEmailView;
cancel = true;
} else if (!isEmailValid(email)) {
mEmailView.setError(getString(R.string.error_invalid_email));
focusView = mEmailView;
cancel = true;
}

if (cancel) {
// There was an error; don't attempt login and focus the first
// form field with an error.
focusView.requestFocus();
} else {
// Show a progress spinner, and kick off a background task to
// perform the user login attempt.
showProgress(true);
mAuthTask = new UserLoginTask(email, password);
mAuthTask.execute((Void) null);
}
}

private boolean isEmailValid(String email) {
//TODO: Replace this with your own logic
return email.contains("@");
}

private boolean isPasswordValid(String password) {
//TODO: Replace this with your own logic
return password.length() > 4;
loginPresenter.validateCredentials(email, password);
}

/**
* Shows the progress UI and hides the login form.
*/
@Override
public void showProgress(final boolean show) {
int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);

Expand All @@ -147,61 +101,45 @@ public void onAnimationEnd(Animator animation) {
});
}

/**
* Represents an asynchronous login/registration task used to authenticate
* the user.
*/
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {

private final String mEmail;
private final String mPassword;

UserLoginTask(String email, String password) {
mEmail = email;
mPassword = password;
}

@Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
@Override
public void setUsernameError(int messageResId) {
mEmailView.setError(getString(messageResId));
mEmailView.requestFocus();
}

try {
// Simulate network access.
Thread.sleep(2000);
} catch (InterruptedException e) {
return false;
}
@Override
public void setPasswordError(int messageResId) {
mPasswordView.setError(getString(messageResId));
mPasswordView.requestFocus();
}

for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
return pieces[1].equals(mPassword);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onCanceledEvent(CanceledEvent canceledEvent) {
showProgress(false);
}

// TODO: register the new account here.
return true;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onPasswordErrorEvent(PasswordErrorEvent passwordErrorEvent) {
showProgress(false);
setPasswordError(passwordErrorEvent.getMessageResId());
}

@Override
protected void onPostExecute(final Boolean success) {
mAuthTask = null;
showProgress(false);
@Subscribe(threadMode = ThreadMode.MAIN)
public void onSuccessEvent(SuccessEvent successEvent) {
showProgress(false);
Toast.makeText(LoginActivity.this, "Success", Toast.LENGTH_SHORT).show();
}

if (success) {
Toast.makeText(LoginActivity.this, "Success", Toast.LENGTH_SHORT).show();
} else {
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

@Override
protected void onCancelled() {
mAuthTask = null;
showProgress(false);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
}

6 changes: 6 additions & 0 deletions app/src/main/java/edu/galileo/mvp/LoginModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package edu.galileo.mvp;

public interface LoginModel {

void login(String username, String password);
}
73 changes: 73 additions & 0 deletions app/src/main/java/edu/galileo/mvp/LoginModelImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package edu.galileo.mvp;

import android.os.AsyncTask;

import org.greenrobot.eventbus.EventBus;

import edu.galileo.mvp.event.CanceledEvent;
import edu.galileo.mvp.event.PasswordErrorEvent;
import edu.galileo.mvp.event.SuccessEvent;

public class LoginModelImpl implements LoginModel {

/**
* A dummy authentication store containing known user names and passwords.
* TODO: remove after connecting to a real authentication system.
*/
private static final String[] DUMMY_CREDENTIALS = new String[] {
"test@galileo.edu:asdfasdf", "test2@galileo.edu:asdfasdf"
};

@Override
public void login(String username, String password) {
new UserLoginTask(username, password).execute((Void) null);
}

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {

private final String mEmail;
private final String mPassword;

UserLoginTask(String email, String password) {
mEmail = email;
mPassword = password;
}

@Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.

try {
// Simulate network access.
Thread.sleep(2000);
} catch (InterruptedException e) {
return false;
}

for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
return pieces[1].equals(mPassword);
}
}

// TODO: register the new account here.
return false;
}

@Override
protected void onPostExecute(final Boolean success) {
if (success) {
EventBus.getDefault().post(new SuccessEvent());
} else {
EventBus.getDefault().post(new PasswordErrorEvent(R.string.error_incorrect_password));
}
}

@Override
protected void onCancelled() {
EventBus.getDefault().post(new CanceledEvent());
}
}
}
6 changes: 6 additions & 0 deletions app/src/main/java/edu/galileo/mvp/LoginPresenter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package edu.galileo.mvp;

public interface LoginPresenter {

void validateCredentials(String username, String password);
}
45 changes: 45 additions & 0 deletions app/src/main/java/edu/galileo/mvp/LoginPresenterImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package edu.galileo.mvp;

import android.text.TextUtils;

public class LoginPresenterImpl implements LoginPresenter {

private LoginView loginView;
private LoginModel loginModel;

public LoginPresenterImpl(LoginView loginView) {
this.loginView = loginView;
this.loginModel = new LoginModelImpl();
}

@Override
public void validateCredentials(String username, String password) {
// Check for a valid password, if the user entered one.
if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
loginView.setPasswordError(R.string.error_invalid_password);
return;
}

// Check for a valid username.
if (TextUtils.isEmpty(username)) {
loginView.setUsernameError(R.string.error_field_required);
return;
} else if (!isEmailValid(username)) {
loginView.setUsernameError(R.string.error_invalid_email);
return;
}

loginView.showProgress(true);
loginModel.login(username, password);
}

private boolean isEmailValid(String email) {
//TODO: Replace this with your own logic
return email.contains("@");
}

private boolean isPasswordValid(String password) {
//TODO: Replace this with your own logic
return password.length() > 4;
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/edu/galileo/mvp/LoginView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package edu.galileo.mvp;

public interface LoginView {

void showProgress(boolean showProgress);

void setUsernameError(int messageResId);

void setPasswordError(int messageResId);
}
4 changes: 4 additions & 0 deletions app/src/main/java/edu/galileo/mvp/event/CanceledEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package edu.galileo.mvp.event;

public class CanceledEvent {
}
Loading