Fixes layout issues of LongForm content when the image is not present.

This commit is contained in:
Vitor Pamplona 2024-03-20 16:02:49 -04:00
parent f2a8e51b20
commit 97cdc0bc7a
6 changed files with 122 additions and 100 deletions

View File

@ -22,17 +22,23 @@ package com.vitorpamplona.amethyst.ui.note.elements
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.note.NoteAuthorPicture
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.Size55dp
import com.vitorpamplona.amethyst.ui.theme.authorNotePictureForImageHeader
@ -43,28 +49,42 @@ fun DefaultImageHeader(
note: Note,
accountViewModel: AccountViewModel,
) {
Box {
note.author?.info?.banner?.let {
AsyncImage(
model = it,
contentDescription =
stringResource(
R.string.preview_card_image_for,
it,
),
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
}
?: Image(
painter = painterResource(R.drawable.profile_banner),
contentDescription = stringResource(R.string.profile_banner),
contentScale = ContentScale.FillWidth,
modifier = imageHeaderBannerSize,
)
val authorState by note.live().authorChanges.observeAsState(note.author)
Box(authorNotePictureForImageHeader.align(Alignment.BottomStart)) {
NoteAuthorPicture(baseNote = note, accountViewModel = accountViewModel, size = Size55dp)
authorState?.let { author ->
Box {
BannerImage(author)
Box(authorNotePictureForImageHeader.align(Alignment.BottomStart)) {
BaseUserPicture(author, Size55dp, accountViewModel, Modifier)
}
}
}
}
@Composable
private fun BoxScope.BannerImage(author: User) {
val currentInfo by author.live().userMetadataInfo.observeAsState()
currentInfo?.banner?.let {
AsyncImage(
model = it,
contentDescription =
stringResource(
R.string.preview_card_image_for,
it,
),
contentScale = ContentScale.FillWidth,
modifier =
Modifier
.fillMaxWidth()
.heightIn(max = 200.dp),
)
} ?: run {
Image(
painter = painterResource(R.drawable.profile_banner),
contentDescription = stringResource(R.string.profile_banner),
contentScale = ContentScale.FillWidth,
modifier = imageHeaderBannerSize,
)
}
}

View File

@ -88,8 +88,9 @@ fun RenderClassifieds(
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
} ?: run {
DefaultImageHeader(note, accountViewModel)
}
?: DefaultImageHeader(note, accountViewModel)
}
Row(

View File

@ -127,8 +127,9 @@ private fun WikiNoteHeader(
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
} ?: run {
DefaultImageHeader(note, accountViewModel)
}
?: DefaultImageHeader(note, accountViewModel)
}
title?.let {

View File

@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.note.types
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
@ -65,14 +64,14 @@ private fun LongFormHeader(
note: Note,
accountViewModel: AccountViewModel,
) {
val image = remember(noteEvent) { noteEvent.image() }
val title = remember(noteEvent) { noteEvent.title() }
val image = noteEvent.image()
val title = noteEvent.title()
val summary =
remember(noteEvent) {
noteEvent.summary()?.ifBlank { null } ?: noteEvent.content.take(200).ifBlank { null }
}
Row(
Column(
modifier =
Modifier
.padding(top = Size5dp)
@ -83,51 +82,53 @@ private fun LongFormHeader(
QuoteBorder,
),
) {
Column {
val automaticallyShowUrlPreview =
remember { accountViewModel.settings.showUrlPreview.value }
val automaticallyShowUrlPreview =
remember { accountViewModel.settings.showImages.value }
if (automaticallyShowUrlPreview) {
image?.let {
AsyncImage(
model = it,
contentDescription =
stringResource(
R.string.preview_card_image_for,
it,
),
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
}
?: DefaultImageHeader(note, accountViewModel)
}
title?.let {
Text(
text = it,
style = MaterialTheme.typography.bodyLarge,
modifier =
Modifier
.fillMaxWidth()
.padding(start = 10.dp, end = 10.dp, top = 10.dp),
if (automaticallyShowUrlPreview) {
println("ImagePreview: $title $image")
image?.let {
println("ImagePreview: Drawing $title $image")
AsyncImage(
model = it,
contentDescription =
stringResource(
R.string.preview_card_image_for,
it,
),
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
} ?: run {
println("ImagePreview: DefaultHeader $title $image")
DefaultImageHeader(note, accountViewModel)
}
}
summary?.let {
Spacer(modifier = StdVertSpacer)
Text(
text = it,
style = MaterialTheme.typography.bodySmall,
modifier =
Modifier
.fillMaxWidth()
.padding(start = 10.dp, end = 10.dp, bottom = 10.dp),
color = Color.Gray,
maxLines = 3,
overflow = TextOverflow.Ellipsis,
)
}
title?.let {
Text(
text = it,
style = MaterialTheme.typography.bodyLarge,
modifier =
Modifier
.fillMaxWidth()
.padding(start = 10.dp, end = 10.dp, top = 10.dp),
)
}
summary?.let {
Spacer(modifier = StdVertSpacer)
Text(
text = it,
style = MaterialTheme.typography.bodySmall,
modifier =
Modifier
.fillMaxWidth()
.padding(start = 10.dp, end = 10.dp, bottom = 10.dp),
color = Color.Gray,
maxLines = 3,
overflow = TextOverflow.Ellipsis,
)
}
}
}

View File

@ -135,8 +135,9 @@ fun VideoDisplay(
contentScale = ContentScale.FillWidth,
modifier = MaterialTheme.colorScheme.imageModifier,
)
} ?: run {
DefaultImageHeader(note, accountViewModel)
}
?: DefaultImageHeader(note, accountViewModel)
}
} else {
ZoomableContentView(

View File

@ -789,43 +789,41 @@ private fun RenderClassifiedsReaderForThread(
@Composable
private fun RenderLongFormHeaderForThread(noteEvent: LongTextNoteEvent) {
Row(modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp)) {
Column {
noteEvent.image()?.let {
AsyncImage(
model = it,
contentDescription =
stringResource(
R.string.preview_card_image_for,
it,
),
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
}
Column(modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp)) {
noteEvent.image()?.let {
AsyncImage(
model = it,
contentDescription =
stringResource(
R.string.preview_card_image_for,
it,
),
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
}
noteEvent.title()?.let {
noteEvent.title()?.let {
Spacer(modifier = DoubleVertSpacer)
Text(
text = it,
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.fillMaxWidth(),
)
}
noteEvent
.summary()
?.ifBlank { null }
?.let {
Spacer(modifier = DoubleVertSpacer)
Text(
text = it,
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.fillMaxWidth(),
color = Color.Gray,
)
}
noteEvent
.summary()
?.ifBlank { null }
?.let {
Spacer(modifier = DoubleVertSpacer)
Text(
text = it,
modifier = Modifier.fillMaxWidth(),
color = Color.Gray,
)
}
}
}
}