Activity Compose Composition Strategy handling

This commit is contained in:
Milan Cerovsky 2024-08-19 16:12:15 +02:00
parent 2df5990238
commit be8ed7a8ad
2 changed files with 77 additions and 3 deletions

View File

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.os.Bundle import android.os.Bundle
import android.os.SystemClock import android.os.SystemClock
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
@ -29,6 +28,7 @@ import cash.z.ecc.sdk.type.fromResources
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
import co.electriccoin.zcash.spackle.Twig import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.common.compose.BindCompLocalProvider import co.electriccoin.zcash.ui.common.compose.BindCompLocalProvider
import co.electriccoin.zcash.ui.common.extension.setContentCompat
import co.electriccoin.zcash.ui.common.model.OnboardingState import co.electriccoin.zcash.ui.common.model.OnboardingState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.viewmodel.AuthenticationUIState import co.electriccoin.zcash.ui.common.viewmodel.AuthenticationUIState
@ -126,8 +126,7 @@ class MainActivity : FragmentActivity() {
// including IME animations, and go edge-to-edge. // including IME animations, and go edge-to-edge.
// This also sets up the initial system bar style based on the platform theme // This also sets up the initial system bar style based on the platform theme
enableEdgeToEdge() enableEdgeToEdge()
setContentCompat {
setContent {
Override(configurationOverrideFlow) { Override(configurationOverrideFlow) {
ZcashTheme { ZcashTheme {
BlankSurface( BlankSurface(
@ -160,6 +159,7 @@ class MainActivity : FragmentActivity() {
Twig.debug { "Authentication initial state" } Twig.debug { "Authentication initial state" }
// Wait for the state update // Wait for the state update
} }
AuthenticationUIState.NotRequired -> { AuthenticationUIState.NotRequired -> {
Twig.debug { "App access authentication NOT required - welcome animation only" } Twig.debug { "App access authentication NOT required - welcome animation only" }
if (animateAppAccess) { if (animateAppAccess) {
@ -173,6 +173,7 @@ class MainActivity : FragmentActivity() {
} }
} }
} }
AuthenticationUIState.Required -> { AuthenticationUIState.Required -> {
Twig.debug { "App access authentication required" } Twig.debug { "App access authentication required" }
@ -198,12 +199,14 @@ class MainActivity : FragmentActivity() {
useCase = AuthenticationUseCase.AppAccess useCase = AuthenticationUseCase.AppAccess
) )
} }
AuthenticationUIState.SupportedRequired -> { AuthenticationUIState.SupportedRequired -> {
Twig.debug { "Authentication support required" } Twig.debug { "Authentication support required" }
WrapSupport( WrapSupport(
goBack = { finish() } goBack = { finish() }
) )
} }
AuthenticationUIState.Successful -> { AuthenticationUIState.Successful -> {
Twig.debug { "Authentication successful - entering the app" } Twig.debug { "Authentication successful - entering the app" }
// No action is needed - the main app content is laid out now // No action is needed - the main app content is laid out now
@ -229,6 +232,7 @@ class MainActivity : FragmentActivity() {
SecretState.None -> { SecretState.None -> {
WrapOnboarding() WrapOnboarding()
} }
is SecretState.NeedsWarning -> { is SecretState.NeedsWarning -> {
WrapSecurityWarning( WrapSecurityWarning(
onBack = { walletViewModel.persistOnboardingState(OnboardingState.NONE) }, onBack = { walletViewModel.persistOnboardingState(OnboardingState.NONE) },
@ -249,15 +253,18 @@ class MainActivity : FragmentActivity() {
} }
) )
} }
is SecretState.NeedsBackup -> { is SecretState.NeedsBackup -> {
WrapNewWalletRecovery( WrapNewWalletRecovery(
secretState.persistableWallet, secretState.persistableWallet,
onBackupComplete = { walletViewModel.persistOnboardingState(OnboardingState.READY) } onBackupComplete = { walletViewModel.persistOnboardingState(OnboardingState.READY) }
) )
} }
is SecretState.Ready -> { is SecretState.Ready -> {
Navigation() Navigation()
} }
else -> { else -> {
error("Unhandled secret state: $secretState") error("Unhandled secret state: $secretState")
} }

View File

@ -0,0 +1,67 @@
package co.electriccoin.zcash.ui.common.extension
import android.view.ViewGroup
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionContext
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.lifecycle.setViewTreeViewModelStoreOwner
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
/**
* Same like [ComponentActivity.setContent] but allows for addition of [ViewCompositionStrategy].
*/
fun ComponentActivity.setContentCompat(
viewCompositionStrategy: ViewCompositionStrategy = ViewCompositionStrategy.DisposeOnDetachedFromWindow,
parent: CompositionContext? = null,
content: @Composable () -> Unit
) {
val existingComposeView =
window.decorView
.findViewById<ViewGroup>(android.R.id.content)
.getChildAt(0) as? ComposeView
if (existingComposeView != null) {
with(existingComposeView) {
setParentCompositionContext(parent)
setContent(content)
}
} else {
ComposeView(this).apply {
// Set content and parent **before** setContentView
// to have ComposeView create the composition on attach
setViewCompositionStrategy(viewCompositionStrategy)
setParentCompositionContext(parent)
setContent(content)
// Set the view tree owners before setting the content view so that the inflation process
// and attach listeners will see them already present
setOwners()
setContentView(
this,
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
)
}
}
}
private fun ComponentActivity.setOwners() {
val decorView = window.decorView
if (decorView.findViewTreeLifecycleOwner() == null) {
decorView.setViewTreeLifecycleOwner(this)
}
if (decorView.findViewTreeViewModelStoreOwner() == null) {
decorView.setViewTreeViewModelStoreOwner(this)
}
if (decorView.findViewTreeSavedStateRegistryOwner() == null) {
decorView.setViewTreeSavedStateRegistryOwner(this)
}
}