From 55d59fcfd25eb6bcd7256cca8a4b8bbefcd7f1c7 Mon Sep 17 00:00:00 2001 From: nrobi144 Date: Mon, 5 Jan 2026 13:12:39 +0200 Subject: [PATCH] fix follows not working --- .../commons/network/RelayConnectionManager.kt | 7 +- .../amethyst/desktop/ui/ComposeNoteDialog.kt | 9 -- .../amethyst/desktop/ui/UserProfileScreen.kt | 97 +++++++++++++------ 3 files changed, 69 insertions(+), 44 deletions(-) diff --git a/commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/network/RelayConnectionManager.kt b/commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/network/RelayConnectionManager.kt index dc026c4d7..3e0f7159d 100644 --- a/commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/network/RelayConnectionManager.kt +++ b/commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/network/RelayConnectionManager.kt @@ -100,12 +100,11 @@ open class RelayConnectionManager( } /** - * Broadcasts an event to all configured relays. - * Events will be sent to relays as they become connected. + * Broadcasts an event to all connected relays. */ fun broadcastToAll(event: Event) { - val configuredRelays = relayStatuses.value.keys - send(event, configuredRelays) + val connected = connectedRelays.value + send(event, connected) } private fun updateRelayStatus( diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/ComposeNoteDialog.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/ComposeNoteDialog.kt index bf6ef13a4..a532439fa 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/ComposeNoteDialog.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/ComposeNoteDialog.kt @@ -177,24 +177,15 @@ private suspend fun publishNote( replyTo: com.vitorpamplona.quartz.nip01Core.core.Event?, ) { withContext(Dispatchers.IO) { - println("[ComposeNoteDialog] Starting publishNote: content length=${content.length}") - // Check read-only mode if (account.isReadOnly) { - println("[ComposeNoteDialog] Error: Cannot post in read-only mode") throw IllegalStateException("Cannot post in read-only mode") } - println("[ComposeNoteDialog] Signing event with pubkey: ${account.pubKeyHex.take(8)}...") - // Use shared PublishAction from commons val signedEvent = PublishAction.publishTextNote(content, account.signer, replyTo) - println("[ComposeNoteDialog] Event signed successfully, ID: ${signedEvent.id.take(8)}...") - // Broadcast to all configured relays - println("[ComposeNoteDialog] Broadcasting to relays...") relayManager.broadcastToAll(signedEvent) - println("[ComposeNoteDialog] Broadcast complete") } } diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/UserProfileScreen.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/UserProfileScreen.kt index cc0f51ebb..9dc55d75a 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/UserProfileScreen.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/UserProfileScreen.kt @@ -122,6 +122,11 @@ fun UserProfileScreen( FollowState(myPubKeyHex = account?.pubKeyHex ?: "") } + // Store the user's contact list separately for reliable access + var myContactList by remember(account) { mutableStateOf(null) } + var contactListLoaded by remember(account) { mutableStateOf(false) } + var eoseReceivedCount by remember(account) { mutableStateOf(0) } + // Load current user's contact list (for follow state) rememberSubscription(relayStatuses, account, relayManager = relayManager) { val configuredRelays = relayStatuses.keys @@ -131,7 +136,22 @@ fun UserProfileScreen( pubKeyHex = account.pubKeyHex, onEvent = { event, _, _, _ -> if (event is ContactListEvent) { + // Store the most recent contact list (by createdAt timestamp) + if (myContactList == null || event.createdAt > myContactList!!.createdAt) { + myContactList = event + } + followState.updateContactList(event, pubKeyHex) + contactListLoaded = true + } + }, + onEose = { _, _ -> + eoseReceivedCount++ + + // Wait for EOSE from at least 2 relays or all relays before enabling button + val minEoseCount = minOf(2, configuredRelays.size) + if (eoseReceivedCount >= minEoseCount && !contactListLoaded) { + contactListLoaded = true } }, ) @@ -216,15 +236,19 @@ fun UserProfileScreen( Button( onClick = { scope.launch { + val currentStatus = followState.currentStatusOrNull() + followState.setFollowLoading() try { - val currentStatus = followState.currentStatusOrNull() val updatedEvent = if (currentStatus?.isFollowing == true) { - unfollowUser(pubKeyHex, account, relayManager, currentStatus.contactList) + unfollowUser(pubKeyHex, account, relayManager, myContactList) } else { - followUser(pubKeyHex, account, relayManager, currentStatus?.contactList) + followUser(pubKeyHex, account, relayManager, myContactList) } + + // Update both stored contact list and followState + myContactList = updatedEvent followState.setFollowSuccess(updatedEvent, pubKeyHex) } catch (e: Exception) { e.printStackTrace() @@ -232,28 +256,40 @@ fun UserProfileScreen( } } }, - enabled = followState.state.value !is com.vitorpamplona.amethyst.commons.state.LoadingState.Loading, + enabled = contactListLoaded && followState.state.value !is com.vitorpamplona.amethyst.commons.state.LoadingState.Loading, ) { val state = followState.state.collectAsState().value val isFollowing = (state as? com.vitorpamplona.amethyst.commons.state.LoadingState.Success)?.data?.isFollowing ?: false val isLoading = state is com.vitorpamplona.amethyst.commons.state.LoadingState.Loading - if (isLoading) { - androidx.compose.material3.CircularProgressIndicator( - modifier = Modifier.size(16.dp), - strokeWidth = 2.dp, - color = MaterialTheme.colorScheme.onPrimary, - ) - Spacer(Modifier.width(8.dp)) - Text(if (isFollowing) "Unfollowing..." else "Following...") - } else { - Icon( - if (isFollowing) Icons.Default.PersonRemove else Icons.Default.PersonAdd, - contentDescription = if (isFollowing) "Unfollow" else "Follow", - modifier = Modifier.size(18.dp), - ) - Spacer(Modifier.width(8.dp)) - Text(if (isFollowing) "Unfollow" else "Follow") + when { + !contactListLoaded -> { + androidx.compose.material3.CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp, + color = MaterialTheme.colorScheme.onPrimary, + ) + Spacer(Modifier.width(8.dp)) + Text("Loading...") + } + isLoading -> { + androidx.compose.material3.CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp, + color = MaterialTheme.colorScheme.onPrimary, + ) + Spacer(Modifier.width(8.dp)) + Text(if (isFollowing) "Unfollowing..." else "Following...") + } + else -> { + Icon( + if (isFollowing) Icons.Default.PersonRemove else Icons.Default.PersonAdd, + contentDescription = if (isFollowing) "Unfollow" else "Follow", + modifier = Modifier.size(18.dp), + ) + Spacer(Modifier.width(8.dp)) + Text(if (isFollowing) "Unfollow" else "Follow") + } } } @@ -460,14 +496,15 @@ private suspend fun followUser( currentContactList: ContactListEvent?, ): ContactListEvent = withContext(Dispatchers.IO) { - println("[UserProfile] Starting followUser: target=${pubKeyHex.take(8)}...") - // Use shared FollowAction from commons val updatedEvent = FollowAction.follow(pubKeyHex, account.signer, currentContactList) - println("[UserProfile] ContactListEvent created, broadcasting...") + val connectedRelays = relayManager.connectedRelays.value + if (connectedRelays.isEmpty()) { + throw IllegalStateException("Cannot follow: No connected relays") + } + relayManager.broadcastToAll(updatedEvent) - println("[UserProfile] Follow broadcast complete") updatedEvent } @@ -482,21 +519,19 @@ private suspend fun unfollowUser( currentContactList: ContactListEvent?, ): ContactListEvent = withContext(Dispatchers.IO) { - println("[UserProfile] Starting unfollowUser: target=${pubKeyHex.take(8)}...") - if (currentContactList != null) { - println("[UserProfile] Removing from existing contact list") - // Use shared FollowAction from commons val updatedEvent = FollowAction.unfollow(pubKeyHex, account.signer, currentContactList) - println("[UserProfile] ContactListEvent updated, broadcasting...") + val connectedRelays = relayManager.connectedRelays.value + if (connectedRelays.isEmpty()) { + throw IllegalStateException("Cannot unfollow: No connected relays") + } + relayManager.broadcastToAll(updatedEvent) - println("[UserProfile] Unfollow broadcast complete") updatedEvent } else { - println("[UserProfile] Error: No contact list to unfollow from") throw IllegalStateException("Cannot unfollow: No contact list available") } }