refs #3771 Attach media files
This commit is contained in:
parent
135ed92b56
commit
a7d80c9d68
|
@ -2,11 +2,18 @@
|
||||||
<div class="compose">
|
<div class="compose">
|
||||||
<el-form :model="form" class="compose-form">
|
<el-form :model="form" class="compose-form">
|
||||||
<el-input v-model="form.status" type="textarea" :autosize="{ minRows: 2 }" :placeholder="$t('modals.new_toot.status')" />
|
<el-input v-model="form.status" type="textarea" :autosize="{ minRows: 2 }" :placeholder="$t('modals.new_toot.status')" />
|
||||||
|
<div class="preview" ref="previewRef">
|
||||||
|
<div class="image-wrapper" v-for="media in attachments" :key="media.id">
|
||||||
|
<img :src="media.preview_url" class="preview-image" />
|
||||||
|
<el-button class="remove-image" link @click="removeAttachment(media)"><font-awesome-icon icon="circle-xmark" /></el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-footer">
|
<div class="form-footer">
|
||||||
<el-button-group class="tool-buttons">
|
<el-button-group class="tool-buttons">
|
||||||
<el-button link size="default">
|
<el-button link size="default" @click="selectImage">
|
||||||
<font-awesome-icon icon="camera" />
|
<font-awesome-icon icon="camera" />
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<input name="image" type="file" class="image-input" ref="imageRef" @change="onChangeImage" />
|
||||||
<el-button link size="default" disabled>
|
<el-button link size="default" disabled>
|
||||||
<font-awesome-icon icon="square-poll-horizontal" />
|
<font-awesome-icon icon="square-poll-horizontal" />
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -19,7 +26,7 @@
|
||||||
</el-button-group>
|
</el-button-group>
|
||||||
<div class="actions-group">
|
<div class="actions-group">
|
||||||
<span>500</span>
|
<span>500</span>
|
||||||
<el-button type="primary" @click="post"> {{ $t('modals.new_toot.toot') }} </el-button>
|
<el-button type="primary" @click="post" :loading="loading"> {{ $t('modals.new_toot.toot') }} </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
@ -29,7 +36,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, reactive, computed, ref, onMounted } from 'vue'
|
import { defineComponent, reactive, computed, ref, onMounted } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import generator, { MegalodonInterface } from 'megalodon'
|
import generator, { Entity, MegalodonInterface } from 'megalodon'
|
||||||
import { useStore } from '@/store'
|
import { useStore } from '@/store'
|
||||||
import { MyWindow } from '~/src/types/global'
|
import { MyWindow } from '~/src/types/global'
|
||||||
import { LocalAccount } from '~/src/types/localAccount'
|
import { LocalAccount } from '~/src/types/localAccount'
|
||||||
|
@ -49,6 +56,9 @@ export default defineComponent({
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
status: ''
|
status: ''
|
||||||
})
|
})
|
||||||
|
const imageRef = ref<any>(null)
|
||||||
|
const attachments = ref<Array<Entity.Attachment | Entity.AsyncAttachment>>([])
|
||||||
|
const loading = ref<boolean>(false)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const [a, s]: [LocalAccount, LocalServer] = await win.ipcRenderer.invoke('get-local-account', id.value)
|
const [a, s]: [LocalAccount, LocalServer] = await win.ipcRenderer.invoke('get-local-account', id.value)
|
||||||
|
@ -60,21 +70,69 @@ export default defineComponent({
|
||||||
if (!client.value) {
|
if (!client.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let options = {}
|
||||||
try {
|
try {
|
||||||
await client.value.postStatus(form.status)
|
loading.value = true
|
||||||
|
if (attachments.value.length > 0) {
|
||||||
|
options = Object.assign(options, {
|
||||||
|
media_ids: attachments.value.map(m => m.id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await client.value.postStatus(form.status, options)
|
||||||
clear()
|
clear()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
form.status = ''
|
form.status = ''
|
||||||
|
attachments.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectImage = () => {
|
||||||
|
imageRef?.value?.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangeImage = async (e: Event) => {
|
||||||
|
const target = e.target as HTMLInputElement
|
||||||
|
const file = target.files?.item(0)
|
||||||
|
if (file === null || file === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await uploadImage(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadImage = async (file: File) => {
|
||||||
|
if (!client.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await client.value.uploadMedia(file)
|
||||||
|
attachments.value = [...attachments.value, res.data]
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeAttachment = async (attachment: Entity.Attachment | Entity.AsyncAttachment) => {
|
||||||
|
attachments.value = attachments.value.filter(e => e.id !== attachment.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
post
|
post,
|
||||||
|
imageRef,
|
||||||
|
selectImage,
|
||||||
|
onChangeImage,
|
||||||
|
loading,
|
||||||
|
attachments,
|
||||||
|
removeAttachment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -96,6 +154,45 @@ export default defineComponent({
|
||||||
box-shadow: 0 0 0 1px var(--theme-border-color, var(--theme-border-color)) inset;
|
box-shadow: 0 0 0 1px var(--theme-border-color, var(--theme-border-color)) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
|
||||||
|
.image-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
min-width: 10%;
|
||||||
|
height: 80px;
|
||||||
|
margin: 4px;
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-image {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
left: 2px;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
|
||||||
|
.fa-icon {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
width: auto;
|
||||||
|
height: 1em;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.form-footer {
|
.form-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -106,6 +203,10 @@ export default defineComponent({
|
||||||
button {
|
button {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions-group {
|
.actions-group {
|
||||||
|
|
Loading…
Reference in New Issue