package com.suno.android.ui.screens.songdetails import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.suno.android.common_core_utils.Id import com.suno.android.common_data.mappers.clips.SongListData import com.suno.android.common_ui.components.omni.CircleIconButton import com.suno.android.common_ui.theme.ExtendedTheme import com.suno.android.ui.screens.songdetails.SongDetailsMviEvent.EditSongArtSubmit import com.suno.android.ui.screens.songdetails.SongDetailsMviEvent.EditSongLyricsSubmit import com.suno.android.ui.screens.songdetails.SongDetailsMviEvent.EditSongTitleCaptionSaveClick import com.suno.android.common_res.R as CommonResR import com.suno.android.common_ui.R as CommonUiR @Composable fun SongDetailsScreen( viewModel: SongDetailsViewModel = hiltViewModel(), isInPostingMode: Boolean, songId: Id, onBackPress: () -> Unit, ) { val snackbarHostState = remember { SnackbarHostState() } val interactionSource = remember { MutableInteractionSource() } val focusManager = LocalFocusManager.current val state by viewModel.state.collectAsStateWithLifecycle() val publishErrorMessage = stringResource(CommonResR.string.post_song_details_error_message) val hasChanges = when (state.screen) { SongDetailsScreenType.Main -> state.songTextFieldsHaveChanges SongDetailsScreenType.Lyrics -> state.songLyricsHasChanges SongDetailsScreenType.SongArt -> state.songArtHasChanged SongDetailsScreenType.MoreOptions -> false } fun handleBackPress( forceBack: Boolean = false, ) { if (!forceBack && hasChanges) { viewModel.sendEvent(SongDetailsMviEvent.ShowConfirmChangeDialog(isInPostingMode)) } else { if (state.screen == SongDetailsScreenType.Main) { onBackPress() } else { viewModel.sendEvent( SongDetailsMviEvent.BackPress(isInPostingMode = isInPostingMode), ) } } } LaunchedEffect(Unit) { viewModel.effects.collect { when (it) { is SongDetailsEffect.PostSongFailure -> { snackbarHostState.showSnackbar(publishErrorMessage) } is SongDetailsEffect.PostSongSuccess -> { onBackPress() } is SongDetailsEffect.HandleBack -> { handleBackPress(it.forceBack) } } } } val title = when (state.screen) { SongDetailsScreenType.Main -> { if (isInPostingMode) { stringResource(CommonResR.string.post_song_details_title) } else { stringResource(CommonResR.string.edit_song_details_title) } } SongDetailsScreenType.Lyrics -> stringResource(CommonResR.string.edit_song_details_lyrics_title) SongDetailsScreenType.SongArt -> stringResource(CommonResR.string.edit_song_details_song_art_title) SongDetailsScreenType.MoreOptions -> stringResource(CommonResR.string.song_details_more_options_title) } val showSaveButton = when (state.screen) { SongDetailsScreenType.Main -> state.songTextFieldsHaveChanges SongDetailsScreenType.Lyrics -> state.songLyricsHasChanges SongDetailsScreenType.SongArt -> state.songArtHasChanged SongDetailsScreenType.MoreOptions -> false } Scaffold( modifier = Modifier .fillMaxSize() .background(ExtendedTheme.colors.backgroundPrimary) .clickable(interactionSource = interactionSource, indication = null) { focusManager.clearFocus() } .padding(12.dp), topBar = { SongDetailsHeader( title = title, actions = { if (showSaveButton) { CircleIconButton( vectorDrawableResId = CommonUiR.drawable.check, contentDescription = stringResource(CommonResR.string.save), showProgressIndicator = state.isSaveInProgress, inverted = true, onClick = { when (state.screen) { SongDetailsScreenType.Main -> { viewModel.sendEvent( EditSongTitleCaptionSaveClick( isInPostingMode = isInPostingMode, ), ) } SongDetailsScreenType.Lyrics -> { viewModel.sendEvent( EditSongLyricsSubmit( isInPostingMode = isInPostingMode, ), ) } SongDetailsScreenType.SongArt -> { viewModel.sendEvent( EditSongArtSubmit( isInPostingMode = isInPostingMode, ), ) } SongDetailsScreenType.MoreOptions -> {} } }, ) } }, onBackPress = { handleBackPress() }, ) }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, ) { innerPadding -> Column( modifier = Modifier .fillMaxSize() .padding(innerPadding), ) { SongDetailsScreenAnimator( visible = state.screen == SongDetailsScreenType.Main, disableExitAnimations = true, // Disabling as this is the first screen animateFromEnd = false, // animating this screen from the left as it's the main screen ) { SongDetailsMainScreen( viewModel = viewModel, isInPostingMode = isInPostingMode, songId = songId, onSongArtClicked = { viewModel.sendEvent( SongDetailsMviEvent.EditSongArtClick( isInPostingMode = isInPostingMode, ), ) }, ) } SongDetailsScreenAnimator( visible = state.screen == SongDetailsScreenType.Lyrics, ) { SongDetailsLyricsScreen( viewModel = viewModel, isInPostingMode = isInPostingMode, ) } SongDetailsScreenAnimator( visible = state.screen == SongDetailsScreenType.SongArt, ) { SongDetailsSongArtScreen( viewModel = viewModel, isInPostingMode = isInPostingMode, ) } SongDetailsScreenAnimator( visible = state.screen == SongDetailsScreenType.MoreOptions, ) { SongDetailsMoreOptionsScreen( viewModel = viewModel, isInPostingMode = isInPostingMode, ) } } } }