diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/NappletsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/NappletsScreen.kt index 2696f54a15..f13bfb4fd8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/NappletsScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/NappletsScreen.kt @@ -20,56 +20,42 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.napplets -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.SuggestionChip import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.napplet.NappletLauncher import com.vitorpamplona.amethyst.ui.navigation.navs.INav -import com.vitorpamplona.amethyst.ui.note.ReactionsRow -import com.vitorpamplona.amethyst.ui.note.UserPicture -import com.vitorpamplona.amethyst.ui.note.UsernameDisplay +import com.vitorpamplona.amethyst.ui.note.NoteCompose import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.LoadUser import com.vitorpamplona.amethyst.ui.screen.loggedIn.napplets.datasource.NappletsFilterAssemblerSubscription import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip5dNapplets.NamedNappletEvent -import com.vitorpamplona.quartz.nip5dNapplets.NappletManifest import com.vitorpamplona.quartz.nip5dNapplets.RootNappletEvent /** - * Lists the napplet manifests currently in the local cache (NIP-5D kinds 15129/35129) and opens - * the selected one in the sandboxed [NappletLauncher] host. The top bar carries a follow-list filter - * (like the Pictures/Articles feeds) and each row is a rich card with the author, declared - * capabilities, and the usual reaction bar (reply/boost/like/zap). + * Lists the napplet manifests currently in the local cache (NIP-5D kinds 15129/35129). The top bar + * carries a follow-list filter (like the Pictures/Articles feeds) and each row is rendered through the + * shared [NoteCompose] — the same path the main feed uses for these events — so it gets the author + * header, the [com.vitorpamplona.amethyst.commons.ui.note.StaticWebsiteCard] (title, description, + * capability chips, and an Open button wired to the sandboxed [NappletLauncher]), and the standard + * reaction bar (reply/boost/like/zap) for free, without a second card implementation that could drift. */ @Composable fun NappletsScreen( @@ -104,23 +90,15 @@ fun NappletsScreen( ) } } else { - val context = LocalContext.current LazyColumn(Modifier.fillMaxSize().padding(padding)) { items(visible, key = { it.id }) { event -> - val manifest = event as? NappletManifest ?: return@items - NappletCard( - event = event, - manifest = manifest, + val note = remember(event.id) { Amethyst.instance.cache.getOrCreateNote(event) } + NoteCompose( + baseNote = note, + modifier = Modifier.fillMaxWidth(), + quotesLeft = 3, accountViewModel = accountViewModel, nav = nav, - onClick = { - NappletLauncher.launch( - context = context, - manifest = manifest, - authorPubKey = event.pubKey, - identifier = (event as? NamedNappletEvent)?.identifier() ?: "", - ) - }, ) HorizontalDivider() } @@ -128,73 +106,3 @@ fun NappletsScreen( } } } - -@OptIn(ExperimentalLayoutApi::class) -@Composable -private fun NappletCard( - event: Event, - manifest: NappletManifest, - accountViewModel: AccountViewModel, - nav: INav, - onClick: () -> Unit, -) { - val note = remember(event.id) { Amethyst.instance.cache.getOrCreateNote(event) } - - Column( - modifier = - Modifier - .fillMaxWidth() - .clickable(onClick = onClick) - .padding(horizontal = 16.dp, vertical = 12.dp), - verticalArrangement = Arrangement.spacedBy(6.dp), - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - UserPicture(userHex = event.pubKey, size = 48.dp, accountViewModel = accountViewModel, nav = nav) - Spacer(Modifier.width(12.dp)) - Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) { - Text( - text = manifest.title()?.ifBlank { null } ?: stringResource(R.string.napplet_untitled), - style = MaterialTheme.typography.titleMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - LoadUser(baseUserHex = event.pubKey, accountViewModel) { user -> - if (user != null) { - UsernameDisplay(user, accountViewModel = accountViewModel) - } - } - } - } - - manifest.description()?.takeIf { it.isNotBlank() }?.let { - Text( - text = it, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 3, - overflow = TextOverflow.Ellipsis, - ) - } - - val requires = manifest.requires() - if (requires.isNotEmpty()) { - FlowRow(horizontalArrangement = Arrangement.spacedBy(6.dp)) { - requires.forEach { capability -> - SuggestionChip( - onClick = onClick, - label = { Text(capability.replaceFirstChar { it.uppercase() }) }, - ) - } - } - } - - ReactionsRow( - baseNote = note, - showReactionDetail = true, - addPadding = false, - editState = null, - accountViewModel = accountViewModel, - nav = nav, - ) - } -}