From ea29d69ce89d0f810b42f3f4c5669a8c50943ae4 Mon Sep 17 00:00:00 2001 From: Emad Askar Date: Sun, 2 Jun 2024 23:51:42 +0300 Subject: [PATCH 1/2] + Remove srcBuild and update gradle & apply version catalog --- actionChooser/build.gradle | 29 --- actionChooser/build.gradle.kts | 39 +++ actionChooser/proguard-rules.pro | 2 +- actionChooser/src/main/AndroidManifest.xml | 6 +- app/build.gradle.kts | 72 +++--- app/src/main/AndroidManifest.xml | 3 +- .../base_mvvm/core/MyApplication.kt | 32 --- appTutorial/build.gradle | 30 --- appTutorial/build.gradle.kts | 42 ++++ appTutorial/proguard-rules.pro | 2 +- appTutorial/src/main/AndroidManifest.xml | 6 +- .../app_tutorial/AppTutorialHelper.kt | 1 + .../app_tutorial/TutorialAdapter.kt | 3 +- build.gradle.kts | 46 ++-- buildSrc/build.gradle.kts | 9 - buildSrc/src/main/java/Config.kt | 45 ---- buildSrc/src/main/java/Libraries.kt | 55 ---- buildSrc/src/main/java/Versions.kt | 46 ---- data/build.gradle.kts | 36 ++- data/src/main/AndroidManifest.xml | 2 +- domain/build.gradle.kts | 12 +- .../base_mvvm/domain/utils/Resource.kt | 4 +- gradle/libs.versions.toml | 115 +++++++++ gradle/wrapper/gradle-wrapper.properties | 2 +- imagesSlider/build.gradle | 34 --- imagesSlider/build.gradle.kts | 45 ++++ imagesSlider/proguard-rules.pro | 2 +- imagesSlider/src/main/AndroidManifest.xml | 3 +- presentation/build.gradle.kts | 79 +++--- presentation/src/main/AndroidManifest.xml | 3 +- .../presentation/account/AccountFragment.kt | 2 + .../presentation/auth/log_in/LogInFragment.kt | 2 + .../presentation/base/BaseActivity.kt | 45 +--- .../base/extensions/NavigationExtensions.kt | 238 ------------------ .../base/extensions/ViewExtensions.kt | 16 +- .../presentation/home/HomeActivity.kt | 61 ++--- .../src/main/res/layout/activity_home.xml | 13 +- .../src/main/res/layout/content_general.xml | 7 +- .../src/main/res/layout/list_general.xml | 5 - .../src/main/res/navigation/nav_main.xml | 10 + prettyPopUp/build.gradle | 29 --- prettyPopUp/build.gradle.kts | 40 +++ prettyPopUp/proguard-rules.pro | 2 +- prettyPopUp/src/main/AndroidManifest.xml | 6 +- settings.gradle.kts | 46 ++-- 45 files changed, 524 insertions(+), 803 deletions(-) delete mode 100644 actionChooser/build.gradle create mode 100644 actionChooser/build.gradle.kts delete mode 100644 appTutorial/build.gradle create mode 100644 appTutorial/build.gradle.kts delete mode 100644 buildSrc/build.gradle.kts delete mode 100644 buildSrc/src/main/java/Config.kt delete mode 100644 buildSrc/src/main/java/Libraries.kt delete mode 100644 buildSrc/src/main/java/Versions.kt create mode 100644 gradle/libs.versions.toml delete mode 100644 imagesSlider/build.gradle create mode 100644 imagesSlider/build.gradle.kts delete mode 100644 presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/NavigationExtensions.kt create mode 100644 presentation/src/main/res/navigation/nav_main.xml delete mode 100644 prettyPopUp/build.gradle create mode 100644 prettyPopUp/build.gradle.kts diff --git a/actionChooser/build.gradle b/actionChooser/build.gradle deleted file mode 100644 index dc23dbf..0000000 --- a/actionChooser/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -plugins { - id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' -} - -android { - compileSdk 30 - - defaultConfig { - minSdk 21 - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - viewBinding { - enabled true - } -} - -dependencies { - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03" - implementation "com.google.android.material:material:1.4.0" -} \ No newline at end of file diff --git a/actionChooser/build.gradle.kts b/actionChooser/build.gradle.kts new file mode 100644 index 0000000..f0ff11f --- /dev/null +++ b/actionChooser/build.gradle.kts @@ -0,0 +1,39 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.android.kotlin) +} + +android { + namespace = "codes.mina_mikhail.action_chooser" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles (getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + buildFeatures { + viewBinding = true + } + +} + +dependencies { + implementation(libs.lifecycle) + implementation(libs.materialDesign) +} \ No newline at end of file diff --git a/actionChooser/proguard-rules.pro b/actionChooser/proguard-rules.pro index 481bb43..ff59496 100644 --- a/actionChooser/proguard-rules.pro +++ b/actionChooser/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/actionChooser/src/main/AndroidManifest.xml b/actionChooser/src/main/AndroidManifest.xml index 596b932..1d26c87 100644 --- a/actionChooser/src/main/AndroidManifest.xml +++ b/actionChooser/src/main/AndroidManifest.xml @@ -1,6 +1,2 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b17635c..65e7195 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,36 +1,38 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties plugins { - id(Config.Plugins.androidApplication) - id(Config.Plugins.kotlinAndroid) - id(Config.Plugins.kotlinKapt) - id(Config.Plugins.navigationSafeArgs) - id(Config.Plugins.hilt) + alias(libs.plugins.android.application) + alias(libs.plugins.android.kotlin) + alias(libs.plugins.kotlin.ksp) + alias(libs.plugins.navigation.safeargs) + alias(libs.plugins.dagger.hilt.android) + alias(libs.plugins.googleServices) } android { - compileSdk = Config.AppConfig.compileSdkVersion + namespace = "com.mina_mikhail.base_mvvm" + compileSdk = 34 defaultConfig { - applicationId = Config.AppConfig.appId - minSdk = Config.AppConfig.minSdkVersion - targetSdk = Config.AppConfig.compileSdkVersion - versionCode = Config.AppConfig.versionCode - versionName = Config.AppConfig.versionName + applicationId = "com.mina_mikhail.base_mvvm" + minSdk = 21 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" vectorDrawables.useSupportLibrary = true multiDexEnabled = true - testInstrumentationRunner = Config.AppConfig.testRunner + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { - getByName("debug") { - resValue("string", "google_api_key", gradleLocalProperties(rootDir).getProperty("GOOGLE_API_KEY")) + debug{ +// resValue("string", "google_api_key", gradleLocalProperties(rootDir).getProperty("GOOGLE_API_KEY")) manifestPlaceholders["appName"] = "@string/app_name_debug" manifestPlaceholders["appIcon"] = "@mipmap/ic_launcher_debug" manifestPlaceholders["appRoundIcon"] = "@mipmap/ic_launcher_debug_round" - buildConfigField("String", "API_BASE_URL", Config.Environments.debugBaseUrl) + buildConfigField("String", "API_BASE_URL", "http://url.to.server/api/") } signingConfigs { @@ -42,32 +44,33 @@ android { } } - getByName("release") { + release{ signingConfig = signingConfigs.getByName("releaseConfig") isMinifyEnabled = true isShrinkResources = true - resValue("string", "google_api_key", gradleLocalProperties(rootDir).getProperty("GOOGLE_API_KEY")) +// resValue("string", "google_api_key", gradleLocalProperties(rootDir).getProperty("GOOGLE_API_KEY")) manifestPlaceholders["appName"] = "@string/app_name" manifestPlaceholders["appIcon"] = "@mipmap/ic_launcher" manifestPlaceholders["appRoundIcon"] = "@mipmap/ic_launcher_round" - buildConfigField("String", "API_BASE_URL", Config.Environments.releaseBaseUrl) + buildConfigField("String", "API_BASE_URL", "http://url.to.server/api/") } } compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = "11" + jvmTarget = JavaVersion.VERSION_17.toString() } - dataBinding { - isEnabled = true + buildFeatures { + buildConfig = true + dataBinding = true } } @@ -75,23 +78,20 @@ dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) // Networking - implementation(Libraries.retrofit) - implementation(Libraries.retrofitConverter) - implementation(Libraries.gson) - implementation(Libraries.interceptor) - implementation(Libraries.chuckLogging) + implementation(libs.bundles.networking) // Utils - implementation(Libraries.playServices) - implementation(Libraries.localization) - implementation(Libraries.multidex) + + implementation(libs.playServices) + implementation(libs.localization) + implementation(libs.multidex) // Hilt - implementation(Libraries.hilt) - kapt(Libraries.hiltDaggerCompiler) + implementation(libs.hilt) + ksp(libs.hiltDaggerCompiler) // Project Modules - implementation(project(Config.Modules.domain)) - implementation(project(Config.Modules.data)) - implementation(project(Config.Modules.presentation)) + implementation(projects.domain) + implementation(projects.data) + implementation(projects.presentation) } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dbf5aa3..e5a1de2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> diff --git a/app/src/main/java/com/mina_mikhail/base_mvvm/core/MyApplication.kt b/app/src/main/java/com/mina_mikhail/base_mvvm/core/MyApplication.kt index e570c84..d73f34c 100644 --- a/app/src/main/java/com/mina_mikhail/base_mvvm/core/MyApplication.kt +++ b/app/src/main/java/com/mina_mikhail/base_mvvm/core/MyApplication.kt @@ -2,14 +2,8 @@ package com.mina_mikhail.base_mvvm.core import android.content.Context import androidx.multidex.MultiDex -import com.google.android.gms.common.GooglePlayServicesNotAvailableException -import com.google.android.gms.common.GooglePlayServicesRepairableException -import com.google.android.gms.security.ProviderInstaller import com.zeugmasolutions.localehelper.LocaleAwareApplication import dagger.hilt.android.HiltAndroidApp -import java.security.KeyManagementException -import java.security.NoSuchAlgorithmException -import javax.net.ssl.SSLContext @HiltAndroidApp class MyApplication : LocaleAwareApplication() { @@ -20,30 +14,4 @@ class MyApplication : LocaleAwareApplication() { MultiDex.install(this) } - - override - fun onCreate() { - super.onCreate() - - updateAndroidSecurityProvider() - } - - private fun updateAndroidSecurityProvider() { - // To fix the following issue, when run app in cellular data, Apis not working - // javax.net.ssl.SSLHandshakeException: SSL handshake aborted: ssl=0x7edfc49e08: I/O error during system call, Connection reset by peer - try { - ProviderInstaller.installIfNeeded(applicationContext) - val sslContext: SSLContext = SSLContext.getInstance("TLSv1.2") - sslContext.init(null, null, null) - sslContext.createSSLEngine() - } catch (e: GooglePlayServicesRepairableException) { - e.printStackTrace() - } catch (e: GooglePlayServicesNotAvailableException) { - e.printStackTrace() - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - } catch (e: KeyManagementException) { - e.printStackTrace() - } - } } \ No newline at end of file diff --git a/appTutorial/build.gradle b/appTutorial/build.gradle deleted file mode 100644 index c1bc4e3..0000000 --- a/appTutorial/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -plugins { - id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' -} - -android { - compileSdk 30 - - defaultConfig { - minSdk 21 - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - viewBinding { - enabled true - } -} - -dependencies { - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1" - implementation "com.google.android.material:material:1.4.0" -} \ No newline at end of file diff --git a/appTutorial/build.gradle.kts b/appTutorial/build.gradle.kts new file mode 100644 index 0000000..3f97c7f --- /dev/null +++ b/appTutorial/build.gradle.kts @@ -0,0 +1,42 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.android.kotlin) + alias(libs.plugins.kotlin.ksp) +} + +android { + namespace = "codes.mina_mikhail.tutorial" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles (getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + + buildFeatures { + viewBinding = true + } +} + +dependencies { + implementation(libs.lifecycle) + implementation(libs.materialDesign) + implementation(libs.coroutinesCore) + implementation(libs.coroutinesAndroid) +} \ No newline at end of file diff --git a/appTutorial/proguard-rules.pro b/appTutorial/proguard-rules.pro index 481bb43..ff59496 100644 --- a/appTutorial/proguard-rules.pro +++ b/appTutorial/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/appTutorial/src/main/AndroidManifest.xml b/appTutorial/src/main/AndroidManifest.xml index 69eea33..1d26c87 100644 --- a/appTutorial/src/main/AndroidManifest.xml +++ b/appTutorial/src/main/AndroidManifest.xml @@ -1,6 +1,2 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/AppTutorialHelper.kt b/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/AppTutorialHelper.kt index 94de78c..e8d446d 100644 --- a/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/AppTutorialHelper.kt +++ b/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/AppTutorialHelper.kt @@ -18,6 +18,7 @@ import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.coroutineScope import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 +import codes.mina_mikhail.tutorial.R import kotlinx.coroutines.delay class AppTutorialHelper private constructor(builder: Builder) : LifecycleObserver { diff --git a/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/TutorialAdapter.kt b/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/TutorialAdapter.kt index 853da64..1711000 100644 --- a/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/TutorialAdapter.kt +++ b/appTutorial/src/main/java/codes/mina_mikhail/app_tutorial/TutorialAdapter.kt @@ -6,7 +6,8 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import codes.mina_mikhail.app_tutorial.TutorialAdapter.ImagesSliderViewHolder -import codes.mina_mikhail.app_tutorial.databinding.ItemTutorialBinding +import codes.mina_mikhail.tutorial.R +import codes.mina_mikhail.tutorial.databinding.ItemTutorialBinding internal class TutorialAdapter( private var titleColor: Int, diff --git a/build.gradle.kts b/build.gradle.kts index 9d0b2c6..5533e85 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,44 +1,34 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. +import org.jlleitschuh.gradle.ktlint.KtlintExtension + +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.android.kotlin) apply false + alias(libs.plugins.kotlin.ksp) apply false + alias(libs.plugins.kotlin.jvm) apply false + alias(libs.plugins.navigation.safeargs) apply false + alias(libs.plugins.ktlint) apply false + alias(libs.plugins.dagger.hilt.android) apply false + alias(libs.plugins.googleServices) apply false +} + buildscript { - repositories { - google() - mavenCentral() - } dependencies { - classpath(Config.Dependencies.gradleVersion) - classpath(Config.Dependencies.kotlin) - classpath(Config.Dependencies.navigationSafeArgs) - classpath(Config.Dependencies.hilt) + classpath(libs.navigationSafeArgs) } } -plugins { - id(Config.Plugins.ktLint) version Versions.ktLint -} - subprojects { - apply(plugin = Config.Plugins.ktLint) // To apply ktLint to all included modules - - repositories { - mavenCentral() - } + apply(plugin = "org.jlleitschuh.gradle.ktlint") // To apply ktLint to all included modules - configure { + configure { debug.set(true) } } -allprojects { - repositories { - google() - mavenCentral() - jcenter() - maven(url = Config.Dependencies.jitPackURL) - } -} tasks.register("clean", Delete::class) { - delete(rootProject.buildDir) + delete(rootProject.layout.buildDirectory) } tasks.register("installGitHooks", Copy::class) { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index 56d089c..0000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,9 +0,0 @@ -plugins { - `kotlin-dsl` -} - -repositories { - google() - mavenCentral() - jcenter() -} \ No newline at end of file diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt deleted file mode 100644 index 79d92ab..0000000 --- a/buildSrc/src/main/java/Config.kt +++ /dev/null @@ -1,45 +0,0 @@ -object Config { - object AppConfig { - const val appId = "com.mina_mikhail.base_mvvm" - const val compileSdkVersion = 30 - const val minSdkVersion = 21 - const val versionCode = 1 - const val versionName = "1" - const val testRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - object Dependencies { - const val jitPackURL = "https://jitpack.io" - const val gradleVersion = "com.android.tools.build:gradle:${Versions.gradleVersion}" - const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}" - const val navigationSafeArgs = - "androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.androidNavigation}" - const val hilt = "com.google.dagger:hilt-android-gradle-plugin:${Versions.hiltVersion}" - } - - object Plugins { - const val androidApplication = "com.android.application" - const val kotlinAndroid = "kotlin-android" - const val kotlinKapt = "kotlin-kapt" - const val navigationSafeArgs = "androidx.navigation.safeargs" - const val hilt = "dagger.hilt.android.plugin" - const val androidLibrary = "com.android.library" - const val kotlinJvm = "org.jetbrains.kotlin.jvm" - const val ktLint = "org.jlleitschuh.gradle.ktlint" - } - - object Modules { - const val domain = ":domain" - const val data = ":data" - const val presentation = ":presentation" - const val prettyPopUp = ":prettyPopUp" - const val actionChooser = ":actionChooser" - const val appTutorial = ":appTutorial" - const val imagesSlider = ":imagesSlider" - } - - object Environments { - const val debugBaseUrl = "\"http://url.to.server/api/\"" - const val releaseBaseUrl = "\"http://url.to.server/api/\"" - } -} \ No newline at end of file diff --git a/buildSrc/src/main/java/Libraries.kt b/buildSrc/src/main/java/Libraries.kt deleted file mode 100644 index 3a87859..0000000 --- a/buildSrc/src/main/java/Libraries.kt +++ /dev/null @@ -1,55 +0,0 @@ -object Libraries { - - // Support - const val appCompat = "androidx.appcompat:appcompat:${Versions.appcompat}" - const val coreKtx = "androidx.core:core-ktx:${Versions.coreKtx}" - const val androidSupport = "androidx.legacy:legacy-support-v4:${Versions.supportVersion}" - - // Kotlin - const val kotlin = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Versions.kotlin}" - - // Java - const val javaInject = "javax.inject:javax.inject:${Versions.javaInject}" - - // Arch Components - const val viewModel = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifecycle}" - const val lifeData = "androidx.lifecycle:lifecycle-livedata-ktx:${Versions.lifecycle}" - const val lifecycle = "androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle}" - const val viewModelState = "androidx.lifecycle:lifecycle-viewmodel-savedstate:${Versions.lifecycle}" - - // Kotlin Coroutines - const val coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}" - const val coroutinesAndroid = - "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.kotlinCoroutines}" - - // Networking - const val retrofit = "com.squareup.retrofit2:retrofit:${Versions.retrofit}" - const val retrofitConverter = "com.squareup.retrofit2:converter-gson:${Versions.retrofit}" - const val gson = "com.google.code.gson:gson:${Versions.gson}" - const val interceptor = "com.squareup.okhttp3:logging-interceptor:${Versions.interceptor}" - const val chuckLogging = "com.readystatesoftware.chuck:library:${Versions.chuckLogging}" - - // UI - const val materialDesign = "com.google.android.material:material:${Versions.materialDesign}" - const val navigationFragment = "androidx.navigation:navigation-fragment-ktx:${Versions.androidNavigation}" - const val navigationUI = "androidx.navigation:navigation-ui-ktx:${Versions.androidNavigation}" - const val loadingAnimations = "com.github.ybq:Android-SpinKit:${Versions.loadingAnimations}" - const val alerter = "com.github.tapadoo:alerter:${Versions.alerter}" - const val coil = "io.coil-kt:coil:${Versions.coil}" - - // Utils - const val playServices = "com.google.android.gms:play-services-auth:${Versions.playServices}" - const val localization = "com.zeugmasolutions.localehelper:locale-helper-android:${Versions.localization}" - const val multidex = "androidx.multidex:multidex:${Versions.multidex}" - const val permissions = "com.afollestad.assent:core:${Versions.permissions}" - - // Hilt - const val hilt = "com.google.dagger:hilt-android:${Versions.hiltVersion}" - const val hiltDaggerCompiler = "com.google.dagger:hilt-android-compiler:${Versions.hiltVersion}" - - // Map - const val map = "com.google.android.gms:play-services-maps:${Versions.map}" - const val playServicesLocation = - "com.google.android.gms:play-services-location:${Versions.playServicesLocation}" - const val rxLocation = "com.github.ShabanKamell:RxLocation:${Versions.rxLocation}" -} \ No newline at end of file diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt deleted file mode 100644 index f0563a9..0000000 --- a/buildSrc/src/main/java/Versions.kt +++ /dev/null @@ -1,46 +0,0 @@ -object Versions { - const val gradleVersion = "7.0.2" - const val kotlin = "1.5.21" - const val ktLint = "10.2.0" - - // Java Inject - const val javaInject = "1" - - // Support - const val appcompat = "1.3.1" - const val coreKtx = "1.6.0" - const val supportVersion = "1.0.0" - - // Arch Components - const val lifecycle = "2.4.0-alpha03" - - // Kotlin Coroutines - const val kotlinCoroutines = "1.4.1" - - // Networking - const val retrofit = "2.9.0" - const val gson = "2.8.6" - const val interceptor = "4.8.1" - const val chuckLogging = "1.1.0" - - // UI - const val materialDesign = "1.4.0" - const val androidNavigation = "2.3.5" - const val loadingAnimations = "1.4.0" - const val alerter = "7.2.4" - const val coil = "1.3.2" - - // Utils - const val playServices = "19.2.0" - const val localization = "1.1.4" - const val multidex = "2.0.1" - const val permissions = "3.0.0-RC4" - - // Hilt - const val hiltVersion = "2.38.1" - - // Map - const val map = "17.0.1" - const val playServicesLocation = "18.0.0" - const val rxLocation = "1.0" -} \ No newline at end of file diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 868ae7d..7a2e8a3 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -1,36 +1,46 @@ plugins { - id(Config.Plugins.androidLibrary) - id(Config.Plugins.kotlinAndroid) - id(Config.Plugins.kotlinKapt) + alias(libs.plugins.android.library) + alias(libs.plugins.android.kotlin) + alias(libs.plugins.kotlin.ksp) } android { - compileSdk = Config.AppConfig.compileSdkVersion + namespace = "com.mina_mikhail.base_mvvm.data" + compileSdk = 34 defaultConfig { - minSdk = Config.AppConfig.minSdkVersion - targetSdk = Config.AppConfig.compileSdkVersion + minSdk = 21 } + buildTypes { - getByName("release") { + release { proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") } } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + } dependencies { // Kotlin Coroutines - implementation(Libraries.coroutinesCore) - implementation(Libraries.coroutinesAndroid) + implementation(libs.coroutinesCore) + implementation(libs.coroutinesAndroid) // Networking - implementation(Libraries.retrofit) - implementation(Libraries.gson) + implementation(libs.bundles.networking) - implementation(Libraries.javaInject) + implementation(libs.javaInject) // Project Modules - implementation(project(Config.Modules.domain)) + implementation(projects.domain) } \ No newline at end of file diff --git a/data/src/main/AndroidManifest.xml b/data/src/main/AndroidManifest.xml index c47c7e2..1d26c87 100644 --- a/data/src/main/AndroidManifest.xml +++ b/data/src/main/AndroidManifest.xml @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 8e2b3f0..59be345 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -1,16 +1,16 @@ plugins { - id(Config.Plugins.kotlinJvm) + alias(libs.plugins.kotlin.jvm) } java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } dependencies { // Kotlin Coroutines - implementation(Libraries.coroutinesCore) - implementation(Libraries.coroutinesAndroid) + implementation(libs.coroutinesCore) + implementation(libs.coroutinesAndroid) - implementation(Libraries.javaInject) + implementation(libs.javaInject) } \ No newline at end of file diff --git a/domain/src/main/java/com/mina_mikhail/base_mvvm/domain/utils/Resource.kt b/domain/src/main/java/com/mina_mikhail/base_mvvm/domain/utils/Resource.kt index 8ab3e5f..93896b9 100644 --- a/domain/src/main/java/com/mina_mikhail/base_mvvm/domain/utils/Resource.kt +++ b/domain/src/main/java/com/mina_mikhail/base_mvvm/domain/utils/Resource.kt @@ -10,7 +10,7 @@ sealed class Resource { val message: String? = null ) : Resource() - object Loading : Resource() + data object Loading : Resource() - object Default : Resource() + data object Default : Resource() } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..e0e9b8b --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,115 @@ +[versions] +gradleVersion = "8.4.1" +kotlin = "2.0.0" +ktLint = "10.2.0" +javaInject = "1" +appcompat = "1.7.0" +coreKtx = "1.13.1" +supportVersion = "1.0.0" +lifecycle = "2.8.1" +kotlinCoroutines = "1.7.3" +retrofit = "2.9.0" +gson = "2.10.1" +interceptor = "4.10.0" +chuckLogging = "1.1.0" +materialDesign = "1.12.0" +androidNavigation = "2.7.7" +loadingAnimations = "1.4.0" +alerter = "7.2.4" +coil = "2.4.0" +gms-googleServices = "4.4.2" +playServices = "21.2.0" +localization = "1.5.1" +multidex = "2.0.1" +permissions = "3.0.0-RC4" +hiltVersion = "2.51.1" +map = "18.2.0" +playServicesLocation = "21.3.0" +ksp = "2.0.0-1.0.21" +glide = "4.15.1" +swiperefreshlayout = "1.1.0" +photoView = "2.3.0" + +[libraries] + +# Support +appCompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat"} +coreKtx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx"} +androidSupport = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "supportVersion"} +androidSwiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" } +# Kotlin +kotlin = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" } + +# Java +javaInject = { group = "javax.inject", name = "javax.inject", version.ref = "javaInject" } + +# Arch Components +viewModel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +lifeData = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle" } +lifecycle = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } +viewModelState = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-savedstate", version.ref = "lifecycle" } + +# Coroutines +coroutinesCore = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinCoroutines" } +coroutinesAndroid = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinCoroutines" } + + +# Networking +retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } +retrofitConverter = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" } +gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } +interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "interceptor" } +chuckLogging = { group = "com.readystatesoftware.chuck", name = "library", version.ref = "chuckLogging" } + +# UI +materialDesign = { group = "com.google.android.material", name = "material", version.ref = "materialDesign" } +navigationSafeArgs = {group = "androidx.navigation",name = "navigation-safe-args-gradle-plugin", version.ref = "androidNavigation"} +navigationFragment = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "androidNavigation" } +navigationUI = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "androidNavigation" } +loadingAnimations = { group = "com.github.ybq", name = "Android-SpinKit", version.ref = "loadingAnimations" } +alerter = { group = "com.github.tapadoo", name = "alerter", version.ref = "alerter" } +coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" } + +# Utils +playServices = { group = "com.google.android.gms", name = "play-services-auth", version.ref = "playServices" } +localization = { group = "com.zeugmasolutions.localehelper", name = "locale-helper-android", version.ref = "localization" } +multidex = { group = "androidx.multidex", name = "multidex", version.ref = "multidex" } +permissions = { group = "com.afollestad.assent", name = "core", version.ref = "permissions" } +glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide"} +glideCompiler = { group = "com.github.bumptech.glide", name = "ksp", version.ref = "glide"} +photoView = { group = "com.github.chrisbanes", name = "PhotoView", version.ref = "photoView"} + +# Hilt +hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "hiltVersion" } +hiltDaggerCompiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hiltVersion" } + +# Maps +map = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "map" } +playServicesLocation = { group = "com.google.android.gms", name = "play-services-location", version.ref = "playServicesLocation" } + +[bundles] + +networking = [ + "retrofit","retrofitConverter","gson","interceptor","chuckLogging" +] + +androidSupport = [ + "appCompat","coreKtx","androidSupport" +] + +archComponents = [ "viewModel","lifecycle","lifeData","viewModelState", + "materialDesign","navigationFragment","navigationUI" +] + + +[plugins] +android-library = { id = "com.android.library", version.ref = "gradleVersion" } +android-application = { id = "com.android.application", version.ref = "gradleVersion"} +android-kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin"} +kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"} +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin"} +navigation-safeargs = { id = "androidx.navigation.safeargs", version.ref = "androidNavigation" } +dagger-hilt-android = { id = "com.google.dagger.hilt.android" , version.ref = "hiltVersion" } +ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktLint" } +googleServices = { id = "com.google.gms.google-services", version.ref = "gms-googleServices"} + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6974aba..5815001 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sat Aug 14 00:33:07 EET 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/imagesSlider/build.gradle b/imagesSlider/build.gradle deleted file mode 100644 index b8a1ef2..0000000 --- a/imagesSlider/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -plugins { - id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' -} - -android { - compileSdk 30 - - defaultConfig { - minSdk 21 - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - viewBinding { - enabled true - } -} - -dependencies { - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1" - implementation "com.google.android.material:material:1.4.0" - implementation "com.github.chrisbanes:PhotoView:2.3.0" - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - implementation "com.github.bumptech.glide:glide:4.12.0" - kapt "com.github.bumptech.glide:compiler:4.12.0" -} \ No newline at end of file diff --git a/imagesSlider/build.gradle.kts b/imagesSlider/build.gradle.kts new file mode 100644 index 0000000..0d41e43 --- /dev/null +++ b/imagesSlider/build.gradle.kts @@ -0,0 +1,45 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.android.kotlin) + alias(libs.plugins.kotlin.ksp) +} + +android { + namespace = "codes.mina_mikhail.images_slider" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles (getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + + buildFeatures { + viewBinding = true + } +} + +dependencies { + implementation(libs.lifecycle) + implementation(libs.materialDesign) + implementation(libs.coroutinesCore) + implementation(libs.photoView) + implementation(libs.androidSwiperefreshlayout) + implementation(libs.glide) + ksp(libs.glideCompiler) +} \ No newline at end of file diff --git a/imagesSlider/proguard-rules.pro b/imagesSlider/proguard-rules.pro index a8c234f..9fc645c 100644 --- a/imagesSlider/proguard-rules.pro +++ b/imagesSlider/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/imagesSlider/src/main/AndroidManifest.xml b/imagesSlider/src/main/AndroidManifest.xml index ef5d7fa..1681dd4 100644 --- a/imagesSlider/src/main/AndroidManifest.xml +++ b/imagesSlider/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + diff --git a/presentation/build.gradle.kts b/presentation/build.gradle.kts index 412b501..6609e5f 100644 --- a/presentation/build.gradle.kts +++ b/presentation/build.gradle.kts @@ -1,75 +1,76 @@ plugins { - id(Config.Plugins.androidLibrary) - id(Config.Plugins.kotlinAndroid) - id(Config.Plugins.kotlinKapt) - id(Config.Plugins.hilt) - id(Config.Plugins.navigationSafeArgs) + alias(libs.plugins.android.library) + alias(libs.plugins.android.kotlin) + alias(libs.plugins.kotlin.ksp) + alias(libs.plugins.dagger.hilt.android) + alias(libs.plugins.navigation.safeargs) } android { - compileSdk = Config.AppConfig.compileSdkVersion + namespace = "com.mina_mikhail.base_mvvm.presentation" + compileSdk = 34 defaultConfig { - minSdk = Config.AppConfig.minSdkVersion + minSdk = 21 vectorDrawables.useSupportLibrary = true } buildTypes { - getByName("release") { + release{ proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") } } - dataBinding { - isEnabled = true + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + buildFeatures { + dataBinding = true } } dependencies { // Support - implementation(Libraries.appCompat) - implementation(Libraries.coreKtx) - implementation(Libraries.androidSupport) + implementation(libs.bundles.androidSupport) // Arch Components - implementation(Libraries.viewModel) - implementation(Libraries.lifeData) - implementation(Libraries.lifecycle) - implementation(Libraries.viewModelState) + implementation(libs.bundles.archComponents) // Kotlin Coroutines - implementation(Libraries.coroutinesCore) - implementation(Libraries.coroutinesAndroid) + implementation(libs.coroutinesCore) + implementation(libs.coroutinesAndroid) // UI - implementation(Libraries.materialDesign) - implementation(Libraries.navigationFragment) - implementation(Libraries.navigationUI) - implementation(Libraries.loadingAnimations) - implementation(Libraries.alerter) - implementation(Libraries.coil) + implementation(libs.loadingAnimations) + implementation(libs.alerter) + implementation(libs.coil) // Utils - implementation(Libraries.playServices) - implementation(Libraries.localization) - implementation(Libraries.permissions) - implementation(Libraries.gson) + implementation(libs.playServices) + implementation(libs.localization) + implementation(libs.permissions) + implementation(libs.gson) // Hilt - implementation(Libraries.hilt) - kapt(Libraries.hiltDaggerCompiler) + implementation(libs.hilt) + ksp(libs.hiltDaggerCompiler) // Map - implementation(Libraries.map) - implementation(Libraries.playServicesLocation) - implementation(Libraries.rxLocation) + implementation(libs.map) + implementation(libs.playServicesLocation) // Project Modules - implementation(project(Config.Modules.domain)) - implementation(project(Config.Modules.prettyPopUp)) - implementation(project(Config.Modules.actionChooser)) - implementation(project(Config.Modules.appTutorial)) - implementation(project(Config.Modules.imagesSlider)) + implementation(projects.domain) + implementation(projects.prettyPopUp) + implementation(projects.actionChooser) + implementation(projects.appTutorial) + implementation(projects.imagesSlider) } \ No newline at end of file diff --git a/presentation/src/main/AndroidManifest.xml b/presentation/src/main/AndroidManifest.xml index f31fd20..4685f82 100644 --- a/presentation/src/main/AndroidManifest.xml +++ b/presentation/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + diff --git a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/account/AccountFragment.kt b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/account/AccountFragment.kt index 6a379f1..23359bd 100644 --- a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/account/AccountFragment.kt +++ b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/account/AccountFragment.kt @@ -83,6 +83,8 @@ class AccountFragment : BaseFragment() { hideLoading() handleApiError(it) } + + else -> {} } } } diff --git a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/auth/log_in/LogInFragment.kt b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/auth/log_in/LogInFragment.kt index 86f857f..5fb1b58 100644 --- a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/auth/log_in/LogInFragment.kt +++ b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/auth/log_in/LogInFragment.kt @@ -158,6 +158,8 @@ class LogInFragment : BaseFragment() { hideLoading() handleApiError(it, retryAction = { viewModel.onLogInClicked() }) } + + else -> {} } } } diff --git a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/BaseActivity.kt b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/BaseActivity.kt index d56b85d..1786feb 100644 --- a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/BaseActivity.kt +++ b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/BaseActivity.kt @@ -7,7 +7,6 @@ import androidx.annotation.LayoutRes import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding -import androidx.lifecycle.LiveData import androidx.navigation.NavController import com.zeugmasolutions.localehelper.LocaleHelper import com.zeugmasolutions.localehelper.LocaleHelperActivityDelegate @@ -16,54 +15,40 @@ import java.util.Locale abstract class BaseActivity : AppCompatActivity() { - private val localeDelegate: LocaleHelperActivityDelegate = LocaleHelperActivityDelegateImpl() + private val localeDelegate: LocaleHelperActivityDelegate by lazy { + LocaleHelperActivityDelegateImpl() + } private var _binding: VB? = null - open val binding get() = _binding!! - public lateinit var navController: LiveData + open val binding get() = checkNotNull(_binding) + public lateinit var navController: NavController - override - fun createConfigurationContext(overrideConfiguration: Configuration): Context { + override fun createConfigurationContext(overrideConfiguration: Configuration): Context { val context = super.createConfigurationContext(overrideConfiguration) return LocaleHelper.onAttach(context) } - override - fun getApplicationContext(): Context = + override fun getApplicationContext(): Context = localeDelegate.getApplicationContext(super.getApplicationContext()) - override - fun onResume() { + override fun onResume() { super.onResume() localeDelegate.onResumed(this) } - override - fun onPause() { + override fun onPause() { super.onPause() localeDelegate.onPaused() } - override - fun onCreate(savedInstanceState: Bundle?) { + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initViewBinding() setContentView(binding.root) - if (savedInstanceState == null) { - setUpBottomNavigation() - } - setUpViews() } - override - fun onRestoreInstanceState(savedInstanceState: Bundle) { - super.onRestoreInstanceState(savedInstanceState) - - setUpBottomNavigation() - } - private fun initViewBinding() { _binding = DataBindingUtil.setContentView(this, getLayoutId()) binding.lifecycleOwner = this @@ -73,19 +58,15 @@ abstract class BaseActivity : AppCompatActivity() { @LayoutRes abstract fun getLayoutId(): Int - open fun setUpBottomNavigation() {} - open fun setUpViews() {} open fun updateLocale(language: String) { localeDelegate.setLocale(this, Locale(language)) } - override - fun onSupportNavigateUp(): Boolean { - return navController.value?.navigateUp()!! || super.onSupportNavigateUp() + override fun onSupportNavigateUp(): Boolean { + return navController.navigateUp() || super.onSupportNavigateUp() } - override - fun getDelegate() = localeDelegate.getAppCompatDelegate(super.getDelegate()) + override fun getDelegate() = localeDelegate.getAppCompatDelegate(super.getDelegate()) } \ No newline at end of file diff --git a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/NavigationExtensions.kt b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/NavigationExtensions.kt deleted file mode 100644 index bf00923..0000000 --- a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/NavigationExtensions.kt +++ /dev/null @@ -1,238 +0,0 @@ -package com.mina_mikhail.base_mvvm.presentation.base.extensions - -import android.content.Intent -import android.util.SparseArray -import androidx.core.util.forEach -import androidx.core.util.set -import androidx.fragment.app.FragmentManager -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.navigation.NavController -import androidx.navigation.fragment.NavHostFragment -import com.google.android.material.bottomnavigation.BottomNavigationView -import com.mina_mikhail.base_mvvm.presentation.R - -/** - * Manages the various graphs needed for a [BottomNavigationView]. - * - * This sample is a workaround until the Navigation Component supports multiple back stacks. - */ -fun BottomNavigationView.setupWithNavController( - navGraphIds: List, - fragmentManager: FragmentManager, - containerId: Int, - intent: Intent -): LiveData { - - // Map of tags - val graphIdToTagMap = SparseArray() - // Result. Mutable live data with the selected controlled - val selectedNavController = MutableLiveData() - - var firstFragmentGraphId = 0 - - // First create a NavHostFragment for each NavGraph ID - navGraphIds.forEachIndexed { index, navGraphId -> - val fragmentTag = getFragmentTag(index) - - // Find or create the Navigation host fragment - val navHostFragment = obtainNavHostFragment( - fragmentManager, - fragmentTag, - navGraphId, - containerId - ) - - // Obtain its id - val graphId = navHostFragment.navController.graph.id - - if (index == 0) { - firstFragmentGraphId = graphId - } - - // Save to the map - graphIdToTagMap[graphId] = fragmentTag - - // Attach or detach nav host fragment depending on whether it's the selected item. - if (this.selectedItemId == graphId) { - // Update livedata with the selected graph - selectedNavController.value = navHostFragment.navController - attachNavHostFragment(fragmentManager, navHostFragment, index == 0) - } else { - detachNavHostFragment(fragmentManager, navHostFragment) - } - } - - // Now connect selecting an item with swapping Fragments - var selectedItemTag = graphIdToTagMap[this.selectedItemId] - val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId] - var isOnFirstFragment = selectedItemTag == firstFragmentTag - - // When a navigation item is selected - setOnNavigationItemSelectedListener { item -> - // Don't do anything if the state is state has already been saved. - if (fragmentManager.isStateSaved) { - false - } else { - val newlySelectedItemTag = graphIdToTagMap[item.itemId] - if (selectedItemTag != newlySelectedItemTag) { - // Pop everything above the first fragment (the "fixed start destination") - fragmentManager.popBackStack( - firstFragmentTag, - FragmentManager.POP_BACK_STACK_INCLUSIVE - ) - val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag) - as NavHostFragment - - // Exclude the first fragment tag because it's always in the back stack. - if (firstFragmentTag != newlySelectedItemTag) { - // Commit a transaction that cleans the back stack and adds the first fragment - // to it, creating the fixed started destination. - fragmentManager.beginTransaction() - .setCustomAnimations( - R.anim.nav_default_enter_anim, - R.anim.nav_default_exit_anim, - R.anim.nav_default_pop_enter_anim, - R.anim.nav_default_pop_exit_anim - ) - .attach(selectedFragment) - .setPrimaryNavigationFragment(selectedFragment) - .apply { - // Detach all other Fragments - graphIdToTagMap.forEach { _, fragmentTagIter -> - if (fragmentTagIter != newlySelectedItemTag) { - detach(fragmentManager.findFragmentByTag(firstFragmentTag)!!) - } - } - } - .addToBackStack(firstFragmentTag) - .setReorderingAllowed(true) - .commit() - } - selectedItemTag = newlySelectedItemTag - isOnFirstFragment = selectedItemTag == firstFragmentTag - selectedNavController.value = selectedFragment.navController - true - } else { - false - } - } - } - - // Optional: on item reselected, pop back stack to the destination of the graph - setupItemReselected(graphIdToTagMap, fragmentManager) - - // Handle deep link - setupDeepLinks(navGraphIds, fragmentManager, containerId, intent) - - // Finally, ensure that we update our BottomNavigationView when the back stack changes - fragmentManager.addOnBackStackChangedListener { - if (!isOnFirstFragment && !fragmentManager.isOnBackStack(firstFragmentTag)) { - this.selectedItemId = firstFragmentGraphId - } - - // Reset the graph if the currentDestination is not valid (happens when the back - // stack is popped after using the back button). - selectedNavController.value?.let { controller -> - if (controller.currentDestination == null) { - controller.navigate(controller.graph.id) - } - } - } - return selectedNavController -} - -private fun BottomNavigationView.setupDeepLinks( - navGraphIds: List, - fragmentManager: FragmentManager, - containerId: Int, - intent: Intent -) { - navGraphIds.forEachIndexed { index, navGraphId -> - val fragmentTag = getFragmentTag(index) - - // Find or create the Navigation host fragment - val navHostFragment = obtainNavHostFragment( - fragmentManager, - fragmentTag, - navGraphId, - containerId - ) - // Handle Intent - if (navHostFragment.navController.handleDeepLink(intent) && - selectedItemId != navHostFragment.navController.graph.id - ) { - this.selectedItemId = navHostFragment.navController.graph.id - } - } -} - -private fun BottomNavigationView.setupItemReselected( - graphIdToTagMap: SparseArray, - fragmentManager: FragmentManager -) { - setOnNavigationItemReselectedListener { item -> - val newlySelectedItemTag = graphIdToTagMap[item.itemId] - val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag) - as NavHostFragment - val navController = selectedFragment.navController - // Pop the back stack to the start destination of the current navController graph - navController.popBackStack( - navController.graph.startDestination, false - ) - } -} - -private fun detachNavHostFragment( - fragmentManager: FragmentManager, - navHostFragment: NavHostFragment -) { - fragmentManager.beginTransaction() - .detach(navHostFragment) - .commitNow() -} - -private fun attachNavHostFragment( - fragmentManager: FragmentManager, - navHostFragment: NavHostFragment, - isPrimaryNavFragment: Boolean -) { - fragmentManager.beginTransaction() - .attach(navHostFragment) - .apply { - if (isPrimaryNavFragment) { - setPrimaryNavigationFragment(navHostFragment) - } - } - .commitNow() -} - -private fun obtainNavHostFragment( - fragmentManager: FragmentManager, - fragmentTag: String, - navGraphId: Int, - containerId: Int -): NavHostFragment { - // If the Nav Host fragment exists, return it - val existingFragment = fragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment? - existingFragment?.let { return it } - - // Otherwise, create it and return it. - val navHostFragment = NavHostFragment.create(navGraphId) - fragmentManager.beginTransaction() - .add(containerId, navHostFragment, fragmentTag) - .commitNow() - return navHostFragment -} - -private fun FragmentManager.isOnBackStack(backStackName: String): Boolean { - val backStackCount = backStackEntryCount - for (index in 0 until backStackCount) { - if (getBackStackEntryAt(index).name == backStackName) { - return true - } - } - return false -} - -private fun getFragmentTag(index: Int) = "bottomNavigation#$index" \ No newline at end of file diff --git a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/ViewExtensions.kt b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/ViewExtensions.kt index 1e5c820..dda1d10 100644 --- a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/ViewExtensions.kt +++ b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/base/extensions/ViewExtensions.kt @@ -10,7 +10,6 @@ import android.widget.ProgressBar import androidx.annotation.ColorRes import androidx.constraintlayout.widget.Group import androidx.core.content.ContextCompat -import androidx.databinding.BindingAdapter import coil.ImageLoader import coil.load import coil.request.ImageRequest @@ -46,7 +45,6 @@ fun View.invisible() { } } -@BindingAdapter("app:goneUnless") fun View.goneUnless(visible: Boolean) { visibility = if (visible) View.VISIBLE else View.GONE if (this is Group) { @@ -93,7 +91,6 @@ fun View.showSnackBar(message: String, retryActionName: String? = null, action: snackBar.show() } -@BindingAdapter(value = ["app:loadImage", "app:progressBar"], requireAll = false) fun ImageView.loadImage(imageUrl: String?, progressBar: ProgressBar?) { if (imageUrl != null && imageUrl.isNotEmpty()) { val request = ImageRequest.Builder(context) @@ -112,7 +109,7 @@ fun ImageView.loadImage(imageUrl: String?, progressBar: ProgressBar?) { setImageDrawable(result) } ) - .listener(onError = { request: ImageRequest, _: Throwable -> + .listener(onError = { request, _ -> progressBar?.hide() setImageDrawable(request.error) }) @@ -126,9 +123,8 @@ fun ImageView.loadImage(imageUrl: String?, progressBar: ProgressBar?) { } } -@BindingAdapter(value = ["app:loadCircleImage", "app:progressBar"], requireAll = false) fun ImageView.loadCircleImage(imageUrl: String?, progressBar: ProgressBar?) { - if (imageUrl != null && imageUrl.isNotEmpty()) { + if (!imageUrl.isNullOrEmpty()) { val request = ImageRequest.Builder(context) .data(imageUrl) .crossfade(true) @@ -148,7 +144,7 @@ fun ImageView.loadCircleImage(imageUrl: String?, progressBar: ProgressBar?) { setImageDrawable(result) } ) - .listener(onError = { request: ImageRequest, _: Throwable -> + .listener(onError = { request, _ -> progressBar?.hide() setImageDrawable(request.error) }) @@ -167,9 +163,8 @@ fun ImageView.loadCircleImage(imageUrl: String?, progressBar: ProgressBar?) { } } -@BindingAdapter(value = ["app:loadRoundImage", "app:progressBar"], requireAll = false) fun ImageView.loadRoundImage(imageUrl: String?, progressBar: ProgressBar?) { - if (imageUrl != null && imageUrl.isNotEmpty()) { + if (!imageUrl.isNullOrEmpty()) { val request = ImageRequest.Builder(context) .data(imageUrl) .crossfade(true) @@ -191,7 +186,7 @@ fun ImageView.loadRoundImage(imageUrl: String?, progressBar: ProgressBar?) { setImageDrawable(result) } ) - .listener(onError = { request: ImageRequest, _: Throwable -> + .listener(onError = { request, _ -> progressBar?.hide() setImageDrawable(request.error) }) @@ -212,7 +207,6 @@ fun ImageView.loadRoundImage(imageUrl: String?, progressBar: ProgressBar?) { } } -@BindingAdapter("load_drawable") fun loadDrawable(imageView: ImageView, drawable: Drawable?) { imageView.setImageDrawable(drawable) } \ No newline at end of file diff --git a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/home/HomeActivity.kt b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/home/HomeActivity.kt index 9a42c75..6188d2a 100644 --- a/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/home/HomeActivity.kt +++ b/presentation/src/main/java/com/mina_mikhail/base_mvvm/presentation/home/HomeActivity.kt @@ -6,9 +6,12 @@ import android.content.Intent import android.content.IntentFilter import androidx.annotation.IdRes import androidx.localbroadcastmanager.content.LocalBroadcastManager +import androidx.navigation.findNavController +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.NavigationUI.setupWithNavController +import androidx.navigation.ui.setupWithNavController import com.mina_mikhail.base_mvvm.presentation.R import com.mina_mikhail.base_mvvm.presentation.base.BaseActivity -import com.mina_mikhail.base_mvvm.presentation.base.extensions.setupWithNavController import com.mina_mikhail.base_mvvm.presentation.databinding.ActivityHomeBinding import dagger.hilt.android.AndroidEntryPoint @@ -23,17 +26,20 @@ class HomeActivity : BaseActivity() { private var isReceiverRegistered = false private val openSpecificTabReceiver: BroadcastReceiver = object : BroadcastReceiver() { - override - fun onReceive(context: Context, intent: Intent) { + + override fun onReceive(context: Context, intent: Intent) { navigateToSpecificTab(intent.getIntExtra(TAB_ID, 0)) } } - override - fun getLayoutId() = R.layout.activity_home + override fun getLayoutId() = R.layout.activity_home + + override fun setUpViews() { + setUpNavController() + setupBottomNavigation() + } - override - fun onResume() { + override fun onResume() { super.onResume() registerOpenSpecificTabReceiver() @@ -50,40 +56,35 @@ class HomeActivity : BaseActivity() { } } - override - fun setUpBottomNavigation() { - setUpBottomNavigationWithGraphs() + + private fun navigateToSpecificTab(@IdRes tabID: Int) { + binding.bottomNavigationView.selectedItemId = tabID } - private fun setUpBottomNavigationWithGraphs() { - val graphIds = listOf( - R.navigation.nav_home, - R.navigation.nav_search, - R.navigation.nav_account - ) - - val controller = binding.bottomNavigationView.setupWithNavController( - graphIds, - supportFragmentManager, - R.id.fragment_host_container, - intent - ) - - navController = controller + private fun setUpNavController() { + val navHostFragment = supportFragmentManager.findFragmentById( + R.id.fragment_host_container + ) as NavHostFragment + navController = navHostFragment.navController } - private fun navigateToSpecificTab(@IdRes tabID: Int) { - binding.bottomNavigationView.selectedItemId = tabID + private fun setupBottomNavigation() { + navController.let { + binding.bottomNavigationView.apply { + inflateMenu(R.menu.menu_bottom_navigation) + setupWithNavController(it) + } + } } - override - fun onDestroy() { + override fun onDestroy() { unregisterOpenSpecificTabReceiver() super.onDestroy() } private fun unregisterOpenSpecificTabReceiver() { - LocalBroadcastManager.getInstance(this).unregisterReceiver(openSpecificTabReceiver) + LocalBroadcastManager.getInstance(this) + .unregisterReceiver(openSpecificTabReceiver) } } \ No newline at end of file diff --git a/presentation/src/main/res/layout/activity_home.xml b/presentation/src/main/res/layout/activity_home.xml index 417d925..838b432 100644 --- a/presentation/src/main/res/layout/activity_home.xml +++ b/presentation/src/main/res/layout/activity_home.xml @@ -12,12 +12,13 @@ > + android:id="@+id/fragment_host_container" + android:name="androidx.navigation.fragment.NavHostFragment" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + app:defaultNavHost="true" + app:navGraph="@navigation/nav_main" /> + android:orientation="vertical" > @@ -56,7 +53,6 @@ android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" - app:goneUnless="@{baseViewModel.dataLoadingEvent == DataStatus.NO_INTERNET}" tools:ignore="UseCompoundDrawables" > @@ -86,7 +82,6 @@ android:layout_height="@dimen/dimen70" android:layout_gravity="center" app:SpinKit_Color="@color/colorPrimary" - app:goneUnless="@{baseViewModel.dataLoadingEvent == DataStatus.LOADING}" /> diff --git a/presentation/src/main/res/layout/list_general.xml b/presentation/src/main/res/layout/list_general.xml index 9ba05a1..2e8f7b3 100644 --- a/presentation/src/main/res/layout/list_general.xml +++ b/presentation/src/main/res/layout/list_general.xml @@ -27,7 +27,6 @@ android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" - app:goneUnless="@{baseViewModel.dataLoadingEvent == DataStatus.NO_DATA}" tools:ignore="UseCompoundDrawables" > @@ -55,7 +54,6 @@ android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" - app:goneUnless="@{baseViewModel.dataLoadingEvent == DataStatus.NO_INTERNET}" tools:ignore="UseCompoundDrawables" > @@ -85,7 +83,6 @@ android:layout_height="@dimen/dimen70" android:layout_gravity="center" app:SpinKit_Color="@color/colorPrimary" - app:goneUnless="@{baseViewModel.dataLoadingEvent == DataStatus.LOADING}" /> diff --git a/presentation/src/main/res/navigation/nav_main.xml b/presentation/src/main/res/navigation/nav_main.xml new file mode 100644 index 0000000..df3c0d2 --- /dev/null +++ b/presentation/src/main/res/navigation/nav_main.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/prettyPopUp/build.gradle b/prettyPopUp/build.gradle deleted file mode 100644 index dc23dbf..0000000 --- a/prettyPopUp/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -plugins { - id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' -} - -android { - compileSdk 30 - - defaultConfig { - minSdk 21 - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - viewBinding { - enabled true - } -} - -dependencies { - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03" - implementation "com.google.android.material:material:1.4.0" -} \ No newline at end of file diff --git a/prettyPopUp/build.gradle.kts b/prettyPopUp/build.gradle.kts new file mode 100644 index 0000000..0d152c6 --- /dev/null +++ b/prettyPopUp/build.gradle.kts @@ -0,0 +1,40 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.android.kotlin) + alias(libs.plugins.kotlin.ksp) +} + +android { + namespace = "codes.mina_mikhail.pretty_pop_up" + compileSdk = 34 + + defaultConfig { + + minSdk = 21 + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + buildFeatures { + viewBinding = true + } +} + +dependencies { + implementation(libs.lifecycle) + implementation(libs.materialDesign) +} \ No newline at end of file diff --git a/prettyPopUp/proguard-rules.pro b/prettyPopUp/proguard-rules.pro index 481bb43..ff59496 100644 --- a/prettyPopUp/proguard-rules.pro +++ b/prettyPopUp/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/prettyPopUp/src/main/AndroidManifest.xml b/prettyPopUp/src/main/AndroidManifest.xml index 4c5cbf1..568741e 100644 --- a/prettyPopUp/src/main/AndroidManifest.xml +++ b/prettyPopUp/src/main/AndroidManifest.xml @@ -1,6 +1,2 @@ - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 5b23d5c..288ba13 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,16 +1,34 @@ -rootProject.name = "Kotlin-Base-MVVM" +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + maven(url = "https://jitpack.io") + } +} -// Include all the existent modules in the project -rootDir - .walk() - .maxDepth(1) - .filter { - it.name != rootProject.name && - ( - it.name != "buildSrc" && it.isDirectory && file("${it.absolutePath}/build.gradle.kts").exists() || - it.name != "buildSrc" && it.isDirectory && file("${it.absolutePath}/build.gradle").exists() - ) +@Suppress("UnstableApiUsage") +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") } - .forEach { - include(":${it.name}") - } \ No newline at end of file +} + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +rootProject.name = "Kotlin-Base-MVVM" +include(":app") + +// Modules +include(":domain",":data",":presentation",":prettyPopUp", + ":actionChooser",":appTutorial",":imagesSlider" + ) \ No newline at end of file From c6006b8f28d7144e19fed8da7540ec4507550a81 Mon Sep 17 00:00:00 2001 From: Emad Askar Date: Sat, 15 Jun 2024 21:43:32 +0300 Subject: [PATCH 2/2] + Update to gradle plugin 8.5 --- gradle/libs.versions.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e0e9b8b..f48153f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,12 +1,12 @@ [versions] -gradleVersion = "8.4.1" +gradleVersion = "8.5.0" kotlin = "2.0.0" -ktLint = "10.2.0" +ktLint = "11.5.1" javaInject = "1" appcompat = "1.7.0" coreKtx = "1.13.1" supportVersion = "1.0.0" -lifecycle = "2.8.1" +lifecycle = "2.8.2" kotlinCoroutines = "1.7.3" retrofit = "2.9.0" gson = "2.10.1"