feat: Update avatar behavior in CollapsingProfileHeader to handle presence of avatar for animations and haptic feedback
This commit is contained in:
@@ -751,17 +751,19 @@ private fun CollapsingProfileHeader(
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// 👤 AVATAR - По умолчанию КРУГЛАЯ, при overscroll расширяется до прямоугольника
|
||||
// При collapse - уменьшается и уходит вверх
|
||||
// ТОЛЬКО ЕСЛИ ЕСТЬ АВАТАРКА! Без аватарки всегда круг
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
val circleSize = AVATAR_SIZE_EXPANDED
|
||||
// Зона аватарки = ВСЯ высота header включая статус бар
|
||||
val avatarZoneHeight = EXPANDED_HEADER_HEIGHT + statusBarHeight
|
||||
|
||||
// При overscroll расширяем до прямоугольника на всю зону (только если не collapsed)
|
||||
// При overscroll расширяем до прямоугольника на всю зону (только если не collapsed И есть
|
||||
// аватарка)
|
||||
val avatarWidth: Dp
|
||||
val avatarHeight: Dp
|
||||
|
||||
if (collapseProgress < 0.1f && expansionProgress > 0f) {
|
||||
// Overscroll: круг -> прямоугольник на всю зону ВКЛЮЧАЯ статус бар
|
||||
if (hasAvatar && collapseProgress < 0.1f && expansionProgress > 0f) {
|
||||
// Overscroll: круг -> прямоугольник на всю зону ВКЛЮЧАЯ статус бар (ТОЛЬКО С АВАТАРКОЙ)
|
||||
avatarWidth = androidx.compose.ui.unit.lerp(circleSize, screenWidthDp, expansionProgress)
|
||||
avatarHeight =
|
||||
androidx.compose.ui.unit.lerp(circleSize, avatarZoneHeight, expansionProgress)
|
||||
@@ -783,8 +785,8 @@ private fun CollapsingProfileHeader(
|
||||
val topAvatarY = 0.dp // От самого верха экрана при полном expansion
|
||||
|
||||
val avatarY =
|
||||
if (collapseProgress < 0.1f && expansionProgress > 0f) {
|
||||
// При overscroll прижимаемся к самому верху
|
||||
if (hasAvatar && collapseProgress < 0.1f && expansionProgress > 0f) {
|
||||
// При overscroll прижимаемся к самому верху (ТОЛЬКО С АВАТАРКОЙ)
|
||||
androidx.compose.ui.unit.lerp(defaultCenterY, topAvatarY, expansionProgress)
|
||||
} else {
|
||||
// Collapse: сразу начинаем уходить вверх
|
||||
@@ -795,9 +797,10 @@ private fun CollapsingProfileHeader(
|
||||
)
|
||||
}
|
||||
|
||||
// Закругление: круг по умолчанию, при overscroll становится квадратом БЕЗ скругления
|
||||
// Закругление: круг по умолчанию, при overscroll становится квадратом БЕЗ скругления (ТОЛЬКО С
|
||||
// АВАТАРКОЙ)
|
||||
val cornerRadius =
|
||||
if (collapseProgress < 0.1f && expansionProgress > 0f) {
|
||||
if (hasAvatar && collapseProgress < 0.1f && expansionProgress > 0f) {
|
||||
// Overscroll: круг -> квадрат без скругления
|
||||
androidx.compose.ui.unit.lerp(avatarSize / 2, 0.dp, expansionProgress)
|
||||
} else {
|
||||
@@ -805,12 +808,12 @@ private fun CollapsingProfileHeader(
|
||||
avatarSize / 2
|
||||
}
|
||||
|
||||
// Haptic feedback при достижении полного квадрата
|
||||
// Haptic feedback при достижении полного квадрата (ТОЛЬКО С АВАТАРКОЙ)
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
var hasTriggeredHaptic by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(expansionProgress) {
|
||||
if (expansionProgress >= 0.95f && !hasTriggeredHaptic) {
|
||||
LaunchedEffect(expansionProgress, hasAvatar) {
|
||||
if (hasAvatar && expansionProgress >= 0.95f && !hasTriggeredHaptic) {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
hasTriggeredHaptic = true
|
||||
} else if (expansionProgress < 0.5f) {
|
||||
@@ -846,36 +849,44 @@ private fun CollapsingProfileHeader(
|
||||
)
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// 👤 AVATAR - Круг по умолчанию, квадрат при overscroll
|
||||
// 👤 AVATAR - Круг по умолчанию, квадрат при overscroll (ТОЛЬКО С АВАТАРКОЙ)
|
||||
// Без аватарки - всегда круглый placeholder как в sidebar
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
if (avatarSize > 1.dp) {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.offset(x = avatarX, y = avatarY)
|
||||
.size(width = avatarWidth, height = avatarHeight)
|
||||
.clip(RoundedCornerShape(cornerRadius)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (avatarRepository != null) {
|
||||
FullSizeAvatar(
|
||||
publicKey = publicKey,
|
||||
avatarRepository = avatarRepository,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
} else {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.fillMaxSize().background(avatarColors.backgroundColor),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (avatarFontSize > 1.sp) {
|
||||
Text(
|
||||
text = getInitials(name),
|
||||
fontSize = avatarFontSize,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = avatarColors.textColor
|
||||
)
|
||||
}
|
||||
if (hasAvatar) {
|
||||
// С аватаркой - расширяется до квадрата
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.offset(x = avatarX, y = avatarY)
|
||||
.size(width = avatarWidth, height = avatarHeight)
|
||||
.clip(RoundedCornerShape(cornerRadius)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (avatarRepository != null) {
|
||||
FullSizeAvatar(
|
||||
publicKey = publicKey,
|
||||
avatarRepository = avatarRepository,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Без аватарки - ВСЕГДА круглый placeholder как в sidebar
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.offset(x = avatarX, y = avatarY)
|
||||
.size(avatarSize)
|
||||
.clip(CircleShape)
|
||||
.background(avatarColors.backgroundColor),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (avatarFontSize > 1.sp) {
|
||||
Text(
|
||||
text = getInitials(name),
|
||||
fontSize = avatarFontSize,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = avatarColors.textColor
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -984,7 +995,7 @@ private fun CollapsingProfileHeader(
|
||||
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
|
||||
Text(text = "online", fontSize = onlineFontSize, color = Color(0xFF4CAF50))
|
||||
Text(text = "online", fontSize = onlineFontSize, color = Color.White)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user