kopia lustrzana https://github.com/vitorpamplona/amethyst
Fixes layout issues of LongForm content when the image is not present.
rodzic
f2a8e51b20
commit
97cdc0bc7a
|
@ -22,17 +22,23 @@ package com.vitorpamplona.amethyst.ui.note.elements
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxScope
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.runtime.Composable
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
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.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size55dp
|
import com.vitorpamplona.amethyst.ui.theme.Size55dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.authorNotePictureForImageHeader
|
import com.vitorpamplona.amethyst.ui.theme.authorNotePictureForImageHeader
|
||||||
|
@ -43,28 +49,42 @@ fun DefaultImageHeader(
|
||||||
note: Note,
|
note: Note,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
Box {
|
val authorState by note.live().authorChanges.observeAsState(note.author)
|
||||||
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,
|
|
||||||
)
|
|
||||||
|
|
||||||
Box(authorNotePictureForImageHeader.align(Alignment.BottomStart)) {
|
authorState?.let { author ->
|
||||||
NoteAuthorPicture(baseNote = note, accountViewModel = accountViewModel, size = Size55dp)
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -88,8 +88,9 @@ fun RenderClassifieds(
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
} ?: run {
|
||||||
|
DefaultImageHeader(note, accountViewModel)
|
||||||
}
|
}
|
||||||
?: DefaultImageHeader(note, accountViewModel)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
|
|
|
@ -127,8 +127,9 @@ private fun WikiNoteHeader(
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
} ?: run {
|
||||||
|
DefaultImageHeader(note, accountViewModel)
|
||||||
}
|
}
|
||||||
?: DefaultImageHeader(note, accountViewModel)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
title?.let {
|
title?.let {
|
||||||
|
|
|
@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.note.types
|
||||||
|
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
@ -65,14 +64,14 @@ private fun LongFormHeader(
|
||||||
note: Note,
|
note: Note,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
val image = remember(noteEvent) { noteEvent.image() }
|
val image = noteEvent.image()
|
||||||
val title = remember(noteEvent) { noteEvent.title() }
|
val title = noteEvent.title()
|
||||||
val summary =
|
val summary =
|
||||||
remember(noteEvent) {
|
remember(noteEvent) {
|
||||||
noteEvent.summary()?.ifBlank { null } ?: noteEvent.content.take(200).ifBlank { null }
|
noteEvent.summary()?.ifBlank { null } ?: noteEvent.content.take(200).ifBlank { null }
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(
|
Column(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.padding(top = Size5dp)
|
.padding(top = Size5dp)
|
||||||
|
@ -83,51 +82,53 @@ private fun LongFormHeader(
|
||||||
QuoteBorder,
|
QuoteBorder,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Column {
|
val automaticallyShowUrlPreview =
|
||||||
val automaticallyShowUrlPreview =
|
remember { accountViewModel.settings.showImages.value }
|
||||||
remember { accountViewModel.settings.showUrlPreview.value }
|
|
||||||
|
|
||||||
if (automaticallyShowUrlPreview) {
|
if (automaticallyShowUrlPreview) {
|
||||||
image?.let {
|
println("ImagePreview: $title $image")
|
||||||
AsyncImage(
|
image?.let {
|
||||||
model = it,
|
println("ImagePreview: Drawing $title $image")
|
||||||
contentDescription =
|
AsyncImage(
|
||||||
stringResource(
|
model = it,
|
||||||
R.string.preview_card_image_for,
|
contentDescription =
|
||||||
it,
|
stringResource(
|
||||||
),
|
R.string.preview_card_image_for,
|
||||||
contentScale = ContentScale.FillWidth,
|
it,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
),
|
||||||
)
|
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),
|
|
||||||
)
|
)
|
||||||
|
} ?: run {
|
||||||
|
println("ImagePreview: DefaultHeader $title $image")
|
||||||
|
DefaultImageHeader(note, accountViewModel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
summary?.let {
|
title?.let {
|
||||||
Spacer(modifier = StdVertSpacer)
|
Text(
|
||||||
Text(
|
text = it,
|
||||||
text = it,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
modifier =
|
||||||
modifier =
|
Modifier
|
||||||
Modifier
|
.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
.padding(start = 10.dp, end = 10.dp, top = 10.dp),
|
||||||
.padding(start = 10.dp, end = 10.dp, bottom = 10.dp),
|
)
|
||||||
color = Color.Gray,
|
}
|
||||||
maxLines = 3,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
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,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,8 +135,9 @@ fun VideoDisplay(
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = MaterialTheme.colorScheme.imageModifier,
|
modifier = MaterialTheme.colorScheme.imageModifier,
|
||||||
)
|
)
|
||||||
|
} ?: run {
|
||||||
|
DefaultImageHeader(note, accountViewModel)
|
||||||
}
|
}
|
||||||
?: DefaultImageHeader(note, accountViewModel)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ZoomableContentView(
|
ZoomableContentView(
|
||||||
|
|
|
@ -789,43 +789,41 @@ private fun RenderClassifiedsReaderForThread(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RenderLongFormHeaderForThread(noteEvent: LongTextNoteEvent) {
|
private fun RenderLongFormHeaderForThread(noteEvent: LongTextNoteEvent) {
|
||||||
Row(modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp)) {
|
Column(modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp)) {
|
||||||
Column {
|
noteEvent.image()?.let {
|
||||||
noteEvent.image()?.let {
|
AsyncImage(
|
||||||
AsyncImage(
|
model = it,
|
||||||
model = it,
|
contentDescription =
|
||||||
contentDescription =
|
stringResource(
|
||||||
stringResource(
|
R.string.preview_card_image_for,
|
||||||
R.string.preview_card_image_for,
|
it,
|
||||||
it,
|
),
|
||||||
),
|
contentScale = ContentScale.FillWidth,
|
||||||
contentScale = ContentScale.FillWidth,
|
modifier = Modifier.fillMaxWidth(),
|
||||||
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)
|
Spacer(modifier = DoubleVertSpacer)
|
||||||
Text(
|
Text(
|
||||||
text = it,
|
text = it,
|
||||||
fontSize = 28.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
color = Color.Gray,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
noteEvent
|
|
||||||
.summary()
|
|
||||||
?.ifBlank { null }
|
|
||||||
?.let {
|
|
||||||
Spacer(modifier = DoubleVertSpacer)
|
|
||||||
Text(
|
|
||||||
text = it,
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
color = Color.Gray,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue