feat: Add BlurredAvatarBackground component and integrate it into ChatsListScreen and ProfileScreen

This commit is contained in:
k1ngsterr1
2026-01-24 20:18:27 +05:00
parent 23e1d72ac0
commit dc548a3c7a
8 changed files with 420 additions and 29 deletions

View File

@@ -0,0 +1,107 @@
package com.rosetta.messenger.utils
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color
import android.net.Uri
import androidx.activity.result.ActivityResult
import androidx.core.content.FileProvider
import com.yalantis.ucrop.UCrop
import java.io.File
/**
* Помощник для работы с обрезкой изображений через uCrop
*/
object ImageCropHelper {
private const val CROP_IMAGE_FILE_NAME = "cropped_avatar.png"
/**
* Создает Intent для запуска uCrop
* @param context Контекст
* @param sourceUri URI исходного изображения
* @param isDarkTheme Темная тема
* @return Intent для запуска uCrop Activity
*/
fun createCropIntent(
context: Context,
sourceUri: Uri,
isDarkTheme: Boolean
): Intent {
// Создаем файл для результата crop
val destinationFile = File(context.cacheDir, CROP_IMAGE_FILE_NAME)
val destinationUri = Uri.fromFile(destinationFile)
// Настройки uCrop
val options = UCrop.Options().apply {
// Круглый overlay для аватара
setCircleDimmedLayer(true)
// Показываем сетку
setShowCropGrid(true)
setShowCropFrame(true)
// Цвета в зависимости от темы
if (isDarkTheme) {
setToolbarColor(Color.parseColor("#1A1A1A"))
setStatusBarColor(Color.parseColor("#1A1A1A"))
setActiveControlsWidgetColor(Color.parseColor("#0A84FF"))
setToolbarWidgetColor(Color.WHITE)
setRootViewBackgroundColor(Color.parseColor("#1A1A1A"))
setDimmedLayerColor(Color.parseColor("#CC000000"))
} else {
setToolbarColor(Color.WHITE)
setStatusBarColor(Color.WHITE)
setActiveControlsWidgetColor(Color.parseColor("#007AFF"))
setToolbarWidgetColor(Color.BLACK)
setRootViewBackgroundColor(Color.WHITE)
setDimmedLayerColor(Color.parseColor("#99000000"))
}
// Скрываем кнопку поворота по желанию (можно оставить)
setFreeStyleCropEnabled(false)
// Качество сжатия
setCompressionFormat(Bitmap.CompressFormat.PNG)
setCompressionQuality(100)
// Заголовок
setToolbarTitle("Crop Avatar")
// Скрываем bottom controls если нужно
setHideBottomControls(false)
}
return UCrop.of(sourceUri, destinationUri)
.withAspectRatio(1f, 1f) // Квадратный crop для аватара
.withMaxResultSize(512, 512) // Максимальный размер
.withOptions(options)
.getIntent(context)
}
/**
* Извлекает результат crop из ActivityResult
* @param result Результат Activity
* @return URI обрезанного изображения или null при ошибке/отмене
*/
fun getCroppedImageUri(result: ActivityResult): Uri? {
return if (result.resultCode == Activity.RESULT_OK && result.data != null) {
UCrop.getOutput(result.data!!)
} else {
null
}
}
/**
* Получает ошибку crop если есть
*/
fun getCropError(result: ActivityResult): Throwable? {
return if (result.data != null) {
UCrop.getError(result.data!!)
} else {
null
}
}
}