aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--src/components/attachment/attachment.js29
-rw-r--r--src/components/attachment/attachment.vue30
-rw-r--r--src/components/gallery/gallery.vue4
-rw-r--r--src/components/media_modal/media_modal.vue10
-rw-r--r--src/components/post_status_form/post_status_form.js7
-rw-r--r--src/components/post_status_form/post_status_form.vue68
-rw-r--r--src/components/status_content/status_content.js12
-rw-r--r--src/components/status_content/status_content.vue12
-rw-r--r--src/components/still-image/still-image.js3
-rw-r--r--src/components/still-image/still-image.vue2
-rw-r--r--src/components/video_attachment/video_attachment.vue2
-rw-r--r--src/i18n/en.json1
-rw-r--r--src/modules/media_viewer.js2
-rw-r--r--src/services/api/api.service.js4
-rw-r--r--src/services/status_poster/status_poster.service.js5
-rw-r--r--static/fontello.json12
17 files changed, 128 insertions, 81 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5d1bd118..ae60d26f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Autocomplete domains from list of known instances
- 'Bot' settings option and badge
- Added profile meta data fields that can be set in profile settings
+- Descriptions can be set on uploaded files before posting
- When a post is a reply to an unavailable post, the 'Reply to'-text has a strike-through style
### Changed
@@ -27,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Close the media modal on navigation events
- Add colons to the emoji alt text, to make them copyable
- Add better visual indication for drag-and-drop for files
+- When disabling attachments, the placeholder links now show an icon and the description instead of just IMAGE or VIDEO etc
### Fixed
- Custom Emoji will display in poll options now.
@@ -38,6 +40,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Subject field now appears disabled when posting
- Fix status ellipsis menu being cut off in notifications column
- Fixed autocomplete sometimes not returning the right user when there's already some results
+- Videos and audio and misc files show description as alt/title properly now
+- Clicking on non-image/video files no longer opens an empty modal
+- Audio files can now be played back in the frontend with hidden attachments
+- Videos are not cropped awkwardly in the uploads section anymore
- Reply filtering options in Settings -> Filtering now work again using filtering on server
- Don't show just blank-screen when cookies are disabled
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', {
diff --git a/static/fontello.json b/static/fontello.json
index 6083c0bf..5ef8544e 100644
--- a/static/fontello.json
+++ b/static/fontello.json
@@ -387,6 +387,18 @@
"css": "bookmark-empty",
"code": 61591,
"src": "fontawesome"
+ },
+ {
+ "uid": "9ea0a737ccc45d6c510dcbae56058849",
+ "css": "music",
+ "code": 59432,
+ "src": "fontawesome"
+ },
+ {
+ "uid": "1b5a5d7b7e3c71437f5a26befdd045ed",
+ "css": "doc",
+ "code": 59433,
+ "src": "fontawesome"
}
]
} \ No newline at end of file