Commit e4ac1aeb authored by Willard's avatar Willard

Add registration feature

parent f834e64b
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testapp"> package="com.testapp">
<!-- To auto-complete the email text field in the login form with the user's emails --> <!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_PROFILE" /> <uses-permission android:name="android.permission.READ_PROFILE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application <application
android:name=".CustomApplication" android:name=".CustomApplication"
...@@ -20,31 +20,33 @@ ...@@ -20,31 +20,33 @@
android:name=".LoginActivity" android:name=".LoginActivity"
android:label="@string/app_name"> android:label="@string/app_name">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".NavDrawerActivity" android:name=".NavDrawerActivity"
android:label="@string/title_activity_nav_drawer" android:label="@string/title_activity_nav_drawer"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar"/>
<activity <activity
android:name=".SearchActivity" android:name=".SearchActivity"
android:label="@string/title_activity_search" android:label="@string/title_activity_search"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar"/>
<activity <activity
android:name=".DishViewActivity" android:name=".DishViewActivity"
android:label="@string/title_activity_blahblah" android:label="@string/title_activity_blahblah"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme"/>
<activity <activity
android:name=".StallViewActivity" android:name=".StallViewActivity"
android:label="@string/title_activity_stall_view" android:label="@string/title_activity_stall_view"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme"/>
<activity <activity
android:name=".AddDishReviewActivity" android:name=".AddDishReviewActivity"
android:label="@string/title_activity_add_dish_review" android:label="@string/title_activity_add_dish_review"
android:theme="@style/AppTheme"></activity> android:theme="@style/AppTheme"/>
<activity android:name=".RegisterActivity">
</activity>
</application> </application>
</manifest> </manifest>
\ No newline at end of file
...@@ -5,6 +5,7 @@ import com.testapp.entities.Dish; ...@@ -5,6 +5,7 @@ import com.testapp.entities.Dish;
import com.testapp.entities.DishReview; import com.testapp.entities.DishReview;
import com.testapp.entities.DishType; import com.testapp.entities.DishType;
import com.testapp.entities.Location; import com.testapp.entities.Location;
import com.testapp.entities.NewUserResult;
import com.testapp.entities.Stall; import com.testapp.entities.Stall;
import com.testapp.entities.StallReview; import com.testapp.entities.StallReview;
import com.testapp.entities.Token; import com.testapp.entities.Token;
...@@ -15,6 +16,8 @@ import okhttp3.ResponseBody; ...@@ -15,6 +16,8 @@ import okhttp3.ResponseBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.http.Body; import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET; import retrofit2.http.GET;
import retrofit2.http.POST; import retrofit2.http.POST;
import retrofit2.http.Path; import retrofit2.http.Path;
...@@ -54,6 +57,10 @@ public interface CanteeneoApiInterface { ...@@ -54,6 +57,10 @@ public interface CanteeneoApiInterface {
@POST("api/dishes/{id}/reviews") @POST("api/dishes/{id}/reviews")
Call<ResponseBody> newDishReview(@Path("id") int id, @Body DishReview review); Call<ResponseBody> newDishReview(@Path("id") int id, @Body DishReview review);
@FormUrlEncoded
@POST("api/users/new")
Call<NewUserResult> newUser(@Field("email") String email, @Field("username") String username, @Field("password") String password);
@GET("api/token") @GET("api/token")
Call<Token> getToken(); Call<Token> getToken();
} }
...@@ -69,10 +69,23 @@ public class LoginActivity extends AppCompatActivity { ...@@ -69,10 +69,23 @@ public class LoginActivity extends AppCompatActivity {
} }
}); });
Button mRegisterButton = (Button) findViewById(R.id.register_button);
mRegisterButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
register();
}
});
mLoginFormView = findViewById(R.id.login_form); mLoginFormView = findViewById(R.id.login_form);
mProgressView = findViewById(R.id.login_progress); mProgressView = findViewById(R.id.login_progress);
} }
public void register() {
Intent intent = new Intent(this, RegisterActivity.class);
startActivity(intent);
}
public void guestLogin() { public void guestLogin() {
Intent intent = new Intent(this, NavDrawerActivity.class); Intent intent = new Intent(this, NavDrawerActivity.class);
startActivity(intent); startActivity(intent);
...@@ -92,8 +105,8 @@ public class LoginActivity extends AppCompatActivity { ...@@ -92,8 +105,8 @@ public class LoginActivity extends AppCompatActivity {
boolean cancel = false; boolean cancel = false;
View focusView = null; View focusView = null;
if (!TextUtils.isEmpty(password)) { if (TextUtils.isEmpty(password)) {
mPasswordView.setError(getString(R.string.error_invalid_password)); mUsernameView.setError(getString(R.string.error_field_required));
focusView = mPasswordView; focusView = mPasswordView;
cancel = true; cancel = true;
} }
...@@ -180,9 +193,6 @@ public class LoginActivity extends AppCompatActivity { ...@@ -180,9 +193,6 @@ public class LoginActivity extends AppCompatActivity {
if (success) { if (success) {
finish(); finish();
} else {
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
} }
} }
......
package com.testapp;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.testapp.entities.NewUserResult;
import com.testapp.entities.Token;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class RegisterActivity extends AppCompatActivity {
private EditText mEmailView;
private EditText mUsernameView;
private EditText mPasswordView;
private EditText mConfirmPasswordView;
private View mProgressView;
private View mRegisterFormView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
mEmailView = (EditText)findViewById(R.id.email);
mUsernameView = (EditText) findViewById(R.id.username);
mPasswordView = (EditText) findViewById(R.id.password);
mConfirmPasswordView = (EditText)findViewById(R.id.confirm_password);
Button mRegisterButton = (Button) findViewById(R.id.register_button);
mRegisterButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
attemptSignIn();
}
});
mRegisterFormView = findViewById(R.id.register_form);
mProgressView = findViewById(R.id.register_progress);
}
private void attemptSignIn() {
mEmailView.setError(null);
mUsernameView.setError(null);
mPasswordView.setError(null);
String email = mEmailView.getText().toString();
String username = mUsernameView.getText().toString();
String password = mPasswordView.getText().toString();
String confirm_password = mConfirmPasswordView.getText().toString();
boolean cancel = false;
View focusView = null;
if(TextUtils.isEmpty(email)) {
mEmailView.setError(getString(R.string.error_field_required));
focusView = mEmailView;
cancel = true;
}
if(TextUtils.isEmpty(password)) {
mPasswordView.setError(getString(R.string.error_field_required));
focusView = mPasswordView;
cancel = true;
}
if(!password.equals(confirm_password)) {
mPasswordView.setError(getString(R.string.error_password_match));
mConfirmPasswordView.setError(getString(R.string.error_password_match));
focusView = mPasswordView;
cancel = true;
}
if (TextUtils.isEmpty(username)) {
mUsernameView.setError(getString(R.string.error_field_required));
focusView = mUsernameView;
cancel = true;
}
if (cancel) {
focusView.requestFocus();
} else {
showProgress(true);
Call<NewUserResult> call = AppUtils.service.newUser(email, username, password);
call.enqueue(new Callback<NewUserResult>() {
@Override
public void onResponse(Call<NewUserResult> call, Response<NewUserResult> response) {
showProgress(false);
NewUserResult result = response.body();
if(result.isSuccess()) {
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
startActivity(intent);
} else {
registerError(result.getField());
}
}
@Override
public void onFailure(Call<NewUserResult> call, Throwable t) {
showProgress(false);
Toast.makeText(RegisterActivity.this, "Server failure, please try again. Message: " + t.getMessage(), Toast.LENGTH_LONG);
}
});
}
}
public void registerError(String field) {
if(field.equals("username")) {
mUsernameView.setError(getString(R.string.error_username_taken));
mUsernameView.requestFocus();
}
if(field.equals("email")) {
mEmailView.setError(getString(R.string.error_email_taken));
mEmailView.requestFocus();
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
private void showProgress(final boolean show) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
mRegisterFormView.setVisibility(show ? View.GONE : View.VISIBLE);
mRegisterFormView.animate().setDuration(shortAnimTime).alpha(
show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mRegisterFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
});
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mProgressView.animate().setDuration(shortAnimTime).alpha(
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
}
});
} else {
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mRegisterFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
}
}
package com.testapp.entities;
public class NewUserResult {
boolean success;
String field;
public NewUserResult(boolean success, String field) {
this.success = success;
this.field = field;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}
...@@ -80,17 +80,18 @@ ...@@ -80,17 +80,18 @@
android:text="@string/action_sign_in"/> android:text="@string/action_sign_in"/>
<Button <Button
android:id="@+id/register_button" android:id="@+id/use_as_guest_button"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/action_guest"/> android:text="@string/action_guest"/>
<Button <Button
android:id="@+id/use_as_guest_button" android:id="@+id/register_button"
style="@android:style/Widget.Material.Light.Button.Borderless"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/action_register" android:text="@string/action_register"
android:layout_marginTop="16dp"
android:elevation="0dp"/> android:elevation="0dp"/>
</LinearLayout> </LinearLayout>
......
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:focusable="true"
android:focusableInTouchMode="true"
tools:context="com.testapp.RegisterActivity">
<ProgressBar
android:id="@+id/register_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:visibility="gone" />
<ScrollView
android:id="@+id/register_form"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/email_login_form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="166dp"
app:srcCompat="@drawable/temp_logo"
android:id="@+id/imageView2"
android:scaleType="fitCenter" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_email"
android:inputType="text"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_username"
android:inputType="text"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_password"
android:imeActionId="@+id/login"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/confirm_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_confirm_password"
android:imeActionId="@+id/register"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/register_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/action_register_short"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
<resources> <resources>
<string name="app_name">Canteeneo</string> <string name="app_name">Canteeneo</string>
<!-- Strings related to login --> <string name="prompt_email">E-mail</string>
<string name="prompt_username">Username</string> <string name="prompt_username">Username</string>
<string name="prompt_password">Password</string> <string name="prompt_password">Password</string>
<string name="prompt_confirm_password">Confirm Password</string>
<string name="action_sign_in">Sign in</string> <string name="action_sign_in">Sign in</string>
<string name="action_sign_in_short">Sign in</string> <string name="action_sign_in_short">Sign in</string>
<string name="action_register">New User? Register Here</string> <string name="action_register">Register</string>
<string name="action_register_short">Register</string>
<string name="error_invalid_email">This email address is invalid</string> <string name="error_invalid_email">This email address is invalid</string>
<string name="error_email_taken">This email address is already in our database</string>
<string name="error_username_taken">This username is already taken</string>
<string name="error_invalid_password">This password is too short</string> <string name="error_invalid_password">This password is too short</string>
<string name="error_incorrect_password">This password is incorrect</string> <string name="error_incorrect_password">This password is incorrect</string>
<string name="error_field_required">This field is required</string> <string name="error_field_required">This field is required</string>
<string name="permission_rationale">"Contacts permissions are needed for providing email <string name="error_password_match">Passwords do not match!</string>
completions."</string>
<string name="action_guest">Use as guest</string> <string name="action_guest">Use as guest</string>
<string name="title_activity_nav_drawer">Main Menu</string> <string name="title_activity_nav_drawer">Main Menu</string>
<string name="drawer_1">All Items</string> <string name="drawer_1">All Items</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment