From 8525f2b930fe3762de4f9738b2e4a3ac2dab5950 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Mar 2026 02:50:46 +0000 Subject: [PATCH] feat: add poll type selector for single and multiple choice polls The poll creation UI now shows filter chips to choose between single choice and multiple choice poll types. Previously it was hardcoded to single choice only. https://claude.ai/code/session_01PEsEyGiNvNcNPSjREN4WzW --- .../note/creators/polls/PollOptionsField.kt | 32 +++++++++++++++++++ .../loggedIn/home/ShortNotePostViewModel.kt | 6 +++- amethyst/src/main/res/values/strings.xml | 2 ++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/polls/PollOptionsField.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/polls/PollOptionsField.kt index 5a973d304..a95acdcdf 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/polls/PollOptionsField.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/polls/PollOptionsField.kt @@ -22,7 +22,9 @@ package com.vitorpamplona.amethyst.ui.note.creators.polls import android.annotation.SuppressLint import androidx.compose.foundation.BorderStroke +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.height @@ -32,6 +34,7 @@ import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Delete import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.FilterChip import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -47,6 +50,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.ShortNotePostViewModel import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.quartz.nip88Polls.poll.tags.OptionTag +import com.vitorpamplona.quartz.nip88Polls.poll.tags.PollType import com.vitorpamplona.quartz.utils.RandomInstance @Composable @@ -55,6 +59,13 @@ fun PollOptionsField(postViewModel: ShortNotePostViewModel) { Column( modifier = Modifier.fillMaxWidth(), ) { + PollTypeSelector( + selectedType = postViewModel.pollType, + onTypeSelected = { postViewModel.pollType = it }, + ) + + Spacer(Modifier.height(4.dp)) + optionsList.forEach { option -> OutlinedTextField( modifier = Modifier.fillMaxWidth(), @@ -118,6 +129,27 @@ fun PollOptionsField(postViewModel: ShortNotePostViewModel) { } } +@Composable +fun PollTypeSelector( + selectedType: PollType, + onTypeSelected: (PollType) -> Unit, +) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + FilterChip( + selected = selectedType == PollType.SINGLE_CHOICE, + onClick = { onTypeSelected(PollType.SINGLE_CHOICE) }, + label = { Text(stringRes(R.string.poll_single_choice)) }, + ) + FilterChip( + selected = selectedType == PollType.MULTI_CHOICE, + onClick = { onTypeSelected(PollType.MULTI_CHOICE) }, + label = { Text(stringRes(R.string.poll_multiple_choice)) }, + ) + } +} + @SuppressLint("ViewModelConstructorInComposable") @Preview @Composable 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 2bbded69b..f5d07a8c7 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 @@ -117,6 +117,7 @@ import com.vitorpamplona.quartz.nip57Zaps.zapraiser.zapraiserAmount import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent import com.vitorpamplona.quartz.nip88Polls.poll.PollEvent import com.vitorpamplona.quartz.nip88Polls.poll.tags.OptionTag +import com.vitorpamplona.quartz.nip88Polls.poll.tags.PollType import com.vitorpamplona.quartz.nip92IMeta.IMetaTagBuilder import com.vitorpamplona.quartz.nip92IMeta.imetas import com.vitorpamplona.quartz.nip94FileMetadata.alt @@ -238,6 +239,7 @@ open class ShortNotePostViewModel : var canUsePoll by mutableStateOf(false) var wantsPoll by mutableStateOf(false) var pollOptions: SnapshotStateMap = newStateMapPollOptions() + var pollType by mutableStateOf(PollType.SINGLE_CHOICE) var closedAt by mutableLongStateOf(TimeUtils.oneDayAhead()) // ZapPolls @@ -596,6 +598,7 @@ open class ShortNotePostViewModel : pollOptions[index] = tag } + pollType = draftEvent.pollType() ?: PollType.SINGLE_CHOICE closedAt = draftEvent.endsAt() ?: TimeUtils.oneDayAhead() message = TextFieldValue(draftEvent.content) @@ -828,7 +831,7 @@ open class ShortNotePostViewModel : accountViewModel.account.nip65RelayList.outboxFlow.value .toList() - PollEvent.build(tagger.message, options, closedAt, relays) { + PollEvent.build(tagger.message, options, closedAt, relays, pollType) { pTags(tagger.directMentionsUsers.map { it.toPTag() }) quotes(quotes) hashtags(findHashtags(tagger.message)) @@ -1054,6 +1057,7 @@ open class ShortNotePostViewModel : wantsPoll = false pollOptions = newStateMapPollOptions() + pollType = PollType.SINGLE_CHOICE closedAt = TimeUtils.oneDayAhead() wantsZapPoll = false diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index b31cf4974..28f63ffea 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -483,6 +483,8 @@ Zap maximum Consensus (0–100)% + Single choice + Multiple choice Poll Closing Date & Time Poll closes in %1$s Close after