feat: add support for audio attachments (#1293)

This is a new thing in Mastodon v2.9. I kept the "camera" icon because I like it better than the paperclip, and I think it covers the 99% use case.
This commit is contained in:
Nolan Lawson 2019-06-23 09:41:31 -07:00 committed by GitHub
parent ea220c32d3
commit d31f2ce010
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 21 deletions

View file

@ -1,5 +1,9 @@
<li class="compose-media compose-media-realm-{realm}"> <li class="compose-media compose-media-realm-{realm}">
<img src={mediaItem.data.preview_url} {alt} /> <img
class="{type === 'audio' ? 'audio-preview' : ''}"
src={previewSrc}
{alt}
/>
<div class="compose-media-delete"> <div class="compose-media-delete">
<button class="compose-media-delete-button" <button class="compose-media-delete-button"
aria-label="Delete {shortName}" aria-label="Delete {shortName}"
@ -10,13 +14,11 @@
<div class="compose-media-alt"> <div class="compose-media-alt">
<textarea id="compose-media-input-{uuid}" <textarea id="compose-media-input-{uuid}"
class="compose-media-alt-input" class="compose-media-alt-input"
placeholder="Describe for the visually impaired" placeholder="Description"
ref:textarea ref:textarea
bind:value=rawText bind:value=rawText
></textarea> ></textarea>
<label for="compose-media-input-{uuid}" class="sr-only"> <label for="compose-media-input-{uuid}" class="sr-only">{label}</label>
Describe {shortName} for the visually impaired
</label>
</div> </div>
</li> </li>
<style> <style>
@ -85,6 +87,10 @@
height: 18px; height: 18px;
} }
.audio-preview {
background: var(--audio-bg);
}
.compose-media-realm-dialog { .compose-media-realm-dialog {
max-height: 20vh; max-height: 20vh;
} }
@ -106,6 +112,7 @@
import { observe } from 'svelte-extras' import { observe } from 'svelte-extras'
import SvgIcon from '../SvgIcon.html' import SvgIcon from '../SvgIcon.html'
import { autosize } from '../../_thirdparty/autosize/autosize' import { autosize } from '../../_thirdparty/autosize/autosize'
import { ONE_TRANSPARENT_PIXEL } from '../../_static/media'
export default { export default {
oncreate () { oncreate () {
@ -126,7 +133,14 @@
// so fall back to the description if it was provided // so fall back to the description if it was provided
filename || mediaItem.description || '' filename || mediaItem.description || ''
), ),
type: ({ mediaItem }) => mediaItem.data.type,
shortName: ({ filename }) => filename || 'media', shortName: ({ filename }) => filename || 'media',
previewSrc: ({ mediaItem, type }) => (
type === 'audio' ? ONE_TRANSPARENT_PIXEL : mediaItem.data.preview_url
),
label: ({ shortName }) => (
`Describe ${shortName} for the visually impaired (image, video) or auditorily impaired (audio, video)`
),
uuid: ({ realm, mediaItem }) => `${realm}-${mediaItem.data.id}` uuid: ({ realm, mediaItem }) => `${realm}-${mediaItem.data.id}`
}, },
store: () => store, store: () => store,

View file

@ -217,7 +217,7 @@
computed: { computed: {
length: ({ mediaItems }) => mediaItems.length, length: ({ mediaItems }) => mediaItems.length,
dots: ({ length }) => times(length, i => ({ i })), dots: ({ length }) => times(length, i => ({ i })),
canPinchZoom: ({ mediaItems }) => !mediaItems.some(media => media.type === 'video') canPinchZoom: ({ mediaItems }) => !mediaItems.some(media => ['video', 'audio'].includes(media.type))
}, },
components: { components: {
ModalDialog, ModalDialog,

View file

@ -6,8 +6,18 @@
{poster} {poster}
controls controls
{intrinsicsize} {intrinsicsize}
ref:video ref:player
/> />
{:elseif type === 'audio'}
<div class="audio-player-container">
<audio
class="audio-player"
aria-label={description}
src={url}
controls
ref:player
/>
</div>
{:elseif type === 'gifv'} {:elseif type === 'gifv'}
<video <video
class="media-fit" class="media-fit"
@ -36,6 +46,27 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.audio-player-container {
min-height: 400px;
min-width: 400px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: flex-end;
background: var(--audio-bg);
}
.audio-player {
padding: 30px 10px;
margin: 10px;
}
@media (max-width: 767px) {
.audio-player-container {
min-height: 200px;
min-width: calc(100vw - 40px);
align-items: center;
}
}
</style> </style>
<script> <script>
export default { export default {
@ -54,8 +85,9 @@
} }
}, },
ondestroy () { ondestroy () {
if (this.refs.video && !this.refs.video.paused) { let player = this.refs.player
this.refs.video.pause() if (player && !player.paused) {
player.pause()
} }
} }
} }

View file

@ -1,20 +1,22 @@
{#if type === 'video'} {#if type === 'video' || type === 'audio'}
<button id={elementId} <button id={elementId}
type="button" type="button"
class="play-video-button {$largeInlineMedia ? '' : 'fixed-size'}" class="play-video-button {$largeInlineMedia ? '' : 'fixed-size'} {type === 'audio' ? 'play-audio-button' : ''}"
aria-label="Play video: {description}" aria-label="Play video: {description}"
style="width: {inlineWidth}px; height: {inlineHeight}px;"> style="width: {inlineWidth}px; height: {inlineHeight}px;">
<PlayVideoIcon /> <PlayVideoIcon />
<LazyImage {#if type === 'video'}
alt={description} <LazyImage
title={description} alt={description}
src={previewUrl} title={description}
fallback={oneTransparentPixel} src={previewUrl}
width={inlineWidth} fallback={oneTransparentPixel}
height={inlineHeight} width={inlineWidth}
background="var(--loading-bg)" height={inlineHeight}
{focus} background="var(--loading-bg)"
/> {focus}
/>
{/if}
</button> </button>
{:else} {:else}
<button id={elementId} <button id={elementId}
@ -72,6 +74,9 @@
background: none; background: none;
position: relative; position: relative;
} }
.play-audio-button {
background: var(--audio-bg);
}
/* the actual focus outline is not very visible, so use an ::after pseudo-element */ /* the actual focus outline is not very visible, so use an ::after pseudo-element */
.play-video-button:focus, .show-image-button:focus { .play-video-button:focus, .show-image-button:focus {

View file

@ -118,4 +118,6 @@
--floating-button-bg-active: #{darken(rgba($main-bg-color, 0.9), 10%)}; --floating-button-bg-active: #{darken(rgba($main-bg-color, 0.9), 10%)};
--length-indicator-color: #{$main-theme-color}; --length-indicator-color: #{$main-theme-color};
--audio-bg: #{rgba(30, 30, 30, 0.8)};
} }