feat: Add AsLockedApp wrapper to require id verification if enabled

This commit is contained in:
Myzel394 2023-12-23 20:41:36 +01:00
parent 025a8a3209
commit 6661d457ea
No known key found for this signature in database
GPG Key ID: 50098FCA22080F0F
4 changed files with 90 additions and 11 deletions

View File

@ -14,7 +14,7 @@ import androidx.core.view.WindowCompat
import androidx.datastore.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.db.AppSettingsSerializer
import app.myzel394.alibi.ui.LockedApp
import app.myzel394.alibi.ui.AsLockedApp
import app.myzel394.alibi.ui.Navigation
import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY
import app.myzel394.alibi.ui.theme.AlibiTheme
@ -33,7 +33,9 @@ class MainActivity : AppCompatActivity() {
setContent {
AlibiTheme {
Navigation()
AsLockedApp {
Navigation()
}
}
}
}

View File

@ -1,11 +1,13 @@
package app.myzel394.alibi.helpers
import android.app.Activity
import android.content.Context
import androidx.biometric.BiometricManager
import androidx.core.content.ContextCompat
import androidx.biometric.BiometricPrompt
import androidx.fragment.app.FragmentActivity
import kotlinx.coroutines.CompletableDeferred
import kotlin.system.exitProcess
class AppLockHelper {
enum class SupportType {
@ -60,5 +62,15 @@ class AppLockHelper {
return deferred
}
fun closeApp(context: Context) {
(context as? Activity)?.let {
it.finishAndRemoveTask()
it.finishAffinity()
it.finish()
}
exitProcess(0)
}
}
}

View File

@ -20,17 +20,88 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.helpers.AppLockHelper
import kotlinx.coroutines.launch
// After this amount, close the app
const val MAX_TRIES = 5
const val MAX_TRIES = 10
@Composable
fun LockedApp() {
fun AsLockedApp(
content: (@Composable () -> Unit),
) {
val scope = rememberCoroutineScope()
val context = LocalContext.current
val settings = context
.dataStore
.data
.collectAsState(initial = null)
.value ?: return
// -1 = Unlocked, any other value = locked
var tries by remember { mutableIntStateOf(0) }
LaunchedEffect(settings.isAppLockEnabled()) {
if (!settings.isAppLockEnabled()) {
tries = -1
}
}
if (tries == -1) {
return content()
}
val title = stringResource(R.string.identityVerificationRequired_title)
val subtitle = stringResource(R.string.identityVerificationRequired_subtitle)
fun openAuthentication() {
if (tries >= MAX_TRIES) {
AppLockHelper.closeApp(context)
return
}
scope.launch {
val successful = AppLockHelper.authenticate(
context,
title,
subtitle,
).await()
if (successful) {
tries = -1
return@launch
}
tries++
if (tries >= MAX_TRIES) {
AppLockHelper.closeApp(context)
}
}
}
LaunchedEffect(settings.isAppLockEnabled()) {
if (settings.isAppLockEnabled()) {
openAuthentication()
}
}
Scaffold { paddingValues ->
Column(
modifier = Modifier
@ -60,7 +131,7 @@ fun LockedApp() {
modifier = Modifier
.fillMaxWidth()
.height(BIG_PRIMARY_BUTTON_SIZE),
onClick = {},
onClick = ::openAuthentication,
colors = ButtonDefaults.filledTonalButtonColors(),
) {
Icon(

View File

@ -72,12 +72,6 @@ fun Navigation(
}
}
LaunchedEffect(Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
AppLockHelper.authenticate(context, "Title", "Subtitle")
}
}
LaunchedEffect(settings.theme) {
if (!SUPPORTS_DARK_MODE_NATIVELY) {
val currentValue = AppCompatDelegate.getDefaultNightMode()