Split chat overlays to fix ART VerifyError
Some checks failed
Android CI / android (push) Failing after 5m57s
Android Release / release (push) Has started running
CI / test (push) Has been cancelled

This commit is contained in:
2026-03-11 23:00:19 +03:00
parent e6f1727800
commit 9af7597f8b

View File

@@ -1958,7 +1958,38 @@ fun ChatScreen(
} }
} }
if (viewerVideoUrl != null) { if (viewerVideoUrl != null) {
val videoUrl = viewerVideoUrl.orEmpty() VideoViewerOverlay(
videoUrl = viewerVideoUrl.orEmpty(),
onDismiss = { viewerVideoUrl = null },
)
}
if (showEmojiPicker) {
EmojiPickerSheet(
sheetState = actionSheetState,
emojiPickerTab = emojiPickerTab,
onEmojiPickerTabChange = { emojiPickerTab = it },
gifSearchQuery = gifSearchQuery,
onGifSearchQueryChange = { gifSearchQuery = it },
giphySearchItems = giphySearchItems,
isGiphyLoading = isGiphyLoading,
giphyErrorMessage = giphyErrorMessage,
onDismiss = { showEmojiPicker = false },
onEmojiSelected = { emoji ->
composerValue = composerValue.insertAtCursor(emoji)
onInputChanged(composerValue.text)
},
onSendPresetMediaUrl = onSendPresetMediaUrl,
onSendRemoteMedia = onSendRemoteMedia,
)
}
}
}
@Composable
private fun VideoViewerOverlay(
videoUrl: String,
onDismiss: () -> Unit,
) {
var videoViewRef by remember(videoUrl) { mutableStateOf<VideoView?>(null) } var videoViewRef by remember(videoUrl) { mutableStateOf<VideoView?>(null) }
var videoPrepared by remember(videoUrl) { mutableStateOf(false) } var videoPrepared by remember(videoUrl) { mutableStateOf(false) }
var videoDurationMs by remember(videoUrl) { mutableStateOf(0) } var videoDurationMs by remember(videoUrl) { mutableStateOf(0) }
@@ -1976,7 +2007,7 @@ fun ChatScreen(
LaunchedEffect(videoPlaying, videoPrepared, isVideoSeeking, videoUrl) { LaunchedEffect(videoPlaying, videoPrepared, isVideoSeeking, videoUrl) {
if (!videoPlaying || !videoPrepared || isVideoSeeking) return@LaunchedEffect if (!videoPlaying || !videoPrepared || isVideoSeeking) return@LaunchedEffect
while (videoPlaying && viewerVideoUrl == videoUrl && !isVideoSeeking) { while (videoPlaying && !isVideoSeeking) {
videoPositionMs = runCatching { videoViewRef?.currentPosition ?: videoPositionMs } videoPositionMs = runCatching { videoViewRef?.currentPosition ?: videoPositionMs }
.getOrDefault(videoPositionMs) .getOrDefault(videoPositionMs)
delay(250) delay(250)
@@ -1999,7 +2030,7 @@ fun ChatScreen(
.padding(horizontal = 8.dp, vertical = 8.dp), .padding(horizontal = 8.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
) { ) {
IconButton(onClick = { viewerVideoUrl = null }) { IconButton(onClick = onDismiss) {
Icon(imageVector = Icons.Filled.Close, contentDescription = "Close video viewer") Icon(imageVector = Icons.Filled.Close, contentDescription = "Close video viewer")
} }
} }
@@ -2108,10 +2139,28 @@ fun ChatScreen(
} }
} }
} }
if (showEmojiPicker) {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun EmojiPickerSheet(
sheetState: androidx.compose.material3.SheetState,
emojiPickerTab: ComposerPickerTab,
onEmojiPickerTabChange: (ComposerPickerTab) -> Unit,
gifSearchQuery: String,
onGifSearchQueryChange: (String) -> Unit,
giphySearchItems: List<RemotePickerItem>,
isGiphyLoading: Boolean,
giphyErrorMessage: String?,
onDismiss: () -> Unit,
onEmojiSelected: (String) -> Unit,
onSendPresetMediaUrl: (String) -> Unit,
onSendRemoteMedia: (String, String, ByteArray) -> Unit,
) {
val scope = rememberCoroutineScope()
var isPickerSending by remember { mutableStateOf(false) }
ModalBottomSheet( ModalBottomSheet(
onDismissRequest = { if (!isPickerSending) showEmojiPicker = false }, onDismissRequest = { if (!isPickerSending) onDismiss() },
sheetState = actionSheetState, sheetState = sheetState,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
@@ -2131,7 +2180,7 @@ fun ChatScreen(
}, },
modifier = Modifier modifier = Modifier
.clip(RoundedCornerShape(16.dp)) .clip(RoundedCornerShape(16.dp))
.clickable { emojiPickerTab = tab }, .clickable { onEmojiPickerTabChange(tab) },
) { ) {
Text( Text(
text = stringResource(id = tab.titleRes), text = stringResource(id = tab.titleRes),
@@ -2162,10 +2211,7 @@ fun ChatScreen(
color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.45f), color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.45f),
modifier = Modifier modifier = Modifier
.clip(RoundedCornerShape(10.dp)) .clip(RoundedCornerShape(10.dp))
.clickable { .clickable { onEmojiSelected(emoji) },
composerValue = composerValue.insertAtCursor(emoji)
onInputChanged(composerValue.text)
},
) { ) {
Box(modifier = Modifier.padding(vertical = 8.dp), contentAlignment = Alignment.Center) { Box(modifier = Modifier.padding(vertical = 8.dp), contentAlignment = Alignment.Center) {
Text(text = emoji) Text(text = emoji)
@@ -2190,7 +2236,7 @@ fun ChatScreen(
if (emojiPickerTab == ComposerPickerTab.Gif) { if (emojiPickerTab == ComposerPickerTab.Gif) {
OutlinedTextField( OutlinedTextField(
value = gifSearchQuery, value = gifSearchQuery,
onValueChange = { gifSearchQuery = it }, onValueChange = onGifSearchQueryChange,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
singleLine = true, singleLine = true,
placeholder = { Text(stringResource(id = R.string.chat_search_gifs)) }, placeholder = { Text(stringResource(id = R.string.chat_search_gifs)) },
@@ -2207,7 +2253,7 @@ fun ChatScreen(
!giphyErrorMessage.isNullOrBlank() -> { !giphyErrorMessage.isNullOrBlank() -> {
Text( Text(
text = giphyErrorMessage.orEmpty(), text = giphyErrorMessage,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
@@ -2233,13 +2279,13 @@ fun ChatScreen(
isPickerSending = true isPickerSending = true
if (emojiPickerTab == ComposerPickerTab.Gif || emojiPickerTab == ComposerPickerTab.Sticker) { if (emojiPickerTab == ComposerPickerTab.Gif || emojiPickerTab == ComposerPickerTab.Sticker) {
onSendPresetMediaUrl(remote.url) onSendPresetMediaUrl(remote.url)
showEmojiPicker = false onDismiss()
} else { } else {
val payload = downloadRemoteMedia(remote.url, remote.fileNamePrefix) val payload = downloadRemoteMedia(remote.url, remote.fileNamePrefix)
if (payload != null) { if (payload != null) {
val stickerAdjustedName = "sticker_${payload.fileName}" val stickerAdjustedName = "sticker_${payload.fileName}"
onSendRemoteMedia(stickerAdjustedName, payload.mimeType, payload.bytes) onSendRemoteMedia(stickerAdjustedName, payload.mimeType, payload.bytes)
showEmojiPicker = false onDismiss()
} }
} }
isPickerSending = false isPickerSending = false
@@ -2273,8 +2319,6 @@ fun ChatScreen(
} }
} }
} }
}
}
private data class PickedMediaPayload( private data class PickedMediaPayload(
val fileName: String, val fileName: String,