From 10f617550bfc13876e9d92a12863edf81f2ea45d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 17:44:05 +0000 Subject: [PATCH] feat: consolidate poll creation into a single screen with poll type selector Replace the two-button expandable FAB (Regular Poll / Zap Poll) with a single FAB navigating to one unified poll screen. The poll type (Regular vs Zap) is now selected via FilterChip options within the post form, eliminating the Route.NewZapPoll route entirely. https://claude.ai/code/session_01PqBSYZvCLBBUCifUFRoLmD --- .../amethyst/ui/navigation/AppNavigation.kt | 11 -- .../amethyst/ui/navigation/routes/Routes.kt | 6 - .../loggedIn/home/ShortNotePostScreen.kt | 100 +++++++--------- .../ui/screen/loggedIn/polls/NewPollButton.kt | 110 ++---------------- .../screen/loggedIn/polls/PollPostScreen.kt | 7 +- 5 files changed, 55 insertions(+), 179 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index aafcb4a21..ae795ed0c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -412,17 +412,6 @@ fun BuildNavigation( composableFromBottomArgs { PollPostScreen( - isZapPoll = false, - message = it.message, - draftId = it.draft, - accountViewModel = accountViewModel, - nav = nav, - ) - } - - composableFromBottomArgs { - PollPostScreen( - isZapPoll = true, message = it.message, draftId = it.draft, accountViewModel = accountViewModel, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt index 16883691d..0d6e614c3 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/routes/Routes.kt @@ -373,12 +373,6 @@ sealed class Route { val draft: String? = null, ) : Route() - @Serializable - data class NewZapPoll( - val message: String? = null, - val draft: String? = null, - ) : Route() - @Serializable data class VoiceReply( val replyToNoteId: String, 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 871810b34..eed62305a 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 @@ -26,6 +26,7 @@ import android.net.Uri import androidx.activity.compose.BackHandler import androidx.compose.foundation.clickable import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -42,12 +43,14 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Poll import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FilterChip import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Switch +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect @@ -108,7 +111,6 @@ 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.Size30Modifier import com.vitorpamplona.amethyst.ui.theme.Size35Modifier import com.vitorpamplona.amethyst.ui.theme.Size35dp @@ -334,21 +336,39 @@ private fun NewPostScreenBody( } } - if (postViewModel.wantsPoll) { - Row( - verticalAlignment = CenterVertically, + if (postViewModel.wantsPoll || postViewModel.wantsZapPoll) { + Column( modifier = Modifier.padding(vertical = Size10dp, horizontal = Size10dp), ) { - PollOptionsField(postViewModel) - } - } - - if (postViewModel.wantsZapPoll) { - Row( - verticalAlignment = CenterVertically, - modifier = Modifier.padding(vertical = Size10dp, horizontal = Size10dp), - ) { - ZapPollField(postViewModel) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + FilterChip( + selected = postViewModel.wantsPoll, + onClick = { + postViewModel.wantsPoll = true + postViewModel.wantsZapPoll = false + }, + label = { Text(stringRes(R.string.kind_poll)) }, + ) + FilterChip( + selected = postViewModel.wantsZapPoll, + onClick = { + postViewModel.wantsZapPoll = true + postViewModel.wantsPoll = false + }, + label = { Text(stringRes(R.string.kind_zap_poll)) }, + ) + } + if (postViewModel.wantsPoll) { + Row(verticalAlignment = CenterVertically) { + PollOptionsField(postViewModel) + } + } else { + Row(verticalAlignment = CenterVertically) { + ZapPollField(postViewModel) + } + } } } @@ -588,24 +608,14 @@ private fun BottomRowActions(postViewModel: ShortNotePostViewModel) { maxDurationSeconds = MAX_VOICE_RECORD_SECONDS, ) - if (postViewModel.canUsePoll) { - 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 - } + if (postViewModel.canUsePoll || postViewModel.canUseZapPoll) { + AddPollButton(postViewModel.wantsPoll || postViewModel.wantsZapPoll) { + val isActive = postViewModel.wantsPoll || postViewModel.wantsZapPoll + if (isActive) { + postViewModel.wantsPoll = false + postViewModel.wantsZapPoll = false + } else { + postViewModel.wantsPoll = true } } } @@ -655,32 +665,6 @@ 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/polls/NewPollButton.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/NewPollButton.kt index a51a5b7fe..8172c942a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/NewPollButton.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/NewPollButton.kt @@ -20,29 +20,12 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.polls -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.slideInVertically -import androidx.compose.animation.slideOutVertically -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Close -import androidx.compose.material.icons.outlined.Poll import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme 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.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route @@ -53,86 +36,17 @@ import com.vitorpamplona.amethyst.ui.theme.Size55Modifier @Composable fun NewPollButton(nav: INav) { - var isOpen by remember { mutableStateOf(false) } - - Column { - AnimatedVisibility( - visible = isOpen, - enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(), - exit = slideOutVertically(targetOffsetY = { it / 2 }) + fadeOut(), - ) { - Column { - FloatingActionButton( - onClick = { - nav.nav(Route.NewPoll()) - isOpen = false - }, - modifier = Size55Modifier, - shape = CircleShape, - containerColor = MaterialTheme.colorScheme.primary, - ) { - Icon( - imageVector = Icons.Outlined.Poll, - contentDescription = stringRes(id = R.string.new_regular_poll), - modifier = Size26Modifier, - tint = Color.White, - ) - } - - Spacer(modifier = Modifier.height(20.dp)) - - FloatingActionButton( - onClick = { - nav.nav(Route.NewZapPoll()) - isOpen = false - }, - modifier = Size55Modifier, - shape = CircleShape, - containerColor = MaterialTheme.colorScheme.primary, - ) { - Icon( - painter = painterRes(R.drawable.ic_poll, 1), - contentDescription = stringRes(id = R.string.new_zap_poll), - modifier = Size26Modifier, - tint = Color.White, - ) - } - - Spacer(modifier = Modifier.height(20.dp)) - } - } - - FloatingActionButton( - onClick = { isOpen = !isOpen }, - modifier = Size55Modifier, - shape = CircleShape, - containerColor = MaterialTheme.colorScheme.primary, - ) { - AnimatedVisibility( - visible = isOpen, - enter = fadeIn(), - exit = fadeOut(), - ) { - Icon( - imageVector = Icons.Outlined.Close, - contentDescription = stringRes(id = R.string.new_poll), - modifier = Size26Modifier, - tint = Color.White, - ) - } - - AnimatedVisibility( - visible = !isOpen, - enter = fadeIn(), - exit = fadeOut(), - ) { - Icon( - painter = painterRes(R.drawable.ic_compose, 4), - contentDescription = stringRes(id = R.string.new_poll), - modifier = Size26Modifier, - tint = Color.White, - ) - } - } + FloatingActionButton( + onClick = { nav.nav(Route.NewPoll()) }, + modifier = Size55Modifier, + shape = CircleShape, + containerColor = MaterialTheme.colorScheme.primary, + ) { + Icon( + painter = painterRes(R.drawable.ic_compose, 4), + contentDescription = stringRes(id = R.string.new_poll), + modifier = Size26Modifier, + tint = Color.White, + ) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/PollPostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/PollPostScreen.kt index 288592f7e..682387167 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/PollPostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/PollPostScreen.kt @@ -35,7 +35,6 @@ import kotlinx.coroutines.FlowPreview @OptIn(ExperimentalMaterial3Api::class, FlowPreview::class) @Composable fun PollPostScreen( - isZapPoll: Boolean, message: String? = null, draftId: HexKey? = null, accountViewModel: AccountViewModel, @@ -51,11 +50,7 @@ fun PollPostScreen( postViewModel.message.setTextAndPlaceCursorAtEnd(it) postViewModel.onMessageChanged() } - if (isZapPoll) { - postViewModel.wantsZapPoll = true - } else { - postViewModel.wantsPoll = true - } + postViewModel.wantsPoll = true } NewPostScreenInner(postViewModel, accountViewModel, nav)