fix(cache): use relayStatuses (available) instead of connectedRelays for subscriptions
Root cause of "0 relays, 0 notes, 0 follows": all screens used connectedRelays as the relay set for subscriptions, but NostrClient uses relay-on-demand — relays only connect when openReqSubscription is called with their URL. This created a deadlock: screens waited for connected relays, but relays only connect when screens subscribe. Fix: use relayStatuses.keys (registered/available relays) which are populated by addDefaultRelays() at startup. openReqSubscription triggers connection on-demand. Affected screens: FeedScreen, UserProfileScreen, ThreadScreen, NotificationsScreen, BookmarksScreen, ReadsScreen, NewDmDialog. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -76,7 +76,8 @@ fun BookmarksScreen(
|
|||||||
onNavigateToThread: (String) -> Unit = {},
|
onNavigateToThread: (String) -> Unit = {},
|
||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
|
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
// Tab state
|
// Tab state
|
||||||
|
|||||||
@@ -166,18 +166,22 @@ fun FeedScreen(
|
|||||||
onNavigateToThread: (String) -> Unit = {},
|
onNavigateToThread: (String) -> Unit = {},
|
||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
||||||
val followedUsers by localCache.followedUsers.collectAsState()
|
val followedUsers by localCache.followedUsers.collectAsState()
|
||||||
|
|
||||||
|
// Available relay URLs — openReqSubscription triggers connection on-demand
|
||||||
|
val allRelayUrls = remember(relayStatuses) { relayStatuses.keys }
|
||||||
|
|
||||||
var replyToEvent by remember { mutableStateOf<Event?>(null) }
|
var replyToEvent by remember { mutableStateOf<Event?>(null) }
|
||||||
var lightboxState by remember { mutableStateOf<LightboxState?>(null) }
|
var lightboxState by remember { mutableStateOf<LightboxState?>(null) }
|
||||||
var feedMode by remember { mutableStateOf(initialFeedMode ?: DesktopPreferences.feedMode) }
|
var feedMode by remember { mutableStateOf(initialFeedMode ?: DesktopPreferences.feedMode) }
|
||||||
|
|
||||||
// Subscribe to contact list (kind 3) — populates localCache.followedUsers
|
// Subscribe to contact list (kind 3) — populates localCache.followedUsers
|
||||||
rememberSubscription(connectedRelays, account, relayManager = relayManager) {
|
rememberSubscription(allRelayUrls, account, relayManager = relayManager) {
|
||||||
if (connectedRelays.isNotEmpty() && account != null) {
|
if (allRelayUrls.isNotEmpty() && account != null) {
|
||||||
createContactListSubscription(
|
createContactListSubscription(
|
||||||
relays = connectedRelays,
|
relays = allRelayUrls,
|
||||||
pubKeyHex = account.pubKeyHex,
|
pubKeyHex = account.pubKeyHex,
|
||||||
onEvent = { event, _, relay, _ ->
|
onEvent = { event, _, relay, _ ->
|
||||||
subscriptionsCoordinator?.consumeEvent(event, relay)
|
subscriptionsCoordinator?.consumeEvent(event, relay)
|
||||||
@@ -189,13 +193,13 @@ fun FeedScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Subscribe to feed events (kind 1) — populates cache via coordinator
|
// Subscribe to feed events (kind 1) — populates cache via coordinator
|
||||||
rememberSubscription(connectedRelays, feedMode, followedUsers, relayManager = relayManager) {
|
rememberSubscription(allRelayUrls, feedMode, followedUsers, relayManager = relayManager) {
|
||||||
if (connectedRelays.isEmpty()) return@rememberSubscription null
|
if (allRelayUrls.isEmpty()) return@rememberSubscription null
|
||||||
|
|
||||||
when (feedMode) {
|
when (feedMode) {
|
||||||
FeedMode.GLOBAL -> {
|
FeedMode.GLOBAL -> {
|
||||||
createGlobalFeedSubscription(
|
createGlobalFeedSubscription(
|
||||||
relays = connectedRelays,
|
relays = allRelayUrls,
|
||||||
onEvent = { event, _, relay, _ ->
|
onEvent = { event, _, relay, _ ->
|
||||||
subscriptionsCoordinator?.consumeEvent(event, relay)
|
subscriptionsCoordinator?.consumeEvent(event, relay)
|
||||||
},
|
},
|
||||||
@@ -206,7 +210,7 @@ fun FeedScreen(
|
|||||||
val follows = followedUsers.toList()
|
val follows = followedUsers.toList()
|
||||||
if (follows.isNotEmpty()) {
|
if (follows.isNotEmpty()) {
|
||||||
createFollowingFeedSubscription(
|
createFollowingFeedSubscription(
|
||||||
relays = connectedRelays,
|
relays = allRelayUrls,
|
||||||
followedUsers = follows,
|
followedUsers = follows,
|
||||||
onEvent = { event, _, relay, _ ->
|
onEvent = { event, _, relay, _ ->
|
||||||
subscriptionsCoordinator?.consumeEvent(event, relay)
|
subscriptionsCoordinator?.consumeEvent(event, relay)
|
||||||
|
|||||||
+2
-1
@@ -112,7 +112,8 @@ fun NotificationsScreen(
|
|||||||
account: AccountState.LoggedIn,
|
account: AccountState.LoggedIn,
|
||||||
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator? = null,
|
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator? = null,
|
||||||
) {
|
) {
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
|
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val notificationState =
|
val notificationState =
|
||||||
remember {
|
remember {
|
||||||
|
|||||||
@@ -187,7 +187,8 @@ fun ReadsScreen(
|
|||||||
onNavigateToThread: (String) -> Unit = {},
|
onNavigateToThread: (String) -> Unit = {},
|
||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
|
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
val eventState =
|
val eventState =
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ fun ThreadScreen(
|
|||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
onReply: (Event) -> Unit = {},
|
onReply: (Event) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
|
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
||||||
|
|
||||||
// Lightbox state
|
// Lightbox state
|
||||||
var lightboxState by remember { mutableStateOf<LightboxState?>(null) }
|
var lightboxState by remember { mutableStateOf<LightboxState?>(null) }
|
||||||
|
|||||||
+2
-1
@@ -124,7 +124,8 @@ fun UserProfileScreen(
|
|||||||
onNavigateToArticle: (String) -> Unit = {},
|
onNavigateToArticle: (String) -> Unit = {},
|
||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
|
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
||||||
|
|
||||||
// User metadata
|
// User metadata
|
||||||
var displayName by remember { mutableStateOf<String?>(null) }
|
var displayName by remember { mutableStateOf<String?>(null) }
|
||||||
|
|||||||
+2
-1
@@ -80,7 +80,8 @@ fun NewDmDialog(
|
|||||||
val cachedUsers by searchState.cachedUserResults.collectAsState()
|
val cachedUsers by searchState.cachedUserResults.collectAsState()
|
||||||
val relaySearchResults by searchState.relaySearchResults.collectAsState()
|
val relaySearchResults by searchState.relaySearchResults.collectAsState()
|
||||||
val isSearchingRelays by searchState.isSearchingRelays.collectAsState()
|
val isSearchingRelays by searchState.isSearchingRelays.collectAsState()
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
|
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
// NIP-50 relay search when local cache has few/no results
|
// NIP-50 relay search when local cache has few/no results
|
||||||
|
|||||||
Reference in New Issue
Block a user