From 44df5691d8b14eb36f102f6b084e1e06e362ba18 Mon Sep 17 00:00:00 2001 From: k1ngsterr1 Date: Mon, 2 Feb 2026 03:33:31 +0500 Subject: [PATCH] fix: enhance gallery and image editor interactions with improved animations and state management --- .../components/MediaPickerBottomSheet.kt | 156 +++++++++++++----- 1 file changed, 113 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/components/MediaPickerBottomSheet.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/components/MediaPickerBottomSheet.kt index a486577..9f0b80e 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/components/MediaPickerBottomSheet.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/components/MediaPickerBottomSheet.kt @@ -44,6 +44,8 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupProperties import androidx.activity.compose.BackHandler @@ -244,18 +246,27 @@ fun MediaPickerBottomSheet( label = "scrim_fade" ) - // Показываем галерею - val showSheet = isVisible && editingItem == null && pendingPhotoUri == null && previewPhotoUri == null + // Показываем галерею (но НЕ когда редактируем фото) + val showSheet = isVisible && pendingPhotoUri == null && previewPhotoUri == null + val showGalleryContent = showSheet && editingItem == null && !isClosing // Запускаем анимацию когда showSheet меняется LaunchedEffect(showSheet) { - if (showSheet) { + if (showSheet && editingItem == null) { shouldShow = true isClosing = false sheetHeightPx.snapTo(collapsedHeightPx) } } + // Закрываем popup когда переходим к редактору + LaunchedEffect(editingItem) { + if (editingItem != null) { + // Галерея уже скрылась, скрываем popup + shouldShow = false + } + } + // Функция для анимированного закрытия val animatedClose: () -> Unit = { if (!isClosing) { @@ -560,9 +571,10 @@ fun MediaPickerBottomSheet( onOpenCamera() }, onItemClick = { item, position -> - // Telegram-style: клик на фото сразу открывает редактор с caption + // Telegram-style: клик на фото сразу открывает редактор if (!item.isVideo) { thumbnailPosition = position + // Сразу открываем редактор - галерея закроется автоматически editingItem = item } else { // Для видео - добавляем/убираем из selection @@ -590,49 +602,107 @@ fun MediaPickerBottomSheet( } } - // Image Editor overlay для фото из галереи - editingItem?.let { item -> - ImageEditorScreen( - imageUri = item.uri, - onDismiss = { + // Image Editor FULLSCREEN overlay для фото из галереи + if (editingItem != null) { + // 🎨 Чёрный статус бар для ImageEditor + DisposableEffect(Unit) { + val window = (view.context as? android.app.Activity)?.window + val originalStatusBarColor = window?.statusBarColor ?: 0 + window?.statusBarColor = android.graphics.Color.BLACK + + onDispose { + window?.statusBarColor = originalStatusBarColor + } + } + + // Используем Dialog для полного перекрытия экрана включая статус бар + Dialog( + onDismissRequest = { editingItem = null thumbnailPosition = null + shouldShow = true }, - onSave = { editedUri -> - editingItem = null - thumbnailPosition = null - // Если нет onMediaSelectedWithCaption - открываем preview - if (onMediaSelectedWithCaption == null) { - previewPhotoUri = editedUri - } else { - // Отправляем без caption (если нажали Done вместо Send) - val mediaItem = MediaItem( - id = System.currentTimeMillis(), - uri = editedUri, - mimeType = "image/png", - dateModified = System.currentTimeMillis() - ) - onMediaSelected(listOf(mediaItem)) - onDismiss() + properties = DialogProperties( + dismissOnBackPress = true, + dismissOnClickOutside = false, + usePlatformDefaultWidth = false, + decorFitsSystemWindows = false // Позволяет рисовать под статус баром + ) + ) { + // Делаем статус бар прозрачным и рисуем под ним + val dialogView = LocalView.current + LaunchedEffect(Unit) { + val window = (dialogView.context as? android.app.Activity)?.window + ?: (dialogView.parent as? android.view.View)?.context?.let { + (it as? android.app.Activity)?.window + } + // Для Dialog нужно получить window диалога + val dialogWindow = (dialogView.parent as? android.view.View)?.let { + var v: android.view.View? = it + while (v != null) { + if (v.context is android.app.Activity) { + break + } + v = v.parent as? android.view.View + } + (v?.context as? android.app.Activity)?.window } - }, - onSaveWithCaption = if (onMediaSelectedWithCaption != null) { editedUri, caption -> - editingItem = null - thumbnailPosition = null - val mediaItem = MediaItem( - id = System.currentTimeMillis(), - uri = editedUri, - mimeType = "image/png", - dateModified = System.currentTimeMillis() - ) - onMediaSelectedWithCaption(mediaItem, caption) - onDismiss() - } else null, - isDarkTheme = isDarkTheme, - showCaptionInput = onMediaSelectedWithCaption != null, - recipientName = recipientName, - thumbnailPosition = thumbnailPosition - ) + } + + // Fullscreen black background + content + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black) + .systemBarsPadding() // Отступы от системных баров + ) { + editingItem?.let { item -> + ImageEditorScreen( + imageUri = item.uri, + onDismiss = { + editingItem = null + thumbnailPosition = null + // Возвращаем галерею обратно + shouldShow = true + }, + onSave = { editedUri -> + editingItem = null + thumbnailPosition = null + // Если нет onMediaSelectedWithCaption - открываем preview + if (onMediaSelectedWithCaption == null) { + previewPhotoUri = editedUri + } else { + // Отправляем без caption (если нажали Done вместо Send) + val mediaItem = MediaItem( + id = System.currentTimeMillis(), + uri = editedUri, + mimeType = "image/png", + dateModified = System.currentTimeMillis() + ) + onMediaSelected(listOf(mediaItem)) + onDismiss() + } + }, + onSaveWithCaption = if (onMediaSelectedWithCaption != null) { editedUri, caption -> + editingItem = null + thumbnailPosition = null + val mediaItem = MediaItem( + id = System.currentTimeMillis(), + uri = editedUri, + mimeType = "image/png", + dateModified = System.currentTimeMillis() + ) + onMediaSelectedWithCaption(mediaItem, caption) + onDismiss() + } else null, + isDarkTheme = isDarkTheme, + showCaptionInput = onMediaSelectedWithCaption != null, + recipientName = recipientName, + thumbnailPosition = thumbnailPosition + ) + } + } + } } // Image Editor overlay для фото с камеры