From 6da30e8963fb1539d0ee3a6966cb4b70f2d125a9 Mon Sep 17 00:00:00 2001 From: Ruthvik B R Date: Wed, 23 Nov 2022 10:32:56 +0530 Subject: [PATCH 1/4] feat: add dynamic module --- app/build.gradle.kts | 2 ++ app/src/main/AndroidManifest.xml | 6 ----- .../java/com/mutualmobile/praxis/PraxisApp.kt | 4 +-- .../praxis/root/BaseSplitActivity.kt | 12 +++++++++ .../praxis/root/OnboardingActivity.kt | 2 ++ app/src/main/res/values/strings.xml | 1 + build.gradle.kts | 1 - buildSrc/src/main/kotlin/AppVersions.kt | 2 +- buildSrc/src/main/kotlin/Dependencies.kt | 4 +-- .../praxis/commonui/reusable/SlackListItem.kt | 1 - gradle/wrapper/gradle-wrapper.properties | 2 +- .../praxis/navigator/Navigator.kt | 3 --- sample/.gitignore | 1 + sample/build.gradle.kts | 25 +++++++++++++++++ .../praxis/ExampleInstrumentedTest.kt | 24 +++++++++++++++++ sample/src/main/AndroidManifest.xml | 27 +++++++++++++++++++ .../praxis/sample/SampleActivity.kt | 12 +++++++++ .../src/main/res/layout/activity_sample.xml | 9 +++++++ .../mutualmobile/praxis/ExampleUnitTest.kt | 17 ++++++++++++ settings.gradle.kts | 1 + 20 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/com/mutualmobile/praxis/root/BaseSplitActivity.kt create mode 100644 sample/.gitignore create mode 100644 sample/build.gradle.kts create mode 100644 sample/src/androidTest/java/com/mutualmobile/praxis/ExampleInstrumentedTest.kt create mode 100644 sample/src/main/AndroidManifest.xml create mode 100644 sample/src/main/java/com/mutualmobile/praxis/sample/SampleActivity.kt create mode 100644 sample/src/main/res/layout/activity_sample.xml create mode 100644 sample/src/test/java/com/mutualmobile/praxis/ExampleUnitTest.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5f8997ff..5b18f33b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -100,6 +100,7 @@ android { kotlinOptions { jvmTarget = "1.8" } + dynamicFeatures += setOf(":sample") } // Required for annotation processing plugins like Dagger @@ -149,6 +150,7 @@ dependencies { // Room api(Lib.Room.roomKtx) api(Lib.Room.roomRuntime) + api("com.google.android.play:core:1.10.3") add("kapt", Lib.Room.roomCompiler) testApi(Lib.Room.testing) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8aae06ce..d0f8d1db 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,12 +24,6 @@ - - \ No newline at end of file diff --git a/app/src/main/java/com/mutualmobile/praxis/PraxisApp.kt b/app/src/main/java/com/mutualmobile/praxis/PraxisApp.kt index 8c56e012..f8452cf4 100644 --- a/app/src/main/java/com/mutualmobile/praxis/PraxisApp.kt +++ b/app/src/main/java/com/mutualmobile/praxis/PraxisApp.kt @@ -1,11 +1,11 @@ package com.mutualmobile.praxis -import android.app.Application +import com.google.android.play.core.splitcompat.SplitCompatApplication import dagger.hilt.android.HiltAndroidApp import timber.log.Timber @HiltAndroidApp -class PraxisCloneApp : Application() { +class PraxisCloneApp : SplitCompatApplication() { override fun onCreate() { super.onCreate() diff --git a/app/src/main/java/com/mutualmobile/praxis/root/BaseSplitActivity.kt b/app/src/main/java/com/mutualmobile/praxis/root/BaseSplitActivity.kt new file mode 100644 index 00000000..e9f5aab1 --- /dev/null +++ b/app/src/main/java/com/mutualmobile/praxis/root/BaseSplitActivity.kt @@ -0,0 +1,12 @@ +package com.mutualmobile.praxis.root + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.google.android.play.core.splitcompat.SplitCompat + +abstract class BaseSplitActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + SplitCompat.installActivity(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mutualmobile/praxis/root/OnboardingActivity.kt b/app/src/main/java/com/mutualmobile/praxis/root/OnboardingActivity.kt index 243107ab..9f3b59db 100644 --- a/app/src/main/java/com/mutualmobile/praxis/root/OnboardingActivity.kt +++ b/app/src/main/java/com/mutualmobile/praxis/root/OnboardingActivity.kt @@ -3,6 +3,7 @@ package com.mutualmobile.praxis.root import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.app.AppCompatDelegate import androidx.compose.runtime.LaunchedEffect import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.WindowCompat @@ -24,6 +25,7 @@ class OnboardingActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); WindowCompat.setDecorFitsSystemWindows(window, false) installSplashScreen() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 50eb0b8d..6a2a8545 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,4 +6,5 @@ Downloading %d bytes No network available! Some error occurred + Sample \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 7dd80b6e..638b2de9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,6 @@ buildscript { classpath(BuildPlugins.KOTLIN_GRADLE_PLUGIN) classpath(kotlin("serialization", version = Lib.Kotlin.KOTLIN_VERSION)) classpath(BuildPlugins.KTLINT_GRADLE_PLUGIN) - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/buildSrc/src/main/kotlin/AppVersions.kt b/buildSrc/src/main/kotlin/AppVersions.kt index 60b5dae6..955cc8d7 100644 --- a/buildSrc/src/main/kotlin/AppVersions.kt +++ b/buildSrc/src/main/kotlin/AppVersions.kt @@ -7,7 +7,7 @@ object AppVersions { const val versionName = "$versionMajor.$versionMinor.$versionPatch" const val COMPILE_SDK = 31 - const val MIN_SDK = 21 + const val MIN_SDK = 24 const val TARGET_SDK = 31 const val APPLICATION_ID = "com.mutualmobile.praxis" } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 81a3a66c..02133943 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -26,7 +26,7 @@ object Lib { const val KOTLIN_VERSION = "1.6.0" private const val KTX_CORE_VERSION = "1.2.0" const val KT_STD = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${KOTLIN_VERSION}" - private const val KTX_CORE = "androidx.core:core-ktx:${KTX_CORE_VERSION}" + const val KTX_CORE = "androidx.core:core-ktx:${KTX_CORE_VERSION}" private const val DATE_TIME = "org.jetbrains.kotlinx:kotlinx-datetime:0.3.2" const val COROUTINES = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${KOTLIN_VERSION}" @@ -49,7 +49,7 @@ object Lib { // Compose const val composeVersion = "1.1.0" private const val SPLASH_SCREEN_API = "androidx.core:core-splashscreen:1.0.0-beta01" - private const val APP_COMPAT = "androidx.appcompat:appcompat:1.3.0-beta01" + const val APP_COMPAT = "androidx.appcompat:appcompat:1.4.2" val list = listOf( APP_COMPAT, diff --git a/commonui/src/main/java/com/mutualmobile/praxis/commonui/reusable/SlackListItem.kt b/commonui/src/main/java/com/mutualmobile/praxis/commonui/reusable/SlackListItem.kt index 285e8685..f064997b 100644 --- a/commonui/src/main/java/com/mutualmobile/praxis/commonui/reusable/SlackListItem.kt +++ b/commonui/src/main/java/com/mutualmobile/praxis/commonui/reusable/SlackListItem.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.unit.dp import com.mutualmobile.praxis.commonui.theme.PraxisColorProvider import com.mutualmobile.praxis.commonui.theme.PraxisTypography -@OptIn(ExperimentalMaterialApi::class) @Composable fun PraxisListItem( icon: ImageVector, diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d8cebfcc..90c1a4d7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Jan 27 08:55:19 IST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/navigator/src/main/java/com/mutualmobile/praxis/navigator/Navigator.kt b/navigator/src/main/java/com/mutualmobile/praxis/navigator/Navigator.kt index 4c4d7fbe..9e636864 100644 --- a/navigator/src/main/java/com/mutualmobile/praxis/navigator/Navigator.kt +++ b/navigator/src/main/java/com/mutualmobile/praxis/navigator/Navigator.kt @@ -49,9 +49,6 @@ abstract class ComposeNavigator : Navigator() { is ComposeNavigationCommand.NavigateUpWithResult<*> -> { navUpWithResult(navigationCommand) } - else -> { - throw RuntimeException("can't handle this with ComposeNavigator") - } } } diff --git a/sample/.gitignore b/sample/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/sample/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts new file mode 100644 index 00000000..a014eb03 --- /dev/null +++ b/sample/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + id("com.android.dynamic-feature") + id("org.jetbrains.kotlin.android") +} +android { + namespace = "com.mutualmobile.praxis.sample" + compileSdk = (AppVersions.COMPILE_SDK) + + defaultConfig { + minSdk = (AppVersions.MIN_SDK) + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables.useSupportLibrary = true + } +} + +dependencies { + implementation(project(":app")) + implementation(Lib.Kotlin.KTX_CORE) + implementation("com.google.android.material:material:1.4.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.4") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0") + androidTestImplementation("androidx.annotation:annotation:1.5.0") +} \ No newline at end of file diff --git a/sample/src/androidTest/java/com/mutualmobile/praxis/ExampleInstrumentedTest.kt b/sample/src/androidTest/java/com/mutualmobile/praxis/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..c309e2b1 --- /dev/null +++ b/sample/src/androidTest/java/com/mutualmobile/praxis/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.mutualmobile.praxis + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.mutualmobile.praxis", appContext.packageName) + } +} \ No newline at end of file diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml new file mode 100644 index 00000000..8d75da7f --- /dev/null +++ b/sample/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/java/com/mutualmobile/praxis/sample/SampleActivity.kt b/sample/src/main/java/com/mutualmobile/praxis/sample/SampleActivity.kt new file mode 100644 index 00000000..3c399f82 --- /dev/null +++ b/sample/src/main/java/com/mutualmobile/praxis/sample/SampleActivity.kt @@ -0,0 +1,12 @@ +package com.mutualmobile.praxis.sample + +import android.os.Bundle +import com.mutualmobile.praxis.root.BaseSplitActivity + +class SampleActivity : BaseSplitActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_sample) + } +} \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_sample.xml b/sample/src/main/res/layout/activity_sample.xml new file mode 100644 index 00000000..9e8913fc --- /dev/null +++ b/sample/src/main/res/layout/activity_sample.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/sample/src/test/java/com/mutualmobile/praxis/ExampleUnitTest.kt b/sample/src/test/java/com/mutualmobile/praxis/ExampleUnitTest.kt new file mode 100644 index 00000000..66640761 --- /dev/null +++ b/sample/src/test/java/com/mutualmobile/praxis/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.mutualmobile.praxis + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 56f746d1..77bc913c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,3 +12,4 @@ include(":common") include(":commonui") include(":navigator") +include(":sample") From af7a4c328e34f82e74718b5a9eaefbeb36870908 Mon Sep 17 00:00:00 2001 From: Ruthvikbr-MM Date: Thu, 24 Nov 2022 15:47:57 +0530 Subject: [PATCH 2/4] feat : Update to AGP 8.0 --- app/build.gradle.kts | 2 +- app/proguard-common.txt | 1 + app/proguard-rules.pro | 2 +- app/src/main/AndroidManifest.xml | 3 +-- build.gradle.kts | 1 + buildSrc/src/main/kotlin/AppVersions.kt | 4 ++-- buildSrc/src/main/kotlin/Dependencies.kt | 6 +++--- common/build.gradle.kts | 2 +- commonui/build.gradle.kts | 2 +- data/build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 6 +++--- navigator/build.gradle.kts | 2 +- ui-authentication/build.gradle.kts | 2 +- .../com/praxis/feat/authentication/ui/AuthenticationUI.kt | 6 +++--- .../com/praxis/feat/authentication/ui/ForgotPasswordUI.kt | 4 ++-- ui-onboarding/build.gradle.kts | 2 +- 16 files changed, 24 insertions(+), 23 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5b18f33b..30b25bb3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,7 +13,7 @@ plugins { android { compileSdk = (AppVersions.COMPILE_SDK) - + namespace = "com.mutualmobile.praxis" defaultConfig { applicationId = (AppVersions.APPLICATION_ID) minSdk = (AppVersions.MIN_SDK) diff --git a/app/proguard-common.txt b/app/proguard-common.txt index be2acee9..0cfcd9a0 100644 --- a/app/proguard-common.txt +++ b/app/proguard-common.txt @@ -25,6 +25,7 @@ -dontwarn android.webkit.WebView -dontwarn android.net.http.SslError -dontwarn android.webkit.WebViewClient +-dontwarn org.slf4j.impl.StaticLoggerBinder #This will print mappings - very useful for troubleshooting. -dump ./build/class_files.txt diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index fd73052e..c636725c 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -14,4 +14,4 @@ # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; -#} +#} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d0f8d1db..d1ad842f 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/build.gradle.kts b/build.gradle.kts index 638b2de9..a7fbd296 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,6 +12,7 @@ buildscript { classpath(BuildPlugins.KOTLIN_GRADLE_PLUGIN) classpath(kotlin("serialization", version = Lib.Kotlin.KOTLIN_VERSION)) classpath(BuildPlugins.KTLINT_GRADLE_PLUGIN) + classpath("com.android.tools.build:gradle:8.0.0-alpha08") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/buildSrc/src/main/kotlin/AppVersions.kt b/buildSrc/src/main/kotlin/AppVersions.kt index 955cc8d7..f4e62d66 100644 --- a/buildSrc/src/main/kotlin/AppVersions.kt +++ b/buildSrc/src/main/kotlin/AppVersions.kt @@ -6,8 +6,8 @@ object AppVersions { const val versionCode = versionMajor * 10000 + versionMinor * 100 + versionPatch const val versionName = "$versionMajor.$versionMinor.$versionPatch" - const val COMPILE_SDK = 31 + const val COMPILE_SDK = 32 const val MIN_SDK = 24 - const val TARGET_SDK = 31 + const val TARGET_SDK = 32 const val APPLICATION_ID = "com.mutualmobile.praxis" } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 02133943..a11a8729 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -3,7 +3,7 @@ object BuildPlugins { private const val TOOLS_BUILD = "7.1.1" private const val KT_LINT = "9.2.1" - private const val SAFE_ARGS = "2.3.5" + private const val SAFE_ARGS = "2.5.0" const val TOOLS_BUILD_GRADLE = "com.android.tools.build:gradle:${TOOLS_BUILD}" const val KTLINT_GRADLE_PLUGIN = "org.jlleitschuh.gradle:ktlint-gradle:${KT_LINT}" @@ -47,9 +47,9 @@ object Lib { object Androidx { // Compose - const val composeVersion = "1.1.0" + const val composeVersion = "1.2.0-rc02" private const val SPLASH_SCREEN_API = "androidx.core:core-splashscreen:1.0.0-beta01" - const val APP_COMPAT = "androidx.appcompat:appcompat:1.4.2" + const val APP_COMPAT = "androidx.appcompat:appcompat:1.4.1" val list = listOf( APP_COMPAT, diff --git a/common/build.gradle.kts b/common/build.gradle.kts index e9bdb2fd..949f788f 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -9,7 +9,7 @@ plugins { android { compileSdk = AppVersions.COMPILE_SDK - + namespace = "com.mutualmobile.praxis.common" defaultConfig { minSdk = (AppVersions.MIN_SDK) targetSdk = (AppVersions.TARGET_SDK) diff --git a/commonui/build.gradle.kts b/commonui/build.gradle.kts index 73940cf7..2bf116f1 100644 --- a/commonui/build.gradle.kts +++ b/commonui/build.gradle.kts @@ -9,7 +9,7 @@ plugins { android { compileSdk = AppVersions.COMPILE_SDK - + namespace = "com.mutualmobile.praxis.commonui" defaultConfig { minSdk = (AppVersions.MIN_SDK) targetSdk = (AppVersions.TARGET_SDK) diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 00e49bff..6a8a902a 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -7,7 +7,7 @@ plugins { android { compileSdk = AppVersions.COMPILE_SDK - + namespace = "com.mutualmobile.praxis.data" defaultConfig { minSdk = (AppVersions.MIN_SDK) targetSdk = (AppVersions.TARGET_SDK) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 90c1a4d7..8c2d6162 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Jan 27 08:55:19 IST 2022 +#Thu Nov 24 14:31:41 IST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/navigator/build.gradle.kts b/navigator/build.gradle.kts index fe83c7e6..f97848d9 100644 --- a/navigator/build.gradle.kts +++ b/navigator/build.gradle.kts @@ -6,7 +6,7 @@ plugins { android { compileSdk = AppVersions.COMPILE_SDK - + namespace = "com.mutualmobile.praxis.navigator" defaultConfig { minSdk = (AppVersions.MIN_SDK) targetSdk = (AppVersions.TARGET_SDK) diff --git a/ui-authentication/build.gradle.kts b/ui-authentication/build.gradle.kts index f976ad7b..f5583aab 100644 --- a/ui-authentication/build.gradle.kts +++ b/ui-authentication/build.gradle.kts @@ -9,7 +9,7 @@ plugins { android { compileSdk = AppVersions.COMPILE_SDK - + namespace = "com.praxis.feat.authentication" defaultConfig { minSdk = (AppVersions.MIN_SDK) targetSdk = (AppVersions.TARGET_SDK) diff --git a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt index 7449c1e5..75c3ea1c 100644 --- a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt +++ b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt @@ -145,7 +145,7 @@ private fun AuthSurface( AnimatedVisibility(visible = randomPhotoState !is AuthVM.UiState.Streaming) { Image( - painter = painterResource(id = R.mipmap.ic_launcher), + painter = painterResource(id = com.mutualmobile.praxis.commonui.R.mipmap.ic_launcher), contentDescription = "Logo", Modifier.size(128.dp) ) } @@ -276,7 +276,7 @@ private fun PasswordTF(authVM: AuthVM, focusRequester: FocusRequester) { keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), leadingIcon = { Image( - painter = painterResource(id = R.drawable.ic_eye), + painter = painterResource(id = com.mutualmobile.praxis.commonui.R.drawable.ic_eye), contentDescription = "email" ) }, @@ -316,7 +316,7 @@ private fun EmailTF(authVM: AuthVM, focusRequester: FocusRequester) { ), leadingIcon = { Image( - painter = painterResource(id = R.drawable.ic_email), + painter = painterResource(id = com.mutualmobile.praxis.commonui.R.drawable.ic_email), contentDescription = "Email" ) }, diff --git a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/ForgotPasswordUI.kt b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/ForgotPasswordUI.kt index b444c5d3..13949423 100644 --- a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/ForgotPasswordUI.kt +++ b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/ForgotPasswordUI.kt @@ -63,7 +63,7 @@ private fun ForgotPasswordSurface(forgotPasswordVM: ForgotPasswordVM) { horizontalAlignment = Alignment.CenterHorizontally ) { Image( - painter = painterResource(id = R.mipmap.ic_launcher), + painter = painterResource(id = com.mutualmobile.praxis.commonui.R.mipmap.ic_launcher), contentDescription = "Logo", Modifier.size(128.dp) ) @@ -107,7 +107,7 @@ private fun EmailTF(forgotPasswordVM: ForgotPasswordVM) { shape = PraxisShapes.large, leadingIcon = { Image( - painter = painterResource(id = R.drawable.ic_email), + painter = painterResource(id = com.mutualmobile.praxis.commonui.R.drawable.ic_email), contentDescription = "Email" ) }, diff --git a/ui-onboarding/build.gradle.kts b/ui-onboarding/build.gradle.kts index ced77d9d..e35ca294 100644 --- a/ui-onboarding/build.gradle.kts +++ b/ui-onboarding/build.gradle.kts @@ -9,7 +9,7 @@ plugins { android { compileSdk = AppVersions.COMPILE_SDK - + namespace = "com.mutualmobile.praxis.uionboarding" defaultConfig { minSdk = (AppVersions.MIN_SDK) targetSdk = (AppVersions.TARGET_SDK) From 3b851955f4d94afe9db5e69233e427beaee8e147 Mon Sep 17 00:00:00 2001 From: Ruthvikbr-MM Date: Fri, 25 Nov 2022 13:34:49 +0530 Subject: [PATCH 3/4] feat : Add downloading capabilities --- app/build.gradle.kts | 1 - buildSrc/src/main/kotlin/Dependencies.kt | 3 +- ui-authentication/build.gradle.kts | 2 - .../authentication/ui/AuthenticationUI.kt | 79 ++++++++++++++----- .../praxis/feat/authentication/vm/AuthVM.kt | 60 +++++++++++++- 5 files changed, 120 insertions(+), 25 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 30b25bb3..3477800c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -150,7 +150,6 @@ dependencies { // Room api(Lib.Room.roomKtx) api(Lib.Room.roomRuntime) - api("com.google.android.play:core:1.10.3") add("kapt", Lib.Room.roomCompiler) testApi(Lib.Room.testing) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index a11a8729..46a82365 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -38,9 +38,10 @@ object Lib { object Google { const val MATERIAL_DESIGN = "com.google.android.material:material:1.4.0" - + const val PLAY_FEATURE_DELIVERY = "com.google.android.play:feature-delivery-ktx:2.0.1" val list = listOf( MATERIAL_DESIGN, + PLAY_FEATURE_DELIVERY ) } diff --git a/ui-authentication/build.gradle.kts b/ui-authentication/build.gradle.kts index f5583aab..33de9757 100644 --- a/ui-authentication/build.gradle.kts +++ b/ui-authentication/build.gradle.kts @@ -62,8 +62,6 @@ dependencies { implementation(project(":navigator")) implementation(project(":commonui")) - - Lib.Androidx.list.forEach(::implementation) Lib.Androidx.Compose.list.forEach(::implementation) Lib.ThirdParty.list.forEach(::implementation) diff --git a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt index 75c3ea1c..716de28f 100644 --- a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt +++ b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt @@ -1,5 +1,7 @@ package com.praxis.feat.authentication.ui +import android.content.Context +import android.content.Intent import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -16,6 +18,7 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.SpanStyle @@ -27,15 +30,20 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.core.content.ContextCompat.startActivity import androidx.hilt.navigation.compose.hiltViewModel import coil.compose.rememberImagePainter import com.google.accompanist.insets.navigationBarsPadding import com.google.accompanist.insets.navigationBarsWithImePadding import com.google.accompanist.insets.statusBarsPadding +import com.google.android.play.core.splitinstall.SplitInstallManager +import com.google.android.play.core.splitinstall.SplitInstallManagerFactory +import com.google.android.play.core.splitinstall.SplitInstallRequest +import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener +import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus import com.mutualmobile.praxis.commonui.material.DefaultSnackbar import com.mutualmobile.praxis.commonui.material.PraxisSurfaceAppBar import com.mutualmobile.praxis.commonui.theme.* -import com.praxis.feat.authentication.R import com.praxis.feat.authentication.vm.AuthVM import com.praxis.feat.authentication.vm.streamProgress import com.praxis.feat.authentication.vm.uri @@ -50,8 +58,8 @@ fun AuthenticationUI( backgroundColor = PraxisColorProvider.colors.uiBackground, contentColor = PraxisColorProvider.colors.textSecondary, modifier = Modifier - .statusBarsPadding() - .navigationBarsPadding(), + .statusBarsPadding() + .navigationBarsPadding(), topBar = { PraxisSurfaceAppBar( title = { @@ -91,16 +99,17 @@ private fun AuthSurface( ) { PraxisSurface( modifier = Modifier - .fillMaxHeight() - .fillMaxWidth() + .fillMaxHeight() + .fillMaxWidth() ) { val resetPasswordState by authVM.snackBarState.collectAsState() val uiState by authVM.formUiState.collectAsState() val randomPhotoState by authVM.randomPhotoState.collectAsState() + val dynamicFeatureUiState by authVM.dynamicUiState.collectAsState() Box() { - AnimatedVisibility(visible = uiState is AuthVM.UiState.SuccessState || randomPhotoState is AuthVM.UiState.Streaming) { + AnimatedVisibility(visible = uiState is AuthVM.UiState.SuccessState || randomPhotoState is AuthVM.UiState.Streaming ) { Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally @@ -123,7 +132,7 @@ private fun AuthSurface( ) RandomPhotoButton(authVM) - + LoadDynamicFeature(authVM) LogoutButton(authVM) } } @@ -132,11 +141,11 @@ private fun AuthSurface( } } Column( - Modifier - .padding(16.dp) - .navigationBarsWithImePadding() - .fillMaxWidth() - .fillMaxHeight(), + Modifier + .padding(16.dp) + .navigationBarsWithImePadding() + .fillMaxWidth() + .fillMaxHeight(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { @@ -162,6 +171,10 @@ private fun AuthSurface( CircularProgressIndicator(modifier = Modifier.padding(8.dp)) } + AnimatedVisibility(visible = (dynamicFeatureUiState is AuthVM.UiState.LoadingState)) { + CircularProgressIndicator(modifier = Modifier.padding(8.dp)) + } + AnimatedVisibility(visible = uiState is AuthVM.UiState.Empty) { LoginButton(authVM = authVM) } @@ -178,6 +191,10 @@ private fun AuthSurface( ) } } + + if(dynamicFeatureUiState is AuthVM.UiState.LaunchDynamicModule) { + launchDynamicModule(LocalContext.current) + } } } @@ -200,6 +217,21 @@ fun RandomPhotoButton(authVM: AuthVM) { } } +@Composable +fun LoadDynamicFeature(authVM: AuthVM) { + Button( + onClick = { + authVM.checkDynamicFeatureInstallation("Sample") + }, Modifier.wrapContentWidth(), + colors = ButtonDefaults.buttonColors(backgroundColor = PraxisColorProvider.colors.buttonColor) + ) { + Text( + text = "Load Dynamic Module", + style = MaterialTheme.typography.body1.copy(color = PraxisColorProvider.colors.buttonTextColor) + ) + } +} + @Composable fun LogoutButton(authVM: AuthVM) { Button( @@ -261,9 +293,9 @@ private fun PasswordTF(authVM: AuthVM, focusRequester: FocusRequester) { authVM.credentials.value = credentials.copy(password = it) }, modifier = Modifier - .padding(16.dp) - .focusRequester(focusRequester) - .fillMaxWidth(), + .padding(16.dp) + .focusRequester(focusRequester) + .fillMaxWidth(), label = { Text( text = "Password", @@ -297,9 +329,9 @@ private fun EmailTF(authVM: AuthVM, focusRequester: FocusRequester) { onValueChange = { authVM.credentials.value = credentials.copy(email = it) }, - Modifier - .padding(16.dp) - .fillMaxWidth(), label = { + Modifier + .padding(16.dp) + .fillMaxWidth(), label = { Text( text = "Email", style = MaterialTheme.typography.body2.copy(color = PraxisColorProvider.colors.textPrimary) @@ -340,4 +372,13 @@ fun PreviewAuth() { PraxisTheme(isDarkTheme = true) { AuthenticationUI() } -} \ No newline at end of file +} +private fun launchDynamicModule(context: Context){ + val packageName = "com.mutualmobile.praxis.sample" + val kotlinSampleClassname = "$packageName.SampleActivity" + Intent().setClassName(packageName, kotlinSampleClassname) + .also { + startActivity(context, it, null) + } +} + diff --git a/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt b/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt index ecb1eaf1..5d0d96b6 100644 --- a/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt +++ b/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt @@ -1,7 +1,14 @@ package com.praxis.feat.authentication.vm +import android.content.Context import android.net.Uri import androidx.lifecycle.* +import androidx.lifecycle.viewmodel.compose.viewModel +import com.google.android.play.core.splitinstall.SplitInstallManager +import com.google.android.play.core.splitinstall.SplitInstallManagerFactory +import com.google.android.play.core.splitinstall.SplitInstallRequest +import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener +import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus import com.mutualmobile.praxis.domain.model.StreamingFile import com.mutualmobile.praxis.domain.usecases.FetchRandomPhotoUseCase import com.mutualmobile.praxis.navigator.ComposeNavigator @@ -10,6 +17,7 @@ import com.mutualmobile.praxis.navigator.PraxisScreen import com.praxis.feat.authentication.ui.exceptions.FormValidationFailed import com.praxis.feat.authentication.ui.model.LoginForm import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import java.io.FileNotFoundException @@ -20,11 +28,11 @@ import javax.inject.Inject class AuthVM @Inject constructor( private val savedStateHandle: SavedStateHandle, private val composeNavigator: ComposeNavigator, - private val fetchPhotoUseCase: FetchRandomPhotoUseCase + private val fetchPhotoUseCase: FetchRandomPhotoUseCase, + @ApplicationContext val context: Context ) : ViewModel() { private var fetchJob: Job? = null - var credentials = MutableStateFlow(LoginForm()) private set var snackBarState = MutableStateFlow("") @@ -34,6 +42,14 @@ class AuthVM @Inject constructor( var randomPhotoState = MutableStateFlow(UiState.Empty) private set + var dynamicUiState = MutableStateFlow(UiState.Empty) + private set + + var dynamicFeatureNameState = MutableStateFlow("") + private set + + private lateinit var manager: SplitInstallManager + private val exceptionHandler = CoroutineExceptionHandler { _, throwable -> when (throwable) { is FormValidationFailed -> { @@ -63,6 +79,7 @@ class AuthVM @Inject constructor( init { observePasswordReset() + manager = SplitInstallManagerFactory.create(context) } private fun observePasswordReset() { @@ -91,6 +108,43 @@ class AuthVM @Inject constructor( composeNavigator.navigate(PraxisScreen.ForgotPassword.route) } + fun checkDynamicFeatureInstallation(moduleName: String) { + if (manager.installedModules.contains(moduleName)) { + viewModelScope.launch { + dynamicUiState.value = UiState.LaunchDynamicModule(moduleName) + dynamicFeatureNameState.value = moduleName + } + } else { + installDynamicModule(moduleName) + } + } + private fun installDynamicModule(moduleName: String) { + val request: SplitInstallRequest = SplitInstallRequest.newBuilder() + .addModule(moduleName) + .build() + manager.startInstall(request) + } + + private val listener = SplitInstallStateUpdatedListener { state -> + when (state.status()) { + SplitInstallSessionStatus.INSTALLING -> { + dynamicUiState.value = UiState.LoadingState + } + + SplitInstallSessionStatus.INSTALLED -> { + dynamicUiState.value = UiState.LaunchDynamicModule(dynamicFeatureNameState.value) + } + + SplitInstallSessionStatus.DOWNLOADING -> { + dynamicUiState.value = UiState.LoadingState + } + + SplitInstallSessionStatus.FAILED -> { + dynamicUiState.value = UiState.LoadingState + } + } + } + fun logout() { viewModelScope.launch(exceptionHandler) { formUiState.value = UiState.LoadingState @@ -127,6 +181,8 @@ class AuthVM @Inject constructor( val authToken: String, ) : UiState() + data class LaunchDynamicModule(val moduleName: String) : UiState() + data class ErrorState(val throwable: Throwable) : UiState() } } From 37c9790d9e99d4eb380fe490f01a0e2bf8c8bd79 Mon Sep 17 00:00:00 2001 From: Ruthvikbr-MM Date: Mon, 28 Nov 2022 12:18:39 +0530 Subject: [PATCH 4/4] feat : Add SplitInstallStateUpdate listener --- .../authentication/ui/AuthenticationUI.kt | 42 ++++++++++++++++--- .../praxis/feat/authentication/vm/AuthVM.kt | 28 +------------ 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt index 716de28f..18877334 100644 --- a/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt +++ b/ui-authentication/src/main/java/com/praxis/feat/authentication/ui/AuthenticationUI.kt @@ -36,9 +36,6 @@ import coil.compose.rememberImagePainter import com.google.accompanist.insets.navigationBarsPadding import com.google.accompanist.insets.navigationBarsWithImePadding import com.google.accompanist.insets.statusBarsPadding -import com.google.android.play.core.splitinstall.SplitInstallManager -import com.google.android.play.core.splitinstall.SplitInstallManagerFactory -import com.google.android.play.core.splitinstall.SplitInstallRequest import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus import com.mutualmobile.praxis.commonui.material.DefaultSnackbar @@ -192,12 +189,16 @@ private fun AuthSurface( } } - if(dynamicFeatureUiState is AuthVM.UiState.LaunchDynamicModule) { - launchDynamicModule(LocalContext.current) + if(dynamicFeatureUiState is AuthVM.UiState.ErrorState) { + LaunchedEffect(scaffoldState) { + scaffoldState.snackbarHostState.showSnackbar( + message = "Something went wrong", + actionLabel = "Ok" + ) + } } } } - } } @@ -219,6 +220,35 @@ fun RandomPhotoButton(authVM: AuthVM) { @Composable fun LoadDynamicFeature(authVM: AuthVM) { + val context = LocalContext.current + LaunchedEffect(key1 = true) { + SplitInstallStateUpdatedListener { state -> + when (state.status()) { + SplitInstallSessionStatus.INSTALLING -> { + authVM.dynamicUiState.value = AuthVM.UiState.LoadingState + } + + SplitInstallSessionStatus.INSTALLED -> { + authVM.dynamicUiState.value = + AuthVM.UiState.LaunchDynamicModule(authVM.dynamicFeatureNameState.value) + launchDynamicModule(context) + } + + SplitInstallSessionStatus.DOWNLOADING -> { + authVM.dynamicUiState.value = AuthVM.UiState.LoadingState + } + + SplitInstallSessionStatus.FAILED -> { + authVM.dynamicUiState.value = AuthVM.UiState.ErrorState(Throwable("Something went wrong")) + } + + else -> { + authVM.dynamicUiState.value = AuthVM.UiState.ErrorState(Throwable("Something went wrong")) + } + } + } + } + Button( onClick = { authVM.checkDynamicFeatureInstallation("Sample") diff --git a/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt b/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt index 5d0d96b6..e009b49e 100644 --- a/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt +++ b/ui-authentication/src/main/java/com/praxis/feat/authentication/vm/AuthVM.kt @@ -3,12 +3,9 @@ package com.praxis.feat.authentication.vm import android.content.Context import android.net.Uri import androidx.lifecycle.* -import androidx.lifecycle.viewmodel.compose.viewModel import com.google.android.play.core.splitinstall.SplitInstallManager import com.google.android.play.core.splitinstall.SplitInstallManagerFactory import com.google.android.play.core.splitinstall.SplitInstallRequest -import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener -import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus import com.mutualmobile.praxis.domain.model.StreamingFile import com.mutualmobile.praxis.domain.usecases.FetchRandomPhotoUseCase import com.mutualmobile.praxis.navigator.ComposeNavigator @@ -48,7 +45,7 @@ class AuthVM @Inject constructor( var dynamicFeatureNameState = MutableStateFlow("") private set - private lateinit var manager: SplitInstallManager + private var manager: SplitInstallManager private val exceptionHandler = CoroutineExceptionHandler { _, throwable -> when (throwable) { @@ -111,8 +108,8 @@ class AuthVM @Inject constructor( fun checkDynamicFeatureInstallation(moduleName: String) { if (manager.installedModules.contains(moduleName)) { viewModelScope.launch { - dynamicUiState.value = UiState.LaunchDynamicModule(moduleName) dynamicFeatureNameState.value = moduleName + dynamicUiState.value = UiState.LaunchDynamicModule(moduleName) } } else { installDynamicModule(moduleName) @@ -125,26 +122,6 @@ class AuthVM @Inject constructor( manager.startInstall(request) } - private val listener = SplitInstallStateUpdatedListener { state -> - when (state.status()) { - SplitInstallSessionStatus.INSTALLING -> { - dynamicUiState.value = UiState.LoadingState - } - - SplitInstallSessionStatus.INSTALLED -> { - dynamicUiState.value = UiState.LaunchDynamicModule(dynamicFeatureNameState.value) - } - - SplitInstallSessionStatus.DOWNLOADING -> { - dynamicUiState.value = UiState.LoadingState - } - - SplitInstallSessionStatus.FAILED -> { - dynamicUiState.value = UiState.LoadingState - } - } - } - fun logout() { viewModelScope.launch(exceptionHandler) { formUiState.value = UiState.LoadingState @@ -180,7 +157,6 @@ class AuthVM @Inject constructor( data class SuccessState( val authToken: String, ) : UiState() - data class LaunchDynamicModule(val moduleName: String) : UiState() data class ErrorState(val throwable: Throwable) : UiState()