fix(dvm-card): star top-right + move reactions to bottom row
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.
This commit is contained in:
+44
-54
@@ -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,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
+17
-7
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user