kopia lustrzana https://github.com/elk-zone/elk
feat: check validity of schedule time and show warning notice
rodzic
dc2e49ffe4
commit
dc4ba794f6
|
@ -131,14 +131,19 @@ const expiresInOptions = computed(() => [
|
||||||
const expiresInDefaultOptionIndex = 2
|
const expiresInDefaultOptionIndex = 2
|
||||||
|
|
||||||
const scheduledTime = ref('')
|
const scheduledTime = ref('')
|
||||||
watchEffect(() => {
|
const now = useNow({ interval: 1000 })
|
||||||
draft.value.params.scheduledAt = scheduledTime.value
|
const minimumScheduledTime = computed(() => getMinimumScheduledTime(now.value))
|
||||||
|
|
||||||
|
const isValidScheduledTime = computed(() => {
|
||||||
|
if (scheduledTime.value === '')
|
||||||
|
return true
|
||||||
|
|
||||||
|
const scheduledTimeDate = new Date(scheduledTime.value)
|
||||||
|
return minimumScheduledTime.value.getTime() <= scheduledTimeDate.getTime()
|
||||||
})
|
})
|
||||||
|
|
||||||
const now = useNow({ interval: 1000 })
|
|
||||||
const minimumScheduledTime = ref()
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
minimumScheduledTime.value = getMinimumScheduledTime(now.value)
|
draft.value.params.scheduledAt = scheduledTime.value
|
||||||
})
|
})
|
||||||
|
|
||||||
// Calculate the minimum scheduled time.
|
// Calculate the minimum scheduled time.
|
||||||
|
@ -146,13 +151,16 @@ watchEffect(() => {
|
||||||
// but if the specified scheduled time is less than 5 minutes, Mastodon will
|
// but if the specified scheduled time is less than 5 minutes, Mastodon will
|
||||||
// send the post immediately.
|
// send the post immediately.
|
||||||
// To prevent this, we add a buffer and round up the minutes.
|
// To prevent this, we add a buffer and round up the minutes.
|
||||||
function getMinimumScheduledTime(now: Date): string {
|
function getMinimumScheduledTime(now: Date): Date {
|
||||||
const bufferInSec = 5 + 5 * 60 // + 5 minutes and 5 seconds
|
const bufferInSec = 5 + 5 * 60 // + 5 minutes and 5 seconds
|
||||||
const nowInSec = Math.floor(now.getTime() / 1000)
|
const nowInSec = Math.floor(now.getTime() / 1000)
|
||||||
const bufferedTimeInSec
|
const bufferedTimeInSec
|
||||||
= Math.ceil((nowInSec + bufferInSec) / 60) * 60
|
= Math.ceil((nowInSec + bufferInSec) / 60) * 60
|
||||||
const minimumScheduledTime = new Date(bufferedTimeInSec * 1000)
|
return new Date(bufferedTimeInSec * 1000)
|
||||||
return minimumScheduledTime.toISOString().slice(0, 16)
|
}
|
||||||
|
|
||||||
|
function getDatetimeInputFormat(time: Date) {
|
||||||
|
return time.toISOString().slice(0, 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
const characterCount = computed(() => {
|
const characterCount = computed(() => {
|
||||||
|
@ -326,9 +334,9 @@ function stopQuestionMarkPropagation(e: KeyboardEvent) {
|
||||||
<div aria-hidden="true" i-ri:error-warning-fill />
|
<div aria-hidden="true" i-ri:error-warning-fill />
|
||||||
<p>{{ scheduledTime ? $t('state.schedule_failed') : $t('state.publish_failed') }}</p>
|
<p>{{ scheduledTime ? $t('state.schedule_failed') : $t('state.publish_failed') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<CommonTooltip placement="bottom" :content="scheduledTime ? $t('state.clear_schedule_failed') : $t('action.clear_publish_failed')">
|
<CommonTooltip placement="bottom" :content="scheduledTime ? $t('action.clear_schedule_failed') : $t('action.clear_publish_failed')">
|
||||||
<button
|
<button
|
||||||
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="scheduledTime ? $t('state.clear_schedule_failed') : $t('action.clear_publish_failed')"
|
flex rounded-4 p1 hover:bg-active cursor-pointer transition-100 :aria-label="scheduledTime ? $t('action.clear_schedule_failed') : $t('action.clear_publish_failed')"
|
||||||
@click="failedMessages = []"
|
@click="failedMessages = []"
|
||||||
>
|
>
|
||||||
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
||||||
|
@ -343,6 +351,15 @@ function stopQuestionMarkPropagation(e: KeyboardEvent) {
|
||||||
</ol>
|
</ol>
|
||||||
</CommonErrorMessage>
|
</CommonErrorMessage>
|
||||||
|
|
||||||
|
<CommonErrorMessage v-if="!isValidScheduledTime" described-by="scheduled-time-invalid" pt-2>
|
||||||
|
<header id="scheduled-time-invalid" flex justify-between>
|
||||||
|
<div flex items-center gap-x-2 font-bold>
|
||||||
|
<div aria-hidden="true" i-ri:error-warning-fill />
|
||||||
|
<p>{{ $t('state.schedule_time_invalid', [minimumScheduledTime.toLocaleString()]) }}</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</CommonErrorMessage>
|
||||||
|
|
||||||
<div relative flex-1 flex flex-col :class="shouldExpanded ? 'min-h-30' : ''">
|
<div relative flex-1 flex flex-col :class="shouldExpanded ? 'min-h-30' : ''">
|
||||||
<EditorContent
|
<EditorContent
|
||||||
:editor="editor" flex max-w-full
|
:editor="editor" flex max-w-full
|
||||||
|
@ -516,7 +533,7 @@ function stopQuestionMarkPropagation(e: KeyboardEvent) {
|
||||||
p2
|
p2
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
name="schedule-datetime"
|
name="schedule-datetime"
|
||||||
:min="minimumScheduledTime"
|
:min="getDatetimeInputFormat(minimumScheduledTime)"
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</CommonDropdown>
|
</CommonDropdown>
|
||||||
|
@ -582,7 +599,8 @@ function stopQuestionMarkPropagation(e: KeyboardEvent) {
|
||||||
<button
|
<button
|
||||||
v-if="!threadIsActive || isFinalItemOfThread"
|
v-if="!threadIsActive || isFinalItemOfThread"
|
||||||
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit class="publish-button"
|
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit class="publish-button"
|
||||||
:aria-disabled="isPublishDisabled || isExceedingCharacterLimit" aria-describedby="publish-tooltip"
|
:aria-disabled="isPublishDisabled || isExceedingCharacterLimit || !isValidScheduledTime"
|
||||||
|
aria-describedby="publish-tooltip"
|
||||||
@click="publish"
|
@click="publish"
|
||||||
>
|
>
|
||||||
<span v-if="isSending" block animate-spin preserve-3d>
|
<span v-if="isSending" block animate-spin preserve-3d>
|
||||||
|
@ -596,8 +614,8 @@ function stopQuestionMarkPropagation(e: KeyboardEvent) {
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span v-if="draft.editingStatus">{{ $t('action.save_changes') }}</span>
|
<span v-if="draft.editingStatus">{{ $t('action.save_changes') }}</span>
|
||||||
<span v-else-if="draft.params.inReplyToId">{{ $t('action.reply') }}</span>
|
|
||||||
<span v-else-if="scheduledTime">{{ !isSending ? $t('action.schedule') : $t('state.scheduling') }}</span>
|
<span v-else-if="scheduledTime">{{ !isSending ? $t('action.schedule') : $t('state.scheduling') }}</span>
|
||||||
|
<span v-else-if="draft.params.inReplyToId">{{ $t('action.reply') }}</span>
|
||||||
<span v-else>{{ !isSending ? $t('action.publish') : $t('state.publishing') }}</span>
|
<span v-else>{{ !isSending ? $t('action.publish') : $t('state.publishing') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -615,6 +615,7 @@
|
||||||
"publishing": "Publishing",
|
"publishing": "Publishing",
|
||||||
"save_failed": "Save failed",
|
"save_failed": "Save failed",
|
||||||
"schedule_failed": "Schedule failed",
|
"schedule_failed": "Schedule failed",
|
||||||
|
"schedule_time_invalid": "The scheduled time must be at least 5 minutes later in the future. Set to {0} or later.",
|
||||||
"scheduling": "Scheduling",
|
"scheduling": "Scheduling",
|
||||||
"upload_failed": "Upload failed",
|
"upload_failed": "Upload failed",
|
||||||
"uploading": "Uploading..."
|
"uploading": "Uploading..."
|
||||||
|
|
Ładowanie…
Reference in New Issue