fix follows not working

This commit is contained in:
nrobi144
2026-01-05 13:12:39 +02:00
parent 115c622dca
commit 55d59fcfd2
3 changed files with 69 additions and 44 deletions
@@ -100,12 +100,11 @@ open class RelayConnectionManager(
} }
/** /**
* Broadcasts an event to all configured relays. * Broadcasts an event to all connected relays.
* Events will be sent to relays as they become connected.
*/ */
fun broadcastToAll(event: Event) { fun broadcastToAll(event: Event) {
val configuredRelays = relayStatuses.value.keys val connected = connectedRelays.value
send(event, configuredRelays) send(event, connected)
} }
private fun updateRelayStatus( private fun updateRelayStatus(
@@ -177,24 +177,15 @@ private suspend fun publishNote(
replyTo: com.vitorpamplona.quartz.nip01Core.core.Event?, replyTo: com.vitorpamplona.quartz.nip01Core.core.Event?,
) { ) {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
println("[ComposeNoteDialog] Starting publishNote: content length=${content.length}")
// Check read-only mode // Check read-only mode
if (account.isReadOnly) { if (account.isReadOnly) {
println("[ComposeNoteDialog] Error: Cannot post in read-only mode")
throw IllegalStateException("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 // Use shared PublishAction from commons
val signedEvent = PublishAction.publishTextNote(content, account.signer, replyTo) val signedEvent = PublishAction.publishTextNote(content, account.signer, replyTo)
println("[ComposeNoteDialog] Event signed successfully, ID: ${signedEvent.id.take(8)}...")
// Broadcast to all configured relays // Broadcast to all configured relays
println("[ComposeNoteDialog] Broadcasting to relays...")
relayManager.broadcastToAll(signedEvent) relayManager.broadcastToAll(signedEvent)
println("[ComposeNoteDialog] Broadcast complete")
} }
} }
@@ -122,6 +122,11 @@ fun UserProfileScreen(
FollowState(myPubKeyHex = account?.pubKeyHex ?: "") FollowState(myPubKeyHex = account?.pubKeyHex ?: "")
} }
// Store the user's contact list separately for reliable access
var myContactList by remember(account) { mutableStateOf<ContactListEvent?>(null) }
var contactListLoaded by remember(account) { mutableStateOf(false) }
var eoseReceivedCount by remember(account) { mutableStateOf(0) }
// Load current user's contact list (for follow state) // Load current user's contact list (for follow state)
rememberSubscription(relayStatuses, account, relayManager = relayManager) { rememberSubscription(relayStatuses, account, relayManager = relayManager) {
val configuredRelays = relayStatuses.keys val configuredRelays = relayStatuses.keys
@@ -131,7 +136,22 @@ fun UserProfileScreen(
pubKeyHex = account.pubKeyHex, pubKeyHex = account.pubKeyHex,
onEvent = { event, _, _, _ -> onEvent = { event, _, _, _ ->
if (event is ContactListEvent) { 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) 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( Button(
onClick = { onClick = {
scope.launch { scope.launch {
val currentStatus = followState.currentStatusOrNull()
followState.setFollowLoading() followState.setFollowLoading()
try { try {
val currentStatus = followState.currentStatusOrNull()
val updatedEvent = val updatedEvent =
if (currentStatus?.isFollowing == true) { if (currentStatus?.isFollowing == true) {
unfollowUser(pubKeyHex, account, relayManager, currentStatus.contactList) unfollowUser(pubKeyHex, account, relayManager, myContactList)
} else { } 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) followState.setFollowSuccess(updatedEvent, pubKeyHex)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() 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 state = followState.state.collectAsState().value
val isFollowing = (state as? com.vitorpamplona.amethyst.commons.state.LoadingState.Success)?.data?.isFollowing ?: false 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 val isLoading = state is com.vitorpamplona.amethyst.commons.state.LoadingState.Loading
if (isLoading) { when {
androidx.compose.material3.CircularProgressIndicator( !contactListLoaded -> {
modifier = Modifier.size(16.dp), androidx.compose.material3.CircularProgressIndicator(
strokeWidth = 2.dp, modifier = Modifier.size(16.dp),
color = MaterialTheme.colorScheme.onPrimary, strokeWidth = 2.dp,
) color = MaterialTheme.colorScheme.onPrimary,
Spacer(Modifier.width(8.dp)) )
Text(if (isFollowing) "Unfollowing..." else "Following...") Spacer(Modifier.width(8.dp))
} else { Text("Loading...")
Icon( }
if (isFollowing) Icons.Default.PersonRemove else Icons.Default.PersonAdd, isLoading -> {
contentDescription = if (isFollowing) "Unfollow" else "Follow", androidx.compose.material3.CircularProgressIndicator(
modifier = Modifier.size(18.dp), modifier = Modifier.size(16.dp),
) strokeWidth = 2.dp,
Spacer(Modifier.width(8.dp)) color = MaterialTheme.colorScheme.onPrimary,
Text(if (isFollowing) "Unfollow" else "Follow") )
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?, currentContactList: ContactListEvent?,
): ContactListEvent = ): ContactListEvent =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
println("[UserProfile] Starting followUser: target=${pubKeyHex.take(8)}...")
// Use shared FollowAction from commons // Use shared FollowAction from commons
val updatedEvent = FollowAction.follow(pubKeyHex, account.signer, currentContactList) 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) relayManager.broadcastToAll(updatedEvent)
println("[UserProfile] Follow broadcast complete")
updatedEvent updatedEvent
} }
@@ -482,21 +519,19 @@ private suspend fun unfollowUser(
currentContactList: ContactListEvent?, currentContactList: ContactListEvent?,
): ContactListEvent = ): ContactListEvent =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
println("[UserProfile] Starting unfollowUser: target=${pubKeyHex.take(8)}...")
if (currentContactList != null) { if (currentContactList != null) {
println("[UserProfile] Removing from existing contact list")
// Use shared FollowAction from commons // Use shared FollowAction from commons
val updatedEvent = FollowAction.unfollow(pubKeyHex, account.signer, currentContactList) 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) relayManager.broadcastToAll(updatedEvent)
println("[UserProfile] Unfollow broadcast complete")
updatedEvent updatedEvent
} else { } else {
println("[UserProfile] Error: No contact list to unfollow from")
throw IllegalStateException("Cannot unfollow: No contact list available") throw IllegalStateException("Cannot unfollow: No contact list available")
} }
} }