diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 5f8997ff..3477800c 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)
@@ -100,6 +100,7 @@ android {
kotlinOptions {
jvmTarget = "1.8"
}
+ dynamicFeatures += setOf(":sample")
}
// Required for annotation processing plugins like Dagger
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 8aae06ce..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">
@@ -24,12 +23,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..a7fbd296 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -12,7 +12,7 @@ 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")
+ 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 60b5dae6..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 MIN_SDK = 21
- const val TARGET_SDK = 31
+ const val COMPILE_SDK = 32
+ const val MIN_SDK = 24
+ 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 81a3a66c..46a82365 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}"
@@ -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}"
@@ -38,18 +38,19 @@ 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
)
}
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"
- private const val APP_COMPAT = "androidx.appcompat:appcompat:1.3.0-beta01"
+ 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/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/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 d8cebfcc..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.2-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/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")
diff --git a/ui-authentication/build.gradle.kts b/ui-authentication/build.gradle.kts
index f976ad7b..33de9757 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)
@@ -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 7449c1e5..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
@@ -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,17 @@ 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.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 +55,8 @@ fun AuthenticationUI(
backgroundColor = PraxisColorProvider.colors.uiBackground,
contentColor = PraxisColorProvider.colors.textSecondary,
modifier = Modifier
- .statusBarsPadding()
- .navigationBarsPadding(),
+ .statusBarsPadding()
+ .navigationBarsPadding(),
topBar = {
PraxisSurfaceAppBar(
title = {
@@ -91,16 +96,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 +129,7 @@ private fun AuthSurface(
)
RandomPhotoButton(authVM)
-
+ LoadDynamicFeature(authVM)
LogoutButton(authVM)
}
}
@@ -132,11 +138,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
) {
@@ -145,7 +151,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)
)
}
@@ -162,6 +168,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,9 +188,17 @@ private fun AuthSurface(
)
}
}
+
+ if(dynamicFeatureUiState is AuthVM.UiState.ErrorState) {
+ LaunchedEffect(scaffoldState) {
+ scaffoldState.snackbarHostState.showSnackbar(
+ message = "Something went wrong",
+ actionLabel = "Ok"
+ )
+ }
+ }
}
}
-
}
}
@@ -200,6 +218,50 @@ 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")
+ }, 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 +323,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",
@@ -276,7 +338,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"
)
},
@@ -297,9 +359,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)
@@ -316,7 +378,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"
)
},
@@ -340,4 +402,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/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-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..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
@@ -1,7 +1,11 @@
package com.praxis.feat.authentication.vm
+import android.content.Context
import android.net.Uri
import androidx.lifecycle.*
+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.mutualmobile.praxis.domain.model.StreamingFile
import com.mutualmobile.praxis.domain.usecases.FetchRandomPhotoUseCase
import com.mutualmobile.praxis.navigator.ComposeNavigator
@@ -10,6 +14,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 +25,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 +39,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 var manager: SplitInstallManager
+
private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
when (throwable) {
is FormValidationFailed -> {
@@ -63,6 +76,7 @@ class AuthVM @Inject constructor(
init {
observePasswordReset()
+ manager = SplitInstallManagerFactory.create(context)
}
private fun observePasswordReset() {
@@ -91,6 +105,23 @@ class AuthVM @Inject constructor(
composeNavigator.navigate(PraxisScreen.ForgotPassword.route)
}
+ fun checkDynamicFeatureInstallation(moduleName: String) {
+ if (manager.installedModules.contains(moduleName)) {
+ viewModelScope.launch {
+ dynamicFeatureNameState.value = moduleName
+ dynamicUiState.value = UiState.LaunchDynamicModule(moduleName)
+ }
+ } else {
+ installDynamicModule(moduleName)
+ }
+ }
+ private fun installDynamicModule(moduleName: String) {
+ val request: SplitInstallRequest = SplitInstallRequest.newBuilder()
+ .addModule(moduleName)
+ .build()
+ manager.startInstall(request)
+ }
+
fun logout() {
viewModelScope.launch(exceptionHandler) {
formUiState.value = UiState.LoadingState
@@ -126,6 +157,7 @@ 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()
}
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)