Implement password verification and enhance BackupScreen UI

- Added password verification logic in MainActivity to decrypt the private key and seed phrase.
- Updated BackupScreen to handle password verification asynchronously using coroutines.
- Improved UI layout for displaying seed phrases in two columns with colored words.
- Added a copy button for the seed phrase with clipboard functionality.
- Introduced a new composable function, WordItem, for better visual representation of seed phrase words.
This commit is contained in:
k1ngsterr1
2026-01-21 16:44:35 +05:00
parent d443592435
commit 7d81dedfab
3 changed files with 176 additions and 33 deletions

File diff suppressed because one or more lines are too long

View File

@@ -542,10 +542,35 @@ fun MainScreen(
showSafetyScreen = true
},
onVerifyPassword = { password ->
// TODO: Implement password verification
if (password == "test") {
"word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12"
} else null
// Verify password by trying to decrypt the private key
try {
val publicKey = account?.publicKey ?: return@BackupScreen null
val accountManager = AccountManager(context)
val encryptedAccount = accountManager.getAccount(publicKey)
if (encryptedAccount != null) {
// Try to decrypt private key with password
val decryptedPrivateKey = com.rosetta.messenger.crypto.CryptoManager.decryptWithPassword(
encryptedAccount.encryptedPrivateKey,
password
)
if (decryptedPrivateKey != null) {
// Password is correct, decrypt seed phrase
com.rosetta.messenger.crypto.CryptoManager.decryptWithPassword(
encryptedAccount.encryptedSeedPhrase,
password
)
} else {
null
}
} else {
null
}
} catch (e: Exception) {
Log.e("MainActivity", "Error verifying password", e)
null
}
}
)
}

View File

@@ -9,9 +9,13 @@ import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material.icons.filled.Warning
@@ -26,18 +30,21 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
import com.airbnb.lottie.compose.*
@Composable
fun BackupScreen(
isDarkTheme: Boolean,
onBack: () -> Unit,
onVerifyPassword: (String) -> String? // Returns seed phrase if password is correct
onVerifyPassword: suspend (String) -> String? // Returns seed phrase if password is correct
) {
val backgroundColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFFFFFFF)
val surfaceColor = if (isDarkTheme) Color(0xFF2C2C2E) else Color(0xFFF2F2F7)
val textColor = if (isDarkTheme) Color.White else Color.Black
val secondaryTextColor = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666)
val scope = rememberCoroutineScope()
var password by remember { mutableStateOf("") }
var seedPhrase by remember { mutableStateOf<String?>(null) }
var passwordVisible by remember { mutableStateOf(false) }
@@ -91,11 +98,15 @@ fun BackupScreen(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
imageVector = Icons.Filled.Warning,
contentDescription = null,
tint = Color(0xFFFFAC00),
modifier = Modifier.size(48.dp)
val composition by rememberLottieComposition(LottieCompositionSpec.Asset("lottie/shush.json"))
val progress by animateLottieCompositionAsState(
composition = composition,
iterations = 1
)
LottieAnimation(
composition = composition,
progress = { progress },
modifier = Modifier.size(80.dp)
)
Spacer(modifier = Modifier.height(12.dp))
Text(
@@ -128,9 +139,11 @@ fun BackupScreen(
onValueChange = { newValue ->
password = newValue
// Try to verify password
val result = onVerifyPassword(newValue)
if (result != null) {
seedPhrase = result
scope.launch {
val result = onVerifyPassword(newValue)
if (result != null) {
seedPhrase = result
}
}
},
modifier = Modifier.weight(1f),
@@ -138,6 +151,7 @@ fun BackupScreen(
color = textColor,
fontSize = 15.sp
),
cursorBrush = SolidColor(textColor),
visualTransformation = if (passwordVisible)
VisualTransformation.None
else
@@ -182,33 +196,80 @@ fun BackupScreen(
lineHeight = 20.sp
)
} else {
// Seed Phrase Display
Surface(
// Seed Phrase Display with colored words
Spacer(modifier = Modifier.height(8.dp))
val words = seedPhrase!!.split(" ")
// Two column layout like in SeedPhraseScreen
Row(
modifier = Modifier.fillMaxWidth(),
color = surfaceColor,
shape = RoundedCornerShape(10.dp)
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
Column(modifier = Modifier.padding(20.dp)) {
val words = seedPhrase!!.split(" ")
words.chunked(3).forEach { rowWords ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
rowWords.forEachIndexed { index, word ->
Text(
text = "${words.indexOf(word) + 1}. $word",
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
color = textColor,
modifier = Modifier.padding(vertical = 4.dp)
)
}
// Left column (words 1-6)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
for (i in 0..5) {
if (i < words.size) {
WordItem(
number = i + 1,
word = words[i],
isDarkTheme = isDarkTheme
)
}
}
}
// Right column (words 7-12)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
for (i in 6..11) {
if (i < words.size) {
WordItem(
number = i + 1,
word = words[i],
isDarkTheme = isDarkTheme
)
}
}
}
}
Spacer(modifier = Modifier.height(16.dp))
// Copy button
val context = androidx.compose.ui.platform.LocalContext.current
Button(
onClick = {
val clipboard = context.getSystemService(android.content.Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
val clip = android.content.ClipData.newPlainText("Seed Phrase", seedPhrase)
clipboard.setPrimaryClip(clip)
},
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF248AE6)
),
shape = RoundedCornerShape(10.dp)
) {
Icon(
imageVector = Icons.Filled.ContentCopy,
contentDescription = null,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "Copy Seed Phrase",
fontSize = 15.sp,
fontWeight = FontWeight.Medium
)
}
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Please don't share your seed phrase! The administration will never ask you for it.",
fontSize = 14.sp,
@@ -222,3 +283,59 @@ fun BackupScreen(
}
}
}
@Composable
private fun WordItem(
number: Int,
word: String,
isDarkTheme: Boolean,
modifier: Modifier = Modifier
) {
val numberColor = if (isDarkTheme) Color(0xFF888888) else Color(0xFF999999)
// Beautiful solid colors that fit the theme
val wordColors = listOf(
Color(0xFF5E9FFF), // Soft blue
Color(0xFFFF7EB3), // Soft pink
Color(0xFF7B68EE), // Medium purple
Color(0xFF50C878), // Emerald green
Color(0xFFFF6B6B), // Coral red
Color(0xFF4ECDC4), // Teal
Color(0xFFFFB347), // Pastel orange
Color(0xFFBA55D3), // Medium orchid
Color(0xFF87CEEB), // Sky blue
Color(0xFFDDA0DD), // Plum
Color(0xFF98D8C8), // Mint
Color(0xFFF7DC6F) // Soft yellow
)
val wordColor = wordColors[(number - 1) % wordColors.size]
val bgColor = if (isDarkTheme) Color(0xFF2A2A2A) else Color(0xFFF5F5F5)
Box(
modifier = modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.background(bgColor)
.padding(horizontal = 16.dp, vertical = 14.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "$number.",
fontSize = 15.sp,
color = numberColor,
modifier = Modifier.width(28.dp)
)
Text(
text = word,
fontSize = 17.sp,
fontWeight = FontWeight.SemiBold,
color = wordColor,
fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace
)
}
}
}