diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 3969b0d8f..6ddfc6fd9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -58,7 +58,7 @@ import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryE import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent import com.vitorpamplona.quartz.experimental.relationshipStatus.ContactCardEvent import com.vitorpamplona.quartz.experimental.trustedAssertions.list.TrustProviderListEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.Address import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent import com.vitorpamplona.quartz.nip01Core.core.Event @@ -961,7 +961,7 @@ object LocalCache : ILocalCache, ICacheProvider { @Suppress("DEPRECATION") fun computeReplyTo(event: Event): List = when (event) { - is PollNoteEvent -> { + is ZapPollEvent -> { event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) } } @@ -1059,7 +1059,7 @@ object LocalCache : ILocalCache, ICacheProvider { } fun consume( - event: PollNoteEvent, + event: ZapPollEvent, relay: NormalizedRelayUrl?, wasVerified: Boolean, ) = consumeRegularEvent(event, relay, wasVerified) @@ -3141,7 +3141,7 @@ object LocalCache : ILocalCache, ICacheProvider { is PublicMessageEvent -> consume(event, relay, wasVerified) is PeopleListEvent -> consume(event, relay, wasVerified) is CodeSnippetEvent -> consume(event, relay, wasVerified) - is PollNoteEvent -> consume(event, relay, wasVerified) + is ZapPollEvent -> consume(event, relay, wasVerified) is PollEvent -> consume(event, relay, wasVerified) is PollResponseEvent -> consume(event, relay, wasVerified) is ReactionEvent -> consume(event, relay, wasVerified) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/account/nip01Notifications/FilterNotificationsToPubkey.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/account/nip01Notifications/FilterNotificationsToPubkey.kt index 7b51380d5..aa90e787f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/account/nip01Notifications/FilterNotificationsToPubkey.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/account/nip01Notifications/FilterNotificationsToPubkey.kt @@ -24,7 +24,7 @@ import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter @@ -65,7 +65,7 @@ val NotificationsPerKeyKinds = ChannelMessageEvent.KIND, EphemeralChatEvent.KIND, BadgeAwardEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, PollEvent.KIND, PollResponseEvent.KIND, PublicMessageEvent.KIND, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToAddresses.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToAddresses.kt index b9d6f7c8d..53b0f12cb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToAddresses.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToAddresses.kt @@ -22,7 +22,7 @@ package com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.watchers import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip09Deletions.DeletionEvent @@ -45,7 +45,7 @@ val RepliesAndReactionsToAddressesKinds1 = GenericRepostEvent.KIND, ReportEvent.KIND, LnZapEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, CommentEvent.KIND, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToNotes.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToNotes.kt index 404722223..46f6331d4 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToNotes.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/reqCommand/event/watchers/FilterRepliesAndReactionsToNotes.kt @@ -23,7 +23,7 @@ package com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.watchers import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.quartz.experimental.edits.TextNoteModificationEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent @@ -63,7 +63,7 @@ val RepliesAndReactionsKinds2 = TorrentCommentEvent.KIND, GitReplyEvent.KIND, PollResponseEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, ) fun filterRepliesAndReactionsToNotes( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchPostsByText.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchPostsByText.kt index ad37d97fe..74ad10761 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchPostsByText.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchPostsByText.kt @@ -27,7 +27,7 @@ import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStory import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent import com.vitorpamplona.quartz.experimental.nns.NNSEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter @@ -64,7 +64,7 @@ val SearchPostsByTextKinds1 = AudioHeaderEvent.KIND, AudioTrackEvent.KIND, PinListEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, ChannelCreateEvent.KIND, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 5a2163075..077683c28 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -184,7 +184,7 @@ import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.tags.geohash.geoHashOrScope import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent @@ -1039,7 +1039,7 @@ private fun RenderNoteRow( ) } - is PollNoteEvent -> { + is ZapPollEvent -> { RenderZapPoll( baseNote, makeItShort, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt index a9c5f7a81..4874e5619 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNote.kt @@ -20,6 +20,8 @@ */ package com.vitorpamplona.amethyst.ui.note +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -32,7 +34,6 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -58,8 +59,11 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.clipRect import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.font.FontWeight @@ -93,13 +97,15 @@ import com.vitorpamplona.amethyst.ui.theme.BigPadding import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.Font14SP -import com.vitorpamplona.amethyst.ui.theme.QuoteBorder import com.vitorpamplona.amethyst.ui.theme.Size14Modifier +import com.vitorpamplona.amethyst.ui.theme.SmallishBorder import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn -import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink +import com.vitorpamplona.amethyst.ui.theme.allGoodColor +import com.vitorpamplona.amethyst.ui.theme.grayText import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.ripple24dp -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.amethyst.ui.theme.subtleBorder +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip31Alts.AltTag import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent import kotlinx.collections.immutable.ImmutableList @@ -115,7 +121,7 @@ import kotlin.uuid.Uuid @Composable fun ZapZapPollNotePreview() { val event = - PollNoteEvent( + ZapPollEvent( id = "6ff9bc13d27490f6e3953325260bd996901a143de89886a0608c39e7d0160a72", pubKey = "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a", createdAt = 1729186078, @@ -188,7 +194,7 @@ fun ZapZapPollNotePreview() { @Composable fun ZapZapPollNotePreview2() { val event = - PollNoteEvent( + ZapPollEvent( id = "3064bf97800a4b04b612fc0fd498936eae75fffbdca5bbd09d19a6dc598530ab", pubKey = "f8ff11c7a7d3478355d3b4d174e5a473797a906ea4aa61aa9b6bc0652c1ea17a", createdAt = 1729191389, @@ -311,13 +317,6 @@ private fun OptionNote( modifier = Modifier.padding(vertical = 3.dp), ) { if (!pollViewModel.canZap.value) { - val color = - if (poolOption.consensusThreadhold.value) { - Color.Green.copy(alpha = 0.32f) - } else { - MaterialTheme.colorScheme.mediumImportanceLink - } - ZapVote( baseNote, poolOption, @@ -326,7 +325,7 @@ private fun OptionNote( RenderOptionAfterVote( baseNote, poolOption, - color, + poolOption.consensusThreadhold.value, canPreview, tags, backgroundColor, @@ -366,7 +365,7 @@ private fun OptionNote( private fun RenderOptionAfterVote( baseNote: Note, poolOption: PollOption, - color: Color, + isWinning: Boolean, canPreview: Boolean, tags: ImmutableListOfLists, backgroundColor: MutableState, @@ -376,14 +375,25 @@ private fun RenderOptionAfterVote( Box( Modifier .fillMaxWidth(0.75f) - .clip(shape = QuoteBorder) + .clip(SmallishBorder) .border( - 2.dp, - color, - QuoteBorder, + width = 1.dp, + color = + if (isWinning) { + MaterialTheme.colorScheme.allGoodColor + } else { + MaterialTheme.colorScheme.grayText + }, + shape = SmallishBorder, + ).background( + if (isWinning) { + MaterialTheme.colorScheme.allGoodColor.copy(0.2f) + } else { + MaterialTheme.colorScheme.subtleBorder + }, ), ) { - DisplayProgress(poolOption, color, modifier = Modifier.matchParentSize()) + DisplayProgress(poolOption, isWinning, modifier = Modifier.matchParentSize()) Row( verticalAlignment = Alignment.CenterVertically, @@ -428,22 +438,29 @@ private fun RenderOptionAfterVote( @Composable private fun DisplayProgress( poolOption: PollOption, - color: Color, + isWinning: Boolean, modifier: Modifier, ) { - val progress by poolOption.tally + // Animate the progress bar when a vote is cast + val animatedProgress by animateFloatAsState( + targetValue = poolOption.tally.value, + animationSpec = tween(durationMillis = 800), + ) - // The LinearProgressIndicator has some weird update issues and renders inaccurate percentages. - Box(modifier = modifier) { - Box( - modifier = - Modifier - .fillMaxWidth(progress) - .fillMaxHeight() - .background(color = color), - ) { - } - } + val progressBarColor = if (isWinning) MaterialTheme.colorScheme.allGoodColor else MaterialTheme.colorScheme.primary + + Box( + modifier = + modifier + .alpha(0.32f) + .drawWithContent { + // Clip the drawing area to show only the progress amount + clipRect(right = size.width * animatedProgress) { + drawRect(progressBarColor) + } + drawContent() + }, + ) } @Composable @@ -475,11 +492,11 @@ private fun RenderOptionBeforeVote( Box( Modifier .fillMaxWidth(0.75f) - .clip(shape = QuoteBorder) + .clip(SmallishBorder) .border( - 2.dp, - MaterialTheme.colorScheme.primary, - QuoteBorder, + width = 1.dp, + color = MaterialTheme.colorScheme.placeholderText, + shape = SmallishBorder, ), ) { Column(BigPadding) { @@ -568,7 +585,19 @@ fun ZapVote( showErrorMessageDialog = StringToastMsg(title, message) }, onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } }, - onPayViaIntent = {}, + onPayViaIntent = { + if (it.size == 1) { + val payable = it.first() + payViaIntent(payable.invoice, context, { }) { error -> + zappingProgress = 0f + showErrorMessageDialog = StringToastMsg(stringRes(context, R.string.error_dialog_zap_error), error) + } + } else { + val uid = Uuid.random().toString() + accountViewModel.tempManualPaymentCache.put(uid, it) + nav.nav(Route.ManualZapSplitPayment(uid)) + } + }, ) } else { wantsToZap = true diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt index 62d8be2b7..58e304779 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapPollNoteViewModel.kt @@ -29,7 +29,7 @@ import androidx.lifecycle.viewModelScope import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent import com.vitorpamplona.quartz.utils.TimeUtils @@ -53,7 +53,7 @@ class PollNoteViewModel : ViewModel() { private lateinit var account: Account private var pollNote: Note? = null - private var pollEvent: PollNoteEvent? = null + private var pollEvent: ZapPollEvent? = null private var pollOptions: Map? = null private var valueMaximum: Long? = null private var valueMinimum: Long? = null @@ -76,7 +76,7 @@ class PollNoteViewModel : ViewModel() { fun load(note: Note?) { if (pollNote != note) { pollNote = note - pollEvent = pollNote?.event as PollNoteEvent + pollEvent = pollNote?.event as ZapPollEvent pollOptions = pollEvent?.pollOptions() valueMaximum = pollEvent?.maxAmount() valueMinimum = pollEvent?.minAmount() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollConsensusThreshold.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollConsensusThreshold.kt new file mode 100644 index 000000000..8c3f47472 --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollConsensusThreshold.kt @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.note.creators.zappolls + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel +import com.vitorpamplona.amethyst.ui.stringRes +import com.vitorpamplona.amethyst.ui.theme.placeholderText +import kotlinx.coroutines.CancellationException + +@Composable +fun ZapPollConsensusThreshold(pollViewModel: ShortNotePostViewModel) { + var text by rememberSaveable { mutableStateOf("") } + + pollViewModel.isValidConsensusThreshold.value = true + if (text.isNotEmpty()) { + try { + val int = text.toInt() + if (int !in 0..100) { + pollViewModel.isValidConsensusThreshold.value = false + } else { + pollViewModel.zapPollConsensusThreshold = int + } + } catch (e: Exception) { + if (e is CancellationException) throw e + pollViewModel.isValidConsensusThreshold.value = false + } + } + + val colorInValid = + OutlinedTextFieldDefaults.colors( + focusedBorderColor = MaterialTheme.colorScheme.error, + unfocusedBorderColor = Color.Red, + ) + val colorValid = + OutlinedTextFieldDefaults.colors( + focusedBorderColor = MaterialTheme.colorScheme.primary, + unfocusedBorderColor = MaterialTheme.colorScheme.placeholderText, + ) + + Row( + Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + OutlinedTextField( + value = text, + onValueChange = { text = it }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + modifier = Modifier.width(150.dp), + colors = if (pollViewModel.isValidConsensusThreshold.value) colorValid else colorInValid, + label = { + Text( + text = stringRes(R.string.poll_consensus_threshold), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + placeholder = { + Text( + text = stringRes(R.string.poll_consensus_threshold_percent), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + ) + } +} + +@SuppressLint("ViewModelConstructorInComposable") +@Preview +@Composable +fun ZapPollConsensusThresholdPreview() { + ZapPollConsensusThreshold(ShortNotePostViewModel()) +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollDeadlinePicker.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollDeadlinePicker.kt new file mode 100644 index 000000000..295c2d8d2 --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollDeadlinePicker.kt @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.note.creators.zappolls + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DateRange +import androidx.compose.material3.DatePicker +import androidx.compose.material3.DatePickerDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.SelectableDates +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TimePicker +import androidx.compose.material3.TimePickerDialog +import androidx.compose.material3.rememberDatePickerState +import androidx.compose.material3.rememberTimePickerState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.note.timeAheadNoDot +import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel +import com.vitorpamplona.amethyst.ui.stringRes +import com.vitorpamplona.quartz.utils.TimeUtils +import java.time.Instant +import java.time.ZoneId +import java.time.ZoneOffset + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ZapPollDeadlinePicker(model: ShortNotePostViewModel) { + var showDatePicker by remember { mutableStateOf(false) } + var showTimePicker by remember { mutableStateOf(false) } + + // Get current time details + val currentTime = Instant.ofEpochMilli(model.zapPollClosedAt * 1000).atZone(ZoneId.systemDefault()).toLocalDateTime() + + val datePickerState = + rememberDatePickerState( + initialSelectedDateMillis = model.zapPollClosedAt * 1000, + yearRange = currentTime.year..2050, + selectableDates = + object : SelectableDates { + override fun isSelectableDate(utcTimeMillis: Long): Boolean { + // Only allow today and future dates + return utcTimeMillis >= System.currentTimeMillis() - 86400000 // minus 24h buffer + } + }, + ) + val timePickerState = + rememberTimePickerState( + initialHour = currentTime.hour, + initialMinute = currentTime.minute, + is24Hour = false, // Set to true if you prefer military time + ) + + val context = LocalContext.current + + OutlinedCard( + onClick = { showDatePicker = true }, + modifier = Modifier.fillMaxWidth(), + ) { + Row( + modifier = Modifier.padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon(Icons.Default.DateRange, contentDescription = stringResource(R.string.accessibility_select_date)) + Spacer(Modifier.width(12.dp)) + + if (model.zapPollClosedAt < TimeUtils.oneMinuteFromNow()) { + Text(stringRes(R.string.poll_closing_date_time) + " " + model.zapPollClosedAt, style = MaterialTheme.typography.bodyLarge) + } else { + Text( + text = stringRes(R.string.poll_closing_in, timeAheadNoDot(model.zapPollClosedAt, context)), + style = MaterialTheme.typography.bodyLarge, + ) + } + } + } + + // --- Date Picker Dialog --- + if (showDatePicker) { + DatePickerDialog( + onDismissRequest = { showDatePicker = false }, + confirmButton = { + TextButton(onClick = { + showDatePicker = false + showTimePicker = true + }) { Text(stringResource(R.string.next)) } + }, + ) { + DatePicker(state = datePickerState) + } + } + + // --- Time Picker Dialog --- + if (showTimePicker) { + TimePickerDialog( + title = { + Text(stringResource(R.string.closing_time)) + }, + onDismissRequest = { showTimePicker = false }, + confirmButton = { + TextButton( + onClick = { + val datetimeLocalTimeZone = + datePickerState.selectedDateMillis?.let { localDayAtZeroHourMillis -> + (localDayAtZeroHourMillis / 1000) + + (timePickerState.hour * TimeUtils.ONE_HOUR) + + (timePickerState.minute * TimeUtils.ONE_MINUTE) + } ?: TimeUtils.oneDayAhead() + + // Get the offset from UTC for the current instant in the local time zone + val offset: ZoneOffset = ZoneId.systemDefault().rules.getOffset(Instant.now()) + + model.zapPollClosedAt = datetimeLocalTimeZone - offset.totalSeconds + + showTimePicker = false + }, + ) { Text(stringResource(R.string.confirm)) } + }, + ) { + TimePicker(state = timePickerState) + } + } +} + +@SuppressLint("ViewModelConstructorInComposable") +@Preview +@Composable +fun ZapPollDeadlinePickerPreview() { + ZapPollDeadlinePicker( + ShortNotePostViewModel(), + ) +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollField.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollField.kt new file mode 100644 index 000000000..78e2c02af --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollField.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.note.creators.zappolls + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel +import com.vitorpamplona.amethyst.ui.stringRes + +@Composable +fun ZapPollField(postViewModel: ShortNotePostViewModel) { + val optionsList = postViewModel.zapPollOptions + Column( + modifier = Modifier.fillMaxWidth(), + ) { + optionsList.forEach { value -> + ZapPollOption(postViewModel, value.key) + } + + Spacer(Modifier.height(8.dp)) + + ZapPollDeadlinePicker(postViewModel) + + ZapPollVoteValueRange(postViewModel) + + Button( + onClick = { + // postViewModel.pollOptions[postViewModel.pollOptions.size] = "" + optionsList[optionsList.size] = "" + }, + border = + BorderStroke( + 1.dp, + MaterialTheme.colorScheme.outlineVariant, + ), + colors = + ButtonDefaults.outlinedButtonColors( + containerColor = MaterialTheme.colorScheme.surface, + ), + ) { + Icon(Icons.Default.Add, contentDescription = stringRes(R.string.add_poll_option_button)) + } + } +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollOption.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollOption.kt new file mode 100644 index 000000000..4bdee9e07 --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollOption.kt @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.note.creators.zappolls + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.tooling.preview.Preview +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel +import com.vitorpamplona.amethyst.ui.stringRes +import com.vitorpamplona.amethyst.ui.theme.placeholderText + +@Composable +fun ZapPollOption( + pollViewModel: ShortNotePostViewModel, + optionIndex: Int, +) { + Row { + val deleteIcon: @Composable (() -> Unit) = { + IconButton( + onClick = { + pollViewModel.removeZapPollOption(optionIndex) + }, + ) { + Icon( + imageVector = Icons.Default.Delete, + contentDescription = stringRes(R.string.clear), + ) + } + } + + OutlinedTextField( + modifier = Modifier.weight(1F), + value = pollViewModel.zapPollOptions[optionIndex] ?: "", + onValueChange = { + pollViewModel.updateZapPollOption(optionIndex, it) + }, + label = { + Text( + text = stringRes(R.string.poll_option_index).format(optionIndex + 1), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + placeholder = { + Text( + text = stringRes(R.string.poll_option_description), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + keyboardOptions = + KeyboardOptions.Default.copy( + capitalization = KeyboardCapitalization.Sentences, + ), + // colors = if (pollViewModel.pollOptions[optionIndex]?.isNotEmpty() == true) colorValid else + // colorInValid, + trailingIcon = if (optionIndex > 1) deleteIcon else null, + ) + } +} + +@SuppressLint("ViewModelConstructorInComposable") +@Preview +@Composable +fun ZapPollOptionPreview() { + ZapPollOption(ShortNotePostViewModel(), 0) +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollVoteValueRange.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollVoteValueRange.kt new file mode 100644 index 000000000..ea72c02ed --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/zappolls/ZapPollVoteValueRange.kt @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.note.creators.zappolls + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel +import com.vitorpamplona.amethyst.ui.stringRes +import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer +import com.vitorpamplona.amethyst.ui.theme.placeholderText + +@Composable +fun ZapPollVoteValueRange(pollViewModel: ShortNotePostViewModel) { + val colorInValid = + OutlinedTextFieldDefaults.colors( + focusedBorderColor = MaterialTheme.colorScheme.error, + unfocusedBorderColor = Color.Red, + ) + val colorValid = + OutlinedTextFieldDefaults.colors( + focusedBorderColor = MaterialTheme.colorScheme.primary, + unfocusedBorderColor = MaterialTheme.colorScheme.placeholderText, + ) + + Row( + Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + OutlinedTextField( + value = pollViewModel.zapPollValueMinimum?.toString() ?: "", + onValueChange = { pollViewModel.updateMinZapAmountForPoll(it) }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + modifier = Modifier.weight(1f), + colors = if (pollViewModel.isValidValueMinimum.value) colorValid else colorInValid, + label = { + Text( + text = stringRes(R.string.poll_zap_value_min), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + placeholder = { + Text( + text = stringRes(R.string.sats), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + ) + + Spacer(modifier = DoubleHorzSpacer) + + OutlinedTextField( + value = pollViewModel.zapPollValueMaximum?.toString() ?: "", + onValueChange = { pollViewModel.updateMaxZapAmountForPoll(it) }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + modifier = Modifier.weight(1f), + colors = if (pollViewModel.isValidValueMaximum.value) colorValid else colorInValid, + label = { + Text( + text = stringRes(R.string.poll_zap_value_max), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + placeholder = { + Text( + text = stringRes(R.string.sats), + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + ) + } + + Row( + Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + Text( + text = stringRes(R.string.poll_zap_value_min_max_explainer), + color = MaterialTheme.colorScheme.placeholderText, + modifier = Modifier.padding(vertical = 10.dp), + ) + } +} + +@SuppressLint("ViewModelConstructorInComposable") +@Preview +@Composable +fun ZapPollVoteValueRangePreview() { + Column( + modifier = Modifier.fillMaxWidth(), + ) { + ZapPollVoteValueRange(ShortNotePostViewModel()) + } +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt index aa40605d6..48847aa61 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt @@ -45,7 +45,7 @@ import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.placeholderText -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hasHashtags import com.vitorpamplona.quartz.nip01Core.tags.people.hasAnyTaggedUser import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent @@ -61,7 +61,7 @@ fun RenderZapPoll( accountViewModel: AccountViewModel, nav: INav, ) { - val noteEvent = note.event as? PollNoteEvent ?: return + val noteEvent = note.event as? ZapPollEvent ?: return val eventContent = noteEvent.content val showReply by diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedConversationsFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedConversationsFeedFilter.kt index 6571ea514..5aa7ccc44 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedConversationsFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedConversationsFeedFilter.kt @@ -32,7 +32,7 @@ import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.amethyst.ui.dal.FilterByListParams import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent @@ -102,7 +102,7 @@ class FollowPackFeedConversationsFeedFilter( ): Boolean = ( event is TextNoteEvent || - event is PollNoteEvent || + event is ZapPollEvent || event is ChannelMessageEvent || event is CommentEvent || event is VoiceReplyEvent || diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedNewThreadFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedNewThreadFeedFilter.kt index 15e043a7a..3b97682e7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedNewThreadFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/followPacks/feed/dal/FollowPackFeedNewThreadFeedFilter.kt @@ -34,7 +34,7 @@ import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent import com.vitorpamplona.quartz.nip18Reposts.RepostEvent @@ -130,7 +130,7 @@ class FollowPackFeedNewThreadFeedFilter( noteEvent is GenericRepostEvent || (noteEvent is LongTextNoteEvent && noteEvent.content.isNotEmpty()) || (noteEvent is WikiNoteEvent && noteEvent.content.isNotEmpty()) || - noteEvent is PollNoteEvent || + noteEvent is ZapPollEvent || noteEvent is HighlightEvent || noteEvent is InteractiveStoryPrologueEvent || noteEvent is CommentEvent || diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/dal/GeoHashFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/dal/GeoHashFeedFilter.kt index b00fbc9a1..723b1a437 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/dal/GeoHashFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/dal/GeoHashFeedFilter.kt @@ -26,7 +26,7 @@ import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHash @@ -77,7 +77,7 @@ class GeoHashFeedFilter( event is WikiNoteEvent || event is ChannelMessageEvent || event is PrivateDmEvent || - event is PollNoteEvent || + event is ZapPollEvent || event is AudioHeaderEvent ) && event.isTaggedGeoHash(geohash) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/datasource/FilterPostsByGeohash.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/datasource/FilterPostsByGeohash.kt index 913be738d..4c02ec0a5 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/datasource/FilterPostsByGeohash.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/geohash/datasource/FilterPostsByGeohash.kt @@ -24,7 +24,7 @@ import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip22Comments.CommentKinds import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl @@ -43,7 +43,7 @@ val PostsByGeohashKinds = ChannelMessageEvent.KIND, LongTextNoteEvent.KIND, PollEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, ClassifiedsEvent.KIND, HighlightEvent.KIND, AudioTrackEvent.KIND, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/dal/HashtagFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/dal/HashtagFeedFilter.kt index e9c468e94..f5fc6b497 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/dal/HashtagFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/dal/HashtagFeedFilter.kt @@ -26,7 +26,7 @@ import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHash @@ -81,7 +81,7 @@ class HashtagFeedFilter( event is WikiNoteEvent || event is ChannelMessageEvent || event is PrivateDmEvent || - event is PollNoteEvent || + event is ZapPollEvent || event is AudioHeaderEvent ) && event.isTaggedHash(hashTag) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/datasource/FilterPostsByHashtags.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/datasource/FilterPostsByHashtags.kt index 69bbeed3d..3c4528c71 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/datasource/FilterPostsByHashtags.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/hashtag/datasource/FilterPostsByHashtags.kt @@ -26,7 +26,7 @@ import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl @@ -61,7 +61,7 @@ val PostsByHashtagKinds2 = AudioTrackEvent.KIND, AudioHeaderEvent.KIND, NipTextEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, ) fun filterPostsByHashtags( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt index 7239f8e82..015501132 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt @@ -94,15 +94,18 @@ import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.AddSecretEmojiBut import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.SecretEmojiRequest import com.vitorpamplona.amethyst.ui.note.creators.uploads.ImageVideoDescription import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList +import com.vitorpamplona.amethyst.ui.note.creators.zappolls.ZapPollField import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.AddZapraiserButton import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton import com.vitorpamplona.amethyst.ui.note.types.ReplyRenderType +import com.vitorpamplona.amethyst.ui.painterRes import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.Size10dp +import com.vitorpamplona.amethyst.ui.theme.Size19Modifier import com.vitorpamplona.amethyst.ui.theme.Size35dp import com.vitorpamplona.amethyst.ui.theme.Size5dp import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer @@ -299,6 +302,15 @@ private fun NewPostScreenBody( } } + if (postViewModel.wantsZapPoll) { + Row( + verticalAlignment = CenterVertically, + modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp), + ) { + ZapPollField(postViewModel) + } + } + DisplayPreviews(postViewModel.urlPreviews, accountViewModel, nav) if (postViewModel.wantsToMarkAsSensitive) { @@ -531,11 +543,24 @@ private fun BottomRowActions(postViewModel: ShortNotePostViewModel) { ) if (postViewModel.canUsePoll) { - // These should be hashtag recommendations the user selects in the future. - // val hashtag = stringRes(R.string.poll_hashtag) - // postViewModel.includePollHashtagInMessage(postViewModel.wantsPoll, hashtag) AddPollButton(postViewModel.wantsPoll) { postViewModel.wantsPoll = !postViewModel.wantsPoll + if (postViewModel.wantsPoll) { + if (postViewModel.wantsZapPoll) { + postViewModel.wantsZapPoll = false + } + } + } + } + + if (postViewModel.canUseZapPoll) { + AddZapPollButton(postViewModel.wantsZapPoll) { + postViewModel.wantsZapPoll = !postViewModel.wantsZapPoll + if (postViewModel.wantsZapPoll) { + if (postViewModel.wantsPoll) { + postViewModel.wantsPoll = false + } + } } } @@ -584,6 +609,32 @@ private fun BottomRowActionsPreview() { } } +@Composable +private fun AddZapPollButton( + isPollActive: Boolean, + onClick: () -> Unit, +) { + IconButton( + onClick = { onClick() }, + ) { + if (!isPollActive) { + Icon( + painter = painterRes(R.drawable.ic_poll, 1), + contentDescription = stringRes(id = R.string.poll), + modifier = Size19Modifier, + tint = MaterialTheme.colorScheme.onBackground, + ) + } else { + Icon( + painter = painterRes(R.drawable.ic_poll, 1), + contentDescription = stringRes(id = R.string.disable_poll), + modifier = Size19Modifier, + tint = MaterialTheme.colorScheme.primary, + ) + } + } +} + @Composable private fun AddPollButton( isPollActive: Boolean, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt index 87fd5939a..1efc07c84 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt @@ -71,6 +71,12 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.privateDM.send.IMetaA import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent +import com.vitorpamplona.quartz.experimental.zapPolls.closedAt +import com.vitorpamplona.quartz.experimental.zapPolls.consensusThreshold +import com.vitorpamplona.quartz.experimental.zapPolls.maxAmount +import com.vitorpamplona.quartz.experimental.zapPolls.minAmount +import com.vitorpamplona.quartz.experimental.zapPolls.tags.PollOptionTag import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate @@ -230,6 +236,20 @@ open class ShortNotePostViewModel : var pollOptions: SnapshotStateMap = newStateMapPollOptions() var closedAt by mutableLongStateOf(TimeUtils.oneDayAhead()) + // ZapPolls + var canUseZapPoll by mutableStateOf(false) + var wantsZapPoll by mutableStateOf(false) + var zapPollOptions: SnapshotStateMap = newStateMapZapPollOptions() + var zapPollValueMaximum by mutableStateOf(null) + var zapPollValueMinimum by mutableStateOf(null) + var zapPollConsensusThreshold: Int? = null + var zapPollClosedAt by mutableLongStateOf(TimeUtils.oneDayAhead()) + + var isValidValueMaximum = mutableStateOf(true) + var isValidValueMinimum = mutableStateOf(true) + var isValidConsensusThreshold = mutableStateOf(true) + var isValidClosedAt = mutableStateOf(true) + // Invoices var canAddInvoice by mutableStateOf(false) var wantsInvoice by mutableStateOf(false) @@ -333,6 +353,7 @@ open class ShortNotePostViewModel : canAddInvoice = user.lnAddress() != null canAddZapRaiser = user.lnAddress() != null canUsePoll = originalNote == null + canUseZapPoll = originalNote == null multiOrchestrator = null quote?.let { quotedNote -> @@ -417,6 +438,10 @@ open class ShortNotePostViewModel : if (draftEvent is PollEvent) { loadFromDraft(draftEvent) } + + if (draftEvent is ZapPollEvent) { + loadFromDraft(draftEvent) + } } private fun loadFromDraft(draftEvent: TextNoteEvent) { @@ -489,12 +514,14 @@ open class ShortNotePostViewModel : } canUsePoll = originalNote == null + canUseZapPoll = originalNote == null if (forwardZapTo.value.items.isNotEmpty()) { wantsForwardZapTo = true } wantsPoll = false + wantsZapPoll = false message = TextFieldValue(draftEvent.content) @@ -550,11 +577,14 @@ open class ShortNotePostViewModel : } canUsePoll = originalNote == null + canUseZapPoll = originalNote == null if (forwardZapTo.value.items.isNotEmpty()) { wantsForwardZapTo = true } + wantsZapPoll = false + val polls = draftEvent.options() wantsPoll = polls.isNotEmpty() @@ -571,6 +601,80 @@ open class ShortNotePostViewModel : urlPreviews.update(message) } + private fun loadFromDraft(draftEvent: ZapPollEvent) { + canAddInvoice = accountViewModel.userProfile().lnAddress() != null + canAddZapRaiser = accountViewModel.userProfile().lnAddress() != null + multiOrchestrator = null + + val localForwardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" } + forwardZapTo.value = SplitBuilder() + localForwardZapTo.forEach { + val user = LocalCache.getOrCreateUser(it[1]) + val value = it.last().toFloatOrNull() ?: 0f + forwardZapTo.value.addItem(user, value) + } + forwardZapToEditting.value = TextFieldValue("") + wantsForwardZapTo = localForwardZapTo.isNotEmpty() + + wantsToMarkAsSensitive = draftEvent.isSensitive() + contentWarningDescription = draftEvent.contentWarningReason() ?: "" + + val draftExpiration = draftEvent.tags.expiration() + wantsExpirationDate = draftExpiration != null + expirationDate = draftExpiration ?: TimeUtils.oneDayAhead() + + val geohash = draftEvent.getGeoHash() + wantsToAddGeoHash = geohash != null + if (geohash != null) { + wantsExclusiveGeoPost = draftEvent.kind == CommentEvent.KIND + } + + val zapRaiser = draftEvent.zapraiserAmount() + wantsZapRaiser = zapRaiser != null + zapRaiserAmount.value = null + if (zapRaiser != null) { + zapRaiserAmount.value = zapRaiser + } + + eTags = + draftEvent.tags.filter { it.size > 1 && (it[0] == "e" || it[0] == "a") && it.getOrNull(3) != "fork" }.mapNotNull { + val note = LocalCache.checkGetOrCreateNote(it[1]) + note + } + + pTags = + draftEvent.tags.filter { it.size > 1 && it[0] == "p" }.map { + LocalCache.getOrCreateUser(it[1]) + } + + canUsePoll = originalNote == null + canUseZapPoll = originalNote == null + + if (forwardZapTo.value.items.isNotEmpty()) { + wantsForwardZapTo = true + } + + wantsPoll = false + + val polls = draftEvent.pollOptionsArray() + wantsZapPoll = polls.isNotEmpty() + + polls.forEach { tag -> + zapPollOptions[tag.index] = tag.descriptor + } + + zapPollValueMinimum = draftEvent.minAmount() + zapPollValueMaximum = draftEvent.maxAmount() + zapPollConsensusThreshold = draftEvent.consensusThreshold()?.let { (it * 100).toInt() } + zapPollClosedAt = draftEvent.closedAt() ?: TimeUtils.oneDayAhead() + + message = TextFieldValue(draftEvent.content) + + iMetaAttachments.addAll(draftEvent.imetas()) + + urlPreviews.update(message) + } + suspend fun sendPostSync() { // Upload voice message first if it hasn't been uploaded yet if (voiceRecording != null && voiceMetadata == null) { @@ -731,6 +835,35 @@ open class ShortNotePostViewModel : contentWarningReason?.let { contentWarning(it) } localExpirationDate?.let { expiration(it) } + emojis(emojis) + imetas(usedAttachments) + } + } else if (wantsZapPoll) { + val options = zapPollOptions.map { PollOptionTag(it.key, it.value) } + + if (options.isEmpty()) return null + + val quotes = findNostrUris(tagger.message) + val relays = + accountViewModel.account.nip65RelayList.outboxFlow.value + .toList() + + ZapPollEvent.build(tagger.message, options) { + zapPollValueMinimum?.let { minAmount(it) } + zapPollValueMaximum?.let { maxAmount(it) } + zapPollClosedAt?.let { closedAt(it) } + zapPollConsensusThreshold?.let { consensusThreshold(it / 100.0) } + + pTags(tagger.directMentionsUsers.map { it.toPTag() }) + quotes(quotes) + hashtags(findHashtags(tagger.message)) + + geoHash?.let { geohash(it) } + localZapRaiserAmount?.let { zapraiser(it) } + zapReceiver?.let { zapSplits(it) } + contentWarningReason?.let { contentWarning(it) } + localExpirationDate?.let { expiration(it) } + emojis(emojis) imetas(usedAttachments) } @@ -915,6 +1048,13 @@ open class ShortNotePostViewModel : pollOptions = newStateMapPollOptions() closedAt = TimeUtils.oneDayAhead() + wantsZapPoll = false + zapPollOptions = newStateMapZapPollOptions() + zapPollValueMaximum = null + zapPollValueMinimum = null + zapPollConsensusThreshold = null + zapPollClosedAt = TimeUtils.oneDayAhead() + wantsInvoice = false wantsZapRaiser = false zapRaiserAmount.value = null @@ -1032,6 +1172,12 @@ open class ShortNotePostViewModel : 1 to OptionTag(RandomInstance.randomChars(6), ""), ) + private fun newStateMapZapPollOptions(): SnapshotStateMap = + mutableStateMapOf( + 0 to "", + 1 to "", + ) + fun canPost(): Boolean { // Voice messages can be posted without text (with either uploaded or pending recording) if (voiceMetadata != null || voiceRecording != null) { @@ -1052,6 +1198,14 @@ open class ShortNotePostViewModel : closedAt > TimeUtils.oneMinuteFromNow() ) ) && + ( + !wantsZapPoll || + ( + zapPollOptions.values.all { it.isNotEmpty() } && + isValidValueMinimum.value && + isValidValueMaximum.value + ) + ) && multiOrchestrator == null } @@ -1254,6 +1408,61 @@ open class ShortNotePostViewModel : this.putAll(newEntries) } + // --- + // Zap Polls + // --- + + fun updateMinZapAmountForPoll(textMin: String) { + zapPollValueMinimum = textMin.toLongOrNull()?.takeIf { it > 0 } + checkMinMax() + draftTag.newVersion() + } + + fun updateMaxZapAmountForPoll(textMax: String) { + zapPollValueMaximum = textMax.toLongOrNull()?.takeIf { it > 0 } + checkMinMax() + draftTag.newVersion() + } + + fun checkMinMax() { + if ((zapPollValueMinimum ?: 0) > (zapPollValueMaximum ?: Long.MAX_VALUE)) { + isValidValueMinimum.value = false + isValidValueMaximum.value = false + } else { + isValidValueMinimum.value = true + isValidValueMaximum.value = true + } + } + + fun removeZapPollOption(optionIndex: Int) { + zapPollOptions.removeOrderedZapPoll(optionIndex) + draftTag.newVersion() + } + + private fun MutableMap.removeOrderedZapPoll(index: Int) { + val keyList = keys + val elementList = values.toMutableList() + run stop@{ + for (i in index until elementList.size) { + val nextIndex = i + 1 + if (nextIndex == elementList.size) return@stop + elementList[i] = elementList[nextIndex].also { elementList[nextIndex] = "null" } + } + } + elementList.removeAt(elementList.size - 1) + val newEntries = keyList.zip(elementList) { key, content -> Pair(key, content) } + this.clear() + this.putAll(newEntries) + } + + fun updateZapPollOption( + optionIndex: Int, + text: String, + ) { + zapPollOptions[optionIndex] = text + draftTag.newVersion() + } + fun toggleMarkAsSensitive() { wantsToMarkAsSensitive = !wantsToMarkAsSensitive draftTag.newVersion() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeConversationsFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeConversationsFeedFilter.kt index 53384e1dd..82a368184 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeConversationsFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeConversationsFeedFilter.kt @@ -29,7 +29,7 @@ import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.amethyst.ui.dal.FilterByListParams import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent @@ -81,7 +81,7 @@ class HomeConversationsFeedFilter( ): Boolean = ( event is TextNoteEvent || - event is PollNoteEvent || + event is ZapPollEvent || event is PollResponseEvent || event is ChannelMessageEvent || event is CommentEvent || diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeNewThreadFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeNewThreadFeedFilter.kt index fc4193fe8..66f61eca9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeNewThreadFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/dal/HomeNewThreadFeedFilter.kt @@ -32,7 +32,7 @@ import com.vitorpamplona.amethyst.ui.dal.FilterByListParams import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent import com.vitorpamplona.quartz.nip18Reposts.RepostEvent @@ -116,7 +116,7 @@ class HomeNewThreadFeedFilter( noteEvent is GenericRepostEvent || (noteEvent is LongTextNoteEvent && noteEvent.content.isNotEmpty()) || (noteEvent is WikiNoteEvent && noteEvent.content.isNotEmpty()) || - noteEvent is PollNoteEvent || + noteEvent is ZapPollEvent || noteEvent is PollEvent || noteEvent is HighlightEvent || noteEvent is InteractiveStoryPrologueEvent || diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/FilterHomePostsByAuthors.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/FilterHomePostsByAuthors.kt index e6c9c2cfb..0aa7d3a1a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/FilterHomePostsByAuthors.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/FilterHomePostsByAuthors.kt @@ -26,7 +26,7 @@ import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter @@ -60,7 +60,7 @@ val HomePostsNewThreadKinds = HighlightEvent.KIND, WikiNoteEvent.KIND, NipTextEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, PollEvent.KIND, InteractiveStoryPrologueEvent.KIND, ChessGameEvent.KIND, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/dal/NotificationFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/dal/NotificationFeedFilter.kt index 718cdfcb7..8c757dad6 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/dal/NotificationFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/dal/NotificationFeedFilter.kt @@ -33,7 +33,7 @@ import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent import com.vitorpamplona.quartz.experimental.forks.IForkableEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser @@ -106,7 +106,7 @@ class NotificationFeedFilter( LiveActivitiesChatMessageEvent.KIND, PictureEvent.KIND, PollEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, PrivateDmEvent.KIND, PublicMessageEvent.KIND, VideoNormalEvent.KIND, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/conversations/dal/UserProfileConversationsFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/conversations/dal/UserProfileConversationsFeedFilter.kt index 660a390f6..273433753 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/conversations/dal/UserProfileConversationsFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/conversations/dal/UserProfileConversationsFeedFilter.kt @@ -27,7 +27,7 @@ import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip22Comments.CommentEvent import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent @@ -64,7 +64,7 @@ class UserProfileConversationsFeedFilter( it.author == user && ( it.event is TextNoteEvent || - it.event is PollNoteEvent || + it.event is ZapPollEvent || it.event is PollResponseEvent || it.event is ChannelMessageEvent || it.event is LiveActivitiesChatMessageEvent || diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/datasource/FilterUserProfilePosts.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/datasource/FilterUserProfilePosts.kt index d95d5f51b..a77b676b6 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/datasource/FilterUserProfilePosts.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/datasource/FilterUserProfilePosts.kt @@ -26,7 +26,7 @@ import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent @@ -64,7 +64,7 @@ val UserProfilePostKinds2 = InteractiveStoryPrologueEvent.KIND, CommentEvent.KIND, VoiceReplyEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, PinListEvent.KIND, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/mutual/dal/UserProfileMutualFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/mutual/dal/UserProfileMutualFeedFilter.kt index 920c0d3e3..ce44c3921 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/mutual/dal/UserProfileMutualFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/mutual/dal/UserProfileMutualFeedFilter.kt @@ -32,7 +32,7 @@ import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent @@ -78,7 +78,7 @@ class UserProfileMutualFeedFilter( it.event is LongTextNoteEvent || it.event is WikiNoteEvent || it.event is NipTextEvent || - it.event is PollNoteEvent || + it.event is ZapPollEvent || it.event is HighlightEvent || it.event is InteractiveStoryPrologueEvent || it.event is AudioTrackEvent || diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/newthreads/dal/UserProfileNewThreadFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/newthreads/dal/UserProfileNewThreadFeedFilter.kt index cf401a723..ea7964f1a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/newthreads/dal/UserProfileNewThreadFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/newthreads/dal/UserProfileNewThreadFeedFilter.kt @@ -31,7 +31,7 @@ import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent @@ -80,7 +80,7 @@ class UserProfileNewThreadFeedFilter( it.event is LongTextNoteEvent || it.event is WikiNoteEvent || it.event is NipTextEvent || - it.event is PollNoteEvent || + it.event is ZapPollEvent || it.event is PollEvent || it.event is HighlightEvent || it.event is InteractiveStoryPrologueEvent || diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relay/datasource/FilterPostsByRelay.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relay/datasource/FilterPostsByRelay.kt index 84ac86e8c..a1538e336 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relay/datasource/FilterPostsByRelay.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relay/datasource/FilterPostsByRelay.kt @@ -25,7 +25,7 @@ import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl @@ -58,7 +58,7 @@ val PostsByRelayKinds2 = AudioTrackEvent.KIND, AudioHeaderEvent.KIND, NipTextEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, ) fun filterPostsByRelay( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/RelayInformationScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/RelayInformationScreen.kt index 99e11bc7a..80e4e2a5f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/RelayInformationScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/RelayInformationScreen.kt @@ -146,7 +146,7 @@ import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryE import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent import com.vitorpamplona.quartz.experimental.relationshipStatus.ContactCardEvent import com.vitorpamplona.quartz.experimental.trustedAssertions.list.TrustProviderListEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import com.vitorpamplona.quartz.nip01Core.relay.client.stats.ErrorDebugMessage @@ -619,7 +619,7 @@ private fun kindDisplayName(kind: Int): Int = PeopleListEvent.KIND -> R.string.kind_people_lists PictureEvent.KIND -> R.string.kind_pictures PinListEvent.KIND -> R.string.kind_pins - PollNoteEvent.KIND -> R.string.kind_zap_poll + ZapPollEvent.KIND -> R.string.kind_zap_poll PollEvent.KIND -> R.string.kind_poll PollResponseEvent.KIND -> R.string.kind_poll_response PrivateDmEvent.KIND -> R.string.kind_nip04_dms diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt index 27bc8972a..82e84b9cc 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt @@ -199,7 +199,7 @@ import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStory import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.tags.geohash.geoHashOrScope import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent @@ -692,7 +692,7 @@ private fun FullBleedNoteCompose( accountViewModel, nav, ) - } else if (noteEvent is PollNoteEvent) { + } else if (noteEvent is ZapPollEvent) { RenderZapPoll( baseNote, false, diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/subscriptions/SearchFilterFactory.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/subscriptions/SearchFilterFactory.kt index 6a61b000d..c918ea775 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/subscriptions/SearchFilterFactory.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/subscriptions/SearchFilterFactory.kt @@ -28,7 +28,7 @@ import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStory import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent import com.vitorpamplona.quartz.experimental.nns.NNSEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip22Comments.CommentEvent @@ -61,7 +61,7 @@ object SearchFilterFactory { AudioHeaderEvent.KIND, AudioTrackEvent.KIND, PinListEvent.KIND, - PollNoteEvent.KIND, + ZapPollEvent.KIND, ChannelCreateEvent.KIND, ) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt index 3b9fbdd86..bec27039a 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/TagArrayBuilderExt.kt @@ -27,19 +27,19 @@ import com.vitorpamplona.quartz.experimental.zapPolls.tags.MinimumTag import com.vitorpamplona.quartz.experimental.zapPolls.tags.PollOptionTag import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder -fun TagArrayBuilder.consensusThreshold(percentage: Double) = addUnique(ConsensusThresholdTag.assemble(percentage)) +fun TagArrayBuilder.consensusThreshold(percentage: Double) = addUnique(ConsensusThresholdTag.assemble(percentage)) -fun TagArrayBuilder.minAmount(value: Long) = addUnique(MinimumTag.assemble(value)) +fun TagArrayBuilder.minAmount(value: Long) = addUnique(MinimumTag.assemble(value)) -fun TagArrayBuilder.maxAmount(value: Long) = addUnique(MaximumTag.assemble(value)) +fun TagArrayBuilder.maxAmount(value: Long) = addUnique(MaximumTag.assemble(value)) -fun TagArrayBuilder.closedAt(timestamp: Long) = addUnique(ClosedAtTag.assemble(timestamp)) +fun TagArrayBuilder.closedAt(timestamp: Long) = addUnique(ClosedAtTag.assemble(timestamp)) -fun TagArrayBuilder.pollOption( +fun TagArrayBuilder.pollOption( index: Int, description: String, ) = add(PollOptionTag.assemble(index, description)) -fun TagArrayBuilder.pollOptions(options: Map) = addAll(options.map { PollOptionTag.assemble(it.key, it.value) }) +fun TagArrayBuilder.pollOptions(options: Map) = addAll(options.map { PollOptionTag.assemble(it.key, it.value) }) -fun TagArrayBuilder.pollOptions(options: List) = addAll(options.map { it.toTagArray() }) +fun TagArrayBuilder.pollOptions(options: List) = addAll(options.map { it.toTagArray() }) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/ZapPollEvent.kt similarity index 96% rename from quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt rename to quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/ZapPollEvent.kt index 19bf092b5..b22d81aed 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/experimental/zapPolls/ZapPollEvent.kt @@ -51,7 +51,7 @@ import com.vitorpamplona.quartz.nip50Search.SearchableEvent import com.vitorpamplona.quartz.utils.TimeUtils @Immutable -class PollNoteEvent( +class ZapPollEvent( id: HexKey, pubKey: HexKey, createdAt: Long, @@ -131,9 +131,9 @@ class PollNoteEvent( post: String, options: List, createdAt: Long = TimeUtils.now(), - initializer: TagArrayBuilder.() -> Unit = {}, - ): EventTemplate { - val tags = TagArrayBuilder() + initializer: TagArrayBuilder.() -> Unit = {}, + ): EventTemplate { + val tags = TagArrayBuilder() tags.pollOptions(options) tags.alt(ALT_DESCRIPTION) tags.apply(initializer) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt index aa97b5d76..a8710fdac 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/EventFactory.kt @@ -38,7 +38,7 @@ import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryE import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent import com.vitorpamplona.quartz.experimental.relationshipStatus.ContactCardEvent import com.vitorpamplona.quartz.experimental.trustedAssertions.list.TrustProviderListEvent -import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent +import com.vitorpamplona.quartz.experimental.zapPolls.ZapPollEvent import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.crypto.EventHasher @@ -282,7 +282,7 @@ class EventFactory { PeopleListEvent.KIND -> PeopleListEvent(id, pubKey, createdAt, tags, content, sig) PictureEvent.KIND -> PictureEvent(id, pubKey, createdAt, tags, content, sig) PinListEvent.KIND -> PinListEvent(id, pubKey, createdAt, tags, content, sig) - PollNoteEvent.KIND -> PollNoteEvent(id, pubKey, createdAt, tags, content, sig) + ZapPollEvent.KIND -> ZapPollEvent(id, pubKey, createdAt, tags, content, sig) PollEvent.KIND -> PollEvent(id, pubKey, createdAt, tags, content, sig) PollResponseEvent.KIND -> PollResponseEvent(id, pubKey, createdAt, tags, content, sig) PrivateDmEvent.KIND -> PrivateDmEvent(id, pubKey, createdAt, tags, content, sig)