Refactor code structure for improved readability and maintainability

This commit is contained in:
2026-01-17 01:50:10 +05:00
parent 97eac22879
commit 14ea9e6996
6 changed files with 139 additions and 78 deletions

View File

@@ -810,6 +810,9 @@ fun ChatDetailScreen(
// Кнопка меню - открывает bottom sheet
IconButton(
onClick = {
// Закрываем клавиатуру перед открытием меню
keyboardController?.hide()
focusManager.clearFocus()
showMenu = true
},
modifier = Modifier
@@ -1087,11 +1090,15 @@ fun ChatDetailScreen(
verticalArrangement = Arrangement.Center
) {
if (isSavedMessages) {
Icon(
Icons.Default.Bookmark,
contentDescription = null,
tint = secondaryTextColor.copy(alpha = 0.5f),
modifier = Modifier.size(64.dp)
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.saved))
val progress by animateLottieCompositionAsState(
composition = composition,
iterations = LottieConstants.IterateForever
)
LottieAnimation(
composition = composition,
progress = { progress },
modifier = Modifier.size(120.dp)
)
} else {
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.speech))

View File

@@ -704,84 +704,113 @@ fun ChatsListScreen(
val requestsCount by chatsViewModel.requestsCount.collectAsState()
val requests by chatsViewModel.requests.collectAsState()
if (showRequestsScreen) {
// 📬 Show Requests Screen
RequestsScreen(
requests = requests,
isDarkTheme = isDarkTheme,
onBack = { showRequestsScreen = false },
onRequestClick = { request ->
showRequestsScreen = false
val user = chatsViewModel.dialogToSearchUser(request)
onUserSelect(user)
// 🎬 Animated content transition between main list and requests
AnimatedContent(
targetState = showRequestsScreen,
transitionSpec = {
if (targetState) {
// Переход на Requests: slide in from right + fade
(slideInHorizontally(
animationSpec = tween(300, easing = FastOutSlowInEasing),
initialOffsetX = { it }
) + fadeIn(tween(300))) togetherWith
(slideOutHorizontally(
animationSpec = tween(300, easing = FastOutSlowInEasing),
targetOffsetX = { -it / 3 }
) + fadeOut(tween(200)))
} else {
// Возврат из Requests: slide out to right
(slideInHorizontally(
animationSpec = tween(300, easing = FastOutSlowInEasing),
initialOffsetX = { -it / 3 }
) + fadeIn(tween(300))) togetherWith
(slideOutHorizontally(
animationSpec = tween(300, easing = FastOutSlowInEasing),
targetOffsetX = { it }
) + fadeOut(tween(200)))
}
)
} else if (dialogsList.isEmpty() && requestsCount == 0) {
// Empty state with Lottie animation
EmptyChatsState(
},
label = "RequestsTransition"
) { isRequestsScreen ->
if (isRequestsScreen) {
// 📬 Show Requests Screen
RequestsScreen(
requests = requests,
isDarkTheme = isDarkTheme,
modifier = Modifier.fillMaxSize()
)
} else {
// Show dialogs list
val dividerColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE8E8E8)
LazyColumn(modifier = Modifier.fillMaxSize()) {
// 📬 Requests Section
if (requestsCount > 0) {
item(key = "requests_section") {
RequestsSection(
count = requestsCount,
isDarkTheme = isDarkTheme,
onClick = { showRequestsScreen = true }
)
Divider(
color = dividerColor,
thickness = 0.5.dp
)
onBack = { showRequestsScreen = false },
onRequestClick = { request ->
showRequestsScreen = false
val user = chatsViewModel.dialogToSearchUser(request)
onUserSelect(user)
}
}
)
} else if (dialogsList.isEmpty() && requestsCount == 0) {
// Empty state with Lottie animation
EmptyChatsState(
isDarkTheme = isDarkTheme,
modifier = Modifier.fillMaxSize()
)
} else {
// Show dialogs list
val dividerColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE8E8E8)
items(dialogsList, key = { it.opponentKey }) { dialog ->
val isSavedMessages = dialog.opponentKey == accountPublicKey
// Check if user is blocked
var isBlocked by remember { mutableStateOf(false) }
LaunchedEffect(dialog.opponentKey, blocklistUpdateTrigger) {
isBlocked = chatsViewModel.isUserBlocked(dialog.opponentKey)
LazyColumn(modifier = Modifier.fillMaxSize()) {
// 📬 Requests Section
if (requestsCount > 0) {
item(key = "requests_section") {
RequestsSection(
count = requestsCount,
isDarkTheme = isDarkTheme,
onClick = { showRequestsScreen = true }
)
Divider(
color = dividerColor,
thickness = 0.5.dp
)
}
}
Column {
SwipeableDialogItem(
dialog = dialog,
isDarkTheme = isDarkTheme,
isTyping = typingUsers.contains(dialog.opponentKey),
isBlocked = isBlocked,
isSavedMessages = isSavedMessages,
onClick = {
val user = chatsViewModel.dialogToSearchUser(dialog)
onUserSelect(user)
},
onDelete = {
dialogToDelete = dialog
},
onBlock = {
dialogToBlock = dialog
},
onUnblock = {
dialogToUnblock = dialog
}
)
items(dialogsList, key = { it.opponentKey }) { dialog ->
val isSavedMessages = dialog.opponentKey == accountPublicKey
// Check if user is blocked
var isBlocked by remember { mutableStateOf(false) }
LaunchedEffect(dialog.opponentKey, blocklistUpdateTrigger) {
isBlocked = chatsViewModel.isUserBlocked(dialog.opponentKey)
}
// 🔥 СЕПАРАТОР - линия разделения между диалогами
Divider(
modifier = Modifier.padding(start = 84.dp),
color = dividerColor,
thickness = 0.5.dp
)
Column {
SwipeableDialogItem(
dialog = dialog,
isDarkTheme = isDarkTheme,
isTyping = typingUsers.contains(dialog.opponentKey),
isBlocked = isBlocked,
isSavedMessages = isSavedMessages,
onClick = {
val user = chatsViewModel.dialogToSearchUser(dialog)
onUserSelect(user)
},
onDelete = {
dialogToDelete = dialog
},
onBlock = {
dialogToBlock = dialog
},
onUnblock = {
dialogToUnblock = dialog
}
)
// 🔥 СЕПАРАТОР - линия разделения между диалогами
Divider(
modifier = Modifier.padding(start = 84.dp),
color = dividerColor,
thickness = 0.5.dp
)
}
}
}
}
}
} // Close AnimatedContent
// Console button removed
}