diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 6f6723bdb..818d6773f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -431,25 +431,35 @@ class Account( return HTTPAuthorizationEvent.create(url, method, body, keyPair.privKey!!) } - fun boost(note: Note) { - if (!isWriteable()) return + fun boost(note: Note, signEvent: Boolean = true): Event? { + if (!isWriteable() && signEvent) return null if (note.hasBoostedInTheLast5Minutes(userProfile())) { // has already bosted in the past 5mins - return + return null } note.event?.let { if (it.kind() == 1) { + if (!signEvent) { + return RepostEvent.create(it, keyPair.pubKey.toHexKey()) + } + val event = RepostEvent.create(it, keyPair.privKey!!) Client.send(event) LocalCache.consume(event) + return null } else { + if (!signEvent) { + return GenericRepostEvent.create(it, keyPair.pubKey.toHexKey()) + } val event = GenericRepostEvent.create(it, keyPair.privKey!!) Client.send(event) LocalCache.consume(event) + return null } } + return null } fun broadcast(note: Note) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/GenericRepostEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/GenericRepostEvent.kt index 2a52d4399..c76fee35e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/GenericRepostEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/GenericRepostEvent.kt @@ -29,6 +29,24 @@ class GenericRepostEvent( companion object { const val kind = 16 + fun create(boostedPost: EventInterface, pubKey: HexKey, createdAt: Long = TimeUtils.now()): GenericRepostEvent { + val content = boostedPost.toJson() + + val replyToPost = listOf("e", boostedPost.id()) + val replyToAuthor = listOf("p", boostedPost.pubKey()) + + var tags: List> = listOf(replyToPost, replyToAuthor) + + if (boostedPost is AddressableEvent) { + tags = tags + listOf(listOf("a", boostedPost.address().toTag())) + } + + tags = tags + listOf(listOf("k", "${boostedPost.kind()}")) + + val id = generateId(pubKey, createdAt, kind, tags, content) + return GenericRepostEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") + } + fun create(boostedPost: EventInterface, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): GenericRepostEvent { val content = boostedPost.toJson() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/RepostEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/RepostEvent.kt index 28484c33f..33697560e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/RepostEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/RepostEvent.kt @@ -29,6 +29,22 @@ class RepostEvent( companion object { const val kind = 6 + fun create(boostedPost: EventInterface, pubKey: HexKey, createdAt: Long = TimeUtils.now()): RepostEvent { + val content = boostedPost.toJson() + + val replyToPost = listOf("e", boostedPost.id()) + val replyToAuthor = listOf("p", boostedPost.pubKey()) + + var tags: List> = listOf(replyToPost, replyToAuthor) + + if (boostedPost is AddressableEvent) { + tags = tags + listOf(listOf("a", boostedPost.address().toTag())) + } + + val id = generateId(pubKey, createdAt, kind, tags, content) + return RepostEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") + } + fun create(boostedPost: EventInterface, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): RepostEvent { val content = boostedPost.toJson() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index 52cd217ae..8a4207585 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -678,6 +678,25 @@ fun BoostReaction( val iconButtonModifier = remember { Modifier.size(iconSize) } + var event by remember { + mutableStateOf(null) + } + + if (event != null) { + SignerDialog( + onClose = { + event = null + }, + onPost = { + scope.launch(Dispatchers.IO) { + Client.send(it) + LocalCache.verifyAndConsume(it, null) + event = null + } + }, + event = event!! + ) + } IconButton( modifier = iconButtonModifier, @@ -691,12 +710,22 @@ fun BoostReaction( wantsToBoost = true } } else { - scope.launch { - Toast.makeText( - context, - context.getString(R.string.login_with_a_private_key_to_be_able_to_boost_posts), - Toast.LENGTH_SHORT - ).show() + if (PackageUtils.isAmberInstalled(context)) { + if (accountViewModel.hasBoosted(baseNote)) { + scope.launch(Dispatchers.IO) { + event = accountViewModel.deleteBoostsTo(baseNote, false) + } + } else { + wantsToBoost = true + } + } else { + scope.launch { + Toast.makeText( + context, + context.getString(R.string.login_with_a_private_key_to_be_able_to_boost_posts), + Toast.LENGTH_SHORT + ).show() + } } } } @@ -714,6 +743,11 @@ fun BoostReaction( onQuote = { wantsToBoost = false onQuotePress() + }, + onRepost = { + scope.launch(Dispatchers.IO) { + event = accountViewModel.boost(baseNote, false) + } } ) } @@ -1266,7 +1300,7 @@ private fun DrawViewCount( @OptIn(ExperimentalLayoutApi::class) @Composable -private fun BoostTypeChoicePopup(baseNote: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit, onQuote: () -> Unit) { +private fun BoostTypeChoicePopup(baseNote: Note, accountViewModel: AccountViewModel, onDismiss: () -> Unit, onQuote: () -> Unit, onRepost: () -> Unit) { Popup( alignment = Alignment.BottomCenter, offset = IntOffset(0, -50), @@ -1277,8 +1311,13 @@ private fun BoostTypeChoicePopup(baseNote: Note, accountViewModel: AccountViewMo Button( modifier = Modifier.padding(horizontal = 3.dp), onClick = { - scope.launch(Dispatchers.IO) { - accountViewModel.boost(baseNote) + if (accountViewModel.isWriteable()) { + scope.launch(Dispatchers.IO) { + accountViewModel.boost(baseNote) + onDismiss() + } + } else { + onRepost() onDismiss() } }, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index a40cce74e..a8c19a560 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -119,8 +119,8 @@ class AccountViewModel(val account: Account) : ViewModel() { return account.hasBoosted(baseNote) } - fun deleteBoostsTo(note: Note) { - account.delete(account.boostsTo(note)) + fun deleteBoostsTo(note: Note, signEvent: Boolean = true): DeletionEvent? { + return account.delete(account.boostsTo(note), signEvent) } fun calculateIfNoteWasZappedByAccount(zappedNote: Note): Boolean { @@ -211,8 +211,8 @@ class AccountViewModel(val account: Account) : ViewModel() { } } - fun boost(note: Note) { - account.boost(note) + fun boost(note: Note, signEvent: Boolean = true): Event? { + return account.boost(note, signEvent) } fun removeEmojiPack(usersEmojiList: Note, emojiList: Note) {