gallery in post status form!
This commit is contained in:
parent
90345f158f
commit
f15599e6e5
6 changed files with 231 additions and 196 deletions
|
@ -13,7 +13,9 @@ import {
|
||||||
faPlayCircle,
|
faPlayCircle,
|
||||||
faTimes,
|
faTimes,
|
||||||
faStop,
|
faStop,
|
||||||
faSearchPlus
|
faSearchPlus,
|
||||||
|
faTrashAlt,
|
||||||
|
faPencilAlt
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
|
@ -24,19 +26,25 @@ library.add(
|
||||||
faPlayCircle,
|
faPlayCircle,
|
||||||
faTimes,
|
faTimes,
|
||||||
faStop,
|
faStop,
|
||||||
faSearchPlus
|
faSearchPlus,
|
||||||
|
faTrashAlt,
|
||||||
|
faPencilAlt
|
||||||
)
|
)
|
||||||
|
|
||||||
const Attachment = {
|
const Attachment = {
|
||||||
props: [
|
props: [
|
||||||
'attachment',
|
'attachment',
|
||||||
|
'description',
|
||||||
|
'hideDescription',
|
||||||
'nsfw',
|
'nsfw',
|
||||||
'size',
|
'size',
|
||||||
'setMedia',
|
'setMedia',
|
||||||
'naturalSizeLoad'
|
'remove',
|
||||||
|
'edit'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
localDescription: this.description || this.attachment.description,
|
||||||
nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,
|
nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,
|
||||||
hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,
|
hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,
|
||||||
preloadImage: this.$store.getters.mergedConfig.preloadImage,
|
preloadImage: this.$store.getters.mergedConfig.preloadImage,
|
||||||
|
@ -93,9 +101,6 @@ const Attachment = {
|
||||||
isEmpty () {
|
isEmpty () {
|
||||||
return (this.type === 'html' && !this.attachment.oembed) || this.type === 'unknown'
|
return (this.type === 'html' && !this.attachment.oembed) || this.type === 'unknown'
|
||||||
},
|
},
|
||||||
isSmall () {
|
|
||||||
return this.size === 'small'
|
|
||||||
},
|
|
||||||
useModal () {
|
useModal () {
|
||||||
const modalTypes = this.size === 'hide' ? ['image', 'video', 'audio']
|
const modalTypes = this.size === 'hide' ? ['image', 'video', 'audio']
|
||||||
: this.mergedConfig.playVideosInModal
|
: this.mergedConfig.playVideosInModal
|
||||||
|
@ -105,6 +110,11 @@ const Attachment = {
|
||||||
},
|
},
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
localDescription (newVal) {
|
||||||
|
this.onEdit(newVal)
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
linkClicked ({ target }) {
|
linkClicked ({ target }) {
|
||||||
if (target.tagName === 'A') {
|
if (target.tagName === 'A') {
|
||||||
|
@ -121,6 +131,12 @@ const Attachment = {
|
||||||
this.$emit('setMedia')
|
this.$emit('setMedia')
|
||||||
this.$store.dispatch('setCurrentMedia', this.attachment)
|
this.$store.dispatch('setCurrentMedia', this.attachment)
|
||||||
},
|
},
|
||||||
|
onEdit (event) {
|
||||||
|
console.log('ONEDIT', event)
|
||||||
|
this.edit && this.edit(this.attachment, event)
|
||||||
|
},
|
||||||
|
onRemove () {
|
||||||
|
this.remove && this.remove(this.attachment)
|
||||||
},
|
},
|
||||||
stopFlash () {
|
stopFlash () {
|
||||||
this.$refs.flash.closePlayer()
|
this.$refs.flash.closePlayer()
|
||||||
|
@ -154,7 +170,7 @@ const Attachment = {
|
||||||
onImageLoad (image) {
|
onImageLoad (image) {
|
||||||
const width = image.naturalWidth
|
const width = image.naturalWidth
|
||||||
const height = image.naturalHeight
|
const height = image.naturalHeight
|
||||||
this.naturalSizeLoad && this.naturalSizeLoad({ width, height })
|
this.$emit('naturalSizeLoad', { id: this.attachment.id, width, height })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,20 @@
|
||||||
:href="attachment.url"
|
:href="attachment.url"
|
||||||
:alt="attachment.description"
|
:alt="attachment.description"
|
||||||
:title="attachment.description"
|
:title="attachment.description"
|
||||||
|
@click.prevent=""
|
||||||
>
|
>
|
||||||
<FAIcon :icon="placeholderIconClass" />
|
<FAIcon :icon="placeholderIconClass" />
|
||||||
<b>{{ nsfw ? "NSFW / " : "" }}</b>{{ placeholderName }}
|
<b>{{ nsfw ? "NSFW / " : "" }}</b>{{ placeholderName }}
|
||||||
</a>
|
</a>
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
v-else
|
|
||||||
v-show="!isEmpty"
|
|
||||||
class="Attachment"
|
class="Attachment"
|
||||||
:class="classNames"
|
:class="classNames"
|
||||||
|
v-else
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="attachment-wrapper"
|
||||||
|
v-show="!isEmpty"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
v-if="hidden"
|
v-if="hidden"
|
||||||
|
@ -67,6 +71,13 @@
|
||||||
>
|
>
|
||||||
<FAIcon icon="times" />
|
<FAIcon icon="times" />
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="remove"
|
||||||
|
class="button-unstyled attachment-button"
|
||||||
|
@click.prevent="onRemove"
|
||||||
|
>
|
||||||
|
<FAIcon icon="trash-alt" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
@ -158,6 +169,24 @@
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="size !== 'hide' && !hideDescription && (edit || localDescription)"
|
||||||
|
class="description-container"
|
||||||
|
:class="{ '-static': !edit }"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
v-if="edit"
|
||||||
|
v-model="localDescription"
|
||||||
|
type="text"
|
||||||
|
class="description-field"
|
||||||
|
:placeholder="$t('post_status.media_description')"
|
||||||
|
@keydown.enter.prevent=""
|
||||||
|
>
|
||||||
|
<p v-else>
|
||||||
|
{{ localDescription }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./attachment.js"></script>
|
<script src="./attachment.js"></script>
|
||||||
|
|
|
@ -4,9 +4,15 @@ import { sumBy } from 'lodash'
|
||||||
const Gallery = {
|
const Gallery = {
|
||||||
props: [
|
props: [
|
||||||
'attachments',
|
'attachments',
|
||||||
|
'limitRows',
|
||||||
|
'descriptions',
|
||||||
'nsfw',
|
'nsfw',
|
||||||
'setMedia',
|
'setMedia',
|
||||||
'size'
|
'size',
|
||||||
|
'editable',
|
||||||
|
'removeAttachment',
|
||||||
|
'editAttachment',
|
||||||
|
'maxPerRow'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
@ -20,24 +26,19 @@ const Gallery = {
|
||||||
if (!this.attachments) {
|
if (!this.attachments) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
console.log(this.size)
|
|
||||||
if (this.size === 'hide') {
|
if (this.size === 'hide') {
|
||||||
return this.attachments.map(item => ({ minimal: true, items: [item] }))
|
return this.attachments.map(item => ({ minimal: true, items: [item] }))
|
||||||
}
|
}
|
||||||
const rows = this.attachments.reduce((acc, attachment, i) => {
|
const rows = this.attachments.reduce((acc, attachment, i) => {
|
||||||
|
if (this.size === 'small' && acc.length === 2) return acc
|
||||||
if (attachment.mimetype.includes('audio')) {
|
if (attachment.mimetype.includes('audio')) {
|
||||||
return [...acc, { audio: true, items: [attachment] }, { items: [] }]
|
return [...acc, { audio: true, items: [attachment] }, { items: [] }]
|
||||||
}
|
}
|
||||||
const maxPerRow = 3
|
const maxPerRow = this.maxPerRow || 3
|
||||||
const attachmentsRemaining = this.attachments.length - i - 1
|
const attachmentsRemaining = this.attachments.length - i + 1
|
||||||
const currentRow = acc[acc.length - 1].items
|
const currentRow = acc[acc.length - 1].items
|
||||||
if (
|
|
||||||
currentRow.length <= maxPerRow ||
|
|
||||||
attachmentsRemaining === 1
|
|
||||||
) {
|
|
||||||
currentRow.push(attachment)
|
currentRow.push(attachment)
|
||||||
}
|
if (currentRow.length >= maxPerRow && attachmentsRemaining > maxPerRow) {
|
||||||
if (currentRow.length === maxPerRow && attachmentsRemaining > 1) {
|
|
||||||
return [...acc, { items: [] }]
|
return [...acc, { items: [] }]
|
||||||
} else {
|
} else {
|
||||||
return acc
|
return acc
|
||||||
|
@ -51,7 +52,9 @@ const Gallery = {
|
||||||
}, 0)
|
}, 0)
|
||||||
},
|
},
|
||||||
tooManyAttachments () {
|
tooManyAttachments () {
|
||||||
if (this.size === 'hide') {
|
if (this.editable || this.size === 'small') {
|
||||||
|
return false
|
||||||
|
} else if (this.size === 'hide') {
|
||||||
return this.attachments.length > 8
|
return this.attachments.length > 8
|
||||||
} else {
|
} else {
|
||||||
return this.attachmentsDimensionalScore > 1
|
return this.attachmentsDimensionalScore > 1
|
||||||
|
@ -59,8 +62,8 @@ const Gallery = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onNaturalSizeLoad (id, size) {
|
onNaturalSizeLoad ({ id, width, height }) {
|
||||||
this.$set(this.sizes, id, size)
|
this.$set(this.sizes, id, { width, height })
|
||||||
},
|
},
|
||||||
rowStyle (row) {
|
rowStyle (row) {
|
||||||
if (row.audio) {
|
if (row.audio) {
|
||||||
|
@ -81,8 +84,11 @@ const Gallery = {
|
||||||
this.hidingLong = event
|
this.hidingLong = event
|
||||||
},
|
},
|
||||||
openGallery () {
|
openGallery () {
|
||||||
this.setMedia()
|
this.$store.dispatch('setMedia', this.attachments)
|
||||||
this.$store.dispatch('setCurrent', this.attachments[0])
|
this.$store.dispatch('setCurrentMedia', this.attachments[0])
|
||||||
|
},
|
||||||
|
onMedia () {
|
||||||
|
this.$store.dispatch('setMedia', this.attachments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,18 @@
|
||||||
v-for="attachment in row.items"
|
v-for="attachment in row.items"
|
||||||
class="gallery-item"
|
class="gallery-item"
|
||||||
:key="attachment.id"
|
:key="attachment.id"
|
||||||
:set-media="setMedia"
|
|
||||||
:nsfw="nsfw"
|
:nsfw="nsfw"
|
||||||
:attachment="attachment"
|
:attachment="attachment"
|
||||||
:allow-play="false"
|
:allow-play="false"
|
||||||
:size="size"
|
:size="size"
|
||||||
:natural-size-load="onNaturalSizeLoad.bind(null, attachment.id)"
|
:editable="editable"
|
||||||
|
:remove="removeAttachment"
|
||||||
|
:edit="editAttachment"
|
||||||
|
:description="descriptions && descriptions[attachment.id]"
|
||||||
|
:hideDescription="tooManyAttachments && hidingLong"
|
||||||
:style="itemStyle(attachment.id, row.items)"
|
:style="itemStyle(attachment.id, row.items)"
|
||||||
|
@setMedia="onMedia"
|
||||||
|
@naturalSizeLoad="onNaturalSizeLoad"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ScopeSelector from '../scope_selector/scope_selector.vue'
|
||||||
import EmojiInput from '../emoji_input/emoji_input.vue'
|
import EmojiInput from '../emoji_input/emoji_input.vue'
|
||||||
import PollForm from '../poll/poll_form.vue'
|
import PollForm from '../poll/poll_form.vue'
|
||||||
import Attachment from '../attachment/attachment.vue'
|
import Attachment from '../attachment/attachment.vue'
|
||||||
|
import Gallery from 'src/components/gallery/gallery.vue'
|
||||||
import StatusContent from '../status_content/status_content.vue'
|
import StatusContent from '../status_content/status_content.vue'
|
||||||
import fileTypeService from '../../services/file_type/file_type.service.js'
|
import fileTypeService from '../../services/file_type/file_type.service.js'
|
||||||
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
|
||||||
|
@ -85,7 +86,8 @@ const PostStatusForm = {
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Select,
|
Select,
|
||||||
Attachment,
|
Attachment,
|
||||||
StatusContent
|
StatusContent,
|
||||||
|
Gallery
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.updateIdempotencyKey()
|
this.updateIdempotencyKey()
|
||||||
|
@ -388,6 +390,10 @@ const PostStatusForm = {
|
||||||
this.newStatus.files.splice(index, 1)
|
this.newStatus.files.splice(index, 1)
|
||||||
this.$emit('resize')
|
this.$emit('resize')
|
||||||
},
|
},
|
||||||
|
editAttachment (fileInfo, newText) {
|
||||||
|
console.log(fileInfo, newText)
|
||||||
|
this.newStatus.mediaDescriptions[fileInfo.id] = newText
|
||||||
|
},
|
||||||
uploadFailed (errString, templateArgs) {
|
uploadFailed (errString, templateArgs) {
|
||||||
templateArgs = templateArgs || {}
|
templateArgs = templateArgs || {}
|
||||||
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
|
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
|
||||||
|
|
|
@ -287,32 +287,21 @@
|
||||||
@click="clearError"
|
@click="clearError"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="attachments">
|
<gallery
|
||||||
<div
|
v-if="newStatus.files && newStatus.files.length > 0"
|
||||||
v-for="file in newStatus.files"
|
class="attachments"
|
||||||
:key="file.url"
|
:maxPerRow="1"
|
||||||
class="media-upload-wrapper"
|
:nsfw="false"
|
||||||
>
|
:attachments="newStatus.files"
|
||||||
<button
|
:descriptions="newStatus.mediaDescriptions"
|
||||||
class="button-unstyled hider"
|
|
||||||
@click="removeMediaFile(file)"
|
|
||||||
>
|
|
||||||
<FAIcon icon="times" />
|
|
||||||
</button>
|
|
||||||
<attachment
|
|
||||||
:attachment="file"
|
|
||||||
:set-media="() => $store.dispatch('setMedia', newStatus.files)"
|
:set-media="() => $store.dispatch('setMedia', newStatus.files)"
|
||||||
|
:editable="true"
|
||||||
|
:editAttachment="editAttachment"
|
||||||
|
:removeAttachment="removeMediaFile"
|
||||||
size="small"
|
size="small"
|
||||||
allow-play="false"
|
@play="$emit('mediaplay', attachment.id)"
|
||||||
|
@pause="$emit('mediapause', attachment.id)"
|
||||||
/>
|
/>
|
||||||
<input
|
|
||||||
v-model="newStatus.mediaDescriptions[file.id]"
|
|
||||||
type="text"
|
|
||||||
:placeholder="$t('post_status.media_description')"
|
|
||||||
@keydown.enter.prevent=""
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-if="newStatus.files.length > 0 && !disableSensitivityCheckbox"
|
v-if="newStatus.files.length > 0 && !disableSensitivityCheckbox"
|
||||||
class="upload_settings"
|
class="upload_settings"
|
||||||
|
@ -507,15 +496,6 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachments .media-upload-wrapper {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.attachment {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -616,11 +596,4 @@
|
||||||
border: 2px dashed var(--text, $fallback--text);
|
border: 2px dashed var(--text, $fallback--text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: unify with attachment.vue (otherwise the uploaded images are not minified unless a status with an attachment was displayed before)
|
|
||||||
img.media-upload, .media-upload-container > video {
|
|
||||||
line-height: 0;
|
|
||||||
max-height: 200px;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue