├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── info │ │ └── androidhive │ │ └── rxjavaretrofit │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── info │ │ │ └── androidhive │ │ │ └── rxjavaretrofit │ │ │ ├── app │ │ │ └── Const.java │ │ │ ├── network │ │ │ ├── ApiClient.java │ │ │ ├── ApiService.java │ │ │ └── model │ │ │ │ ├── BaseResponse.java │ │ │ │ ├── Note.java │ │ │ │ └── User.java │ │ │ ├── utils │ │ │ ├── MyDividerItemDecoration.java │ │ │ ├── PrefUtils.java │ │ │ └── RecyclerTouchListener.java │ │ │ └── view │ │ │ ├── MainActivity.java │ │ │ └── NotesAdapter.java │ └── res │ │ ├── drawable-hdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-mdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-xxhdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable-xxxhdpi │ │ └── ic_add_white_24dp.png │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── content_main.xml │ │ ├── note_dialog.xml │ │ └── note_list_row.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── array.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── info │ └── androidhive │ └── rxjavaretrofit │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "info.androidhive.rxjavaretrofit" 7 | minSdkVersion 16 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:28.0.0' 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 25 | implementation 'com.android.support:design:28.0.0' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 28 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 29 | 30 | implementation 'com.android.support:recyclerview-v7:28.0.0' 31 | 32 | implementation 'io.reactivex.rxjava2:rxjava:2.1.9' 33 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' 34 | 35 | compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 36 | 37 | // butter knife 38 | implementation "com.jakewharton:butterknife:8.8.1" 39 | annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1" 40 | 41 | implementation "com.squareup.retrofit2:retrofit:2.5.0" 42 | implementation "com.squareup.retrofit2:converter-gson:2.0.0" 43 | implementation "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0" 44 | implementation "com.squareup.okhttp3:okhttp:3.12.0" 45 | implementation "com.squareup.okhttp3:okhttp-urlconnection:3.0.1" 46 | implementation "com.squareup.okhttp3:logging-interceptor:3.4.1" 47 | } 48 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/info/androidhive/rxjavaretrofit/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("info.androidhive.rxjavaretrofit", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/app/Const.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.app; 2 | 3 | /** 4 | * Created by ravi on 20/02/18. 5 | */ 6 | 7 | public class Const { 8 | public static final String BASE_URL = "https://demo.androidhive.info/"; 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/network/ApiClient.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.network; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | 6 | import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 7 | 8 | import java.io.IOException; 9 | import java.util.Collections; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | import info.androidhive.rxjavaretrofit.app.Const; 13 | import info.androidhive.rxjavaretrofit.utils.PrefUtils; 14 | import okhttp3.CipherSuite; 15 | import okhttp3.ConnectionSpec; 16 | import okhttp3.Interceptor; 17 | import okhttp3.OkHttpClient; 18 | import okhttp3.Request; 19 | import okhttp3.Response; 20 | import okhttp3.TlsVersion; 21 | import okhttp3.logging.HttpLoggingInterceptor; 22 | import retrofit2.Retrofit; 23 | import retrofit2.converter.gson.GsonConverterFactory; 24 | 25 | /** 26 | * Created by ravi on 20/02/18. 27 | */ 28 | 29 | public class ApiClient { 30 | private static Retrofit retrofit = null; 31 | private static int REQUEST_TIMEOUT = 60; 32 | private static OkHttpClient okHttpClient; 33 | 34 | public static Retrofit getClient(Context context) { 35 | 36 | if (okHttpClient == null) 37 | initOkHttp(context); 38 | 39 | if (retrofit == null) { 40 | retrofit = new Retrofit.Builder() 41 | .baseUrl(Const.BASE_URL) 42 | .client(okHttpClient) 43 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 44 | .addConverterFactory(GsonConverterFactory.create()) 45 | .build(); 46 | } 47 | return retrofit; 48 | } 49 | 50 | private static void initOkHttp(final Context context) { 51 | OkHttpClient.Builder httpClient = new OkHttpClient().newBuilder() 52 | .connectTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS) 53 | .readTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS) 54 | .writeTimeout(REQUEST_TIMEOUT, TimeUnit.SECONDS); 55 | 56 | HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 57 | interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 58 | 59 | httpClient.addInterceptor(interceptor); 60 | 61 | httpClient.addInterceptor(new Interceptor() { 62 | @Override 63 | public Response intercept(Chain chain) throws IOException { 64 | Request original = chain.request(); 65 | Request.Builder requestBuilder = original.newBuilder() 66 | .addHeader("Accept", "application/json") 67 | .addHeader("Content-Type", "application/json"); 68 | 69 | // Adding Authorization token (API Key) 70 | // Requests will be denied without API key 71 | if (!TextUtils.isEmpty(PrefUtils.getApiKey(context))) { 72 | requestBuilder.addHeader("Authorization", PrefUtils.getApiKey(context)); 73 | } 74 | 75 | Request request = requestBuilder.build(); 76 | return chain.proceed(request); 77 | } 78 | }); 79 | 80 | okHttpClient = httpClient.build(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/network/ApiService.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.network; 2 | 3 | import java.util.List; 4 | 5 | import info.androidhive.rxjavaretrofit.network.model.Note; 6 | import info.androidhive.rxjavaretrofit.network.model.User; 7 | import io.reactivex.Completable; 8 | import io.reactivex.Single; 9 | import retrofit2.http.DELETE; 10 | import retrofit2.http.Field; 11 | import retrofit2.http.FormUrlEncoded; 12 | import retrofit2.http.GET; 13 | import retrofit2.http.POST; 14 | import retrofit2.http.PUT; 15 | import retrofit2.http.Path; 16 | 17 | /** 18 | * Created by ravi on 20/02/18. 19 | */ 20 | 21 | public interface ApiService { 22 | // Register new user 23 | @FormUrlEncoded 24 | @POST("notes/user/register") 25 | Single register(@Field("device_id") String deviceId); 26 | 27 | // Create note 28 | @FormUrlEncoded 29 | @POST("notes/new") 30 | Single createNote(@Field("note") String note); 31 | 32 | // Fetch all notes 33 | @GET("notes/all") 34 | Single> fetchAllNotes(); 35 | 36 | // Update single note 37 | @FormUrlEncoded 38 | @PUT("notes/{id}") 39 | Completable updateNote(@Path("id") int noteId, @Field("note") String note); 40 | 41 | // Delete note 42 | @DELETE("notes/{id}") 43 | Completable deleteNote(@Path("id") int noteId); 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/network/model/BaseResponse.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.network.model; 2 | 3 | /** 4 | * Created by ravi on 21/02/18. 5 | */ 6 | 7 | public class BaseResponse { 8 | String error; 9 | 10 | public String getError() { 11 | return error; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/network/model/Note.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.network.model; 2 | 3 | /** 4 | * Created by ravi on 20/02/18. 5 | */ 6 | 7 | public class Note extends BaseResponse{ 8 | int id; 9 | String note; 10 | String timestamp; 11 | 12 | public int getId() { 13 | return id; 14 | } 15 | 16 | public String getNote() { 17 | return note; 18 | } 19 | 20 | public void setNote(String note) { 21 | this.note = note; 22 | } 23 | 24 | public String getTimestamp() { 25 | return timestamp; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/network/model/User.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.network.model; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Created by ravi on 20/02/18. 7 | */ 8 | 9 | public class User extends BaseResponse { 10 | 11 | @SerializedName("api_key") 12 | String apiKey; 13 | 14 | public String getApiKey() { 15 | return apiKey; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/utils/MyDividerItemDecoration.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.utils; 2 | 3 | /** 4 | * Created by ravi on 18/01/18. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.content.res.Resources; 9 | import android.content.res.TypedArray; 10 | import android.graphics.Canvas; 11 | import android.graphics.Rect; 12 | import android.graphics.drawable.Drawable; 13 | import android.support.v7.widget.LinearLayoutManager; 14 | import android.support.v7.widget.RecyclerView; 15 | import android.util.TypedValue; 16 | import android.view.View; 17 | 18 | 19 | public class MyDividerItemDecoration extends RecyclerView.ItemDecoration { 20 | 21 | private static final int[] ATTRS = new int[]{ 22 | android.R.attr.listDivider 23 | }; 24 | 25 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; 26 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; 27 | 28 | private Drawable mDivider; 29 | private int mOrientation; 30 | private Context context; 31 | private int margin; 32 | 33 | public MyDividerItemDecoration(Context context, int orientation, int margin) { 34 | this.context = context; 35 | this.margin = margin; 36 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 37 | mDivider = a.getDrawable(0); 38 | a.recycle(); 39 | setOrientation(orientation); 40 | } 41 | 42 | public void setOrientation(int orientation) { 43 | if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { 44 | throw new IllegalArgumentException("invalid orientation"); 45 | } 46 | mOrientation = orientation; 47 | } 48 | 49 | @Override 50 | public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { 51 | if (mOrientation == VERTICAL_LIST) { 52 | drawVertical(c, parent); 53 | } else { 54 | drawHorizontal(c, parent); 55 | } 56 | } 57 | 58 | public void drawVertical(Canvas c, RecyclerView parent) { 59 | final int left = parent.getPaddingLeft(); 60 | final int right = parent.getWidth() - parent.getPaddingRight(); 61 | 62 | final int childCount = parent.getChildCount(); 63 | for (int i = 0; i < childCount; i++) { 64 | final View child = parent.getChildAt(i); 65 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 66 | .getLayoutParams(); 67 | final int top = child.getBottom() + params.bottomMargin; 68 | final int bottom = top + mDivider.getIntrinsicHeight(); 69 | mDivider.setBounds(left + dpToPx(margin), top, right - dpToPx(margin), bottom); 70 | mDivider.draw(c); 71 | } 72 | } 73 | 74 | public void drawHorizontal(Canvas c, RecyclerView parent) { 75 | final int top = parent.getPaddingTop(); 76 | final int bottom = parent.getHeight() - parent.getPaddingBottom(); 77 | 78 | final int childCount = parent.getChildCount(); 79 | for (int i = 0; i < childCount; i++) { 80 | final View child = parent.getChildAt(i); 81 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 82 | .getLayoutParams(); 83 | final int left = child.getRight() + params.rightMargin; 84 | final int right = left + mDivider.getIntrinsicHeight(); 85 | mDivider.setBounds(left, top + dpToPx(margin), right, bottom - dpToPx(margin)); 86 | mDivider.draw(c); 87 | } 88 | } 89 | 90 | @Override 91 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 92 | if (mOrientation == VERTICAL_LIST) { 93 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 94 | } else { 95 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 96 | } 97 | } 98 | 99 | private int dpToPx(int dp) { 100 | Resources r = context.getResources(); 101 | return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics())); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/utils/PrefUtils.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | /** 7 | * Created by ravi on 20/02/18. 8 | */ 9 | 10 | public class PrefUtils { 11 | /** 12 | * Storing API Key in shared preferences to 13 | * add it in header part of every retrofit request 14 | */ 15 | public PrefUtils() { 16 | } 17 | 18 | private static SharedPreferences getSharedPreferences(Context context) { 19 | return context.getSharedPreferences("APP_PREF", Context.MODE_PRIVATE); 20 | } 21 | 22 | public static void storeApiKey(Context context, String apiKey) { 23 | SharedPreferences.Editor editor = getSharedPreferences(context).edit(); 24 | editor.putString("API_KEY", apiKey); 25 | editor.commit(); 26 | } 27 | 28 | public static String getApiKey(Context context) { 29 | return getSharedPreferences(context).getString("API_KEY", null); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/utils/RecyclerTouchListener.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.utils; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.GestureDetector; 6 | import android.view.MotionEvent; 7 | import android.view.View; 8 | 9 | /** 10 | * Created by ravi on 21/02/18. 11 | */ 12 | 13 | public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener { 14 | 15 | private ClickListener clicklistener; 16 | private GestureDetector gestureDetector; 17 | 18 | public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener) { 19 | 20 | this.clicklistener = clicklistener; 21 | gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 22 | @Override 23 | public boolean onSingleTapUp(MotionEvent e) { 24 | return true; 25 | } 26 | 27 | @Override 28 | public void onLongPress(MotionEvent e) { 29 | View child = recycleView.findChildViewUnder(e.getX(), e.getY()); 30 | if (child != null && clicklistener != null) { 31 | clicklistener.onLongClick(child, recycleView.getChildAdapterPosition(child)); 32 | } 33 | } 34 | }); 35 | } 36 | 37 | @Override 38 | public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 39 | View child = rv.findChildViewUnder(e.getX(), e.getY()); 40 | if (child != null && clicklistener != null && gestureDetector.onTouchEvent(e)) { 41 | clicklistener.onClick(child, rv.getChildAdapterPosition(child)); 42 | } 43 | 44 | return false; 45 | } 46 | 47 | @Override 48 | public void onTouchEvent(RecyclerView rv, MotionEvent e) { 49 | 50 | } 51 | 52 | @Override 53 | public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { 54 | 55 | } 56 | 57 | public interface ClickListener { 58 | void onClick(View view, int position); 59 | 60 | void onLongClick(View view, int position); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/view/MainActivity.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.view; 2 | 3 | import android.content.DialogInterface; 4 | import android.graphics.Color; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.design.widget.CoordinatorLayout; 8 | import android.support.design.widget.FloatingActionButton; 9 | import android.support.design.widget.Snackbar; 10 | import android.support.v7.app.AlertDialog; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.support.v7.widget.DefaultItemAnimator; 13 | import android.support.v7.widget.LinearLayoutManager; 14 | import android.support.v7.widget.RecyclerView; 15 | import android.support.v7.widget.Toolbar; 16 | import android.text.TextUtils; 17 | import android.util.Log; 18 | import android.view.LayoutInflater; 19 | import android.view.View; 20 | import android.widget.EditText; 21 | import android.widget.TextView; 22 | import android.widget.Toast; 23 | 24 | import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; 25 | 26 | import org.json.JSONException; 27 | import org.json.JSONObject; 28 | 29 | import java.io.IOException; 30 | import java.util.ArrayList; 31 | import java.util.Collections; 32 | import java.util.Comparator; 33 | import java.util.List; 34 | import java.util.UUID; 35 | 36 | import butterknife.BindView; 37 | import butterknife.ButterKnife; 38 | import info.androidhive.rxjavaretrofit.R; 39 | import info.androidhive.rxjavaretrofit.network.ApiClient; 40 | import info.androidhive.rxjavaretrofit.network.ApiService; 41 | import info.androidhive.rxjavaretrofit.network.model.Note; 42 | import info.androidhive.rxjavaretrofit.network.model.User; 43 | import info.androidhive.rxjavaretrofit.utils.MyDividerItemDecoration; 44 | import info.androidhive.rxjavaretrofit.utils.PrefUtils; 45 | import info.androidhive.rxjavaretrofit.utils.RecyclerTouchListener; 46 | import io.reactivex.android.schedulers.AndroidSchedulers; 47 | import io.reactivex.disposables.CompositeDisposable; 48 | import io.reactivex.functions.Function; 49 | import io.reactivex.observers.DisposableCompletableObserver; 50 | import io.reactivex.observers.DisposableSingleObserver; 51 | import io.reactivex.schedulers.Schedulers; 52 | 53 | public class MainActivity extends AppCompatActivity { 54 | private static final String TAG = MainActivity.class.getSimpleName(); 55 | private ApiService apiService; 56 | private CompositeDisposable disposable = new CompositeDisposable(); 57 | private NotesAdapter mAdapter; 58 | private List notesList = new ArrayList<>(); 59 | 60 | @BindView(R.id.coordinator_layout) 61 | CoordinatorLayout coordinatorLayout; 62 | 63 | @BindView(R.id.recycler_view) 64 | RecyclerView recyclerView; 65 | 66 | @BindView(R.id.txt_empty_notes_view) 67 | TextView noNotesView; 68 | 69 | @Override 70 | protected void onCreate(Bundle savedInstanceState) { 71 | super.onCreate(savedInstanceState); 72 | getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); 73 | setContentView(R.layout.activity_main); 74 | ButterKnife.bind(this); 75 | 76 | Toolbar toolbar = findViewById(R.id.toolbar); 77 | toolbar.setTitle(getString(R.string.activity_title_home)); 78 | setSupportActionBar(toolbar); 79 | 80 | 81 | FloatingActionButton fab = findViewById(R.id.fab); 82 | fab.setOnClickListener(new View.OnClickListener() { 83 | @Override 84 | public void onClick(View view) { 85 | showNoteDialog(false, null, -1); 86 | } 87 | }); 88 | 89 | // white background notification bar 90 | whiteNotificationBar(fab); 91 | 92 | apiService = ApiClient.getClient(getApplicationContext()).create(ApiService.class); 93 | 94 | mAdapter = new NotesAdapter(this, notesList); 95 | RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext()); 96 | recyclerView.setLayoutManager(mLayoutManager); 97 | recyclerView.setItemAnimator(new DefaultItemAnimator()); 98 | recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16)); 99 | recyclerView.setAdapter(mAdapter); 100 | 101 | /** 102 | * On long press on RecyclerView item, open alert dialog 103 | * with options to choose 104 | * Edit and Delete 105 | * */ 106 | recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this, 107 | recyclerView, new RecyclerTouchListener.ClickListener() { 108 | @Override 109 | public void onClick(View view, final int position) { 110 | } 111 | 112 | @Override 113 | public void onLongClick(View view, int position) { 114 | showActionsDialog(position); 115 | } 116 | })); 117 | 118 | /** 119 | * Check for stored Api Key in shared preferences 120 | * If not present, make api call to register the user 121 | * This will be executed when app is installed for the first time 122 | * or data is cleared from settings 123 | * */ 124 | if (TextUtils.isEmpty(PrefUtils.getApiKey(this))) { 125 | registerUser(); 126 | } else { 127 | // user is already registered, fetch all notes 128 | fetchAllNotes(); 129 | } 130 | } 131 | 132 | /** 133 | * Registering new user 134 | * sending unique id as device identification 135 | * https://developer.android.com/training/articles/user-data-ids.html 136 | */ 137 | private void registerUser() { 138 | // unique id to identify the device 139 | String uniqueId = UUID.randomUUID().toString(); 140 | 141 | disposable.add( 142 | apiService 143 | .register(uniqueId) 144 | .subscribeOn(Schedulers.io()) 145 | .observeOn(AndroidSchedulers.mainThread()) 146 | .subscribeWith(new DisposableSingleObserver() { 147 | @Override 148 | public void onSuccess(User user) { 149 | // Storing user API Key in preferences 150 | PrefUtils.storeApiKey(getApplicationContext(), user.getApiKey()); 151 | 152 | Toast.makeText(getApplicationContext(), 153 | "Device is registered successfully! ApiKey: " + PrefUtils.getApiKey(getApplicationContext()), 154 | Toast.LENGTH_LONG).show(); 155 | } 156 | 157 | @Override 158 | public void onError(Throwable e) { 159 | Log.e(TAG, "onError: " + e.getMessage()); 160 | showError(e); 161 | } 162 | })); 163 | } 164 | 165 | /** 166 | * Fetching all notes from api 167 | * The received items will be in random order 168 | * map() operator is used to sort the items in descending order by Id 169 | */ 170 | private void fetchAllNotes() { 171 | disposable.add( 172 | apiService.fetchAllNotes() 173 | .subscribeOn(Schedulers.io()) 174 | .observeOn(AndroidSchedulers.mainThread()) 175 | .map(new Function, List>() { 176 | @Override 177 | public List apply(List notes) throws Exception { 178 | // TODO - note about sort 179 | Collections.sort(notes, new Comparator() { 180 | @Override 181 | public int compare(Note n1, Note n2) { 182 | return n2.getId() - n1.getId(); 183 | } 184 | }); 185 | return notes; 186 | } 187 | }) 188 | .subscribeWith(new DisposableSingleObserver>() { 189 | @Override 190 | public void onSuccess(List notes) { 191 | notesList.clear(); 192 | notesList.addAll(notes); 193 | mAdapter.notifyDataSetChanged(); 194 | 195 | toggleEmptyNotes(); 196 | } 197 | 198 | @Override 199 | public void onError(Throwable e) { 200 | Log.e(TAG, "onError: " + e.getMessage()); 201 | showError(e); 202 | } 203 | }) 204 | ); 205 | } 206 | 207 | /** 208 | * Creating new note 209 | */ 210 | private void createNote(String note) { 211 | disposable.add( 212 | apiService.createNote(note) 213 | .subscribeOn(Schedulers.io()) 214 | .observeOn(AndroidSchedulers.mainThread()) 215 | .subscribeWith(new DisposableSingleObserver() { 216 | 217 | @Override 218 | public void onSuccess(Note note) { 219 | if (!TextUtils.isEmpty(note.getError())) { 220 | Toast.makeText(getApplicationContext(), note.getError(), Toast.LENGTH_LONG).show(); 221 | return; 222 | } 223 | 224 | Log.d(TAG, "new note created: " + note.getId() + ", " + note.getNote() + ", " + note.getTimestamp()); 225 | 226 | // Add new item and notify adapter 227 | notesList.add(0, note); 228 | mAdapter.notifyItemInserted(0); 229 | 230 | toggleEmptyNotes(); 231 | } 232 | 233 | @Override 234 | public void onError(Throwable e) { 235 | Log.e(TAG, "onError: " + e.getMessage()); 236 | showError(e); 237 | } 238 | })); 239 | } 240 | 241 | /** 242 | * Updating a note 243 | */ 244 | private void updateNote(int noteId, final String note, final int position) { 245 | disposable.add( 246 | apiService.updateNote(noteId, note) 247 | .subscribeOn(Schedulers.io()) 248 | .observeOn(AndroidSchedulers.mainThread()) 249 | .subscribeWith(new DisposableCompletableObserver() { 250 | @Override 251 | public void onComplete() { 252 | Log.d(TAG, "Note updated!"); 253 | 254 | Note n = notesList.get(position); 255 | n.setNote(note); 256 | 257 | // Update item and notify adapter 258 | notesList.set(position, n); 259 | mAdapter.notifyItemChanged(position); 260 | } 261 | 262 | @Override 263 | public void onError(Throwable e) { 264 | Log.e(TAG, "onError: " + e.getMessage()); 265 | showError(e); 266 | } 267 | })); 268 | } 269 | 270 | /** 271 | * Deleting a note 272 | */ 273 | private void deleteNote(final int noteId, final int position) { 274 | Log.e(TAG, "deleteNote: " + noteId + ", " + position); 275 | disposable.add( 276 | apiService.deleteNote(noteId) 277 | .subscribeOn(Schedulers.io()) 278 | .observeOn(AndroidSchedulers.mainThread()) 279 | .subscribeWith(new DisposableCompletableObserver() { 280 | @Override 281 | public void onComplete() { 282 | Log.d(TAG, "Note deleted! " + noteId); 283 | 284 | // Remove and notify adapter about item deletion 285 | notesList.remove(position); 286 | mAdapter.notifyItemRemoved(position); 287 | 288 | Toast.makeText(MainActivity.this, "Note deleted!", Toast.LENGTH_SHORT).show(); 289 | 290 | toggleEmptyNotes(); 291 | } 292 | 293 | @Override 294 | public void onError(Throwable e) { 295 | Log.e(TAG, "onError: " + e.getMessage()); 296 | showError(e); 297 | } 298 | }) 299 | ); 300 | } 301 | 302 | /** 303 | * Shows alert dialog with EditText options to enter / edit 304 | * a note. 305 | * when shouldUpdate=true, it automatically displays old note and changes the 306 | * button text to UPDATE 307 | */ 308 | private void showNoteDialog(final boolean shouldUpdate, final Note note, final int position) { 309 | LayoutInflater layoutInflaterAndroid = LayoutInflater.from(getApplicationContext()); 310 | View view = layoutInflaterAndroid.inflate(R.layout.note_dialog, null); 311 | 312 | AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(MainActivity.this); 313 | alertDialogBuilderUserInput.setView(view); 314 | 315 | final EditText inputNote = view.findViewById(R.id.note); 316 | TextView dialogTitle = view.findViewById(R.id.dialog_title); 317 | dialogTitle.setText(!shouldUpdate ? getString(R.string.lbl_new_note_title) : getString(R.string.lbl_edit_note_title)); 318 | 319 | if (shouldUpdate && note != null) { 320 | inputNote.setText(note.getNote()); 321 | } 322 | alertDialogBuilderUserInput 323 | .setCancelable(false) 324 | .setPositiveButton(shouldUpdate ? "update" : "save", new DialogInterface.OnClickListener() { 325 | public void onClick(DialogInterface dialogBox, int id) { 326 | 327 | } 328 | }) 329 | .setNegativeButton("cancel", 330 | new DialogInterface.OnClickListener() { 331 | public void onClick(DialogInterface dialogBox, int id) { 332 | dialogBox.cancel(); 333 | } 334 | }); 335 | 336 | final AlertDialog alertDialog = alertDialogBuilderUserInput.create(); 337 | alertDialog.show(); 338 | 339 | alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { 340 | @Override 341 | public void onClick(View v) { 342 | // Show toast message when no text is entered 343 | if (TextUtils.isEmpty(inputNote.getText().toString())) { 344 | Toast.makeText(MainActivity.this, "Enter note!", Toast.LENGTH_SHORT).show(); 345 | return; 346 | } else { 347 | alertDialog.dismiss(); 348 | } 349 | 350 | // check if user updating note 351 | if (shouldUpdate && note != null) { 352 | // update note by it's id 353 | updateNote(note.getId(), inputNote.getText().toString(), position); 354 | } else { 355 | // create new note 356 | createNote(inputNote.getText().toString()); 357 | } 358 | } 359 | }); 360 | } 361 | 362 | /** 363 | * Opens dialog with Edit - Delete options 364 | * Edit - 0 365 | * Delete - 0 366 | */ 367 | private void showActionsDialog(final int position) { 368 | CharSequence colors[] = new CharSequence[]{"Edit", "Delete"}; 369 | 370 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 371 | builder.setTitle("Choose option"); 372 | builder.setItems(colors, new DialogInterface.OnClickListener() { 373 | @Override 374 | public void onClick(DialogInterface dialog, int which) { 375 | if (which == 0) { 376 | showNoteDialog(true, notesList.get(position), position); 377 | } else { 378 | deleteNote(notesList.get(position).getId(), position); 379 | } 380 | } 381 | }); 382 | builder.show(); 383 | } 384 | 385 | private void toggleEmptyNotes() { 386 | if (notesList.size() > 0) { 387 | noNotesView.setVisibility(View.GONE); 388 | } else { 389 | noNotesView.setVisibility(View.VISIBLE); 390 | } 391 | } 392 | 393 | /** 394 | * Showing a Snackbar with error message 395 | * The error body will be in json format 396 | * {"error": "Error message!"} 397 | */ 398 | private void showError(Throwable e) { 399 | String message = ""; 400 | try { 401 | if (e instanceof IOException) { 402 | message = "No internet connection!"; 403 | } else if (e instanceof HttpException) { 404 | HttpException error = (HttpException) e; 405 | String errorBody = error.response().errorBody().string(); 406 | JSONObject jObj = new JSONObject(errorBody); 407 | 408 | message = jObj.getString("error"); 409 | } 410 | } catch (IOException e1) { 411 | e1.printStackTrace(); 412 | } catch (JSONException e1) { 413 | e1.printStackTrace(); 414 | } catch (Exception e1) { 415 | e1.printStackTrace(); 416 | } 417 | 418 | if (TextUtils.isEmpty(message)) { 419 | message = "Unknown error occurred! Check LogCat."; 420 | } 421 | 422 | Snackbar snackbar = Snackbar 423 | .make(coordinatorLayout, message, Snackbar.LENGTH_LONG); 424 | 425 | View sbView = snackbar.getView(); 426 | TextView textView = sbView.findViewById(android.support.design.R.id.snackbar_text); 427 | textView.setTextColor(Color.YELLOW); 428 | snackbar.show(); 429 | } 430 | 431 | private void whiteNotificationBar(View view) { 432 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 433 | int flags = view.getSystemUiVisibility(); 434 | flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 435 | view.setSystemUiVisibility(flags); 436 | getWindow().setStatusBarColor(Color.WHITE); 437 | } 438 | } 439 | 440 | @Override 441 | protected void onDestroy() { 442 | super.onDestroy(); 443 | disposable.dispose(); 444 | } 445 | } 446 | -------------------------------------------------------------------------------- /app/src/main/java/info/androidhive/rxjavaretrofit/view/NotesAdapter.java: -------------------------------------------------------------------------------- 1 | package info.androidhive.rxjavaretrofit.view; 2 | 3 | /** 4 | * Created by ravi on 20/02/18. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.content.res.TypedArray; 9 | import android.graphics.Color; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.text.Html; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.TextView; 16 | 17 | import java.text.ParseException; 18 | import java.text.SimpleDateFormat; 19 | import java.util.Date; 20 | import java.util.List; 21 | 22 | import butterknife.BindView; 23 | import butterknife.ButterKnife; 24 | import info.androidhive.rxjavaretrofit.R; 25 | import info.androidhive.rxjavaretrofit.network.model.Note; 26 | 27 | public class NotesAdapter extends RecyclerView.Adapter { 28 | 29 | private Context context; 30 | private List notesList; 31 | 32 | public class MyViewHolder extends RecyclerView.ViewHolder { 33 | 34 | @BindView(R.id.note) 35 | TextView note; 36 | 37 | @BindView(R.id.dot) 38 | TextView dot; 39 | 40 | @BindView(R.id.timestamp) 41 | TextView timestamp; 42 | 43 | public MyViewHolder(View view) { 44 | super(view); 45 | ButterKnife.bind(this, view); 46 | } 47 | } 48 | 49 | 50 | public NotesAdapter(Context context, List notesList) { 51 | this.context = context; 52 | this.notesList = notesList; 53 | } 54 | 55 | @Override 56 | public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 57 | View itemView = LayoutInflater.from(parent.getContext()) 58 | .inflate(R.layout.note_list_row, parent, false); 59 | 60 | return new MyViewHolder(itemView); 61 | } 62 | 63 | @Override 64 | public void onBindViewHolder(MyViewHolder holder, int position) { 65 | Note note = notesList.get(position); 66 | 67 | holder.note.setText(note.getNote()); 68 | 69 | // Displaying dot from HTML character code 70 | holder.dot.setText(Html.fromHtml("•")); 71 | 72 | // Changing dot color to random color 73 | holder.dot.setTextColor(getRandomMaterialColor("400")); 74 | 75 | // Formatting and displaying timestamp 76 | holder.timestamp.setText(formatDate(note.getTimestamp())); 77 | } 78 | 79 | @Override 80 | public int getItemCount() { 81 | return notesList.size(); 82 | } 83 | 84 | /** 85 | * Chooses random color defined in res/array.xml 86 | */ 87 | private int getRandomMaterialColor(String typeColor) { 88 | int returnColor = Color.GRAY; 89 | int arrayId = context.getResources().getIdentifier("mdcolor_" + typeColor, "array", context.getPackageName()); 90 | 91 | if (arrayId != 0) { 92 | TypedArray colors = context.getResources().obtainTypedArray(arrayId); 93 | int index = (int) (Math.random() * colors.length()); 94 | returnColor = colors.getColor(index, Color.GRAY); 95 | colors.recycle(); 96 | } 97 | return returnColor; 98 | } 99 | 100 | /** 101 | * Formatting timestamp to `MMM d` format 102 | * Input: 2018-02-21 00:15:42 103 | * Output: Feb 21 104 | */ 105 | private String formatDate(String dateStr) { 106 | try { 107 | SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 108 | Date date = fmt.parse(dateStr); 109 | SimpleDateFormat fmtOut = new SimpleDateFormat("MMM d"); 110 | return fmtOut.format(date); 111 | } catch (ParseException e) { 112 | 113 | } 114 | 115 | return ""; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/drawable-hdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/drawable-mdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/note_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/note_list_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 21 | 22 | 29 | 30 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ravi8x/RxJavaRetrofitNotesApp/e97ea3214001f9f82c99ff52946c81208f1697d7/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/array.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #e84e40 5 | #ec407a 6 | #ab47bc 7 | #7e57c2 8 | #5c6bc0 9 | #738ffe 10 | #29b6f6 11 | #26c6da 12 | #26a69a 13 | #2baf2b 14 | #9ccc65 15 | #d4e157 16 | #ffee58 17 | #ffa726 18 | #ff7043 19 | #8d6e63 20 | #bdbdbd 21 | #78909c 22 | 23 | 24 | #e51c23 25 | #e91e63 26 | #9c27b0 27 | #673ab7 28 | #3f51b5 29 | #5677fc 30 | #03a9f4 31 | #00bcd4 32 | #009688 33 | #259b24 34 | #8bc34a 35 | #cddc39 36 | #ffeb3b 37 | #ff9800 38 | #ff5722 39 | #795548 40 | #9e9e9e 41 | #607d8b 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #111 4 | #FFF 5 | #36D3B2 6 | #999 7 | #89c3c3c3 8 | #858585 9 | #232323 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 16dp 4 | 10dp 5 | 26sp 6 | 120dp 7 | 20sp 8 | 10dp 9 | 20sp 10 | 30dp 11 | 40sp 12 | 14sp 13 | 18sp 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | RxJava Retrofit 3 | Settings 4 | Notes 5 | No notes found! 6 | New Note 7 | Edit Note 8 | Enter your note! 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |