mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-05 19:08:23 +00:00
Replace runBlocking with suspend functions for PIN storage
Make loadPinFromEncryptedStorage and savePinToEncryptedStorage suspend functions, and update all callers (SecurityScreen, ConfirmPinScreen, BiometricAuthScreen) to use coroutine scopes instead of blocking the calling thread. https://claude.ai/code/session_01TeTHfGJL42J7eHCDdhsDnP
This commit is contained in:
@@ -157,20 +157,20 @@ object LocalPreferences {
|
||||
}
|
||||
}
|
||||
|
||||
fun loadPinFromEncryptedStorage(): String? {
|
||||
suspend fun loadPinFromEncryptedStorage(): String? {
|
||||
val context = Amber.instance
|
||||
// Migration: move PIN from plain SharedPreferences to encrypted DataStore
|
||||
val legacyPin = sharedPrefs(context).getString(SettingsKeys.PIN.key, null)
|
||||
if (legacyPin != null) {
|
||||
runBlocking { DataStoreAccess.savePin(context, legacyPin) }
|
||||
DataStoreAccess.savePin(context, legacyPin)
|
||||
sharedPrefs(context).edit { remove(SettingsKeys.PIN.key) }
|
||||
}
|
||||
return runBlocking { DataStoreAccess.loadPin(context) }
|
||||
return DataStoreAccess.loadPin(context)
|
||||
}
|
||||
|
||||
fun savePinToEncryptedStorage(pin: String?) {
|
||||
suspend fun savePinToEncryptedStorage(pin: String?) {
|
||||
val context = Amber.instance
|
||||
runBlocking { DataStoreAccess.savePin(context, pin) }
|
||||
DataStoreAccess.savePin(context, pin)
|
||||
}
|
||||
|
||||
suspend fun reloadApp() {
|
||||
|
||||
@@ -90,8 +90,12 @@ fun SecurityScreen(
|
||||
.padding(horizontal = 8.dp)
|
||||
.clickable {
|
||||
if (setupPin) {
|
||||
val pin = LocalPreferences.loadPinFromEncryptedStorage()
|
||||
navController.navigate("${Route.ConfirmPin.route.split("/")[0]}/$pin")
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val pin = LocalPreferences.loadPinFromEncryptedStorage()
|
||||
scope.launch(Dispatchers.Main) {
|
||||
navController.navigate("${Route.ConfirmPin.route.split("/")[0]}/$pin")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
navController.navigate(Route.SetupPin.route)
|
||||
}
|
||||
@@ -105,8 +109,12 @@ fun SecurityScreen(
|
||||
checked = setupPin,
|
||||
onCheckedChange = {
|
||||
if (setupPin) {
|
||||
val pin = LocalPreferences.loadPinFromEncryptedStorage()
|
||||
navController.navigate("${Route.ConfirmPin.route.split("/")[0]}/$pin")
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val pin = LocalPreferences.loadPinFromEncryptedStorage()
|
||||
scope.launch(Dispatchers.Main) {
|
||||
navController.navigate("${Route.ConfirmPin.route.split("/")[0]}/$pin")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
navController.navigate(Route.SetupPin.route)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.greenart7c3.nostrsigner.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.navigation.NavController
|
||||
@@ -10,6 +11,8 @@ import com.greenart7c3.nostrsigner.LocalPreferences
|
||||
import com.greenart7c3.nostrsigner.R
|
||||
import com.greenart7c3.nostrsigner.ui.components.RandomPinInput
|
||||
import com.greenart7c3.nostrsigner.ui.navigation.Route
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun SetupPinScreen(
|
||||
@@ -32,6 +35,7 @@ fun ConfirmPinScreen(
|
||||
navController: NavController,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
Column(
|
||||
modifier,
|
||||
) {
|
||||
@@ -41,22 +45,21 @@ fun ConfirmPinScreen(
|
||||
ToastManager.toast(context.getString(R.string.pin), context.getString(R.string.pin_does_not_match))
|
||||
} else {
|
||||
val usePin = Amber.instance.settings.usePin
|
||||
if (usePin) {
|
||||
Amber.instance.settings = Amber.instance.settings.copy(usePin = false)
|
||||
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
|
||||
LocalPreferences.savePinToEncryptedStorage(null)
|
||||
navController.navigate(Route.Security.route) {
|
||||
popUpTo(Route.Security.route) {
|
||||
inclusive = true
|
||||
}
|
||||
scope.launch(Dispatchers.IO) {
|
||||
if (usePin) {
|
||||
Amber.instance.settings = Amber.instance.settings.copy(usePin = false)
|
||||
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
|
||||
LocalPreferences.savePinToEncryptedStorage(null)
|
||||
} else {
|
||||
Amber.instance.settings = Amber.instance.settings.copy(usePin = true)
|
||||
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
|
||||
LocalPreferences.savePinToEncryptedStorage(pin)
|
||||
}
|
||||
} else {
|
||||
Amber.instance.settings = Amber.instance.settings.copy(usePin = true)
|
||||
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
|
||||
LocalPreferences.savePinToEncryptedStorage(pin)
|
||||
navController.navigate(Route.Security.route) {
|
||||
popUpTo(Route.Security.route) {
|
||||
inclusive = true
|
||||
scope.launch(Dispatchers.Main) {
|
||||
navController.navigate(Route.Security.route) {
|
||||
popUpTo(Route.Security.route) {
|
||||
inclusive = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-16
@@ -15,6 +15,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -36,6 +37,7 @@ fun BiometricAuthScreen(
|
||||
onAuth: (Boolean) -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
var showPinDialog by remember { mutableStateOf(false) }
|
||||
val keyguardLauncher =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
|
||||
@@ -117,22 +119,25 @@ fun BiometricAuthScreen(
|
||||
) {
|
||||
RandomPinInput(
|
||||
text = stringResource(R.string.enter_pin),
|
||||
onPinEntered = {
|
||||
val pin = LocalPreferences.loadPinFromEncryptedStorage()
|
||||
if (it == pin) {
|
||||
Amber.instance.settings = Amber.instance.settings.copy(
|
||||
lastBiometricsTime = System.currentTimeMillis(),
|
||||
)
|
||||
|
||||
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
|
||||
onAuth(true)
|
||||
showPinDialog = false
|
||||
} else {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.pin_does_not_match),
|
||||
Toast.LENGTH_SHORT,
|
||||
).show()
|
||||
onPinEntered = { enteredPin ->
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val pin = LocalPreferences.loadPinFromEncryptedStorage()
|
||||
scope.launch(Dispatchers.Main) {
|
||||
if (enteredPin == pin) {
|
||||
Amber.instance.settings = Amber.instance.settings.copy(
|
||||
lastBiometricsTime = System.currentTimeMillis(),
|
||||
)
|
||||
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
|
||||
onAuth(true)
|
||||
showPinDialog = false
|
||||
} else {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.pin_does_not_match),
|
||||
Toast.LENGTH_SHORT,
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user