feat: Add Lottie animation for avatar in attachment UI and refactor file layout by removing search functionality

This commit is contained in:
2026-02-22 18:32:03 +05:00
parent 14ab10a1a0
commit 290143dfc4
5 changed files with 35 additions and 81 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
package com.rosetta.messenger package com.rosetta.messenger
import android.app.Application import android.app.Application
import com.airbnb.lottie.L
import com.rosetta.messenger.data.DraftManager import com.rosetta.messenger.data.DraftManager
import com.rosetta.messenger.utils.CrashReportManager import com.rosetta.messenger.utils.CrashReportManager
@@ -16,6 +17,8 @@ class RosettaApplication : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
// Убираем красную букву "L" от Lottie
L.setTraceEnabled(false)
// Инициализируем crash reporter // Инициализируем crash reporter
initCrashReporting() initCrashReporting()

View File

@@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -11,7 +12,11 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.rosetta.messenger.ui.icons.TelegramIcons import com.airbnb.lottie.compose.LottieAnimation
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.LottieConstants
import com.airbnb.lottie.compose.animateLottieCompositionAsState
import com.airbnb.lottie.compose.rememberLottieComposition
import com.rosetta.messenger.ui.onboarding.PrimaryBlue import com.rosetta.messenger.ui.onboarding.PrimaryBlue
/** /**
@@ -27,6 +32,12 @@ internal fun AttachAlertAvatarLayout(
val textColor = if (isDarkTheme) Color.White else Color.Black val textColor = if (isDarkTheme) Color.White else Color.Black
val secondaryTextColor = Color(0xFF8E8E93) val secondaryTextColor = Color(0xFF8E8E93)
val composition by rememberLottieComposition(LottieCompositionSpec.Asset("lottie/avatar.json"))
val progress by animateLottieCompositionAsState(
composition = composition,
iterations = LottieConstants.IterateForever
)
Box( Box(
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
@@ -35,11 +46,10 @@ internal fun AttachAlertAvatarLayout(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(32.dp) modifier = Modifier.padding(32.dp)
) { ) {
Icon( LottieAnimation(
painter = TelegramIcons.Contact, composition = composition,
contentDescription = null, progress = { progress },
tint = PrimaryBlue, modifier = Modifier.size(100.dp)
modifier = Modifier.size(72.dp)
) )
Spacer(modifier = Modifier.height(20.dp)) Spacer(modifier = Modifier.height(20.dp))
Text( Text(

View File

@@ -14,7 +14,6 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -106,8 +105,6 @@ internal fun AttachAlertFileLayout(
var currentDir by remember { mutableStateOf<File?>(null) } var currentDir by remember { mutableStateOf<File?>(null) }
var currentTitle by remember { mutableStateOf("Select File") } var currentTitle by remember { mutableStateOf("Select File") }
var history by remember { mutableStateOf(listOf<HistoryEntry>()) } var history by remember { mutableStateOf(listOf<HistoryEntry>()) }
var searchQuery by remember { mutableStateOf("") }
var isSearching by remember { mutableStateOf(false) }
// ── Gallery mode state ── // ── Gallery mode state ──
var showGallery by remember { mutableStateOf(false) } var showGallery by remember { mutableStateOf(false) }
@@ -127,11 +124,8 @@ internal fun AttachAlertFileLayout(
} else emptyList() } else emptyList()
} }
// ── Search filter ── val displayedRecentFiles = recentFiles
val displayedRecentFiles = if (searchQuery.isBlank()) recentFiles val displayedDirContents = dirContents
else recentFiles.filter { it.name.contains(searchQuery, ignoreCase = true) }
val displayedDirContents = if (searchQuery.isBlank()) dirContents
else dirContents.filter { it.name.contains(searchQuery, ignoreCase = true) }
// ── Back handler ── // ── Back handler ──
val isAtRoot = currentDir == null val isAtRoot = currentDir == null
@@ -146,8 +140,6 @@ internal fun AttachAlertFileLayout(
currentDir = null currentDir = null
currentTitle = "Select File" currentTitle = "Select File"
} }
searchQuery = ""
isSearching = false
} }
fun navigateToDir(dir: File) { fun navigateToDir(dir: File) {
@@ -155,8 +147,6 @@ internal fun AttachAlertFileLayout(
history = history + HistoryEntry(currentDir ?: Environment.getExternalStorageDirectory(), currentTitle) history = history + HistoryEntry(currentDir ?: Environment.getExternalStorageDirectory(), currentTitle)
currentDir = dir currentDir = dir
currentTitle = dir.name currentTitle = dir.name
searchQuery = ""
isSearching = false
} }
if (showGallery) { if (showGallery) {
@@ -182,8 +172,6 @@ internal fun AttachAlertFileLayout(
FilePickerTopBar( FilePickerTopBar(
title = displayTitle, title = displayTitle,
showBack = showGallery || !isAtRoot, showBack = showGallery || !isAtRoot,
isSearching = isSearching,
searchQuery = searchQuery,
onBackClick = { onBackClick = {
if (showGallery) { if (showGallery) {
showGallery = false showGallery = false
@@ -192,8 +180,6 @@ internal fun AttachAlertFileLayout(
navigateBack() navigateBack()
} }
}, },
onSearchToggle = { isSearching = !isSearching; if (!isSearching) searchQuery = "" },
onSearchQueryChange = { searchQuery = it },
textColor = textColor, textColor = textColor,
bgColor = bgColor bgColor = bgColor
) )
@@ -357,7 +343,7 @@ internal fun AttachAlertFileLayout(
} }
) )
} }
} else if (searchQuery.isBlank()) { } else {
item(key = "recent_empty_divider") { item(key = "recent_empty_divider") {
Spacer( Spacer(
modifier = Modifier modifier = Modifier
@@ -390,7 +376,7 @@ internal fun AttachAlertFileLayout(
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Text( Text(
text = if (searchQuery.isNotBlank()) "No results" else "Empty folder", text = "Empty folder",
color = secondaryText, color = secondaryText,
fontSize = 15.sp fontSize = 15.sp
) )
@@ -437,11 +423,7 @@ internal fun AttachAlertFileLayout(
private fun FilePickerTopBar( private fun FilePickerTopBar(
title: String, title: String,
showBack: Boolean, showBack: Boolean,
isSearching: Boolean,
searchQuery: String,
onBackClick: () -> Unit, onBackClick: () -> Unit,
onSearchToggle: () -> Unit,
onSearchQueryChange: (String) -> Unit,
textColor: Color, textColor: Color,
bgColor: Color bgColor: Color
) { ) {
@@ -465,26 +447,6 @@ private fun FilePickerTopBar(
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
} }
if (isSearching) {
TextField(
value = searchQuery,
onValueChange = onSearchQueryChange,
placeholder = {
Text("Search", color = Color(0xFF8E8E93), fontSize = 16.sp)
},
singleLine = true,
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
cursorColor = PrimaryBlue,
focusedTextColor = textColor,
unfocusedTextColor = textColor
),
modifier = Modifier.weight(1f)
)
} else {
Text( Text(
text = title, text = title,
color = textColor, color = textColor,
@@ -495,15 +457,6 @@ private fun FilePickerTopBar(
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) )
} }
IconButton(onClick = onSearchToggle) {
Icon(
imageVector = Icons.Default.Search,
contentDescription = "Search",
tint = textColor
)
}
}
} }
/** Rootlevel special item row (Internal Storage, Rosetta, Gallery) */ /** Rootlevel special item row (Internal Storage, Rosetta, Gallery) */

View File

@@ -675,26 +675,13 @@ fun ImageCollage(
val totalRows = rows.size val totalRows = rows.size
rows.forEachIndexed { rowIndex, rowItems -> rows.forEachIndexed { rowIndex, rowItems ->
val isLastRow = rowIndex == totalRows - 1 val isLastRow = rowIndex == totalRows - 1
val isIncompleteRow = rowItems.size < 3
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = if (isIncompleteRow) horizontalArrangement = Arrangement.spacedBy(spacing)
Arrangement.Start
else
Arrangement.spacedBy(spacing)
) { ) {
rowItems.forEachIndexed { index, attachment -> rowItems.forEachIndexed { index, attachment ->
val isLastItem = isLastRow && index == rowItems.size - 1 val isLastItem = isLastRow && index == rowItems.size - 1
// Для неполных рядов используем фиксированную ширину = 1/3 от общей Box(modifier = Modifier.weight(1f).aspectRatio(1f)) {
val cellModifier = if (isIncompleteRow) {
Modifier
.fillMaxWidth(1f / 3f)
.padding(end = if (index < rowItems.size - 1) spacing else 0.dp)
.aspectRatio(1f)
} else {
Modifier.weight(1f).aspectRatio(1f)
}
Box(modifier = cellModifier) {
ImageAttachment( ImageAttachment(
attachment = attachment, attachment = attachment,
chachaKey = chachaKey, chachaKey = chachaKey,