logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
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:

Msrc/components/attachment/attachment.js30+++++++++++++++++++++++-------
Msrc/components/attachment/attachment.vue279++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/components/gallery/gallery.js38++++++++++++++++++++++----------------
Msrc/components/gallery/gallery.vue9+++++++--
Msrc/components/post_status_form/post_status_form.js8+++++++-
Msrc/components/post_status_form/post_status_form.vue57+++++++++++++++------------------------------------------
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>