package com.craigvg.lichun_android.ui.screens.messaging.components import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.spring import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowUpward import androidx.compose.material.icons.filled.Bolt import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.craigvg.lichun_android.R import com.craigvg.lichun_android.ui.theme.AppColors import com.craigvg.lichun_android.ui.theme.AppSpacing import com.craigvg.lichun_android.ui.theme.AppTypography import com.craigvg.lichun_android.utils.HapticFeedback /** * Growing text field with send button for chat. * Ported from iOS ExpandableMessageInput.swift */ @Composable fun ExpandableMessageInput( messageInput: String, onMessageChange: (String) -> Unit, onSend: () -> Unit, canSend: Boolean, currentEnergy: Int ) { val view = LocalView.current var isFocused by remember { mutableStateOf(false) } val borderColor by animateColorAsState( targetValue = if (isFocused) AppColors.primary.copy(alpha = 0.25f) else AppColors.secondaryText.copy(alpha = 0.12f), animationSpec = spring(), label = "border" ) Column( modifier = Modifier .fillMaxWidth() .background(AppColors.background) .padding(horizontal = AppSpacing.md, vertical = AppSpacing.sm) ) { // Energy cost indicator Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = AppSpacing.sm, vertical = 2.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.Default.Bolt, contentDescription = null, tint = AppColors.energy, modifier = Modifier.size(16.dp) ) Spacer(modifier = Modifier.width(4.dp)) Text( text = stringResource(R.string.energy_per_message), style = AppTypography.caption, color = AppColors.secondaryText ) } Text( text = "$currentEnergy", style = AppTypography.captionBold, color = if (currentEnergy >= 10) AppColors.energy else AppColors.error ) } Spacer(modifier = Modifier.height(AppSpacing.xs)) // Input row Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.Bottom ) { OutlinedTextField( value = messageInput, onValueChange = onMessageChange, placeholder = { Text( text = stringResource(R.string.type_a_message), color = AppColors.disabledText ) }, modifier = Modifier .weight(1f) .onFocusChanged { isFocused = it.isFocused }, shape = RoundedCornerShape(20.dp), colors = OutlinedTextFieldDefaults.colors( focusedBorderColor = borderColor, unfocusedBorderColor = borderColor, focusedContainerColor = AppColors.surfaceElevated, unfocusedContainerColor = AppColors.surfaceElevated ), maxLines = 4 ) Spacer(modifier = Modifier.width(AppSpacing.sm)) // Send button val sendEnabled = canSend && messageInput.isNotBlank() IconButton( onClick = { if (sendEnabled) { HapticFeedback.medium(view) onSend() } }, enabled = sendEnabled, modifier = Modifier .size(44.dp) .clip(CircleShape) .background( if (sendEnabled) Brush.linearGradient(listOf(AppColors.primary, AppColors.accent)) else Brush.linearGradient(listOf(AppColors.disabledText, AppColors.disabledText)), CircleShape ) ) { Icon( imageVector = Icons.Default.ArrowUpward, contentDescription = stringResource(R.string.send), tint = Color.White, modifier = Modifier.size(18.dp) ) } } } }