feat: simplify color handling in ChatsListScreen and improve gesture callbacks in SwipeableDialogItem
This commit is contained in:
@@ -38,37 +38,63 @@ fun BoxScope.BlurredAvatarBackground(
|
||||
avatarRepository: AvatarRepository?,
|
||||
fallbackColor: Color,
|
||||
blurRadius: Float = 25f,
|
||||
alpha: Float = 0.3f,
|
||||
overlayColors: List<Color>? = null
|
||||
alpha: Float = 0.9f,
|
||||
overlayColors: List<Color>? = null,
|
||||
isDarkTheme: Boolean = true
|
||||
) {
|
||||
// Получаем аватары из репозитория
|
||||
val avatars by avatarRepository?.getAvatars(publicKey, allDecode = false)?.collectAsState()
|
||||
// В светлой теме: если дефолтный фон (avatar) — синий как шапка chat list,
|
||||
// если выбран кастомный цвет в Appearance — используем его
|
||||
if (!isDarkTheme) {
|
||||
val lightBgModifier = if (overlayColors != null && overlayColors.isNotEmpty()) {
|
||||
if (overlayColors.size == 1) {
|
||||
Modifier.matchParentSize().background(overlayColors[0])
|
||||
} else {
|
||||
Modifier.matchParentSize().background(
|
||||
Brush.linearGradient(colors = overlayColors)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Modifier.matchParentSize().background(Color(0xFF0D8CF4))
|
||||
}
|
||||
Box(modifier = lightBgModifier)
|
||||
return
|
||||
}
|
||||
|
||||
// Если выбран цвет в Appearance — просто сплошной цвет/градиент, без blur
|
||||
if (overlayColors != null && overlayColors.isNotEmpty()) {
|
||||
val bgModifier = if (overlayColors.size == 1) {
|
||||
Modifier.matchParentSize().background(overlayColors[0])
|
||||
} else {
|
||||
Modifier.matchParentSize().background(
|
||||
Brush.linearGradient(colors = overlayColors)
|
||||
)
|
||||
}
|
||||
Box(modifier = bgModifier)
|
||||
return
|
||||
}
|
||||
|
||||
// Нет фона (avatar default) — blur аватарки
|
||||
val avatars by avatarRepository?.getAvatars(publicKey, allDecode = false)?.collectAsState()
|
||||
?: remember { mutableStateOf(emptyList()) }
|
||||
|
||||
// Состояние для bitmap и размытого bitmap
|
||||
|
||||
var originalBitmap by remember(avatars) { mutableStateOf<Bitmap?>(null) }
|
||||
var blurredBitmap by remember(avatars) { mutableStateOf<Bitmap?>(null) }
|
||||
|
||||
// Декодируем и размываем аватар
|
||||
|
||||
LaunchedEffect(avatars) {
|
||||
if (avatars.isNotEmpty()) {
|
||||
originalBitmap = withContext(Dispatchers.IO) {
|
||||
AvatarFileManager.base64ToBitmap(avatars.first().base64Data)
|
||||
}
|
||||
|
||||
// Размываем bitmap (уменьшаем для производительности, затем применяем blur)
|
||||
originalBitmap?.let { bitmap ->
|
||||
blurredBitmap = withContext(Dispatchers.Default) {
|
||||
// Уменьшаем размер для быстрого blur
|
||||
val scaledBitmap = Bitmap.createScaledBitmap(
|
||||
bitmap,
|
||||
bitmap.width / 4,
|
||||
bitmap.height / 4,
|
||||
true
|
||||
)
|
||||
// Применяем blur несколько раз для более гладкого эффекта
|
||||
var result = scaledBitmap
|
||||
repeat(3) {
|
||||
repeat(2) {
|
||||
result = fastBlur(result, (blurRadius / 4).toInt().coerceAtLeast(1))
|
||||
}
|
||||
result
|
||||
@@ -79,71 +105,22 @@ fun BoxScope.BlurredAvatarBackground(
|
||||
blurredBitmap = null
|
||||
}
|
||||
}
|
||||
|
||||
// Используем matchParentSize() чтобы занимать только размер родителя
|
||||
|
||||
Box(modifier = Modifier.matchParentSize()) {
|
||||
if (blurredBitmap != null) {
|
||||
// Показываем размытое изображение
|
||||
Image(
|
||||
bitmap = blurredBitmap!!.asImageBitmap(),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
this.alpha = alpha
|
||||
},
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
|
||||
// Дополнительный overlay — кастомный или стандартный
|
||||
if (overlayColors != null && overlayColors.isNotEmpty()) {
|
||||
// Кастомный цветной overlay
|
||||
val overlayModifier = if (overlayColors.size == 1) {
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.background(overlayColors[0].copy(alpha = 0.55f))
|
||||
} else {
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
Brush.linearGradient(
|
||||
colors = overlayColors.map { it.copy(alpha = 0.55f) }
|
||||
)
|
||||
)
|
||||
}
|
||||
Box(modifier = overlayModifier)
|
||||
} else {
|
||||
// Стандартный overlay для затемнения
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(fallbackColor.copy(alpha = 0.3f))
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Fallback: когда нет аватарки
|
||||
if (overlayColors != null && overlayColors.isNotEmpty()) {
|
||||
// Кастомный фон без blur
|
||||
val bgModifier = if (overlayColors.size == 1) {
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.background(overlayColors[0])
|
||||
} else {
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
Brush.linearGradient(colors = overlayColors)
|
||||
)
|
||||
}
|
||||
Box(modifier = bgModifier)
|
||||
} else {
|
||||
// Стандартный fallback: цветной фон
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(fallbackColor)
|
||||
)
|
||||
}
|
||||
// Нет фото — цвет аватарки
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(fallbackColor)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user