package com.syncflow import android.os.Build import android.os.Bundle import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.biometric.BiometricManager import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL import androidx.biometric.BiometricPrompt import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.core.content.ContextCompat import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.lifecycleScope import androidx.navigation.compose.rememberNavController import com.syncflow.data.preferences.AppPreferences import com.syncflow.ui.navigation.SyncFlowNavGraph import com.syncflow.ui.theme.SyncFlowTheme import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var appPreferences: AppPreferences private var isLocked by mutableStateOf(false) override fun onCreate(savedInstanceState: Bundle?) { installSplashScreen() super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { SyncFlowTheme { Surface(modifier = Modifier.fillMaxSize()) { SyncFlowNavGraph(rememberNavController()) } if (isLocked) { LockOverlay() LaunchedEffect(Unit) { showBiometricPrompt(onSuccess = { isLocked = false }) } } } } } override fun onStop() { super.onStop() if (isChangingConfigurations) return lifecycleScope.launch { if (appPreferences.biometricLockEnabled.first() && canAuthenticate()) { isLocked = true } } } private fun canAuthenticate(): Boolean { val authenticators = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) BIOMETRIC_STRONG or DEVICE_CREDENTIAL else BIOMETRIC_STRONG return BiometricManager.from(this).canAuthenticate(authenticators) == BiometricManager.BIOMETRIC_SUCCESS } private fun showBiometricPrompt(onSuccess: () -> Unit) { val executor = ContextCompat.getMainExecutor(this) val prompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { onSuccess() } }) val promptInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { BiometricPrompt.PromptInfo.Builder() .setTitle("Unlock SyncFlow") .setSubtitle("Confirm your identity to continue") .setAllowedAuthenticators(BIOMETRIC_STRONG or DEVICE_CREDENTIAL) .build() } else { BiometricPrompt.PromptInfo.Builder() .setTitle("Unlock SyncFlow") .setSubtitle("Confirm your identity to continue") .setNegativeButtonText("Cancel") .build() } prompt.authenticate(promptInfo) } } @Composable private fun LockOverlay() { Box( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background), contentAlignment = Alignment.Center, ) { CircularProgressIndicator() } }