package com.suno.android.ui.screens.create.text import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.suno.android.common_ui.components.omni.CircleIconButton import com.suno.android.common_ui.components.text_fields.CustomModeInputTextField import com.suno.android.common_ui.theme.ExtendedTheme import kotlinx.coroutines.launch import com.suno.android.common_res.R as CommonResR import com.suno.android.common_ui.R as CommonUIR @Composable fun LyricsInputCard( isInstrumental: Boolean, onInstrumentalCheckChange: (Boolean) -> Unit, lyricsInput: String, onLyricTextInput: (String) -> Unit, enhanceLyricsLoading: Boolean, onEnhanceLyricsClicked: () -> Unit, onResetLyrics: () -> Unit, resetFieldsFlagEnabled: Boolean? = false, onUndo: () -> Unit, canUndo: Boolean = false, ) { var showLyricsBottomSheet by remember { mutableStateOf(false) } val lyricsSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val scope = rememberCoroutineScope() Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors( containerColor = ExtendedTheme.colors.backgroundTertiary, ), shape = MaterialTheme.shapes.small, ) { Column( modifier = Modifier.padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(4.dp), ) { LyricsInputTopRow( isInstrumental = isInstrumental, enhanceLyricsLoading = enhanceLyricsLoading, onEnhanceLyricsClicked = { onEnhanceLyricsClicked.invoke() }, onResetLyrics = { onResetLyrics.invoke() }, resetFieldsFlagEnabled = resetFieldsFlagEnabled, lyricsInput = lyricsInput, canUndo = canUndo, onUndo = onUndo, ) AnimatedContent( targetState = isInstrumental, transitionSpec = { fadeIn() togetherWith fadeOut() }, ) { isInstrumental -> if (isInstrumental) { Text( modifier = Modifier.padding(bottom = 20.dp), text = stringResource(id = CommonResR.string.instrumental_track_lyrics_disabled), style = ExtendedTheme.typography.body, color = ExtendedTheme.colors.foregroundInactive, ) } else { CustomModeInputTextField( modifier = Modifier .height(248.dp) .fillMaxWidth(), disableTextInput = enhanceLyricsLoading, placeHolderText = stringResource(id = CommonResR.string.lyrics_placeholder), inputText = lyricsInput, onValueChange = { lyricsString -> onLyricTextInput.invoke(lyricsString) }, ) } } LyricsInputBottomRow( isInstrumental = isInstrumental, onInstrumentalCheckChange = { onInstrumentalCheckChange.invoke(it) }, onExpandClicked = { scope.launch { lyricsSheetState.show() showLyricsBottomSheet = true } }, ) } } if (showLyricsBottomSheet) { LyricsBottomSheet( sheetState = lyricsSheetState, onDismiss = { scope.launch { lyricsSheetState.hide() showLyricsBottomSheet = false } }, lyricsInput = lyricsInput, onLyricTextInput = onLyricTextInput, enhanceLyricsLoading = enhanceLyricsLoading, onEnhanceLyricsClicked = { onEnhanceLyricsClicked.invoke() }, onResetLyrics = { onResetLyrics.invoke() }, canUndo = canUndo, onUndo = { onUndo.invoke() }, ) } } @Composable fun LyricsInputTopRow( isInstrumental: Boolean, enhanceLyricsLoading: Boolean, onEnhanceLyricsClicked: () -> Unit, onResetLyrics: () -> Unit, resetFieldsFlagEnabled: Boolean? = false, lyricsInput: String, canUndo: Boolean, onUndo: () -> Unit, ) { Row( modifier = Modifier .fillMaxWidth() .padding(top = 12.dp) .height(48.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = stringResource(id = CommonResR.string.lyrics), style = ExtendedTheme.typography.body, color = ExtendedTheme.colors.textPrimary, ) Row( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { AnimatedVisibility( visible = canUndo, enter = fadeIn(), exit = fadeOut(), ) { CircleIconButton( bgColor = ExtendedTheme.colors.backgroundTertiary, vectorDrawableResId = CommonUIR.drawable.refresh, contentDescription = stringResource(CommonResR.string.undo), onClick = { onUndo.invoke() }, ) } if (resetFieldsFlagEnabled == true) { AnimatedVisibility( visible = !lyricsInput.isEmpty() && !isInstrumental, enter = fadeIn(), exit = fadeOut(), ) { CircleIconButton( bgColor = ExtendedTheme.colors.backgroundTertiary, vectorDrawableResId = CommonUIR.drawable.trash, contentDescription = stringResource(CommonResR.string.reset), onClick = { onResetLyrics.invoke() }, ) } } AnimatedVisibility( visible = !isInstrumental, enter = fadeIn(), exit = fadeOut(), ) { CircleIconButton( auraBg = true, enabled = !enhanceLyricsLoading, bgColor = Color.Transparent, iconColor = Color.White, showProgressIndicator = enhanceLyricsLoading, vectorDrawableResId = CommonUIR.drawable.enhance, contentDescription = stringResource(CommonResR.string.enhance), onClick = { onEnhanceLyricsClicked.invoke() }, ) } } } } @Composable fun LyricsInputBottomRow( isInstrumental: Boolean, onInstrumentalCheckChange: (Boolean) -> Unit, onExpandClicked: () -> Unit, ) { Row( modifier = Modifier .fillMaxWidth() .padding(bottom = 12.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.Bottom, ) { InstrumentalToggleButton( label = stringResource(id = CommonResR.string.instrumental), isChecked = isInstrumental, onCheckedChange = { onInstrumentalCheckChange.invoke(it) }, ) AnimatedVisibility( visible = !isInstrumental, enter = fadeIn(), exit = fadeOut(), ) { CircleIconButton( vectorDrawableResId = CommonUIR.drawable.zoom, contentDescription = stringResource(CommonResR.string.expand), onClick = { onExpandClicked.invoke() }, ) } } }