├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── mindorks │ │ └── framework │ │ └── mvp │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── seed │ │ │ ├── options.json │ │ │ └── questions.json │ ├── java │ │ └── com │ │ │ └── mindorks │ │ │ └── framework │ │ │ └── mvp │ │ │ ├── MvpApp.kt │ │ │ ├── data │ │ │ ├── database │ │ │ │ ├── AppDatabase.kt │ │ │ │ └── repository │ │ │ │ │ ├── options │ │ │ │ │ ├── Options.kt │ │ │ │ │ ├── OptionsDao.kt │ │ │ │ │ ├── OptionsRepo.kt │ │ │ │ │ └── OptionsRepository.kt │ │ │ │ │ └── questions │ │ │ │ │ ├── Question.kt │ │ │ │ │ ├── QuestionRepo.kt │ │ │ │ │ ├── QuestionRepository.kt │ │ │ │ │ └── QuestionsDao.kt │ │ │ ├── network │ │ │ │ ├── ApiEndPoint.kt │ │ │ │ ├── ApiHeader.kt │ │ │ │ ├── ApiHelper.kt │ │ │ │ ├── AppApiHelper.kt │ │ │ │ ├── Blog.kt │ │ │ │ ├── BlogResponse.kt │ │ │ │ ├── LoginRequest.kt │ │ │ │ ├── LoginResponse.kt │ │ │ │ ├── LogoutResponse.kt │ │ │ │ ├── OpenSource.kt │ │ │ │ └── OpenSourceResponse.kt │ │ │ └── preferences │ │ │ │ ├── AppPreferenceHelper.kt │ │ │ │ └── PreferenceHelper.kt │ │ │ ├── di │ │ │ ├── ApiKeyInfo.kt │ │ │ ├── PreferenceInfo.kt │ │ │ ├── builder │ │ │ │ └── ActivityBuilder.kt │ │ │ ├── component │ │ │ │ └── AppComponent.kt │ │ │ └── module │ │ │ │ └── AppModule.kt │ │ │ ├── ui │ │ │ ├── about │ │ │ │ ├── AboutFragmentProvider.kt │ │ │ │ └── view │ │ │ │ │ └── AboutFragment.kt │ │ │ ├── base │ │ │ │ ├── interactor │ │ │ │ │ ├── BaseInteractor.kt │ │ │ │ │ └── MVPInteractor.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── BasePresenter.kt │ │ │ │ │ └── MVPPresenter.kt │ │ │ │ └── view │ │ │ │ │ ├── BaseActivity.kt │ │ │ │ │ ├── BaseDialogView.kt │ │ │ │ │ ├── BaseFragment.kt │ │ │ │ │ ├── DialogMVPView.kt │ │ │ │ │ └── MVPView.kt │ │ │ ├── feed │ │ │ │ ├── FeedPagerAdapter.kt │ │ │ │ ├── blog │ │ │ │ │ ├── BlogFragmentModule.kt │ │ │ │ │ ├── BlogFragmentProvider.kt │ │ │ │ │ ├── interactor │ │ │ │ │ │ ├── BlogInteractor.kt │ │ │ │ │ │ └── BlogMVPInteractor.kt │ │ │ │ │ ├── presenter │ │ │ │ │ │ ├── BlogMVPPresenter.kt │ │ │ │ │ │ └── BlogPresenter.kt │ │ │ │ │ └── view │ │ │ │ │ │ ├── BlogAdapter.kt │ │ │ │ │ │ ├── BlogFragment.kt │ │ │ │ │ │ └── BlogMVPView.kt │ │ │ │ ├── opensource │ │ │ │ │ ├── OpenSourceFragmentModule.kt │ │ │ │ │ ├── OpenSourceFragmentProvider.kt │ │ │ │ │ ├── interactor │ │ │ │ │ │ ├── OpenSourceInteractor.kt │ │ │ │ │ │ └── OpenSourceMVPInteractor.kt │ │ │ │ │ ├── presenter │ │ │ │ │ │ ├── OpenSourceMVPPresenter.kt │ │ │ │ │ │ └── OpenSourcePresenter.kt │ │ │ │ │ └── view │ │ │ │ │ │ ├── OpenSourceAdapter.kt │ │ │ │ │ │ ├── OpenSourceFragment.kt │ │ │ │ │ │ └── OpenSourceMVPView.kt │ │ │ │ └── view │ │ │ │ │ └── FeedActivity.kt │ │ │ ├── login │ │ │ │ ├── LoginActivityModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── LoginInteractor.kt │ │ │ │ │ └── LoginMVPInteractor.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── LoginMVPPresenter.kt │ │ │ │ │ └── LoginPresenter.kt │ │ │ │ └── view │ │ │ │ │ ├── LoginActivity.kt │ │ │ │ │ └── LoginMVPView.kt │ │ │ ├── main │ │ │ │ ├── MainActivityModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── MainInteractor.kt │ │ │ │ │ ├── MainMVPInteractor.kt │ │ │ │ │ └── QuestionCardData.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── MainMVPPresenter.kt │ │ │ │ │ └── MainPresenter.kt │ │ │ │ └── view │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ ├── MainMVPView.kt │ │ │ │ │ └── QuestionCardView.kt │ │ │ ├── rate │ │ │ │ ├── RateUsDialogFragmentProvider.kt │ │ │ │ ├── RateUsFragmentModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── RateUsInteractor.kt │ │ │ │ │ └── RateUsMVPInterator.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── RateUsMVPPresenter.kt │ │ │ │ │ └── RateUsPresenter.kt │ │ │ │ └── view │ │ │ │ │ ├── RateUsDialog.kt │ │ │ │ │ └── RateUsDialogMVPView.kt │ │ │ └── splash │ │ │ │ ├── SplashActivityModule.kt │ │ │ │ ├── interactor │ │ │ │ ├── SplashInteractor.kt │ │ │ │ └── SplashMVPInteractor.kt │ │ │ │ ├── presenter │ │ │ │ ├── SplashMVPPresenter.kt │ │ │ │ └── SplashPresenter.kt │ │ │ │ └── view │ │ │ │ ├── SplashMVPActivity.kt │ │ │ │ └── SplashMVPView.kt │ │ │ └── util │ │ │ ├── AppConstants.kt │ │ │ ├── CommonUtil.kt │ │ │ ├── FileUtils.kt │ │ │ ├── SchedulerProvider.kt │ │ │ ├── ScreenUtils.kt │ │ │ └── extension │ │ │ ├── FragmentManager.kt │ │ │ └── ImageView.kt │ └── res │ │ ├── anim │ │ ├── slide_left.xml │ │ └── slide_right.xml │ │ ├── drawable-v21 │ │ ├── button_primary_bg.xml │ │ ├── button_secondary_bg.xml │ │ ├── ic_menu_camera.xml │ │ ├── ic_menu_gallery.xml │ │ ├── ic_menu_manage.xml │ │ ├── ic_menu_send.xml │ │ ├── ic_menu_share.xml │ │ └── ic_menu_slideshow.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── bg_design.xml │ │ ├── border_dark_color.xml │ │ ├── bottom_border_shadow.xml │ │ ├── button_bg.xml │ │ ├── button_negative_text_drawable.xml │ │ ├── button_positive_text_drawable.xml │ │ ├── button_secondary_bg.xml │ │ ├── corner_border_rect_gray.xml │ │ ├── ic_arrow_back_white_24px.xml │ │ ├── ic_facebook.xml │ │ ├── ic_google_plus.xml │ │ ├── ic_info_24px.xml │ │ ├── ic_keyboard_backspace_24px.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_power_settings_new_24px.xml │ │ ├── ic_rabbit.xml │ │ ├── ic_rss_symbol.xml │ │ ├── ic_star.xml │ │ ├── input_border_bottom.xml │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_feed.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_splash.xml │ │ ├── app_bar_navigation.xml │ │ ├── card_layout.xml │ │ ├── content_navigation.xml │ │ ├── dialog_rate_us.xml │ │ ├── fragment_about.xml │ │ ├── fragment_blog.xml │ │ ├── fragment_open_source.xml │ │ ├── item_blog_list.xml │ │ ├── item_open_source_list.xml │ │ ├── nav_header_navigation.xml │ │ └── progress_dialog.xml │ │ ├── menu │ │ ├── activity_navigation_drawer.xml │ │ ├── activity_navigation_drawer_drawer.xml │ │ ├── drawer_items.xml │ │ ├── navigation.xml │ │ └── navigation_drawer.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values-v21 │ │ └── styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── mindorks │ └── framework │ └── mvp │ └── ExampleUnitTest.kt ├── 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 -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | 1. Fork it! 4 | 2. Checkout the development branch: `git checkout development` 5 | 3. Create your feature branch: `git checkout -b my-new-feature` 6 | 4. Add your changes to the index: `git add .` 7 | 5. Commit your changes: `git commit -m 'Add some feature'` 8 | 6. Push to the branch: `git push origin my-new-feature` 9 | 7. Submit a pull request against the `development` branch -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Deprecated](https://img.shields.io/badge/deprecated-yes-red)](https://github.com/janishar/wimm-android-app) 2 | 3 | --- 4 | # This Project is [Deprecated] goto latest project: [Modern Android Development - WhereIsMyMotivation](https://github.com/janishar/wimm-android-app) 5 | --- 6 | 7 | # Deprecated 8 | ### Android Kotlin MVP Architecture: Sample App 9 | 10 | This repository contains a detailed sample app that implements MVP architecture in Kotlin using Dagger2, Room, RxJava, FastAndroidNetworking, PlaceHolderView and AndroidDebugDatabase 11 |

12 | 13 | 14 | 15 |

16 |
17 |

18 | 19 | 20 | 21 | 22 |

23 |
24 |
25 | 26 | # Architecture Blueprint 27 | ![Blueprint](https://janishar.github.io/images/mvp-app-pics/mvp-interactor-arch.png) 28 |
29 | 30 | # Project Structure 31 | ![Structure](https://janishar.github.io/images/mvp-app-pics/mvp-interactor-project-structure.png) 32 |
33 | 34 | # About The Author 35 | You can connect with me here: 36 | * [Janishar Ali](https://janisharali.com) 37 | * [Twitter](https://twitter.com/janisharali) 38 | * [YouTube Channel](https://www.youtube.com/@unusualcode) 39 | 40 | # Read the below listed articles. They describe the MVP concepts and the Project structure. 41 | 1. [MVP: Part 1](https://janisharali.com/blog/essential-guide-for-designing-your-android-app-architecture-mvp-part-1-74efaf1cda40#.lkml1yggq) 42 | 2. [MVP: Part 2](https://janisharali.com/blog/essential-guide-for-designing-your-android-app-architecture-mvp-part-2-b2ac6f3f9637#.dge0wl8rl) 43 | 3. [MVP: Part 3](https://janisharali.com/blog/essential-guide-for-designing-your-android-app-architecture-mvp-part-3-dialog-viewpager-and-7bdfab86aabb) 44 | 4. [Extension with Interactors and Repositories](https://janisharali.com/blog/android-mvp-architecture-extension-with-interactors-and-repositories-bd4b51972339) 45 | 46 | #### The app has following packages: 47 | 1. **data**: It contains all the data accessing and manipulating components. 48 | 2. **di**: Dependency providing classes using Dagger2. 49 | 3. **ui**: View classes along with their corresponding Presenters. 50 | 4. **utils**: Utility classes. 51 | 52 | #### Classes have been designed in such a way that it could be inherited and maximize the code reuse. 53 | 54 | ### Library reference resources: 55 | 2. Dagger2: https://github.com/janishar/android-dagger2-example 56 | 4. PlaceHolderView: https://github.com/janishar/PlaceHolderView 57 | 6. Calligraphy: https://github.com/chrisjenx/Calligraphy 58 | 7. GreenDao: http://greenrobot.org/greendao/ 59 | 8. ButterKnife: http://jakewharton.github.io/butterknife/ 60 | 61 | ### Concept reference resources: 62 | 1. [Introduction to Dagger 2: Part 1](https://janisharali.com/blog/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b#.ki6nt86l6) 63 | 2. [Introduction to Dagger 2: Part 2](https://janisharali.com/blog/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd#.mkpzyk8sa) 64 | 3. [Android Dagger2: Critical things to know before you implement](https://janisharali.com/blog/android-dagger2-critical-things-to-know-before-you-implement-275663aecc3e#.bskiz1879) 65 | 4. [Android Tinder Swipe View Example](https://janisharali.com/blog/android-tinder-swipe-view-example-3eca9b0d4794#.u7i7jbbvy) 66 | 5. [RxJava Anatomy: What is RxJava, how RxJava is designed, and how RxJava works.](https://janisharali.com/blog/rxjava-anatomy-what-is-rxjava-how-rxjava-is-designed-and-how-rxjava-works-d357b3aca586) 67 | 68 | ### Looking for MVVM Architecture - [Check here](https://github.com/janishar/android-mvvm-architecture) 69 | 70 | ### License 71 | ``` 72 | Copyright (C) 2022 JANISHAR ALI ANWAR 73 | 74 | Licensed under the Apache License, Version 2.0 (the "License"); 75 | you may not use this file except in compliance with the License. 76 | You may obtain a copy of the License at 77 | 78 | http://www.apache.org/licenses/LICENSE-2.0 79 | 80 | Unless required by applicable law or agreed to in writing, software 81 | distributed under the License is distributed on an "AS IS" BASIS, 82 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 83 | See the License for the specific language governing permissions and 84 | limitations under the License. 85 | ``` 86 | 87 | ### Contributing to Android Kotlin MVP Architecture 88 | All pull requests are welcome, make sure to follow the [contribution guidelines](CONTRIBUTING.md) 89 | when you submit pull request. 90 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | apply plugin: 'kotlin-kapt' 8 | 9 | android { 10 | compileSdkVersion rootProject.ext.compileSdkVersion 11 | defaultConfig { 12 | applicationId "com.mindorks.framework.mvp" 13 | minSdkVersion rootProject.ext.minSdkVersion 14 | targetSdkVersion rootProject.ext.targetSdkVersion 15 | versionCode 1 16 | versionName "1.0" 17 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 18 | vectorDrawables.useSupportLibrary = true 19 | } 20 | buildTypes { 21 | debug { 22 | buildConfigField("String", "BASE_URL", "\"http://www.mocky.io/v2\"") 23 | buildConfigField("String", "API_KEY", "\"ABCXYZ123TEST\"") 24 | } 25 | release { 26 | minifyEnabled true 27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 28 | buildConfigField("String", "BASE_URL", "\"http://www.mocky.io/v2\"") 29 | buildConfigField("String", "API_KEY", "\"ABCXYZ123TEST\"") 30 | } 31 | } 32 | } 33 | 34 | dependencies { 35 | implementation fileTree(dir: 'libs', include: ['*.jar']) 36 | 37 | // kotlin 38 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.kotlinVersion" 39 | 40 | // android support libraries 41 | implementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" 42 | implementation "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion" 43 | implementation "com.android.support:cardview-v7:$rootProject.supportLibraryVersion" 44 | implementation "com.android.support:design:$rootProject.supportLibraryVersion" 45 | implementation "com.android.support:support-vector-drawable:$rootProject.supportLibraryVersion" 46 | implementation "com.android.support:animated-vector-drawable:$rootProject.supportLibraryVersion" 47 | 48 | // network 49 | implementation "com.amitshekhar.android:rx2-android-networking:$rootProject.rx2FastAndroidNetworking" 50 | 51 | // database 52 | implementation "android.arch.persistence.room:rxjava2:$rootProject.roomDatabaseVersion" 53 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 54 | kapt "android.arch.persistence.room:compiler:$rootProject.roomDatabaseVersion" 55 | 56 | // font 57 | implementation "uk.co.chrisjenx:calligraphy:$rootProject.calligraphyVersion" 58 | 59 | // image 60 | implementation "com.github.bumptech.glide:glide:$rootProject.glideVersion" 61 | 62 | // parser 63 | implementation "com.google.code.gson:gson:$rootProject.gsonVersion" 64 | 65 | // debug database 66 | debugImplementation "com.amitshekhar.android:debug-db:$rootProject.debugDBVersion" 67 | 68 | // dependency injection 69 | implementation "com.google.dagger:dagger:$rootProject.dagger2Version" 70 | kapt "com.google.dagger:dagger-compiler:$rootProject.dagger2Version" 71 | kapt "com.google.dagger:dagger-android-processor:$rootProject.dagger2Version" 72 | implementation "com.google.dagger:dagger-android-support:$rootProject.dagger2Version" 73 | 74 | // reactive 75 | implementation "io.reactivex.rxjava2:rxjava:$rootProject.rxjava2Version" 76 | implementation "io.reactivex.rxjava2:rxandroid:$rootProject.rxandroidVersion" 77 | 78 | // code generator for view 79 | implementation "com.jakewharton:butterknife:$rootProject.butterKnifeVersion" 80 | kapt "com.jakewharton:butterknife-compiler:$rootProject.butterKnifeVersion" 81 | 82 | // swipe view 83 | implementation "com.mindorks:placeholderview:$rootProject.placeholderviewVersion" 84 | 85 | // logger 86 | implementation "com.jakewharton.timber:timber:$rootProject.timberVersion" 87 | 88 | // dependencies for local unit tests 89 | testImplementation "junit:junit:$rootProject.ext.junitVersion" 90 | testImplementation "org.mockito:mockito-core:$rootProject.mockitoVersion" 91 | kaptTest "com.google.dagger:dagger-compiler:$rootProject.dagger2Version" 92 | 93 | // UI Testing 94 | androidTestImplementation "com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion" 95 | androidTestImplementation "com.android.support.test.espresso:espresso-intents:$rootProject.espressoVersion" 96 | androidTestImplementation "org.mockito:mockito-core:$rootProject.mockitoVersion" 97 | kaptAndroidTest "com.google.dagger:dagger-compiler:$rootProject.dagger2Version" 98 | 99 | // Android Kotlin Extension 100 | implementation "androidx.core:core-ktx:$rootProject.androidKTXVersion" 101 | } 102 | -------------------------------------------------------------------------------- /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/com/mindorks/framework/mvp/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.mindorks.framework.mvp", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/assets/seed/options.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "option_text": "MVVM", 4 | "question_id": 1, 5 | "is_correct": false 6 | }, 7 | { 8 | "option_text": "MVP", 9 | "question_id": 1, 10 | "is_correct": true 11 | }, 12 | { 13 | "option_text": "MVC", 14 | "question_id": 1, 15 | "is_correct": false 16 | }, 17 | { 18 | "option_text": "Data Manager", 19 | "question_id": 2, 20 | "is_correct": true 21 | }, 22 | { 23 | "option_text": "View", 24 | "question_id": 2, 25 | "is_correct": false 26 | }, 27 | { 28 | "option_text": "Presenter", 29 | "question_id": 2, 30 | "is_correct": false 31 | }, 32 | { 33 | "option_text": "Yes", 34 | "question_id": 3, 35 | "is_correct": false 36 | }, 37 | { 38 | "option_text": "Never", 39 | "question_id": 3, 40 | "is_correct": true 41 | }, 42 | { 43 | "option_text": "Sometimes", 44 | "question_id": 3, 45 | "is_correct": false 46 | }, 47 | { 48 | "option_text": "It fetches the data from the database.", 49 | "question_id": 4, 50 | "is_correct": false 51 | }, 52 | { 53 | "option_text": "It delegates View's requirements to Data Manager.", 54 | "question_id": 4, 55 | "is_correct": true 56 | }, 57 | { 58 | "option_text": "It instructs the View to perform actions.", 59 | "question_id": 4, 60 | "is_correct": true 61 | }, 62 | { 63 | "option_text": "It created a readable code.", 64 | "question_id": 5, 65 | "is_correct": true 66 | }, 67 | { 68 | "option_text": "It is highly testable.", 69 | "question_id": 5, 70 | "is_correct": true 71 | }, 72 | { 73 | "option_text": "It provides reusable code.", 74 | "question_id": 5, 75 | "is_correct": true 76 | }, 77 | { 78 | "option_text": "Linus Torvalds", 79 | "question_id": 6, 80 | "is_correct": true 81 | }, 82 | { 83 | "option_text": "Janishar Ali", 84 | "question_id": 6, 85 | "is_correct": false 86 | }, 87 | { 88 | "option_text": "Amit Shekhar", 89 | "question_id": 6, 90 | "is_correct": false 91 | }, 92 | { 93 | "option_text": "None", 94 | "question_id": 7, 95 | "is_correct": false 96 | }, 97 | { 98 | "option_text": "Mindorks", 99 | "question_id": 7, 100 | "is_correct": true 101 | }, 102 | { 103 | "option_text": "Google", 104 | "question_id": 7, 105 | "is_correct": false 106 | } 107 | ] -------------------------------------------------------------------------------- /app/src/main/assets/seed/questions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "question_text": "What is the architecture of this app?", 5 | "question_img_url": null 6 | }, 7 | { 8 | "id": 2, 9 | "question_text": "Which component of the MVP controls the data flow?", 10 | "question_img_url": null 11 | }, 12 | { 13 | "id": 3, 14 | "question_text": "Can a View ask for data from a Data Manager?", 15 | "question_img_url": null 16 | }, 17 | { 18 | "id": 4, 19 | "question_text": "What is the role of a Presenter?", 20 | "question_img_url": null 21 | }, 22 | { 23 | "id": 5, 24 | "question_text": "Why should we follow MVP?", 25 | "question_img_url": null 26 | }, 27 | { 28 | "id": 6, 29 | "question_text": "Who is this person?", 30 | "question_img_url": "https://avatars3.githubusercontent.com/u/1024025" 31 | }, 32 | { 33 | "id": 7, 34 | "question_text": "Which company's logo is this?", 35 | "question_img_url": "https://janishar.github.io/images/mindorks-logo-small.png" 36 | } 37 | ] -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/MvpApp.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp 2 | 3 | import android.app.Activity 4 | import android.app.Application 5 | import com.mindorks.framework.mvp.di.component.DaggerAppComponent 6 | import dagger.android.DispatchingAndroidInjector 7 | import dagger.android.HasActivityInjector 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by amitshekhar on 24/12/17. 12 | */ 13 | class MvpApp : Application(), HasActivityInjector { 14 | 15 | @Inject 16 | lateinit internal var activityDispatchingAndroidInjector: DispatchingAndroidInjector 17 | 18 | 19 | override fun activityInjector() = activityDispatchingAndroidInjector 20 | 21 | override fun onCreate() { 22 | super.onCreate() 23 | DaggerAppComponent.builder() 24 | .application(this) 25 | .build() 26 | .inject(this) 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/AppDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database 2 | 3 | import android.arch.persistence.room.Database 4 | import android.arch.persistence.room.RoomDatabase 5 | import com.mindorks.framework.mvp.data.database.repository.options.Options 6 | import com.mindorks.framework.mvp.data.database.repository.options.OptionsDao 7 | import com.mindorks.framework.mvp.data.database.repository.questions.Question 8 | import com.mindorks.framework.mvp.data.database.repository.questions.QuestionsDao 9 | 10 | /** 11 | * Created by jyotidubey on 03/01/18. 12 | */ 13 | @Database(entities = [(Question::class), (Options::class)], version = 1) 14 | abstract class AppDatabase : RoomDatabase() { 15 | 16 | abstract fun optionsDao(): OptionsDao 17 | 18 | abstract fun questionsDao(): QuestionsDao 19 | 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/options/Options.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.options 2 | 3 | import android.arch.persistence.room.ColumnInfo 4 | import android.arch.persistence.room.Entity 5 | import android.arch.persistence.room.ForeignKey 6 | import android.arch.persistence.room.PrimaryKey 7 | import com.google.gson.annotations.Expose 8 | import com.google.gson.annotations.SerializedName 9 | import com.mindorks.framework.mvp.data.database.repository.questions.Question 10 | 11 | /** 12 | * Created by jyotidubey on 03/01/18. 13 | */ 14 | @Entity(tableName = "options", foreignKeys = [(ForeignKey(entity = Question::class, 15 | parentColumns = arrayOf("id"), 16 | childColumns = arrayOf("question_id"), 17 | onDelete = ForeignKey.CASCADE))]) 18 | data class Options( 19 | 20 | @PrimaryKey(autoGenerate = true) var id: Long, 21 | 22 | @Expose 23 | @SerializedName("option_text") 24 | @ColumnInfo(name = "option_text") 25 | var optionText: String, 26 | 27 | @Expose 28 | @SerializedName("question_id") 29 | @ColumnInfo(name = "question_id") 30 | var questionId: Long, 31 | 32 | @Expose 33 | @SerializedName("is_correct") 34 | @ColumnInfo(name = "is_correct") 35 | var isCorrect: Boolean, 36 | 37 | @Expose 38 | @SerializedName("created_at") 39 | @ColumnInfo(name = "created_at") 40 | var createdAt: String?, 41 | 42 | @Expose 43 | @SerializedName("updated_at") 44 | @ColumnInfo(name = "updated_at") 45 | var updatedAt: String? 46 | ) 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/options/OptionsDao.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.options 2 | 3 | import android.arch.persistence.room.Dao 4 | import android.arch.persistence.room.Insert 5 | import android.arch.persistence.room.OnConflictStrategy 6 | import android.arch.persistence.room.Query 7 | 8 | /** 9 | * Created by jyotidubey on 03/01/18. 10 | */ 11 | @Dao 12 | interface OptionsDao { 13 | 14 | @Insert(onConflict = OnConflictStrategy.REPLACE) 15 | fun insertAll(options: List) 16 | 17 | @Query("SELECT * FROM options WHERE question_id = :questionId") 18 | fun loadOptionsByQuestionId(questionId: Long): List 19 | 20 | @Query("SELECT * FROM options") 21 | fun loadAll(): List 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/options/OptionsRepo.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.options 2 | 3 | import io.reactivex.Observable 4 | import io.reactivex.Single 5 | 6 | /** 7 | * Created by jyotidubey on 06/01/18. 8 | */ 9 | interface OptionsRepo { 10 | 11 | fun isOptionsRepoEmpty(): Observable 12 | 13 | fun insertOptions(options: List): Observable 14 | 15 | fun loadOptions(questionId: Long): Single> 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/options/OptionsRepository.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.options 2 | 3 | import io.reactivex.Observable 4 | import io.reactivex.Single 5 | import javax.inject.Inject 6 | 7 | /** 8 | * Created by jyotidubey on 06/01/18. 9 | */ 10 | class OptionsRepository @Inject constructor(private val optionsDao: OptionsDao) : OptionsRepo { 11 | 12 | override fun isOptionsRepoEmpty(): Observable = Observable.just(optionsDao.loadAll().isEmpty()) 13 | 14 | override fun insertOptions(options: List): Observable { 15 | optionsDao.insertAll(options) 16 | return Observable.just(true) 17 | } 18 | 19 | override fun loadOptions(questionId: Long): Single> 20 | = Single.fromCallable({ optionsDao.loadOptionsByQuestionId(questionId) }) 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/questions/Question.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.questions 2 | 3 | import android.arch.persistence.room.ColumnInfo 4 | import android.arch.persistence.room.Entity 5 | import android.arch.persistence.room.PrimaryKey 6 | import com.google.gson.annotations.Expose 7 | import com.google.gson.annotations.SerializedName 8 | 9 | /** 10 | * Created by jyotidubey on 03/01/18. 11 | */ 12 | @Entity(tableName = "questions") 13 | data class Question( 14 | @Expose 15 | @PrimaryKey 16 | var id: Long, 17 | 18 | @Expose 19 | @SerializedName("question_text") 20 | @ColumnInfo(name = "question_text") 21 | var questionText: String, 22 | 23 | @Expose 24 | @SerializedName("question_img_url") 25 | @ColumnInfo(name = "question_img_url") 26 | var imgUrl: String?, 27 | 28 | @Expose 29 | @SerializedName("created_at") 30 | @ColumnInfo(name = "created_at") 31 | var createdAt: String?, 32 | 33 | @Expose 34 | @SerializedName("updated_at") 35 | @ColumnInfo(name = "updated_at") 36 | var updatedAt: String? 37 | 38 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/questions/QuestionRepo.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.questions 2 | 3 | import io.reactivex.Observable 4 | 5 | /** 6 | * Created by jyotidubey on 06/01/18. 7 | */ 8 | interface QuestionRepo { 9 | 10 | fun isQuestionsRepoEmpty(): Observable 11 | 12 | fun insertQuestions(questions: List): Observable 13 | 14 | fun loadQuestions(): Observable> 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/questions/QuestionRepository.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.questions 2 | 3 | import io.reactivex.Observable 4 | import javax.inject.Inject 5 | 6 | /** 7 | * Created by jyotidubey on 06/01/18. 8 | */ 9 | class QuestionRepository @Inject internal constructor(private val questionsDao: QuestionsDao) : QuestionRepo { 10 | 11 | override fun isQuestionsRepoEmpty(): Observable = Observable.fromCallable({ questionsDao.loadAll().isEmpty() }) 12 | 13 | override fun insertQuestions(questions: List): Observable { 14 | questionsDao.insertAll(questions) 15 | return Observable.just(true) 16 | } 17 | 18 | override fun loadQuestions(): Observable> = Observable.fromCallable({ questionsDao.loadAll() }) 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/database/repository/questions/QuestionsDao.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.database.repository.questions 2 | 3 | import android.arch.persistence.room.Dao 4 | import android.arch.persistence.room.Insert 5 | import android.arch.persistence.room.OnConflictStrategy 6 | import android.arch.persistence.room.Query 7 | 8 | /** 9 | * Created by jyotidubey on 04/01/18. 10 | */ 11 | @Dao 12 | interface QuestionsDao { 13 | 14 | @Insert(onConflict = OnConflictStrategy.REPLACE) 15 | fun insertAll(question: List) 16 | 17 | @Query("SELECT * FROM questions") 18 | fun loadAll(): List 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/ApiEndPoint.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.mindorks.framework.mvp.BuildConfig 4 | 5 | /** 6 | * Created by jyotidubey on 11/01/18. 7 | */ 8 | object ApiEndPoint { 9 | 10 | val ENDPOINT_GOOGLE_LOGIN = BuildConfig.BASE_URL + "/588d14f4100000a9072d2943" 11 | val ENDPOINT_FACEBOOK_LOGIN = BuildConfig.BASE_URL + "/588d15d3100000ae072d2944" 12 | val ENDPOINT_SERVER_LOGIN = BuildConfig.BASE_URL + "/588d15f5100000a8072d2945" 13 | val ENDPOINT_LOGOUT = BuildConfig.BASE_URL + "/588d161c100000a9072d2946" 14 | val ENDPOINT_BLOG = BuildConfig.BASE_URL + "/5926ce9d11000096006ccb30" 15 | val ENDPOINT_OPEN_SOURCE = BuildConfig.BASE_URL + "/5926c34212000035026871cd" 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/ApiHeader.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | import com.mindorks.framework.mvp.di.ApiKeyInfo 6 | import javax.inject.Inject 7 | 8 | /** 9 | * Created by jyotidubey on 11/01/18. 10 | */ 11 | class ApiHeader @Inject constructor(internal val publicApiHeader: PublicApiHeader, internal val protectedApiHeader: ProtectedApiHeader) { 12 | 13 | class PublicApiHeader @Inject constructor(@ApiKeyInfo 14 | @Expose 15 | @SerializedName 16 | ("api_key") val apiKey: String) 17 | 18 | class ProtectedApiHeader @Inject constructor(@Expose 19 | @SerializedName("api_key") val apiKey: String, 20 | @Expose 21 | @SerializedName("user_id") val userId: Long?, 22 | @Expose 23 | @SerializedName("access_token") val accessToken: String?) 24 | 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/ApiHelper.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import io.reactivex.Observable 4 | 5 | /** 6 | * Created by jyotidubey on 04/01/18. 7 | */ 8 | interface ApiHelper { 9 | 10 | fun performServerLogin(request: LoginRequest.ServerLoginRequest): Observable 11 | 12 | fun performFBLogin(request: LoginRequest.FacebookLoginRequest): Observable 13 | 14 | fun performGoogleLogin(request: LoginRequest.GoogleLoginRequest): Observable 15 | 16 | fun performLogoutApiCall(): Observable 17 | 18 | fun getBlogApiCall(): Observable 19 | 20 | fun getOpenSourceApiCall(): Observable 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/AppApiHelper.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.rx2androidnetworking.Rx2AndroidNetworking 4 | import io.reactivex.Observable 5 | import javax.inject.Inject 6 | 7 | /** 8 | * Created by jyotidubey on 04/01/18. 9 | */ 10 | class AppApiHelper @Inject constructor(private val apiHeader: ApiHeader) : ApiHelper { 11 | 12 | override fun performServerLogin(request: LoginRequest.ServerLoginRequest): Observable = 13 | Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_SERVER_LOGIN) 14 | .addHeaders(apiHeader.publicApiHeader) 15 | .addBodyParameter(request) 16 | .build() 17 | .getObjectObservable(LoginResponse::class.java) 18 | 19 | override fun performFBLogin(request: LoginRequest.FacebookLoginRequest): Observable = 20 | Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_FACEBOOK_LOGIN) 21 | .addHeaders(apiHeader.publicApiHeader) 22 | .addBodyParameter(request) 23 | .build() 24 | .getObjectObservable(LoginResponse::class.java) 25 | 26 | override fun performGoogleLogin(request: LoginRequest.GoogleLoginRequest): Observable = 27 | Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_GOOGLE_LOGIN) 28 | .addHeaders(apiHeader.publicApiHeader) 29 | .addBodyParameter(request) 30 | .build() 31 | .getObjectObservable(LoginResponse::class.java) 32 | 33 | override fun performLogoutApiCall(): Observable = 34 | Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_LOGOUT) 35 | .addHeaders(apiHeader.protectedApiHeader) 36 | .build() 37 | .getObjectObservable(LogoutResponse::class.java) 38 | 39 | override fun getBlogApiCall(): Observable = 40 | Rx2AndroidNetworking.get(ApiEndPoint.ENDPOINT_BLOG) 41 | .addHeaders(apiHeader.protectedApiHeader) 42 | .build() 43 | .getObjectObservable(BlogResponse::class.java) 44 | 45 | override fun getOpenSourceApiCall(): Observable = 46 | Rx2AndroidNetworking.get(ApiEndPoint.ENDPOINT_OPEN_SOURCE) 47 | .addHeaders(apiHeader.protectedApiHeader) 48 | .build() 49 | .getObjectObservable(OpenSourceResponse::class.java) 50 | 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/Blog.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | /** 7 | * Created by jyotidubey on 17/01/18. 8 | */ 9 | data class Blog(@Expose 10 | @SerializedName("blog_url") 11 | var blogUrl: String? = null, 12 | 13 | @Expose 14 | @SerializedName("img_url") 15 | var coverImgUrl: String? = null, 16 | 17 | @Expose 18 | @SerializedName("title") 19 | var title: String? = null, 20 | 21 | @Expose 22 | @SerializedName("description") 23 | var description: String? = null, 24 | 25 | @Expose 26 | @SerializedName("author") 27 | var author: String? = null, 28 | 29 | @Expose 30 | @SerializedName("published_at") 31 | var date: String? = null) -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/BlogResponse.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | /** 7 | * Created by jyotidubey on 13/01/18. 8 | */ 9 | data class BlogResponse(@Expose 10 | @SerializedName("status_code") 11 | private var statusCode: String? = null, 12 | 13 | @Expose 14 | @SerializedName("message") 15 | private var message: String? = null, 16 | 17 | @Expose 18 | @SerializedName("data") 19 | var data: List? = null) 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/LoginRequest.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | /** 7 | * Created by jyotidubey on 11/01/18. 8 | */ 9 | class LoginRequest { 10 | 11 | data class ServerLoginRequest internal constructor(@Expose 12 | @SerializedName("email") internal val email: String, 13 | @Expose 14 | @SerializedName("password") internal val password: String) 15 | 16 | data class FacebookLoginRequest internal constructor(@Expose 17 | @SerializedName("fb_user_id") 18 | internal val fbUserId: String, 19 | @Expose 20 | @SerializedName("fb_access_token") 21 | internal val fbAccessToken: String) 22 | 23 | data class GoogleLoginRequest internal constructor(@Expose 24 | @SerializedName("google_user_id") 25 | internal val googleUserId: String, 26 | @Expose 27 | @SerializedName("google_id_token") 28 | internal val idToken: String) 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/LoginResponse.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | /** 7 | * Created by jyotidubey on 11/01/18. 8 | */ 9 | data class LoginResponse(@Expose 10 | @SerializedName("status_code") 11 | var statusCode: String? = null, 12 | 13 | @Expose 14 | @SerializedName("user_id") 15 | var userId: Long? = null, 16 | 17 | @Expose 18 | @SerializedName("access_token") 19 | var accessToken: String? = null, 20 | 21 | @Expose 22 | @SerializedName("user_name") 23 | var userName: String? = null, 24 | 25 | @Expose 26 | @SerializedName("email") 27 | var userEmail: String? = null, 28 | 29 | @Expose 30 | @SerializedName("server_profile_pic_url") 31 | var serverProfilePicUrl: String? = null, 32 | 33 | @Expose 34 | @SerializedName("fb_profile_pic_url") 35 | var fbProfilePicUrl: String? = null, 36 | 37 | @Expose 38 | @SerializedName("google_profile_pic_url") 39 | var googleProfilePicUrl: String? = null, 40 | 41 | @Expose 42 | @SerializedName("message") 43 | var message: String? = null) 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/LogoutResponse.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | /** 7 | * Created by jyotidubey on 12/01/18. 8 | */ 9 | data class LogoutResponse internal constructor(@Expose 10 | @SerializedName("status_code") 11 | private var statusCode: String? = null, 12 | @Expose 13 | @SerializedName("message") 14 | private var message: String? = null) 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/OpenSource.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | /** 7 | * Created by jyotidubey on 17/01/18. 8 | */ 9 | data class OpenSource(@Expose 10 | @SerializedName("project_url") 11 | var projectUrl: String? = null, 12 | 13 | @Expose 14 | @SerializedName("img_url") 15 | var coverImgUrl: String? = null, 16 | 17 | @Expose 18 | @SerializedName("title") 19 | var title: String? = null, 20 | 21 | @Expose 22 | @SerializedName("description") 23 | var description: String? = null) -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/network/OpenSourceResponse.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | /** 7 | * Created by jyotidubey on 14/01/18. 8 | */ 9 | data class OpenSourceResponse(@Expose 10 | @SerializedName("status_code") 11 | private var statusCode: String? = null, 12 | 13 | @Expose 14 | @SerializedName("message") 15 | private var message: String? = null, 16 | 17 | @Expose 18 | @SerializedName("data") 19 | var data: List? = null) 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/preferences/AppPreferenceHelper.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.preferences 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import androidx.content.edit 6 | import com.mindorks.framework.mvp.di.PreferenceInfo 7 | import com.mindorks.framework.mvp.util.AppConstants 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by jyotidubey on 04/01/18. 12 | */ 13 | class AppPreferenceHelper @Inject constructor(context: Context, 14 | @PreferenceInfo private val prefFileName: String) : PreferenceHelper { 15 | companion object { 16 | private val PREF_KEY_USER_LOGGED_IN_MODE = "PREF_KEY_USER_LOGGED_IN_MODE" 17 | private val PREF_KEY_CURRENT_USER_ID = "PREF_KEY_CURRENT_USER_ID" 18 | private val PREF_KEY_ACCESS_TOKEN = "PREF_KEY_ACCESS_TOKEN" 19 | private val PREF_KEY_CURRENT_USER_NAME = "PREF_KEY_CURRENT_USER_NAME" 20 | private val PREF_KEY_CURRENT_USER_EMAIL = "PREF_KEY_CURRENT_USER_EMAIL" 21 | } 22 | 23 | private val mPrefs: SharedPreferences = context.getSharedPreferences(prefFileName, Context.MODE_PRIVATE) 24 | 25 | override fun getCurrentUserLoggedInMode() = mPrefs.getInt(PREF_KEY_USER_LOGGED_IN_MODE, AppConstants.LoggedInMode.LOGGED_IN_MODE_LOGGED_OUT.type) 26 | 27 | override fun getCurrentUserName(): String = mPrefs.getString(PREF_KEY_CURRENT_USER_NAME, "ABC") 28 | 29 | override fun setCurrentUserName(userName: String?) = mPrefs.edit { putString(PREF_KEY_CURRENT_USER_NAME, userName) } 30 | 31 | override fun getCurrentUserEmail(): String = mPrefs.getString(PREF_KEY_CURRENT_USER_EMAIL, "abc@gmail.com") 32 | 33 | override fun setCurrentUserEmail(email: String?) = mPrefs.edit { putString(PREF_KEY_CURRENT_USER_EMAIL, email) } 34 | 35 | override fun getAccessToken(): String = mPrefs.getString(PREF_KEY_ACCESS_TOKEN, "") 36 | 37 | override fun setAccessToken(accessToken: String?) = mPrefs.edit { putString(PREF_KEY_ACCESS_TOKEN, accessToken) } 38 | 39 | override fun getCurrentUserId(): Long? { 40 | val userId = mPrefs.getLong(PREF_KEY_CURRENT_USER_ID, AppConstants.NULL_INDEX) 41 | return when (userId) { 42 | AppConstants.NULL_INDEX -> null 43 | else -> userId 44 | } 45 | } 46 | 47 | override fun setCurrentUserId(userId: Long?) { 48 | val id = userId ?: AppConstants.NULL_INDEX 49 | mPrefs.edit { putLong(PREF_KEY_CURRENT_USER_ID, id) } 50 | } 51 | 52 | override fun setCurrentUserLoggedInMode(mode: AppConstants.LoggedInMode) { 53 | mPrefs.edit { putInt(PREF_KEY_USER_LOGGED_IN_MODE, mode.type) } 54 | } 55 | 56 | 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/data/preferences/PreferenceHelper.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.data.preferences 2 | 3 | import com.mindorks.framework.mvp.util.AppConstants 4 | 5 | /** 6 | * Created by jyotidubey on 04/01/18. 7 | */ 8 | interface PreferenceHelper { 9 | 10 | fun getCurrentUserLoggedInMode(): Int 11 | 12 | fun setCurrentUserLoggedInMode(mode: AppConstants.LoggedInMode) 13 | 14 | fun getCurrentUserId(): Long? 15 | 16 | fun setCurrentUserId(userId: Long?) 17 | 18 | fun getCurrentUserName(): String 19 | 20 | fun setCurrentUserName(userName: String?) 21 | 22 | fun getCurrentUserEmail(): String? 23 | 24 | fun setCurrentUserEmail(email: String?) 25 | 26 | fun getAccessToken(): String? 27 | 28 | fun setAccessToken(accessToken: String?) 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/di/ApiKeyInfo.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.di 2 | 3 | import javax.inject.Qualifier 4 | 5 | /** 6 | * Created by jyotidubey on 22/01/18. 7 | */ 8 | @Qualifier 9 | @Retention annotation class ApiKeyInfo -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/di/PreferenceInfo.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.di 2 | 3 | import javax.inject.Qualifier 4 | 5 | /** 6 | * Created by jyotidubey on 11/01/18. 7 | */ 8 | @Qualifier 9 | @Retention annotation class PreferenceInfo -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/di/builder/ActivityBuilder.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.di.builder 2 | 3 | import com.mindorks.framework.mvp.ui.about.AboutFragmentProvider 4 | import com.mindorks.framework.mvp.ui.feed.blog.BlogFragmentProvider 5 | import com.mindorks.framework.mvp.ui.feed.opensource.OpenSourceFragmentProvider 6 | import com.mindorks.framework.mvp.ui.feed.view.FeedActivity 7 | import com.mindorks.framework.mvp.ui.login.LoginActivityModule 8 | import com.mindorks.framework.mvp.ui.login.view.LoginActivity 9 | import com.mindorks.framework.mvp.ui.main.MainActivityModule 10 | import com.mindorks.framework.mvp.ui.main.view.MainActivity 11 | import com.mindorks.framework.mvp.ui.rate.RateUsDialogFragmentProvider 12 | import com.mindorks.framework.mvp.ui.splash.SplashActivityModule 13 | import com.mindorks.framework.mvp.ui.splash.view.SplashMVPActivity 14 | import dagger.Module 15 | import dagger.android.ContributesAndroidInjector 16 | 17 | /** 18 | * Created by jyotidubey on 05/01/18. 19 | */ 20 | @Module 21 | abstract class ActivityBuilder { 22 | 23 | @ContributesAndroidInjector(modules = [(SplashActivityModule::class)]) 24 | abstract fun bindSplashActivity(): SplashMVPActivity 25 | 26 | @ContributesAndroidInjector(modules = [(MainActivityModule::class), (RateUsDialogFragmentProvider::class), (AboutFragmentProvider::class)]) 27 | abstract fun bindMainActivity(): MainActivity 28 | 29 | @ContributesAndroidInjector(modules = [(LoginActivityModule::class)]) 30 | abstract fun bindLoginActivity(): LoginActivity 31 | 32 | @ContributesAndroidInjector(modules = [(BlogFragmentProvider::class), (OpenSourceFragmentProvider::class)]) 33 | abstract fun bindFeedActivity(): FeedActivity 34 | 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/di/component/AppComponent.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.di.component 2 | 3 | import android.app.Application 4 | import com.mindorks.framework.mvp.MvpApp 5 | import com.mindorks.framework.mvp.di.builder.ActivityBuilder 6 | import com.mindorks.framework.mvp.di.module.AppModule 7 | import dagger.BindsInstance 8 | import dagger.Component 9 | import dagger.android.AndroidInjectionModule 10 | import javax.inject.Singleton 11 | 12 | /** 13 | * Created by jyotidubey on 05/01/18. 14 | */ 15 | @Singleton 16 | @Component(modules = [(AndroidInjectionModule::class), (AppModule::class), (ActivityBuilder::class)]) 17 | interface AppComponent { 18 | 19 | @Component.Builder 20 | interface Builder { 21 | 22 | @BindsInstance 23 | fun application(application: Application): Builder 24 | 25 | fun build(): AppComponent 26 | } 27 | 28 | fun inject(app: MvpApp) 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/di/module/AppModule.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.di.module 2 | 3 | import android.app.Application 4 | import android.arch.persistence.room.Room 5 | import android.content.Context 6 | import com.mindorks.framework.mvp.BuildConfig 7 | import com.mindorks.framework.mvp.data.database.AppDatabase 8 | import com.mindorks.framework.mvp.data.database.repository.options.OptionsRepo 9 | import com.mindorks.framework.mvp.data.database.repository.options.OptionsRepository 10 | import com.mindorks.framework.mvp.data.database.repository.questions.QuestionRepo 11 | import com.mindorks.framework.mvp.data.database.repository.questions.QuestionRepository 12 | import com.mindorks.framework.mvp.data.network.ApiHeader 13 | import com.mindorks.framework.mvp.data.network.ApiHelper 14 | import com.mindorks.framework.mvp.data.network.AppApiHelper 15 | import com.mindorks.framework.mvp.data.preferences.AppPreferenceHelper 16 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 17 | import com.mindorks.framework.mvp.di.ApiKeyInfo 18 | import com.mindorks.framework.mvp.di.PreferenceInfo 19 | import com.mindorks.framework.mvp.util.AppConstants 20 | import com.mindorks.framework.mvp.util.SchedulerProvider 21 | import dagger.Module 22 | import dagger.Provides 23 | import io.reactivex.disposables.CompositeDisposable 24 | import javax.inject.Singleton 25 | 26 | /** 27 | * Created by jyotidubey on 05/01/18. 28 | */ 29 | @Module 30 | class AppModule { 31 | 32 | @Provides 33 | @Singleton 34 | internal fun provideContext(application: Application): Context = application 35 | 36 | @Provides 37 | @Singleton 38 | internal fun provideAppDatabase(context: Context): AppDatabase = 39 | Room.databaseBuilder(context, AppDatabase::class.java, AppConstants.APP_DB_NAME).build() 40 | 41 | @Provides 42 | @ApiKeyInfo 43 | internal fun provideApiKey(): String = BuildConfig.API_KEY 44 | 45 | @Provides 46 | @PreferenceInfo 47 | internal fun provideprefFileName(): String = AppConstants.PREF_NAME 48 | 49 | @Provides 50 | @Singleton 51 | internal fun providePrefHelper(appPreferenceHelper: AppPreferenceHelper): PreferenceHelper = appPreferenceHelper 52 | 53 | @Provides 54 | @Singleton 55 | internal fun provideProtectedApiHeader(@ApiKeyInfo apiKey: String, preferenceHelper: PreferenceHelper) 56 | : ApiHeader.ProtectedApiHeader = ApiHeader.ProtectedApiHeader(apiKey = apiKey, 57 | userId = preferenceHelper.getCurrentUserId(), 58 | accessToken = preferenceHelper.getAccessToken()) 59 | 60 | @Provides 61 | @Singleton 62 | internal fun provideApiHelper(appApiHelper: AppApiHelper): ApiHelper = appApiHelper 63 | 64 | @Provides 65 | @Singleton 66 | internal fun provideQuestionRepoHelper(appDatabase: AppDatabase): QuestionRepo = QuestionRepository(appDatabase.questionsDao()) 67 | 68 | @Provides 69 | @Singleton 70 | internal fun provideOptionsRepoHelper(appDatabase: AppDatabase): OptionsRepo = OptionsRepository(appDatabase.optionsDao()) 71 | 72 | @Provides 73 | internal fun provideCompositeDisposable(): CompositeDisposable = CompositeDisposable() 74 | 75 | @Provides 76 | internal fun provideSchedulerProvider(): SchedulerProvider = SchedulerProvider() 77 | 78 | 79 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/about/AboutFragmentProvider.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.about 2 | 3 | import com.mindorks.framework.mvp.ui.about.view.AboutFragment 4 | import dagger.Module 5 | import dagger.android.ContributesAndroidInjector 6 | 7 | /** 8 | * Created by jyotidubey on 15/01/18. 9 | */ 10 | @Module 11 | abstract class AboutFragmentProvider { 12 | 13 | @ContributesAndroidInjector 14 | abstract internal fun provideAboutFragment(): AboutFragment 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/about/view/AboutFragment.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.about.view 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import com.mindorks.framework.mvp.R 8 | import com.mindorks.framework.mvp.ui.base.view.BaseFragment 9 | import kotlinx.android.synthetic.main.fragment_about.* 10 | 11 | /** 12 | * Created by jyotidubey on 12/01/18. 13 | */ 14 | class AboutFragment : BaseFragment() { 15 | 16 | companion object { 17 | 18 | internal val TAG = "AboutFragment" 19 | 20 | fun newInstance(): AboutFragment { 21 | return AboutFragment() 22 | } 23 | 24 | } 25 | 26 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = 27 | inflater.inflate(R.layout.fragment_about, container, false) 28 | 29 | override fun setUp() = navBackBtn.setOnClickListener { getBaseActivity()?.onFragmentDetached(TAG) } 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/interactor/BaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.ApiHelper 4 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 5 | import com.mindorks.framework.mvp.util.AppConstants 6 | 7 | /** 8 | * Created by jyotidubey on 04/01/18. 9 | */ 10 | open class BaseInteractor() : MVPInteractor { 11 | 12 | protected lateinit var preferenceHelper: PreferenceHelper 13 | protected lateinit var apiHelper: ApiHelper 14 | 15 | constructor(preferenceHelper: PreferenceHelper, apiHelper: ApiHelper) : this() { 16 | this.preferenceHelper = preferenceHelper 17 | this.apiHelper = apiHelper 18 | } 19 | 20 | override fun isUserLoggedIn() = this.preferenceHelper.getCurrentUserLoggedInMode() != AppConstants.LoggedInMode.LOGGED_IN_MODE_LOGGED_OUT.type 21 | 22 | override fun performUserLogout() = preferenceHelper.let { 23 | it.setCurrentUserId(null) 24 | it.setAccessToken(null) 25 | it.setCurrentUserEmail(null) 26 | it.setCurrentUserLoggedInMode(AppConstants.LoggedInMode.LOGGED_IN_MODE_LOGGED_OUT) 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/interactor/MVPInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.interactor 2 | 3 | /** 4 | * Created by jyotidubey on 04/01/18. 5 | */ 6 | interface MVPInteractor { 7 | 8 | fun isUserLoggedIn(): Boolean 9 | 10 | fun performUserLogout() 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/presenter/BasePresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 4 | import com.mindorks.framework.mvp.ui.base.view.MVPView 5 | import com.mindorks.framework.mvp.util.SchedulerProvider 6 | import io.reactivex.disposables.CompositeDisposable 7 | 8 | /** 9 | * Created by jyotidubey on 04/01/18. 10 | */ 11 | abstract class BasePresenter internal constructor(protected var interactor: I?, protected val schedulerProvider: SchedulerProvider, protected val compositeDisposable: CompositeDisposable) : MVPPresenter { 12 | 13 | private var view: V? = null 14 | private val isViewAttached: Boolean get() = view != null 15 | 16 | override fun onAttach(view: V?) { 17 | this.view = view 18 | } 19 | 20 | override fun getView(): V? = view 21 | 22 | override fun onDetach() { 23 | compositeDisposable.dispose() 24 | view = null 25 | interactor = null 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/presenter/MVPPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 4 | import com.mindorks.framework.mvp.ui.base.view.MVPView 5 | 6 | /** 7 | * Created by jyotidubey on 04/01/18. 8 | */ 9 | interface MVPPresenter { 10 | 11 | fun onAttach(view: V?) 12 | 13 | fun onDetach() 14 | 15 | fun getView(): V? 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/view/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.view 2 | 3 | import android.app.ProgressDialog 4 | import android.os.Bundle 5 | import android.support.v7.app.AppCompatActivity 6 | import com.mindorks.framework.mvp.util.CommonUtil 7 | import dagger.android.AndroidInjection 8 | 9 | /** 10 | * Created by jyotidubey on 04/01/18. 11 | */ 12 | abstract class BaseActivity : AppCompatActivity(), MVPView, BaseFragment.CallBack { 13 | 14 | private var progressDialog: ProgressDialog? = null 15 | 16 | override fun onCreate(savedInstanceState: Bundle?) { 17 | performDI() 18 | super.onCreate(savedInstanceState) 19 | } 20 | 21 | override fun hideProgress() { 22 | progressDialog?.let { if (it.isShowing) it.cancel() } 23 | } 24 | 25 | override fun showProgress() { 26 | hideProgress() 27 | progressDialog = CommonUtil.showLoadingDialog(this) 28 | } 29 | 30 | private fun performDI() = AndroidInjection.inject(this) 31 | 32 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/view/BaseDialogView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.view 2 | 3 | import android.app.ProgressDialog 4 | import android.content.Context 5 | import android.os.Bundle 6 | import android.support.v4.app.DialogFragment 7 | import android.support.v4.app.FragmentManager 8 | import com.mindorks.framework.mvp.util.CommonUtil 9 | import dagger.android.support.AndroidSupportInjection 10 | 11 | 12 | /** 13 | * Created by jyotidubey on 14/01/18. 14 | */ 15 | abstract class BaseDialogView : DialogFragment(), DialogMVPView { 16 | 17 | private var parentActivity: BaseActivity? = null 18 | private var progressDialog: ProgressDialog? = null 19 | 20 | override fun onAttach(context: Context?) { 21 | super.onAttach(context) 22 | if (context is BaseActivity) { 23 | val activity = context as BaseActivity? 24 | this.parentActivity = activity 25 | activity?.onFragmentAttached() 26 | } 27 | } 28 | 29 | override fun onCreate(savedInstanceState: Bundle?) { 30 | super.onCreate(savedInstanceState) 31 | performDependencyInjection() 32 | } 33 | 34 | override fun show(fragmentManager: FragmentManager, tag: String) { 35 | val transaction = fragmentManager.beginTransaction() 36 | 37 | val prevFragment = fragmentManager.findFragmentByTag(tag) 38 | if (prevFragment != null) { 39 | transaction.remove(prevFragment) 40 | } 41 | transaction.addToBackStack(null) 42 | show(transaction, tag) 43 | } 44 | 45 | override fun hideProgress() { 46 | if (progressDialog != null && progressDialog?.isShowing!!) { 47 | progressDialog?.cancel() 48 | } 49 | } 50 | 51 | override fun showProgress() { 52 | hideProgress() 53 | progressDialog = CommonUtil.showLoadingDialog(this.context) 54 | } 55 | 56 | private fun performDependencyInjection() { 57 | AndroidSupportInjection.inject(this) 58 | } 59 | 60 | fun dismissDialog(tag: String) { 61 | dismiss() 62 | getBaseActivity()?.onFragmentDetached(tag) 63 | } 64 | 65 | private fun getBaseActivity(): BaseActivity? { 66 | return parentActivity 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/view/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.view 2 | 3 | import android.app.ProgressDialog 4 | import android.content.Context 5 | import android.os.Bundle 6 | import android.support.v4.app.Fragment 7 | import android.view.View 8 | import com.mindorks.framework.mvp.util.CommonUtil 9 | import dagger.android.support.AndroidSupportInjection 10 | 11 | 12 | /** 13 | * Created by jyotidubey on 12/01/18. 14 | */ 15 | abstract class BaseFragment : Fragment(), MVPView { 16 | 17 | private var parentActivity: BaseActivity? = null 18 | private var progressDialog: ProgressDialog? = null 19 | 20 | override fun onAttach(context: Context?) { 21 | super.onAttach(context) 22 | if (context is BaseActivity) { 23 | val activity = context as BaseActivity? 24 | this.parentActivity = activity 25 | activity?.onFragmentAttached() 26 | } 27 | } 28 | 29 | override fun onCreate(savedInstanceState: Bundle?) { 30 | performDependencyInjection() 31 | super.onCreate(savedInstanceState) 32 | setHasOptionsMenu(false) 33 | } 34 | 35 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 36 | super.onViewCreated(view, savedInstanceState) 37 | setUp() 38 | } 39 | 40 | override fun hideProgress() { 41 | if (progressDialog != null && progressDialog?.isShowing!!) { 42 | progressDialog?.cancel() 43 | } 44 | } 45 | 46 | override fun showProgress() { 47 | hideProgress() 48 | progressDialog = CommonUtil.showLoadingDialog(this.context) 49 | } 50 | 51 | fun getBaseActivity() = parentActivity 52 | 53 | private fun performDependencyInjection() = AndroidSupportInjection.inject(this) 54 | 55 | interface CallBack { 56 | fun onFragmentAttached() 57 | fun onFragmentDetached(tag: String) 58 | } 59 | 60 | abstract fun setUp() 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/view/DialogMVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.view 2 | 3 | /** 4 | * Created by jyotidubey on 15/01/18. 5 | */ 6 | interface DialogMVPView : MVPView -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/base/view/MVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.base.view 2 | 3 | /** 4 | * Created by jyotidubey on 04/01/18. 5 | */ 6 | interface MVPView { 7 | 8 | fun showProgress() 9 | 10 | fun hideProgress() 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/FeedPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed 2 | 3 | import android.support.v4.app.Fragment 4 | import android.support.v4.app.FragmentManager 5 | import android.support.v4.app.FragmentStatePagerAdapter 6 | import com.mindorks.framework.mvp.ui.feed.blog.view.BlogFragment 7 | import com.mindorks.framework.mvp.ui.feed.opensource.view.OpenSourceFragment 8 | 9 | /** 10 | * Created by jyotidubey on 13/01/18. 11 | */ 12 | class FeedPagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager) { 13 | 14 | private var tabCount = 0 15 | 16 | override fun getCount(): Int { 17 | return tabCount 18 | } 19 | 20 | override fun getItem(position: Int): Fragment? { 21 | return when (position) { 22 | 0 -> BlogFragment.newInstance() 23 | 1 -> OpenSourceFragment.newInstance() 24 | else -> null 25 | } 26 | } 27 | 28 | internal fun setCount(count: Int) { 29 | this.tabCount = count 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/BlogFragmentModule.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog 2 | 3 | import android.support.v7.widget.LinearLayoutManager 4 | import com.mindorks.framework.mvp.ui.feed.blog.interactor.BlogInteractor 5 | import com.mindorks.framework.mvp.ui.feed.blog.interactor.BlogMVPInteractor 6 | import com.mindorks.framework.mvp.ui.feed.blog.presenter.BlogMVPPresenter 7 | import com.mindorks.framework.mvp.ui.feed.blog.presenter.BlogPresenter 8 | import com.mindorks.framework.mvp.ui.feed.blog.view.BlogAdapter 9 | import com.mindorks.framework.mvp.ui.feed.blog.view.BlogFragment 10 | import com.mindorks.framework.mvp.ui.feed.blog.view.BlogMVPView 11 | import dagger.Module 12 | import dagger.Provides 13 | import java.util.* 14 | 15 | /** 16 | * Created by jyotidubey on 14/01/18. 17 | */ 18 | @Module 19 | class BlogFragmentModule { 20 | 21 | @Provides 22 | internal fun provideBlogInteractor(interactor: BlogInteractor): BlogMVPInteractor = interactor 23 | 24 | @Provides 25 | internal fun provideBlogPresenter(presenter: BlogPresenter) 26 | : BlogMVPPresenter = presenter 27 | 28 | @Provides 29 | internal fun provideBlogAdapter(): BlogAdapter = BlogAdapter(ArrayList()) 30 | 31 | @Provides 32 | internal fun provideLinearLayoutManager(fragment: BlogFragment): LinearLayoutManager = LinearLayoutManager(fragment.activity) 33 | 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/BlogFragmentProvider.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog 2 | 3 | import com.mindorks.framework.mvp.ui.feed.blog.view.BlogFragment 4 | import dagger.Module 5 | import dagger.android.ContributesAndroidInjector 6 | 7 | /** 8 | * Created by jyotidubey on 14/01/18. 9 | */ 10 | @Module 11 | internal abstract class BlogFragmentProvider { 12 | 13 | @ContributesAndroidInjector(modules = [BlogFragmentModule::class]) 14 | internal abstract fun provideBlogFragmentFactory(): BlogFragment 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/interactor/BlogInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.ApiHelper 4 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 5 | import com.mindorks.framework.mvp.ui.base.interactor.BaseInteractor 6 | import javax.inject.Inject 7 | 8 | /** 9 | * Created by jyotidubey on 13/01/18. 10 | */ 11 | class BlogInteractor @Inject internal constructor(preferenceHelper: PreferenceHelper, apiHelper: ApiHelper) : BaseInteractor(preferenceHelper, apiHelper), BlogMVPInteractor { 12 | 13 | override fun getBlogList() = apiHelper.getBlogApiCall() 14 | 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/interactor/BlogMVPInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.BlogResponse 4 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 5 | import io.reactivex.Observable 6 | 7 | /** 8 | * Created by jyotidubey on 13/01/18. 9 | */ 10 | interface BlogMVPInteractor : MVPInteractor { 11 | 12 | fun getBlogList(): Observable 13 | 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/presenter/BlogMVPPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.MVPPresenter 4 | import com.mindorks.framework.mvp.ui.feed.blog.interactor.BlogMVPInteractor 5 | import com.mindorks.framework.mvp.ui.feed.blog.view.BlogMVPView 6 | 7 | /** 8 | * Created by jyotidubey on 13/01/18. 9 | */ 10 | interface BlogMVPPresenter : MVPPresenter { 11 | 12 | fun onViewPrepared() 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/presenter/BlogPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.BasePresenter 4 | import com.mindorks.framework.mvp.ui.feed.blog.interactor.BlogMVPInteractor 5 | import com.mindorks.framework.mvp.ui.feed.blog.view.BlogMVPView 6 | import com.mindorks.framework.mvp.util.SchedulerProvider 7 | import io.reactivex.disposables.CompositeDisposable 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by jyotidubey on 13/01/18. 12 | */ 13 | class BlogPresenter @Inject constructor(interactor: I, schedulerProvider: SchedulerProvider, compositeDisposable: CompositeDisposable) : BasePresenter(interactor = interactor, schedulerProvider = schedulerProvider, compositeDisposable = compositeDisposable), BlogMVPPresenter { 14 | 15 | override fun onViewPrepared() { 16 | getView()?.showProgress() 17 | interactor?.let { 18 | it.getBlogList() 19 | .compose(schedulerProvider.ioToMainObservableScheduler()) 20 | .subscribe { blogResponse -> 21 | getView()?.let { 22 | it.hideProgress() 23 | it.displayBlogList(blogResponse.data) 24 | } 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/view/BlogAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog.view 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.support.v7.widget.RecyclerView 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import com.mindorks.framework.mvp.R 10 | import com.mindorks.framework.mvp.data.network.Blog 11 | import com.mindorks.framework.mvp.util.extension.loadImage 12 | import kotlinx.android.synthetic.main.item_blog_list.view.* 13 | 14 | 15 | /** 16 | * Created by jyotidubey on 14/01/18. 17 | */ 18 | class BlogAdapter(private val blogListItems: MutableList) : RecyclerView.Adapter() { 19 | 20 | override fun getItemCount() = this.blogListItems.size 21 | 22 | override fun onBindViewHolder(holder: BlogViewHolder, position: Int) = holder.let { 23 | it.clear() 24 | it.onBind(position) 25 | } 26 | 27 | override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int) = BlogViewHolder(LayoutInflater.from(parent?.context) 28 | .inflate(R.layout.item_blog_list, parent, false)) 29 | 30 | internal fun addBlogsToList(blogs: List) { 31 | this.blogListItems.addAll(blogs) 32 | notifyDataSetChanged() 33 | } 34 | 35 | inner class BlogViewHolder(view: View) : RecyclerView.ViewHolder(view) { 36 | 37 | fun clear() { 38 | itemView.coverImageView.setImageDrawable(null) 39 | itemView.titleTextView.text = "" 40 | itemView.contentTextView.text = "" 41 | } 42 | 43 | fun onBind(position: Int) { 44 | 45 | val (title, coverPageUrl, date, description, author, blogUrl) = blogListItems[position] 46 | 47 | inflateData(title, author, date, description, coverPageUrl) 48 | setItemClickListener(blogUrl) 49 | } 50 | 51 | private fun setItemClickListener(blogUrl: String?) { 52 | itemView.setOnClickListener { 53 | blogUrl?.let { 54 | try { 55 | val intent = Intent() 56 | // using "with" as an example 57 | with(intent) { 58 | action = Intent.ACTION_VIEW 59 | data = Uri.parse(it) 60 | addCategory(Intent.CATEGORY_BROWSABLE) 61 | } 62 | itemView.context.startActivity(intent) 63 | } catch (e: Exception) { 64 | } 65 | } 66 | 67 | } 68 | } 69 | 70 | private fun inflateData(title: String?, author: String?, date: String?, description: String?, coverPageUrl: String?) { 71 | title?.let { itemView.titleTextView.text = it } 72 | author?.let { itemView.authorTextView.text = it } 73 | date?.let { itemView.dateTextView.text = it } 74 | description?.let { itemView.contentTextView.text = it } 75 | coverPageUrl?.let { 76 | itemView.coverImageView.loadImage(it) 77 | } 78 | } 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/view/BlogFragment.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog.view 2 | 3 | import android.os.Bundle 4 | import android.support.v7.widget.DefaultItemAnimator 5 | import android.support.v7.widget.LinearLayoutManager 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import com.mindorks.framework.mvp.R 10 | import com.mindorks.framework.mvp.data.network.Blog 11 | import com.mindorks.framework.mvp.ui.base.view.BaseFragment 12 | import com.mindorks.framework.mvp.ui.feed.blog.interactor.BlogMVPInteractor 13 | import com.mindorks.framework.mvp.ui.feed.blog.presenter.BlogMVPPresenter 14 | import kotlinx.android.synthetic.main.fragment_blog.* 15 | import javax.inject.Inject 16 | 17 | 18 | /** 19 | * Created by jyotidubey on 13/01/18. 20 | */ 21 | class BlogFragment : BaseFragment(), BlogMVPView { 22 | 23 | companion object { 24 | 25 | fun newInstance(): BlogFragment { 26 | return BlogFragment() 27 | } 28 | } 29 | 30 | @Inject 31 | internal lateinit var blogAdapter: BlogAdapter 32 | @Inject 33 | internal lateinit var layoutManager: LinearLayoutManager 34 | @Inject 35 | internal lateinit var presenter: BlogMVPPresenter 36 | 37 | 38 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) 39 | = inflater.inflate(R.layout.fragment_blog, container, false) 40 | 41 | 42 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 43 | presenter.onAttach(this) 44 | super.onViewCreated(view, savedInstanceState) 45 | } 46 | 47 | override fun setUp() { 48 | layoutManager.orientation = LinearLayoutManager.VERTICAL 49 | blog_recycler_view.layoutManager = layoutManager 50 | blog_recycler_view.itemAnimator = DefaultItemAnimator() 51 | blog_recycler_view.adapter = blogAdapter 52 | presenter.onViewPrepared() 53 | } 54 | 55 | override fun displayBlogList(blogs: List?) = blogs?.let { 56 | blogAdapter.addBlogsToList(it) 57 | } 58 | 59 | override fun onDestroyView() { 60 | presenter.onDetach() 61 | super.onDestroyView() 62 | } 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/blog/view/BlogMVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.blog.view 2 | 3 | import com.mindorks.framework.mvp.data.network.Blog 4 | import com.mindorks.framework.mvp.ui.base.view.MVPView 5 | 6 | /** 7 | * Created by jyotidubey on 13/01/18. 8 | */ 9 | interface BlogMVPView : MVPView { 10 | 11 | fun displayBlogList(blogs: List?) : Unit? 12 | 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/OpenSourceFragmentModule.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource 2 | 3 | import android.support.v7.widget.LinearLayoutManager 4 | import com.mindorks.framework.mvp.ui.feed.opensource.interactor.OpenSourceInteractor 5 | import com.mindorks.framework.mvp.ui.feed.opensource.interactor.OpenSourceMVPInteractor 6 | import com.mindorks.framework.mvp.ui.feed.opensource.presenter.OpenSourceMVPPresenter 7 | import com.mindorks.framework.mvp.ui.feed.opensource.presenter.OpenSourcePresenter 8 | import com.mindorks.framework.mvp.ui.feed.opensource.view.OpenSourceAdapter 9 | import com.mindorks.framework.mvp.ui.feed.opensource.view.OpenSourceFragment 10 | import com.mindorks.framework.mvp.ui.feed.opensource.view.OpenSourceMVPView 11 | import dagger.Module 12 | import dagger.Provides 13 | 14 | /** 15 | * Created by jyotidubey on 14/01/18. 16 | */ 17 | @Module 18 | class OpenSourceFragmentModule { 19 | 20 | @Provides 21 | internal fun provideOpenSourceInteractor(interactor: OpenSourceInteractor): OpenSourceMVPInteractor = interactor 22 | 23 | @Provides 24 | internal fun provideOpenSourcePresenter(presenter: OpenSourcePresenter) 25 | : OpenSourceMVPPresenter = presenter 26 | 27 | @Provides 28 | internal fun provideOpenSourceAdapter(): OpenSourceAdapter = OpenSourceAdapter(ArrayList()) 29 | 30 | @Provides 31 | internal fun provideLinearLayoutManager(fragment: OpenSourceFragment): LinearLayoutManager = LinearLayoutManager(fragment.activity) 32 | 33 | 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/OpenSourceFragmentProvider.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource 2 | 3 | import com.mindorks.framework.mvp.ui.feed.opensource.view.OpenSourceFragment 4 | import dagger.Module 5 | import dagger.android.ContributesAndroidInjector 6 | 7 | /** 8 | * Created by jyotidubey on 14/01/18. 9 | */ 10 | @Module 11 | internal abstract class OpenSourceFragmentProvider { 12 | 13 | @ContributesAndroidInjector(modules = [(OpenSourceFragmentModule::class)]) 14 | internal abstract fun provideBlogFragmentFactory(): OpenSourceFragment 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/interactor/OpenSourceInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.ApiHelper 4 | import com.mindorks.framework.mvp.data.network.OpenSourceResponse 5 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 6 | import com.mindorks.framework.mvp.ui.base.interactor.BaseInteractor 7 | import io.reactivex.Observable 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by jyotidubey on 14/01/18. 12 | */ 13 | class OpenSourceInteractor @Inject internal constructor(preferenceHelper: PreferenceHelper, apiHelper: ApiHelper) : BaseInteractor(preferenceHelper, apiHelper), OpenSourceMVPInteractor { 14 | 15 | override fun getOpenSourceList(): Observable { 16 | return apiHelper.getOpenSourceApiCall() 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/interactor/OpenSourceMVPInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.OpenSourceResponse 4 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 5 | import io.reactivex.Observable 6 | 7 | /** 8 | * Created by jyotidubey on 14/01/18. 9 | */ 10 | interface OpenSourceMVPInteractor : MVPInteractor { 11 | 12 | fun getOpenSourceList(): Observable 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/presenter/OpenSourceMVPPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.MVPPresenter 4 | import com.mindorks.framework.mvp.ui.feed.opensource.interactor.OpenSourceMVPInteractor 5 | import com.mindorks.framework.mvp.ui.feed.opensource.view.OpenSourceMVPView 6 | 7 | /** 8 | * Created by jyotidubey on 14/01/18. 9 | */ 10 | interface OpenSourceMVPPresenter : MVPPresenter { 11 | 12 | fun onViewPrepared() 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/presenter/OpenSourcePresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.BasePresenter 4 | import com.mindorks.framework.mvp.ui.feed.opensource.interactor.OpenSourceMVPInteractor 5 | import com.mindorks.framework.mvp.ui.feed.opensource.view.OpenSourceMVPView 6 | import com.mindorks.framework.mvp.util.SchedulerProvider 7 | import io.reactivex.disposables.CompositeDisposable 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by jyotidubey on 14/01/18. 12 | */ 13 | class OpenSourcePresenter @Inject constructor(interactor: I, schedulerProvider: SchedulerProvider, compositeDisposable: CompositeDisposable) : BasePresenter(interactor = interactor, schedulerProvider = schedulerProvider, compositeDisposable = compositeDisposable), OpenSourceMVPPresenter { 14 | 15 | override fun onViewPrepared() { 16 | getView()?.showProgress() 17 | interactor?.let { 18 | compositeDisposable.add(it.getOpenSourceList() 19 | .compose(schedulerProvider.ioToMainObservableScheduler()) 20 | .subscribe { openSourceResponse -> 21 | getView()?.let { 22 | it.hideProgress() 23 | it.displayOpenSourceList(openSourceResponse.data) 24 | } 25 | }) 26 | } 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/view/OpenSourceAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource.view 2 | 3 | import android.content.Intent 4 | import android.support.v7.widget.RecyclerView 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.net.toUri 9 | import com.mindorks.framework.mvp.R 10 | import com.mindorks.framework.mvp.data.network.OpenSource 11 | import com.mindorks.framework.mvp.util.extension.loadImage 12 | import kotlinx.android.synthetic.main.item_open_source_list.view.* 13 | 14 | 15 | /** 16 | * Created by jyotidubey on 14/01/18. 17 | */ 18 | class OpenSourceAdapter(openSourceListItems: MutableList) : RecyclerView.Adapter() { 19 | 20 | private val openSourceListItems: MutableList = openSourceListItems 21 | 22 | 23 | override fun getItemCount() = openSourceListItems.size 24 | 25 | override fun onBindViewHolder(holder: OpenSourceViewHolder, position: Int) = holder.run { 26 | clear() 27 | onBind(position) 28 | } 29 | 30 | override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int) = OpenSourceViewHolder(LayoutInflater.from(parent?.context) 31 | .inflate(R.layout.item_open_source_list, parent, false)) 32 | 33 | 34 | internal fun addOpenSourcesToList(OpenSources: List) { 35 | this.openSourceListItems.addAll(OpenSources) 36 | notifyDataSetChanged() 37 | } 38 | 39 | inner class OpenSourceViewHolder(view: View) : RecyclerView.ViewHolder(view) { 40 | 41 | fun clear() { 42 | itemView.coverImageView.setImageDrawable(null) 43 | itemView.titleTextView.text = "" 44 | itemView.contentTextView.text = "" 45 | } 46 | 47 | fun onBind(position: Int) { 48 | val (projectUrl, coverImgUrl, title, description) = openSourceListItems[position] 49 | 50 | inflateData(title, description, coverImgUrl) 51 | setItemClickListener(projectUrl) 52 | } 53 | 54 | private fun setItemClickListener(projectUrl: String?) { 55 | itemView.setOnClickListener { 56 | projectUrl?.let { 57 | try { 58 | // using "apply" as an example 59 | itemView.context.startActivity(Intent().apply { 60 | action = Intent.ACTION_VIEW 61 | data = it.toUri() 62 | addCategory(Intent.CATEGORY_BROWSABLE) 63 | }) 64 | } catch (e: Exception) { 65 | } 66 | } 67 | } 68 | } 69 | 70 | private fun inflateData(title: String?, description: String?, coverImgUrl: String?) { 71 | title?.let { itemView.titleTextView.text = it } 72 | description?.let { itemView.contentTextView.text = it } 73 | coverImgUrl?.let { 74 | itemView.coverImageView.loadImage(it) 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/view/OpenSourceFragment.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource.view 2 | 3 | import android.os.Bundle 4 | import android.support.v7.widget.DefaultItemAnimator 5 | import android.support.v7.widget.LinearLayoutManager 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import com.mindorks.framework.mvp.R 10 | import com.mindorks.framework.mvp.data.network.OpenSource 11 | import com.mindorks.framework.mvp.ui.base.view.BaseFragment 12 | import com.mindorks.framework.mvp.ui.feed.opensource.interactor.OpenSourceMVPInteractor 13 | import com.mindorks.framework.mvp.ui.feed.opensource.presenter.OpenSourceMVPPresenter 14 | import kotlinx.android.synthetic.main.fragment_open_source.* 15 | import javax.inject.Inject 16 | 17 | /** 18 | * Created by jyotidubey on 13/01/18. 19 | */ 20 | class OpenSourceFragment : BaseFragment(), OpenSourceMVPView { 21 | 22 | companion object { 23 | 24 | fun newInstance(): OpenSourceFragment { 25 | return OpenSourceFragment() 26 | } 27 | 28 | } 29 | 30 | @Inject 31 | internal lateinit var openSourceAdapter: OpenSourceAdapter 32 | @Inject 33 | internal lateinit var layoutManager: LinearLayoutManager 34 | @Inject 35 | internal lateinit var presenter: OpenSourceMVPPresenter 36 | 37 | 38 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 39 | return inflater.inflate(R.layout.fragment_open_source, container, false) 40 | } 41 | 42 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 43 | presenter.onAttach(this) 44 | super.onViewCreated(view, savedInstanceState) 45 | } 46 | 47 | override fun setUp() { 48 | layoutManager.orientation = LinearLayoutManager.VERTICAL 49 | repo_recycler_view.layoutManager = layoutManager 50 | repo_recycler_view.itemAnimator = DefaultItemAnimator() 51 | repo_recycler_view.adapter = openSourceAdapter 52 | presenter.onViewPrepared() 53 | } 54 | 55 | override fun displayOpenSourceList(OpenSources: List?) { 56 | OpenSources?.let { 57 | openSourceAdapter.addOpenSourcesToList(it) 58 | } 59 | } 60 | 61 | override fun onDestroyView() { 62 | presenter.onDetach() 63 | super.onDestroyView() 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/opensource/view/OpenSourceMVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.opensource.view 2 | 3 | import com.mindorks.framework.mvp.data.network.OpenSource 4 | import com.mindorks.framework.mvp.ui.base.view.MVPView 5 | 6 | /** 7 | * Created by jyotidubey on 14/01/18. 8 | */ 9 | interface OpenSourceMVPView : MVPView { 10 | fun displayOpenSourceList(blogs: List?) 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/feed/view/FeedActivity.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.feed.view 2 | 3 | import android.os.Bundle 4 | import android.support.design.widget.TabLayout 5 | import android.support.v4.app.Fragment 6 | import com.mindorks.framework.mvp.R 7 | import com.mindorks.framework.mvp.ui.base.view.BaseActivity 8 | import com.mindorks.framework.mvp.ui.feed.FeedPagerAdapter 9 | import dagger.android.AndroidInjector 10 | import dagger.android.DispatchingAndroidInjector 11 | import dagger.android.support.HasSupportFragmentInjector 12 | import kotlinx.android.synthetic.main.activity_feed.* 13 | import javax.inject.Inject 14 | 15 | /** 16 | * Created by jyotidubey on 13/01/18. 17 | */ 18 | class FeedActivity : BaseActivity(), HasSupportFragmentInjector { 19 | 20 | @Inject 21 | internal lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector 22 | internal lateinit var feedPagerAdapter: FeedPagerAdapter 23 | 24 | 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | setContentView(R.layout.activity_feed) 28 | feedPagerAdapter = FeedPagerAdapter(supportFragmentManager) 29 | setUpFeedPagerAdapter() 30 | } 31 | 32 | override fun onFragmentAttached() { 33 | } 34 | 35 | override fun onFragmentDetached(tag: String) { 36 | } 37 | 38 | override fun supportFragmentInjector(): AndroidInjector? { 39 | return fragmentDispatchingAndroidInjector 40 | } 41 | 42 | private fun setUpFeedPagerAdapter() { 43 | feedPagerAdapter.count = 2 44 | feedViewPager.adapter = feedPagerAdapter 45 | tabLayout.addTab(tabLayout.newTab().setText(R.string.blogs)) 46 | tabLayout.addTab(tabLayout.newTab().setText(R.string.open_source)) 47 | feedViewPager.offscreenPageLimit = tabLayout.tabCount; 48 | feedViewPager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout)); 49 | tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { 50 | override fun onTabSelected(tab: TabLayout.Tab) { 51 | feedViewPager.currentItem = tab.position 52 | } 53 | override fun onTabUnselected(tab: TabLayout.Tab) {} 54 | override fun onTabReselected(tab: TabLayout.Tab) {} 55 | }) 56 | 57 | 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/login/LoginActivityModule.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.login 2 | 3 | import com.mindorks.framework.mvp.ui.login.interactor.LoginInteractor 4 | import com.mindorks.framework.mvp.ui.login.interactor.LoginMVPInteractor 5 | import com.mindorks.framework.mvp.ui.login.presenter.LoginMVPPresenter 6 | import com.mindorks.framework.mvp.ui.login.presenter.LoginPresenter 7 | import com.mindorks.framework.mvp.ui.login.view.LoginMVPView 8 | import dagger.Module 9 | import dagger.Provides 10 | 11 | /** 12 | * Created by jyotidubey on 10/01/18. 13 | */ 14 | @Module 15 | class LoginActivityModule { 16 | 17 | @Provides 18 | internal fun provideLoginInteractor(interactor: LoginInteractor): LoginMVPInteractor = interactor 19 | 20 | @Provides 21 | internal fun provideLoginPresenter(presenter: LoginPresenter) 22 | : LoginMVPPresenter = presenter 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/login/interactor/LoginInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.login.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.ApiHelper 4 | import com.mindorks.framework.mvp.data.network.LoginRequest 5 | import com.mindorks.framework.mvp.data.network.LoginResponse 6 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 7 | import com.mindorks.framework.mvp.ui.base.interactor.BaseInteractor 8 | import com.mindorks.framework.mvp.util.AppConstants 9 | import javax.inject.Inject 10 | 11 | /** 12 | * Created by jyotidubey on 10/01/18. 13 | */ 14 | class LoginInteractor @Inject internal constructor(preferenceHelper: PreferenceHelper, apiHelper: ApiHelper) : BaseInteractor(preferenceHelper, apiHelper), LoginMVPInteractor { 15 | 16 | override fun doGoogleLoginApiCall() = 17 | apiHelper.performGoogleLogin(LoginRequest.GoogleLoginRequest("test1", "test1")) 18 | 19 | override fun doFBLoginApiCall() = 20 | apiHelper.performFBLogin(LoginRequest.FacebookLoginRequest("test3", "test4")) 21 | 22 | 23 | override fun doServerLoginApiCall(email: String, password: String) = 24 | apiHelper.performServerLogin(LoginRequest.ServerLoginRequest(email = email, password = password)) 25 | 26 | 27 | override fun updateUserInSharedPref(loginResponse: LoginResponse, loggedInMode: AppConstants.LoggedInMode) = 28 | preferenceHelper.let { 29 | it.setCurrentUserId(loginResponse.userId) 30 | it.setAccessToken(loginResponse.accessToken) 31 | it.setCurrentUserLoggedInMode(loggedInMode) 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/login/interactor/LoginMVPInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.login.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.LoginResponse 4 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 5 | import com.mindorks.framework.mvp.util.AppConstants 6 | import io.reactivex.Observable 7 | 8 | /** 9 | * Created by jyotidubey on 10/01/18. 10 | */ 11 | interface LoginMVPInteractor : MVPInteractor { 12 | 13 | fun doServerLoginApiCall(email: String, password: String): Observable 14 | 15 | fun doFBLoginApiCall(): Observable 16 | 17 | fun doGoogleLoginApiCall(): Observable 18 | 19 | fun updateUserInSharedPref(loginResponse: LoginResponse, loggedInMode: AppConstants.LoggedInMode) 20 | 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/login/presenter/LoginMVPPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.login.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.MVPPresenter 4 | import com.mindorks.framework.mvp.ui.login.interactor.LoginMVPInteractor 5 | import com.mindorks.framework.mvp.ui.login.view.LoginMVPView 6 | 7 | /** 8 | * Created by jyotidubey on 10/01/18. 9 | */ 10 | interface LoginMVPPresenter : MVPPresenter { 11 | 12 | fun onServerLoginClicked(email: String, password: String) 13 | fun onFBLoginClicked() 14 | fun onGoogleLoginClicked() 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/login/presenter/LoginPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.login.presenter 2 | 3 | import com.mindorks.framework.mvp.data.network.LoginResponse 4 | import com.mindorks.framework.mvp.ui.base.presenter.BasePresenter 5 | import com.mindorks.framework.mvp.ui.login.interactor.LoginMVPInteractor 6 | import com.mindorks.framework.mvp.ui.login.view.LoginMVPView 7 | import com.mindorks.framework.mvp.util.AppConstants 8 | import com.mindorks.framework.mvp.util.SchedulerProvider 9 | import io.reactivex.disposables.CompositeDisposable 10 | import io.reactivex.functions.Consumer 11 | import javax.inject.Inject 12 | 13 | /** 14 | * Created by jyotidubey on 10/01/18. 15 | */ 16 | class LoginPresenter @Inject internal constructor(interactor: I, schedulerProvider: SchedulerProvider, disposable: CompositeDisposable) : BasePresenter(interactor = interactor, schedulerProvider = schedulerProvider, compositeDisposable = disposable), LoginMVPPresenter { 17 | 18 | override fun onServerLoginClicked(email: String, password: String) { 19 | when { 20 | email.isEmpty() -> getView()?.showValidationMessage(AppConstants.EMPTY_EMAIL_ERROR) 21 | password.isEmpty() -> getView()?.showValidationMessage(AppConstants.EMPTY_PASSWORD_ERROR) 22 | else -> { 23 | getView()?.showProgress() 24 | interactor?.let { 25 | compositeDisposable.add(it.doServerLoginApiCall(email, password) 26 | .compose(schedulerProvider.ioToMainObservableScheduler()) 27 | .subscribe({ loginResponse -> 28 | updateUserInSharedPref(loginResponse = loginResponse, 29 | loggedInMode = AppConstants.LoggedInMode.LOGGED_IN_MODE_SERVER) 30 | getView()?.openMainActivity() 31 | }, { err -> println(err) })) 32 | } 33 | 34 | } 35 | } 36 | } 37 | 38 | override fun onFBLoginClicked() { 39 | getView()?.showProgress() 40 | interactor?.let { 41 | compositeDisposable.add(it.doFBLoginApiCall() 42 | .compose(schedulerProvider.ioToMainObservableScheduler()) 43 | .subscribe({ loginResponse -> 44 | updateUserInSharedPref(loginResponse = loginResponse, 45 | loggedInMode = AppConstants.LoggedInMode.LOGGED_IN_MODE_FB) 46 | getView()?.let { 47 | it.hideProgress() 48 | it.openMainActivity() 49 | } 50 | }, { err -> println(err) })) 51 | } 52 | 53 | 54 | } 55 | 56 | override fun onGoogleLoginClicked() { 57 | getView()?.showProgress() 58 | interactor?.let { 59 | compositeDisposable.add(it.doGoogleLoginApiCall() 60 | .compose(schedulerProvider.ioToMainObservableScheduler()) 61 | .subscribe({ loginResponse -> 62 | updateUserInSharedPref(loginResponse = loginResponse, 63 | loggedInMode = AppConstants.LoggedInMode.LOGGED_IN_MODE_GOOGLE) 64 | getView()?.let { 65 | it.hideProgress() 66 | it.openMainActivity() 67 | } 68 | }, { err -> println(err) })) 69 | } 70 | 71 | } 72 | 73 | private fun updateUserInSharedPref(loginResponse: LoginResponse, 74 | loggedInMode: AppConstants.LoggedInMode) = 75 | interactor?.updateUserInSharedPref(loginResponse, loggedInMode) 76 | 77 | 78 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/login/view/LoginActivity.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.login.view 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.widget.Toast 6 | import com.mindorks.framework.mvp.R 7 | import com.mindorks.framework.mvp.ui.base.view.BaseActivity 8 | import com.mindorks.framework.mvp.ui.login.interactor.LoginMVPInteractor 9 | import com.mindorks.framework.mvp.ui.login.presenter.LoginMVPPresenter 10 | import com.mindorks.framework.mvp.ui.main.view.MainActivity 11 | import com.mindorks.framework.mvp.util.AppConstants 12 | import kotlinx.android.synthetic.main.activity_login.* 13 | import javax.inject.Inject 14 | 15 | /** 16 | * Created by jyotidubey on 10/01/18. 17 | */ 18 | class LoginActivity : BaseActivity(), LoginMVPView { 19 | 20 | @Inject 21 | internal lateinit var presenter: LoginMVPPresenter 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContentView(R.layout.activity_login) 26 | presenter.onAttach(this) 27 | setOnClickListeners() 28 | } 29 | 30 | override fun onDestroy() { 31 | presenter.onDetach() 32 | super.onDestroy() 33 | } 34 | 35 | override fun onFragmentDetached(tag: String) { 36 | } 37 | 38 | override fun onFragmentAttached() { 39 | } 40 | 41 | override fun showValidationMessage(errorCode: Int) { 42 | when (errorCode) { 43 | AppConstants.EMPTY_EMAIL_ERROR -> Toast.makeText(this, getString(R.string.empty_email_error_message), Toast.LENGTH_LONG).show() 44 | AppConstants.INVALID_EMAIL_ERROR -> Toast.makeText(this, getString(R.string.invalid_email_error_message), Toast.LENGTH_LONG).show() 45 | AppConstants.EMPTY_PASSWORD_ERROR -> Toast.makeText(this, getString(R.string.empty_password_error_message), Toast.LENGTH_LONG).show() 46 | AppConstants.LOGIN_FAILURE -> Toast.makeText(this, getString(R.string.login_failure), Toast.LENGTH_LONG).show() 47 | } 48 | } 49 | 50 | override fun openMainActivity() { 51 | val intent = Intent(this, MainActivity::class.java) 52 | startActivity(intent) 53 | finish() 54 | } 55 | 56 | private fun setOnClickListeners() { 57 | btnServerLogin.setOnClickListener { presenter.onServerLoginClicked(et_email.text.toString(), et_password.text.toString()) } 58 | ibGoogleLogin.setOnClickListener { presenter.onGoogleLoginClicked() } 59 | ibFbLogin.setOnClickListener { presenter.onFBLoginClicked() } 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/login/view/LoginMVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.login.view 2 | 3 | import com.mindorks.framework.mvp.ui.base.view.MVPView 4 | 5 | /** 6 | * Created by jyotidubey on 10/01/18. 7 | */ 8 | interface LoginMVPView : MVPView { 9 | 10 | fun showValidationMessage(errorCode: Int) 11 | fun openMainActivity() 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/MainActivityModule.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main 2 | 3 | import com.mindorks.framework.mvp.ui.main.interactor.MainInteractor 4 | import com.mindorks.framework.mvp.ui.main.interactor.MainMVPInteractor 5 | import com.mindorks.framework.mvp.ui.main.presenter.MainMVPPresenter 6 | import com.mindorks.framework.mvp.ui.main.presenter.MainPresenter 7 | import com.mindorks.framework.mvp.ui.main.view.MainMVPView 8 | import dagger.Module 9 | import dagger.Provides 10 | 11 | /** 12 | * Created by jyotidubey on 09/01/18. 13 | */ 14 | @Module 15 | class MainActivityModule { 16 | 17 | @Provides 18 | internal fun provideMainInteractor(mainInteractor: MainInteractor): MainMVPInteractor = mainInteractor 19 | 20 | @Provides 21 | internal fun provideMainPresenter(mainPresenter: MainPresenter) 22 | : MainMVPPresenter = mainPresenter 23 | 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/interactor/MainInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main.interactor 2 | 3 | import com.mindorks.framework.mvp.data.database.repository.options.Options 4 | import com.mindorks.framework.mvp.data.database.repository.options.OptionsRepo 5 | import com.mindorks.framework.mvp.data.database.repository.questions.Question 6 | import com.mindorks.framework.mvp.data.database.repository.questions.QuestionRepo 7 | import com.mindorks.framework.mvp.data.network.ApiHelper 8 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 9 | import com.mindorks.framework.mvp.ui.base.interactor.BaseInteractor 10 | import javax.inject.Inject 11 | 12 | /** 13 | * Created by jyotidubey on 08/01/18. 14 | */ 15 | class MainInteractor @Inject internal constructor(private val questionRepoHelper: QuestionRepo, private val optionsRepoHelper: OptionsRepo, preferenceHelper: PreferenceHelper, apiHelper: ApiHelper) : BaseInteractor(preferenceHelper = preferenceHelper, apiHelper = apiHelper), MainMVPInteractor { 16 | 17 | override fun getQuestionCardData() = questionRepoHelper.loadQuestions() 18 | .flatMapIterable { question -> question } 19 | .flatMapSingle { question -> getQuestionCards(question) } 20 | .toList() 21 | 22 | override fun getUserDetails() = Pair(preferenceHelper.getCurrentUserName(), 23 | preferenceHelper.getCurrentUserEmail()) 24 | 25 | override fun makeLogoutApiCall() = apiHelper.performLogoutApiCall() 26 | 27 | private fun getQuestionCards(question: Question) = optionsRepoHelper.loadOptions(question.id) 28 | .map { options -> createQuestionCard(options, question) } 29 | 30 | private fun createQuestionCard(options: List, question: Question) = QuestionCardData(options, question) 31 | 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/interactor/MainMVPInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.LogoutResponse 4 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 5 | import io.reactivex.Observable 6 | import io.reactivex.Single 7 | 8 | /** 9 | * Created by jyotidubey on 08/01/18. 10 | */ 11 | interface MainMVPInteractor : MVPInteractor { 12 | 13 | fun getQuestionCardData(): Single> 14 | fun getUserDetails() : Pair 15 | fun makeLogoutApiCall() : Observable 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/interactor/QuestionCardData.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main.interactor 2 | 3 | import com.mindorks.framework.mvp.data.database.repository.options.Options 4 | import com.mindorks.framework.mvp.data.database.repository.questions.Question 5 | 6 | /** 7 | * Created by jyotidubey on 08/01/18. 8 | */ 9 | data class QuestionCardData(val option: List, val question: Question) -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/presenter/MainMVPPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.MVPPresenter 4 | import com.mindorks.framework.mvp.ui.main.interactor.MainMVPInteractor 5 | import com.mindorks.framework.mvp.ui.main.view.MainMVPView 6 | 7 | /** 8 | * Created by jyotidubey on 08/01/18. 9 | */ 10 | interface MainMVPPresenter : MVPPresenter { 11 | 12 | fun refreshQuestionCards(): Boolean? 13 | fun onDrawerOptionAboutClick() : Unit? 14 | fun onDrawerOptionRateUsClick(): Unit? 15 | fun onDrawerOptionFeedClick(): Unit? 16 | fun onDrawerOptionLogoutClick() 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/presenter/MainPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.BasePresenter 4 | import com.mindorks.framework.mvp.ui.main.interactor.MainMVPInteractor 5 | import com.mindorks.framework.mvp.ui.main.view.MainMVPView 6 | import com.mindorks.framework.mvp.util.SchedulerProvider 7 | import io.reactivex.disposables.CompositeDisposable 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by jyotidubey on 08/01/18. 12 | */ 13 | class MainPresenter @Inject internal constructor(interactor: I, schedulerProvider: SchedulerProvider, disposable: CompositeDisposable) : BasePresenter(interactor = interactor, schedulerProvider = schedulerProvider, compositeDisposable = disposable), MainMVPPresenter { 14 | 15 | override fun onAttach(view: V?) { 16 | super.onAttach(view) 17 | getUserData() 18 | getQuestionCards() 19 | } 20 | 21 | override fun refreshQuestionCards() = getQuestionCards() 22 | 23 | override fun onDrawerOptionRateUsClick() = getView()?.openRateUsDialog() 24 | 25 | override fun onDrawerOptionFeedClick() = getView()?.openFeedActivity() 26 | 27 | override fun onDrawerOptionAboutClick() = getView()?.openAboutFragment() 28 | 29 | override fun onDrawerOptionLogoutClick() { 30 | getView()?.showProgress() 31 | interactor?.let { 32 | compositeDisposable.add( 33 | it.makeLogoutApiCall() 34 | .compose(schedulerProvider.ioToMainObservableScheduler()) 35 | .subscribe({ 36 | interactor?.performUserLogout() 37 | getView()?.let { 38 | it.hideProgress() 39 | it.openLoginActivity() 40 | } 41 | }, { err -> println(err) })) 42 | } 43 | 44 | } 45 | 46 | private fun getQuestionCards() = interactor?.let { 47 | compositeDisposable.add(it.getQuestionCardData() 48 | .compose(schedulerProvider.ioToMainSingleScheduler()) 49 | .subscribe({ questionCard -> 50 | getView()?.let { 51 | if (questionCard.isEmpty()) return@subscribe 52 | else it.displayQuestionCard(questionCard) 53 | } 54 | }, { err -> println(err) })) 55 | } 56 | 57 | 58 | private fun getUserData() = interactor?.let { 59 | val userData = it.getUserDetails() 60 | getView()?.inflateUserDetails(userData) 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/view/MainMVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main.view 2 | 3 | import com.mindorks.framework.mvp.ui.base.view.MVPView 4 | import com.mindorks.framework.mvp.ui.main.interactor.QuestionCardData 5 | 6 | /** 7 | * Created by jyotidubey on 08/01/18. 8 | */ 9 | interface MainMVPView : MVPView { 10 | 11 | fun inflateUserDetails(userDetails: Pair) 12 | fun displayQuestionCard(questionCard: List) 13 | fun openLoginActivity() 14 | fun openFeedActivity() 15 | fun openAboutFragment() 16 | fun openRateUsDialog(): Unit? 17 | fun lockDrawer(): Unit? 18 | fun unlockDrawer(): Unit? 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/main/view/QuestionCardView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.main.view 2 | 3 | import android.graphics.Color 4 | import android.widget.Button 5 | import android.widget.TextView 6 | import com.androidnetworking.widget.ANImageView 7 | import com.mindorks.framework.mvp.R 8 | import com.mindorks.framework.mvp.ui.main.interactor.QuestionCardData 9 | import com.mindorks.placeholderview.annotations.* 10 | 11 | /** 12 | * Created by jyotidubey on 09/01/18. 13 | */ 14 | @NonReusable 15 | @Layout(R.layout.card_layout) 16 | class QuestionCard(private val mQuestion: QuestionCardData) { 17 | 18 | @View(R.id.tv_question_txt) 19 | private lateinit var mQuestionTextView: TextView 20 | 21 | @View(R.id.btn_option_1) 22 | private lateinit var mOption1Button: Button 23 | 24 | @View(R.id.btn_option_2) 25 | private lateinit var mOption2Button: Button 26 | 27 | @View(R.id.btn_option_3) 28 | private lateinit var mOption3Button: Button 29 | 30 | @View(R.id.iv_pic) 31 | private lateinit var mPicImageView: ANImageView 32 | 33 | @Click(R.id.btn_option_1) 34 | internal fun onOption1Click() { 35 | showCorrectOptions() 36 | } 37 | 38 | @Click(R.id.btn_option_2) 39 | internal fun onOption2Click() { 40 | showCorrectOptions() 41 | } 42 | 43 | @Click(R.id.btn_option_3) 44 | internal fun onOption3Click() { 45 | showCorrectOptions() 46 | } 47 | 48 | @Resolve 49 | private fun onResolved() { 50 | mQuestionTextView.text = mQuestion.question.questionText 51 | for (i in 0..2) { 52 | var button: Button? = null 53 | when (i) { 54 | 0 -> button = mOption1Button 55 | 1 -> button = mOption2Button 56 | 2 -> button = mOption3Button 57 | } 58 | button?.text = mQuestion.option[i].optionText 59 | mQuestion.question.imgUrl?.let { mPicImageView.setImageUrl(it) } 60 | 61 | } 62 | } 63 | 64 | private fun showCorrectOptions() { 65 | for (i in 0..2) { 66 | val option = mQuestion.option[i] 67 | var button: Button? = null 68 | when (i) { 69 | 0 -> button = mOption1Button 70 | 1 -> button = mOption2Button 71 | 2 -> button = mOption3Button 72 | } 73 | button?.let{ 74 | if(option.isCorrect) it.setBackgroundColor(Color.GREEN) else it.setBackgroundColor(Color.RED) 75 | } 76 | 77 | } 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/RateUsDialogFragmentProvider.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate 2 | 3 | import com.mindorks.framework.mvp.ui.rate.view.RateUsDialog 4 | import dagger.Module 5 | import dagger.android.ContributesAndroidInjector 6 | 7 | /** 8 | * Created by jyotidubey on 15/01/18. 9 | */ 10 | @Module 11 | abstract class RateUsDialogFragmentProvider{ 12 | 13 | @ContributesAndroidInjector(modules = [RateUsFragmentModule::class]) 14 | internal abstract fun provideRateUsFragment() : RateUsDialog 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/RateUsFragmentModule.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate 2 | 3 | import com.mindorks.framework.mvp.ui.rate.interactor.RateUsInteractor 4 | import com.mindorks.framework.mvp.ui.rate.interactor.RateUsMVPInterator 5 | import com.mindorks.framework.mvp.ui.rate.presenter.RateUsMVPPresenter 6 | import com.mindorks.framework.mvp.ui.rate.presenter.RateUsPresenter 7 | import com.mindorks.framework.mvp.ui.rate.view.RateUsDialogMVPView 8 | import dagger.Module 9 | import dagger.Provides 10 | 11 | /** 12 | * Created by jyotidubey on 15/01/18. 13 | */ 14 | @Module 15 | class RateUsFragmentModule { 16 | 17 | @Provides 18 | internal fun provideRateUsInteractor(interactor: RateUsInteractor): RateUsMVPInterator = interactor 19 | 20 | @Provides 21 | internal fun provideRateUsPresenter(presenter: RateUsPresenter) 22 | : RateUsMVPPresenter = presenter 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/interactor/RateUsInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate.interactor 2 | 3 | import com.mindorks.framework.mvp.data.network.ApiHelper 4 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 5 | import com.mindorks.framework.mvp.ui.base.interactor.BaseInteractor 6 | import javax.inject.Inject 7 | 8 | /** 9 | * Created by jyotidubey on 15/01/18. 10 | */ 11 | class RateUsInteractor @Inject internal constructor(apiHelper: ApiHelper, preferenceHelper: PreferenceHelper) : BaseInteractor(apiHelper = apiHelper, preferenceHelper = preferenceHelper), RateUsMVPInterator { 12 | 13 | override fun submitRating() {} 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/interactor/RateUsMVPInterator.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate.interactor 2 | 3 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 4 | 5 | /** 6 | * Created by jyotidubey on 15/01/18. 7 | */ 8 | interface RateUsMVPInterator : MVPInteractor{ 9 | 10 | fun submitRating() 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/presenter/RateUsMVPPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.MVPPresenter 4 | import com.mindorks.framework.mvp.ui.rate.interactor.RateUsMVPInterator 5 | import com.mindorks.framework.mvp.ui.rate.view.RateUsDialogMVPView 6 | 7 | /** 8 | * Created by jyotidubey on 15/01/18. 9 | */ 10 | interface RateUsMVPPresenter : MVPPresenter { 11 | 12 | fun onLaterOptionClicked() : Unit? 13 | fun onSubmitOptionClicked() : Unit? 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/presenter/RateUsPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.BasePresenter 4 | import com.mindorks.framework.mvp.ui.rate.interactor.RateUsMVPInterator 5 | import com.mindorks.framework.mvp.ui.rate.view.RateUsDialogMVPView 6 | import com.mindorks.framework.mvp.util.SchedulerProvider 7 | import io.reactivex.disposables.CompositeDisposable 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by jyotidubey on 15/01/18. 12 | */ 13 | class RateUsPresenter @Inject internal constructor(interator: I, schedulerProvider: SchedulerProvider, compositeDisposable: CompositeDisposable) : BasePresenter(interactor = interator, schedulerProvider = schedulerProvider, compositeDisposable = compositeDisposable), RateUsMVPPresenter { 14 | 15 | override fun onLaterOptionClicked() = getView()?.let { it.dismissDialog() } 16 | 17 | override fun onSubmitOptionClicked() = interactor?.let { 18 | it.submitRating() 19 | getView()?.let { 20 | it.showRatingSubmissionSuccessMessage() 21 | it.dismissDialog() 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/view/RateUsDialog.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate.view 2 | 3 | import android.os.Bundle 4 | import android.support.v4.app.FragmentManager 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.Toast 9 | import com.mindorks.framework.mvp.R 10 | import com.mindorks.framework.mvp.ui.base.view.BaseDialogView 11 | import com.mindorks.framework.mvp.ui.rate.interactor.RateUsMVPInterator 12 | import com.mindorks.framework.mvp.ui.rate.presenter.RateUsMVPPresenter 13 | import kotlinx.android.synthetic.main.dialog_rate_us.* 14 | import javax.inject.Inject 15 | 16 | /** 17 | * Created by jyotidubey on 14/01/18. 18 | */ 19 | class RateUsDialog : BaseDialogView(), RateUsDialogMVPView { 20 | 21 | companion object { 22 | fun newInstance(): RateUsDialog? { 23 | return RateUsDialog() 24 | } 25 | 26 | } 27 | 28 | @Inject 29 | internal lateinit var presenter: RateUsMVPPresenter 30 | 31 | private val TAG = "RateUsDialog" 32 | 33 | 34 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = 35 | inflater.inflate(R.layout.dialog_rate_us, container, false) 36 | 37 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 38 | super.onViewCreated(view, savedInstanceState) 39 | presenter.onAttach(this) 40 | btnLater.setOnClickListener { presenter.onLaterOptionClicked() } 41 | btnSubmit.setOnClickListener { presenter.onSubmitOptionClicked() } 42 | } 43 | 44 | override fun onDestroyView() { 45 | presenter.onDetach() 46 | super.onDestroyView() 47 | } 48 | 49 | override fun dismissDialog() = super.dismissDialog(TAG) 50 | 51 | override fun showRatingSubmissionSuccessMessage() = Toast.makeText(context, getString(R.string.rating_submitted_successfully), Toast.LENGTH_LONG).show() 52 | 53 | internal fun show(fragmentManager: FragmentManager) = super.show(fragmentManager, TAG) 54 | 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/rate/view/RateUsDialogMVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.rate.view 2 | 3 | import com.mindorks.framework.mvp.ui.base.view.MVPView 4 | 5 | /** 6 | * Created by jyotidubey on 14/01/18. 7 | */ 8 | interface RateUsDialogMVPView : MVPView{ 9 | 10 | fun dismissDialog() 11 | fun showRatingSubmissionSuccessMessage() 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/splash/SplashActivityModule.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.splash 2 | 3 | import com.mindorks.framework.mvp.ui.splash.interactor.SplashInteractor 4 | import com.mindorks.framework.mvp.ui.splash.interactor.SplashMVPInteractor 5 | import com.mindorks.framework.mvp.ui.splash.presenter.SplashMVPPresenter 6 | import com.mindorks.framework.mvp.ui.splash.presenter.SplashPresenter 7 | import com.mindorks.framework.mvp.ui.splash.view.SplashMVPView 8 | import dagger.Module 9 | import dagger.Provides 10 | 11 | /** 12 | * Created by jyotidubey on 06/01/18. 13 | */ 14 | @Module 15 | class SplashActivityModule { 16 | 17 | @Provides 18 | internal fun provideSplashInteractor(splashInteractor: SplashInteractor): SplashMVPInteractor = splashInteractor 19 | 20 | @Provides 21 | internal fun provideSplashPresenter(splashPresenter: SplashPresenter) 22 | : SplashMVPPresenter = splashPresenter 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/splash/interactor/SplashInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.splash.interactor 2 | 3 | import android.content.Context 4 | import com.google.gson.GsonBuilder 5 | import com.google.gson.internal.`$Gson$Types` 6 | import com.mindorks.framework.mvp.data.database.repository.options.Options 7 | import com.mindorks.framework.mvp.data.database.repository.options.OptionsRepo 8 | import com.mindorks.framework.mvp.data.database.repository.questions.Question 9 | import com.mindorks.framework.mvp.data.database.repository.questions.QuestionRepo 10 | import com.mindorks.framework.mvp.data.network.ApiHelper 11 | import com.mindorks.framework.mvp.data.preferences.PreferenceHelper 12 | import com.mindorks.framework.mvp.ui.base.interactor.BaseInteractor 13 | import com.mindorks.framework.mvp.util.AppConstants 14 | import com.mindorks.framework.mvp.util.FileUtils 15 | import io.reactivex.Observable 16 | import javax.inject.Inject 17 | 18 | /** 19 | * Created by jyotidubey on 04/01/18. 20 | */ 21 | class SplashInteractor @Inject constructor(private val mContext: Context, private val questionRepoHelper: QuestionRepo, private val optionsRepoHelper: OptionsRepo, preferenceHelper: PreferenceHelper, apiHelper: ApiHelper) : BaseInteractor(preferenceHelper, apiHelper), SplashMVPInteractor { 22 | 23 | override fun getQuestion(): Observable> { 24 | return questionRepoHelper.loadQuestions() 25 | } 26 | 27 | override fun seedQuestions(): Observable { 28 | val builder = GsonBuilder().excludeFieldsWithoutExposeAnnotation() 29 | val gson = builder.create() 30 | return questionRepoHelper.isQuestionsRepoEmpty().concatMap { isEmpty -> 31 | if (isEmpty) { 32 | val type = `$Gson$Types`.newParameterizedTypeWithOwner(null, List::class.java, Question::class.java) 33 | val questionList = gson.fromJson>( 34 | FileUtils.loadJSONFromAsset( 35 | mContext, 36 | AppConstants.SEED_DATABASE_QUESTIONS), 37 | type) 38 | questionRepoHelper.insertQuestions(questionList) 39 | } else 40 | Observable.just(false) 41 | } 42 | } 43 | 44 | override fun seedOptions(): Observable { 45 | val builder = GsonBuilder().excludeFieldsWithoutExposeAnnotation() 46 | val gson = builder.create() 47 | return optionsRepoHelper.isOptionsRepoEmpty().concatMap { isEmpty -> 48 | if (isEmpty) { 49 | val type = `$Gson$Types`.newParameterizedTypeWithOwner(null, List::class.java, Options::class.java) 50 | val optionsList = gson.fromJson>( 51 | FileUtils.loadJSONFromAsset( 52 | mContext, 53 | AppConstants.SEED_DATABASE_OPTIONS), 54 | type) 55 | optionsRepoHelper.insertOptions(optionsList) 56 | } else 57 | Observable.just(false) 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/splash/interactor/SplashMVPInteractor.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.splash.interactor 2 | 3 | import com.mindorks.framework.mvp.data.database.repository.questions.Question 4 | import com.mindorks.framework.mvp.ui.base.interactor.MVPInteractor 5 | import io.reactivex.Observable 6 | 7 | /** 8 | * Created by jyotidubey on 04/01/18. 9 | */ 10 | interface SplashMVPInteractor : MVPInteractor { 11 | 12 | fun seedQuestions(): Observable 13 | fun seedOptions(): Observable 14 | fun getQuestion() : Observable> 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/splash/presenter/SplashMVPPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.splash.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.MVPPresenter 4 | import com.mindorks.framework.mvp.ui.splash.interactor.SplashMVPInteractor 5 | import com.mindorks.framework.mvp.ui.splash.view.SplashMVPView 6 | 7 | /** 8 | * Created by jyotidubey on 04/01/18. 9 | */ 10 | interface SplashMVPPresenter : MVPPresenter -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/splash/presenter/SplashPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.splash.presenter 2 | 3 | import com.mindorks.framework.mvp.ui.base.presenter.BasePresenter 4 | import com.mindorks.framework.mvp.ui.splash.interactor.SplashMVPInteractor 5 | import com.mindorks.framework.mvp.ui.splash.view.SplashMVPView 6 | import com.mindorks.framework.mvp.util.SchedulerProvider 7 | import io.reactivex.disposables.CompositeDisposable 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by jyotidubey on 04/01/18. 12 | */ 13 | class SplashPresenter @Inject internal constructor(interactor: I, schedulerProvider: SchedulerProvider, disposable: CompositeDisposable) : BasePresenter(interactor = interactor, schedulerProvider = schedulerProvider, compositeDisposable = disposable), SplashMVPPresenter { 14 | 15 | override fun onAttach(view: V?) { 16 | super.onAttach(view) 17 | feedInDatabase() 18 | } 19 | 20 | private fun feedInDatabase() = interactor?.let { 21 | compositeDisposable.add(it.seedQuestions() 22 | .flatMap { interactor?.seedOptions() } 23 | .compose(schedulerProvider.ioToMainObservableScheduler()) 24 | .subscribe({ 25 | getView()?.let { decideActivityToOpen() } 26 | })) 27 | } 28 | 29 | private fun decideActivityToOpen() = getView()?.let { 30 | if (isUserLoggedIn()) 31 | it.openMainActivity() 32 | else 33 | it.openLoginActivity() 34 | } 35 | 36 | private fun isUserLoggedIn(): Boolean { 37 | interactor?.let { return it.isUserLoggedIn() } 38 | return false 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/splash/view/SplashMVPActivity.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.splash.view 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import com.mindorks.framework.mvp.R 6 | import com.mindorks.framework.mvp.ui.base.view.BaseActivity 7 | import com.mindorks.framework.mvp.ui.login.view.LoginActivity 8 | import com.mindorks.framework.mvp.ui.main.view.MainActivity 9 | import com.mindorks.framework.mvp.ui.splash.interactor.SplashMVPInteractor 10 | import com.mindorks.framework.mvp.ui.splash.presenter.SplashMVPPresenter 11 | import javax.inject.Inject 12 | 13 | class SplashMVPActivity : BaseActivity(), SplashMVPView { 14 | 15 | @Inject 16 | lateinit var presenter: SplashMVPPresenter 17 | 18 | 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | setContentView(R.layout.activity_splash) 22 | presenter.onAttach(this) 23 | } 24 | 25 | override fun onDestroy() { 26 | presenter.onDetach() 27 | super.onDestroy() 28 | } 29 | 30 | override fun onFragmentDetached(tag: String) { 31 | } 32 | 33 | override fun onFragmentAttached() { 34 | } 35 | 36 | override fun showSuccessToast() { 37 | } 38 | 39 | override fun showErrorToast() { 40 | } 41 | 42 | override fun openMainActivity() { 43 | val intent = Intent(this, MainActivity::class.java) 44 | startActivity(intent) 45 | finish() 46 | } 47 | 48 | override fun openLoginActivity() { 49 | val intent = Intent(this, LoginActivity::class.java) 50 | startActivity(intent) 51 | finish() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/ui/splash/view/SplashMVPView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.ui.splash.view 2 | 3 | import com.mindorks.framework.mvp.ui.base.view.MVPView 4 | 5 | /** 6 | * Created by jyotidubey on 04/01/18. 7 | */ 8 | interface SplashMVPView : MVPView { 9 | 10 | fun showSuccessToast() 11 | fun showErrorToast() 12 | fun openMainActivity() 13 | fun openLoginActivity() 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/util/AppConstants.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.util 2 | 3 | 4 | /** 5 | * Created by jyotidubey on 05/01/18. 6 | */ 7 | object AppConstants { 8 | 9 | internal val APP_DB_NAME = "mindorks_mvp.db" 10 | internal val PREF_NAME = "mindorks_pref" 11 | internal val SEED_DATABASE_QUESTIONS = "seed/questions.json" 12 | internal val SEED_DATABASE_OPTIONS = "seed/options.json" 13 | internal val EMPTY_EMAIL_ERROR = 1001 14 | internal val INVALID_EMAIL_ERROR = 1002 15 | internal val EMPTY_PASSWORD_ERROR = 1003 16 | internal val LOGIN_FAILURE = 1004 17 | internal val NULL_INDEX = -1L 18 | 19 | enum class LoggedInMode constructor(val type: Int) { 20 | LOGGED_IN_MODE_LOGGED_OUT(0), 21 | LOGGED_IN_MODE_GOOGLE(1), 22 | LOGGED_IN_MODE_FB(2), 23 | LOGGED_IN_MODE_SERVER(3) 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/util/CommonUtil.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.util 2 | 3 | import android.app.ProgressDialog 4 | import android.content.Context 5 | import android.graphics.Color 6 | import android.graphics.drawable.ColorDrawable 7 | import androidx.graphics.drawable.toDrawable 8 | import com.mindorks.framework.mvp.R 9 | 10 | /** 11 | * Created by jyotidubey on 11/01/18. 12 | */ 13 | object CommonUtil { 14 | 15 | fun showLoadingDialog(context: Context?): ProgressDialog { 16 | val progressDialog = ProgressDialog(context) 17 | progressDialog.let { 18 | it.show() 19 | it.window?.setBackgroundDrawable(Color.TRANSPARENT.toDrawable()) 20 | it.setContentView(R.layout.progress_dialog) 21 | it.isIndeterminate = true 22 | it.setCancelable(false) 23 | it.setCanceledOnTouchOutside(false) 24 | return it 25 | } 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/util/FileUtils.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.util 2 | 3 | import android.content.Context 4 | import java.io.IOException 5 | import java.nio.charset.Charset 6 | 7 | /** 8 | * Created by jyotidubey on 07/01/18. 9 | */ 10 | object FileUtils { 11 | 12 | @Throws(IOException::class) 13 | fun loadJSONFromAsset(context: Context, jsonFileName: String): String { 14 | (context.assets).open(jsonFileName).let { 15 | val buffer = ByteArray(it.available()) 16 | it.read(buffer) 17 | it.close() 18 | return String(buffer, Charset.forName("UTF-8")) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/util/SchedulerProvider.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.util 2 | 3 | import io.reactivex.* 4 | import io.reactivex.android.schedulers.AndroidSchedulers 5 | import io.reactivex.schedulers.Schedulers 6 | 7 | /** 8 | * Created by jyotidubey on 16/01/18. 9 | */ 10 | class SchedulerProvider { 11 | 12 | fun ioToMainObservableScheduler(): ObservableTransformer = ObservableTransformer { upstream -> 13 | upstream.subscribeOn(getIOThreadScheduler()) 14 | .observeOn(getMainThreadScheduler()) 15 | } 16 | 17 | fun ioToMainSingleScheduler(): SingleTransformer = SingleTransformer { upstream -> 18 | upstream.subscribeOn(getIOThreadScheduler()) 19 | .observeOn(getMainThreadScheduler()) 20 | } 21 | 22 | 23 | fun ioToMainCompletableScheduler(): CompletableTransformer = CompletableTransformer { upstream -> 24 | upstream.subscribeOn(getIOThreadScheduler()) 25 | .observeOn(getMainThreadScheduler()) 26 | } 27 | 28 | 29 | fun ioToMainFlowableScheduler(): FlowableTransformer = FlowableTransformer { upstream -> 30 | upstream.subscribeOn(getIOThreadScheduler()) 31 | .observeOn(getMainThreadScheduler()) 32 | } 33 | 34 | 35 | fun ioToMainMaybeScheduler(): MaybeTransformer = MaybeTransformer { upstream -> 36 | upstream.subscribeOn(getIOThreadScheduler()) 37 | .observeOn(getMainThreadScheduler()) 38 | } 39 | 40 | private fun getIOThreadScheduler() = Schedulers.io() 41 | 42 | private fun getMainThreadScheduler() = AndroidSchedulers.mainThread() 43 | 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/util/ScreenUtils.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.util 2 | 3 | import android.content.Context 4 | import android.util.DisplayMetrics 5 | import android.view.WindowManager 6 | 7 | /** 8 | * Created by jyotidubey on 09/01/18. 9 | */ 10 | object ScreenUtils { 11 | 12 | fun getScreenWidth(context: Context): Int { 13 | val windowManager = context 14 | .getSystemService(Context.WINDOW_SERVICE) as WindowManager 15 | windowManager.let { 16 | val dm = DisplayMetrics() 17 | it.defaultDisplay.getMetrics(dm) 18 | return dm.widthPixels 19 | } 20 | } 21 | 22 | fun getScreenHeight(context: Context): Int { 23 | val windowManager = context 24 | .getSystemService(Context.WINDOW_SERVICE) as WindowManager 25 | windowManager.let { 26 | val dm = DisplayMetrics() 27 | it.defaultDisplay.getMetrics(dm) 28 | return dm.heightPixels 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/util/extension/FragmentManager.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.util.extension 2 | 3 | import android.support.v4.app.Fragment 4 | import android.support.v4.app.FragmentManager 5 | import android.widget.ImageView 6 | import com.bumptech.glide.Glide 7 | import com.mindorks.framework.mvp.R 8 | 9 | /** 10 | * Created by jyotidubey on 18/01/18. 11 | */ 12 | internal fun FragmentManager.removeFragment(tag: String, 13 | slideIn: Int = R.anim.slide_left, 14 | slideOut: Int = R.anim.slide_right) { 15 | this.beginTransaction() 16 | .disallowAddToBackStack() 17 | .setCustomAnimations(slideIn, slideOut) 18 | .remove(this.findFragmentByTag(tag)) 19 | .commitNow() 20 | } 21 | 22 | internal fun FragmentManager.addFragment(containerViewId: Int, 23 | fragment: Fragment, 24 | tag: String, 25 | slideIn: Int = R.anim.slide_left, 26 | slideOut: Int = R.anim.slide_right) { 27 | this.beginTransaction().disallowAddToBackStack() 28 | .setCustomAnimations(slideIn, slideOut) 29 | .add(containerViewId, fragment, tag) 30 | .commit() 31 | } 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/mindorks/framework/mvp/util/extension/ImageView.kt: -------------------------------------------------------------------------------- 1 | package com.mindorks.framework.mvp.util.extension 2 | 3 | import android.widget.ImageView 4 | import com.bumptech.glide.Glide 5 | 6 | /** 7 | * Created by jyotidubey on 24/01/18. 8 | */ 9 | internal fun ImageView.loadImage(url: String) { 10 | Glide.with(this.context) 11 | .load(url) 12 | .asBitmap() 13 | .centerCrop() 14 | .into(this) 15 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/button_primary_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/button_secondary_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_camera.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_gallery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_manage.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_slideshow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /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/bg_design.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/border_dark_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bottom_border_shadow.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_negative_text_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_positive_text_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_secondary_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/corner_border_rect_gray.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back_white_24px.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_facebook.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_google_plus.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_backspace_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_power_settings_new_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_rabbit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 13 | 16 | 19 | 22 | 25 | 28 | 31 | 34 | 37 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_rss_symbol.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_star.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/input_border_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 21 | 22 | 30 | 31 | 32 | 33 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 28 | 29 | 35 | 36 | 41 | 42 | 58 | 59 | 60 | 61 | 68 | 69 | 85 | 86 | 87 | 88 | 98 | 99 | 100 | 106 | 107 | 113 | 114 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 15 | 16 | 20 | 21 | 25 | 26 | 27 | 28 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_bar_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/card_layout.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 28 | 29 | 38 | 39 | 45 | 46 | 51 | 52 | 58 | 59 | 64 | 65 | 72 | 73 | 84 | 85 | 92 | 93 | 94 | 95 | 96 | 97 |