diff --git a/components/publish/PublishWidget.vue b/components/publish/PublishWidget.vue
index 5b3b1d64..92206864 100644
--- a/components/publish/PublishWidget.vue
+++ b/components/publish/PublishWidget.vue
@@ -3,32 +3,33 @@ import type { CreateStatusParams, StatusVisibility } from 'masto'
import { fileOpen } from 'browser-fs-access'
import { useDropZone } from '@vueuse/core'
import { EditorContent } from '@tiptap/vue-3'
+import type { Draft } from '~/composables/statusDrafts'
const {
draftKey,
- placeholder = 'What is on your mind?',
- inReplyToId,
- inReplyToVisibility = 'public',
+ initial = getDefaultDraft() as never /* Bug of vue-core */,
expanded: _expanded = false,
} = defineProps<{
draftKey: string
+ initial?: () => Draft
placeholder?: string
inReplyToId?: string
inReplyToVisibility?: StatusVisibility
expanded?: boolean
}>()
+// eslint-disable-next-line prefer-const
+let { draft, isEmpty } = $(useDraft(draftKey, initial))
+
let isSending = $ref(false)
-let { draft } = $(useDraft(draftKey, inReplyToId, inReplyToVisibility))
-const isExistDraft = $computed(() => !!draft.params.status && draft.params.status !== '
')
-let isExpanded = $ref(isExistDraft || _expanded)
+let isExpanded = $ref(!isEmpty || _expanded)
const { editor } = useTiptap({
content: computed({
get: () => draft.params.status,
set: newVal => draft.params.status = newVal,
}),
- placeholder,
+ placeholder: draft.placeholder,
autofocus: isExpanded,
onSubmit: publish,
onFocus() { isExpanded = true },
@@ -108,6 +109,7 @@ async function publish() {
raw: draft.params.status,
...payload,
})
+ // eslint-disable-next-line no-alert
const result = confirm('[DEV] Payload logged to console, do you want to publish it?')
if (!result)
return
@@ -121,7 +123,7 @@ async function publish() {
else
await useMasto().statuses.update(draft.editingStatus.id, payload)
- draft = getDefaultDraft({ inReplyToId, visibility: inReplyToVisibility })
+ draft = initial()
isPublishDialogOpen.value = false
}
finally {
@@ -137,15 +139,6 @@ async function onDrop(files: File[] | null) {
}
const { isOverDropZone } = useDropZone(dropZoneRef, onDrop)
-
-onUnmounted(() => {
- // Remove draft if it's empty
- if (!draft.attachments.length && !draft.params.status) {
- nextTick(() => {
- delete currentUserDrafts.value[draftKey]
- })
- }
-})
@@ -261,7 +254,7 @@ onUnmounted(() => {
diff --git a/composables/dialog.ts b/composables/dialog.ts
index d8ebe235..c3562f54 100644
--- a/composables/dialog.ts
+++ b/composables/dialog.ts
@@ -19,9 +19,12 @@ export function openSigninDialog() {
isSigninDialogOpen.value = true
}
-export function openPublishDialog(draftKey = 'dialog', draft?: Draft) {
+export function openPublishDialog(draftKey = 'dialog', draft?: Draft, overwrite = false): void {
dialogDraftKey.value = draftKey
- if (draft)
+ if (overwrite) {
+ // TODO overwrite warning
+ }
+ if (draft && (overwrite || !currentUserDrafts.value[draftKey]))
currentUserDrafts.value[draftKey] = draft
isPublishDialogOpen.value = true
}
diff --git a/composables/statusDrafts.ts b/composables/statusDrafts.ts
index e241a07c..da4c2348 100644
--- a/composables/statusDrafts.ts
+++ b/composables/statusDrafts.ts
@@ -1,4 +1,4 @@
-import type { Account, Attachment, CreateStatusParams, Status, StatusVisibility } from 'masto'
+import type { Account, Attachment, CreateStatusParams, Status } from 'masto'
import { STORAGE_KEY_DRAFTS } from '~/constants'
import type { Mutable } from '~/types/utils'
@@ -8,6 +8,7 @@ export interface Draft {
status?: Exclude
}
attachments: Attachment[]
+ placeholder: string
}
export type DraftMap = Record
@@ -26,30 +27,56 @@ export function getDefaultDraft({
status = '',
inReplyToId,
visibility = 'public',
-}: Partial = {}): Draft {
+ placeholder = 'What is on your mind?',
+ attachments = [],
+}: Partial> = {}): Draft {
return {
params: {
status,
inReplyToId,
visibility,
},
- attachments: [],
+ attachments,
+ placeholder,
}
}
-export function getParamsFromStatus(status: Status): Draft['params'] {
- return {
- status: status.content,
+export function getDraftFromStatus(status: Status, text?: null | string): Draft {
+ return getDefaultDraft({
+ status: text || status.content,
mediaIds: status.mediaAttachments.map(att => att.id),
visibility: status.visibility,
+ attachments: status.mediaAttachments,
+ })
+}
+
+export function getReplyDraft(status: Status) {
+ return {
+ key: `reply-${status.id}`,
+ draft: () => getDefaultDraft({
+ inReplyToId: status!.id,
+ placeholder: `Reply to ${status?.account ? getDisplayName(status.account) : 'this thread'}`,
+ visibility: status.visibility,
+ }),
}
}
-export function useDraft(draftKey: string, inReplyToId?: string, inReplyToVisibility?: StatusVisibility) {
+export const isEmptyDraft = (draft: Draft) => {
+ const { params, attachments } = draft
+ const status = params.status || ''
+ return (status.length === 0 || status === '')
+ && attachments.length === 0
+ && (params.spoilerText || '').length === 0
+}
+
+export function useDraft(
+ draftKey: string,
+ initial: () => Draft = () => getDefaultDraft(),
+) {
const draft = computed({
get() {
if (!currentUserDrafts.value[draftKey])
- currentUserDrafts.value[draftKey] = getDefaultDraft({ inReplyToId, visibility: inReplyToVisibility })
+ currentUserDrafts.value[draftKey] = initial()
return currentUserDrafts.value[draftKey]
},
set(val) {
@@ -57,27 +84,30 @@ export function useDraft(draftKey: string, inReplyToId?: string, inReplyToVisibi
},
})
- const isEmpty = computed(() => {
- return (draft.value.params.status ?? '').trim().length === 0
- && draft.value.attachments.length === 0
+ const isEmpty = computed(() => isEmptyDraft(draft.value))
+
+ onUnmounted(async () => {
+ // Remove draft if it's empty
+ if (isEmpty.value) {
+ await nextTick()
+ delete currentUserDrafts.value[draftKey]
+ }
})
return { draft, isEmpty }
}
-export const dialogDraft = useDraft('dialog')
-
export function mentionUser(account: Account) {
openPublishDialog('dialog', getDefaultDraft({
status: `@${account.acct} `,
- }))
+ }), true)
}
export function directMessageUser(account: Account) {
openPublishDialog('dialog', getDefaultDraft({
status: `@${account.acct} `,
visibility: 'direct',
- }))
+ }), true)
}
export function clearUserDrafts(account?: Account) {
diff --git a/pages/@[account]/[status].vue b/pages/@[account]/[status].vue
index 74f842fb..344efcc6 100644
--- a/pages/@[account]/[status].vue
+++ b/pages/@[account]/[status].vue
@@ -1,4 +1,5 @@