commit: f15599e6e57477131ba5592e2874916ed1da06e2
parent 90345f158ff2eb12e619dbd7406f2fa81c379637
Author: Henry Jameson <me@hjkos.com>
Date: Fri, 18 Jun 2021 02:04:01 +0300
gallery in post status form!
Diffstat:
6 files changed, 228 insertions(+), 193 deletions(-)
diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js
@@ -13,7 +13,9 @@ import {
faPlayCircle,
faTimes,
faStop,
- faSearchPlus
+ faSearchPlus,
+ faTrashAlt,
+ faPencilAlt
} from '@fortawesome/free-solid-svg-icons'
library.add(
@@ -24,19 +26,25 @@ library.add(
faPlayCircle,
faTimes,
faStop,
- faSearchPlus
+ faSearchPlus,
+ faTrashAlt,
+ faPencilAlt
)
const Attachment = {
props: [
'attachment',
+ 'description',
+ 'hideDescription',
'nsfw',
'size',
'setMedia',
- 'naturalSizeLoad'
+ 'remove',
+ 'edit'
],
data () {
return {
+ localDescription: this.description || this.attachment.description,
nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,
hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,
preloadImage: this.$store.getters.mergedConfig.preloadImage,
@@ -93,9 +101,6 @@ const Attachment = {
isEmpty () {
return (this.type === 'html' && !this.attachment.oembed) || this.type === 'unknown'
},
- isSmall () {
- return this.size === 'small'
- },
useModal () {
const modalTypes = this.size === 'hide' ? ['image', 'video', 'audio']
: this.mergedConfig.playVideosInModal
@@ -105,6 +110,11 @@ const Attachment = {
},
...mapGetters(['mergedConfig'])
},
+ watch: {
+ localDescription (newVal) {
+ this.onEdit(newVal)
+ }
+ },
methods: {
linkClicked ({ target }) {
if (target.tagName === 'A') {
@@ -121,6 +131,12 @@ const Attachment = {
this.$emit('setMedia')
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 () {
this.$refs.flash.closePlayer()
@@ -154,7 +170,7 @@ const Attachment = {
onImageLoad (image) {
const width = image.naturalWidth
const height = image.naturalHeight
- this.naturalSizeLoad && this.naturalSizeLoad({ width, height })
+ this.$emit('naturalSizeLoad', { id: this.attachment.id, width, height })
}
}
}
diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue
@@ -12,151 +12,180 @@
:href="attachment.url"
:alt="attachment.description"
:title="attachment.description"
+ @click.prevent=""
>
<FAIcon :icon="placeholderIconClass" />
<b>{{ nsfw ? "NSFW / " : "" }}</b>{{ placeholderName }}
</a>
</button>
<div
- v-else
- v-show="!isEmpty"
class="Attachment"
:class="classNames"
+ v-else
>
- <a
- v-if="hidden"
- class="image-container"
- :href="attachment.url"
- :alt="attachment.description"
- :title="attachment.description"
- @click.prevent.stop="toggleHidden"
- >
- <img
- :key="nsfwImage"
- class="nsfw"
- :src="nsfwImage"
- >
- <FAIcon
- v-if="type === 'video'"
- class="play-icon"
- icon="play-circle"
- />
- </a>
<div
- class="attachment-buttons"
- v-if="!hidden"
- >
- <button
- v-if="type === 'flash' && flashLoaded"
- class="button-unstyled attachment-button"
- @click.prevent="stopFlash"
- >
- <FAIcon icon="stop" />
- </button>
- <button
- v-if="!useModal"
- class="button-unstyled attachment-button"
- @click.prevent="openModalForce"
- >
- <FAIcon icon="search-plus" />
- </button>
- <button
- v-if="nsfw && hideNsfwLocal"
- class="button-unstyled attachment-button"
- @click.prevent="toggleHidden"
- >
- <FAIcon icon="times" />
- </button>
- </div>
-
- <a
- v-if="type === 'image' && (!hidden || preloadImage)"
- class="image-container"
- :class="{'-hidden': hidden && preloadImage }"
- :href="attachment.url"
- target="_blank"
- @click.stop.prevent="openModal"
+ class="attachment-wrapper"
+ v-show="!isEmpty"
>
- <StillImage
- class="image"
- :referrerpolicy="referrerpolicy"
- :mimetype="attachment.mimetype"
- :src="attachment.large_thumb_url || attachment.url"
- :image-load-handler="onImageLoad"
+ <a
+ v-if="hidden"
+ class="image-container"
+ :href="attachment.url"
:alt="attachment.description"
- />
- </a>
+ :title="attachment.description"
+ @click.prevent.stop="toggleHidden"
+ >
+ <img
+ :key="nsfwImage"
+ class="nsfw"
+ :src="nsfwImage"
+ >
+ <FAIcon
+ v-if="type === 'video'"
+ class="play-icon"
+ icon="play-circle"
+ />
+ </a>
+ <div
+ class="attachment-buttons"
+ v-if="!hidden"
+ >
+ <button
+ v-if="type === 'flash' && flashLoaded"
+ class="button-unstyled attachment-button"
+ @click.prevent="stopFlash"
+ >
+ <FAIcon icon="stop" />
+ </button>
+ <button
+ v-if="!useModal"
+ class="button-unstyled attachment-button"
+ @click.prevent="openModalForce"
+ >
+ <FAIcon icon="search-plus" />
+ </button>
+ <button
+ v-if="nsfw && hideNsfwLocal"
+ class="button-unstyled attachment-button"
+ @click.prevent="toggleHidden"
+ >
+ <FAIcon icon="times" />
+ </button>
+ <button
+ v-if="remove"
+ class="button-unstyled attachment-button"
+ @click.prevent="onRemove"
+ >
+ <FAIcon icon="trash-alt" />
+ </button>
+ </div>
- <a
- v-if="type === 'video' && !hidden"
- class="video-container"
- :href="attachment.url"
- @click.stop.prevent="openModal"
- >
- <VideoAttachment
- class="video"
- :attachment="attachment"
- :controls="!useModal"
- @play="$emit('play')"
- @pause="$emit('pause')"
- />
- <FAIcon
- v-if="useModal"
- class="play-icon"
- icon="play-circle"
- />
- </a>
+ <a
+ v-if="type === 'image' && (!hidden || preloadImage)"
+ class="image-container"
+ :class="{'-hidden': hidden && preloadImage }"
+ :href="attachment.url"
+ target="_blank"
+ @click.stop.prevent="openModal"
+ >
+ <StillImage
+ class="image"
+ :referrerpolicy="referrerpolicy"
+ :mimetype="attachment.mimetype"
+ :src="attachment.large_thumb_url || attachment.url"
+ :image-load-handler="onImageLoad"
+ :alt="attachment.description"
+ />
+ </a>
- <a
- v-if="type === 'audio' && !hidden"
- class="audio-container"
- :href="attachment.url"
- @click.stop.prevent="openModal"
- >
- <audio
- v-if="type === 'audio'"
- :src="attachment.url"
- :alt="attachment.description"
- :title="attachment.description"
- controls
- @play="$emit('play')"
- @pause="$emit('pause')"
- />
- </a>
+ <a
+ v-if="type === 'video' && !hidden"
+ class="video-container"
+ :href="attachment.url"
+ @click.stop.prevent="openModal"
+ >
+ <VideoAttachment
+ class="video"
+ :attachment="attachment"
+ :controls="!useModal"
+ @play="$emit('play')"
+ @pause="$emit('pause')"
+ />
+ <FAIcon
+ v-if="useModal"
+ class="play-icon"
+ icon="play-circle"
+ />
+ </a>
+
+ <a
+ v-if="type === 'audio' && !hidden"
+ class="audio-container"
+ :href="attachment.url"
+ @click.stop.prevent="openModal"
+ >
+ <audio
+ v-if="type === 'audio'"
+ :src="attachment.url"
+ :alt="attachment.description"
+ :title="attachment.description"
+ controls
+ @play="$emit('play')"
+ @pause="$emit('pause')"
+ />
+ </a>
- <div
- v-if="type === 'html' && attachment.oembed"
- class="oembed-container"
- @click.prevent="linkClicked"
- >
<div
- v-if="attachment.thumb_url"
- class="image"
+ v-if="type === 'html' && attachment.oembed"
+ class="oembed-container"
+ @click.prevent="linkClicked"
>
- <img :src="attachment.thumb_url">
- </div>
- <div class="text">
- <!-- eslint-disable vue/no-v-html -->
- <h1><a :href="attachment.url">{{ attachment.oembed.title }}</a></h1>
- <div v-html="attachment.oembed.oembedHTML" />
- <!-- eslint-enable vue/no-v-html -->
+ <div
+ v-if="attachment.thumb_url"
+ class="image"
+ >
+ <img :src="attachment.thumb_url">
+ </div>
+ <div class="text">
+ <!-- eslint-disable vue/no-v-html -->
+ <h1><a :href="attachment.url">{{ attachment.oembed.title }}</a></h1>
+ <div v-html="attachment.oembed.oembedHTML" />
+ <!-- eslint-enable vue/no-v-html -->
+ </div>
</div>
- </div>
- <a
- v-if="type === 'flash' && !hidden"
- class="flash-container"
- :href="attachment.url"
- @click.stop.prevent="openModal"
+ <a
+ v-if="type === 'flash' && !hidden"
+ class="flash-container"
+ :href="attachment.url"
+ @click.stop.prevent="openModal"
+ >
+ <Flash
+ class="flash"
+ ref="flash"
+ :src="attachment.large_thumb_url || attachment.url"
+ @playerOpened="setFlashLoaded(true)"
+ @playerClosed="setFlashLoaded(false)"
+ />
+ </a>
+ </div>
+ <div
+ v-if="size !== 'hide' && !hideDescription && (edit || localDescription)"
+ class="description-container"
+ :class="{ '-static': !edit }"
>
- <Flash
- class="flash"
- ref="flash"
- :src="attachment.large_thumb_url || attachment.url"
- @playerOpened="setFlashLoaded(true)"
- @playerClosed="setFlashLoaded(false)"
- />
- </a>
+ <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>
diff --git a/src/components/gallery/gallery.js b/src/components/gallery/gallery.js
@@ -4,9 +4,15 @@ import { sumBy } from 'lodash'
const Gallery = {
props: [
'attachments',
+ 'limitRows',
+ 'descriptions',
'nsfw',
'setMedia',
- 'size'
+ 'size',
+ 'editable',
+ 'removeAttachment',
+ 'editAttachment',
+ 'maxPerRow'
],
data () {
return {
@@ -20,24 +26,19 @@ const Gallery = {
if (!this.attachments) {
return []
}
- console.log(this.size)
if (this.size === 'hide') {
return this.attachments.map(item => ({ minimal: true, items: [item] }))
}
const rows = this.attachments.reduce((acc, attachment, i) => {
+ if (this.size === 'small' && acc.length === 2) return acc
if (attachment.mimetype.includes('audio')) {
return [...acc, { audio: true, items: [attachment] }, { items: [] }]
}
- const maxPerRow = 3
- const attachmentsRemaining = this.attachments.length - i - 1
+ const maxPerRow = this.maxPerRow || 3
+ const attachmentsRemaining = this.attachments.length - i + 1
const currentRow = acc[acc.length - 1].items
- if (
- currentRow.length <= maxPerRow ||
- attachmentsRemaining === 1
- ) {
- currentRow.push(attachment)
- }
- if (currentRow.length === maxPerRow && attachmentsRemaining > 1) {
+ currentRow.push(attachment)
+ if (currentRow.length >= maxPerRow && attachmentsRemaining > maxPerRow) {
return [...acc, { items: [] }]
} else {
return acc
@@ -51,7 +52,9 @@ const Gallery = {
}, 0)
},
tooManyAttachments () {
- if (this.size === 'hide') {
+ if (this.editable || this.size === 'small') {
+ return false
+ } else if (this.size === 'hide') {
return this.attachments.length > 8
} else {
return this.attachmentsDimensionalScore > 1
@@ -59,8 +62,8 @@ const Gallery = {
}
},
methods: {
- onNaturalSizeLoad (id, size) {
- this.$set(this.sizes, id, size)
+ onNaturalSizeLoad ({ id, width, height }) {
+ this.$set(this.sizes, id, { width, height })
},
rowStyle (row) {
if (row.audio) {
@@ -81,8 +84,11 @@ const Gallery = {
this.hidingLong = event
},
openGallery () {
- this.setMedia()
- this.$store.dispatch('setCurrent', this.attachments[0])
+ this.$store.dispatch('setMedia', this.attachments)
+ this.$store.dispatch('setCurrentMedia', this.attachments[0])
+ },
+ onMedia () {
+ this.$store.dispatch('setMedia', this.attachments)
}
}
}
diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue
@@ -17,13 +17,18 @@
v-for="attachment in row.items"
class="gallery-item"
:key="attachment.id"
- :set-media="setMedia"
:nsfw="nsfw"
:attachment="attachment"
:allow-play="false"
: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)"
+ @setMedia="onMedia"
+ @naturalSizeLoad="onNaturalSizeLoad"
/>
</div>
</div>
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
@@ -4,6 +4,7 @@ import ScopeSelector from '../scope_selector/scope_selector.vue'
import EmojiInput from '../emoji_input/emoji_input.vue'
import PollForm from '../poll/poll_form.vue'
import Attachment from '../attachment/attachment.vue'
+import Gallery from 'src/components/gallery/gallery.vue'
import StatusContent from '../status_content/status_content.vue'
import fileTypeService from '../../services/file_type/file_type.service.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
@@ -85,7 +86,8 @@ const PostStatusForm = {
Checkbox,
Select,
Attachment,
- StatusContent
+ StatusContent,
+ Gallery
},
mounted () {
this.updateIdempotencyKey()
@@ -388,6 +390,10 @@ const PostStatusForm = {
this.newStatus.files.splice(index, 1)
this.$emit('resize')
},
+ editAttachment (fileInfo, newText) {
+ console.log(fileInfo, newText)
+ this.newStatus.mediaDescriptions[fileInfo.id] = newText
+ },
uploadFailed (errString, templateArgs) {
templateArgs = templateArgs || {}
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
@@ -287,32 +287,21 @@
@click="clearError"
/>
</div>
- <div class="attachments">
- <div
- v-for="file in newStatus.files"
- :key="file.url"
- class="media-upload-wrapper"
- >
- <button
- class="button-unstyled hider"
- @click="removeMediaFile(file)"
- >
- <FAIcon icon="times" />
- </button>
- <attachment
- :attachment="file"
- :set-media="() => $store.dispatch('setMedia', newStatus.files)"
- size="small"
- allow-play="false"
- />
- <input
- v-model="newStatus.mediaDescriptions[file.id]"
- type="text"
- :placeholder="$t('post_status.media_description')"
- @keydown.enter.prevent=""
- >
- </div>
- </div>
+ <gallery
+ v-if="newStatus.files && newStatus.files.length > 0"
+ class="attachments"
+ :maxPerRow="1"
+ :nsfw="false"
+ :attachments="newStatus.files"
+ :descriptions="newStatus.mediaDescriptions"
+ :set-media="() => $store.dispatch('setMedia', newStatus.files)"
+ :editable="true"
+ :editAttachment="editAttachment"
+ :removeAttachment="removeMediaFile"
+ size="small"
+ @play="$emit('mediaplay', attachment.id)"
+ @pause="$emit('mediapause', attachment.id)"
+ />
<div
v-if="newStatus.files.length > 0 && !disableSensitivityCheckbox"
class="upload_settings"
@@ -507,15 +496,6 @@
flex-direction: column;
}
- .attachments .media-upload-wrapper {
- position: relative;
-
- .attachment {
- margin: 0;
- padding: 0;
- }
- }
-
.btn {
cursor: pointer;
}
@@ -616,11 +596,4 @@
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>