diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index f929d17a685..c937052661d 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -259,8 +259,8 @@ export default class Status extends ImmutablePureComponent { } }; - handleOpenVideo = startTime => { - this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), startTime); + handleOpenVideo = (media, startTime) => { + this.props.onOpenVideo(media, startTime); } handleHotkeyReply = e => { diff --git a/app/javascript/flavours/glitch/containers/card_container.js b/app/javascript/flavours/glitch/containers/card_container.js deleted file mode 100644 index dec7df52236..00000000000 --- a/app/javascript/flavours/glitch/containers/card_container.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Card from 'flavours/glitch/features/status/components/card'; -import { fromJS } from 'immutable'; - -export default class CardContainer extends React.PureComponent { - - static propTypes = { - locale: PropTypes.string, - card: PropTypes.array.isRequired, - }; - - render () { - const { card, ...props } = this.props; - return ; - } - -} diff --git a/app/javascript/flavours/glitch/containers/media_container.js b/app/javascript/flavours/glitch/containers/media_container.js new file mode 100644 index 00000000000..0e1904132e4 --- /dev/null +++ b/app/javascript/flavours/glitch/containers/media_container.js @@ -0,0 +1,90 @@ +import React, { PureComponent, Fragment } from 'react'; +import ReactDOM from 'react-dom'; +import PropTypes from 'prop-types'; +import { IntlProvider, addLocaleData } from 'react-intl'; +import { getLocale } from 'mastodon/locales'; +import MediaGallery from 'flavours/glitch/components/media_gallery'; +import Video from 'flavours/glitch/features/video'; +import Card from 'flavours/glitch/features/status/components/card'; +import ModalRoot from 'flavours/glitch/components/modal_root'; +import MediaModal from 'flavours/glitch/features/ui/components/media_modal'; +import { List as ImmutableList, fromJS } from 'immutable'; + +const { localeData, messages } = getLocale(); +addLocaleData(localeData); + +const MEDIA_COMPONENTS = { MediaGallery, Video, Card }; + +export default class MediaContainer extends PureComponent { + + static propTypes = { + locale: PropTypes.string.isRequired, + components: PropTypes.object.isRequired, + }; + + state = { + media: null, + index: null, + time: null, + }; + + handleOpenMedia = (media, index) => { + document.body.classList.add('media-standalone__body'); + this.setState({ media, index }); + } + + handleOpenVideo = (video, time) => { + const media = ImmutableList([video]); + + document.body.classList.add('media-standalone__body'); + this.setState({ media, time }); + } + + handleCloseMedia = () => { + document.body.classList.remove('media-standalone__body'); + this.setState({ media: null, index: null, time: null }); + } + + render () { + const { locale, components } = this.props; + + return ( + + + {[].map.call(components, (component, i) => { + const componentName = component.getAttribute('data-component'); + const Component = MEDIA_COMPONENTS[componentName]; + const { media, card, ...props } = JSON.parse(component.getAttribute('data-props')); + + Object.assign(props, { + ...(media ? { media: fromJS(media) } : {}), + ...(card ? { card: fromJS(card) } : {}), + + ...(componentName === 'Video' ? { + onOpenVideo: this.handleOpenVideo, + } : { + onOpenMedia: this.handleOpenMedia, + }), + }); + + return ReactDOM.createPortal( + , + component, + ); + })} + + {this.state.media && ( + + )} + + + + ); + } + +} diff --git a/app/javascript/flavours/glitch/containers/media_galleries_container.js b/app/javascript/flavours/glitch/containers/media_galleries_container.js deleted file mode 100644 index a694578821e..00000000000 --- a/app/javascript/flavours/glitch/containers/media_galleries_container.js +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import PropTypes from 'prop-types'; -import { IntlProvider, addLocaleData } from 'react-intl'; -import { getLocale } from 'mastodon/locales'; -import MediaGallery from 'flavours/glitch/components/media_gallery'; -import ModalRoot from 'flavours/glitch/components/modal_root'; -import MediaModal from 'flavours/glitch/features/ui/components/media_modal'; -import { fromJS } from 'immutable'; - -const { localeData, messages } = getLocale(); -addLocaleData(localeData); - -export default class MediaGalleriesContainer extends React.PureComponent { - - static propTypes = { - locale: PropTypes.string.isRequired, - galleries: PropTypes.object.isRequired, - }; - - state = { - media: null, - index: null, - }; - - handleOpenMedia = (media, index) => { - document.body.classList.add('media-gallery-standalone__body'); - this.setState({ media, index }); - } - - handleCloseMedia = () => { - document.body.classList.remove('media-gallery-standalone__body'); - this.setState({ media: null, index: null }); - } - - render () { - const { locale, galleries } = this.props; - - return ( - - - {[].map.call(galleries, gallery => { - const { media, ...props } = JSON.parse(gallery.getAttribute('data-props')); - - return ReactDOM.createPortal( - , - gallery - ); - })} - - {this.state.media === null || this.state.index === null ? null : ( - - )} - - - - ); - } - -} diff --git a/app/javascript/flavours/glitch/containers/video_container.js b/app/javascript/flavours/glitch/containers/video_container.js deleted file mode 100644 index b206e9a1001..00000000000 --- a/app/javascript/flavours/glitch/containers/video_container.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { IntlProvider, addLocaleData } from 'react-intl'; -import { getLocale } from 'mastodon/locales'; -import Video from 'flavours/glitch/features/video'; - -const { localeData, messages } = getLocale(); -addLocaleData(localeData); - -export default class VideoContainer extends React.PureComponent { - - static propTypes = { - locale: PropTypes.string.isRequired, - }; - - render () { - const { locale, ...props } = this.props; - - return ( - - - - ); - } - -} diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.js b/app/javascript/flavours/glitch/features/status/components/detailed_status.js index 16f7ae830e1..5cfc9dfaed1 100644 --- a/app/javascript/flavours/glitch/features/status/components/detailed_status.js +++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.js @@ -37,8 +37,8 @@ export default class DetailedStatus extends ImmutablePureComponent { e.stopPropagation(); } - handleOpenVideo = startTime => { - this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), startTime); + handleOpenVideo = (media, startTime) => { + this.props.onOpenVideo(media, startTime); } render () { diff --git a/app/javascript/flavours/glitch/features/ui/components/media_modal.js b/app/javascript/flavours/glitch/features/ui/components/media_modal.js index 6ab6770ed48..bffe3b1f738 100644 --- a/app/javascript/flavours/glitch/features/ui/components/media_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/media_modal.js @@ -2,6 +2,7 @@ import React from 'react'; import ReactSwipeableViews from 'react-swipeable-views'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; +import Video from 'flavours/glitch/features/video'; import ExtendedVideoPlayer from 'flavours/glitch/components/extended_video_player'; import classNames from 'classnames'; import { defineMessages, injectIntl } from 'react-intl'; @@ -112,6 +113,22 @@ export default class MediaModal extends ImmutablePureComponent { onClick={this.toggleNavigation} /> ); + } else if (image.get('type') === 'video') { + const { time } = this.props; + + return ( + + ); } else if (image.get('type') === 'gifv') { return ( e.stopPropagation(); + handlePlay = () => { this.setState({ paused: false }); } @@ -246,8 +249,17 @@ export default class Video extends React.PureComponent { } handleOpenVideo = () => { + const { src, preview, width, height } = this.props; + const media = fromJS({ + type: 'video', + url: src, + preview_url: preview, + width, + height, + }); + this.video.pause(); - this.props.onOpenVideo(this.video.currentTime); + this.props.onOpenVideo(media, this.video.currentTime); } handleCloseVideo = () => { @@ -279,7 +291,15 @@ export default class Video extends React.PureComponent { } return ( - + { - const props = JSON.parse(content.getAttribute('data-props')); - ReactDOM.render(, content); - }); - - [].forEach.call(document.querySelectorAll('[data-component="Card"]'), (content) => { - const props = JSON.parse(content.getAttribute('data-props')); - ReactDOM.render(, content); - }); - - const mediaGalleries = document.querySelectorAll('[data-component="MediaGallery"]'); - - if (mediaGalleries.length > 0) { - const MediaGalleriesContainer = require('flavours/glitch/containers/media_galleries_container').default; - const content = document.createElement('div'); - - ReactDOM.render(, content); - document.body.appendChild(content); + const reactComponents = document.querySelectorAll('[data-component]'); + if (reactComponents.length > 0) { + import(/* webpackChunkName: "containers/media_container" */ 'flavours/glitch/containers/media_container') + .then(({ default: MediaContainer }) => { + const content = document.createElement('div'); + ReactDOM.render(, content); + document.body.appendChild(content); + }) + .catch(error => console.error(error)); } }); } diff --git a/app/javascript/flavours/glitch/styles/components/media.scss b/app/javascript/flavours/glitch/styles/components/media.scss index 90674612d35..5a49c07fa8e 100644 --- a/app/javascript/flavours/glitch/styles/components/media.scss +++ b/app/javascript/flavours/glitch/styles/components/media.scss @@ -279,6 +279,10 @@ background: $base-shadow-color; max-width: 100%; + &:focus { + outline: 0; + } + .detailed-status & { width: 100%; height: 100%; diff --git a/app/javascript/flavours/glitch/styles/containers.scss b/app/javascript/flavours/glitch/styles/containers.scss index c40b38a5a53..ac648c8680e 100644 --- a/app/javascript/flavours/glitch/styles/containers.scss +++ b/app/javascript/flavours/glitch/styles/containers.scss @@ -60,8 +60,7 @@ } } -.card-standalone__body, -.media-gallery-standalone__body { +.media-standalone__body { overflow: hidden; }