fix: LOCKED UI как в Telegram — CANCEL текст вместо ✕, без blob при lock
Telegram LOCKED layout: [timer] [waveform] [CANCEL] [⏸] [Send] Изменения: - RecordLockedControls: убрана круглая ✕ кнопка delete - Вместо неё: текст "CANCEL" синим bold 15sp (как в Telegram) - Пауза иконка увеличена 12→14dp, фон 15% alpha - Blob анимация скрыта при LOCKED/PAUSED (Telegram: solid circle) - Spacing 8→12dp между CANCEL и паузой Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -781,6 +781,17 @@ private fun VoiceWaveformBar(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Telegram-exact locked recording controls.
|
||||
*
|
||||
* Layout: [CANCEL text-button] [⏸/▶ circle button]
|
||||
*
|
||||
* - CANCEL = blue text (15sp bold, uppercase), clickable — cancels recording
|
||||
* - ⏸ = small circle button (36dp), toggles pause/resume
|
||||
* - No separate delete icon — CANCEL IS delete
|
||||
*
|
||||
* Reference: ChatActivityEnterView recordedAudioPanel + SlideTextView cancelToProgress
|
||||
*/
|
||||
@Composable
|
||||
private fun RecordLockedControls(
|
||||
isPaused: Boolean,
|
||||
@@ -789,37 +800,31 @@ private fun RecordLockedControls(
|
||||
onTogglePause: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val deleteBgColor = if (isDarkTheme) Color(0xFF444444) else Color(0xFFE0E0E0)
|
||||
val deleteIconColor = if (isDarkTheme) Color.White.copy(alpha = 0.8f) else Color(0xFF666666)
|
||||
val pauseBgColor = if (isDarkTheme) Color(0xFF69CCFF).copy(alpha = 0.3f) else Color(0xFF2D9CFF).copy(alpha = 0.2f)
|
||||
val cancelColor = if (isDarkTheme) Color(0xFF69CCFF) else Color(0xFF2D9CFF)
|
||||
val pauseBgColor = if (isDarkTheme) Color(0xFF69CCFF).copy(alpha = 0.15f) else Color(0xFF2D9CFF).copy(alpha = 0.1f)
|
||||
val pauseIconColor = if (isDarkTheme) Color(0xFF69CCFF) else Color(0xFF2D9CFF)
|
||||
|
||||
Row(
|
||||
modifier = modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
// Delete button
|
||||
Box(
|
||||
// CANCEL text button — Telegram: blue bold uppercase
|
||||
Text(
|
||||
text = "CANCEL",
|
||||
color = cancelColor,
|
||||
fontSize = 15.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.clip(CircleShape)
|
||||
.background(deleteBgColor)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = null
|
||||
) { onDelete() },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = "Delete recording",
|
||||
tint = deleteIconColor,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
) { onDelete() }
|
||||
.padding(horizontal = 4.dp, vertical = 8.dp)
|
||||
)
|
||||
|
||||
// Pause/Resume button
|
||||
// Pause/Resume button — circle with icon
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
@@ -832,7 +837,8 @@ private fun RecordLockedControls(
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (isPaused) {
|
||||
Canvas(modifier = Modifier.size(12.dp)) {
|
||||
// Play triangle
|
||||
Canvas(modifier = Modifier.size(14.dp)) {
|
||||
val path = Path().apply {
|
||||
moveTo(size.width * 0.2f, 0f)
|
||||
lineTo(size.width, size.height / 2f)
|
||||
@@ -842,19 +848,20 @@ private fun RecordLockedControls(
|
||||
drawPath(path, color = pauseIconColor)
|
||||
}
|
||||
} else {
|
||||
Canvas(modifier = Modifier.size(12.dp)) {
|
||||
val barW = size.width * 0.25f
|
||||
val gap = size.width * 0.15f
|
||||
// Pause bars
|
||||
Canvas(modifier = Modifier.size(14.dp)) {
|
||||
val barW = size.width * 0.22f
|
||||
val gap = size.width * 0.14f
|
||||
drawRoundRect(
|
||||
color = pauseIconColor,
|
||||
topLeft = Offset(size.width / 2f - gap - barW, 0f),
|
||||
size = androidx.compose.ui.geometry.Size(barW, size.height),
|
||||
topLeft = Offset(size.width / 2f - gap - barW, size.height * 0.1f),
|
||||
size = androidx.compose.ui.geometry.Size(barW, size.height * 0.8f),
|
||||
cornerRadius = androidx.compose.ui.geometry.CornerRadius(barW / 3f)
|
||||
)
|
||||
drawRoundRect(
|
||||
color = pauseIconColor,
|
||||
topLeft = Offset(size.width / 2f + gap, 0f),
|
||||
size = androidx.compose.ui.geometry.Size(barW, size.height),
|
||||
topLeft = Offset(size.width / 2f + gap, size.height * 0.1f),
|
||||
size = androidx.compose.ui.geometry.Size(barW, size.height * 0.8f),
|
||||
cornerRadius = androidx.compose.ui.geometry.CornerRadius(barW / 3f)
|
||||
)
|
||||
}
|
||||
@@ -2240,18 +2247,20 @@ fun MessageInputBar(
|
||||
}
|
||||
}
|
||||
|
||||
// Blob: 48dp base → 1.7x = ~82dp visual (matches Telegram circleRadius 41dp)
|
||||
VoiceButtonBlob(
|
||||
voiceLevel = voiceLevel,
|
||||
isDarkTheme = isDarkTheme,
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.graphicsLayer {
|
||||
scaleX = 1.7f
|
||||
scaleY = 1.7f
|
||||
clip = false
|
||||
}
|
||||
)
|
||||
// Blob: only during RECORDING (Telegram hides waves when locked)
|
||||
if (recordUiState == RecordUiState.RECORDING) {
|
||||
VoiceButtonBlob(
|
||||
voiceLevel = voiceLevel,
|
||||
isDarkTheme = isDarkTheme,
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.graphicsLayer {
|
||||
scaleX = 1.7f
|
||||
scaleY = 1.7f
|
||||
clip = false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Solid circle: 48dp layout, scaled to 82dp visual
|
||||
val sendScale by animateFloatAsState(
|
||||
|
||||
Reference in New Issue
Block a user