Change login and whole API handling to rxjava

This commit is contained in:
Mieszko 2018-08-30 10:04:37 +02:00
parent 56b472887c
commit e36eb8bf0d
31 changed files with 491 additions and 180 deletions

View File

@ -30,11 +30,19 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation "io.swagger:swagger-annotations:1.5.15"
implementation "org.threeten:threetenbp:1.3.5"
implementation "com.squareup.okhttp3:logging-interceptor:3.10.0"
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:6.4.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation "com.jakewharton:butterknife:8.8.1"
annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"
implementation "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0"
implementation "com.squareup.okhttp3:okhttp:3.11.0"
implementation "com.squareup.okhttp3:okhttp-urlconnection:3.10.0"
implementation "com.squareup.okhttp3:logging-interceptor:3.11.0"
}

View File

@ -8,7 +8,8 @@
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application

View File

@ -4,11 +4,9 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
@ -34,13 +32,17 @@ import android.widget.TextView;
import com.uam.wmi.findmytutor.R;
import com.uam.wmi.findmytutor.model.JwtToken;
import com.uam.wmi.findmytutor.model.LdapUser;
import com.uam.wmi.findmytutor.network.RetrofitClientInstance;
import com.uam.wmi.findmytutor.network.ApiClient;
import com.uam.wmi.findmytutor.service.LdapService;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Response;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;
import static android.Manifest.permission.READ_CONTACTS;
@ -309,40 +311,42 @@ public class LoginActivity extends AppCompatActivity implements LoaderCallbacks<
private final String mEmail;
private final String mPassword;
private LdapService ldapService;
private CompositeDisposable disposable = new CompositeDisposable();
private Boolean isAuthorizate;
// Constructor
UserLoginTask(String email, String password) {
mEmail = email;
mPassword = password;
this.ldapService = ApiClient.getClient(getApplicationContext())
.create(LdapService.class);
this.isAuthorizate = false;
}
@Override
protected Boolean doInBackground(Void... params) {
LdapService service = RetrofitClientInstance.createService(LdapService.class);
LdapUser user = new LdapUser("string",mPassword,"string","tutor","string","string",mEmail);
LdapUser user = new LdapUser("string",mPassword,"string","string","string","string",mEmail);
Log.e("Login", "jwt token: " + user);
try {
Response<JwtToken> loginResponse = service.fakeValidate(user).execute();
Log.e("Login", "jwt token: " + loginResponse.body());
if (loginResponse.isSuccessful()) {
String authToken = loginResponse.body().getToken();
Log.e("Login", "jwt token: " + authToken);
SharedPreferences sharedPref = getSharedPreferences("fmtPrefs", Context.MODE_PRIVATE);
sharedPref.edit().putString("authToken", authToken).putBoolean("loggedIn", true).apply();
disposable.add(
ldapService
.fakeValidate(user)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<JwtToken>() {
@Override
public void onSuccess(JwtToken jwtToken) {
PrefUtils.storeApiKey(getApplicationContext(), jwtToken.getToken());
onPostExecute(true);
}
@Override
public void onError(Throwable e) {
Log.e("LoginError", "onError: " + e.getMessage());
}
}));
return true;
}
} catch (Exception e) {
Log.e("Login error", "Something went wrong while logging in...");
return false;
}
return false;
}
@Override
@ -361,6 +365,7 @@ public class LoginActivity extends AppCompatActivity implements LoaderCallbacks<
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
@Override

View File

@ -6,24 +6,17 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.uam.wmi.findmytutor.R;
import com.uam.wmi.findmytutor.model.Coordinate;
import com.uam.wmi.findmytutor.network.RetrofitClientInstance;
import com.uam.wmi.findmytutor.service.Coordinates;
import com.uam.wmi.findmytutor.network.ApiClient;
import com.uam.wmi.findmytutor.service.CoordinateService;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private MapView mapView;
@ -62,46 +55,10 @@ public class MainActivity extends AppCompatActivity {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
final SharedPreferences sharedPref = getSharedPreferences("fmtPrefs", Context.MODE_PRIVATE);
final String authToken = sharedPref.getString("authToken",null);
Coordinates service = RetrofitClientInstance.createService(Coordinates.class,authToken);
Call<List<Coordinate>> call = service.getOnlineCoordinates();
CoordinateService service = ApiClient.getClient(getApplicationContext())
.create(CoordinateService.class);
call.enqueue(new Callback<List<Coordinate>>() {
@Override
public void onResponse(Call<List<Coordinate>> call, Response<List<Coordinate>> response) {
Log.e("MainActivity", "rsp: " + response.body());
setCoordinates(response.body());
/* mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap,List<Coordinate> response) {
// Add the custom icon marker to the map
for(Coordinate coord: response.body()){
mapboxMap.addMarker(new MarkerOptions()
.position(new LatLng(coord.getLatitude(), coord.getLongitude()))
}
}
});*/
}
@Override
public void onFailure(Call<List<Coordinate>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Something went wrong...Error message: " + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}

View File

@ -0,0 +1,9 @@
package com.uam.wmi.findmytutor.model;
public class BaseResponse {
String error;
public String getError() {
return error;
}
}

View File

@ -11,7 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
* Coordinate
*/
public class Coordinate {
public class Coordinate extends BaseResponse{
@SerializedName("coordinateId")
private UUID coordinateId = null;

View File

@ -11,7 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
* DutyHour
*/
public class DutyHour {
public class DutyHour extends BaseResponse {
@SerializedName("dutyHourId")
private UUID dutyHourId = null;

View File

@ -3,7 +3,7 @@ package com.uam.wmi.findmytutor.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class IsUsingListBool {
public class IsUsingListBool extends BaseResponse{
@SerializedName("isUsing")
@Expose

View File

@ -10,7 +10,7 @@ import io.swagger.annotations.ApiModelProperty;
* IsUsingListBoolModel
*/
public class IsUsingListBoolModel {
public class IsUsingListBoolModel extends BaseResponse {
@SerializedName("isUsing")
private Boolean isUsing = null;

View File

@ -11,7 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
* LdapUser
*/
public class LdapUser {
public class LdapUser extends BaseResponse{
@SerializedName("login")
private String login = null;

View File

@ -0,0 +1,16 @@
package com.uam.wmi.findmytutor.model;
import com.google.gson.annotations.SerializedName;
public class Model
{
@SerializedName("data")
private PagedResult data;
public PagedResult getData ()
{
return data;
}
}

View File

@ -1,14 +1,15 @@
package com.uam.wmi.findmytutor.model;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class PagedResult {
@SerializedName("results")
@Expose
private List<Result> results = null;
private List<User> results = null;
@SerializedName("currentPage")
@Expose
private Integer currentPage;
@ -28,11 +29,11 @@ public class PagedResult {
@Expose
private Integer lastRowOnPage;
public List<Result> getResults() {
public List<User> getResults() {
return results;
}
public void setResults(List<Result> results) {
public void setResults(List<User> results) {
this.results = results;
}

View File

@ -12,7 +12,7 @@ import io.swagger.annotations.ApiModelProperty;
* PagedResultUserResponseModel
*/
public class PagedResultUserResponseModel {
public class PagedResultUserResponseModel extends BaseResponse {
@SerializedName("results")
private List<UserResponseModel> results = null;

View File

@ -1,9 +1,10 @@
package com.uam.wmi.findmytutor.model;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Result {
import java.util.List;
public class Result extends BaseResponse {
@SerializedName("id")
@Expose

View File

@ -11,7 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
* StudentIdModel
*/
public class StudentIdModel {
public class StudentIdModel extends BaseResponse{
@SerializedName("studentId")
private String studentId = null;

View File

@ -15,7 +15,7 @@ import io.swagger.annotations.ApiModelProperty;
* TutorTab
*/
public class TutorTab {
public class TutorTab extends BaseResponse{
@SerializedName("tutorTabId")
private UUID tutorTabId = null;

View File

@ -15,7 +15,7 @@ import io.swagger.annotations.ApiModelProperty;
* User
*/
public class User {
public class User extends BaseResponse{
@SerializedName("isOnline")
private Boolean isOnline = null;

View File

@ -12,7 +12,7 @@ import io.swagger.annotations.ApiModelProperty;
* UserResponseModel
*/
public class UserResponseModel {
public class UserResponseModel extends BaseResponse{
@SerializedName("id")
private String id = null;

View File

@ -0,0 +1,75 @@
package com.uam.wmi.findmytutor.network;
import android.content.Context;
import android.text.TextUtils;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiClient {
private static Retrofit retrofit = null;
private static int REQUEST_TIMEOUT = 60;
private static OkHttpClient okHttpClient;
private static final String BASE_URL = "https://s416084.projektstudencki.pl/develop/";
public static Retrofit getClient(Context context) {
if (okHttpClient == null)
initOkHttp(context);
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
private static void initOkHttp(final Context context) {
OkHttpClient.Builder httpClient = new OkHttpClient().newBuilder()
.connectTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS);
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(interceptor);
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json");
// Adding Authorization token (API Key)
// Requests will be denied without API key
if (!TextUtils.isEmpty(PrefUtils.getApiKey(context))) {
requestBuilder.addHeader("Authorization", PrefUtils.getApiKey(context));
}
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
okHttpClient = httpClient.build();
}
};

View File

@ -1,51 +0,0 @@
package com.uam.wmi.findmytutor.network;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClientInstance {
private static final String BASE_URL = "https://s416084.projektstudencki.pl/develop/";
private static Retrofit.Builder builder
= new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
private static Retrofit retrofit = builder.build();
private static OkHttpClient.Builder httpClient
= new OkHttpClient.Builder();
private static HttpLoggingInterceptor logging
= new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BASIC);
public static <S> S createService(Class<S> serviceClass) {
if (!httpClient.interceptors().contains(logging)) {
httpClient.addInterceptor(logging);
builder.client(httpClient.build());
retrofit = builder.build();
}
return retrofit.create(serviceClass);
}
public static <S> S createService(Class<S> serviceClass, final String token) {
if (token != null) {
httpClient.interceptors().clear();
httpClient.addInterceptor(chain -> {
Request original = chain.request();
Request.Builder builder1 = original.newBuilder()
.header("Authorization", "Bearer " + token);
Request request = builder1.build();
return chain.proceed(request);
});
builder.client(httpClient.build());
retrofit = builder.build();
}
return retrofit.create(serviceClass);
}
}

View File

@ -13,7 +13,7 @@ import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;
public interface Coordinates {
public interface CoordinateService {
@GET("api/coordinates")
Call<List<Coordinate>> getAllCoordinates();

View File

@ -3,7 +3,7 @@ package com.uam.wmi.findmytutor.service;
import com.uam.wmi.findmytutor.model.JwtToken;
import com.uam.wmi.findmytutor.model.LdapUser;
import retrofit2.Call;
import io.reactivex.Single;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
@ -12,15 +12,15 @@ import retrofit2.http.Path;
public interface LdapService {
@POST("api/ldap/fakeValidate")
Call<JwtToken> fakeValidate(@Body LdapUser user);
Single<JwtToken> fakeValidate(@Body LdapUser user);
@POST("api/ldap/validate")
Call<JwtToken> validate(@Body LdapUser user);
Single<JwtToken> validate(@Body LdapUser user);
@GET("api/ldap/getUserData/{login}")
Call<LdapUser> getUserDataByLogin(@Path("login") String userLogin);
Single<LdapUser> getUserDataByLogin(@Path("login") String userLogin);
@GET("api/ldap/getUserData/email/{email}")
Call<LdapUser> getUserDataByMail(@Path("email") String userMail);
Single<LdapUser> getUserDataByMail(@Path("email") String userMail);
}

View File

@ -1,77 +1,77 @@
package com.uam.wmi.findmytutor.service;
import com.uam.wmi.findmytutor.model.JwtToken;
import com.uam.wmi.findmytutor.model.PagedResult;
import com.uam.wmi.findmytutor.model.User;
import com.uam.wmi.findmytutor.model.IsUsingListBool;
import com.uam.wmi.findmytutor.model.PagedResult;
import com.uam.wmi.findmytutor.model.StudentIdModel;
import com.uam.wmi.findmytutor.model.User;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import io.reactivex.Completable;
import io.reactivex.Single;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.PUT;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;
import retrofit2.http.Header;
public interface UserService {
@GET("api/users")
Call<List<User>> getAllUsers();
Single <List<User>> getAllUsers();
@POST("api/users")
Call<ResponseBody> createUser(@Body User user);
Completable createUser(@Body User user);
@GET("api/users/page/{pageNum}")
Call<PagedResult> getPagedUsers(@Path("pageNum") String pageNum );
Single <PagedResult> getPagedUsers(@Path("pageNum") String pageNum );
@GET("/api/users/tutors/page/{pageNum}")
Call<PagedResult> getPagedTutors(@Path("pageNum") String pageNum);
@GET("api/users/tutors/page/{pageNum}")
Single <PagedResult> getPagedTutors(@Path("pageNum") String pageNum);
@GET("/api/users/students/page/{pageNum}")
Call<PagedResult> getPagedStudents(@Path("pageNum") String pageNum);
@GET("api/users/students/page/{pageNum}")
Single<PagedResult> getPagedStudents(@Path("pageNum") String pageNum);
@GET("api/users/{id}")
Call<User> getUserByID(@Path("id") String userID);
Single<User> getUserByID(@Path("id") String userID);
@PUT("api/users/{id}")
Call<User> updateUserByID(@Path("id") String userID, @Body User user);
Completable updateUserByID(@Path("id") String userID, @Body User user);
@DELETE("api/users/{id}")
Call<User> deleteUserByID(@Path("id") String userID);
Completable deleteUserByID(@Path("id") String userID);
@GET("api/users/userLogin/{ldapLogin}")
Call<String> getUserLdapLogin(@Path("ldapLogin") String ldapLogin);
Single<String> getUserLdapLogin(@Path("ldapLogin") String ldapLogin);
@PUT("api/users/setActive/{userID}")
Call<User> setUserActive(@Path("userID") String userID);
Completable setUserActive(@Path("userID") String userID);
@PUT("api/users/setInActive/{userID}")
Call<User> setUserInActive(@Path("userID") String userID);
Completable setUserInActive(@Path("userID") String userID);
@GET("api/users/blacklist/{tutorID}")
Call<List<User>> getTutorBlacklistedByID(@Path("tutorID") String tutorID);
Single<List<User>> getTutorBlacklistedByID(@Path("tutorID") String tutorID);
@PUT("api/users/blacklist/{tutorID}")
Call<User> setTutorBlacklist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing);
Completable setTutorBlacklist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing);
@POST("api/users/blacklist/{tutorID}")
Call<ResponseBody> addStudentToBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
Completable addStudentToBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
@DELETE("api/users/blacklist/{tutorID}")
Call<List<User>> removeStudentFromBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
Completable removeStudentFromBlacklist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
@GET("api/users/whitelist/{tutorID}")
Call<List<User>> getTutorwhitelistedByID(@Path("tutorID") String tutorID);
Single<List<User>> getTutorwhitelistedByID(@Path("tutorID") String tutorID);
@PUT("api/users/whitelist/{tutorID}")
Call<User> setTutorWhitelist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing);
Completable setTutorWhitelist(@Path("tutorID") String tutorID, @Body IsUsingListBool isUsing);
@POST("api/users/whitelist/{tutorID}")
Call<ResponseBody> addStudentTowhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
Completable addStudentTowhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
@DELETE("api/users/whitelist/{tutorID}")
Call<List<User>> removeStudentFromWhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
Completable removeStudentFromWhitelist(@Path("tutorID") String tutorID, @Body StudentIdModel student);
}

View File

@ -0,0 +1,98 @@
package com.uam.wmi.findmytutor.utils;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;
public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
private Context context;
private int margin;
public MyDividerItemDecoration(Context context, int orientation, int margin) {
this.context = context;
this.margin = margin;
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left + dpToPx(margin), top, right - dpToPx(margin), bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top + dpToPx(margin), right, bottom - dpToPx(margin));
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
private int dpToPx(int dp) {
Resources r = context.getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
}

View File

@ -0,0 +1,27 @@
package com.uam.wmi.findmytutor.utils;
import android.content.Context;
import android.content.SharedPreferences;
public class PrefUtils {
/**
* Storing API Key in shared preferences to
* add it in header part of every retrofit request
*/
public PrefUtils() {
}
private static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences("APP_PREF", Context.MODE_PRIVATE);
}
public static void storeApiKey(Context context, String apiKey) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putString("API_KEY", apiKey);
editor.commit();
}
public static String getApiKey(Context context) {
return getSharedPreferences(context).getString("API_KEY", null);
}
}

View File

@ -0,0 +1,54 @@
package com.uam.wmi.findmytutor.utils;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private ClickListener clicklistener;
private GestureDetector gestureDetector;
public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener) {
this.clicklistener = clicklistener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recycleView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clicklistener != null) {
clicklistener.onLongClick(child, recycleView.getChildAdapterPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clicklistener != null && gestureDetector.onTouchEvent(e)) {
clicklistener.onClick(child, rv.getChildAdapterPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
public interface ClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp"
android:clickable="true"
android:paddingBottom="@dimen/dimen_10"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingTop="@dimen/dimen_10">
<TextView
android:id="@+id/firstName"
android:layout_width="match_parent"
android:layout_height="14dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="13dp"
android:textColor="@color/note_list_text"
android:textSize="@dimen/note_list_text" />
<TextView
android:id="@+id/lastName"
android:layout_width="match_parent"
android:layout_height="14dp"
android:layout_below="@+id/firstName"
android:layout_centerHorizontal="true"
android:textColor="@color/note_list_text"
android:textSize="@dimen/note_list_text" />
<TextView
android:id="@+id/isOnline"
android:layout_width="match_parent"
android:layout_height="14dp"
android:layout_below="@+id/lastName"
android:layout_centerHorizontal="true"
android:textColor="@color/note_list_text"
android:textSize="@dimen/note_list_text" />
</RelativeLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="mdcolor_400">
<item name="red_400" type="color">#e84e40</item>
<item name="pink_400" type="color">#ec407a</item>
<item name="purple_400" type="color">#ab47bc</item>
<item name="deep_purple_400" type="color">#7e57c2</item>
<item name="indigo_400" type="color">#5c6bc0</item>
<item name="blue_400" type="color">#738ffe</item>
<item name="light_blue_400" type="color">#29b6f6</item>
<item name="cyan_400" type="color">#26c6da</item>
<item name="teal_400" type="color">#26a69a</item>
<item name="green_400" type="color">#2baf2b</item>
<item name="light_green_400" type="color">#9ccc65</item>
<item name="lime_400" type="color">#d4e157</item>
<item name="yellow_400" type="color">#ffee58</item>
<item name="orange_400" type="color">#ffa726</item>
<item name="deep_orange_400" type="color">#ff7043</item>
<item name="brown_400" type="color">#8d6e63</item>
<item name="grey_400" type="color">#bdbdbd</item>
<item name="blue_grey_400" type="color">#78909c</item>
</array>
<array name="mdcolor_500">
<item name="red_500" type="color">#e51c23</item>
<item name="pink_500" type="color">#e91e63</item>
<item name="purple_500" type="color">#9c27b0</item>
<item name="deep_purple_500" type="color">#673ab7</item>
<item name="indigo_500" type="color">#3f51b5</item>
<item name="blue_500" type="color">#5677fc</item>
<item name="light_blue_500" type="color">#03a9f4</item>
<item name="cyan_500" type="color">#00bcd4</item>
<item name="teal_500" type="color">#009688</item>
<item name="green_500" type="color">#259b24</item>
<item name="light_green_500" type="color">#8bc34a</item>
<item name="lime_500" type="color">#cddc39</item>
<item name="yellow_500" type="color">#ffeb3b</item>
<item name="orange_500" type="color">#ff9800</item>
<item name="deep_orange_500" type="color">#ff5722</item>
<item name="brown_500" type="color">#795548</item>
<item name="grey_500" type="color">#9e9e9e</item>
<item name="blue_grey_500" type="color">#607d8b</item>
</array>
</resources>

View File

@ -3,4 +3,8 @@
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="msg_no_notes">#999</color>
<color name="hint_enter_note">#89c3c3c3</color>
<color name="timestamp">#858585</color>
<color name="note_list_text">#232323</color>
</resources>

View File

@ -3,4 +3,18 @@
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<!-- Tutors list -->
<dimen name="activity_margin">16dp</dimen>
<dimen name="dot_margin_right">10dp</dimen>
<dimen name="msg_no_notes">26sp</dimen>
<dimen name="margin_top_no_notes">120dp</dimen>
<dimen name="lbl_new_note_title">20sp</dimen>
<dimen name="dimen_10">10dp</dimen>
<dimen name="input_new_note">20sp</dimen>
<dimen name="dot_height">10dp</dimen>
<dimen name="dot_text_size">40sp</dimen>
<dimen name="timestamp">14sp</dimen>
<dimen name="note_list_text">13sp</dimen>
</resources>

View File

@ -3,6 +3,13 @@
<string name="title_activity_login">Sign in</string>
<string name="title_activity_startup" translatable="false">StartUp Activity</string>
<!-- Tutors list -->
<string name="action_settings">Settings</string>
<string name="activity_title_home">Notes</string>
<string name="msg_no_notes">No notes found!</string>
<string name="lbl_new_note_title">New Note</string>
<string name="hint_enter_note">Enter your note!</string>
<!-- Strings related to login -->
<string name="prompt_email" translatable="false">Email</string>