diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt index 58884fe..f18a82f 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.foundation.gestures.calculateZoom import androidx.compose.foundation.gestures.waitForUpOrCancellation import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -650,6 +651,7 @@ private fun ChatScreen( val listState = rememberLazyListState() val scope = rememberCoroutineScope() val allViewerMediaItems = remember(state.messages) { buildChatViewerMediaItems(state.messages) } + val isTabletLayout = LocalConfiguration.current.screenWidthDp >= 840 val isChannelChat = state.chatType.equals("channel", ignoreCase = true) val isPrivateChat = state.chatType.equals("private", ignoreCase = true) val showUnknownPrivateChatBanner = isPrivateChat && @@ -657,7 +659,7 @@ private fun ChatScreen( state.isCounterpartRelationshipResolved && !state.isCounterpartContact && !state.isCounterpartBlocked - val showPrivateInfoCard = isPrivateChat && state.counterpartUserId != null + val showPrivateInfoCard = isPrivateChat && state.counterpartUserId != null && !isTabletLayout val canShowMembersTab = state.chatType.equals("group", ignoreCase = true) || (state.chatType.equals("channel", ignoreCase = true) && state.canManageMembers) val timelineItems = remember(state.messages, context) { buildChatTimelineItems(state.messages, context) } @@ -721,7 +723,6 @@ private fun ChatScreen( val forwardSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val chatInfoSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val attachmentSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - val isTabletLayout = LocalConfiguration.current.screenWidthDp >= 840 val adaptiveHorizontalPadding = if (isTabletLayout) 72.dp else 0.dp val chatInfoEntries = remember(state.messages, context) { buildChatInfoEntries(state.messages, context) } val giphyApiKey = remember { BuildConfig.GIPHY_API_KEY.trim() } @@ -4069,6 +4070,16 @@ private fun MessageBubble( message.type.contains("video_note", ignoreCase = true) ) val renderWithoutBubble = hasSingleStickerAttachment || hasSingleCircleAttachment + val configuration = LocalConfiguration.current + val isTabletLayout = configuration.screenWidthDp >= 840 + val bubbleMaxWidth = when { + hasSingleCircleAttachment -> if (isTabletLayout) 220.dp else 190.dp + renderAsChannelPost -> if (isTabletLayout) 480.dp else 360.dp + else -> if (isTabletLayout) 360.dp else 300.dp + } + val singleMediaMaxWidth = if (isTabletLayout) 320.dp else 240.dp + val singleMediaMaxHeight = if (isTabletLayout) 260.dp else 220.dp + val gridMediaTileHeight = if (isTabletLayout) 96.dp else 112.dp Row( modifier = Modifier.fillMaxWidth(), @@ -4084,16 +4095,10 @@ private fun MessageBubble( } Column( modifier = Modifier - .fillMaxWidth( - if (hasSingleStickerAttachment || hasSingleCircleAttachment) { - if (renderAsChannelPost) 0.58f else 0.52f - } else if (renderAsChannelPost) { - 0.94f - } else { - 0.8f - }, + .widthIn( + min = if (renderWithoutBubble) 96.dp else if (renderAsChannelPost) 120.dp else 82.dp, + max = bubbleMaxWidth, ) - .widthIn(min = if (renderWithoutBubble) 96.dp else if (renderAsChannelPost) 120.dp else 82.dp) .then( if (renderWithoutBubble) { Modifier @@ -4233,8 +4238,8 @@ private fun MessageBubble( .size(176.dp) } else { Modifier - .fillMaxWidth() - .height(188.dp) + .widthIn(max = singleMediaMaxWidth) + .heightIn(max = singleMediaMaxHeight) }, ) .clip(RoundedCornerShape(12.dp)) @@ -4338,8 +4343,8 @@ private fun MessageBubble( .size(176.dp) } else { Modifier - .fillMaxWidth() - .height(188.dp) + .widthIn(max = singleMediaMaxWidth) + .heightIn(max = singleMediaMaxHeight) }, ) .clip(RoundedCornerShape(12.dp)) @@ -4383,7 +4388,7 @@ private fun MessageBubble( Box( modifier = Modifier .weight(1f) - .height(112.dp) + .height(gridMediaTileHeight) .clip(RoundedCornerShape(10.dp)) .let { base -> if (openable) base.clickable { onAttachmentImageClick(image.fileUrl) } else base @@ -4604,6 +4609,8 @@ private fun CircleVideoAttachmentPlayer( onForceToggleAudioSourceHandled: (String) -> Unit, onForceCycleSpeedAudioSourceHandled: (String) -> Unit, ) { + val isTabletLayout = LocalConfiguration.current.screenWidthDp >= 840 + val circleSize = if (isTabletLayout) 190.dp else 150.dp val playerState = rememberManagedMediaPlayerState( url = url, speedOptions = listOf(1f), @@ -4648,8 +4655,7 @@ private fun CircleVideoAttachmentPlayer( val progressActiveColor = MaterialTheme.colorScheme.primary Box( modifier = Modifier - .fillMaxWidth() - .aspectRatio(1f) + .size(circleSize) .padding(horizontal = 6.dp, vertical = 2.dp), contentAlignment = Alignment.Center, ) {