package com.suno.android.ui.bottom_sheets.comments import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SheetState import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf 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.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.platform.LocalFocusManager import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.suno.android.common_core_utils.Id import com.suno.android.common_core_utils.model.UserHandle import com.suno.android.common_data.comments.MediaEntity import com.suno.android.common_data.user.UserProfile import kotlinx.coroutines.launch @Composable fun CommentsBottomSheet( mediaEntity: MediaEntity, authorId: Id?, authorHandle: UserHandle?, onDismiss: () -> Unit, sheetState: SheetState = rememberModalBottomSheetState(true), onProfileClicked: (profileHandle: UserHandle) -> Unit, onBeginWriting: () -> Unit = {}, ) { val vm = hiltViewModel( key = when (mediaEntity) { is MediaEntity.ClipEntity -> "clip" is MediaEntity.HookEntity -> "hook" }, creationCallback = { factory: CommentsBottomSheetVM.Factory -> factory.create(mediaEntity) }, ) LaunchedEffect(mediaEntity) { vm.fetchPage(mediaEntity, isFirstLoad = true) } val viewState by vm.state.collectAsStateWithLifecycle() val reportCommentSheetState = rememberModalBottomSheetState( skipPartiallyExpanded = true, ) var showReportCommentSheet by remember { mutableStateOf(false) } val scope = rememberCoroutineScope() val focusManager = LocalFocusManager.current val focusRequester = remember { FocusRequester() } var isTextFieldFocused by remember { mutableStateOf(false) } var hasBegunTyping by remember { mutableStateOf(false) } val lazyListState = rememberLazyListState() val endOfListReached: Boolean by remember { derivedStateOf { !lazyListState.canScrollForward } } LaunchedEffect(endOfListReached) { if (endOfListReached) { vm.fetchPage(mediaEntity) } } LaunchedEffect(sheetState.isVisible) { if (!sheetState.isVisible) { vm.clearComments() } } ModalBottomSheet( onDismissRequest = { onDismiss() }, sheetState = sheetState, dragHandle = null, modifier = Modifier.statusBarsPadding(), ) { CommentsBottomSheetContent( vm = vm, viewState = viewState, mediaEntity = mediaEntity, authorId = authorId, authorHandle = authorHandle, onDismiss = onDismiss, onProfileClicked = onProfileClicked, onBeginWriting = onBeginWriting, focusRequester = focusRequester, focusManager = focusManager, lazyListState = lazyListState, sheetState = sheetState, isTextFieldFocused = isTextFieldFocused, hasBegunTyping = hasBegunTyping, onFocusChanged = { isTextFieldFocused = it }, onTypingStateChanged = { hasBegunTyping = it }, onShowReportSheet = { scope.launch { showReportCommentSheet = true reportCommentSheetState.show() } }, modifier = Modifier.fillMaxSize(), ) if (showReportCommentSheet) { fun dismissSheet() { scope.launch { vm.sendEvent(CommentsBottomSheetEvent.Internal.OnClearCommentToReport) reportCommentSheetState.hide() showReportCommentSheet = false } } ReportCommentBottomSheet( onDismiss = { dismissSheet() }, onReport = { reason -> scope.launch { vm.sendEvent(CommentsBottomSheetEvent.OnReportComment(reason)) dismissSheet() } }, sheetState = reportCommentSheetState, ) } } }