fix: unneeded space after post text

This commit is contained in:
Diego Beraldin 2023-10-03 19:39:16 +02:00
parent 682f0c2ec0
commit 83160d5cff
3 changed files with 90 additions and 77 deletions

View File

@ -16,20 +16,25 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalPixel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
@ -215,17 +220,22 @@ private fun ExtendedPost(
onImageClick = onImageClick, onImageClick = onImageClick,
) )
Box { Box {
val maxHeight = 200.dp
val maxHeightPx = maxHeight.toLocalPixel()
var textHeightPx by remember { mutableStateOf(0f) }
PostCardBody( PostCardBody(
modifier = Modifier.let { modifier = Modifier.let {
if (withOverflowBlurred) { if (withOverflowBlurred) {
it.heightIn(max = 200.dp) it.heightIn(max = maxHeight)
} else { } else {
it it
} }
}.padding(horizontal = Spacing.xs), }.padding(horizontal = Spacing.xs).onGloballyPositioned {
textHeightPx = it.size.toSize().height
},
text = post.text, text = post.text,
) )
if (withOverflowBlurred) { if (withOverflowBlurred && textHeightPx >= maxHeightPx) {
Box( Box(
modifier = Modifier.height(Spacing.xxl).fillMaxWidth() modifier = Modifier.height(Spacing.xxl).fillMaxWidth()
.align(Alignment.BottomCenter).background( .align(Alignment.BottomCenter).background(
@ -242,9 +252,7 @@ private fun ExtendedPost(
if (post.url != post.imageUrl) { if (post.url != post.imageUrl) {
PostLinkBanner( PostLinkBanner(
modifier = Modifier.padding(vertical = Spacing.xs), modifier = Modifier.padding(vertical = Spacing.xs),
url = post.url.takeIf { url = post.url?.takeIf { !it.looksLikeAnImage }.orEmpty(),
it?.contains("pictrs/image") == false
}.orEmpty(),
) )
} }
PostCardFooter( PostCardFooter(
@ -266,8 +274,11 @@ private fun ExtendedPost(
private val PostModel.imageUrl: String private val PostModel.imageUrl: String
get() = thumbnailUrl?.takeIf { it.isNotEmpty() } ?: run { get() = thumbnailUrl?.takeIf { it.isNotEmpty() } ?: run {
url?.takeIf { u -> url?.takeIf { it.looksLikeAnImage }
val imageExtensions = listOf(".jpeg", ".jpg", ".png") }.orEmpty()
imageExtensions.any { u.endsWith(it) }
} private val String.looksLikeAnImage: Boolean
}.orEmpty() get() {
val imageExtensions = listOf(".jpeg", ".jpg", ".png")
return imageExtensions.any { this.endsWith(it) }
}

View File

@ -59,7 +59,7 @@ fun PostCardFooter(
Box(modifier = modifier) { Box(modifier = modifier) {
Row( Row(
modifier = Modifier.padding(bottom = Spacing.xxxs), modifier = Modifier.padding(vertical = Spacing.xxxs),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Spacing.xxs), horizontalArrangement = Arrangement.spacedBy(Spacing.xxs),
) { ) {

View File

@ -97,72 +97,74 @@ internal fun MarkdownText(
Column( Column(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
Text( if (inlineImages || content.text != imageUrl) {
text = content, Text(
modifier = textModifier, text = content,
style = style, modifier = textModifier,
inlineContent = mapOf( style = style,
TAG_IMAGE_URL to InlineTextContent( inlineContent = mapOf(
if (inlineImages) { TAG_IMAGE_URL to InlineTextContent(
Placeholder( if (inlineImages) {
180.sp, Placeholder(
180.sp, 180.sp,
PlaceholderVerticalAlign.Bottom, 180.sp,
) // TODO: identify flexible scaling! PlaceholderVerticalAlign.Bottom,
} else { ) // TODO: identify flexible scaling!
Placeholder(1.sp, 1.sp, PlaceholderVerticalAlign.Bottom) } else {
} Placeholder(1.sp, 1.sp, PlaceholderVerticalAlign.Bottom)
) { link -> }
if (inlineImages) { ) { link ->
CustomImage( if (inlineImages) {
modifier = Modifier CustomImage(
.fillMaxWidth() modifier = Modifier
.clickable( .fillMaxWidth()
interactionSource = remember { MutableInteractionSource() }, .clickable(
indication = null interactionSource = remember { MutableInteractionSource() },
) { indication = null
onOpenImage?.invoke(imageUrl) ) {
}, onOpenImage?.invoke(imageUrl)
url = link, },
quality = FilterQuality.Low, url = link,
contentDescription = null, quality = FilterQuality.Low,
contentScale = ContentScale.FillWidth, contentDescription = null,
onFailure = { contentScale = ContentScale.FillWidth,
Text( onFailure = {
modifier = Modifier.fillMaxWidth(), Text(
textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth(),
text = stringResource(MR.strings.message_image_loading_error), textAlign = TextAlign.Center,
style = LocalMarkdownTypography.current.text text = stringResource(MR.strings.message_image_loading_error),
) style = LocalMarkdownTypography.current.text
},
onLoading = { progress ->
val prog = if (progress != null) {
progress
} else {
val transition = rememberInfiniteTransition()
val res by transition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = InfiniteRepeatableSpec(
animation = tween(1000)
)
) )
res },
} onLoading = { progress ->
CircularProgressIndicator( val prog = if (progress != null) {
progress = prog, progress
color = MaterialTheme.colorScheme.primary, } else {
) val transition = rememberInfiniteTransition()
}, val res by transition.animateFloat(
) initialValue = 0f,
} else { targetValue = 1f,
imageUrl = link animationSpec = InfiniteRepeatableSpec(
} animation = tween(1000)
}, )
), )
color = LocalMarkdownColors.current.text, res
onTextLayout = { layoutResult.value = it }, }
) CircularProgressIndicator(
progress = prog,
color = MaterialTheme.colorScheme.primary,
)
},
)
} else {
imageUrl = link
}
},
),
color = LocalMarkdownColors.current.text,
onTextLayout = { layoutResult.value = it },
)
}
if (!inlineImages && imageUrl.isNotEmpty()) { if (!inlineImages && imageUrl.isNotEmpty()) {
CustomImage( CustomImage(
modifier = modifier.fillMaxWidth() modifier = modifier.fillMaxWidth()