From e4d9369e7df07bbd346d7af66bcd75fcdd320648 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 3 Nov 2026 13:31:36 +0100 Subject: [PATCH] android: send taken receipts only after successful photo or video opening --- .../app/src/main/java/com/utun/chat/MainActivity.kt | 4 ++-- .../java/com/utun/chat/ui/screens/PhotoViewerScreen.kt | 7 +++++-- .../java/com/utun/chat/ui/screens/VideoPlayerScreen.kt | 6 +++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/MainActivity.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/MainActivity.kt index 8acbad463..98f1eabea 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/MainActivity.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/MainActivity.kt @@ -607,13 +607,13 @@ class MainActivity : AppCompatActivity() { videoMessage?.let { msg -> if (msg.filePath.isNotEmpty()) { - VideoPlayerScreen(filePath = msg.filePath, onClose = { videoMessage = null }) + VideoPlayerScreen(filePath = msg.filePath, onClose = { videoMessage = null }, onOpened = vm::attachmentOpened) } } photoMessage?.let { msg -> if (msg.filePath.isNotEmpty()) { - PhotoViewerScreen(filePath = msg.filePath, onClose = { photoMessage = null }) + PhotoViewerScreen(filePath = msg.filePath, onClose = { photoMessage = null }, onOpened = vm::attachmentOpened) } } diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/PhotoViewerScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/PhotoViewerScreen.kt index 2ce9ba86a..38c6e6bbd 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/PhotoViewerScreen.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/PhotoViewerScreen.kt @@ -29,7 +29,7 @@ private const val MAX_DECODE_DIM = 4096 /** Локальное изображение с EXIF и Fit/zoom; декодирование в IO ограничено стороной 4096 пикселей. * Экран владеет Bitmap через Compose; смена пути отменяет доставку старого результата. Ошибка оставляет доступным выход. */ @Composable -fun PhotoViewerScreen(filePath: String, onClose: () -> Unit) { +fun PhotoViewerScreen(filePath: String, onClose: () -> Unit, onOpened: (String) -> Unit = {}) { var bmp by remember(filePath) { mutableStateOf(null) } var loaded by remember(filePath) { mutableStateOf(false) } BackHandler(onBack = onClose) @@ -45,7 +45,10 @@ fun PhotoViewerScreen(filePath: String, onClose: () -> Unit) { } loaded = true if (bmp == null) LogManager.addLog("ERROR", "PhotoViewer", "decode failed: $filePath") - else LogManager.addLog("DEBUG", "PhotoViewer", "Opened image ${bmp?.width}x${bmp?.height} path=$filePath") + else { + LogManager.addLog("DEBUG", "PhotoViewer", "Opened image ${bmp?.width}x${bmp?.height} path=$filePath") + onOpened(filePath) + } } Box( diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/VideoPlayerScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/VideoPlayerScreen.kt index 7492f8273..7717e8d1d 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/VideoPlayerScreen.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/VideoPlayerScreen.kt @@ -63,7 +63,7 @@ private tailrec fun Context.findActivity(): Activity? = when (this) { * Controls показывают подтверждённое SDK состояние; zoom/pan и пауза сохраняются при смене размеров Surface. * Завершение файла закрывает экран. Ориентация и панели окна восстанавливаются при выходе. */ @Composable -fun VideoPlayerScreen(filePath: String, onClose: () -> Unit) { +fun VideoPlayerScreen(filePath: String, onClose: () -> Unit, onOpened: (String) -> Unit = {}) { val completed by rememberUpdatedState(onClose) val player = remember(filePath) { VideoFilePlayer { completed() } } val playback by player.state.collectAsState() @@ -71,6 +71,10 @@ fun VideoPlayerScreen(filePath: String, onClose: () -> Unit) { val isPlaying = playback.playing val durationMs = playback.durationMs val positionMs = playback.positionMs + var reported by remember(filePath) { mutableStateOf(false) } + LaunchedEffect(filePath, playback.prepared, error) { + if (playback.prepared && error == null && !reported) { reported = true; onOpened(filePath) } + } var controlsVisible by remember(filePath) { mutableStateOf(true) } var dragging by remember(filePath) { mutableStateOf(false) } var dragPosition by remember(filePath) { mutableStateOf(0) }