kopia lustrzana https://github.com/elk-zone/elk
Merge c3a36e0a0e
into d27771f614
commit
4bb513704f
|
@ -2,6 +2,7 @@
|
||||||
import type { DraftItem } from '#shared/types'
|
import type { DraftItem } from '#shared/types'
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
import { EditorContent } from '@tiptap/vue-3'
|
import { EditorContent } from '@tiptap/vue-3'
|
||||||
|
import { useNow } from '@vueuse/core'
|
||||||
import stringLength from 'string-length'
|
import stringLength from 'string-length'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -53,7 +54,16 @@ const {
|
||||||
dropZoneRef,
|
dropZoneRef,
|
||||||
} = useUploadMediaAttachment(draft)
|
} = useUploadMediaAttachment(draft)
|
||||||
|
|
||||||
const { shouldExpanded, isExpanded, isSending, isPublishDisabled, publishDraft, failedMessages, preferredLanguage, publishSpoilerText } = usePublish(
|
const {
|
||||||
|
shouldExpanded,
|
||||||
|
isExpanded,
|
||||||
|
isSending,
|
||||||
|
isPublishDisabled,
|
||||||
|
publishDraft,
|
||||||
|
failedMessages,
|
||||||
|
preferredLanguage,
|
||||||
|
publishSpoilerText,
|
||||||
|
} = usePublish(
|
||||||
{
|
{
|
||||||
draftItem: draft,
|
draftItem: draft,
|
||||||
...{ expanded: toRef(() => expanded), isUploading, initialDraft: initial, isPartOfThread: false },
|
...{ expanded: toRef(() => expanded), isUploading, initialDraft: initial, isPartOfThread: false },
|
||||||
|
@ -132,6 +142,73 @@ const expiresInOptions = computed(() => [
|
||||||
|
|
||||||
const expiresInDefaultOptionIndex = 2
|
const expiresInDefaultOptionIndex = 2
|
||||||
|
|
||||||
|
const scheduledTime = ref('')
|
||||||
|
const now = useNow({ interval: 1000 })
|
||||||
|
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 initialDateTime = computed(() => {
|
||||||
|
const t = new Date(minimumScheduledTime.value.getTime())
|
||||||
|
t.setHours(t.getHours() + 1)
|
||||||
|
t.setMinutes(0)
|
||||||
|
t.setSeconds(0)
|
||||||
|
t.setMilliseconds(0)
|
||||||
|
return t
|
||||||
|
})
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
// Convert the local datetime string from the input to a UTC ISO string for the API
|
||||||
|
if (scheduledTime.value) {
|
||||||
|
const localDate = new Date(scheduledTime.value)
|
||||||
|
draft.value.params.scheduledAt = localDate.toISOString()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
draft.value.params.scheduledAt = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function setInitialScheduledTime() {
|
||||||
|
if (scheduledTime.value === '') {
|
||||||
|
scheduledTime.value = getDatetimeInputFormat(initialDateTime.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
draft.value.params.scheduledAt = scheduledTime.value
|
||||||
|
})
|
||||||
|
|
||||||
|
// Calculate the minimum scheduled time.
|
||||||
|
// Mastodon API allows to set the scheduled time to 5 minutes in the future
|
||||||
|
// but if the specified scheduled time is less than 5 minutes, Mastodon will
|
||||||
|
// send the post immediately.
|
||||||
|
// To prevent this, we add a buffer and round up the minutes.
|
||||||
|
function getMinimumScheduledTime(now: Date): Date {
|
||||||
|
const bufferInSec = 5 + 5 * 60 // + 5 minutes and 5 seconds
|
||||||
|
const nowInSec = Math.floor(now.getTime() / 1000)
|
||||||
|
const bufferedTimeInSec
|
||||||
|
= Math.ceil((nowInSec + bufferInSec) / 60) * 60
|
||||||
|
return new Date(bufferedTimeInSec * 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDatetimeInputFormat(time: Date) {
|
||||||
|
// Returns string in 'YYYY-MM-DDTHH:MM' format using local time components
|
||||||
|
// This is the format expected by the <input type="datetime-local"> element.
|
||||||
|
const year = time.getFullYear()
|
||||||
|
const month = (time.getMonth() + 1).toString().padStart(2, '0')
|
||||||
|
const day = time.getDate().toString().padStart(2, '0')
|
||||||
|
const hours = time.getHours().toString().padStart(2, '0')
|
||||||
|
const minutes = time.getMinutes().toString().padStart(2, '0')
|
||||||
|
|
||||||
|
return `${year}-${month}-${day}T${hours}:${minutes}`
|
||||||
|
}
|
||||||
|
|
||||||
const characterCount = computed(() => {
|
const characterCount = computed(() => {
|
||||||
const text = htmlToText(editor.value?.getHTML() || '')
|
const text = htmlToText(editor.value?.getHTML() || '')
|
||||||
|
|
||||||
|
@ -186,6 +263,7 @@ async function handlePaste(evt: ClipboardEvent) {
|
||||||
function insertEmoji(name: string) {
|
function insertEmoji(name: string) {
|
||||||
editor.value?.chain().focus().insertEmoji(name).run()
|
editor.value?.chain().focus().insertEmoji(name).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertCustomEmoji(image: any) {
|
function insertCustomEmoji(image: any) {
|
||||||
editor.value?.chain().focus().insertCustomEmoji(image).run()
|
editor.value?.chain().focus().insertCustomEmoji(image).run()
|
||||||
}
|
}
|
||||||
|
@ -353,6 +431,41 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</CommonErrorMessage>
|
</CommonErrorMessage>
|
||||||
|
<CommonErrorMessage v-if="failedMessages.length > 0" described-by="publish-failed">
|
||||||
|
<header id="publish-failed" flex justify-between>
|
||||||
|
<div flex items-center gap-x-2 font-bold>
|
||||||
|
<div aria-hidden="true" i-ri:error-warning-fill />
|
||||||
|
<p>{{ scheduledTime ? $t('state.schedule_failed') : $t('state.publish_failed') }}</p>
|
||||||
|
</div>
|
||||||
|
<CommonTooltip
|
||||||
|
placement="bottom"
|
||||||
|
:content="scheduledTime ? $t('action.clear_schedule_failed') : $t('action.clear_publish_failed')"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
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 = []"
|
||||||
|
>
|
||||||
|
<span aria-hidden="true" w="1.75em" h="1.75em" i-ri:close-line />
|
||||||
|
</button>
|
||||||
|
</CommonTooltip>
|
||||||
|
</header>
|
||||||
|
<ol ps-2 sm:ps-1>
|
||||||
|
<li v-for="(error, i) in failedMessages" :key="i" flex="~ col sm:row" gap-y-1 sm:gap-x-2>
|
||||||
|
<strong>{{ i + 1 }}.</strong>
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</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
|
||||||
|
@ -435,7 +548,8 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
aspect-ratio-1 h-10
|
aspect-ratio-1 h-10
|
||||||
:style="{ background: `radial-gradient(closest-side, rgba(var(--rgb-bg-base)) 79%, transparent 80% 100%), conic-gradient(${draft.params.poll!.options[index].length / currentInstance?.configuration?.polls.maxCharactersPerOption > 1 ? 'var(--c-danger)' : 'var(--c-primary)'} ${draft.params.poll!.options[index].length / currentInstance?.configuration?.polls.maxCharactersPerOption * 100}%, var(--c-primary-fade) 0)` }"
|
:style="{ background: `radial-gradient(closest-side, rgba(var(--rgb-bg-base)) 79%, transparent 80% 100%), conic-gradient(${draft.params.poll!.options[index].length / currentInstance?.configuration?.polls.maxCharactersPerOption > 1 ? 'var(--c-danger)' : 'var(--c-primary)'} ${draft.params.poll!.options[index].length / currentInstance?.configuration?.polls.maxCharactersPerOption * 100}%, var(--c-primary-fade) 0)` }"
|
||||||
>{{
|
>{{
|
||||||
draft.params.poll!.options[index].length }}</span>
|
draft.params.poll!.options[index].length
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div v-if="shouldExpanded" flex="~ gap-1 1 wrap" m="s--1" pt-2 justify="end" max-w-full border="t base">
|
<div v-if="shouldExpanded" flex="~ gap-1 1 wrap" m="s--1" pt-2 justify="end" max-w-full border="t base">
|
||||||
|
@ -489,7 +603,8 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
/>
|
/>
|
||||||
<CommonCheckbox
|
<CommonCheckbox
|
||||||
v-model="draft.params.poll.hideTotals"
|
v-model="draft.params.poll.hideTotals"
|
||||||
:label="draft.params.poll.hideTotals ? $t('polls.show_votes') : $t('polls.hide_votes')" px-2 gap-3
|
:label="draft.params.poll.hideTotals ? $t('polls.show_votes') : $t('polls.hide_votes')" px-2
|
||||||
|
gap-3
|
||||||
h-9 flex justify-center hover:bg-active rounded-full icon-checked="i-ri:eye-close-line"
|
h-9 flex justify-center hover:bg-active rounded-full icon-checked="i-ri:eye-close-line"
|
||||||
icon-unchecked="i-ri:eye-line"
|
icon-unchecked="i-ri:eye-line"
|
||||||
/>
|
/>
|
||||||
|
@ -506,7 +621,8 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
<template #popper>
|
<template #popper>
|
||||||
<CommonDropdownItem
|
<CommonDropdownItem
|
||||||
v-for="expiresInOption in expiresInOptions" :key="expiresInOption.seconds"
|
v-for="expiresInOption in expiresInOptions" :key="expiresInOption.seconds"
|
||||||
:text="expiresInOption.label" :checked="draft.params.poll!.expiresIn === expiresInOption.seconds"
|
:text="expiresInOption.label"
|
||||||
|
:checked="draft.params.poll!.expiresIn === expiresInOption.seconds"
|
||||||
@click="draft.params.poll!.expiresIn = expiresInOption.seconds"
|
@click="draft.params.poll!.expiresIn = expiresInOption.seconds"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -515,6 +631,22 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<PublishEditorTools v-if="editor" :editor="editor" />
|
<PublishEditorTools v-if="editor" :editor="editor" />
|
||||||
|
<CommonDropdown placement="bottom" @click="setInitialScheduledTime">
|
||||||
|
<CommonTooltip placement="top" :content="$t('tooltip.schedule_post')" no-auto-focus>
|
||||||
|
<button btn-action-icon :aria-label="$t('tooltip.schedule_post')">
|
||||||
|
<div i-ri:calendar-schedule-line :class="scheduledTime !== '' ? 'text-primary' : ''" />
|
||||||
|
</button>
|
||||||
|
</CommonTooltip>
|
||||||
|
<template #popper>
|
||||||
|
<input
|
||||||
|
v-model="scheduledTime"
|
||||||
|
p2
|
||||||
|
type="datetime-local"
|
||||||
|
name="schedule-datetime"
|
||||||
|
:min="getDatetimeInputFormat(minimumScheduledTime)"
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</CommonDropdown>
|
||||||
|
|
||||||
<div flex-auto />
|
<div flex-auto />
|
||||||
|
|
||||||
|
@ -557,7 +689,7 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
|
|
||||||
<CommonTooltip
|
<CommonTooltip
|
||||||
v-if="failedMessages.length > 0" id="publish-failed-tooltip" placement="top"
|
v-if="failedMessages.length > 0" id="publish-failed-tooltip" placement="top"
|
||||||
:content="$t('tooltip.publish_failed')"
|
:content="scheduledTime ? $t('state.schedule_failed') : $t('tooltip.publish_failed')"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
btn-danger rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit
|
btn-danger rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit
|
||||||
|
@ -566,7 +698,7 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
<span block>
|
<span block>
|
||||||
<div block i-carbon:face-dizzy-filled />
|
<div block i-carbon:face-dizzy-filled />
|
||||||
</span>
|
</span>
|
||||||
<span>{{ $t('state.publish_failed') }}</span>
|
<span>{{ scheduledTime ? $t('state.schedule_failed') : $t('state.publish_failed') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</CommonTooltip>
|
</CommonTooltip>
|
||||||
|
|
||||||
|
@ -577,8 +709,9 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
<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 || threadIsSending" aria-describedby="publish-tooltip"
|
:aria-disabled="isPublishDisabled || isExceedingCharacterLimit || threadIsSending || !isValidScheduledTime"
|
||||||
:disabled="isPublishDisabled || isExceedingCharacterLimit || threadIsSending"
|
aria-describedby="publish-tooltip"
|
||||||
|
:disabled="isPublishDisabled || isExceedingCharacterLimit || threadIsSending || !isValidScheduledTime"
|
||||||
@click="publish"
|
@click="publish"
|
||||||
>
|
>
|
||||||
<span v-if="isSending || threadIsSending" block animate-spin preserve-3d>
|
<span v-if="isSending || threadIsSending" block animate-spin preserve-3d>
|
||||||
|
@ -592,6 +725,9 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
</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="scheduledTime">{{
|
||||||
|
!isSending ? $t('action.schedule') : $t('state.scheduling')
|
||||||
|
}}</span>
|
||||||
<span v-else-if="draft.params.inReplyToId">{{ $t('action.reply') }}</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>
|
||||||
|
@ -616,11 +752,11 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
color: var(--c-text-btn-disabled);
|
color: var(--c-text-btn-disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-input:focus+.delete-button {
|
.option-input:focus + .delete-button {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-input:not(:focus)+.delete-button+.char-limit-radial {
|
.option-input:not(:focus) + .delete-button + .char-limit-radial {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,4 +766,8 @@ const detectLanguage = useDebounceFn(async () => {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[name="schedule-datetime"]:invalid {
|
||||||
|
color: var(--c-danger);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function usePublish(options: {
|
||||||
failedMessages.value.length = 0
|
failedMessages.value.length = 0
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
async function publishDraft() {
|
async function publishDraft(): Promise<mastodon.v1.Status | undefined> {
|
||||||
if (isPublishDisabled.value)
|
if (isPublishDisabled.value)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -71,7 +71,6 @@ export function usePublish(options: {
|
||||||
content = `${draftItem.value.mentions.map(i => `@${i}`).join(' ')} ${content}`
|
content = `${draftItem.value.mentions.map(i => `@${i}`).join(' ')} ${content}`
|
||||||
|
|
||||||
let poll
|
let poll
|
||||||
|
|
||||||
if (draftItem.value.params.poll) {
|
if (draftItem.value.params.poll) {
|
||||||
let options = draftItem.value.params.poll.options
|
let options = draftItem.value.params.poll.options
|
||||||
|
|
||||||
|
@ -87,6 +86,10 @@ export function usePublish(options: {
|
||||||
poll = { ...draftItem.value.params.poll, options }
|
poll = { ...draftItem.value.params.poll, options }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scheduledAt
|
||||||
|
if (draftItem.value.params.scheduledAt)
|
||||||
|
scheduledAt = new Date(draftItem.value.params.scheduledAt).toISOString()
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
...draftItem.value.params,
|
...draftItem.value.params,
|
||||||
spoilerText: publishSpoilerText.value,
|
spoilerText: publishSpoilerText.value,
|
||||||
|
@ -94,8 +97,9 @@ export function usePublish(options: {
|
||||||
mediaIds: draftItem.value.attachments.map(a => a.id),
|
mediaIds: draftItem.value.attachments.map(a => a.id),
|
||||||
language: draftItem.value.params.language || preferredLanguage.value,
|
language: draftItem.value.params.language || preferredLanguage.value,
|
||||||
poll,
|
poll,
|
||||||
|
scheduledAt,
|
||||||
...(isGlitchEdition.value ? { 'content-type': 'text/markdown' } : {}),
|
...(isGlitchEdition.value ? { 'content-type': 'text/markdown' } : {}),
|
||||||
} as mastodon.rest.v1.CreateStatusParams
|
} as mastodon.rest.v1.CreateScheduledStatusParams
|
||||||
|
|
||||||
if (import.meta.dev) {
|
if (import.meta.dev) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
@ -116,7 +120,6 @@ export function usePublish(options: {
|
||||||
if (!draftItem.value.editingStatus) {
|
if (!draftItem.value.editingStatus) {
|
||||||
status = await client.value.v1.statuses.create(payload)
|
status = await client.value.v1.statuses.create(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
status = await client.value.v1.statuses.$select(draftItem.value.editingStatus.id).update({
|
status = await client.value.v1.statuses.$select(draftItem.value.editingStatus.id).update({
|
||||||
...payload,
|
...payload,
|
||||||
|
@ -131,6 +134,12 @@ export function usePublish(options: {
|
||||||
|
|
||||||
draftItem.value = options.initialDraft()
|
draftItem.value = options.initialDraft()
|
||||||
|
|
||||||
|
if ('scheduled_at' in status)
|
||||||
|
// When created a scheduled post, it returns `mastodon.v1.ScheduledStatus` instead
|
||||||
|
// We want to return only Status, which will be used to route to the posted status page
|
||||||
|
// ref. Mastodon documentation - https://docs.joinmastodon.org/methods/statuses/#create
|
||||||
|
return
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ function getDefaultVisibility(currentVisibility: mastodon.v1.StatusVisibility) {
|
||||||
: preferredVisibility
|
: preferredVisibility
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDefaultDraftItem(options: Partial<Mutable<mastodon.rest.v1.CreateStatusParams> & Omit<DraftItem, 'params'>> = {}): DraftItem {
|
export function getDefaultDraftItem(options: Partial<Mutable<mastodon.rest.v1.CreateScheduledStatusParams> & Omit<DraftItem, 'params'>> = {}): DraftItem {
|
||||||
const {
|
const {
|
||||||
attachments = [],
|
attachments = [],
|
||||||
initialText = '',
|
initialText = '',
|
||||||
|
@ -37,6 +37,7 @@ export function getDefaultDraftItem(options: Partial<Mutable<mastodon.rest.v1.Cr
|
||||||
language,
|
language,
|
||||||
mentions,
|
mentions,
|
||||||
poll,
|
poll,
|
||||||
|
scheduledAt,
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -45,6 +46,7 @@ export function getDefaultDraftItem(options: Partial<Mutable<mastodon.rest.v1.Cr
|
||||||
params: {
|
params: {
|
||||||
status: status || '',
|
status: status || '',
|
||||||
poll,
|
poll,
|
||||||
|
scheduledAt,
|
||||||
inReplyToId,
|
inReplyToId,
|
||||||
visibility: getDefaultVisibility(visibility || 'public'),
|
visibility: getDefaultVisibility(visibility || 'public'),
|
||||||
sensitive: sensitive ?? false,
|
sensitive: sensitive ?? false,
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"clear_publish_failed": "Clear publish errors",
|
"clear_publish_failed": "Clear publish errors",
|
||||||
"clear_save_failed": "Clear save errors",
|
"clear_save_failed": "Clear save errors",
|
||||||
|
"clear_schedule_failed": "Clear schedule errors",
|
||||||
"clear_upload_failed": "Clear file upload errors",
|
"clear_upload_failed": "Clear file upload errors",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"compose": "Compose",
|
"compose": "Compose",
|
||||||
|
@ -82,6 +83,7 @@
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"save_changes": "Save changes",
|
"save_changes": "Save changes",
|
||||||
|
"schedule": "Schedule",
|
||||||
"sign_in": "Sign in",
|
"sign_in": "Sign in",
|
||||||
"sign_in_to": "Sign in to {0}",
|
"sign_in_to": "Sign in to {0}",
|
||||||
"switch_account": "Switch account",
|
"switch_account": "Switch account",
|
||||||
|
@ -617,6 +619,9 @@
|
||||||
"publish_failed": "Publish failed",
|
"publish_failed": "Publish failed",
|
||||||
"publishing": "Publishing",
|
"publishing": "Publishing",
|
||||||
"save_failed": "Save failed",
|
"save_failed": "Save 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",
|
||||||
"upload_failed": "Upload failed",
|
"upload_failed": "Upload failed",
|
||||||
"uploading": "Uploading..."
|
"uploading": "Uploading..."
|
||||||
},
|
},
|
||||||
|
@ -744,6 +749,8 @@
|
||||||
"pick_an_icon": "Pick an icon",
|
"pick_an_icon": "Pick an icon",
|
||||||
"publish_failed": "Close failed messages at the top of editor to republish posts",
|
"publish_failed": "Close failed messages at the top of editor to republish posts",
|
||||||
"remove_thread_item": "Remove item from thread",
|
"remove_thread_item": "Remove item from thread",
|
||||||
|
"schedule_failed": "Close failed messages at the top of editor to reschedule posts",
|
||||||
|
"schedule_post": "Schedule post",
|
||||||
"start_thread": "Start thread",
|
"start_thread": "Start thread",
|
||||||
"toggle_bold": "Toggle bold",
|
"toggle_bold": "Toggle bold",
|
||||||
"toggle_code_block": "Toggle code block",
|
"toggle_code_block": "Toggle code block",
|
||||||
|
|
|
@ -46,7 +46,7 @@ export type NotificationSlot = GroupedNotifications | GroupedLikeNotifications |
|
||||||
export interface DraftItem {
|
export interface DraftItem {
|
||||||
editingStatus?: mastodon.v1.Status
|
editingStatus?: mastodon.v1.Status
|
||||||
initialText?: string
|
initialText?: string
|
||||||
params: MarkNonNullable<Mutable<Omit<mastodon.rest.v1.CreateStatusParams, 'poll'>>, 'status' | 'language' | 'sensitive' | 'spoilerText' | 'visibility'> & { poll: Mutable<mastodon.rest.v1.CreateStatusParams['poll']> }
|
params: MarkNonNullable<Mutable<Omit<mastodon.rest.v1.CreateScheduledStatusParams, 'poll'>>, 'status' | 'language' | 'sensitive' | 'spoilerText' | 'visibility'> & { poll: Mutable<mastodon.rest.v1.CreateScheduledStatusParams['poll']> }
|
||||||
attachments: mastodon.v1.MediaAttachment[]
|
attachments: mastodon.v1.MediaAttachment[]
|
||||||
lastUpdated: number
|
lastUpdated: number
|
||||||
mentions?: string[]
|
mentions?: string[]
|
||||||
|
|
Ładowanie…
Reference in New Issue