diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/attachment/attachment.js | 29 | ||||
| -rw-r--r-- | src/components/attachment/attachment.vue | 30 | ||||
| -rw-r--r-- | src/components/gallery/gallery.vue | 4 | ||||
| -rw-r--r-- | src/components/media_modal/media_modal.vue | 10 | ||||
| -rw-r--r-- | src/components/post_status_form/post_status_form.js | 7 | ||||
| -rw-r--r-- | src/components/post_status_form/post_status_form.vue | 68 | ||||
| -rw-r--r-- | src/components/status_content/status_content.js | 12 | ||||
| -rw-r--r-- | src/components/status_content/status_content.vue | 12 | ||||
| -rw-r--r-- | src/components/still-image/still-image.js | 3 | ||||
| -rw-r--r-- | src/components/still-image/still-image.vue | 2 | ||||
| -rw-r--r-- | src/components/video_attachment/video_attachment.vue | 2 | ||||
| -rw-r--r-- | src/i18n/en.json | 1 | ||||
| -rw-r--r-- | src/modules/media_viewer.js | 2 | ||||
| -rw-r--r-- | src/services/api/api.service.js | 4 | ||||
| -rw-r--r-- | src/services/status_poster/status_poster.service.js | 5 |
15 files changed, 110 insertions, 81 deletions
diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index b832e10f..23af693f 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -8,7 +8,6 @@ const Attachment = { props: [ 'attachment', 'nsfw', - 'statusId', 'size', 'allowPlay', 'setMedia', @@ -30,9 +29,21 @@ const Attachment = { VideoAttachment }, computed: { - usePlaceHolder () { + usePlaceholder () { return this.size === 'hide' || this.type === 'unknown' }, + placeholderName () { + if (this.attachment.description === '' || !this.attachment.description) { + return this.type.toUpperCase() + } + return this.attachment.description + }, + placeholderIconClass () { + if (this.type === 'image') return 'icon-picture' + if (this.type === 'video') return 'icon-video' + if (this.type === 'audio') return 'icon-music' + return 'icon-doc' + }, referrerpolicy () { return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer' }, @@ -51,6 +62,13 @@ const Attachment = { fullwidth () { return this.type === 'html' || this.type === 'audio' }, + useModal () { + const modalTypes = this.size === 'hide' ? ['image', 'video', 'audio'] + : this.mergedConfig.playVideosInModal + ? ['image', 'video'] + : ['image'] + return modalTypes.includes(this.type) + }, ...mapGetters(['mergedConfig']) }, methods: { @@ -60,12 +78,7 @@ const Attachment = { } }, openModal (event) { - const modalTypes = this.mergedConfig.playVideosInModal - ? ['image', 'video'] - : ['image'] - if (fileTypeService.fileMatchesSomeType(modalTypes, this.attachment) || - this.usePlaceHolder - ) { + if (this.useModal) { event.stopPropagation() event.preventDefault() this.setMedia() diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index a7e217c1..a18bf186 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -1,6 +1,6 @@ <template> <div - v-if="usePlaceHolder" + v-if="usePlaceholder" @click="openModal" > <a @@ -8,8 +8,11 @@ class="placeholder" target="_blank" :href="attachment.url" + :alt="attachment.description" + :title="attachment.description" > - [{{ nsfw ? "NSFW/" : "" }}{{ type.toUpperCase() }}] + <span :class="placeholderIconClass" /> + <b>{{ nsfw ? "NSFW / " : "" }}</b>{{ placeholderName }} </a> </div> <div @@ -22,6 +25,8 @@ v-if="hidden" class="image-attachment" :href="attachment.url" + :alt="attachment.description" + :title="attachment.description" @click.prevent="toggleHidden" > <img @@ -51,7 +56,6 @@ :class="{'hidden': hidden && preloadImage }" :href="attachment.url" target="_blank" - :title="attachment.description" @click="openModal" > <StillImage @@ -59,6 +63,7 @@ :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url" :image-load-handler="onImageLoad" + :alt="attachment.description" /> </a> @@ -83,6 +88,8 @@ <audio v-if="type === 'audio'" :src="attachment.url" + :alt="attachment.description" + :title="attachment.description" controls /> @@ -116,22 +123,19 @@ display: flex; flex-wrap: wrap; - .attachment.media-upload-container { - flex: 0 0 auto; - max-height: 200px; + .non-gallery { max-width: 100%; - display: flex; - align-items: center; - video { - max-width: 100%; - } } .placeholder { - margin-right: 8px; - margin-bottom: 4px; + display: inline-block; + padding: 0.3em 1em 0.3em 0; color: $fallback--link; color: var(--postLink, $fallback--link); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + max-width: 100%; } .nsfw-placeholder { diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index 1ffa7b3c..ca91c9c1 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -50,9 +50,7 @@ align-content: stretch; } - // FIXME: specificity problem with this and .attachments.attachment - // we shouldn't have the need for .image here - .attachment.image { + .gallery-row-inner .attachment { margin: 0 0.5em 0 0; flex-grow: 1; height: 100%; diff --git a/src/components/media_modal/media_modal.vue b/src/components/media_modal/media_modal.vue index 80d2a8b9..46931667 100644 --- a/src/components/media_modal/media_modal.vue +++ b/src/components/media_modal/media_modal.vue @@ -8,6 +8,8 @@ v-if="type === 'image'" class="modal-image" :src="currentMedia.url" + :alt="currentMedia.description" + :title="currentMedia.description" @touchstart.stop="mediaTouchStart" @touchmove.stop="mediaTouchMove" @click="hide" @@ -18,6 +20,14 @@ :attachment="currentMedia" :controls="true" /> + <audio + v-if="type === 'audio'" + class="modal-image" + :src="currentMedia.url" + :alt="currentMedia.description" + :title="currentMedia.description" + controls + /> <button v-if="canNavigate" :title="$t('media_modal.previous')" diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 9027566f..6bbf6cf1 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -3,6 +3,7 @@ import MediaUpload from '../media_upload/media_upload.vue' 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 fileTypeService from '../../services/file_type/file_type.service.js' import { findOffset } from '../../services/offset_finder/offset_finder.service.js' import { reject, map, uniqBy } from 'lodash' @@ -38,7 +39,8 @@ const PostStatusForm = { EmojiInput, PollForm, ScopeSelector, - Checkbox + Checkbox, + Attachment }, mounted () { this.resize(this.$refs.textarea) @@ -78,6 +80,7 @@ const PostStatusForm = { nsfw: false, files: [], poll: {}, + mediaDescriptions: {}, visibility: scope, contentType }, @@ -190,6 +193,7 @@ const PostStatusForm = { visibility: newStatus.visibility, sensitive: newStatus.nsfw, media: newStatus.files, + mediaDescriptions: newStatus.mediaDescriptions || {}, store: this.$store, inReplyToStatusId: this.replyTo, contentType: newStatus.contentType, @@ -200,6 +204,7 @@ const PostStatusForm = { status: '', spoilerText: '', files: [], + mediaDescriptions: {}, visibility: newStatus.visibility, contentType: newStatus.contentType, poll: {} diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index e3d8d087..442b9297 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -245,27 +245,18 @@ class="fa button-icon icon-cancel" @click="removeMediaFile(file)" /> - <div class="media-upload-container attachment"> - <img - v-if="type(file) === 'image'" - class="thumbnail media-upload" - :src="file.url" - > - <video - v-if="type(file) === 'video'" - :src="file.url" - controls - /> - <audio - v-if="type(file) === 'audio'" - :src="file.url" - controls - /> - <a - v-if="type(file) === 'unknown'" - :href="file.url" - >{{ file.url }}</a> - </div> + <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> <div @@ -381,11 +372,9 @@ } .media-upload-wrapper { - flex: 0 0 auto; - max-width: 100%; - min-width: 50px; margin-right: .2em; margin-bottom: .5em; + width: 18em; .icon-cancel { display: inline-block; @@ -399,6 +388,20 @@ border-bottom-left-radius: 0; border-bottom-right-radius: 0; } + + img, video { + object-fit: contain; + max-height: 10em; + } + + .video { + max-height: 10em; + } + + input { + flex: 1; + width: 100%; + } } .status-input-wrapper { @@ -413,23 +416,8 @@ .attachment { margin: 0; + padding: 0; position: relative; - flex: 0 0 auto; - border: 1px solid $fallback--border; - border: 1px solid var(--border, $fallback--border); - text-align: center; - - audio { - min-width: 300px; - flex: 1 0 auto; - } - - a { - display: block; - text-align: left; - line-height: 1.2; - padding: .5em; - } } i { diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js index 09ea3a20..2b9ea50c 100644 --- a/src/components/status_content/status_content.js +++ b/src/components/status_content/status_content.js @@ -99,15 +99,9 @@ const StatusContent = { file => !fileType.fileMatchesSomeType(this.galleryTypes, file) ) }, - hasImageAttachments () { - return this.status.attachments.some( - file => fileType.fileType(file.mimetype) === 'image' - ) - }, - hasVideoAttachments () { - return this.status.attachments.some( - file => fileType.fileType(file.mimetype) === 'video' - ) + attachmentTypes () { + console.log(this.status.attachments) + return this.status.attachments.map(file => fileType.fileType(file.mimetype)) }, maxThumbnails () { return this.mergedConfig.maxThumbnails diff --git a/src/components/status_content/status_content.vue b/src/components/status_content/status_content.vue index 3460c2fa..5a4b4f1e 100644 --- a/src/components/status_content/status_content.vue +++ b/src/components/status_content/status_content.vue @@ -55,14 +55,22 @@ > {{ $t("status.show_content") }} <span - v-if="hasImageAttachments" + v-if="attachmentTypes.includes('image')" class="icon-picture" /> <span - v-if="hasVideoAttachments" + v-if="attachmentTypes.includes('video')" class="icon-video" /> <span + v-if="attachmentTypes.includes('audio')" + class="icon-music" + /> + <span + v-if="attachmentTypes.includes('unknown')" + class="icon-doc" + /> + <span v-if="status.card" class="icon-link" /> diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js index e48fef47..ab40bbd7 100644 --- a/src/components/still-image/still-image.js +++ b/src/components/still-image/still-image.js @@ -4,7 +4,8 @@ const StillImage = { 'referrerpolicy', 'mimetype', 'imageLoadError', - 'imageLoadHandler' + 'imageLoadHandler', + 'alt' ], data () { return { diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue index f2ddeb7b..2ebf33ba 100644 --- a/src/components/still-image/still-image.vue +++ b/src/components/still-image/still-image.vue @@ -11,6 +11,8 @@ <img ref="src" :key="src" + :alt="alt" + :title="alt" :src="src" :referrerpolicy="referrerpolicy" @load="onLoad" diff --git a/src/components/video_attachment/video_attachment.vue b/src/components/video_attachment/video_attachment.vue index 97ddf1cd..1ffed4e0 100644 --- a/src/components/video_attachment/video_attachment.vue +++ b/src/components/video_attachment/video_attachment.vue @@ -4,6 +4,8 @@ :src="attachment.url" :loop="loopVideo" :controls="controls" + :alt="attachment.description" + :title="attachment.description" playsinline @loadeddata="onVideoDataLoad" /> diff --git a/src/i18n/en.json b/src/i18n/en.json index 8f13dfe9..a6495848 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -178,6 +178,7 @@ "account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.", "account_not_locked_warning_link": "locked", "attachments_sensitive": "Mark attachments as sensitive", + "media_description": "Media description", "content_type": { "text/plain": "Plain text", "text/html": "HTML", diff --git a/src/modules/media_viewer.js b/src/modules/media_viewer.js index a24b408d..721c25e6 100644 --- a/src/modules/media_viewer.js +++ b/src/modules/media_viewer.js @@ -22,7 +22,7 @@ const mediaViewer = { setMedia ({ commit }, attachments) { const media = attachments.filter(attachment => { const type = fileTypeService.fileType(attachment.mimetype) - return type === 'image' || type === 'video' + return type === 'image' || type === 'video' || type === 'audio' }) commit('setMedia', media) }, diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index c9ec88b7..c4d7fb53 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -645,7 +645,8 @@ const postStatus = ({ poll, mediaIds = [], inReplyToStatusId, - contentType + contentType, + mediaDescriptions }) => { const form = new FormData() const pollOptions = poll.options || [] @@ -672,6 +673,7 @@ const postStatus = ({ form.append('poll[options][]', option) }) } + form.append('descriptions', JSON.stringify(mediaDescriptions)) if (inReplyToStatusId) { form.append('in_reply_to_id', inReplyToStatusId) } diff --git a/src/services/status_poster/status_poster.service.js b/src/services/status_poster/status_poster.service.js index 9e904d3a..090ff673 100644 --- a/src/services/status_poster/status_poster.service.js +++ b/src/services/status_poster/status_poster.service.js @@ -1,7 +1,7 @@ import { map } from 'lodash' import apiService from '../api/api.service.js' -const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => { +const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, media = [], inReplyToStatusId = undefined, contentType = 'text/plain', mediaDescriptions = {} }) => { const mediaIds = map(media, 'id') return apiService.postStatus({ @@ -13,7 +13,8 @@ const postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, m mediaIds, inReplyToStatusId, contentType, - poll }) + poll, + mediaDescriptions }) .then((data) => { if (!data.error) { store.dispatch('addNewStatuses', { |
