├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── githubrepo │ │ └── ExampleInstrumentedTest.kt │ ├── debug │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── githubrepo │ │ └── BaseUrlModule.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── iamkamrul │ │ │ └── githubrepo │ │ │ ├── MainActivity.kt │ │ │ ├── application │ │ │ └── GithubRepoApplication.kt │ │ │ └── di │ │ │ ├── ApplicationModule.kt │ │ │ └── RepositoryModule.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── content_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ ├── release │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── githubrepo │ │ └── BaseUrlModule.kt │ └── test │ └── java │ └── com │ └── iamkamrul │ └── githubrepo │ └── ExampleUnitTest.kt ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts └── src │ └── main │ └── kotlin │ ├── ProjectConfigs.kt │ ├── core │ ├── Dependencies.kt │ ├── ModulesDep.kt │ └── Versions.kt │ ├── dependencies │ ├── GroupedDepHandlerExtension.kt │ ├── GroupedDependencies.kt │ ├── ModuleGroupedDepHandlerExtension.kt │ └── ModuleGroupedDependencies.kt │ └── plugins │ ├── android-base-library-core.gradle.kts │ ├── android-base-library-feature.gradle.kts │ └── android-base-library.gradle.kts ├── common ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── common │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── iamkamrul │ │ │ └── common │ │ │ ├── adapter │ │ │ ├── DataBoundListAdapter.kt │ │ │ └── DataBoundViewHolder.kt │ │ │ ├── base │ │ │ ├── BaseFragment.kt │ │ │ └── BaseViewModel.kt │ │ │ └── extension │ │ │ └── RecyclerviewExtension.kt │ └── res │ │ ├── drawable │ │ ├── ic_baseline_circle_24.xml │ │ ├── ic_baseline_fork_24.xml │ │ └── ic_baseline_star_24.xml │ │ ├── values-land │ │ └── dimens.xml │ │ ├── values-night │ │ ├── colors.xml │ │ └── themes.xml │ │ ├── values-v29 │ │ └── themes.xml │ │ ├── values-w1240dp │ │ └── dimens.xml │ │ ├── values-w600dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── iamkamrul │ └── common │ └── ExampleUnitTest.kt ├── data ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── data │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── data │ │ ├── apiservice │ │ ├── ApiService.kt │ │ ├── ApiServiceModule.kt │ │ └── NetworkBoundResources.kt │ │ ├── mapper │ │ ├── BaseMapper.kt │ │ ├── RepositoryListItemMapper.kt │ │ └── UserProfileMapper.kt │ │ └── repoimpl │ │ └── GithubRepoImpl.kt │ └── test │ └── java │ └── com │ └── iamkamrul │ └── data │ └── ExampleUnitTest.kt ├── di ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── di │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── di │ │ ├── module │ │ ├── OkHttpModule.kt │ │ └── RetrofitModule.kt │ │ └── qualifier │ │ └── BaseUrl.kt │ └── test │ └── java │ └── com │ └── iamkamrul │ └── di │ └── ExampleUnitTest.kt ├── domain ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── domain │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── domain │ │ ├── base │ │ ├── BaseUsecase.kt │ │ └── Result.kt │ │ ├── repository │ │ └── GithubRepository.kt │ │ └── usecase │ │ ├── RepositoryListUsecase.kt │ │ └── UserProfileUsecase.kt │ └── test │ └── java │ └── com │ └── iamkamrul │ └── domain │ └── ExampleUnitTest.kt ├── features ├── profile │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── iamkamrul │ │ │ └── profile │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── iamkamrul │ │ │ │ └── profile │ │ │ │ ├── ProfileFragment.kt │ │ │ │ └── ProfileViewModel.kt │ │ └── res │ │ │ └── layout │ │ │ └── fragment_profile.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── profile │ │ └── ExampleUnitTest.kt └── repolist │ ├── .gitignore │ ├── build.gradle.kts │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── repolist │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── iamkamrul │ │ │ └── repolist │ │ │ ├── RepoListAdapter.kt │ │ │ ├── RepoListFragment.kt │ │ │ └── RepoListViewModel.kt │ └── res │ │ └── layout │ │ ├── fragment_repo_list.xml │ │ └── item_repo_list.xml │ └── test │ └── java │ └── com │ └── iamkamrul │ └── repolist │ └── ExampleUnitTest.kt ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── model ├── apiresponse │ ├── .gitignore │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── apiresponse │ │ ├── RepositoryListItemApiResponse.kt │ │ └── UserProfileApiResponse.kt └── entity │ ├── .gitignore │ ├── build.gradle.kts │ └── src │ └── main │ └── java │ └── com │ └── iamkamrul │ └── entity │ ├── RepositoryListItemEntity.kt │ └── UserProfileEntity.kt ├── navigation ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iamkamrul │ │ └── navigation │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── res │ │ └── navigation │ │ └── nav_graph.xml │ └── test │ └── java │ └── com │ └── iamkamrul │ └── navigation │ └── ExampleUnitTest.kt └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/java,linux,macos,windows,android,intellij,androidstudio 2 | # Edit at https://www.gitignore.io/?templates=java,linux,macos,windows,android,intellij,androidstudio 3 | 4 | ### Android ### 5 | # Built application files 6 | *.apk 7 | *.ap_ 8 | *.aab 9 | 10 | # Files for the ART/Dalvik VM 11 | *.dex 12 | 13 | # Java class files 14 | *.class 15 | 16 | # Generated files 17 | bin/ 18 | gen/ 19 | out/ 20 | 21 | # Gradle files 22 | .gradle/ 23 | build/ 24 | 25 | # Local configuration file (sdk path, etc) 26 | local.properties 27 | 28 | # Proguard folder generated by Eclipse 29 | proguard/ 30 | 31 | # Log Files 32 | *.log 33 | 34 | # Android Studio Navigation editor temp files 35 | .navigation/ 36 | 37 | # Android Studio captures folder 38 | captures/ 39 | 40 | # IntelliJ 41 | *.iml 42 | .idea/workspace.xml 43 | .idea/tasks.xml 44 | .idea/gradle.xml 45 | .idea/assetWizardSettings.xml 46 | .idea/dictionaries 47 | .idea/libraries 48 | .idea/caches 49 | 50 | # Keystore files 51 | # Uncomment the following lines if you do not want to check your keystore files in. 52 | #*.jks 53 | #*.keystore 54 | 55 | # External native build folder generated in Android Studio 2.2 and later 56 | .externalNativeBuild 57 | 58 | # Google Services (e.g. APIs or Firebase) 59 | google-services.json 60 | 61 | # Freeline 62 | freeline.py 63 | freeline/ 64 | freeline_project_description.json 65 | 66 | # fastlane 67 | fastlane/report.xml 68 | fastlane/Preview.html 69 | fastlane/screenshots 70 | fastlane/test_output 71 | fastlane/readme.md 72 | 73 | ### Android Patch ### 74 | gen-external-apklibs 75 | 76 | ### AndroidStudio ### 77 | # Covers files to be ignored for android development using Android Studio. 78 | 79 | # Built application files 80 | 81 | # Files for the ART/Dalvik VM 82 | 83 | # Java class files 84 | 85 | # Generated files 86 | 87 | # Gradle files 88 | .gradle 89 | 90 | # Signing files 91 | .signing/ 92 | 93 | # Local configuration file (sdk path, etc) 94 | 95 | # Proguard folder generated by Eclipse 96 | 97 | # Log Files 98 | 99 | # Android Studio 100 | /*/build/ 101 | /*/local.properties 102 | /*/out 103 | /*/*/build 104 | /*/*/production 105 | *.ipr 106 | *~ 107 | *.swp 108 | 109 | # Android Patch 110 | 111 | # External native build folder generated in Android Studio 2.2 and later 112 | 113 | # NDK 114 | obj/ 115 | 116 | # IntelliJ IDEA 117 | *.iws 118 | /out/ 119 | 120 | # User-specific configurations 121 | .idea/caches/ 122 | .idea/libraries/ 123 | .idea/shelf/ 124 | .idea/.name 125 | .idea/compiler.xml 126 | .idea/copyright/profiles_settings.xml 127 | .idea/encodings.xml 128 | .idea/misc.xml 129 | .idea/modules.xml 130 | .idea/scopes/scope_settings.xml 131 | .idea/vcs.xml 132 | .idea/jsLibraryMappings.xml 133 | .idea/datasources.xml 134 | .idea/dataSources.ids 135 | .idea/sqlDataSources.xml 136 | .idea/dynamic.xml 137 | .idea/uiDesigner.xml 138 | 139 | # OS-specific files 140 | .DS_Store 141 | .DS_Store? 142 | ._* 143 | .Spotlight-V100 144 | .Trashes 145 | ehthumbs.db 146 | Thumbs.db 147 | 148 | # Legacy Eclipse project files 149 | .classpath 150 | .project 151 | .cproject 152 | .settings/ 153 | 154 | # Mobile Tools for Java (J2ME) 155 | .mtj.tmp/ 156 | 157 | # Package Files # 158 | *.war 159 | *.ear 160 | 161 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 162 | hs_err_pid* 163 | 164 | ## Plugin-specific files: 165 | 166 | # mpeltonen/sbt-idea plugin 167 | .idea_modules/ 168 | 169 | # JIRA plugin 170 | atlassian-ide-plugin.xml 171 | 172 | # Mongo Explorer plugin 173 | .idea/mongoSettings.xml 174 | 175 | # Crashlytics plugin (for Android Studio and IntelliJ) 176 | com_crashlytics_export_strings.xml 177 | crashlytics.properties 178 | crashlytics-build.properties 179 | fabric.properties 180 | 181 | ### AndroidStudio Patch ### 182 | 183 | !/gradle/wrapper/gradle-wrapper.jar 184 | 185 | ### Intellij ### 186 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 187 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 188 | 189 | # User-specific stuff 190 | .idea/**/workspace.xml 191 | .idea/**/tasks.xml 192 | .idea/**/usage.statistics.xml 193 | .idea/**/dictionaries 194 | .idea/**/shelf 195 | 196 | # Generated files 197 | .idea/**/contentModel.xml 198 | 199 | # Sensitive or high-churn files 200 | .idea/**/dataSources/ 201 | .idea/**/dataSources.ids 202 | .idea/**/dataSources.local.xml 203 | .idea/**/sqlDataSources.xml 204 | .idea/**/dynamic.xml 205 | .idea/**/uiDesigner.xml 206 | .idea/**/dbnavigator.xml 207 | 208 | # Gradle 209 | .idea/**/gradle.xml 210 | .idea/**/libraries 211 | 212 | # Gradle and Maven with auto-import 213 | # When using Gradle or Maven with auto-import, you should exclude module files, 214 | # since they will be recreated, and may cause churn. Uncomment if using 215 | # auto-import. 216 | # .idea/modules.xml 217 | # .idea/*.iml 218 | # .idea/modules 219 | 220 | # CMake 221 | cmake-build-*/ 222 | 223 | # Mongo Explorer plugin 224 | .idea/**/mongoSettings.xml 225 | 226 | # File-based project format 227 | 228 | # IntelliJ 229 | 230 | # mpeltonen/sbt-idea plugin 231 | 232 | # JIRA plugin 233 | 234 | # Cursive Clojure plugin 235 | .idea/replstate.xml 236 | 237 | # Crashlytics plugin (for Android Studio and IntelliJ) 238 | 239 | # Editor-based Rest Client 240 | .idea/httpRequests 241 | 242 | # Android studio 3.1+ serialized cache file 243 | .idea/caches/build_file_checksums.ser 244 | 245 | ### Intellij Patch ### 246 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 247 | 248 | # *.iml 249 | # modules.xml 250 | # .idea/misc.xml 251 | # *.ipr 252 | 253 | # Sonarlint plugin 254 | .idea/sonarlint 255 | 256 | ### Java ### 257 | # Compiled class file 258 | 259 | # Log file 260 | 261 | # BlueJ files 262 | *.ctxt 263 | 264 | # Mobile Tools for Java (J2ME) 265 | 266 | # Package Files # 267 | *.jar 268 | *.nar 269 | *.zip 270 | *.tar.gz 271 | *.rar 272 | 273 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 274 | 275 | ### Linux ### 276 | 277 | # temporary files which can be created if a process still has a handle open of a deleted file 278 | .fuse_hidden* 279 | 280 | # KDE directory preferences 281 | .directory 282 | 283 | # Linux trash folder which might appear on any partition or disk 284 | .Trash-* 285 | 286 | # .nfs files are created when an open file is removed but is still being accessed 287 | .nfs* 288 | 289 | ### macOS ### 290 | # General 291 | .AppleDouble 292 | .LSOverride 293 | 294 | # Icon must end with two \r 295 | Icon 296 | 297 | # Thumbnails 298 | 299 | # Files that might appear in the root of a volume 300 | .DocumentRevisions-V100 301 | .fseventsd 302 | .TemporaryItems 303 | .VolumeIcon.icns 304 | .com.apple.timemachine.donotpresent 305 | 306 | # Directories potentially created on remote AFP share 307 | .AppleDB 308 | .AppleDesktop 309 | Network Trash Folder 310 | Temporary Items 311 | .apdisk 312 | 313 | ### Windows ### 314 | # Windows thumbnail cache files 315 | ehthumbs_vista.db 316 | 317 | # Dump file 318 | *.stackdump 319 | 320 | # Folder config file 321 | [Dd]esktop.ini 322 | 323 | # Recycle Bin used on file shares 324 | $RECYCLE.BIN/ 325 | 326 | # Windows Installer files 327 | *.cab 328 | *.msi 329 | *.msix 330 | *.msm 331 | *.msp 332 | 333 | # Windows shortcuts 334 | *.lnk 335 | 336 | # End of https://www.gitignore.io/api/java,linux,macos,windows,android,intellij,androidstudio 337 | /.idea/jarRepositories.xml 338 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MVVM-Clean-Architecture-Modularization 2 | A clean architecture approach (multi-module) using Kotlin, Navigation Component, MVVM, Hilt, Kotlin Coroutines,Flow and Retrofit. 3 |
4 |
5 |
6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dependencies.* 2 | 3 | plugins { 4 | id("com.android.application") 5 | id("kotlin-android") 6 | id("kotlin-kapt") 7 | id("dagger.hilt.android.plugin") 8 | id("androidx.navigation.safeargs") 9 | } 10 | 11 | android { 12 | compileSdk = ProjectConfigs.compileSdkVersion 13 | defaultConfig { 14 | applicationId = ProjectConfigs.applicationId 15 | minSdk = ProjectConfigs.minSdkVersion 16 | targetSdk = ProjectConfigs.targetSdkVersion 17 | versionCode = 1 18 | versionName = "1.0.0" 19 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 20 | } 21 | 22 | buildTypes { 23 | release { 24 | isMinifyEnabled = false 25 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility = JavaVersion.VERSION_11 30 | targetCompatibility = JavaVersion.VERSION_11 31 | } 32 | kotlinOptions { 33 | jvmTarget = "11" 34 | } 35 | 36 | buildFeatures { 37 | viewBinding = true 38 | } 39 | } 40 | 41 | dependencies { 42 | addFeatureModules() 43 | addDataModule() 44 | addDomainModule() 45 | addCommonModule() 46 | 47 | addAndroidxCoreDependencies() 48 | addAndroidxNavigationDependencies() 49 | addAndroidxLifeCycleDependencies() 50 | addViewStateDependencies() 51 | addHiltDependencies() 52 | addAndroidTestsDependencies() 53 | } 54 | kapt { 55 | correctErrorTypes = true 56 | } -------------------------------------------------------------------------------- /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.kts. 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 -------------------------------------------------------------------------------- /app/src/androidTest/java/com/iamkamrul/githubrepo/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.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.getInstrumentation().targetContext 22 | assertEquals("com.iamkamrul.githubrepo", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/debug/java/com/iamkamrul/githubrepo/BaseUrlModule.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo 2 | 3 | import com.iamkamrul.di.qualifier.BaseUrl 4 | import dagger.Module 5 | import dagger.Provides 6 | import dagger.hilt.InstallIn 7 | import dagger.hilt.components.SingletonComponent 8 | 9 | @Module 10 | @InstallIn(SingletonComponent::class) 11 | class BaseUrlModule { 12 | @Provides 13 | @BaseUrl 14 | fun provideBaseUrl():String = "https://api.github.com/" 15 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/iamkamrul/githubrepo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo 2 | 3 | import android.os.Bundle 4 | import com.google.android.material.snackbar.Snackbar 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.core.view.WindowCompat 7 | import androidx.navigation.findNavController 8 | import androidx.navigation.ui.AppBarConfiguration 9 | import androidx.navigation.ui.navigateUp 10 | import androidx.navigation.ui.setupActionBarWithNavController 11 | import android.view.Menu 12 | import android.view.MenuItem 13 | import com.iamkamrul.githubrepo.databinding.ActivityMainBinding 14 | import dagger.hilt.android.AndroidEntryPoint 15 | 16 | @AndroidEntryPoint 17 | class MainActivity : AppCompatActivity() { 18 | 19 | private lateinit var appBarConfiguration: AppBarConfiguration 20 | private lateinit var binding: ActivityMainBinding 21 | 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | WindowCompat.setDecorFitsSystemWindows(window, false) 24 | super.onCreate(savedInstanceState) 25 | 26 | binding = ActivityMainBinding.inflate(layoutInflater) 27 | setContentView(binding.root) 28 | 29 | setSupportActionBar(binding.toolbar) 30 | 31 | val navController = findNavController(R.id.nav_host_fragment_content_main) 32 | appBarConfiguration = AppBarConfiguration(navController.graph) 33 | setupActionBarWithNavController(navController, appBarConfiguration) 34 | 35 | } 36 | 37 | override fun onSupportNavigateUp(): Boolean { 38 | val navController = findNavController(R.id.nav_host_fragment_content_main) 39 | return navController.navigateUp(appBarConfiguration) 40 | || super.onSupportNavigateUp() 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/iamkamrul/githubrepo/application/GithubRepoApplication.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo.application 2 | 3 | import android.app.Application 4 | import com.iamkamrul.githubrepo.BuildConfig 5 | import dagger.hilt.android.HiltAndroidApp 6 | import timber.log.Timber 7 | 8 | @HiltAndroidApp 9 | class GithubRepoApplication : Application(){ 10 | override fun onCreate() { 11 | super.onCreate() 12 | if (BuildConfig.DEBUG){ 13 | Timber.plant(Timber.DebugTree()) 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/iamkamrul/githubrepo/di/ApplicationModule.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo.di 2 | 3 | import dagger.Module 4 | import dagger.hilt.InstallIn 5 | import dagger.hilt.components.SingletonComponent 6 | 7 | @Module 8 | @InstallIn(SingletonComponent::class) 9 | class ApplicationModule { 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/iamkamrul/githubrepo/di/RepositoryModule.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo.di 2 | 3 | import com.iamkamrul.data.repoimpl.GithubRepoImpl 4 | import com.iamkamrul.domain.repository.GithubRepository 5 | import dagger.Binds 6 | import dagger.Module 7 | import dagger.hilt.InstallIn 8 | import dagger.hilt.components.SingletonComponent 9 | 10 | @Module 11 | @InstallIn(SingletonComponent::class) 12 | interface RepositoryModule { 13 | 14 | @Binds 15 | fun bindGithubRepository(githubRepoImpl: GithubRepoImpl):GithubRepository 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/release/java/com/iamkamrul/githubrepo/BaseUrlModule.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo 2 | 3 | import com.iamkamrul.di.qualifier.BaseUrl 4 | import dagger.Module 5 | import dagger.Provides 6 | import dagger.hilt.InstallIn 7 | import dagger.hilt.components.SingletonComponent 8 | 9 | @Module 10 | @InstallIn(SingletonComponent::class) 11 | class BaseUrlModule { 12 | @Provides 13 | @BaseUrl 14 | fun provideBaseUrl():String = "https://api.github.com/" 15 | } -------------------------------------------------------------------------------- /app/src/test/java/com/iamkamrul/githubrepo/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.githubrepo 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenLocal() 4 | mavenCentral() 5 | google() 6 | maven ("https://jitpack.io") 7 | maven ("https://oss.jfrog.org/libs-snapshot") 8 | } 9 | dependencies { 10 | classpath(ProjectConfigs.buildGradle) 11 | classpath(ProjectConfigs.kotlinGradlePlugin) 12 | classpath(ProjectConfigs.hiltAndroidGradlePlugin) 13 | classpath(ProjectConfigs.navSafeArgs) 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | mavenLocal() 20 | mavenCentral() 21 | google() 22 | maven ("https://jitpack.io") 23 | maven ("https://oss.jfrog.org/libs-snapshot") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradle.kotlin.dsl.`kotlin-dsl` 2 | plugins { 3 | `kotlin-dsl` 4 | } 5 | 6 | buildscript { 7 | repositories { 8 | mavenLocal() 9 | mavenCentral() 10 | google() 11 | maven ("https://jitpack.io") 12 | maven ("https://oss.jfrog.org/libs-snapshot") 13 | } 14 | } 15 | repositories { 16 | mavenLocal() 17 | mavenCentral() 18 | google() 19 | maven ("https://jitpack.io") 20 | maven ("https://oss.jfrog.org/libs-snapshot") 21 | } 22 | dependencies { 23 | compileOnly(gradleKotlinDsl()) 24 | implementation("com.android.tools.build:gradle:7.2.1") 25 | implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21") 26 | implementation("com.google.dagger:hilt-android-gradle-plugin:2.39.1") 27 | implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.4.2") 28 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ProjectConfigs.kt: -------------------------------------------------------------------------------- 1 | import core.Versions 2 | 3 | object ProjectConfigs { 4 | const val compileSdkVersion = 32 5 | const val minSdkVersion = 21 6 | const val targetSdkVersion = 32 7 | const val applicationId = "com.iamkamrul.githubrepo" 8 | const val buildGradle = "com.android.tools.build:gradle:${Versions.buildGradle_version}" 9 | const val kotlinGradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin_version}" 10 | const val hiltAndroidGradlePlugin = "com.google.dagger:hilt-android-gradle-plugin:${Versions.hilt_android_version}" 11 | const val navSafeArgs = "androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.nav_version}" 12 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/core/Dependencies.kt: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | internal object Dependencies { 4 | const val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat_version}" 5 | const val coreKtx = "androidx.core:core-ktx:${Versions.coreKtx_version}" 6 | const val material = "com.google.android.material:material:${Versions.material_version}" 7 | const val constraintLayout = "androidx.constraintlayout:constraintlayout:${Versions.constraintLayout_version}" 8 | const val activityKtx = "androidx.activity:activity-ktx:${Versions.activity_version}" 9 | const val fragmentKtx = "androidx.fragment:fragment-ktx:${Versions.fragment_version}" 10 | const val recyclerview = "androidx.recyclerview:recyclerview:${Versions.recyclerview_version}" 11 | const val cardview = "androidx.cardview:cardview:${Versions.card_view_version}" 12 | const val preference = "androidx.preference:preference:${Versions.preference_version}" 13 | const val swipeToRefreshLayout = "androidx.swiperefreshlayout:swiperefreshlayout:${Versions.swipeLayout_version}" 14 | 15 | const val viewModel = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifecycle_version}" 16 | const val livedata = "androidx.lifecycle:lifecycle-livedata-ktx:${Versions.lifecycle_version}" 17 | const val lifecycleRuntime = "androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle_version}" 18 | const val viewModelSaveState = "androidx.lifecycle:lifecycle-viewmodel-savedstate:${Versions.lifecycle_version}" 19 | const val lifecycleService = "androidx.lifecycle:lifecycle-service:${Versions.lifecycle_version}" 20 | 21 | const val hiltAndroid = "com.google.dagger:hilt-android:${Versions.hilt_android_version}" 22 | const val hiltCompiler = "com.google.dagger:hilt-android-compiler:${Versions.hilt_android_version}" 23 | 24 | const val navigationFragmentKtx = "androidx.navigation:navigation-fragment-ktx:${Versions.nav_version}" 25 | const val navigationUiKtx = "androidx.navigation:navigation-ui-ktx:${Versions.nav_version}" 26 | 27 | const val kotlinxCoroutinesAndroid = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutines_version}" 28 | 29 | const val retrofit = "com.squareup.retrofit2:retrofit:${Versions.retrofit_version}" 30 | const val rxJava3adapter = "com.squareup.retrofit2:adapter-rxjava3:${Versions.retrofit_version}" 31 | const val converterGson = "com.squareup.retrofit2:converter-gson:${Versions.retrofit_version}" 32 | const val gson = "com.google.code.gson:gson:${Versions.retrofit_version}" 33 | 34 | const val okhttp3 = "com.squareup.okhttp3:okhttp:${Versions.okhttp3_version}" 35 | const val okhttp3logging = "com.squareup.okhttp3:logging-interceptor:${Versions.okhttp3_version}" 36 | 37 | const val rxJava3 = "io.reactivex.rxjava3:rxjava:${Versions.rxJava3_version}" 38 | const val rxJava3Android = "io.reactivex.rxjava3:rxandroid:${Versions.rx_android3_version}" 39 | 40 | const val sdp = "com.intuit.sdp:sdp-android:${Versions.sdp_version}" 41 | const val ssp = "com.intuit.ssp:ssp-android:${Versions.sdp_version}" 42 | 43 | const val playStoreCore = "com.google.android.play:core:${Versions.play_core_version}" 44 | const val playStoreKtx = "com.google.android.play:core-ktx:${Versions.play_ktx_version}" 45 | 46 | const val facebookAndroid = "com.facebook.android:facebook-android-sdk:${Versions.facebook_version}" 47 | const val facebookMarketing = "com.facebook.android:facebook-marketing:${Versions.facebook_marketing_version}" 48 | 49 | const val mapCore = "com.google.android.gms:play-services-maps:${Versions.map_version}" 50 | const val mapLocation = "com.google.android.gms:play-services-location:${Versions.map_location_version}" 51 | const val mapPlaces = "com.google.android.libraries.places:places:${Versions.map_place_version}" 52 | 53 | const val firebaseBom = "com.google.firebase:firebase-bom:${Versions.firebase_bom_version}" 54 | const val firebaseCore = "com.google.firebase:firebase-core" 55 | const val firebaseMessaging = "com.google.firebase:firebase-messaging-ktx" 56 | const val firebaseAnalytics = "com.google.firebase:firebase-analytics-ktx" 57 | const val firebaseCrashlytics = "com.google.firebase:firebase-crashlytics-ktx" 58 | 59 | const val roomKtx = "androidx.room:room-ktx:${Versions.room_version}" 60 | const val roomRuntime = "androidx.room:room-runtime:${Versions.room_version}" 61 | const val roomCompiler = "androidx.room:room-compiler:${Versions.room_version}" 62 | const val roomCommon = "androidx.room:room-common:${Versions.room_version}" 63 | 64 | const val leakcanary = "com.squareup.leakcanary:leakcanary-android:${Versions.leakcanary_version}" 65 | const val timber = "com.jakewharton.timber:timber:${Versions.timberVersion}" 66 | const val viewStateLayout = "com.github.kamrul3288:ViewStateLayout:${Versions.viewStateLayoutVersion}" 67 | const val circleImageview = "de.hdodenhof:circleimageview:${Versions.circleImageViewVersion}" 68 | const val picasso = "com.squareup.picasso:picasso:${Versions.picassoVersion}" 69 | const val dotIndicator = "com.tbuonomo:dotsindicator:${Versions.dots_indicator_version}" 70 | const val alerter = "com.github.tapadoo:alerter:${Versions.alerter_version}" 71 | const val imageZoomView = "com.github.chrisbanes:PhotoView:${Versions.image_zoom_version}" 72 | const val epoxyCore = "com.airbnb.android:epoxy:${Versions.epoxy_version}" 73 | 74 | const val junit = "junit:junit:${Versions.junit}" 75 | const val ext_junit = "androidx.test.ext:junit:${Versions.ext_junit}" 76 | const val espresso_core = "androidx.test.espresso:espresso-core:${Versions.espresso}" 77 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/core/ModulesDep.kt: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | object ModulesDep { 4 | const val apiResponse = ":model:apiresponse" 5 | const val entity = ":model:entity" 6 | const val di = ":di" 7 | const val data = ":data" 8 | const val domain = ":domain" 9 | const val common = ":common" 10 | const val navigation = ":navigation" 11 | 12 | const val repoList = ":features:repolist" 13 | const val profile = ":features:profile" 14 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/core/Versions.kt: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | internal object Versions { 4 | const val buildGradle_version = "7.2.1" 5 | const val kotlin_version = "1.6.21" 6 | const val firebaseCrashAnalyticGradleVersion = "2.7.1" 7 | const val googleServicesVersion = "4.3.8" 8 | 9 | const val appcompat_version = "1.4.2" 10 | const val preference_version = "1.2.0" 11 | const val swipeLayout_version = "1.1.0" 12 | const val coreKtx_version = "1.8.0" 13 | const val constraintLayout_version = "2.1.4" 14 | const val material_version = "1.7.0-alpha02" 15 | const val activity_version = "1.4.0" 16 | const val fragment_version = "1.4.1" 17 | const val lifecycle_version = "2.4.0" 18 | const val recyclerview_version = "1.2.1" 19 | const val card_view_version = "1.0.0" 20 | const val hilt_android_version = "2.39.1" 21 | const val nav_version = "2.4.2" 22 | const val coroutines_version = "1.6.2" 23 | const val retrofit_version = "2.9.0" 24 | const val okhttp3_version = "4.9.3" 25 | const val timberVersion = "5.0.1" 26 | const val viewStateLayoutVersion = "1.0.4" 27 | const val circleImageViewVersion = "3.1.0" 28 | const val picassoVersion = "2.8" 29 | const val rxJava3_version = "3.1.5" 30 | const val rx_android3_version = "3.0.0" 31 | const val sdp_version = "1.0.6" 32 | const val leakcanary_version = "2.7" 33 | const val dots_indicator_version = "4.3" 34 | const val play_core_version = "1.10.3" 35 | const val play_ktx_version = "1.8.1" 36 | const val facebook_version = "12.0.1" 37 | const val facebook_marketing_version = "7.0.1" 38 | const val map_version = "18.0.2" 39 | const val map_location_version = "19.0.0" 40 | const val map_place_version = "2.6.0" 41 | const val firebase_bom_version= "30.1.0" 42 | const val room_version = "2.4.2" 43 | const val alerter_version = "7.2.4" 44 | const val epoxy_version = "5.0.0-beta03" 45 | const val image_zoom_version = "2.3.0" 46 | 47 | const val junit = "4.13.2" 48 | const val ext_junit = "1.1.3" 49 | const val espresso = "3.4.0" 50 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/dependencies/GroupedDepHandlerExtension.kt: -------------------------------------------------------------------------------- 1 | package dependencies 2 | import core.Dependencies 3 | import org.gradle.api.artifacts.dsl.DependencyHandler 4 | 5 | fun DependencyHandler.addAndroidxCoreDependencies(){ 6 | androidxCoreDependencies.forEach { 7 | add("implementation",it) 8 | } 9 | } 10 | 11 | fun DependencyHandler.addAndroidxSwipeRefreshLayout(){ 12 | androidxSwipeRefreshLayout.forEach { 13 | add("implementation",it) 14 | } 15 | } 16 | 17 | fun DependencyHandler.addAndroidxLifeCycleDependencies(){ 18 | androidxLifeCycleDependencies.forEach { 19 | add("implementation",it) 20 | } 21 | } 22 | 23 | fun DependencyHandler.addLiveDataDependencies(){ 24 | add("implementation",Dependencies.livedata) 25 | } 26 | 27 | 28 | fun DependencyHandler.addAndroidxNavigationDependencies(){ 29 | androidxNavigationDependencies.forEach { 30 | add("implementation",it) 31 | } 32 | } 33 | 34 | fun DependencyHandler.addCoroutinesAndroidDependencies(){ 35 | coroutinesAndroidDependencies.forEach { 36 | add("implementation",it) 37 | } 38 | } 39 | 40 | fun DependencyHandler.addNetworkDependencies(configurationName:String = "implementation"){ 41 | networkDependencies.forEach { 42 | add(configurationName,it) 43 | } 44 | } 45 | 46 | fun DependencyHandler.addHiltDependencies() { 47 | add("implementation",Dependencies.hiltAndroid) 48 | add("kapt",Dependencies.hiltCompiler) 49 | } 50 | 51 | fun DependencyHandler.addRxjava3Dependencies(){ 52 | rxjava3Dependencies.forEach { 53 | add("implementation",it) 54 | } 55 | } 56 | 57 | fun DependencyHandler.addTimberDependencies(configurationName:String = "implementation"){ 58 | add(configurationName,Dependencies.timber) 59 | } 60 | 61 | fun DependencyHandler.addGsonDependencies(configurationName:String = "implementation"){ 62 | add(configurationName,Dependencies.gson) 63 | } 64 | 65 | fun DependencyHandler.addAndroidResponsiveSizeDependenciesDependencies(){ 66 | androidResponsiveSizeDependencies.forEach { 67 | add("implementation",it) 68 | } 69 | } 70 | 71 | fun DependencyHandler.addAlerterDependencies() { 72 | add("implementation",Dependencies.alerter) 73 | } 74 | 75 | fun DependencyHandler.addEPoxyDependencies(){ 76 | add("implementation",Dependencies.epoxyCore) 77 | } 78 | 79 | fun DependencyHandler.addCircleImageviewDependencies(){ 80 | add("implementation",Dependencies.circleImageview) 81 | } 82 | 83 | fun DependencyHandler.addPicassoDependencies(){ 84 | add("implementation",Dependencies.picasso) 85 | } 86 | 87 | fun DependencyHandler.addViewStateDependencies(){ 88 | add("implementation",Dependencies.viewStateLayout) 89 | } 90 | 91 | fun DependencyHandler.addFirebaseDependencies(){ 92 | firebaseDependencies.forEachIndexed { index, it -> 93 | when (index) { 94 | 0 -> add("implementation", platform(it)) 95 | else -> add("implementation", it) 96 | } 97 | } 98 | } 99 | 100 | fun DependencyHandler.addPlayCoreDependencies(){ 101 | playCoreDependencies.forEach { 102 | add("implementation",it) 103 | } 104 | } 105 | 106 | fun DependencyHandler.addFacebookDependencies(){ 107 | facebookDependencies.forEach { 108 | add("implementation",it) 109 | } 110 | } 111 | 112 | fun DependencyHandler.addGoogleMapDependencies(){ 113 | googleMapDependencies.forEach { 114 | add("implementation",it) 115 | } 116 | } 117 | 118 | 119 | fun DependencyHandler.addRoomDependencies(){ 120 | add("implementation",Dependencies.roomKtx) 121 | add("implementation",Dependencies.roomRuntime) 122 | add("kapt",Dependencies.roomCompiler) 123 | 124 | } 125 | 126 | fun DependencyHandler.addRoomCommonDependencies(){ 127 | add("implementation",Dependencies.roomCommon) 128 | } 129 | 130 | fun DependencyHandler.addImageZoomViewDependencies(){ 131 | imageZoomViewDependencies.forEach { 132 | add("implementation",it) 133 | } 134 | } 135 | 136 | fun DependencyHandler.addLeakcanaryDependencies(){ 137 | add("debugImplementation",Dependencies.leakcanary) 138 | } 139 | 140 | fun DependencyHandler.addAndroidTestsDependencies() { 141 | add("testImplementation",Dependencies.junit) 142 | add("androidTestImplementation",Dependencies.ext_junit) 143 | add("androidTestImplementation",Dependencies.espresso_core) 144 | } 145 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/dependencies/GroupedDependencies.kt: -------------------------------------------------------------------------------- 1 | package dependencies 2 | import core.Dependencies 3 | 4 | internal val androidxCoreDependencies = listOf( 5 | Dependencies.appcompat, 6 | Dependencies.coreKtx, 7 | Dependencies.material, 8 | Dependencies.constraintLayout, 9 | Dependencies.activityKtx, 10 | Dependencies.fragmentKtx, 11 | Dependencies.recyclerview, 12 | Dependencies.cardview, 13 | Dependencies.preference, 14 | ) 15 | 16 | internal val androidxSwipeRefreshLayout = listOf( 17 | Dependencies.swipeToRefreshLayout 18 | ) 19 | 20 | internal val androidxLifeCycleDependencies = listOf( 21 | Dependencies.viewModel, 22 | Dependencies.livedata, 23 | Dependencies.lifecycleRuntime, 24 | Dependencies.viewModelSaveState, 25 | Dependencies.lifecycleService, 26 | ) 27 | 28 | internal val androidxNavigationDependencies = listOf( 29 | Dependencies.navigationFragmentKtx, 30 | Dependencies.navigationUiKtx, 31 | ) 32 | 33 | internal val coroutinesAndroidDependencies = listOf( 34 | Dependencies.kotlinxCoroutinesAndroid, 35 | ) 36 | 37 | internal val rxjava3Dependencies = listOf( 38 | Dependencies.rxJava3, 39 | Dependencies.rxJava3Android 40 | ) 41 | 42 | 43 | 44 | internal val firebaseDependencies = listOf( 45 | Dependencies.firebaseBom, 46 | Dependencies.firebaseCore, 47 | Dependencies.firebaseMessaging, 48 | Dependencies.firebaseAnalytics, 49 | Dependencies.firebaseCrashlytics, 50 | ) 51 | 52 | internal val playCoreDependencies = listOf( 53 | Dependencies.playStoreCore, 54 | Dependencies.playStoreKtx 55 | ) 56 | 57 | internal val facebookDependencies = listOf( 58 | Dependencies.facebookAndroid, 59 | Dependencies.facebookMarketing 60 | ) 61 | 62 | internal val googleMapDependencies = listOf( 63 | Dependencies.mapCore, 64 | Dependencies.mapLocation, 65 | Dependencies.mapPlaces, 66 | ) 67 | 68 | 69 | 70 | internal val imageZoomViewDependencies = listOf( 71 | Dependencies.imageZoomView 72 | ) 73 | 74 | 75 | internal val networkDependencies = listOf( 76 | Dependencies.retrofit, 77 | Dependencies.converterGson, 78 | Dependencies.gson, 79 | Dependencies.okhttp3, 80 | Dependencies.okhttp3logging, 81 | Dependencies.rxJava3adapter, 82 | ) 83 | 84 | 85 | internal val androidResponsiveSizeDependencies = listOf( 86 | Dependencies.sdp, 87 | Dependencies.ssp, 88 | ) 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/dependencies/ModuleGroupedDepHandlerExtension.kt: -------------------------------------------------------------------------------- 1 | package dependencies 2 | import core.ModulesDep 3 | import org.gradle.api.artifacts.dsl.DependencyHandler 4 | import org.gradle.kotlin.dsl.project 5 | 6 | fun DependencyHandler.addDiModule(configurationName:String = "implementation"){ 7 | add(configurationName, project(ModulesDep.di)) 8 | } 9 | 10 | fun DependencyHandler.addDomainModule(){ 11 | add("implementation", project(ModulesDep.domain)) 12 | } 13 | 14 | fun DependencyHandler.addDataModule(){ 15 | add("implementation", project(ModulesDep.data)) 16 | } 17 | 18 | fun DependencyHandler.addApiResponseModule(configurationName:String = "implementation"){ 19 | add(configurationName, project(ModulesDep.apiResponse)) 20 | } 21 | 22 | fun DependencyHandler.addEntityModule(configurationName:String = "implementation"){ 23 | add(configurationName, project(ModulesDep.entity)) 24 | } 25 | 26 | fun DependencyHandler.addCommonModule(){ 27 | add("implementation", project(ModulesDep.common)) 28 | } 29 | 30 | fun DependencyHandler.addFeatureModules(){ 31 | featureModuleDependencies.forEach{ 32 | add("implementation", project(it)) 33 | } 34 | } 35 | 36 | 37 | fun DependencyHandler.addFeatureModuleDependantDependencies(){ 38 | featureModuleDependantDependencies.forEach{ 39 | add("implementation", project(it)) 40 | } 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/dependencies/ModuleGroupedDependencies.kt: -------------------------------------------------------------------------------- 1 | package dependencies 2 | import core.ModulesDep 3 | 4 | internal val featureModuleDependencies = listOf( 5 | ModulesDep.repoList, 6 | ModulesDep.profile 7 | ) 8 | 9 | internal val featureModuleDependantDependencies = listOf( 10 | ModulesDep.di, 11 | ModulesDep.domain, 12 | ModulesDep.common, 13 | ModulesDep.navigation 14 | ) -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/plugins/android-base-library-core.gradle.kts: -------------------------------------------------------------------------------- 1 | package plugins 2 | import dependencies.addAndroidTestsDependencies 3 | import dependencies.addHiltDependencies 4 | import dependencies.addLiveDataDependencies 5 | 6 | plugins { 7 | id("com.android.library") 8 | kotlin("android") 9 | kotlin("kapt") 10 | id("dagger.hilt.android.plugin") 11 | } 12 | 13 | android{ 14 | compileSdk = ProjectConfigs.compileSdkVersion 15 | 16 | defaultConfig { 17 | minSdk = ProjectConfigs.minSdkVersion 18 | targetSdk = ProjectConfigs.targetSdkVersion 19 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 20 | consumerProguardFiles("consumer-rules.pro") 21 | } 22 | compileOptions { 23 | sourceCompatibility = JavaVersion.VERSION_11 24 | targetCompatibility = JavaVersion.VERSION_11 25 | } 26 | kotlinOptions { 27 | jvmTarget = "11" 28 | } 29 | } 30 | 31 | 32 | dependencies { 33 | addHiltDependencies() 34 | addLiveDataDependencies() 35 | addAndroidTestsDependencies() 36 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/plugins/android-base-library-feature.gradle.kts: -------------------------------------------------------------------------------- 1 | package plugins 2 | import dependencies.addAndroidTestsDependencies 3 | import dependencies.addHiltDependencies 4 | import dependencies.addAndroidxCoreDependencies 5 | import dependencies.addFeatureModuleDependantDependencies 6 | import dependencies.addAndroidxNavigationDependencies 7 | import dependencies.addCoroutinesAndroidDependencies 8 | import dependencies.addViewStateDependencies 9 | import dependencies.addAndroidResponsiveSizeDependenciesDependencies 10 | import gradle.kotlin.dsl.accessors._f28201936ac5dc93fbe24b62cb4541cf.android 11 | import gradle.kotlin.dsl.accessors._f28201936ac5dc93fbe24b62cb4541cf.kotlinOptions 12 | 13 | plugins { 14 | id("com.android.library") 15 | kotlin("android") 16 | kotlin("kapt") 17 | id("dagger.hilt.android.plugin") 18 | } 19 | 20 | android{ 21 | compileSdk = ProjectConfigs.compileSdkVersion 22 | 23 | defaultConfig { 24 | minSdk = ProjectConfigs.minSdkVersion 25 | targetSdk = ProjectConfigs.targetSdkVersion 26 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 27 | consumerProguardFiles("consumer-rules.pro") 28 | } 29 | compileOptions { 30 | sourceCompatibility = JavaVersion.VERSION_11 31 | targetCompatibility = JavaVersion.VERSION_11 32 | } 33 | kotlinOptions { 34 | jvmTarget = "11" 35 | } 36 | 37 | buildFeatures{ 38 | viewBinding = true 39 | } 40 | } 41 | 42 | 43 | dependencies { 44 | addFeatureModuleDependantDependencies() 45 | addHiltDependencies() 46 | addAndroidxCoreDependencies() 47 | addAndroidxNavigationDependencies() 48 | addCoroutinesAndroidDependencies() 49 | addAndroidResponsiveSizeDependenciesDependencies() 50 | addViewStateDependencies() 51 | addAndroidTestsDependencies() 52 | } -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/plugins/android-base-library.gradle.kts: -------------------------------------------------------------------------------- 1 | package plugins 2 | plugins { 3 | id("com.android.library") 4 | kotlin("android") 5 | kotlin("kapt") 6 | } 7 | 8 | android{ 9 | compileSdk = ProjectConfigs.compileSdkVersion 10 | 11 | defaultConfig { 12 | minSdk = ProjectConfigs.minSdkVersion 13 | targetSdk = ProjectConfigs.targetSdkVersion 14 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 15 | consumerProguardFiles("consumer-rules.pro") 16 | } 17 | compileOptions { 18 | sourceCompatibility = JavaVersion.VERSION_11 19 | targetCompatibility = JavaVersion.VERSION_11 20 | } 21 | kotlinOptions { 22 | jvmTarget = "11" 23 | } 24 | buildFeatures { 25 | viewBinding = true 26 | } 27 | } -------------------------------------------------------------------------------- /common/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dependencies.* 2 | 3 | plugins { 4 | plugins.`android-base-library` 5 | } 6 | dependencies { 7 | addCoroutinesAndroidDependencies() 8 | addAndroidxCoreDependencies() 9 | addAndroidxLifeCycleDependencies() 10 | } 11 | -------------------------------------------------------------------------------- /common/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamrul3288/MVVM-Clean-Architecture-Modularization/578b4e5d559a0fa56610804b7eaac3a2ab3f7ff8/common/consumer-rules.pro -------------------------------------------------------------------------------- /common/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 -------------------------------------------------------------------------------- /common/src/androidTest/java/com/iamkamrul/common/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.common 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.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.getInstrumentation().targetContext 22 | assertEquals("com.iamkamrul.common.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /common/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /common/src/main/java/com/iamkamrul/common/adapter/DataBoundListAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.common.adapter 2 | 3 | import androidx.recyclerview.widget.ListAdapter 4 | import androidx.recyclerview.widget.DiffUtil 5 | import android.view.ViewGroup 6 | import androidx.viewbinding.ViewBinding 7 | 8 | /** 9 | * A generic RecyclerView adapter that uses Data Binding & DiffUtil. 10 | * 11 | * @param Type of the items in the list 12 | * @param The type of the ViewDataBinding 13 | */ 14 | abstract class DataBoundListAdapter( 15 | diffCallback: DiffUtil.ItemCallback 16 | ) : ListAdapter>(diffCallback){ 17 | 18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataBoundViewHolder { 19 | val binding = createBinding(parent) 20 | return DataBoundViewHolder(binding) 21 | } 22 | 23 | override fun onBindViewHolder(holder: DataBoundViewHolder, position: Int) { 24 | 25 | bind(holder.binding, getItem(position), position) 26 | } 27 | 28 | protected abstract fun createBinding(parent: ViewGroup): V 29 | protected abstract fun bind(binding: V, item: T, position: Int) 30 | } 31 | 32 | -------------------------------------------------------------------------------- /common/src/main/java/com/iamkamrul/common/adapter/DataBoundViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.common.adapter 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import androidx.viewbinding.ViewBinding 5 | 6 | /** 7 | * A generic ViewHolder that works with a [ViewBinding]. 8 | * @param The type of the ViewDataBinding. 9 | */ 10 | class DataBoundViewHolder constructor(val binding: T) : RecyclerView.ViewHolder(binding.root) 11 | -------------------------------------------------------------------------------- /common/src/main/java/com/iamkamrul/common/base/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.common.base 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.view.WindowManager 8 | import android.widget.Toast 9 | import androidx.fragment.app.Fragment 10 | import androidx.lifecycle.Lifecycle 11 | import androidx.lifecycle.lifecycleScope 12 | import androidx.lifecycle.repeatOnLifecycle 13 | import androidx.viewbinding.ViewBinding 14 | import com.google.android.material.snackbar.Snackbar 15 | import kotlinx.coroutines.flow.Flow 16 | import kotlinx.coroutines.launch 17 | 18 | abstract class BaseFragment : Fragment() { 19 | private var _binding: V? = null 20 | protected val binding get() = _binding!! 21 | protected abstract fun viewBindingLayout(): V 22 | protected abstract fun initializeView(savedInstanceState: Bundle?) 23 | 24 | override fun onCreateView( 25 | inflater: LayoutInflater, 26 | container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View? { 29 | _binding = viewBindingLayout() 30 | initializeView(savedInstanceState) 31 | return binding.root 32 | } 33 | 34 | protected fun showMessage(message: String?) { 35 | Snackbar.make( 36 | requireActivity().findViewById(android.R.id.content), 37 | "" + message, 38 | Snackbar.LENGTH_LONG 39 | ).show() 40 | } 41 | 42 | protected fun showProgressBar(isLoading: Boolean, view: View) { 43 | if (isLoading) { 44 | view.visibility = View.VISIBLE 45 | requireActivity().window?.setFlags( 46 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, 47 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 48 | ) 49 | } else { 50 | view.visibility = View.GONE 51 | requireActivity().window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) 52 | } 53 | } 54 | 55 | protected fun showToastMessage(message: String) { 56 | Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() 57 | } 58 | 59 | override fun onDestroyView() { 60 | super.onDestroyView() 61 | _binding = null 62 | } 63 | 64 | protected inline fun Flow.execute(crossinline action:(T)->Unit){ 65 | with(viewLifecycleOwner){ 66 | lifecycleScope.launch { 67 | repeatOnLifecycle(Lifecycle.State.STARTED){ 68 | collect{ 69 | action(it) 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /common/src/main/java/com/iamkamrul/common/base/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.common.base 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.viewModelScope 5 | import kotlinx.coroutines.CoroutineDispatcher 6 | import kotlinx.coroutines.Dispatchers 7 | import kotlinx.coroutines.launch 8 | 9 | open class BaseViewModel( 10 | private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO 11 | ) : ViewModel(){ 12 | fun execute(job: suspend () -> Unit){ 13 | viewModelScope.launch { 14 | job.invoke() 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /common/src/main/java/com/iamkamrul/common/extension/RecyclerviewExtension.kt: -------------------------------------------------------------------------------- 1 | package com.iamkamrul.common.extension 2 | 3 | import android.content.Context 4 | import androidx.recyclerview.widget.GridLayoutManager 5 | import androidx.recyclerview.widget.LinearLayoutManager 6 | import androidx.recyclerview.widget.RecyclerView 7 | 8 | fun> Context.setUpGridRecyclerView(view: RecyclerView, viewAdapter:T, column:Int){ 9 | view.setHasFixedSize(true) 10 | view.layoutManager = GridLayoutManager(this,column) 11 | view.adapter = viewAdapter 12 | } 13 | 14 | fun> Context.setUpHorizontalReverseRecyclerView(view: RecyclerView, viewAdapter:T){ 15 | view.setHasFixedSize(true) 16 | view.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,false) 17 | view.adapter = viewAdapter 18 | } 19 | 20 | fun> Context.setUpVerticalRecyclerView(view: RecyclerView, viewAdapter:T){ 21 | view.setHasFixedSize(true) 22 | view.layoutManager = LinearLayoutManager(this) 23 | view.adapter = viewAdapter 24 | } 25 | 26 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/ic_baseline_circle_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/ic_baseline_fork_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/drawable/ic_baseline_star_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common/src/main/res/values-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 48dp 3 | -------------------------------------------------------------------------------- /common/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | #000000 5 | #333333 6 | #212121 7 | -------------------------------------------------------------------------------- /common/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /common/src/main/res/values-v29/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /common/src/main/res/values-w1240dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 200dp 3 | -------------------------------------------------------------------------------- /common/src/main/res/values-w600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 48dp 3 | -------------------------------------------------------------------------------- /common/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF000000 4 | #FFFFFFFF 5 | #F6F5F5 6 | #FFFFFF 7 | -------------------------------------------------------------------------------- /common/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | -------------------------------------------------------------------------------- /common/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GithubRepo 3 | Settings 4 | 5 | First Fragment 6 | Second Fragment 7 | Next 8 | Previous 9 | 10 | 11 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris 12 | volutpat, dolor id interdum ullamcorper, risus dolor egestas lectus, sit amet mattis purus 13 | dui nec risus. Maecenas non sodales nisi, vel dictum dolor. Class aptent taciti sociosqu ad 14 | litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse blandit eleifend 15 | diam, vel rutrum tellus vulputate quis. Aliquam eget libero aliquet, imperdiet nisl a, 16 | ornare ex. Sed rhoncus est ut libero porta lobortis. Fusce in dictum tellus.\n\n 17 | Suspendisse interdum ornare ante. Aliquam nec cursus lorem. Morbi id magna felis. Vivamus 18 | egestas, est a condimentum egestas, turpis nisl iaculis ipsum, in dictum tellus dolor sed 19 | neque. Morbi tellus erat, dapibus ut sem a, iaculis tincidunt dui. Interdum et malesuada 20 | fames ac ante ipsum primis in faucibus. Curabitur et eros porttitor, ultricies urna vitae, 21 | molestie nibh. Phasellus at commodo eros, non aliquet metus. Sed maximus nisl nec dolor 22 | bibendum, vel congue leo egestas.\n\n 23 | Sed interdum tortor nibh, in sagittis risus mollis quis. Curabitur mi odio, condimentum sit 24 | amet auctor at, mollis non turpis. Nullam pretium libero vestibulum, finibus orci vel, 25 | molestie quam. Fusce blandit tincidunt nulla, quis sollicitudin libero facilisis et. Integer 26 | interdum nunc ligula, et fermentum metus hendrerit id. Vestibulum lectus felis, dictum at 27 | lacinia sit amet, tristique id quam. Cras eu consequat dui. Suspendisse sodales nunc ligula, 28 | in lobortis sem porta sed. Integer id ultrices magna, in luctus elit. Sed a pellentesque 29 | est.\n\n 30 | Aenean nunc velit, lacinia sed dolor sed, ultrices viverra nulla. Etiam a venenatis nibh. 31 | Morbi laoreet, tortor sed facilisis varius, nibh orci rhoncus nulla, id elementum leo dui 32 | non lorem. Nam mollis ipsum quis auctor varius. Quisque elementum eu libero sed commodo. In 33 | eros nisl, imperdiet vel imperdiet et, scelerisque a mauris. Pellentesque varius ex nunc, 34 | quis imperdiet eros placerat ac. Duis finibus orci et est auctor tincidunt. Sed non viverra 35 | ipsum. Nunc quis augue egestas, cursus lorem at, molestie sem. Morbi a consectetur ipsum, a 36 | placerat diam. Etiam vulputate dignissim convallis. Integer faucibus mauris sit amet finibus 37 | convallis.\n\n 38 | Phasellus in aliquet mi. Pellentesque habitant morbi tristique senectus et netus et 39 | malesuada fames ac turpis egestas. In volutpat arcu ut felis sagittis, in finibus massa 40 | gravida. Pellentesque id tellus orci. Integer dictum, lorem sed efficitur ullamcorper, 41 | libero justo consectetur ipsum, in mollis nisl ex sed nisl. Donec maximus ullamcorper 42 | sodales. Praesent bibendum rhoncus tellus nec feugiat. In a ornare nulla. Donec rhoncus 43 | libero vel nunc consequat, quis tincidunt nisl eleifend. Cras bibendum enim a justo luctus 44 | vestibulum. Fusce dictum libero quis erat maximus, vitae volutpat diam dignissim. 45 | 46 | -------------------------------------------------------------------------------- /common/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 |