diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 340ca2339..055cb6ae2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -935,6 +935,8 @@ class Account( fun upgradeAttestations() = otsState.upgradeAttestationsIfNeeded(::sendAutomatic) + suspend fun follow(users: List) = sendMyPublicAndPrivateOutbox(kind3FollowList.follow(users)) + suspend fun follow(user: User) = sendMyPublicAndPrivateOutbox(kind3FollowList.follow(user)) suspend fun unfollow(user: User) = sendMyPublicAndPrivateOutbox(kind3FollowList.unfollow(user)) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip02FollowLists/Kind3FollowListState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip02FollowLists/Kind3FollowListState.kt index de3fba5d6..528b19cf5 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip02FollowLists/Kind3FollowListState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip02FollowLists/Kind3FollowListState.kt @@ -113,6 +113,25 @@ class Kind3FollowListState( ) } + suspend fun follow(users: List): ContactListEvent { + val contactList = getFollowListEvent() + + val contacts = + users.map { + ContactTag(user.pubkeyHex, user.bestRelayHint(), null) + } + + return if (contactList != null) { + ContactListEvent.followUsers(contactList, contacts, signer) + } else { + ContactListEvent.createFromScratch( + followUsers = contacts, + relayUse = emptyMap(), + signer = signer, + ) + } + } + suspend fun follow(user: User): ContactListEvent { val contactList = getFollowListEvent() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index d26c6a8c6..e950ea523 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -914,6 +914,8 @@ class AccountViewModel( fun unfollow(channel: EphemeralChatChannel) = launchSigner { account.unfollow(channel) } + fun follow(users: List) = launchSigner { account.follow(users) } + fun follow(user: User) = launchSigner { account.follow(user) } fun unfollow(user: User) = launchSigner { account.unfollow(user) } diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt index a371e1335..d4961a0aa 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt @@ -123,6 +123,25 @@ class ContactListEvent( ) } + suspend fun followUsers( + earlierVersion: ContactListEvent, + users: List, + signer: NostrSigner, + createdAt: Long = TimeUtils.now(), + ): ContactListEvent { + val follows = earlierVersion.verifiedFollowKeySet() + val toBeAdded = users.filter { it.pubKey !in follows }.distinctBy { it.pubKey }.map { it.toTagArray() } + + if (toBeAdded.isEmpty()) return earlierVersion + + return create( + content = earlierVersion.content, + tags = earlierVersion.tags + toBeAdded, + signer = signer, + createdAt = createdAt, + ) + } + suspend fun unfollowUser( earlierVersion: ContactListEvent, pubKeyHex: String,