From 309e474a3dd4c570d1a86edfce41962a594b1ab4 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Apr 2026 23:02:53 +0000 Subject: [PATCH] fix(dvm-card): star top-right + move reactions to bottom row MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Putting the star back where the user actually sees DVMs first — the Discover Content card. Two changes that together stop the layout from breaking: - FavoriteDvmToggle now uses ClickableBox + small Icon (no IconButton padding) so it occupies the same compact footprint as LikeReaction. Adding it to LeftPictureLayout's title row no longer inflates the row height. - DVMCard's title row now holds only the name (weight 1) plus the star toggle on the right. LikeReaction and ZapReaction move down to the bottom row, pushed to the far right with a Spacer(weight 1) so the amount/personalised chips stay on the left. --- .../loggedIn/discover/nip90DVMs/DVMCard.kt | 98 +++++++++---------- .../screen/loggedIn/dvms/FavoriteDvmToggle.kt | 24 +++-- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt index 6fa904415..0ca21209b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/DVMCard.kt @@ -21,11 +21,9 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -40,8 +38,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription import com.vitorpamplona.amethyst.ui.components.MyAsyncImage @@ -51,12 +49,12 @@ import com.vitorpamplona.amethyst.ui.note.LikeReaction import com.vitorpamplona.amethyst.ui.note.ZapReaction import com.vitorpamplona.amethyst.ui.note.elements.BannerImage import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel +import com.vitorpamplona.amethyst.ui.screen.loggedIn.dvms.FavoriteDvmToggle import com.vitorpamplona.amethyst.ui.screen.loggedIn.dvms.observeAppDefinition import com.vitorpamplona.amethyst.ui.theme.HalfTopPadding import com.vitorpamplona.amethyst.ui.theme.RowColSpacing5dp import com.vitorpamplona.amethyst.ui.theme.SimpleImageBorder import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer -import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.bitcoinColor import com.vitorpamplona.amethyst.ui.theme.grayText import com.vitorpamplona.amethyst.ui.theme.nip05 @@ -118,25 +116,12 @@ fun RenderContentDVMThumb( overflow = TextOverflow.Ellipsis, modifier = Modifier.weight(1f), ) - Spacer(modifier = StdVertSpacer) - Row( - verticalAlignment = CenterVertically, - horizontalArrangement = RowColSpacing5dp, - ) { - LikeReaction( - baseNote = baseNote, - grayTint = MaterialTheme.colorScheme.onSurface, + if (baseNote is AddressableNote) { + FavoriteDvmToggle( + appDefinitionNote = baseNote, accountViewModel = accountViewModel, - nav, ) } - Spacer(modifier = StdHorzSpacer) - ZapReaction( - baseNote = baseNote, - grayTint = MaterialTheme.colorScheme.onSurface, - accountViewModel = accountViewModel, - nav = nav, - ) }, onDescription = { card.description?.let { @@ -168,22 +153,16 @@ fun RenderContentDVMThumb( color = MaterialTheme.colorScheme.primary amount = card.amount + " Sats" } - Row( - verticalAlignment = CenterVertically, - horizontalArrangement = Arrangement.Absolute.Right, - ) { - Text( - textAlign = TextAlign.End, - text = " $amount ", - color = color, - maxLines = 3, - modifier = - Modifier - .weight(1f, fill = false) - .border(Dp(.1f), color, shape = RoundedCornerShape(20)), - fontSize = 12.sp, - ) - } + Text( + textAlign = TextAlign.End, + text = " $amount ", + color = color, + maxLines = 1, + modifier = + Modifier + .border(Dp(.1f), color, shape = RoundedCornerShape(20)), + fontSize = 12.sp, + ) } Spacer(modifier = StdHorzSpacer) card.personalized?.let { @@ -196,24 +175,35 @@ fun RenderContentDVMThumb( color = MaterialTheme.colorScheme.nip05 name = "Generic" } - Spacer(modifier = StdVertSpacer) - Row( - verticalAlignment = CenterVertically, - horizontalArrangement = Arrangement.Absolute.Right, - ) { - Text( - textAlign = TextAlign.End, - text = " $name ", - color = color, - maxLines = 3, - modifier = - Modifier - .padding(start = 4.dp) - .weight(1f, fill = false) - .border(Dp(.1f), color, shape = RoundedCornerShape(20)), - fontSize = 12.sp, - ) - } + Text( + textAlign = TextAlign.End, + text = " $name ", + color = color, + maxLines = 1, + modifier = + Modifier + .border(Dp(.1f), color, shape = RoundedCornerShape(20)), + fontSize = 12.sp, + ) + } + Spacer(modifier = Modifier.weight(1f)) + Row( + verticalAlignment = CenterVertically, + horizontalArrangement = RowColSpacing5dp, + ) { + LikeReaction( + baseNote = baseNote, + grayTint = MaterialTheme.colorScheme.onSurface, + accountViewModel = accountViewModel, + nav, + ) + Spacer(modifier = StdHorzSpacer) + ZapReaction( + baseNote = baseNote, + grayTint = MaterialTheme.colorScheme.onSurface, + accountViewModel = accountViewModel, + nav = nav, + ) } }, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/FavoriteDvmToggle.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/FavoriteDvmToggle.kt index 98cd9f062..1bed004b7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/FavoriteDvmToggle.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/FavoriteDvmToggle.kt @@ -24,7 +24,6 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Star import androidx.compose.material.icons.outlined.StarBorder import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -33,6 +32,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteAndMap +import com.vitorpamplona.amethyst.ui.components.ClickableBox import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.Size20Modifier @@ -40,14 +40,24 @@ import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.AddressBookmark import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent import com.vitorpamplona.quartz.nip90Dvms.contentDiscoveryRequest.NIP90ContentDiscoveryRequestEvent +/** + * Inline star toggle that follows / unfollows a NIP-90 content-discovery DVM. + * + * Uses [ClickableBox] (no [androidx.compose.material3.IconButton] padding) so it + * fits in a `LeftPictureLayout` title row alongside other compact reactions + * without inflating the row to 48dp. + * + * Hidden until the underlying [AppDefinitionEvent] loads and we can confirm the + * DVM advertises kind 5300 — favouriting any other DVM type would only stall on + * a 6300 reply that never comes. + */ @Composable fun FavoriteDvmToggle( appDefinitionNote: AddressableNote, accountViewModel: AccountViewModel, modifier: Modifier = Modifier, + iconSizeModifier: Modifier = Size20Modifier, ) { - // Only NIP-90 content-discovery DVMs (kind 5300) produce a feed; hide the toggle - // for any other DVM type so users don't favourite something that would never reply. val supportsContentDiscovery by observeNoteAndMap(appDefinitionNote, accountViewModel) { note -> (note.event as? AppDefinitionEvent)?.includeKind(NIP90ContentDiscoveryRequestEvent.KIND) == true @@ -60,7 +70,8 @@ fun FavoriteDvmToggle( val isFavorite = favorites.contains(appDefinitionNote.address) - IconButton( + ClickableBox( + modifier = modifier, onClick = { if (isFavorite) { accountViewModel.unfollowFavoriteDvm(appDefinitionNote.address) @@ -73,20 +84,19 @@ fun FavoriteDvmToggle( ) } }, - modifier = modifier, ) { if (isFavorite) { Icon( imageVector = Icons.Filled.Star, contentDescription = stringRes(R.string.remove_dvm_from_favorites), - modifier = Size20Modifier, + modifier = iconSizeModifier, tint = MaterialTheme.colorScheme.primary, ) } else { Icon( imageVector = Icons.Outlined.StarBorder, contentDescription = stringRes(R.string.add_dvm_to_favorites), - modifier = Size20Modifier, + modifier = iconSizeModifier, tint = MaterialTheme.colorScheme.onSurface, ) }