fix: enhance gallery and image editor interactions with improved animations and state management
This commit is contained in:
@@ -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 для фото с камеры
|
||||
|
||||
Reference in New Issue
Block a user