mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Make it even smoother
Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
@@ -8,6 +8,7 @@ import androidx.compose.animation.fadeOut
|
|||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -59,7 +60,7 @@ import ru.fromchat.api.DmEnvelope
|
|||||||
import ru.fromchat.api.DmFile
|
import ru.fromchat.api.DmFile
|
||||||
|
|
||||||
private val IMAGE_SIZE = 160.dp
|
private val IMAGE_SIZE = 160.dp
|
||||||
private val IMAGE_RADIUS = 8.dp
|
private val IMAGE_RADIUS = 12.dp
|
||||||
|
|
||||||
internal fun isImageFilename(name: String): Boolean =
|
internal fun isImageFilename(name: String): Boolean =
|
||||||
name.endsWith(".png", true) || name.endsWith(".jpg", true) ||
|
name.endsWith(".png", true) || name.endsWith(".jpg", true) ||
|
||||||
@@ -125,7 +126,7 @@ fun AttachmentPreview(
|
|||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.then(
|
.then(
|
||||||
if (onImageClick != null && isFullyLoaded && !isExpanded) Modifier.clickable(onClick = onImageClick)
|
if (onImageClick != null && isFullyLoaded && !isExpanded) Modifier.clickable(indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = onImageClick)
|
||||||
else Modifier
|
else Modifier
|
||||||
)
|
)
|
||||||
.conditional(
|
.conditional(
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ fun ImageFullscreenPreview(
|
|||||||
val thumbWidth = thumbnailBounds.width
|
val thumbWidth = thumbnailBounds.width
|
||||||
val s = thumbWidth / containerWidth
|
val s = thumbWidth / containerWidth
|
||||||
val o = thumbCenter - fullCenter
|
val o = thumbCenter - fullCenter
|
||||||
InitialTransform(s, o.x, o.y, 8f, 0f)
|
InitialTransform(s, o.x, o.y, 12f, 0f)
|
||||||
} else {
|
} else {
|
||||||
InitialTransform(1f, 0f, 0f, 0f, 1f)
|
InitialTransform(1f, 0f, 0f, 0f, 1f)
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ fun ImageFullscreenPreview(
|
|||||||
scaleAnim.snapTo(startScale)
|
scaleAnim.snapTo(startScale)
|
||||||
offsetXAnim.snapTo(startOffset.x)
|
offsetXAnim.snapTo(startOffset.x)
|
||||||
offsetYAnim.snapTo(startOffset.y)
|
offsetYAnim.snapTo(startOffset.y)
|
||||||
cornerRadiusAnim.snapTo(8f)
|
cornerRadiusAnim.snapTo(12f)
|
||||||
backgroundAlpha.snapTo(0f)
|
backgroundAlpha.snapTo(0f)
|
||||||
menusVisible = false
|
menusVisible = false
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ fun ImageFullscreenPreview(
|
|||||||
launch { scaleAnim.animateTo(targetScale, tween(250)) }
|
launch { scaleAnim.animateTo(targetScale, tween(250)) }
|
||||||
launch { offsetXAnim.animateTo(targetOffset.x, tween(250)) }
|
launch { offsetXAnim.animateTo(targetOffset.x, tween(250)) }
|
||||||
launch { offsetYAnim.animateTo(targetOffset.y, tween(250)) }
|
launch { offsetYAnim.animateTo(targetOffset.y, tween(250)) }
|
||||||
launch { cornerRadiusAnim.animateTo(8f, tween(250)) }
|
launch { cornerRadiusAnim.animateTo(12f, tween(250)) }
|
||||||
launch { backgroundAlpha.animateTo(0f, tween(250)) }
|
launch { backgroundAlpha.animateTo(0f, tween(250)) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -351,8 +351,9 @@ fun ImageFullscreenPreview(
|
|||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
scaleX = scaleAnim.value
|
scaleX = scaleAnim.value
|
||||||
scaleY = scaleAnim.value
|
scaleY = scaleAnim.value
|
||||||
shape = androidx.compose.foundation.shape.RoundedCornerShape(cornerRadiusAnim.value.dp)
|
val scale = maxOf(scaleAnim.value, 0.01f)
|
||||||
clip = cornerRadiusAnim.value > 0f
|
shape = androidx.compose.foundation.shape.RoundedCornerShape((cornerRadiusAnim.value / scale).dp)
|
||||||
|
clip = true
|
||||||
},
|
},
|
||||||
contentScale = ContentScale.FillWidth
|
contentScale = ContentScale.FillWidth
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -119,6 +119,10 @@ fun MessageItem(
|
|||||||
) {
|
) {
|
||||||
// Message bubble
|
// Message bubble
|
||||||
val isDark = isSystemInDarkTheme()
|
val isDark = isSystemInDarkTheme()
|
||||||
|
val firstContentIsImage = (!showUsername || isAuthor) &&
|
||||||
|
message.reply_to == null &&
|
||||||
|
(message.pendingFileUri?.let { isImageFilename(it.substringAfterLast('/').substringBefore('?')) } == true ||
|
||||||
|
message.files?.firstOrNull()?.let { isImageFilename(it.name) } == true)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
// Max width: 70% of row, min width: content-driven
|
// Max width: 70% of row, min width: content-driven
|
||||||
@@ -151,7 +155,7 @@ fun MessageItem(
|
|||||||
background(MaterialTheme.colorScheme.surfaceContainerHighest)
|
background(MaterialTheme.colorScheme.surfaceContainerHighest)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.padding(top = 6.dp)
|
.padding(top = if (firstContentIsImage) 0.dp else 6.dp)
|
||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
// Username inside bubble (for received messages)
|
// Username inside bubble (for received messages)
|
||||||
|
|||||||
Reference in New Issue
Block a user