feat: Add public key handling for avatar display and enhance paste functionality in seed phrase confirmation

This commit is contained in:
k1ngsterr1
2026-01-09 01:58:56 +05:00
parent 634d3094e3
commit e9eac107f2
3 changed files with 167 additions and 103 deletions

View File

@@ -205,11 +205,13 @@ fun MainScreen(
val accountPhone = account?.publicKey?.take(16)?.let {
"+${it.take(1)} ${it.substring(1, 4)} ${it.substring(4, 7)}${it.substring(7)}"
} ?: "+7 775 9932587"
val accountPublicKey = account?.publicKey ?: "04c266b98ae5"
ChatsListScreen(
isDarkTheme = isDarkTheme,
accountName = accountName,
accountPhone = accountPhone,
accountPublicKey = accountPublicKey,
onToggleTheme = onToggleTheme,
onProfileClick = {
// TODO: Navigate to profile

View File

@@ -140,30 +140,11 @@ fun ConfirmSeedPhraseScreen(
modifier = Modifier
.fillMaxWidth()
.padding(4.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = onBack) {
Icon(Icons.Default.ArrowBack, "Back", tint = textColor)
}
// Paste button
OutlinedButton(
onClick = handlePaste,
modifier = Modifier.height(40.dp),
colors = ButtonDefaults.outlinedButtonColors(
contentColor = PrimaryBlue
),
border = BorderStroke(1.dp, PrimaryBlue)
) {
Icon(
Icons.Default.ContentPaste,
contentDescription = "Paste",
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(6.dp))
Text("Paste", fontSize = 14.sp)
}
}
Column(
@@ -318,6 +299,38 @@ fun ConfirmSeedPhraseScreen(
}
}
Spacer(modifier = Modifier.height(20.dp))
// Paste button
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 400))
) {
OutlinedButton(
onClick = handlePaste,
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
colors = ButtonDefaults.outlinedButtonColors(
contentColor = PrimaryBlue
),
border = BorderStroke(1.dp, PrimaryBlue),
shape = RoundedCornerShape(12.dp)
) {
Icon(
Icons.Default.ContentPaste,
contentDescription = "Paste",
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "Paste from Clipboard",
fontSize = 16.sp,
fontWeight = FontWeight.Medium
)
}
}
// Error message
AnimatedVisibility(
visible = showError,

View File

@@ -112,6 +112,11 @@ fun getInitials(name: String): String {
}
}
// Get avatar text from public key (first 2 chars)
fun getAvatarText(publicKey: String): String {
return publicKey.take(2).uppercase()
}
// Drawer menu item
data class DrawerMenuItem(
val icon: ImageVector,
@@ -126,6 +131,7 @@ fun ChatsListScreen(
isDarkTheme: Boolean,
accountName: String,
accountPhone: String,
accountPublicKey: String,
onToggleTheme: () -> Unit,
onProfileClick: () -> Unit,
onNewGroupClick: () -> Unit,
@@ -242,6 +248,10 @@ fun ChatsListScreen(
var titleClickCount by remember { mutableStateOf(0) }
var lastClickTime by remember { mutableStateOf(0L) }
// Search state
var isSearchExpanded by remember { mutableStateOf(false) }
var searchQuery by remember { mutableStateOf("") }
var visible by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
@@ -401,19 +411,20 @@ fun ChatsListScreen(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Top
) {
// Avatar with initials
// Avatar with public key
val avatarColors = getAvatarColor(accountName, isDarkTheme)
Box(
modifier = Modifier
.size(64.dp)
.clip(CircleShape)
.background(PrimaryBlue),
.background(avatarColors.backgroundColor),
contentAlignment = Alignment.Center
) {
Text(
text = getInitials(accountName),
text = getAvatarText(accountPublicKey),
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
color = Color.White
color = avatarColors.textColor
)
}
@@ -556,91 +567,129 @@ fun ChatsListScreen(
}
},
title = {
// Stories / Title area - Triple click to open dev console
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime < 500) {
titleClickCount++
if (titleClickCount >= 3) {
showDevConsole = true
titleClickCount = 0
}
} else {
titleClickCount = 1
}
lastClickTime = currentTime
}
) {
// User story avatar placeholder
Box(
modifier = Modifier
.size(36.dp)
.clip(CircleShape)
.background(
brush = androidx.compose.ui.graphics.Brush.linearGradient(
colors = listOf(
Color(0xFF405DE6),
Color(0xFFC13584),
Color(0xFFFD1D1D)
)
)
)
.padding(2.dp)
.clip(CircleShape)
.background(backgroundColor),
contentAlignment = Alignment.Center
) {
val avatarColors = getAvatarColor(accountName, isDarkTheme)
Box(
modifier = Modifier
.size(30.dp)
.clip(CircleShape)
.background(avatarColors.backgroundColor),
contentAlignment = Alignment.Center
// Search field or Stories / Title area
AnimatedContent(
targetState = isSearchExpanded,
transitionSpec = {
fadeIn(tween(200)) togetherWith fadeOut(tween(200))
},
label = "searchAnimation"
) { expanded ->
if (expanded) {
// Search TextField
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(
text = getInitials(accountName),
fontSize = 12.sp,
fontWeight = FontWeight.Bold,
color = avatarColors.textColor
IconButton(
onClick = {
isSearchExpanded = false
searchQuery = ""
}
) {
Icon(
Icons.Default.ArrowBack,
contentDescription = "Close search",
tint = textColor
)
}
TextField(
value = searchQuery,
onValueChange = { searchQuery = it },
placeholder = {
Text(
"Search...",
color = secondaryTextColor
)
},
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
focusedTextColor = textColor,
unfocusedTextColor = textColor,
cursorColor = textColor,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent
),
singleLine = true,
modifier = Modifier.weight(1f)
)
}
}
} else {
// Triple click to open dev console
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime < 500) {
titleClickCount++
if (titleClickCount >= 3) {
showDevConsole = true
titleClickCount = 0
}
} else {
titleClickCount = 1
}
lastClickTime = currentTime
}
) {
// User avatar
val avatarColors = getAvatarColor(accountName, isDarkTheme)
Box(
modifier = Modifier
.size(36.dp)
.clip(CircleShape)
.background(avatarColors.backgroundColor),
contentAlignment = Alignment.Center
) {
Text(
text = getAvatarText(accountPublicKey),
fontSize = 14.sp,
fontWeight = FontWeight.Bold,
color = avatarColors.textColor
)
}
Spacer(modifier = Modifier.width(12.dp))
Spacer(modifier = Modifier.width(12.dp))
// Title with connection status
Column {
Text(
"Rosetta",
fontWeight = FontWeight.Bold,
fontSize = 20.sp
)
if (protocolState != ProtocolState.AUTHENTICATED) {
Text(
text = when (protocolState) {
ProtocolState.DISCONNECTED -> "Connecting..."
ProtocolState.CONNECTING -> "Connecting..."
ProtocolState.CONNECTED -> "Authenticating..."
ProtocolState.HANDSHAKING -> "Authenticating..."
ProtocolState.AUTHENTICATED -> ""
},
fontSize = 12.sp,
color = secondaryTextColor
)
// Title with connection status
Column {
Text(
"Rosetta",
fontWeight = FontWeight.Bold,
fontSize = 20.sp
)
if (protocolState != ProtocolState.AUTHENTICATED) {
Text(
text = when (protocolState) {
ProtocolState.DISCONNECTED -> "Connecting..."
ProtocolState.CONNECTING -> "Connecting..."
ProtocolState.CONNECTED -> "Authenticating..."
ProtocolState.HANDSHAKING -> "Authenticating..."
ProtocolState.AUTHENTICATED -> ""
},
fontSize = 12.sp,
color = secondaryTextColor
)
}
}
}
}
}
},
actions = {
IconButton(onClick = onSearchClick) {
Icon(
Icons.Default.Search,
contentDescription = "Search",
tint = textColor
)
if (!isSearchExpanded) {
IconButton(
onClick = {
isSearchExpanded = true
}
) {
Icon(
Icons.Default.Search,
contentDescription = "Search",
tint = textColor
)
}
}
},
colors = TopAppBarDefaults.topAppBarColors(
@@ -833,7 +882,7 @@ fun ChatItem(
val dividerColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE8E8E8)
val avatarColors = getAvatarColor(chat.name, isDarkTheme)
val initials = getInitials(chat.name)
val avatarText = getAvatarText(chat.publicKey)
Column {
Row(
@@ -852,7 +901,7 @@ fun ChatItem(
contentAlignment = Alignment.Center
) {
Text(
text = initials,
text = avatarText,
fontSize = 20.sp,
fontWeight = FontWeight.SemiBold,
color = avatarColors.textColor