Makes 24h the default end time for polls

This commit is contained in:
Vitor Pamplona
2026-02-17 18:41:25 -05:00
parent a6ff66b8ae
commit bb3937edb4
4 changed files with 31 additions and 37 deletions
@@ -56,11 +56,10 @@ 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.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.ZoneId
import java.time.ZoneOffset
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -69,15 +68,12 @@ fun PollDeadlinePicker(model: ShortNotePostViewModel) {
var showTimePicker by remember { mutableStateOf(false) }
// Get current time details
val currentTime = LocalDateTime.now()
val currentTime = Instant.ofEpochMilli(model.closedAt * 1000).atZone(ZoneId.systemDefault()).toLocalDateTime()
val datePickerState =
rememberDatePickerState(
initialSelectedDateMillis =
currentTime
.atZone(ZoneId.systemDefault())
.toInstant()
.toEpochMilli(),
initialSelectedDateMillis = model.closedAt * 1000,
yearRange = currentTime.year..2050,
selectableDates =
object : SelectableDates {
override fun isSelectableDate(utcTimeMillis: Long): Boolean {
@@ -106,11 +102,11 @@ fun PollDeadlinePicker(model: ShortNotePostViewModel) {
Icon(Icons.Default.DateRange, contentDescription = null)
Spacer(Modifier.width(12.dp))
if (model.closedAt == null) {
Text(stringRes(R.string.poll_closing_date_time), style = MaterialTheme.typography.bodyLarge)
if (model.closedAt < TimeUtils.oneMinuteFromNow()) {
Text(stringRes(R.string.poll_closing_date_time) + " " + model.closedAt, style = MaterialTheme.typography.bodyLarge)
} else {
Text(
text = timeAheadNoDot(model.closedAt, context),
text = stringRes(R.string.poll_closing_in, timeAheadNoDot(model.closedAt, context)),
style = MaterialTheme.typography.bodyLarge,
)
}
@@ -140,28 +136,23 @@ fun PollDeadlinePicker(model: ShortNotePostViewModel) {
},
onDismissRequest = { showTimePicker = false },
confirmButton = {
TextButton(onClick = {
val date =
datePickerState.selectedDateMillis?.let {
Instant.ofEpochMilli(it).atZone(ZoneId.systemDefault()).toLocalDate()
} ?: LocalDate.now()
TextButton(
onClick = {
val datetimeLocalTimeZone =
datePickerState.selectedDateMillis?.let { localDayAtZeroHourMillis ->
(localDayAtZeroHourMillis / 1000) +
(timePickerState.hour * TimeUtils.ONE_HOUR) +
(timePickerState.minute * TimeUtils.ONE_MINUTE)
} ?: TimeUtils.oneDayAhead()
val finalDateTime =
LocalDateTime.of(
date,
LocalTime.of(timePickerState.hour, timePickerState.minute),
)
// Get the offset from UTC for the current instant in the local time zone
val offset: ZoneOffset = ZoneId.systemDefault().rules.getOffset(Instant.now())
// 2. Convert to Unix Timestamp (Seconds)
val unixTimestamp =
finalDateTime
.atZone(ZoneId.systemDefault())
.toInstant()
.epochSecond
model.closedAt = datetimeLocalTimeZone - offset.totalSeconds
model.closedAt = unixTimestamp
showTimePicker = false
}) { Text(stringResource(R.string.confirm)) }
showTimePicker = false
},
) { Text(stringResource(R.string.confirm)) }
},
) {
TimePicker(state = timePickerState)
@@ -123,6 +123,7 @@ import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceEvent
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent
import com.vitorpamplona.quartz.utils.Log
import com.vitorpamplona.quartz.utils.RandomInstance
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.StateFlow
@@ -220,7 +221,7 @@ open class ShortNotePostViewModel :
var canUsePoll by mutableStateOf(false)
var wantsPoll by mutableStateOf(false)
var pollOptions: SnapshotStateMap<Int, OptionTag> = newStateMapPollOptions()
var closedAt by mutableStateOf<Long?>(null)
var closedAt by mutableStateOf(TimeUtils.oneDayAhead())
// Invoices
var canAddInvoice by mutableStateOf(false)
@@ -539,9 +540,7 @@ open class ShortNotePostViewModel :
pollOptions[index] = tag
}
draftEvent.endsAt()?.let {
closedAt = it
}
closedAt = draftEvent.endsAt() ?: TimeUtils.oneDayAhead()
message = TextFieldValue(draftEvent.content)
@@ -889,7 +888,7 @@ open class ShortNotePostViewModel :
wantsPoll = false
pollOptions = newStateMapPollOptions()
closedAt = null
closedAt = TimeUtils.oneDayAhead()
wantsInvoice = false
wantsZapRaiser = false
@@ -1018,7 +1017,8 @@ open class ShortNotePostViewModel :
(
!wantsPoll ||
(
pollOptions.isNotEmpty() && pollOptions.all { it.value.label.isNotEmpty() }
pollOptions.isNotEmpty() && pollOptions.all { it.value.label.isNotEmpty() } &&
closedAt > TimeUtils.oneMinuteFromNow()
)
) &&
multiOrchestrator == null
+1
View File
@@ -469,6 +469,7 @@
<string name="poll_consensus_threshold">Consensus</string>
<string name="poll_consensus_threshold_percent">(0100)%</string>
<string name="poll_closing_date_time">Poll Closing Date &amp; Time</string>
<string name="poll_closing_in">Poll closes in %1$s</string>
<string name="poll_closing_time">Close after</string>
<string name="poll_closing_time_days">days</string>
<string name="poll_unable_to_vote">Unable to vote</string>
@@ -55,6 +55,8 @@ object TimeUtils {
fun oneDayAgo() = now() - ONE_DAY
fun oneDayAhead() = now() + ONE_DAY
fun eightHoursAgo() = now() - EIGHT_HOURS
fun twoDays() = ONE_DAY * 2