From d8b313088da73dca93554fbe30c15292b30b7537 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 19 Apr 2026 14:34:07 +0000 Subject: [PATCH] fix(dvm-favorites): star click is a no-op + star missing from DVM detail top bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two distinct bugs with the same symptom ("clicking the star doesn't seem to do anything"): 1. LocalCache didn't know how to route kind 10090. FavoriteDvmListEvent was missing from LocalCache's event-type dispatch, so after Account.followFavoriteDvm signs and publishes the event, the cache silently dropped it — never updated favoriteDvmListNote, so account.favoriteDvmList.flow never re-emitted, so the star's filled/outlined state (and the spinner chip) never flipped. Add `is FavoriteDvmListEvent -> consumeBaseReplaceable(...)`. 2. DvmTopBar's toggle never rendered. The Home feed passes the DVM's hex event id via Route.ContentDiscovery, so LoadNote(baseNoteHex) returns a plain Note, not the AddressableNote the toggle needs (the `is AddressableNote` guard was always false). Derive the AddressableNote from the loaded AppDefinitionEvent.address() so the toggle shows up with the correct backing object. --- .../amethyst/model/LocalCache.kt | 2 ++ .../ui/screen/loggedIn/dvms/DvmTopBar.kt | 26 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 347df0b52..339747d75 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -149,6 +149,7 @@ import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent import com.vitorpamplona.quartz.nip51Lists.PinListEvent import com.vitorpamplona.quartz.nip51Lists.bookmarkList.BookmarkListEvent import com.vitorpamplona.quartz.nip51Lists.bookmarkList.OldBookmarkListEvent +import com.vitorpamplona.quartz.nip51Lists.favoriteDvmList.FavoriteDvmListEvent import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent @@ -2635,6 +2636,7 @@ object LocalCache : ILocalCache, ICacheProvider { is LiveChessGameEndEvent -> consumeBaseReplaceable(event, relay, wasVerified) is LiveChessDrawOfferEvent -> consumeBaseReplaceable(event, relay, wasVerified) is HashtagListEvent -> consumeBaseReplaceable(event, relay, wasVerified) + is FavoriteDvmListEvent -> consumeBaseReplaceable(event, relay, wasVerified) is HighlightEvent -> consumeRegularEvent(event, relay, wasVerified) is IndexerRelayListEvent -> consumeBaseReplaceable(event, relay, wasVerified) is InteractiveStoryPrologueEvent -> consumeBaseReplaceable(event, relay, wasVerified) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/DvmTopBar.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/DvmTopBar.kt index d3dcecc66..4ae8cefe5 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/DvmTopBar.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/dvms/DvmTopBar.kt @@ -24,10 +24,12 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.style.TextOverflow -import com.vitorpamplona.amethyst.model.AddressableNote +import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteAndMap import com.vitorpamplona.amethyst.ui.components.LoadNote import com.vitorpamplona.amethyst.ui.components.MyAsyncImage import com.vitorpamplona.amethyst.ui.navigation.navs.INav @@ -37,6 +39,7 @@ import com.vitorpamplona.amethyst.ui.note.elements.BannerImage import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer import com.vitorpamplona.amethyst.ui.theme.SimpleImage35Modifier +import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent @Composable fun DvmTopBar( @@ -87,12 +90,23 @@ fun DvmTopBar( }, navigationIcon = { IconButton(onClick = nav::popBack) { ArrowBackIcon() } }, actions = { + // The route passes the event's hex id, so LoadNote returns a plain Note, + // not the AddressableNote the toggle needs. Derive the AddressableNote + // from the loaded AppDefinitionEvent's address() once the event exists. LoadNote(baseNoteHex = appDefinitionId, accountViewModel = accountViewModel) { appDefinitionNote -> - if (appDefinitionNote is AddressableNote) { - FavoriteDvmToggle( - appDefinitionNote = appDefinitionNote, - accountViewModel = accountViewModel, - ) + if (appDefinitionNote != null) { + val addressableNote by + observeNoteAndMap(appDefinitionNote, accountViewModel) { note -> + (note.event as? AppDefinitionEvent)?.let { + LocalCache.getOrCreateAddressableNote(it.address()) + } + } + addressableNote?.let { target -> + FavoriteDvmToggle( + appDefinitionNote = target, + accountViewModel = accountViewModel, + ) + } } } },