feat: Enhance dialog message deletion logic; ensure correct dialog key calculation and improve UI overlay behavior

This commit is contained in:
k1ngsterr1
2026-01-17 00:39:54 +05:00
parent 1ce7e6498c
commit f71209f3c6
2 changed files with 83 additions and 76 deletions

View File

@@ -1267,10 +1267,17 @@ fun ChatDetailScreen(
showDeleteConfirm = false
scope.launch {
try {
// Вычисляем правильный dialog_key (отсортированная комбинация ключей)
val dialogKey = if (currentUserPublicKey < user.publicKey) {
"$currentUserPublicKey:${user.publicKey}"
} else {
"${user.publicKey}:$currentUserPublicKey"
}
// Удаляем все сообщения из диалога по dialog_key
database.messageDao().deleteDialog(
account = currentUserPublicKey,
dialogKey = user.publicKey
dialogKey = dialogKey
)
// Также пробуем удалить по from/to ключам (на всякий случай)
database.messageDao().deleteMessagesBetweenUsers(
@@ -1404,6 +1411,8 @@ fun ChatDetailScreen(
onDismissRequest = { showMenu = false },
containerColor = if (isDarkTheme) Color(0xFF1C1C1E) else Color.White,
shape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp),
scrimColor = Color.Black.copy(alpha = 0.6f),
windowInsets = WindowInsets(0, 0, 0, 0), // Перекрываем весь экран включая status bar
dragHandle = {
Box(
modifier = Modifier

View File

@@ -202,6 +202,9 @@ fun ChatsListScreen(
// Status dialog state
var showStatusDialog by remember { mutableStateOf(false) }
// 📬 Requests screen state
var showRequestsScreen by remember { mutableStateOf(false) }
// 🔥 Используем rememberSaveable чтобы сохранить состояние при навигации
// Header сразу visible = true, без анимации при возврате из чата
@@ -579,62 +582,88 @@ fun ChatsListScreen(
animationSpec = tween(200)
)
) {
key(isDarkTheme) {
key(isDarkTheme, showRequestsScreen) {
TopAppBar(
navigationIcon = {
IconButton(
onClick = {
scope.launch { drawerState.open() }
}
) {
Icon(
Icons.Default.Menu,
contentDescription = "Menu",
tint = textColor
)
if (showRequestsScreen) {
// Back button for Requests
IconButton(onClick = { showRequestsScreen = false }) {
Icon(
Icons.Default.ArrowBack,
contentDescription = "Back",
tint = PrimaryBlue
)
}
} else {
// Menu button for main screen
IconButton(
onClick = {
scope.launch { drawerState.open() }
}
) {
Icon(
Icons.Default.Menu,
contentDescription = "Menu",
tint = textColor
)
}
}
},
title = {
Row(
verticalAlignment = Alignment.CenterVertically
) {
if (showRequestsScreen) {
// Requests title
Text(
"Rosetta",
"Requests",
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
color = textColor
)
Spacer(modifier = Modifier.width(8.dp))
Box(
modifier = Modifier
.size(10.dp)
.clip(CircleShape)
.background(
when (protocolState) {
ProtocolState.AUTHENTICATED -> Color(0xFF4CAF50)
ProtocolState.CONNECTING, ProtocolState.CONNECTED, ProtocolState.HANDSHAKING -> Color(0xFFFFC107)
ProtocolState.DISCONNECTED -> Color(0xFFF44336)
}
)
.clickable { showStatusDialog = true }
)
} else {
// Rosetta title with status
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(
"Rosetta",
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
color = textColor
)
Spacer(modifier = Modifier.width(8.dp))
Box(
modifier = Modifier
.size(10.dp)
.clip(CircleShape)
.background(
when (protocolState) {
ProtocolState.AUTHENTICATED -> Color(0xFF4CAF50)
ProtocolState.CONNECTING, ProtocolState.CONNECTED, ProtocolState.HANDSHAKING -> Color(0xFFFFC107)
ProtocolState.DISCONNECTED -> Color(0xFFF44336)
}
)
.clickable { showStatusDialog = true }
)
}
}
},
actions = {
IconButton(
onClick = {
if (protocolState == ProtocolState.AUTHENTICATED) {
onSearchClick()
}
},
enabled = protocolState == ProtocolState.AUTHENTICATED
) {
Icon(
Icons.Default.Search,
contentDescription = "Search",
tint = if (protocolState == ProtocolState.AUTHENTICATED)
textColor else textColor.copy(alpha = 0.5f)
)
// Search only on main screen
if (!showRequestsScreen) {
IconButton(
onClick = {
if (protocolState == ProtocolState.AUTHENTICATED) {
onSearchClick()
}
},
enabled = protocolState == ProtocolState.AUTHENTICATED
) {
Icon(
Icons.Default.Search,
contentDescription = "Search",
tint = if (protocolState == ProtocolState.AUTHENTICATED)
textColor else textColor.copy(alpha = 0.5f)
)
}
}
},
colors = TopAppBarDefaults.topAppBarColors(
@@ -669,9 +698,6 @@ fun ChatsListScreen(
},
containerColor = backgroundColor
) { paddingValues ->
// 📬 State for showing requests screen
var showRequestsScreen by remember { mutableStateOf(false) }
// Main content
Box(modifier = Modifier.fillMaxSize().padding(paddingValues)) {
// 📬 Requests count from ViewModel
@@ -1537,9 +1563,8 @@ fun RequestsSection(
}
/**
* 📬 Экран со списком Requests
* 📬 Экран со списком Requests (без хедера - хедер в основном TopAppBar)
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RequestsScreen(
requests: List<DialogUiModel>,
@@ -1548,7 +1573,6 @@ fun RequestsScreen(
onRequestClick: (DialogUiModel) -> Unit
) {
val backgroundColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFFFFFFF)
val textColor = if (isDarkTheme) Color.White else Color.Black
val dividerColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE8E8E8)
Column(
@@ -1556,32 +1580,6 @@ fun RequestsScreen(
.fillMaxSize()
.background(backgroundColor)
) {
// Header
TopAppBar(
navigationIcon = {
IconButton(onClick = onBack) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Back",
tint = PrimaryBlue
)
}
},
title = {
Text(
text = "Requests",
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
color = textColor
)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = backgroundColor
)
)
Divider(color = dividerColor, thickness = 0.5.dp)
if (requests.isEmpty()) {
// Empty state
Box(