diff --git a/app/soapbox/components/status.js b/app/soapbox/components/status.js
index bc0dc1cbc..9c308c2f2 100644
--- a/app/soapbox/components/status.js
+++ b/app/soapbox/components/status.js
@@ -12,7 +12,7 @@ import AttachmentList from './attachment_list';
import Card from '../features/status/components/card';
import { injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { MediaGallery, Video } from '../features/ui/util/async-components';
+import { MediaGallery, Video, Audio } from '../features/ui/util/async-components';
import { HotKeys } from 'react-hotkeys';
import classNames from 'classnames';
import Icon from 'soapbox/components/icon';
@@ -73,6 +73,7 @@ class Status extends ImmutablePureComponent {
onPin: PropTypes.func,
onOpenMedia: PropTypes.func,
onOpenVideo: PropTypes.func,
+ onOpenAudio: PropTypes.func,
onBlock: PropTypes.func,
onEmbed: PropTypes.func,
onHeightChange: PropTypes.func,
@@ -194,10 +195,18 @@ class Status extends ImmutablePureComponent {
return
;
}
+ renderLoadingAudioPlayer() {
+ return ;
+ }
+
handleOpenVideo = (media, startTime) => {
this.props.onOpenVideo(media, startTime);
}
+ handleOpenAudio = (media, startTime) => {
+ this.props.OnOpenAudio(media, startTime);
+ }
+
handleHotkeyReply = e => {
e.preventDefault();
this.props.onReply(this._properStatus(), this.context.router.history);
@@ -356,6 +365,23 @@ class Status extends ImmutablePureComponent {
)}
);
+ } else if (status.getIn(['media_attachments', 0, 'type']) === 'audio') {
+ const audio = status.getIn(['media_attachments', 0]);
+
+ media = (
+
+ {Component => (
+
+ )}
+
+ );
} else {
media = (
diff --git a/app/soapbox/containers/status_container.js b/app/soapbox/containers/status_container.js
index 0e25f9e65..d84141165 100644
--- a/app/soapbox/containers/status_container.js
+++ b/app/soapbox/containers/status_container.js
@@ -146,6 +146,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(openModal('VIDEO', { media, time }));
},
+ onOpenAudio(media, time) {
+ dispatch(openModal('AUDIO', { media, time }));
+ },
+
onBlock(status) {
const account = status.get('account');
dispatch(openModal('CONFIRM', {
diff --git a/app/soapbox/features/account_gallery/index.js b/app/soapbox/features/account_gallery/index.js
index de2213b07..4736f48aa 100644
--- a/app/soapbox/features/account_gallery/index.js
+++ b/app/soapbox/features/account_gallery/index.js
@@ -133,6 +133,8 @@ class AccountGallery extends ImmutablePureComponent {
handleOpenMedia = attachment => {
if (attachment.get('type') === 'video') {
this.props.dispatch(openModal('VIDEO', { media: attachment, status: attachment.get('status') }));
+ } else if (attachment.get('type') === 'audio') {
+ this.props.dispatch(openModal('AUDIO', { media: attachment, status: attachment.get('status') }));
} else {
const media = attachment.getIn(['status', 'media_attachments']);
const index = media.findIndex(x => x.get('id') === attachment.get('id'));
diff --git a/app/soapbox/features/audio/index.js b/app/soapbox/features/audio/index.js
index 3d35a2e96..256fa4ab9 100644
--- a/app/soapbox/features/audio/index.js
+++ b/app/soapbox/features/audio/index.js
@@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import { fromJS, is } from 'immutable';
+import { is } from 'immutable';
import { throttle } from 'lodash';
import classNames from 'classnames';
import Icon from 'soapbox/components/icon';
@@ -11,7 +11,11 @@ import { getSettings } from 'soapbox/actions/settings';
const messages = defineMessages({
play: { id: 'audio.play', defaultMessage: 'Play' },
pause: { id: 'audio.pause', defaultMessage: 'Pause' },
- hide: { id: 'video.hide', defaultMessage: 'Hide audio' },
+ mute: { id: 'audio.mute', defaultMessage: 'Mute' },
+ unmute: { id: 'audio.unmute', defaultMessage: 'Unmute' },
+ hide: { id: 'audio.hide', defaultMessage: 'Hide audio' },
+ expand: { id: 'audio.expand', defaultMessage: 'Expand audio' },
+ close: { id: 'audio.close', defaultMessage: 'Close audio' },
});
const formatTime = secondsNum => {
@@ -20,7 +24,7 @@ const formatTime = secondsNum => {
let seconds = secondsNum - (hours * 3600) - (minutes * 60);
if (hours < 10) hours = '0' + hours;
- if (minutes < 10) minutes = '0' + minutes;
+ if (minutes < 10 && hours >= 1) minutes = '0' + minutes;
if (seconds < 10) seconds = '0' + seconds;
return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
@@ -92,8 +96,6 @@ class Audio extends React.PureComponent {
alt: PropTypes.string,
sensitive: PropTypes.bool,
startTime: PropTypes.number,
- onOpenAudio: PropTypes.func,
- onCloseAudio: PropTypes.func,
detailed: PropTypes.bool,
inline: PropTypes.bool,
cacheWidth: PropTypes.func,
@@ -110,7 +112,6 @@ class Audio extends React.PureComponent {
volume: 0.5,
paused: true,
dragging: false,
- hovered: false,
muted: false,
revealed: this.props.visible !== undefined ? this.props.visible : (this.props.displayMedia !== 'hide_all' && !this.props.sensitive || this.props.displayMedia === 'show_all'),
};
@@ -118,10 +119,10 @@ class Audio extends React.PureComponent {
// hard coded in components.scss
// any way to get ::before values programatically?
volWidth = 50;
- volOffset = 70;
+ volOffset = 85;
volHandleOffset = v => {
const offset = v * this.volWidth + this.volOffset;
- return (offset > 110) ? 110 : offset;
+ return (offset > 125) ? 125 : offset;
}
setPlayerRef = c => {
@@ -233,7 +234,7 @@ class Audio extends React.PureComponent {
handleMouseMove = throttle(e => {
const { x } = getPointerPosition(this.seek, e);
- const currentTime = Math.floor(this.video.duration * x);
+ const currentTime = Math.floor(this.audio.duration * x);
if (!isNaN(currentTime)) {
this.audio.currentTime = currentTime;
@@ -261,14 +262,6 @@ class Audio extends React.PureComponent {
}
}
- handleMouseEnter = () => {
- this.setState({ hovered: true });
- }
-
- handleMouseLeave = () => {
- this.setState({ hovered: false });
- }
-
toggleMute = () => {
this.audio.muted = !this.audio.muted;
this.setState({ muted: this.audio.muted });
@@ -299,24 +292,6 @@ class Audio extends React.PureComponent {
this.setState({ volume: this.audio.volume, muted: this.audio.muted });
}
- handleOpenAudio = () => {
- const { src, alt } = this.props;
-
- const media = fromJS({
- type: 'audio',
- url: src,
- description: alt,
- });
-
- this.audio.pause();
- this.props.onOpenAudio(media, this.audio.currentTime);
- }
-
- handleCloseAudio = () => {
- this.audio.pause();
- this.props.onCloseAudio();
- }
-
getPreload = () => {
const { startTime, detailed } = this.props;
const { dragging } = this.state;
@@ -331,8 +306,8 @@ class Audio extends React.PureComponent {
}
render() {
- const { src, inline, onOpenAudio, onCloseAudio, intl, alt, detailed, sensitive, link } = this.props;
- const { currentTime, duration, volume, buffer, dragging, paused, hovered, muted, revealed } = this.state;
+ const { src, inline, intl, alt, detailed, sensitive, link } = this.props;
+ const { currentTime, duration, volume, buffer, dragging, paused, muted, revealed } = this.state;
const progress = (currentTime / duration) * 100;
const volumeWidth = (muted) ? 0 : volume * this.volWidth;
@@ -361,6 +336,7 @@ class Audio extends React.PureComponent {
{revealed &&