diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1d52735ce7..536e770195 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -55,6 +55,7 @@ + private lateinit var appThemeModeFlow: SharedFlow // TODO: fixme: inject through DI private val intentProcessor: IntentProcessor = IntentProcessor() @@ -172,10 +173,10 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac private val onActivityResultCallbacks = mutableListOf() override fun onCreate(savedInstanceState: Bundle?) { - val splashScreen = installSplashScreen() - installAppTheme() // We need to call it before onCreate to prevent unnecessary activity recreation + val splashScreen = installSplashScreen() + super.onCreate(savedInstanceState) splashScreen.setKeepOnScreenCondition { viewModel.isSplashScreenShown } @@ -248,14 +249,13 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac private fun installAppTheme() { appThemeModeFlow = createAppThemeModeFlow() - val mode = runBlocking { appThemeModeFlow.filterNotNull().first() } + val mode = runBlocking { appThemeModeFlow.first() } updateAppTheme(mode) } private fun observeAppThemeModeUpdates() { appThemeModeFlow - .filterNotNull() .flowWithLifecycle(lifecycle) .onEach(::updateAppTheme) .launchIn(lifecycleScope) @@ -273,15 +273,17 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } - private fun createAppThemeModeFlow(): SharedFlow { + private fun createAppThemeModeFlow(): SharedFlow { val tangemApplication = application as TangemApplication return tangemApplication.getAppThemeModeUseCase() + .filterNotNull() .map { maybeMode -> maybeMode.getOrElse { AppThemeMode.DEFAULT } } + .distinctUntilChanged() .shareIn( - scope = lifecycleScope + Dispatchers.IO, + scope = lifecycleScope, started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000), ) } @@ -337,17 +339,18 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac } private fun updateAppTheme(appThemeMode: AppThemeMode) { - MutableAppThemeModeHolder.value = appThemeMode - MutableAppThemeModeHolder.isDarkThemeActive = isDarkTheme() - val mode = when (appThemeMode) { AppThemeMode.FORCE_DARK -> AppCompatDelegate.MODE_NIGHT_YES AppThemeMode.FORCE_LIGHT -> AppCompatDelegate.MODE_NIGHT_NO AppThemeMode.FOLLOW_SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM } - setDefaultNightMode(mode) - delegate.localNightMode = mode + if (mode != getDefaultNightMode()) { + setDefaultNightMode(mode) + } + + MutableAppThemeModeHolder.value = appThemeMode + MutableAppThemeModeHolder.isDarkThemeActive = isDarkTheme() } private fun isDarkTheme(): Boolean { diff --git a/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeFragment.kt b/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeFragment.kt index fb811871af..c60bf1ba7b 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeFragment.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/screen/ComposeFragment.kt @@ -1,5 +1,6 @@ package com.tangem.core.ui.screen +import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -22,6 +23,18 @@ abstract class ComposeFragment : Fragment(), ComposeScreen { } } + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + + /* + * We need to manually dispatch configuration changes to the Compose view. + * + + * `android:configChanges="uiMode"` is set in the manifest. + * */ + view?.dispatchConfigurationChanged(newConfig) + } + /** * Inflates transitions for the fragment. Override this method to customize * enter and exit transitions for the fragment.