diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt index 683f9a54d..40189567e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt @@ -972,8 +972,6 @@ class NoteLiveSet(u: Note) { val relays = innerRelays.map { it } val zaps = innerZaps.map { it } - val authorChanges = innerMetadata.map { it.note.author }.distinctUntilChanged() - val hasEvent = innerMetadata.map { it.note.event != null }.distinctUntilChanged() val hasReactions = @@ -1011,7 +1009,6 @@ class NoteLiveSet(u: Note) { reports.hasObservers() || relays.hasObservers() || zaps.hasObservers() || - authorChanges.hasObservers() || hasEvent.hasObservers() || hasReactions.hasObservers() || replyCount.hasObservers() || diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt index cc71bdf44..7efedde72 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt @@ -853,9 +853,7 @@ fun Gallery( @Composable fun DisplayAuthorBanner(note: Note) { - val authorState by note.live().authorChanges.observeAsState(note.author) - - authorState?.let { author -> - BannerImage(author, Modifier.fillMaxSize().clip(QuoteBorder)) + WatchAuthor(note) { + BannerImage(it, Modifier.fillMaxSize().clip(QuoteBorder)) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt index 47702a68e..7e380fd09 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt @@ -84,12 +84,15 @@ fun ChatroomHeaderCompose( accountViewModel: AccountViewModel, nav: (String) -> Unit, ) { - val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null) - - if (hasEvent) { + if (baseNote.event != null) { ChatroomComposeChannelOrUser(baseNote, accountViewModel, nav) } else { - BlankNote() + val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null) + if (hasEvent) { + ChatroomComposeChannelOrUser(baseNote, accountViewModel, nav) + } else { + BlankNote() + } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt index ba57c5d1b..ac15c4bfa 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt @@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.note import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -142,11 +143,6 @@ fun HashCheckFailedIcon(iconSize: Dp) { ) } -@Composable -fun LikedIcon(iconSize: Dp) { - LikedIcon(modifier = remember(iconSize) { Modifier.size(iconSize) }) -} - @Composable fun LikedIcon(modifier: Modifier) { Icon( @@ -206,6 +202,18 @@ fun ZappedIcon(modifier: Modifier) { ZapIcon(modifier = modifier, BitcoinOrange) } +@Preview +@Composable +fun ReactionRowIconPreview() { + Row(verticalAlignment = Alignment.CenterVertically) { + CommentIcon(Size20Modifier, Color.Unspecified) + RepostedIcon(Size20Modifier) + LikeIcon(Size20Modifier, Color.Unspecified) + ZapIcon(Size20Modifier) + ZappedIcon(Size20Modifier) + } +} + @Composable fun ZapIcon( modifier: Modifier, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt index f856575cb..a36c9288e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/MultiSetCompose.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.note -import androidx.compose.animation.Crossfade import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -76,8 +75,8 @@ import com.vitorpamplona.amethyst.ui.theme.HalfTopPadding import com.vitorpamplona.amethyst.ui.theme.NotificationIconModifier import com.vitorpamplona.amethyst.ui.theme.NotificationIconModifierSmaller import com.vitorpamplona.amethyst.ui.theme.Size10dp -import com.vitorpamplona.amethyst.ui.theme.Size18dp import com.vitorpamplona.amethyst.ui.theme.Size19dp +import com.vitorpamplona.amethyst.ui.theme.Size20dp import com.vitorpamplona.amethyst.ui.theme.Size25dp import com.vitorpamplona.amethyst.ui.theme.Size35Modifier import com.vitorpamplona.amethyst.ui.theme.Size35dp @@ -223,7 +222,7 @@ fun RenderLikeGallery( ) } else { when (val shortReaction = reactionType) { - "+" -> LikedIcon(modifier.size(Size18dp)) + "+" -> LikedIcon(modifier.size(Size19dp)) "-" -> Text(text = "\uD83D\uDC4E", modifier = modifier) else -> Text(text = shortReaction, modifier = modifier) } @@ -268,7 +267,7 @@ fun RenderBoostGallery( modifier = NotificationIconModifierSmaller, ) { RepostedIcon( - modifier = remember { Modifier.size(Size19dp).align(Alignment.TopEnd) }, + modifier = remember { Modifier.size(Size20dp).align(Alignment.TopEnd) }, ) } @@ -289,7 +288,7 @@ fun RenderBoostGallery( modifier = NotificationIconModifierSmaller, ) { RepostedIcon( - modifier = remember { Modifier.size(Size19dp).align(Alignment.TopEnd) }, + modifier = remember { Modifier.size(Size20dp).align(Alignment.TopEnd) }, ) } @@ -494,13 +493,11 @@ private fun BoxedAuthor( accountViewModel: AccountViewModel, ) { Box(modifier = Size35Modifier.clickable(onClick = { nav(authorRouteFor(note)) })) { - WatchNoteAuthor(note) { targetAuthor -> - Crossfade(targetState = targetAuthor, modifier = Size35Modifier) { author -> - WatchUserMetadataAndFollowsAndRenderUserProfilePictureOrDefaultAuthor( - author, - accountViewModel, - ) - } + WatchAuthorWithBlank(note, Size35Modifier) { author -> + WatchUserMetadataAndFollowsAndRenderUserProfilePictureOrDefaultAuthor( + author, + accountViewModel, + ) } } } @@ -546,16 +543,6 @@ fun WatchUserMetadataAndFollowsAndRenderUserProfilePicture( } } -@Composable -private fun WatchNoteAuthor( - baseNote: Note, - onContent: @Composable (User?) -> Unit, -) { - val author by baseNote.live().authorChanges.observeAsState(baseNote.author) - - onContent(author) -} - @Composable private fun WatchUserMetadata( author: User, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt index 913cc66f4..421f9156c 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NIP05VerificationDisplay.kt @@ -60,6 +60,7 @@ import com.vitorpamplona.amethyst.ui.note.LoadStatuses import com.vitorpamplona.amethyst.ui.note.NIP05CheckingIcon import com.vitorpamplona.amethyst.ui.note.NIP05FailedVerification import com.vitorpamplona.amethyst.ui.note.NIP05VerifiedIcon +import com.vitorpamplona.amethyst.ui.note.WatchAuthor import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.Font14SP import com.vitorpamplona.amethyst.ui.theme.NIP05IconSize @@ -116,9 +117,9 @@ fun ObserveDisplayNip05Status( accountViewModel: AccountViewModel, nav: (String) -> Unit, ) { - val author by baseNote.live().authorChanges.observeAsState() - - author?.let { ObserveDisplayNip05Status(it, columnModifier, accountViewModel, nav) } + WatchAuthor(baseNote = baseNote) { + ObserveDisplayNip05Status(it, columnModifier, accountViewModel, nav) + } } @Composable diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index cff732ba2..e881f6909 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -99,7 +99,6 @@ import coil.request.CachePolicy import coil.request.ImageRequest import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.model.zap import com.vitorpamplona.amethyst.service.ZapPaymentHandler import com.vitorpamplona.amethyst.ui.actions.NewPostView import com.vitorpamplona.amethyst.ui.components.GenericLoadable @@ -111,13 +110,13 @@ import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.DarkerGreen import com.vitorpamplona.amethyst.ui.theme.Font14SP import com.vitorpamplona.amethyst.ui.theme.HalfDoubleVertSpacer -import com.vitorpamplona.amethyst.ui.theme.HalfStartPadding import com.vitorpamplona.amethyst.ui.theme.Height24dpModifier import com.vitorpamplona.amethyst.ui.theme.ModifierWidth3dp import com.vitorpamplona.amethyst.ui.theme.NoSoTinyBorders import com.vitorpamplona.amethyst.ui.theme.ReactionRowExpandButton import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeight import com.vitorpamplona.amethyst.ui.theme.ReactionRowZapraiserSize +import com.vitorpamplona.amethyst.ui.theme.RowColSpacing import com.vitorpamplona.amethyst.ui.theme.Size0dp import com.vitorpamplona.amethyst.ui.theme.Size16Modifier import com.vitorpamplona.amethyst.ui.theme.Size17Modifier @@ -229,7 +228,11 @@ private fun GenericInnerReactionRow( five: @Composable () -> Unit, six: @Composable () -> Unit, ) { - Row(verticalAlignment = CenterVertically, modifier = ReactionRowHeight) { + Row( + verticalAlignment = CenterVertically, + horizontalArrangement = RowColSpacing, + modifier = ReactionRowHeight, + ) { val fullWeight = remember { Modifier.weight(1f) } if (showReactionDetail) { @@ -241,11 +244,11 @@ private fun GenericInnerReactionRow( } } - Row(verticalAlignment = CenterVertically, modifier = fullWeight) { two() } + Row(verticalAlignment = CenterVertically, horizontalArrangement = RowColSpacing, modifier = fullWeight) { two() } - Row(verticalAlignment = CenterVertically, modifier = fullWeight) { three() } + Row(verticalAlignment = CenterVertically, horizontalArrangement = RowColSpacing, modifier = fullWeight) { three() } - Row(verticalAlignment = CenterVertically, modifier = fullWeight) { four() } + Row(verticalAlignment = CenterVertically, horizontalArrangement = RowColSpacing, modifier = fullWeight) { four() } Row(verticalAlignment = CenterVertically, modifier = fullWeight) { five() } @@ -670,7 +673,6 @@ fun TextCount( text = showCount(count), fontSize = Font14SP, color = textColor, - modifier = HalfStartPadding, maxLines = 1, ) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt index 852bcc256..93bda3465 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt @@ -21,7 +21,6 @@ package com.vitorpamplona.amethyst.ui.note import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.Crossfade import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.ExperimentalFoundationApi @@ -77,9 +76,7 @@ fun NoteAuthorPicture( modifier: Modifier = Modifier, onClick: ((User) -> Unit)? = null, ) { - val author by baseNote.live().authorChanges.observeAsState(baseNote.author) - - Crossfade(targetState = author, label = "NoteAuthorPicture") { + WatchAuthorWithBlank(baseNote) { if (it == null) { DisplayBlankAuthor(size, modifier) } else { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt index 10d018bc9..d28211fe2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UsernameDisplay.kt @@ -52,10 +52,43 @@ fun NoteUsernameDisplay( showPlayButton: Boolean = true, textColor: Color = Color.Unspecified, ) { - val authorState by baseNote.live().authorChanges.observeAsState(baseNote.author) + WatchAuthor(baseNote) { + UsernameDisplay(it, weight, showPlayButton, textColor = textColor) + } +} - Crossfade(targetState = authorState, modifier = weight, label = "NoteUsernameDisplay") { - it?.let { UsernameDisplay(it, weight, showPlayButton, textColor = textColor) } +@Composable +fun WatchAuthor( + baseNote: Note, + inner: @Composable (User) -> Unit, +) { + val noteAuthor = baseNote.author + if (noteAuthor != null) { + inner(noteAuthor) + } else { + val authorState by baseNote.live().metadata.observeAsState() + + authorState?.note?.author?.let { + inner(it) + } + } +} + +@Composable +fun WatchAuthorWithBlank( + baseNote: Note, + modifier: Modifier = Modifier, + inner: @Composable (User?) -> Unit, +) { + val noteAuthor = baseNote.author + if (noteAuthor != null) { + inner(noteAuthor) + } else { + val authorState by baseNote.live().metadata.observeAsState() + + Crossfade(targetState = authorState?.note?.author, modifier = modifier, label = "WatchAuthorWithBlank") { newAuthor -> + inner(newAuthor) + } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DefaultImageHeader.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DefaultImageHeader.kt index e021842b5..3e62441f7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DefaultImageHeader.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DefaultImageHeader.kt @@ -38,6 +38,7 @@ import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.ui.note.BaseUserPicture +import com.vitorpamplona.amethyst.ui.note.WatchAuthor import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.Size55dp import com.vitorpamplona.amethyst.ui.theme.authorNotePictureForImageHeader @@ -47,14 +48,12 @@ fun DefaultImageHeader( note: Note, accountViewModel: AccountViewModel, ) { - val authorState by note.live().authorChanges.observeAsState(note.author) - - authorState?.let { author -> + WatchAuthor(baseNote = note) { Box { - BannerImage(author) + BannerImage(it) Box(authorNotePictureForImageHeader.align(Alignment.BottomStart)) { - BaseUserPicture(author, Size55dp, accountViewModel, Modifier) + BaseUserPicture(it, Size55dp, accountViewModel, Modifier) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt index 5c9ca3a4c..2270fd09a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt @@ -99,6 +99,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size39Modifier import com.vitorpamplona.amethyst.ui.theme.Size40Modifier import com.vitorpamplona.amethyst.ui.theme.Size40dp import com.vitorpamplona.amethyst.ui.theme.Size55dp +import com.vitorpamplona.amethyst.ui.theme.VideoReactionColumnPadding import com.vitorpamplona.amethyst.ui.theme.onBackgroundColorFilter import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.quartz.events.FileHeaderEvent @@ -462,7 +463,7 @@ fun ReactionsColumn( Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.padding(bottom = 75.dp, end = 10.dp), + modifier = VideoReactionColumnPadding, ) { ReplyReaction( baseNote = baseNote, @@ -495,7 +496,7 @@ fun ReactionsColumn( nav = nav, iconSize = Size40dp, heartSizeModifier = Size35Modifier, - 28.sp, + iconFontSize = 28.sp, ) ZapReaction( baseNote = baseNote, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt index c18e7e0e0..e1381f1d7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt @@ -21,6 +21,7 @@ package com.vitorpamplona.amethyst.ui.theme import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxWidth @@ -102,6 +103,8 @@ val HalfPadding = Modifier.padding(5.dp) val StdPadding = Modifier.padding(10.dp) val BigPadding = Modifier.padding(15.dp) +val RowColSpacing = Arrangement.spacedBy(3.dp) + val HalfHorzPadding = Modifier.padding(horizontal = 5.dp) val HalfVertPadding = Modifier.padding(vertical = 5.dp) @@ -137,6 +140,8 @@ val ReactionRowExpandButton = Modifier.width(65.dp).padding(start = 31.dp) val WidthAuthorPictureModifier = Modifier.width(55.dp) val WidthAuthorPictureModifierWithPadding = Modifier.width(65.dp) +val VideoReactionColumnPadding = Modifier.padding(bottom = 75.dp) + val DividerThickness = 0.25.dp val ReactionRowHeight = Modifier.height(24.dp).padding(start = 10.dp) @@ -224,4 +229,4 @@ val liveStreamTag = .padding(horizontal = Size5dp) val chatAuthorImage = Modifier.size(20.dp).clip(shape = CircleShape) -val AuthorInfoVideoFeed = Modifier.width(75.dp) +val AuthorInfoVideoFeed = Modifier.width(75.dp).padding(end = 15.dp) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 090e7d146..43a6e6388 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ benchmarkJunit4 = "1.2.3" biometricKtx = "1.2.0-alpha05" blurhash = "1.0.0" coil = "2.6.0" -composeBom = "2024.02.02" +composeBom = "2024.03.00" coreKtx = "1.12.0" espressoCore = "3.5.1" firebaseBom = "32.7.4"