feat: Update version to 1.0.6 and enhance release notes with new features and improvements

This commit is contained in:
2026-02-24 09:02:39 +05:00
parent fba95c0516
commit 73ec5d77f4
11 changed files with 275 additions and 111 deletions

View File

@@ -353,7 +353,7 @@ private fun ProfileBlurPreview(
if (decoded != null) {
avatarBitmap = decoded
blurredBitmap = withContext(Dispatchers.Default) {
appearanceGaussianBlur(blurContext, decoded, radius = 25f, passes = 3)
appearanceGaussianBlur(blurContext, decoded, radius = 20f, passes = 2)
}
}
} else {
@@ -373,15 +373,17 @@ private fun ProfileBlurPreview(
.height(280.dp + statusBarHeight)
) {
// ═══════════════════════════════════════════════════
// LAYER 1: Blurred avatar background (как в профиле)
// LAYER 1: Blurred avatar background (идентично BlurredAvatarBackground)
// ═══════════════════════════════════════════════════
if (blurredBitmap != null) {
// overlay-режим: 0.85f, стандартный: 0.9f (как в BlurredAvatarBackground)
val blurImgAlpha = if (overlayColors != null && overlayColors.isNotEmpty()) 0.85f else 0.9f
Image(
bitmap = blurredBitmap!!.asImageBitmap(),
contentDescription = null,
modifier = Modifier
.fillMaxSize()
.graphicsLayer { alpha = 0.35f },
.graphicsLayer { alpha = blurImgAlpha },
contentScale = ContentScale.Crop
)
}
@@ -400,25 +402,25 @@ private fun ProfileBlurPreview(
val overlayMod = if (overlayColors.size == 1) {
Modifier
.fillMaxSize()
.background(overlayColors[0].copy(alpha = if (blurredBitmap != null) 0.55f else 0.85f))
.background(overlayColors[0].copy(alpha = if (blurredBitmap != null) 0.4f else 0.85f))
} else {
Modifier
.fillMaxSize()
.background(
Brush.linearGradient(
colors = overlayColors.map {
it.copy(alpha = if (blurredBitmap != null) 0.55f else 0.85f)
it.copy(alpha = if (blurredBitmap != null) 0.4f else 0.85f)
}
)
)
}
Box(modifier = overlayMod)
} else if (blurredBitmap != null) {
// Стандартный затемняющий overlay (как в профиле)
// Стандартный тинт (идентичен BlurredAvatarBackground)
Box(
modifier = Modifier
.fillMaxSize()
.background(avatarColors.backgroundColor.copy(alpha = 0.3f))
.background(avatarColors.backgroundColor.copy(alpha = 0.12f))
)
} else {
// Нет аватарки и нет overlay — fallback цвет
@@ -432,18 +434,17 @@ private fun ProfileBlurPreview(
}
// ═══════════════════════════════════════════════════
// LAYER 3: Тонкий нижний градиент-затемнение
// LAYER 3: Нижний градиент (идентичен BlurredAvatarBackground)
// ═══════════════════════════════════════════════════
Box(
modifier = Modifier
.fillMaxWidth()
.height(80.dp)
.align(Alignment.BottomCenter)
.fillMaxSize()
.background(
Brush.verticalGradient(
colors = listOf(
Color.Transparent,
Color.Black.copy(alpha = 0.35f)
Color.Transparent,
Color.Black.copy(alpha = if (selectedId == "none") 0f else 0.2f)
)
)
)
@@ -731,13 +732,37 @@ private fun ColorCircleItem(
/**
* Proper Gaussian blur via RenderScript — smooth, non-pixelated.
* Mirrors edges to eliminate banding artifacts.
*/
@Suppress("deprecation")
private fun appearanceGaussianBlur(context: Context, source: Bitmap, radius: Float = 25f, passes: Int = 3): Bitmap {
val w = (source.width / 4).coerceAtLeast(8)
val h = (source.height / 4).coerceAtLeast(8)
var current = Bitmap.createScaledBitmap(source, w, h, true)
.copy(Bitmap.Config.ARGB_8888, true)
private fun appearanceGaussianBlur(context: Context, source: Bitmap, radius: Float = 20f, passes: Int = 2): Bitmap {
val w = (source.width / 3).coerceAtLeast(32)
val h = (source.height / 3).coerceAtLeast(32)
val scaled = Bitmap.createScaledBitmap(source, w, h, true)
// Pad with mirrored edges to eliminate edge banding
val pad = (radius * passes).toInt().coerceAtLeast(8)
val paddedW = w + pad * 2
val paddedH = h + pad * 2
val padded = Bitmap.createBitmap(paddedW, paddedH, Bitmap.Config.ARGB_8888)
val canvas = android.graphics.Canvas(padded)
canvas.drawBitmap(scaled, pad.toFloat(), pad.toFloat(), null)
for (x in 0 until pad) {
for (y in 0 until h) {
padded.setPixel(x, y + pad, scaled.getPixel((pad - x - 1).coerceIn(0, w - 1), y))
padded.setPixel(paddedW - 1 - x, y + pad, scaled.getPixel((w - 1 - x.coerceIn(0, w - 1)), y))
}
}
for (y in 0 until pad) {
for (x in 0 until paddedW) {
val srcX = (x - pad).coerceIn(0, w - 1)
padded.setPixel(x, y, scaled.getPixel(srcX, (pad - y - 1).coerceIn(0, h - 1)))
padded.setPixel(x, paddedH - 1 - y, scaled.getPixel(srcX, (h - 1 - y.coerceIn(0, h - 1))))
}
}
var current = padded.copy(Bitmap.Config.ARGB_8888, true)
val rs = RenderScript.create(context)
val blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
@@ -755,6 +780,6 @@ private fun appearanceGaussianBlur(context: Context, source: Bitmap, radius: Flo
blur.destroy()
rs.destroy()
return current
return Bitmap.createBitmap(current, pad, pad, w, h)
}

View File

@@ -1936,7 +1936,7 @@ private fun CollapsingOtherProfileHeader(
verified = if (verified > 0) verified else 1,
size = (nameFontSize.value * 0.8f).toInt(),
isDarkTheme = isDarkTheme,
badgeTint = if (isRosettaOfficial) rosettaBadgeBlue else null
badgeTint = Color.White
)
}
}

View File

@@ -1403,7 +1403,7 @@ private fun CollapsingProfileHeader(
verified = 2,
size = (nameFontSize.value * 0.8f).toInt(),
isDarkTheme = isDarkTheme,
badgeTint = rosettaBadgeBlue
badgeTint = Color.White
)
}
}