fix(ui): sync Activity uiMode to in-app theme at startup (C-DARKART-002 architectural fix)

This commit is contained in:
null 2026-06-28 16:35:01 -05:00
parent 4ee600125d
commit c3a3c38e0e
1 changed files with 26 additions and 1 deletions

View File

@ -5,6 +5,7 @@ import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.compose.foundation.layout.Box
@ -37,8 +38,10 @@ import app.closer.notifications.PartnerNotificationPayload
import app.closer.notifications.PartnerNotificationType
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import app.closer.domain.repository.AppSettings
import app.closer.domain.repository.AuthRepository
import app.closer.domain.repository.SettingsRepository
@ -92,14 +95,30 @@ class MainActivity : AppCompatActivity() {
registerFcmToken()
pendingDeepLink.value = deepLinkRouteFromIntent(intent)
if (BuildConfig.DEBUG) attemptDebugAutoLogin()
// Drive the REAL Configuration uiMode from the in-app theme (Settings → Appearance) so that
// `painterResource` and the `drawable-night*` variants follow the app's own theme, not just
// the Compose color scheme. Without this, in-app-Dark + system-Light shows light artwork on a
// dark UI (C-DARKART-002). Read the persisted theme synchronously here so the placeholder
// (default DEVICE) can never fight the persisted night-mode default and cause a recreation
// flicker loop; runtime toggles are handled by the LaunchedEffect below.
val initialSettings = runBlocking { settingsRepository.settings.first() }
AppCompatDelegate.setDefaultNightMode(nightModeFor(initialSettings.themeMode))
setContent {
val settings by settingsRepository.settings.collectAsState(initial = AppSettings())
val settings by settingsRepository.settings.collectAsState(initial = initialSettings)
val systemInDarkTheme = isSystemInDarkTheme()
val useDarkTheme = when (settings.themeMode) {
ThemeMode.DEVICE -> systemInDarkTheme
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
}
// Apply runtime theme changes to the Configuration uiMode too (AppCompat recreates the
// Activity with the new uiMode so artwork re-resolves the correct -night variant).
LaunchedEffect(settings.themeMode) {
val target = nightModeFor(settings.themeMode)
if (AppCompatDelegate.getDefaultNightMode() != target) {
AppCompatDelegate.setDefaultNightMode(target)
}
}
var sessionVerified by remember { mutableStateOf(false) }
val needsBiometricLock = settings.biometricLoginEnabled
@ -133,6 +152,12 @@ class MainActivity : AppCompatActivity() {
}
}
private fun nightModeFor(mode: ThemeMode): Int = when (mode) {
ThemeMode.DEVICE -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
ThemeMode.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
ThemeMode.DARK -> AppCompatDelegate.MODE_NIGHT_YES
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)