elk/components/publish/PublishWidget.vue

148 wiersze
3.4 KiB
Vue
Czysty Zwykły widok Historia

2022-11-21 06:55:31 +00:00
<script setup lang="ts">
2022-11-23 17:17:54 +00:00
import type { Attachment, CreateStatusParams, CreateStatusParamsWithStatus } from 'masto'
2022-11-21 06:55:31 +00:00
const {
draftKey,
placeholder = 'What is on your mind?',
inReplyToId,
} = defineProps<{
draftKey: string
placeholder?: string
inReplyToId?: string
}>()
let isSending = $ref(false)
function getDefaultStatus(): CreateStatusParamsWithStatus {
return {
status: '',
inReplyToId,
}
}
2022-11-24 06:54:54 +00:00
const draft = $computed(() => {
if (!currentUserDrafts.value[draftKey]) {
currentUserDrafts.value[draftKey] = {
params: getDefaultStatus(),
attachments: [],
}
}
return currentUserDrafts.value[draftKey]
})
2022-11-23 17:17:54 +00:00
const status = $computed(() => {
return {
2022-11-24 06:54:54 +00:00
...draft.params,
mediaIds: draft.attachments.map(a => a.id),
2022-11-23 17:17:54 +00:00
} as CreateStatusParams
})
let isUploading = $ref<boolean>(false)
async function handlePaste(evt: ClipboardEvent) {
const files = evt.clipboardData?.files
if (!files)
return
2022-11-24 04:05:13 +00:00
evt.preventDefault()
2022-11-23 17:17:54 +00:00
await uploadAttachments(Array.from(files))
}
async function pickAttachments() {
if (!globalThis.showOpenFilePicker)
2022-11-24 04:05:13 +00:00
// TODO: FireFox & Safari don't support it.
2022-11-23 17:17:54 +00:00
return
const handles = await showOpenFilePicker({
multiple: true,
types: [{
2022-11-24 04:05:13 +00:00
description: 'Attachments',
2022-11-23 17:17:54 +00:00
accept: {
2022-11-24 04:05:13 +00:00
'image/*': ['.png', '.gif', '.jpeg', '.jpg', '.webp', '.avif', '.heic', '.heif'],
'video/*': ['.webm', '.mp4', '.m4v', '.mov', '.ogv', '.3gp'],
'audio/*': ['.mp3', '.ogg', '.oga', '.wav', '.flac', '.opus', '.aac', '.m4a', '.3gp', '.wma'],
2022-11-23 17:17:54 +00:00
},
}],
})
const files = await Promise.all(handles.map(handle => handle.getFile()))
await uploadAttachments(files)
}
async function uploadAttachments(files: File[]) {
isUploading = true
for (const file of files) {
const attachment = await masto.mediaAttachments.create({
file,
})
2022-11-24 06:54:54 +00:00
draft.attachments.push(attachment)
2022-11-23 17:17:54 +00:00
}
isUploading = false
}
2022-11-24 04:05:13 +00:00
function removeAttachment(index: number) {
2022-11-24 06:54:54 +00:00
draft.attachments.splice(index, 1)
2022-11-23 17:17:54 +00:00
}
2022-11-21 06:55:31 +00:00
async function publish() {
try {
isSending = true
2022-11-23 17:17:54 +00:00
await masto.statuses.create(status)
2022-11-24 06:54:54 +00:00
draft.params = getDefaultStatus()
draft.attachments = []
2022-11-21 06:55:31 +00:00
}
finally {
isSending = false
}
}
onUnmounted(() => {
2022-11-24 06:54:54 +00:00
if (!draft.attachments.length && !draft.params.status) {
2022-11-21 06:55:31 +00:00
nextTick(() => {
2022-11-24 06:54:54 +00:00
delete currentUserDrafts.value[draftKey]
2022-11-21 06:55:31 +00:00
})
}
})
</script>
<template>
<div
2022-11-23 17:17:54 +00:00
flex flex-col gap-3
2022-11-21 06:55:31 +00:00
:class="isSending ? 'pointer-events-none' : ''"
>
<textarea
2022-11-24 06:54:54 +00:00
v-model="draft.params.status"
2022-11-21 06:55:31 +00:00
:placeholder="placeholder"
p2 border-rounded w-full h-40
2022-11-23 02:16:31 +00:00
bg-gray:10 outline-none border="~ base"
2022-11-23 17:17:54 +00:00
@paste="handlePaste"
2022-11-21 06:55:31 +00:00
/>
2022-11-23 17:17:54 +00:00
<div flex="~" gap-2>
<button hover:bg-active p2 rounded-5 @click="pickAttachments">
<div i-ri:upload-line />
</button>
</div>
<div flex="~ col gap-2" max-h-50vh overflow-auto>
<publish-attachment
2022-11-24 06:54:54 +00:00
v-for="(att, idx) in draft.attachments" :key="att.id"
2022-11-23 17:17:54 +00:00
:attachment="att"
@remove="removeAttachment(idx)"
/>
</div>
<div v-if="isUploading" flex gap-2 justify-end items-center>
<div op50 i-ri:loader-2-fill animate-spin text-2xl />
Uploading...
</div>
2022-11-21 06:55:31 +00:00
<div flex justify-end>
<button
2022-11-23 03:06:56 +00:00
btn-solid
2022-11-24 06:54:54 +00:00
:disabled="isUploading || (draft.attachments.length === 0 && !draft.params.status)"
2022-11-21 06:55:31 +00:00
@click="publish"
>
Publish!
</button>
</div>
</div>
</template>