feat: Update ChatDetailScreen and ChatsListScreen for improved UI responsiveness and consistency; add custom verified badge icon

This commit is contained in:
2026-02-24 20:35:33 +05:00
parent 73ec5d77f4
commit 6643e0e069
17 changed files with 931 additions and 153 deletions

View File

@@ -1935,8 +1935,7 @@ private fun CollapsingOtherProfileHeader(
VerifiedBadge(
verified = if (verified > 0) verified else 1,
size = (nameFontSize.value * 0.8f).toInt(),
isDarkTheme = isDarkTheme,
badgeTint = Color.White
isDarkTheme = isDarkTheme
)
}
}

View File

@@ -1402,8 +1402,7 @@ private fun CollapsingProfileHeader(
VerifiedBadge(
verified = 2,
size = (nameFontSize.value * 0.8f).toInt(),
isDarkTheme = isDarkTheme,
badgeTint = Color.White
isDarkTheme = isDarkTheme
)
}
}

View File

@@ -7,20 +7,21 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import com.rosetta.messenger.ui.icons.TelegramIcons
import compose.icons.TablerIcons
import compose.icons.tablericons.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.rosetta.messenger.BuildConfig
import com.rosetta.messenger.update.UpdateManager
import com.rosetta.messenger.update.UpdateState
import kotlinx.coroutines.launch
@Composable
fun UpdatesScreen(
@@ -28,6 +29,8 @@ fun UpdatesScreen(
onBack: () -> Unit
) {
val view = LocalView.current
val context = LocalContext.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as android.app.Activity).window
@@ -43,8 +46,11 @@ fun UpdatesScreen(
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)
// Handle back gesture
val updateState by UpdateManager.updateState.collectAsState()
val downloadProgress by UpdateManager.downloadProgress.collectAsState()
val coroutineScope = rememberCoroutineScope()
BackHandler { onBack() }
Column(
@@ -87,29 +93,12 @@ fun UpdatesScreen(
.verticalScroll(rememberScrollState())
.padding(16.dp)
) {
// Info Card
Surface(
modifier = Modifier.fillMaxWidth(),
color = Color(0xFF2E7D32).copy(alpha = 0.2f),
shape = RoundedCornerShape(12.dp)
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = "✓ App is up to date",
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
color = Color(0xFF2E7D32)
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "You're using the latest version",
fontSize = 12.sp,
color = secondaryTextColor
)
}
}
// Status Card
UpdateStatusCard(
state = updateState,
progress = downloadProgress,
secondaryTextColor = secondaryTextColor
)
Spacer(modifier = Modifier.height(24.dp))
@@ -168,23 +157,191 @@ fun UpdatesScreen(
Spacer(modifier = Modifier.height(16.dp))
// Check for updates button
Button(
onClick = { /* TODO: Implement update check */ },
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF007AFF)
),
shape = RoundedCornerShape(12.dp)
) {
Text(
text = "Check for Updates",
fontSize = 16.sp,
fontWeight = FontWeight.Medium
)
// Action Button
when (val state = updateState) {
is UpdateState.Idle, is UpdateState.UpToDate, is UpdateState.Checking, is UpdateState.Error -> {
Button(
onClick = {
coroutineScope.launch {
UpdateManager.checkForUpdates()
}
},
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
enabled = state !is UpdateState.Checking,
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF007AFF)
),
shape = RoundedCornerShape(12.dp)
) {
if (state is UpdateState.Checking) {
CircularProgressIndicator(
modifier = Modifier.size(20.dp),
color = Color.White,
strokeWidth = 2.dp
)
Spacer(modifier = Modifier.width(8.dp))
Text("Checking...", fontSize = 16.sp, fontWeight = FontWeight.Medium)
} else {
Text("Check for Updates", fontSize = 16.sp, fontWeight = FontWeight.Medium)
}
}
}
is UpdateState.UpdateAvailable -> {
Button(
onClick = { UpdateManager.downloadAndInstall(context) },
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF34C759)
),
shape = RoundedCornerShape(12.dp)
) {
Icon(
imageVector = TablerIcons.Download,
contentDescription = null,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
"Download ${state.version}",
fontSize = 16.sp,
fontWeight = FontWeight.Medium
)
}
}
is UpdateState.Downloading -> {
Column {
LinearProgressIndicator(
progress = state.progress / 100f,
modifier = Modifier
.fillMaxWidth()
.height(6.dp),
color = Color(0xFF007AFF),
trackColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE0E0E0),
)
Spacer(modifier = Modifier.height(12.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
"Downloading... ${state.progress}%",
fontSize = 14.sp,
color = textColor
)
TextButton(onClick = { UpdateManager.cancelDownload() }) {
Text("Cancel", color = Color(0xFFFF3B30), fontSize = 14.sp)
}
}
}
}
is UpdateState.ReadyToInstall -> {
Button(
onClick = {
UpdateManager.downloadAndInstall(context)
},
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF34C759)
),
shape = RoundedCornerShape(12.dp)
) {
Text(
"Install Update",
fontSize = 16.sp,
fontWeight = FontWeight.Medium
)
}
}
}
}
}
}
@Composable
private fun UpdateStatusCard(
state: UpdateState,
progress: Int,
secondaryTextColor: Color
) {
val (bgColor, iconColor, title, subtitle) = when (state) {
is UpdateState.Idle -> StatusCardData(
bg = Color(0xFF2E7D32).copy(alpha = 0.2f),
icon = Color(0xFF2E7D32),
title = "✓ App is up to date",
subtitle = "You're using the latest version"
)
is UpdateState.UpToDate -> StatusCardData(
bg = Color(0xFF2E7D32).copy(alpha = 0.2f),
icon = Color(0xFF2E7D32),
title = "✓ App is up to date",
subtitle = "You're using the latest version"
)
is UpdateState.Checking -> StatusCardData(
bg = Color(0xFF007AFF).copy(alpha = 0.2f),
icon = Color(0xFF007AFF),
title = "Checking for updates...",
subtitle = "Connecting to update server"
)
is UpdateState.UpdateAvailable -> StatusCardData(
bg = Color(0xFF007AFF).copy(alpha = 0.2f),
icon = Color(0xFF007AFF),
title = "Update available: ${state.version}",
subtitle = "A new version is ready to download"
)
is UpdateState.Downloading -> StatusCardData(
bg = Color(0xFF007AFF).copy(alpha = 0.2f),
icon = Color(0xFF007AFF),
title = "Downloading... $progress%",
subtitle = "Please wait while the update is downloading"
)
is UpdateState.ReadyToInstall -> StatusCardData(
bg = Color(0xFF34C759).copy(alpha = 0.2f),
icon = Color(0xFF34C759),
title = "Ready to install",
subtitle = "Tap the button below to install the update"
)
is UpdateState.Error -> StatusCardData(
bg = Color(0xFFFF3B30).copy(alpha = 0.2f),
icon = Color(0xFFFF3B30),
title = "Update check failed",
subtitle = state.message
)
}
Surface(
modifier = Modifier.fillMaxWidth(),
color = bgColor,
shape = RoundedCornerShape(12.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = title,
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
color = iconColor
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = subtitle,
fontSize = 12.sp,
color = secondaryTextColor
)
}
}
}
private data class StatusCardData(
val bg: Color,
val icon: Color,
val title: String,
val subtitle: String
)