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
This commit is contained in:
@@ -412,17 +412,6 @@ fun BuildNavigation(
|
||||
|
||||
composableFromBottomArgs<Route.NewPoll> {
|
||||
PollPostScreen(
|
||||
isZapPoll = false,
|
||||
message = it.message,
|
||||
draftId = it.draft,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
composableFromBottomArgs<Route.NewZapPoll> {
|
||||
PollPostScreen(
|
||||
isZapPoll = true,
|
||||
message = it.message,
|
||||
draftId = it.draft,
|
||||
accountViewModel = accountViewModel,
|
||||
|
||||
@@ -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,
|
||||
|
||||
+42
-58
@@ -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,
|
||||
|
||||
+12
-98
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-6
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user