diff --git a/app/javascript/mastodon/features/status/components/card.js b/app/javascript/mastodon/features/status/components/card.js index 93eb1b04499a18..39123f9eea61f3 100644 --- a/app/javascript/mastodon/features/status/components/card.js +++ b/app/javascript/mastodon/features/status/components/card.js @@ -2,13 +2,14 @@ import React from 'react'; import PropTypes from 'prop-types'; import Immutable from 'immutable'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import punycode from 'punycode'; import classnames from 'classnames'; import Icon from 'mastodon/components/icon'; import { useBlurhash } from 'mastodon/initial_state'; import Blurhash from 'mastodon/components/blurhash'; import { debounce } from 'lodash'; +import IconButton from 'mastodon/components/icon_button'; const IDNA_PREFIX = 'xn--'; @@ -37,28 +38,12 @@ const trim = (text, len) => { const domParser = new DOMParser(); -const addAutoPlay = html => { - const document = domParser.parseFromString(html, 'text/html').documentElement; - const iframe = document.querySelector('iframe'); +const messages = defineMessages({ + fullscreen: { id: 'status.fullscreen', defaultMessage: 'Expand to full screen view' }, +}); - if (iframe) { - if (iframe.src.indexOf('?') !== -1) { - iframe.src += '&'; - } else { - iframe.src += '?'; - } - - iframe.src += 'autoplay=1&auto_play=1'; - - // DOM parser creates html/body elements around original HTML fragment, - // so we need to get innerHTML out of the body and not the entire document - return document.querySelector('body').innerHTML; - } - - return html; -}; - -export default class Card extends React.PureComponent { +export default @injectIntl +class Card extends React.PureComponent { static contextTypes = { router: PropTypes.object, @@ -72,6 +57,7 @@ export default class Card extends React.PureComponent { defaultWidth: PropTypes.number, cacheWidth: PropTypes.func, sensitive: PropTypes.bool, + intl: PropTypes.object.isRequired, quote: PropTypes.bool, }; @@ -85,6 +71,7 @@ export default class Card extends React.PureComponent { previewLoaded: false, embedded: false, revealed: !this.props.sensitive, + isIframe: false, }; componentWillReceiveProps (nextProps) { @@ -171,20 +158,74 @@ export default class Card extends React.PureComponent { this.setState({ revealed: true }); } + addAutoPlay = html => { + const document = domParser.parseFromString(html, 'text/html').documentElement; + const iframe = document.querySelector('iframe'); + + if (iframe) { + this.setState({ isIframe: true }); + + if (iframe.src.indexOf('?') !== -1) { + iframe.src += '&'; + } else { + iframe.src += '?'; + } + + iframe.src += 'autoplay=1&auto_play=1'; + + // DOM parser creates html/body elements around original HTML fragment, + // so we need to get innerHTML out of the body and not the entire document + return document.querySelector('body').innerHTML; + } + + return html; + } + + handleIframeFullscreen = () => { + const iframe = this.node; + if (iframe.requestFullscreen) { + iframe.requestFullscreen(); + } else if (iframe.webkitRequestFullscreen) { + iframe.webkitRequestFullscreen(); + } else if (iframe.mozRequestFullScreen) { + iframe.mozRequestFullScreen(); + } else if (iframe.msRequestFullscreen) { + iframe.msRequestFullscreen(); + } + } + renderVideo () { - const { card } = this.props; - const content = { __html: addAutoPlay(card.get('html')) }; + const { card, intl } = this.props; + const content = { __html: this.addAutoPlay(card.get('html')) }; const { width } = this.state; const ratio = card.get('width') / card.get('height'); const height = width / ratio; + const fullscreenEnabled = (document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) ? true : false; + const isIframe = this.state.isIframe; + return ( -
+
+
+ {fullscreenEnabled && isIframe ? ( + + ) : null} +
); } diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index d7adc0bef3f519..ce797fb367b2de 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -3212,6 +3212,10 @@ { "defaultMessage": "Sensitive content", "id": "status.sensitive_warning" + }, + { + "defaultMessage": "Expand to full screen view", + "id": "status.fullscreen" } ], "path": "app/javascript/mastodon/features/status/components/card.json" diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index bc2878f901c342..b01cf9c2bb3089 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -480,6 +480,7 @@ "status.embed": "Embed", "status.favourite": "Favourite", "status.filtered": "Filtered", + "status.fullscreen": "Expand to full screen view", "status.hide_translation": "Hide translation", "status.history.created": "{name} created {date}", "status.history.edited": "{name} edited {date}", diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 0ee90884318682..f35ecb707d918f 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -28,6 +28,16 @@ html { } } +.status-card-video__container { + .fullscreen-iframe-button { + color: rgba($white, 0.8); + + &:hover { + color: $white; + } + } +} + // Change default background colors of columns .column > .scrollable, .getting-started, diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 3d34784313b5e1..de8cb8f80445bb 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -3420,6 +3420,30 @@ a.status-card { } } +.status-card-video__container { + .fullscreen-iframe-button { + position: absolute; + top: 50%; + right: 0; + padding: 6px; + border-radius: 8px 0 0 8px; + color: $secondary-text-color; + background: rgba($base-shadow-color, 0.6); + transform: translate(100%, -50%); + transition: transform 0.5s; + + &:hover { + color: $primary-text-color; + } + } + + &:hover { + .fullscreen-iframe-button { + transform: translate(0, -50%); + } + } +} + .status-card__title { display: block; font-weight: 500;