1package com.peachpasswords23import android.content.Intent4import android.content.res.Configuration5import android.graphics.Color as AndroidColor6import android.graphics.drawable.ColorDrawable7import android.os.Bundle8import android.view.WindowManager9import androidx.activity.compose.setContent10import androidx.activity.enableEdgeToEdge11import androidx.compose.foundation.isSystemInDarkTheme12import androidx.compose.runtime.SideEffect13import androidx.compose.ui.unit.dp14import androidx.compose.ui.unit.Density15import androidx.compose.ui.platform.LocalDensity16import androidx.compose.ui.Modifier17import androidx.compose.runtime.CompositionLocalProvider18import androidx.compose.runtime.Composable19import androidx.compose.foundation.layout.fillMaxSize20import androidx.compose.foundation.layout.BoxWithConstraints21import androidx.compose.runtime.collectAsState22import androidx.compose.runtime.getValue23import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen24import androidx.core.view.WindowCompat25import androidx.fragment.app.FragmentActivity26import dagger.hilt.android.AndroidEntryPoint27import javax.inject.Inject28import com.peachpasswords.ui.PeachAppNavHost29import com.peachpasswords.ui.components.QaFlags30import com.peachpasswords.ui.onboarding.ONBOARD_KEY31import com.peachpasswords.ui.onboarding.ONBOARD_PREFS32import com.peachpasswords.ui.onboarding.onboardingStartDestination33import com.peachpasswords.ui.theme.ACCENT_COLORS34import com.peachpasswords.ui.theme.DEFAULT_ACCENT35import com.peachpasswords.ui.theme.PeachTheme36import com.peachpasswords.updates.EXTRA_OPEN_UPDATE37import com.peachpasswords.updates.UpdateRepository38import com.peachpasswords.vault.VaultLockTimer39import com.peachpasswords.vault.VaultRepository404142@AndroidEntryPoint43class MainActivity : FragmentActivity() {44 @Inject lateinit var vault: VaultRepository45 @Inject lateinit var lockTimer: VaultLockTimer46 @Inject lateinit var updates: UpdateRepository4748 49 override fun onUserInteraction() {50 super.onUserInteraction()51 lockTimer.poke()52 }5354 55 56 57 override fun onNewIntent(intent: Intent) {58 super.onNewIntent(intent)59 setIntent(intent)60 if (intent.getBooleanExtra(EXTRA_OPEN_UPDATE, false)) updates.requestOpen()61 if (BuildConfig.DEBUG) {62 QaFlags.disableSecureCaptureForQa = intent.getBooleanExtra("qa_disable_secure_flag", false)63 }64 }6566 override fun onCreate(savedInstanceState: Bundle?) {67 installSplashScreen()68 super.onCreate(savedInstanceState)6970 71 if (intent.getBooleanExtra(EXTRA_OPEN_UPDATE, false)) updates.requestOpen()7273 74 75 76 val initialTheme = vault.settings.value.theme77 val initialDark = when (initialTheme) {78 "light" -> false79 "system" -> (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==80 Configuration.UI_MODE_NIGHT_YES81 else -> true82 }83 window.setBackgroundDrawable(84 ColorDrawable(AndroidColor.parseColor(if (initialDark) "#0C0A06" else "#EFEEE9")),85 )8687 enableEdgeToEdge()8889 90 if (!BuildConfig.DEBUG) {91 window.setFlags(92 WindowManager.LayoutParams.FLAG_SECURE,93 WindowManager.LayoutParams.FLAG_SECURE,94 )95 } else {96 97 98 99 QaFlags.disableSecureCaptureForQa = intent.getBooleanExtra("qa_disable_secure_flag", false)100 }101102 103 val onboarded = getSharedPreferences(ONBOARD_PREFS, MODE_PRIVATE)104 .getBoolean(ONBOARD_KEY, false)105 val start = onboardingStartDestination(hasVault = vault.hasVault(), onboarded = onboarded)106107 setContent {108 val settings by vault.settings.collectAsState()109 val darkTheme = when (settings.theme) {110 "light" -> false111 "system" -> isSystemInDarkTheme()112 else -> true113 }114 115 116 117 118 119 120 121 122 SideEffect {123 WindowCompat.getInsetsController(window, window.decorView).apply {124 isAppearanceLightStatusBars = !darkTheme125 isAppearanceLightNavigationBars = !darkTheme126 }127 }128 val accent = ACCENT_COLORS[settings.accentColor] ?: DEFAULT_ACCENT129 PeachTheme(130 darkTheme = darkTheme,131 accent = accent,132 reduceMotion = settings.reduceMotion,133 ) {134 WideScreenScale {135 PeachAppNavHost(startDestination = start, isUnlocked = vault.isUnlocked)136 }137 }138 }139 }140}141142143private val BASE_WIDTH = 411.dp144145146private const val MAX_SCALE = 1.35f147148149150151152153154155156157158@Composable159private fun WideScreenScale(content: @Composable () -> Unit) {160 BoxWithConstraints(Modifier.fillMaxSize()) {161 val base = LocalDensity.current162 val scale = (maxWidth / BASE_WIDTH).coerceIn(1f, MAX_SCALE)163 if (scale == 1f) {164 content()165 } else {166 CompositionLocalProvider(167 LocalDensity provides Density(base.density * scale, base.fontScale),168 content = content,169 )170 }171 }172}