about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/components/components/video_player.jsx27
-rw-r--r--app/assets/javascripts/components/locales/en.jsx1
-rw-r--r--app/assets/stylesheets/components.scss2
3 files changed, 24 insertions, 6 deletions
diff --git a/app/assets/javascripts/components/components/video_player.jsx b/app/assets/javascripts/components/components/video_player.jsx
index e9e860e39..0da544746 100644
--- a/app/assets/javascripts/components/components/video_player.jsx
+++ b/app/assets/javascripts/components/components/video_player.jsx
@@ -7,7 +7,8 @@ import { isIOS } from '../is_mobile';
 const messages = defineMessages({
   toggle_sound: { id: 'video_player.toggle_sound', defaultMessage: 'Toggle sound' },
   toggle_visible: { id: 'video_player.toggle_visible', defaultMessage: 'Toggle visibility' },
-  expand_video: { id: 'video_player.expand', defaultMessage: 'Expand video' }
+  expand_video: { id: 'video_player.expand', defaultMessage: 'Expand video' },
+  expand_video: { id: 'video_player.video_error', defaultMessage: 'Video could not be played' }
 });
 
 const videoStyle = {
@@ -30,7 +31,7 @@ const muteStyle = {
   zIndex: '5'
 };
 
-const spoilerStyle = {
+const coverStyle = {
   marginTop: '8px',
   textAlign: 'center',
   height: '100%',
@@ -94,7 +95,8 @@ const VideoPlayer = React.createClass({
       visible: !this.props.sensitive,
       preview: true,
       muted: true,
-      hasAudio: true
+      hasAudio: true,
+      videoError: false
     };
   },
 
@@ -142,12 +144,17 @@ const VideoPlayer = React.createClass({
     }
   },
 
+  handleVideoError () {
+    this.setState({ videoError: true });
+  },
+
   componentDidMount () {
     if (!this.video) {
       return;
     }
 
     this.video.addEventListener('loadeddata', this.handleLoadedData);
+    this.video.addEventListener('error', this.handleVideoError);
   },
 
   componentDidUpdate () {
@@ -156,6 +163,7 @@ const VideoPlayer = React.createClass({
     }
 
     this.video.addEventListener('loadeddata', this.handleLoadedData);
+    this.video.addEventListener('error', this.handleVideoError);
   },
 
   componentWillUnmount () {
@@ -164,6 +172,7 @@ const VideoPlayer = React.createClass({
     }
 
     this.video.removeEventListener('loadeddata', this.handleLoadedData);
+    this.video.removeEventListener('error', this.handleVideoError);
   },
 
   render () {
@@ -194,7 +203,7 @@ const VideoPlayer = React.createClass({
     if (!this.state.visible) {
       if (sensitive) {
         return (
-          <div role='button' tabIndex='0' style={{...spoilerStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
+          <div role='button' tabIndex='0' style={{...coverStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
             {spoilerButton}
             <span style={spoilerSpanStyle}><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span>
             <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
@@ -202,7 +211,7 @@ const VideoPlayer = React.createClass({
         );
       } else {
         return (
-          <div role='button' tabIndex='0' style={{...spoilerStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
+          <div role='button' tabIndex='0' style={{...coverStyle, width: `${width}px`, height: `${height}px` }} className='media-spoiler' onClick={this.handleVisibility}>
             {spoilerButton}
             <span style={spoilerSpanStyle}><FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' /></span>
             <span style={spoilerSubSpanStyle}><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
@@ -220,6 +229,14 @@ const VideoPlayer = React.createClass({
       );
     }
 
+    if (this.state.videoError) {
+      return (
+        <div style={{...coverStyle, width: `${width}px`, height: `${height}px` }} className='video-error-cover' >
+          <span style={spoilerSpanStyle}><FormattedMessage id='video_player.video_error' defaultMessage='Video could not be played' /></span>
+        </div>
+      );
+    }
+
     return (
       <div style={{ cursor: 'default', marginTop: '8px', overflow: 'hidden', width: `${width}px`, height: `${height}px`, boxSizing: 'border-box', background: '#000', position: 'relative' }}>
         {spoilerButton}
diff --git a/app/assets/javascripts/components/locales/en.jsx b/app/assets/javascripts/components/locales/en.jsx
index fe7be0f24..5c1238524 100644
--- a/app/assets/javascripts/components/locales/en.jsx
+++ b/app/assets/javascripts/components/locales/en.jsx
@@ -129,6 +129,7 @@ const en = {
   "video_player.toggle_sound": "Toggle sound",
   "video_player.toggle_visible": "Toggle visibility",
   "video_player.expand": "Expand video",
+  "video_player.video_error": "Video could not be played",
 };
 
 export default en;
diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss
index 90fada672..d1c4d2bb2 100644
--- a/app/assets/stylesheets/components.scss
+++ b/app/assets/stylesheets/components.scss
@@ -1383,7 +1383,7 @@ button.icon-button.active i.fa-retweet {
   }
 }
 
-.media-spoiler {
+.media-spoiler, .video-error-cover {
   background: $color8;
   color: $color5;
 }