diff --git a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Attachments.kt b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Attachments.kt index 189dcff1cf..bbcfb812af 100644 --- a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Attachments.kt +++ b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Attachments.kt @@ -21,6 +21,10 @@ import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -32,6 +36,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage +import coil3.compose.AsyncImagePainter import coil3.compose.rememberAsyncImagePainter import coil3.request.ImageRequest import coil3.request.crossfade @@ -48,7 +53,6 @@ import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi import com.bumptech.glide.integration.compose.GlideImage import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.engine.DiskCacheStrategy -import timber.log.Timber @Composable @OptIn(ExperimentalGlideComposeApi::class, ExperimentalFoundationApi::class) @@ -58,7 +62,7 @@ fun BubbleAttachments( onAttachmentLongClicked: (ChatView.Message.Attachment) -> Unit, isUserAuthor: Boolean ) { - Timber.d("Binding attachments: $attachments") + var isVideoPreviewLoaded by remember { mutableStateOf(false) } val context = LocalContext.current attachments.forEachIndexed { idx, attachment -> when (attachment) { @@ -68,6 +72,7 @@ fun BubbleAttachments( rowConfig.forEachIndexed { idx, rowSize -> BubbleGalleryRowLayout( onAttachmentClicked = onAttachmentClicked, + onAttachmentLongClicked = onAttachmentLongClicked, images = attachment.images.slice(index until index + rowSize) ) if (idx != rowConfig.lastIndex) { @@ -94,14 +99,16 @@ fun BubbleAttachments( } ) ) { - CircularProgressIndicator( - modifier = Modifier - .align(alignment = Alignment.Center) - .size(48.dp), - color = colorResource(R.color.glyph_active), - trackColor = colorResource(R.color.glyph_active).copy(alpha = 0.5f), - strokeWidth = 4.dp - ) + if (!isVideoPreviewLoaded) { + CircularProgressIndicator( + modifier = Modifier + .align(alignment = Alignment.Center) + .size(48.dp), + color = colorResource(R.color.glyph_active), + trackColor = colorResource(R.color.glyph_active).copy(alpha = 0.5f), + strokeWidth = 4.dp + ) + } AsyncImage( modifier = Modifier .size(292.dp) @@ -112,14 +119,18 @@ fun BubbleAttachments( .crossfade(true) .build(), contentDescription = null, - contentScale = ContentScale.Crop - ) - - Image( - modifier = Modifier.align(Alignment.Center), - painter = painterResource(id = R.drawable.ic_chat_attachment_play), - contentDescription = "Play button" + contentScale = ContentScale.Crop, + onState = { state -> + isVideoPreviewLoaded = state is AsyncImagePainter.State.Success + } ) + if (isVideoPreviewLoaded) { + Image( + modifier = Modifier.align(Alignment.Center), + painter = painterResource(id = R.drawable.ic_chat_attachment_play), + contentDescription = "Play button" + ) + } } } is ChatView.Message.Attachment.Image -> { diff --git a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/ChatBox.kt b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/ChatBox.kt index 06a8e713ac..2a0ce9aa0d 100644 --- a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/ChatBox.kt +++ b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/ChatBox.kt @@ -63,6 +63,7 @@ import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.PopupProperties import com.anytypeio.anytype.core_models.Url import com.anytypeio.anytype.core_ui.common.DefaultPreviews import com.anytypeio.anytype.core_ui.common.FULL_ALPHA @@ -209,7 +210,6 @@ fun ChatBox( .clip(CircleShape) .clickable { scope.launch { - focus.clearFocus(force = true) showDropdownMenu = true } } @@ -242,7 +242,8 @@ fun ChatBox( .align(Alignment.BottomEnd) .defaultMinSize( minWidth = 252.dp - ) + ), + properties = PopupProperties(focusable = false) ) { DropdownMenuItem( text = { @@ -820,7 +821,8 @@ fun ChatBoxEditPanel( .align(Alignment.BottomEnd) .defaultMinSize( minWidth = 252.dp - ) + ), + properties = PopupProperties(focusable = false) ) { DropdownMenuItem( text = { diff --git a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Gallery.kt b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Gallery.kt index 1d0f858f20..943037df9c 100644 --- a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Gallery.kt +++ b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Gallery.kt @@ -1,7 +1,8 @@ package com.anytypeio.anytype.feature_chats.ui +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -26,11 +27,12 @@ import com.bumptech.glide.integration.compose.GlideImage import com.bumptech.glide.load.DecodeFormat import com.bumptech.glide.load.engine.DiskCacheStrategy -@OptIn(ExperimentalGlideComposeApi::class) +@OptIn(ExperimentalGlideComposeApi::class, ExperimentalFoundationApi::class) @Composable fun BubbleGalleryRowLayout( images: List, onAttachmentClicked: (ChatView.Message.Attachment) -> Unit, + onAttachmentLongClicked: (ChatView.Message.Attachment) -> Unit ) { Row( modifier = Modifier @@ -64,9 +66,14 @@ fun BubbleGalleryRowLayout( modifier = Modifier .fillMaxSize() .clip(shape = RoundedCornerShape(12.dp)) - .clickable { - onAttachmentClicked(image) - } + .combinedClickable( + onClick = { + onAttachmentClicked(image) + }, + onLongClick = { + onAttachmentLongClicked(image) + } + ) ) { it .override(512, 512) diff --git a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Reactions.kt b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Reactions.kt index ce8576f59a..6ef8f1d10f 100644 --- a/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Reactions.kt +++ b/feature-chats/src/main/java/com/anytypeio/anytype/feature_chats/ui/Reactions.kt @@ -16,7 +16,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Text @@ -24,6 +23,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp @@ -42,6 +43,7 @@ fun ReactionList( onAddNewReaction: () -> Unit, isMaxReactionCountReached: Boolean = false, ) { + val haptic = LocalHapticFeedback.current FlowRow( modifier = Modifier .padding(top = 4.dp), @@ -75,6 +77,7 @@ fun ReactionList( onReacted(reaction.emoji) }, onLongClick = { + haptic.performHapticFeedback(HapticFeedbackType.LongPress) onViewReaction(reaction.emoji) } )