feat(dvm-favorites): rename user-facing to "Favorite Feed Algorithms" + fix cold-start race
- User-facing rename. All user-visible strings switch from "favourite" to "favorite" (American spelling) and from "DVM(s)" to "Feed Algorithm(s)": settings entry, spinner group label, empty state, banner messages, menu accessibility labels. Code identifiers still reference NIP-90's "DVM" protocol name since that's the wire spec. - Cold-start race. When the app relaunches with a persisted TopFilter.FavoriteDvm, the AppDefinitionEvent may not be in cache yet. mergeInterests was filtering out any favorite whose AppDefinitionEvent didn't yet advertise kind 5300, so the spinner didn't include a chip matching the persisted selection — it showed "Select an option" while the orchestrator quietly fired the RPC with no UI to ground it. Always include every favorite; the 5300 check at add time (in FavoriteDvmToggle) is enough.
This commit is contained in:
+2
-2
@@ -45,7 +45,7 @@ import kotlinx.coroutines.sync.withLock
|
||||
private const val RESPONSE_TIMEOUT_MS = 20_000L
|
||||
|
||||
/**
|
||||
* Immutable snapshot of a favourite DVM's current request/response state.
|
||||
* Immutable snapshot of a favorite DVM's current request/response state.
|
||||
*
|
||||
* - [requestId] is the id of the most recently published kind-5300 request.
|
||||
* - [responseRelays] is the relay set the kind-5300 was sent to — the same set on
|
||||
@@ -65,7 +65,7 @@ data class FavoriteDvmSnapshot(
|
||||
)
|
||||
|
||||
/**
|
||||
* Manages the NIP-90 content-discovery RPC cycle for each favourite DVM the user
|
||||
* Manages the NIP-90 content-discovery RPC cycle for each favorite DVM the user
|
||||
* pins to the top-nav.
|
||||
*
|
||||
* The orchestrator is lazy: it starts a request/response cycle the first time any
|
||||
|
||||
+2
-2
@@ -34,9 +34,9 @@ import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
|
||||
/**
|
||||
* Feed flow that merges snapshots from every currently-favourited DVM into a
|
||||
* Feed flow that merges snapshots from every currently-favorited DVM into a
|
||||
* single [AllFavoriteDvmsTopNavFilter]. Re-wires subscriptions whenever the
|
||||
* favourite set changes.
|
||||
* favorite set changes.
|
||||
*/
|
||||
class AllFavoriteDvmsFeedFlow(
|
||||
val favoriteDvmAddresses: StateFlow<Set<Address>>,
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
/**
|
||||
* Top-nav filter that unions the latest kind-6300 responses from every currently
|
||||
* favourited DVM. Behaves like [FavoriteDvmTopNavFilter] (pure membership check
|
||||
* favorited DVM. Behaves like [FavoriteDvmTopNavFilter] (pure membership check
|
||||
* against a snapshot), but the accepted set is the union across N DVMs and the
|
||||
* request-id list carries one entry per DVM for the relay-listen subscription.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
/**
|
||||
* Top-nav filter backed by the latest kind-6300 response from a favourite DVM.
|
||||
* Top-nav filter backed by the latest kind-6300 response from a favorite DVM.
|
||||
*
|
||||
* The filter is a pure immutable membership check: [match] accepts a note only if the
|
||||
* DVM's latest response included it. When a new response arrives, a new instance is
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
* - [listenRelays] — the union of DVM publish relays across all active DVMs
|
||||
* (where they will deliver future kind 6300 / 7000 events for their requests).
|
||||
* - [requestIds] — the set of currently-active kind-5300 request ids to listen
|
||||
* for. A single-DVM filter carries one; the merged "All favourite DVMs"
|
||||
* filter carries one per favourite DVM.
|
||||
* for. A single-DVM filter carries one; the merged "All favorite DVMs"
|
||||
* filter carries one per favorite DVM.
|
||||
*/
|
||||
class FavoriteDvmTopNavPerRelayFilterSet(
|
||||
val contentFetches: Map<NormalizedRelayUrl, FavoriteDvmTopNavPerRelayFilter>,
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.displayUrl
|
||||
import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent
|
||||
import com.vitorpamplona.quartz.nip90Dvms.contentDiscoveryRequest.NIP90ContentDiscoveryRequestEvent
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
@@ -182,24 +181,22 @@ class TopNavFilterState(
|
||||
)
|
||||
}
|
||||
|
||||
// Only DVMs that advertise NIP-90 content discovery (kind 5300) can produce a
|
||||
// home feed. Hide entries whose AppDefinitionEvent isn't loaded yet OR doesn't
|
||||
// include kind 5300 so the chip doesn't appear for image-generation, translation,
|
||||
// search, or other DVM kinds that would never reply.
|
||||
// Favorites can only be added through FavoriteDvmToggle, which itself checks
|
||||
// that the AppDefinitionEvent advertises kind 5300. Don't re-check here: on
|
||||
// cold start the AppDefinitionEvent may not be in cache yet, and dropping
|
||||
// the entry means the persisted TopFilter.FavoriteDvm can't find its chip
|
||||
// in the spinner (user sees "Select an option" while the banner fires the
|
||||
// RPC — the bug we had before this change).
|
||||
val favoriteDvms =
|
||||
favoriteDvmList.mapNotNull { dvmNote ->
|
||||
val supports5300 =
|
||||
(dvmNote.event as? AppDefinitionEvent)
|
||||
?.includeKind(NIP90ContentDiscoveryRequestEvent.KIND) == true
|
||||
if (!supports5300) return@mapNotNull null
|
||||
favoriteDvmList.map { dvmNote ->
|
||||
FeedDefinition(
|
||||
TopFilter.FavoriteDvm(dvmNote.address),
|
||||
FavoriteDvmName(dvmNote),
|
||||
)
|
||||
}
|
||||
|
||||
// Only show the "All favourite DVMs" meta-chip when there is at least one
|
||||
// real favourite to merge; otherwise the chip opens to an empty feed.
|
||||
// Only show the "All favorite DVMs" meta-chip when there is at least one
|
||||
// real favorite to merge; otherwise the chip opens to an empty feed.
|
||||
val allFavorites =
|
||||
if (favoriteDvms.isNotEmpty()) listOf(allFavoriteDvmsFollow) else emptyList()
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ import com.vitorpamplona.quartz.nip90Dvms.contentDiscoveryResponse.NIP90ContentD
|
||||
import com.vitorpamplona.quartz.nip90Dvms.status.NIP90StatusEvent
|
||||
|
||||
/**
|
||||
* Builds relay REQ filters for a favourite-DVM home feed.
|
||||
* Builds relay REQ filters for a favorite-DVM home feed.
|
||||
*
|
||||
* Two distinct subscription kinds with two distinct relay sets:
|
||||
*
|
||||
|
||||
@@ -1728,20 +1728,20 @@
|
||||
<string name="feed_group_locations">Locations</string>
|
||||
<string name="feed_group_communities">Communities</string>
|
||||
<string name="feed_group_lists">Lists</string>
|
||||
<string name="feed_group_dvms">DVMs</string>
|
||||
<string name="follow_list_all_favorite_dvms">All favourite DVMs</string>
|
||||
<string name="feed_group_dvms">Feed Algorithms</string>
|
||||
<string name="follow_list_all_favorite_dvms">All favorite feed algorithms</string>
|
||||
<string name="feed_group_relays">Relays</string>
|
||||
|
||||
<string name="add_dvm_to_favorites">Add DVM to favorites</string>
|
||||
<string name="add_dvm_to_favorites">Add feed algorithm to favorites</string>
|
||||
<string name="remove_dvm_from_favorites">Remove from favorites</string>
|
||||
<string name="favorite_dvms_title">Favourite DVMs</string>
|
||||
<string name="favorite_dvms_explainer">Content-discovery DVMs you starred here appear as filter chips on the Home feed. Open Discover to add more.</string>
|
||||
<string name="favorite_dvms_empty">No favourite DVMs yet. Open Discover, tap a content-discovery DVM, and star it to add it here.</string>
|
||||
<string name="favorite_dvms_title">Favorite Feed Algorithms</string>
|
||||
<string name="favorite_dvms_explainer">Feed algorithms you starred here appear as filter chips on the Home feed. Open Discover to add more.</string>
|
||||
<string name="favorite_dvms_empty">No favorite feed algorithms yet. Open Discover, tap one, and star it to add it here.</string>
|
||||
<string name="dvm_home_status_requesting">Asking %1$s for a feed…</string>
|
||||
<string name="dvm_home_status_requesting_all">Asking your favourite DVMs for feeds…</string>
|
||||
<string name="dvm_home_status_requesting_all">Asking your favorite feed algorithms for feeds…</string>
|
||||
<string name="dvm_home_status_processing">Processing your feed…</string>
|
||||
<string name="dvm_home_status_payment_required">This DVM requires payment</string>
|
||||
<string name="dvm_home_status_error">DVM returned an error</string>
|
||||
<string name="dvm_home_status_payment_required">This feed algorithm requires payment</string>
|
||||
<string name="dvm_home_status_error">The feed algorithm returned an error</string>
|
||||
<string name="dvm_home_retry">Retry</string>
|
||||
|
||||
<string name="temporary_account">Log off on device lock</string>
|
||||
|
||||
Reference in New Issue
Block a user