package com.suno.android.common_ui.effects import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.key import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember 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.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.suno.android.common_core_utils.global_errors.DialogSpec import com.suno.android.common_core_utils.global_errors.DialogSpec.Button.DialogButtonType import com.suno.android.common_core_utils.model.UiString import com.suno.android.common_ui.components.preview.SunoPreview import com.suno.android.common_ui.models.text import com.suno.android.common_ui.theme.ExtendedTheme import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.Flow @Composable fun DialogEffect( dialogFlow: Flow, ) { var dialogs by remember { mutableStateOf(persistentListOf()) } LaunchedEffect(dialogFlow) { dialogFlow.collect { newDialog -> dialogs = dialogs.add(newDialog) } } dialogs.forEach { dialog -> SunoErrorDialog( spec = dialog, onDismissRequest = { dialogs = dialogs.filter { it.id != dialog.id }.toPersistentList() }, ) } } @Composable fun SunoErrorDialog( spec: DialogSpec, onDismissRequest: () -> Unit, ) { Dialog( onDismissRequest = onDismissRequest, properties = DialogProperties( usePlatformDefaultWidth = false, ), ) { Card( modifier = Modifier.padding(16.dp), ) { Column( modifier = Modifier.padding(24.dp), ) { spec.title?.let { title -> Text( text = title.text(), style = ExtendedTheme.typography.categoryHeadline, ) Spacer(Modifier.height(16.dp)) } Text( text = spec.body.text(), style = ExtendedTheme.typography.body, modifier = Modifier .weight(1f, false) .verticalScroll( state = rememberScrollState(), ), ) if (spec.buttons.isNotEmpty()) { Spacer(Modifier.height(24.dp)) } FlowRow( modifier = Modifier.align(Alignment.End), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { spec.buttons.forEach { key(it) { TextButton( modifier = Modifier.height(48.dp), onClick = { it.onClick.invoke( /*dismiss =*/ onDismissRequest, ) }, colors = ButtonDefaults.textButtonColors( contentColor = when (it.type) { DialogButtonType.DEFAULT -> ExtendedTheme.colors.textSecondary DialogButtonType.PRIMARY -> ExtendedTheme.colors.backgroundPrimary DialogButtonType.WARNING -> ExtendedTheme.colors.warning }, containerColor = when (it.type) { DialogButtonType.DEFAULT -> Color.Transparent DialogButtonType.PRIMARY -> ExtendedTheme.colors.backgroundInvert DialogButtonType.WARNING -> Color.Transparent }, ), shape = when (it.type) { DialogButtonType.DEFAULT -> ButtonDefaults.shape DialogButtonType.WARNING -> ButtonDefaults.shape DialogButtonType.PRIMARY -> MaterialTheme.shapes.extraLarge }, ) { Text( modifier = Modifier.padding(horizontal = 8.dp), text = it.label.text(), style = ExtendedTheme.typography.smallBody, ) } } } } } } } } @PreviewLightDark @Composable fun SunoErrorDialog_Preview() { SunoPreview { SunoErrorDialog( spec = DialogSpec( title = UiString.Raw("Test Dialog"), body = UiString.Raw("This is a test dialog with a pretty long message"), buttons = persistentListOf( DialogSpec.Button( label = UiString.Raw("Cancel"), onClick = { }, type = DialogButtonType.DEFAULT, ), DialogSpec.Button( label = UiString.Raw("OH GOD"), onClick = { }, type = DialogSpec.Button.DialogButtonType.WARNING, ), DialogSpec.Button( label = UiString.Raw("OK"), onClick = { }, type = DialogButtonType.PRIMARY, ), ), ), onDismissRequest = { // no-op }, ) } }