Added login and registration using firebase

This commit is contained in:
Gilbert Kimutai 2019-03-30 06:01:00 +03:00
parent 152397b6fa
commit 7643a8e089
35 changed files with 1683 additions and 8 deletions

View File

@ -8,7 +8,7 @@ android {
compileSdkVersion 28 compileSdkVersion 28
defaultConfig { defaultConfig {
applicationId "me.gilo.wc" applicationId "me.gilo.wc"
minSdkVersion 15 minSdkVersion 16
targetSdkVersion 28 targetSdkVersion 28
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@ -54,6 +54,16 @@ dependencies {
implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0' implementation 'com.android.support:design:28.0.0'
implementation 'com.google.firebase:firebase-database:16.0.4'
implementation 'com.google.firebase:firebase-auth:16.0.4'
implementation 'com.google.firebase:firebase-core:16.0.4'
implementation 'com.google.firebase:firebase-firestore:17.1.1'
implementation 'com.google.firebase:firebase-storage:16.0.4'
implementation 'com.firebaseui:firebase-ui-database:4.2.0'
implementation 'com.firebaseui:firebase-ui-firestore:4.2.0'
implementation 'com.firebaseui:firebase-ui-storage:4.2.0'
implementation 'com.google.firebase:firebase-messaging:17.1.0'
implementation 'io.github.inflationx:calligraphy3:3.0.0' implementation 'io.github.inflationx:calligraphy3:3.0.0'
implementation 'io.github.inflationx:viewpump:1.0.0' implementation 'io.github.inflationx:viewpump:1.0.0'
@ -94,3 +104,7 @@ dependencies {
} }
apply plugin: 'com.google.gms.google-services'
googleServices { disableVersionCheck = true }

42
app/google-services.json Normal file
View File

@ -0,0 +1,42 @@
{
"project_info": {
"project_number": "159460744011",
"firebase_url": "https://api-project-159460744011.firebaseio.com",
"project_id": "api-project-159460744011",
"storage_bucket": "api-project-159460744011.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:159460744011:android:6480f4108da5caac",
"android_client_info": {
"package_name": "me.gilo.wc"
}
},
"oauth_client": [
{
"client_id": "159460744011-nbbmft1vofqfrkmt88fub6u8jumt4f7v.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCoViVbbgVc_-NOPwSwHIfutH6ZK8nbn-k"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}

View File

@ -11,8 +11,13 @@
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:usesCleartextTraffic="true" android:theme="@style/AppTheme"
android:theme="@style/AppTheme"> android:usesCleartextTraffic="true">
<activity
android:name=".ui.order.MyOrdersActivity"
android:label="@string/title_activity_my_orders"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<activity <activity
android:name=".ui.home.HomeActivity" android:name=".ui.home.HomeActivity"
android:label="@string/title_activity_home" android:label="@string/title_activity_home"
@ -23,6 +28,19 @@
android:label="@string/title_activity_category" android:label="@string/title_activity_category"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
</activity> </activity>
<activity
android:name="me.gilo.raison.ui.user.onboarding.SignUpActivity"
android:label="@string/title_activity_category"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<activity
android:name="me.gilo.raison.ui.user.onboarding.SignInActivity"
android:label="@string/title_activity_category"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<activity <activity
android:name=".ui.product.NavigatioDrawerActivity" android:name=".ui.product.NavigatioDrawerActivity"
android:label="@string/title_activity_navigatio_drawer" android:label="@string/title_activity_navigatio_drawer"

View File

@ -3,6 +3,8 @@ package me.gilo.wc
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import me.gilo.raison.ui.user.onboarding.SignInActivity
import me.gilo.raison.ui.user.onboarding.SignUpActivity
import me.gilo.wc.ui.home.HomeActivity import me.gilo.wc.ui.home.HomeActivity
import me.gilo.wc.ui.product.ProductActivity import me.gilo.wc.ui.product.ProductActivity
@ -14,7 +16,7 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
startActivity(Intent(baseContext, HomeActivity::class.java)) startActivity(Intent(baseContext, SignInActivity::class.java))
// val intent = Intent(baseContext, ProductActivity::class.java) // val intent = Intent(baseContext, ProductActivity::class.java)
// intent.putExtra("productId", 63) // intent.putExtra("productId", 63)

View File

@ -0,0 +1,36 @@
package me.gilo.wc.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import me.gilo.wc.R;
import me.gilo.wc.adapter.viewholder.CategoryViewHolder;
import me.gilo.wc.adapter.viewholder.OrderViewHolder;
import me.gilo.woodroid.models.Category;
import me.gilo.woodroid.models.Order;
import java.util.List;
public class OrderAdapter extends RecyclerView.Adapter<OrderViewHolder> {
private List<Order> orders;
public OrderAdapter(List<Order> orders) {
this.orders = orders;
}
@Override
public OrderViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new OrderViewHolder(parent.getContext(), LayoutInflater.from(parent.getContext()).inflate(R.layout.single_order_item, parent, false));
}
@Override
public void onBindViewHolder(OrderViewHolder holder, int position) {
holder.renderView(orders.get(position));
}
@Override
public int getItemCount() {
return orders.size() == 0 ? 0 : orders.size();
}
}

View File

@ -0,0 +1,24 @@
package me.gilo.wc.adapter.viewholder
import android.content.Context
import android.content.Intent
import android.support.v7.widget.RecyclerView
import android.text.Html
import android.view.View
import android.widget.TextView
import me.gilo.wc.R
import me.gilo.wc.ui.product.ShopActivity
import me.gilo.woodroid.models.Category
import me.gilo.woodroid.models.Order
class OrderViewHolder(val context: Context, itemView: View) :
RecyclerView.ViewHolder(itemView) {
fun renderView(order: Order) {
val tvTitle = itemView.findViewById<TextView>(R.id.tvTitle)
tvTitle.text = order.orderNumber
}
}

View File

@ -0,0 +1,25 @@
package me.gilo.wc.common;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.DocumentReference;
public final class CompletionDocLiveData extends LiveData<Resource<Boolean>> implements OnCompleteListener<DocumentReference> {
public CompletionDocLiveData() {
setValue(new Resource<>(Status.LOADING));
}
@Override
public final void onComplete(@NonNull Task<DocumentReference> task) {
if (task.isSuccessful()) {
setValue(new Resource<>(true));
} else {
setValue(new Resource<>(task.getException()));
}
}
}

View File

@ -0,0 +1,25 @@
package me.gilo.wc.common;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
public final class CompletionGenericLiveData<T> extends LiveData<Resource<T>> implements OnCompleteListener<T> {
public CompletionGenericLiveData() {
setValue(new Resource<>(Status.LOADING));
}
@Override
public final void onComplete(@NonNull Task<T> task) {
if (task.isSuccessful()) {
setValue(new Resource<T>(task.getResult()));
} else {
setValue(new Resource<>(task.getException()));
}
}
}

View File

@ -0,0 +1,24 @@
package me.gilo.wc.common;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
public final class CompletionLiveData extends LiveData<Resource<Boolean>> implements OnCompleteListener<Void> {
public CompletionLiveData() {
setValue(new Resource<>(Status.LOADING));
}
@Override
public final void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
setValue(new Resource<>(true));
} else {
setValue(new Resource<>(task.getException()));
}
}
}

View File

@ -0,0 +1,41 @@
package me.gilo.wc.common;
import android.arch.lifecycle.LiveData;
import com.google.firebase.firestore.*;
public class DocumentLiveData<T> extends LiveData<Resource<T>>
implements EventListener<DocumentSnapshot> {
private final Class<T> type;
private ListenerRegistration registration;
private final DocumentReference ref;
public DocumentLiveData(DocumentReference ref, Class<T> type) {
this.ref = ref;
this.type = type;
}
@Override
public void onEvent(DocumentSnapshot snapshot, FirebaseFirestoreException e) {
if (e != null) {
setValue(new Resource<>(e));
return;
}
setValue(new Resource<>(snapshot.toObject(type)));
}
@Override
protected void onActive() {
super.onActive();
registration = ref.addSnapshotListener(this);
}
@Override
protected void onInactive() {
super.onInactive();
if (registration != null) {
registration.remove();
registration = null;
}
}
}

View File

@ -2,6 +2,8 @@ package me.gilo.wc.di;
import dagger.Module; import dagger.Module;
import dagger.android.ContributesAndroidInjector; import dagger.android.ContributesAndroidInjector;
import me.gilo.raison.ui.user.onboarding.SignInActivity;
import me.gilo.raison.ui.user.onboarding.SignUpActivity;
import me.gilo.wc.MainActivity; import me.gilo.wc.MainActivity;
import me.gilo.wc.ui.home.HomeActivity; import me.gilo.wc.ui.home.HomeActivity;
import me.gilo.wc.ui.product.ProductActivity; import me.gilo.wc.ui.product.ProductActivity;
@ -22,4 +24,10 @@ abstract class ActivitiesModule {
@ContributesAndroidInjector @ContributesAndroidInjector
abstract HomeActivity contributesHomeActivity(); abstract HomeActivity contributesHomeActivity();
@ContributesAndroidInjector
abstract SignInActivity contributesSignInActivity();
@ContributesAndroidInjector
abstract SignUpActivity contributesSignUpActivity();
} }

View File

@ -14,6 +14,7 @@ import javax.inject.Singleton;
@Component(modules = { @Component(modules = {
AndroidSupportInjectionModule.class, AndroidSupportInjectionModule.class,
ViewModelModule.class, ViewModelModule.class,
FirebaseModule.class,
ActivitiesModule.class, ActivitiesModule.class,
AppModule.class AppModule.class
}) })

View File

@ -0,0 +1,46 @@
package me.gilo.wc.di;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import dagger.Module;
import dagger.Provides;
import javax.inject.Named;
import javax.inject.Singleton;
@Module
class FirebaseModule {
@Singleton
@Provides
FirebaseFirestore providesFirestore() {
FirebaseFirestore db = FirebaseFirestore.getInstance();
return db;
}
@Singleton
@Provides
@Named("storage")
StorageReference providesStorage() {
return FirebaseStorage.getInstance().getReference();
}
@Singleton
@Provides
@Named("users")
CollectionReference providesUsers() {
return getFirestoreInstance().collection("users");
}
FirebaseFirestore getFirestoreInstance(){
FirebaseFirestore db = FirebaseFirestore.getInstance();
return db;
}
}

View File

@ -2,19 +2,31 @@ package me.gilo.wc.di;
import android.arch.lifecycle.ViewModel; import android.arch.lifecycle.ViewModel;
import android.arch.lifecycle.ViewModelProvider; import android.arch.lifecycle.ViewModelProvider;
import com.google.firebase.firestore.CollectionReference;
import dagger.Binds; import dagger.Binds;
import dagger.Module; import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap; import dagger.multibindings.IntoMap;
import me.gilo.wc.utils.ViewModelFactory; import me.gilo.wc.utils.ViewModelFactory;
import me.gilo.wc.viewmodels.CategoryViewModel; import me.gilo.wc.viewmodels.CategoryViewModel;
import me.gilo.wc.viewmodels.ProductViewModel; import me.gilo.wc.viewmodels.ProductViewModel;
import me.gilo.wc.viewmodels.ReviewViewModel; import me.gilo.wc.viewmodels.ReviewViewModel;
import me.gilo.wc.viewmodels.UserViewModel;
import javax.inject.Named;
import javax.inject.Singleton;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@Module @Module
public abstract class ViewModelModule { public abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(UserViewModel.class)
abstract ViewModel bindUserViewModel(UserViewModel viewModel);
@Binds @Binds
@IntoMap @IntoMap
@ViewModelKey(ProductViewModel.class) @ViewModelKey(ProductViewModel.class)
@ -29,8 +41,10 @@ public abstract class ViewModelModule {
@Binds @Binds
@IntoMap @IntoMap
@ViewModelKey(ReviewViewModel.class) @ViewModelKey(ReviewViewModel.class)
abstract ViewModel bindRevuewViewModel(ReviewViewModel viewModel); abstract ViewModel bindReviewViewModel(ReviewViewModel viewModel);
@Binds @Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory); abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
} }

View File

@ -0,0 +1,18 @@
package me.gilo.wc.models;
import com.google.firebase.firestore.Exclude;
/**
* Represents an object that can be uniquely identified among other objects of the same type
* by using an UID.
*
* @param <TKey> type of the unique key (UID) this object is uniquely identified by. The type needs
* a correct implementation of its equals() method or the behaviour of code using this
* interface will be undefined.
*/
public interface Identifiable<TKey> {
@Exclude
TKey getEntityKey();
}

View File

@ -0,0 +1,45 @@
package me.gilo.wc.models;
import com.google.android.gms.tasks.Task;
/**
* Manages data access for POJOs that are uniquely identifiable by a key, such as POJOs implementing {@link Identifiable}.
*/
public interface Repository<TEntity extends Identifiable<TKey>, TKey> {
/**
* Checks the repository for a given id and returns a boolean representing its existence.
* @param id the unique id of an entity.
* @return A {@link Task} for a boolean which is 'true' if the entity for the given id exists, 'false' otherwise.
*/
Task<Boolean> exists(TKey id);
/**
* Queries the repository for an uniquely identified entity and returns it. If the entity does
* not exist in the repository, a new instance is returned.
* @param id the unique id of an entity.
* @return A {@link Task} for an entity implementing {@link Identifiable}.
*/
Task<TEntity> get(TKey id);
/**
* Stores an entity in the repository so it is accessible via its unique id.
* @param entity the entity implementing {@link Identifiable} to be stored.
* @return An {@link Task} to be notified of failures.
*/
Task<Void> create(TEntity entity);
/**
* Updates an entity in the repository
* @param entity the new entity to be stored.
* @return A {@link Task} to be notified of failures.
*/
Task<Void> update(TEntity entity);
/**
* Deletes an entity from the repository.
* @param id uniquely identifying the entity.
* @return A {@link Task} to be notified of failures.
*/
Task<Void> delete(TKey id);
}

View File

@ -0,0 +1,85 @@
package me.gilo.wc.models;
public class User{
String id;
private String middlename;
private String email;
private String dob;
private String gender;
private String surname;
private String firstname;
private String lastname;
private String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMiddlename() {
return middlename;
}
public void setMiddlename(String middlename) {
this.middlename = middlename;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@ -0,0 +1,111 @@
package me.gilo.wc.repo;
import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.gms.tasks.Continuation;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import me.gilo.wc.models.Identifiable;
import me.gilo.wc.models.Repository;
/**
* Manages data access for Firebase
*/
public class FirebaseRepository<TEntity extends Identifiable<String>> implements Repository<TEntity, String> {
private static final String TAG = "FirebaseRepository";
private final Class<TEntity> entityClass;
private final CollectionReference collectionReference;
private final String collectionName;
public FirebaseRepository(Class<TEntity> entityClass, String collectionName) {
this.collectionName = collectionName;
this.entityClass = entityClass;
FirebaseFirestore db = FirebaseFirestore.getInstance();
this.collectionReference = db.collection(this.collectionName);
}
@Override
public Task<Boolean> exists(final String documentName) {
DocumentReference documentReference = collectionReference.document(documentName);
Log.i(TAG, "Checking existence of '" + documentName + "' in '" + collectionName + "'.");
return documentReference.get().continueWith(new Continuation<DocumentSnapshot, Boolean>() {
@Override
public Boolean then(@NonNull Task<DocumentSnapshot> task) {
Log.d(TAG,"Checking if '" + documentName + "' exists in '" + collectionName +"'.");
return task.getResult().exists();
}
});
}
@Override
public Task<TEntity> get(String id) {
final String documentName = id;
DocumentReference documentReference = collectionReference.document(documentName);
Log.i(TAG, "Getting '" + documentName + "' in '" + collectionName + "'.");
return documentReference.get().continueWith(new Continuation<DocumentSnapshot, TEntity>() {
@Override
public TEntity then(@NonNull Task<DocumentSnapshot> task) throws Exception {
DocumentSnapshot documentSnapshot = task.getResult();
if (documentSnapshot.exists()) {
return documentSnapshot.toObject(entityClass);
} else {
Log.d(TAG, "Document '" + documentName + "' does not exist in '" + collectionName + "'.");
return entityClass.newInstance();
}
}
});
}
@Override
public Task<Void> create(TEntity entity) {
final String documentName = entity.getEntityKey();
DocumentReference documentReference = collectionReference.document(documentName);
Log.i(TAG, "Creating '" + documentName + "' in '" + collectionName + "'.");
return documentReference.set(entity).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d(TAG, "There was an error creating '" + documentName + "' in '" + collectionName + "'!", e);
}
});
}
@Override
public Task<Void> update(TEntity entity) {
final String documentName = entity.getEntityKey();
DocumentReference documentReference = collectionReference.document(documentName);
Log.i(TAG, "Updating '" + documentName + "' in '" + collectionName + "'.");
return documentReference.set(entity).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d(TAG, "There was an error updating '" + documentName + "' in '" + collectionName + "'.", e);
}
});
}
@Override
public Task<Void> delete(final String documentName) {
DocumentReference documentReference = collectionReference.document(documentName);
Log.i(TAG, "Deleting '" + documentName + "' in '" + collectionName + "'.");
return documentReference.delete().addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d(TAG, "There was an error deleting '" + documentName + "' in '" + collectionName + "'.", e);
}
});
}
}

View File

@ -0,0 +1,85 @@
package me.gilo.wc.repo;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.storage.StorageReference;
import me.gilo.wc.common.CompletionGenericLiveData;
import me.gilo.wc.common.CompletionLiveData;
import me.gilo.wc.common.DocumentLiveData;
import me.gilo.wc.models.User;
import javax.inject.Inject;
import javax.inject.Named;
public class FirebaseUserRepository extends FirebaseRepository {
private final CollectionReference users;
private final StorageReference storage;
@Inject
public FirebaseUserRepository(@Named("users") CollectionReference users, @Named("storage") StorageReference storage) {
super(User.class, "users");
this.users = users;
this.storage = storage;
}
public CompletionGenericLiveData<AuthResult> login(String email, String password) {
final CompletionGenericLiveData<AuthResult> completion = new CompletionGenericLiveData();
FirebaseAuth auth = FirebaseAuth.getInstance();
auth.signInWithEmailAndPassword(email, password).addOnCompleteListener(completion);
return completion;
}
public CompletionGenericLiveData<AuthResult> signUp(String email, String password) {
final CompletionGenericLiveData<AuthResult> completion = new CompletionGenericLiveData();
FirebaseAuth auth = FirebaseAuth.getInstance();
auth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(completion);
return completion;
}
public DocumentLiveData<User> user(final String id) {
if (id == null) {
return null;
}
final DocumentReference userRef = users.document(id);
DocumentLiveData<User> data = new DocumentLiveData<>(userRef, User.class);
userRef.addSnapshotListener(data);
return data;
}
public DocumentLiveData<User> user() {
final DocumentReference userRef = users.document(FirebaseAuth.getInstance().getCurrentUser().getUid());
DocumentLiveData<User> data = new DocumentLiveData<>(userRef, User.class);
userRef.addSnapshotListener(data);
return data;
}
public CompletionLiveData addUser(User user, OnSuccessListener successListener, OnFailureListener failureListener) {
final CompletionLiveData completion = new CompletionLiveData();
users.add(user).addOnSuccessListener(successListener).addOnFailureListener(failureListener).addOnCompleteListener(completion);
return completion;
}
public CompletionLiveData update(User user) {
final CompletionLiveData completion = new CompletionLiveData();
users.document(user.getId()).set(user).addOnCompleteListener(completion);
return completion;
}
}

View File

@ -4,8 +4,10 @@ package me.gilo.wc.repo;
import me.gilo.wc.common.WooLiveData; import me.gilo.wc.common.WooLiveData;
import me.gilo.woodroid.Woocommerce; import me.gilo.woodroid.Woocommerce;
import me.gilo.woodroid.models.Order; import me.gilo.woodroid.models.Order;
import me.gilo.woodroid.models.filters.OrderFilter;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.List;
public class OrderRepository { public class OrderRepository {
@ -25,4 +27,53 @@ public class OrderRepository {
return callBack; return callBack;
} }
public WooLiveData<Order> create(Order order) {
final WooLiveData<Order> callBack = new WooLiveData();
woocommerce.OrderRepository().create(order).enqueue(callBack);
return callBack;
}
public WooLiveData<Order> order(int id) {
final WooLiveData<Order> callBack = new WooLiveData();
woocommerce.OrderRepository().order(id).enqueue(callBack);
return callBack;
}
public WooLiveData<List<Order>> orders() {
final WooLiveData<List<Order>> callBack = new WooLiveData();
woocommerce.OrderRepository().orders().enqueue(callBack);
return callBack;
}
public WooLiveData<List<Order>> orders(OrderFilter orderFilter) {
final WooLiveData<List<Order>> callBack = new WooLiveData();
woocommerce.OrderRepository().orders(orderFilter).enqueue(callBack);
return callBack;
}
public WooLiveData<Order> update(int id, Order order) {
final WooLiveData<Order> callBack = new WooLiveData();
woocommerce.OrderRepository().update(id, order).enqueue(callBack);
return callBack;
}
public WooLiveData<Order> delete(int id) {
final WooLiveData<Order> callBack = new WooLiveData();
woocommerce.OrderRepository().delete(id).enqueue(callBack);
return callBack;
}
public WooLiveData<Order> delete(int id, boolean force) {
final WooLiveData<Order> callBack = new WooLiveData();
woocommerce.OrderRepository().delete(id, force).enqueue(callBack);
return callBack;
}
} }

View File

@ -0,0 +1,125 @@
package me.gilo.raison.ui.user.onboarding
import android.arch.lifecycle.Observer
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.support.v4.content.ContextCompat.startActivity
import android.widget.Toast
import io.github.inflationx.viewpump.ViewPumpContextWrapper
import kotlinx.android.synthetic.main.content_sign_in.*
import me.gilo.wc.R
import me.gilo.wc.common.BaseActivity
import me.gilo.wc.common.Status
import me.gilo.wc.ui.home.HomeActivity
import me.gilo.wc.ui.state.ProgressDialogFragment
import me.gilo.wc.viewmodels.UserViewModel
import org.json.JSONObject
import java.util.regex.Matcher
import java.util.regex.Pattern
class SignInActivity : BaseActivity() {
lateinit var viewModel : UserViewModel
val TAG = this::getLocalClassName
private lateinit var progressDialog: ProgressDialogFragment
private val pattern = Pattern.compile(EMAIL_PATTERN)
private var matcher: Matcher? = null
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sign_in)
viewModel = getViewModel(UserViewModel::class.java)
title = "Sign In"
flSignIn.setOnClickListener{
login()
}
tvSignUp.setOnClickListener{startActivity(Intent(baseContext, SignUpActivity::class.java))}
}
private fun login() {
if (validates()) {
val email = etEmail.text.toString()
val password = etPassword.text.toString()
viewModel.login(email, password).observe(this, Observer {
response->
when (response!!.status()){
Status.LOADING ->{
showLoading("Performing log in", "This will only take a short while")
}
Status.SUCCESS ->{
stopShowingLoading()
startActivity(Intent(baseContext, HomeActivity::class.java))
}
Status.ERROR ->{
stopShowingLoading()
Toast.makeText(baseContext, "Something went wrong", Toast.LENGTH_LONG).show()
}
Status.EMPTY ->{
stopShowingLoading()
}
}
})
} else {
Toast.makeText(this, "Please correct the information entered", Toast.LENGTH_SHORT).show()
}
}
private fun validates(): Boolean {
var validation = true
tilEmail.isErrorEnabled = false
tilPassword.isErrorEnabled = false
val email = tilEmail.editText!!.text.toString()
if (email.isEmpty()) {
tilEmail.error = "This cannot be left blank!"
validation = false
}
return validation
}
private fun validateEmail(email: String): Boolean {
matcher = pattern.matcher(email)
return matcher!!.matches()
}
private fun showLoading(title: String, message: String) {
val manager = supportFragmentManager
progressDialog = ProgressDialogFragment.newInstance(title, message)
progressDialog.isCancelable = false
progressDialog.show(manager, "progress")
}
private fun stopShowingLoading() {
progressDialog.dismiss()
}
companion object {
private const val EMAIL_PATTERN = "^[a-zA-Z0-9#_~!$&'()*+,;=:.\"(),:;<>@\\[\\]\\\\]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$"
}
}

View File

@ -0,0 +1,204 @@
package me.gilo.raison.ui.user.onboarding
import android.arch.lifecycle.Observer
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.support.v4.content.ContextCompat.startActivity
import android.widget.Toast
import io.github.inflationx.viewpump.ViewPumpContextWrapper
import kotlinx.android.synthetic.main.content_sign_up.*
import me.gilo.wc.R
import me.gilo.wc.common.BaseActivity
import me.gilo.wc.common.Status
import me.gilo.wc.models.User
import me.gilo.wc.ui.home.HomeActivity
import me.gilo.wc.ui.state.ProgressDialogFragment
import me.gilo.wc.viewmodels.UserViewModel
import java.util.regex.Matcher
import java.util.regex.Pattern
class SignUpActivity : BaseActivity() {
lateinit var viewModel : UserViewModel
val TAG = this::getLocalClassName
private lateinit var progressDialog: ProgressDialogFragment
private val pattern = Pattern.compile(EMAIL_PATTERN)
private var matcher: Matcher? = null
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sign_up)
viewModel = getViewModel(UserViewModel::class.java)
title = "Sign Up"
flSignup.setOnClickListener{
signUp()
}
}
private fun signUp() {
if (validates()) {
val email = etEmail.text.toString()
val firstName = etFirstName.text.toString()
val lastName = etLastName.text.toString()
val password = etPassword.text.toString()
var user = User()
user.email = email
user.firstname = firstName
user.lastname = lastName
viewModel.signUp(email, password).observe(this, Observer {
response->
when (response!!.status()){
Status.LOADING ->{
showLoading("Uploading account details", "This will only take a short while")
}
Status.SUCCESS ->{
stopShowingLoading()
startActivity(Intent(baseContext, HomeActivity::class.java))
}
Status.ERROR ->{
stopShowingLoading()
Toast.makeText(baseContext, response.error().message.toString(), Toast.LENGTH_LONG).show()
}
Status.EMPTY ->{
}
}
})
} else {
Toast.makeText(this, "Please correct the information entered", Toast.LENGTH_SHORT).show()
}
}
private fun sendDetails() {
if (validates()) {
val email = etEmail.text.toString()
val firstName = etFirstName.text.toString()
val lastName = etLastName.text.toString()
var user = User()
user.email = email
user.firstname = firstName
user.lastname = lastName
viewModel.updateUser(user).observe(this, Observer {
response->
when (response!!.status()){
Status.LOADING ->{
showLoading("Uploading account details", "This will only take a short while")
}
Status.SUCCESS ->{
stopShowingLoading()
startActivity(Intent(baseContext, HomeActivity::class.java))
}
Status.ERROR ->{
stopShowingLoading()
Toast.makeText(baseContext, response.error().message.toString(), Toast.LENGTH_LONG).show()
}
Status.EMPTY ->{
}
}
})
} else {
Toast.makeText(this, "Please correct the information entered", Toast.LENGTH_SHORT).show()
}
}
private fun validates(): Boolean {
tilEmail.isErrorEnabled = false
tilFirstName.isErrorEnabled = false
tilLastName.isErrorEnabled = false
tilPassword.isErrorEnabled = false
tilPasswordVerify.isErrorEnabled = false
var validation = true
val email = tilEmail.editText!!.text.toString()
val firstName = etFirstName.text.toString()
val lastName = etLastName.text.toString()
val password = etPassword.text.toString()
val passwordVerify = etPasswordVerify.text.toString()
if (!validateEmail(email)) {
tilEmail.error = "Not a valid email address!"
validation = false
}
if (firstName.isEmpty()) {
tilFirstName.error = "Please fill this"
validation = false
}
if (lastName.isEmpty()) {
tilLastName.error = "Please fill this"
validation = false
}
if (password.isEmpty()) {
tilPassword.error = "Please fill this"
validation = false
}
if (passwordVerify.isEmpty()) {
tilPasswordVerify.error = "Please fill this"
validation = false
}
if (passwordVerify != password) {
tilPasswordVerify.error = "Passwords do not match"
validation = false
}
return validation
}
private fun validateEmail(email: String): Boolean {
matcher = pattern.matcher(email)
return matcher!!.matches()
}
private fun showLoading(title: String, message: String) {
val manager = supportFragmentManager
progressDialog = ProgressDialogFragment.newInstance(title, message)
progressDialog.isCancelable = false
progressDialog.show(manager, "progress")
}
private fun stopShowingLoading() {
progressDialog.dismiss()
}
companion object {
private const val EMAIL_PATTERN = "^[a-zA-Z0-9#_~!$&'()*+,;=:.\"(),:;<>@\\[\\]\\\\]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*$"
}
}

View File

@ -0,0 +1,19 @@
package me.gilo.wc.ui.order
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import me.gilo.wc.R
import kotlinx.android.synthetic.main.activity_my_orders.*
class MyOrdersActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my_orders)
setSupportActionBar(toolbar)
}
}

View File

@ -0,0 +1,58 @@
package me.gilo.wc.viewmodels;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import me.gilo.wc.common.CompletionGenericLiveData;
import me.gilo.wc.common.CompletionLiveData;
import me.gilo.wc.common.DocumentLiveData;
import me.gilo.wc.models.User;
import me.gilo.wc.repo.FirebaseUserRepository;
import javax.inject.Inject;
public final class UserViewModel extends ViewModel {
private final MutableLiveData<String> id = new MutableLiveData<>();
private final FirebaseUserRepository firebaseUserRepository;
@Inject
UserViewModel(FirebaseUserRepository firebaseUserRepository) {
this.firebaseUserRepository = firebaseUserRepository;
}
public CompletionGenericLiveData<AuthResult> login(String username, String password) {
return firebaseUserRepository.login(username, password);
}
public CompletionGenericLiveData<AuthResult> firebaseLogin(String email, String password) {
return firebaseUserRepository.login(email, password);
}
public CompletionGenericLiveData<AuthResult> signUp(String email, String password) {
return firebaseUserRepository.signUp(email, password);
}
public CompletionLiveData addUser(User user, OnSuccessListener successListener, OnFailureListener failureListener) {
return firebaseUserRepository.addUser(user, successListener, failureListener);
}
public DocumentLiveData<User> user(String user_id) {
return firebaseUserRepository.user(user_id);
}
public DocumentLiveData<User> user() {
return firebaseUserRepository.user();
}
public CompletionLiveData updateUser(User user) {
user.setId(FirebaseAuth.getInstance().getCurrentUser().getUid());
return firebaseUserRepository.update(user);
}
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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"
tools:context=".ui.order.MyOrdersActivity">
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_my_orders"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email"/>
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
>
<include layout="@layout/content_sign_in" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
>
<include layout="@layout/content_sign_up" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_my_orders"
tools:context=".ui.order.MyOrdersActivity">
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:attrs="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:orientation="vertical"
android:background="@color/bg"
tools:ignore="MissingPrefix"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
fontPath="@string/font_medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_marginLeft="16dp"
android:layout_marginTop="40dp"
android:layout_marginRight="16dp"
android:text="Login"
android:textColor="@color/text_black_2"
android:textSize="20sp"
/>
<TextView
fontPath="@string/font_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="4dp"
android:text="Welcome, Enter you login details to enter"
android:maxLines="6"
android:lineSpacingMultiplier="1.2"
android:textColor="@color/text_black_9"
android:textSize="16sp"
/>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/rect_white"
android:elevation="2dp"
android:layout_margin="16dp"
android:padding="16dp">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#9e9e9e"
android:id="@+id/tilEmail"
android:theme="@style/OnboardingTextLabel"
android:visibility="visible">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email or Phone"
android:id="@+id/etEmail"
android:inputType="textEmailAddress"
android:paddingBottom="16dp"
android:textColor="#5f6368"
android:textColorHint="#9e9e9e"
android:textSize="16sp"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textColorHint="#9e9e9e"
android:id="@+id/tilPassword"
android:theme="@style/OnboardingTextLabel"
android:visibility="visible">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:id="@+id/etPassword"
android:inputType="textPassword"
android:paddingBottom="16dp"
android:textColor="#5f6368"
android:textColorHint="#9e9e9e"
android:textSize="16sp"
/>
</android.support.design.widget.TextInputLayout>
<TextView
fontPath="@string/font_regular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginBottom="16dp"
android:gravity="center"
android:id="@+id/tvSignUp"
android:lineSpacingMultiplier="1.2"
android:text="Don't have an account? Sign up."
android:textColor="@color/text_black_9"
android:textSize="16sp"
tools:ignore="MissingPrefix"/>
<TextView
fontPath="@string/font_regular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="16dp"
android:gravity="center"
android:id="@+id/tvForgotPassword"
android:lineSpacingMultiplier="1.2"
android:text="Forgot password?"
android:textColor="@color/text_black_9"
android:textSize="16sp"
tools:ignore="MissingPrefix"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:orientation="horizontal"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingRight="16dp"
android:layout_margin="16dp"
android:gravity="center"
android:elevation="2dp"
android:id="@+id/flSignIn"
>
<TextView
android:id="@+id/bNext"
fontPath="@string/font_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@color/colorPrimary"
android:text="Login"
android:padding="12dp"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="16sp"
tools:ignore="MissingPrefix"/>
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@drawable/ic_action_navigation_arrow_back_inverted"
android:tint="#ffffff"
android:layout_gravity="right|center"
android:rotation="180"
/>
</FrameLayout>
</LinearLayout>

View File

@ -0,0 +1,236 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:attrs="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:orientation="vertical"
android:background="@color/bg"
tools:ignore="MissingPrefix"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
fontPath="@string/font_medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_marginLeft="16dp"
android:layout_marginTop="40dp"
android:layout_marginRight="16dp"
android:text="Create account"
android:textColor="@color/text_black_2"
android:textSize="20sp"
/>
<TextView
fontPath="@string/font_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="4dp"
android:text="Register to keep track of your wishlists, cart and orders."
android:maxLines="6"
android:lineSpacingMultiplier="1.2"
android:textColor="@color/text_black_9"
android:textSize="16sp"/>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/rect_white"
android:elevation="2dp"
android:layout_margin="16dp"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.design.widget.TextInputLayout
android:id="@+id/tilFirstName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColorHint="#9e9e9e"
android:theme="@style/OnboardingTextLabel"
android:visibility="visible">
<EditText
android:id="@+id/etFirstName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="First name"
android:inputType="textPersonName"
android:paddingBottom="16dp"
android:textColor="#5f6368"
android:textColorHint="#9e9e9e"
android:textSize="16sp"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/tilLastName"
android:textColorHint="#9e9e9e"
android:theme="@style/OnboardingTextLabel"
android:visibility="visible">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Last name"
android:id="@+id/etLastName"
android:inputType="textPersonName"
android:paddingBottom="16dp"
android:textColor="#5f6368"
android:textColorHint="#9e9e9e"
android:textSize="16sp"
/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textColorHint="#9e9e9e"
android:id="@+id/tilEmail"
android:theme="@style/OnboardingTextLabel"
android:visibility="visible">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:id="@+id/etEmail"
android:inputType="textEmailAddress"
android:paddingBottom="16dp"
android:textColor="#5f6368"
android:textColorHint="#9e9e9e"
android:textSize="16sp"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textColorHint="#9e9e9e"
android:id="@+id/tilPassword"
android:theme="@style/OnboardingTextLabel"
android:visibility="visible">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:id="@+id/etPassword"
android:inputType="textPassword"
android:paddingBottom="16dp"
android:textColor="#5f6368"
android:textColorHint="#9e9e9e"
android:textSize="16sp"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textColorHint="#9e9e9e"
android:id="@+id/tilPasswordVerify"
android:theme="@style/OnboardingTextLabel"
android:visibility="visible">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Verify Password"
android:id="@+id/etPasswordVerify"
android:inputType="textPassword"
android:paddingBottom="16dp"
android:textColor="#5f6368"
android:textColorHint="#9e9e9e"
android:textSize="16sp"
/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:orientation="horizontal"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingRight="16dp"
android:layout_margin="16dp"
android:gravity="center"
android:elevation="2dp"
android:id="@+id/flSignup"
>
<TextView
android:id="@+id/bNext"
fontPath="@string/font_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@color/colorPrimary"
android:text="Create Account"
android:padding="12dp"
android:gravity="center"
android:textAllCaps="false"
android:textColor="#ffffff"
android:textSize="16sp"
tools:ignore="MissingPrefix"/>
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@drawable/ic_action_navigation_arrow_back_inverted"
android:tint="#ffffff"
android:layout_gravity="right|center"
android:rotation="180"
/>
</FrameLayout>
</LinearLayout>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingPrefix">
<TextView
android:id="@+id/tvTitle"
fontPath="@string/font_regular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:gravity="left"
android:textColor="@color/text_black_4"
android:textSize="16sp"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/bg"
/>
</LinearLayout>

View File

@ -31,5 +31,6 @@
<string name="title_activity_category">CategoryActivity</string> <string name="title_activity_category">CategoryActivity</string>
<string name="title_activity_home">HomeActivity</string> <string name="title_activity_home">HomeActivity</string>
<string name="lorem">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s</string> <string name="lorem">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s</string>
<string name="title_activity_my_orders">MyOrdersActivity</string>
</resources> </resources>

View File

@ -11,6 +11,43 @@
<item name="android:spinnerItemStyle">@style/SpinnerItemStyle</item> <item name="android:spinnerItemStyle">@style/SpinnerItemStyle</item>
</style> </style>
<style name="OnboardingTextLabel" parent="AppTheme">
<!-- Hint color and label color in FALSE state -->
<item name="android:textColorHint">#9e9e9e</item>
<item name="android:textSize">14sp</item>
<item name="colorAccent">#9e9e9e</item>
<item name="colorControlNormal">#212121</item>
<item name="colorControlHighlight">#5f6368</item>
<item name="colorControlActivated">#5f6368</item>
<item name="hintTextAppearance">@style/AppTheme.TextFloatLabelAppearance</item>
<item name="errorTextAppearance">@style/AppTheme.TextErrorAppearance</item>
<item name="counterTextAppearance">@style/TextAppearance.Design.Counter</item>
<item name="counterOverflowTextAppearance">@style/TextAppearance.Design.Counter.Overflow
</item>
</style>
<style name="Widget.Design.TextInputLayout" parent="AppTheme">
<item name="hintTextAppearance">@style/AppTheme.TextFloatLabelAppearance</item>
<item name="errorTextAppearance">@style/AppTheme.TextErrorAppearance</item>
<item name="counterTextAppearance">@style/TextAppearance.Design.Counter</item>
<item name="counterOverflowTextAppearance">@style/TextAppearance.Design.Counter.Overflow
</item>
</style>
<style name="AppTheme.TextFloatLabelAppearance" parent="TextAppearance.Design.Hint">
<!-- Floating label appearance here -->
<item name="android:textColor">#9e9e9e</item>
<item name="android:textSize">14sp</item>
</style>
<style name="AppTheme.TextErrorAppearance" parent="TextAppearance.Design.Error">
<!-- Error message appearance here -->
<item name="android:textColor">#f95133</item>
<item name="android:textSize">14sp</item>
</style>
<style name="AppTheme.NoActionBar"> <style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>

View File

@ -8,8 +8,9 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.0-alpha07' classpath 'com.android.tools.build:gradle:3.5.0-alpha08'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.0.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }

View File

@ -1,6 +1,6 @@
#Mon Mar 18 05:31:54 EAT 2019 #Fri Mar 29 07:25:52 EAT 2019
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-rc-2-all.zip