After merge resolutions

This commit is contained in:
mgabdev 2020-01-28 11:29:37 -05:00
parent 0a3c6cea89
commit 8c9cac2beb
4 changed files with 159 additions and 87 deletions

View File

@ -1,8 +1,11 @@
import React from 'react';
import { connect } from 'react-redux';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import StatusListContainer from '../../containers/status_list_container'; import PropTypes from 'prop-types';
import StatusListContainer from '../ui/containers/status_list_container';
import Column from '../../components/column'; import Column from '../../components/column';
import ColumnSettings from './components/column_settings'; import ColumnSettingsContainer from './containers/column_settings_container';
import { HomeColumnHeader } from '../../components/column_header'; import HomeColumnHeader from '../../components/home_column_header';
import { import {
expandCommunityTimeline, expandCommunityTimeline,
expandPublicTimeline, expandPublicTimeline,
@ -32,17 +35,12 @@ const mapStateToProps = state => {
export default @connect(mapStateToProps) export default @connect(mapStateToProps)
@injectIntl @injectIntl
class CommunityTimeline extends PureComponent { class CommunityTimeline extends React.PureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object, router: PropTypes.object,
}; };
static defaultProps = {
onlyMedia: false,
allFediverse: false,
};
static propTypes = { static propTypes = {
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
@ -104,9 +102,9 @@ class CommunityTimeline extends PureComponent {
const { intl, hasUnread, onlyMedia, timelineId, allFediverse } = this.props; const { intl, hasUnread, onlyMedia, timelineId, allFediverse } = this.props;
return ( return (
<Column heading={intl.formatMessage(messages.title)}> <Column label={intl.formatMessage(messages.title)}>
<HomeColumnHeader activeItem='all' active={hasUnread} > <HomeColumnHeader activeItem='all' active={hasUnread} >
<ColumnSettings /> <ColumnSettingsContainer />
</HomeColumnHeader> </HomeColumnHeader>
<StatusListContainer <StatusListContainer
scrollKey={`${timelineId}_timeline`} scrollKey={`${timelineId}_timeline`}

View File

@ -1,36 +1,44 @@
'use strict'; 'use strict';
import classNames from 'classnames'; import classNames from 'classnames';
import React from 'react';
import { HotKeys } from 'react-hotkeys'; import { HotKeys } from 'react-hotkeys';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { Switch, Redirect, withRouter } from 'react-router-dom'; import { Switch, Redirect, withRouter } from 'react-router-dom';
import NotificationsContainer from '../../containers/notifications_container'; import PropTypes from 'prop-types';
import LoadingBarContainer from '../../containers/loading_bar_container'; import NotificationsContainer from './containers/notifications_container';
import ModalContainer from '../../containers/modal_container'; import LoadingBarContainer from './containers/loading_bar_container';
import { isMobile } from '../../utils/is_mobile'; import ModalContainer from './containers/modal_container';
import { isMobile } from '../../is_mobile';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { uploadCompose, resetCompose } from '../../actions/compose'; import { uploadCompose, resetCompose } from '../../actions/compose';
import { expandHomeTimeline } from '../../actions/timelines'; import { expandHomeTimeline } from '../../actions/timelines';
import { expandNotifications } from '../../actions/notifications'; import {
initializeNotifications,
expandNotifications,
} from '../../actions/notifications';
import { fetchFilters } from '../../actions/filters'; import { fetchFilters } from '../../actions/filters';
import { clearHeight } from '../../actions/height_cache'; import { clearHeight } from '../../actions/height_cache';
import { openModal } from '../../actions/modal'; import { openModal } from '../../actions/modal';
import WrappedRoute from './util/wrapped_route'; import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
import UploadArea from '../../components/upload_area'; import UploadArea from './components/upload_area';
import TabsBar from '../../components/tabs_bar'; import TabsBar from './components/tabs_bar';
import { WhoToFollowPanel } from '../../components/panel'; import FooterBar from './components/footer_bar';
import LinkFooter from '../../components/link_footer'; // import TrendsPanel from './components/trends_panel';
import WhoToFollowPanel from './components/who_to_follow_panel';
import LinkFooter from './components/link_footer';
import ProfilePage from 'gabsocial/pages/profile_page'; import ProfilePage from 'gabsocial/pages/profile_page';
import GroupsPage from 'gabsocial/pages/groups_page';
import GroupPage from 'gabsocial/pages/group_page'; import GroupPage from 'gabsocial/pages/group_page';
import SearchPage from 'gabsocial/pages/search_page'; import SearchPage from 'gabsocial/pages/search_page';
import HomePage from 'gabsocial/pages/home_page'; import HomePage from 'gabsocial/pages/home_page';
import GroupSidebarPanel from '../groups/sidebar_panel'; import GroupSidebarPanel from '../groups/sidebar_panel';
import FloatingActionButton from '../../components/floating_action_button'; import SidebarMenu from '../../components/sidebar_menu';
import PromoPanel from '../../components/promo_panel/promo_panel';
import UserPanel from '../../components/user_panel/user_panel';
import { import {
Status, Status,
GettingStarted,
CommunityTimeline, CommunityTimeline,
AccountTimeline, AccountTimeline,
AccountGallery, AccountGallery,
@ -38,6 +46,8 @@ import {
Followers, Followers,
Following, Following,
Reblogs, Reblogs,
Favourites,
DirectTimeline,
HashtagTimeline, HashtagTimeline,
Notifications, Notifications,
FollowRequests, FollowRequests,
@ -48,6 +58,7 @@ import {
Mutes, Mutes,
PinnedStatuses, PinnedStatuses,
Search, Search,
Explore,
Groups, Groups,
GroupTimeline, GroupTimeline,
ListTimeline, ListTimeline,
@ -58,15 +69,13 @@ import {
GroupEdit, GroupEdit,
} from './util/async-components'; } from './util/async-components';
import { me, meUsername } from '../../initial_state'; import { me, meUsername } from '../../initial_state';
import { previewState as previewMediaState } from './components/media_modal';
import { previewState as previewVideoState } from './components/video_modal';
// Dummy import, to make sure that <Status /> ends up in the application bundle. // Dummy import, to make sure that <Status /> ends up in the application bundle.
// Without this it ends up in ~8 very commonly used bundles. // Without this it ends up in ~8 very commonly used bundles.
import '../../components/status'; import '../../components/status';
import { fetchGroups } from '../../actions/groups'; import { fetchGroups } from '../../actions/groups';
import { Fragment } from 'react';
import '../../../styles/application.scss';
import './ui.scss';
const messages = defineMessages({ const messages = defineMessages({
beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Gab Social.' }, beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Gab Social.' },
@ -114,46 +123,30 @@ const LAYOUT = {
RIGHT: null, RIGHT: null,
}, },
DEFAULT: { DEFAULT: {
LEFT: ( LEFT: [
<Fragment> <WhoToFollowPanel key='0' />,
<WhoToFollowPanel /> <LinkFooter key='1' />,
<LinkFooter /> ],
</Fragment> RIGHT: [
), // <TrendsPanel />,
RIGHT: <GroupSidebarPanel /> <GroupSidebarPanel key='0' />
],
}, },
STATUS: { STATUS: {
TOP: null, TOP: null,
LEFT: null, LEFT: null,
RIGHT: ( RIGHT: [
<Fragment> <GroupSidebarPanel key='0' />,
<GroupSidebarPanel /> <WhoToFollowPanel key='1' />,
<WhoToFollowPanel /> // <TrendsPanel />,
<LinkFooter /> <LinkFooter key='2' />,
</Fragment> ],
),
}, },
GROUPS: {
TOP: null,
LEFT: (
<Fragment>
<UserPanel />
<PromoPanel />
<LinkFooter />
</Fragment>
),
RIGHT: (
<Fragment>
<GroupSidebarPanel />
<WhoToFollowPanel />
</Fragment>
),
}
}; };
const shouldHideFAB = path => path.match(/^\/posts\/|^\/search/); const shouldHideFAB = path => path.match(/^\/posts\/|^\/search|^\/getting-started/);
class SwitchingColumnsArea extends PureComponent { class SwitchingColumnsArea extends React.PureComponent {
static propTypes = { static propTypes = {
children: PropTypes.node, children: PropTypes.node,
@ -187,7 +180,8 @@ class SwitchingColumnsArea extends PureComponent {
} }
render() { render() {
const { children } = this.props; const { children, account } = this.props;
const { mobile } = this.state;
return ( return (
<Switch> <Switch>
@ -195,23 +189,26 @@ class SwitchingColumnsArea extends PureComponent {
<WrappedRoute path='/home' exact page={HomePage} component={HomeTimeline} content={children} /> <WrappedRoute path='/home' exact page={HomePage} component={HomeTimeline} content={children} />
<WrappedRoute path='/timeline/all' exact page={HomePage} component={CommunityTimeline} content={children} /> <WrappedRoute path='/timeline/all' exact page={HomePage} component={CommunityTimeline} content={children} />
<WrappedRoute path='/groups' exact layout={LAYOUT.GROUPS} component={Groups} content={children} componentParams={{ activeTab: 'featured' }} /> <WrappedRoute path='/groups' exact page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'featured' }} />
<WrappedRoute path='/groups/create' layout={LAYOUT.GROUPS} component={Groups} content={children} componentParams={{ showCreateForm: true, activeTab: 'featured' }} /> <WrappedRoute path='/groups/create' page={GroupsPage} component={Groups} content={children} componentParams={{ showCreateForm: true, activeTab: 'featured' }} />
<WrappedRoute path='/groups/browse/member' layout={LAYOUT.GROUPS} component={Groups} content={children} componentParams={{ activeTab: 'member' }} /> <WrappedRoute path='/groups/browse/member' page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'member' }} />
<WrappedRoute path='/groups/browse/admin' layout={LAYOUT.GROUPS} component={Groups} content={children} componentParams={{ activeTab: 'admin' }} /> <WrappedRoute path='/groups/browse/admin' page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'admin' }} />
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} /> <WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
<WrappedRoute path='/groups/:id/removed_accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} /> <WrappedRoute path='/groups/:id/removed_accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} />
<WrappedRoute path='/groups/:id/edit' page={GroupPage} component={GroupEdit} content={children} /> <WrappedRoute path='/groups/:id/edit' page={GroupPage} component={GroupEdit} content={children} />
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} /> <WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
<WrappedRoute path='/tags/:id' component={HashtagTimeline} content={children} /> <WrappedRoute path='/tags/:id' publicRoute component={HashtagTimeline} content={children} />
<WrappedRoute path='/lists' layout={LAYOUT.DEFAULT} component={Lists} content={children} /> <WrappedRoute path='/lists' layout={LAYOUT.DEFAULT} component={Lists} content={children} />
<WrappedRoute path='/list/:id' page={HomePage} component={ListTimeline} content={children} /> <WrappedRoute path='/list/:id' page={HomePage} component={ListTimeline} content={children} />
<WrappedRoute path='/notifications' layout={LAYOUT.DEFAULT} component={Notifications} content={children} /> <WrappedRoute path='/notifications' layout={LAYOUT.DEFAULT} component={Notifications} content={children} />
<WrappedRoute path='/search' publicRoute page={SearchPage} component={Search} content={children} /> <WrappedRoute path='/search' exact publicRoute page={SearchPage} component={Search} content={children} />
<WrappedRoute path='/search/people' exact page={SearchPage} component={Search} content={children} />
<WrappedRoute path='/search/hashtags' exact page={SearchPage} component={Search} content={children} />
<WrappedRoute path='/search/groups' exact page={SearchPage} component={Search} content={children} />
<WrappedRoute path='/follow_requests' layout={LAYOUT.DEFAULT} component={FollowRequests} content={children} /> <WrappedRoute path='/follow_requests' layout={LAYOUT.DEFAULT} component={FollowRequests} content={children} />
<WrappedRoute path='/blocks' layout={LAYOUT.DEFAULT} component={Blocks} content={children} /> <WrappedRoute path='/blocks' layout={LAYOUT.DEFAULT} component={Blocks} content={children} />
@ -257,7 +254,7 @@ class SwitchingColumnsArea extends PureComponent {
export default @connect(mapStateToProps) export default @connect(mapStateToProps)
@injectIntl @injectIntl
@withRouter @withRouter
class UI extends PureComponent { class UI extends React.PureComponent {
static contextTypes = { static contextTypes = {
router: PropTypes.object.isRequired, router: PropTypes.object.isRequired,
@ -344,7 +341,9 @@ class UI extends PureComponent {
this.dragTargets = this.dragTargets.filter(el => el !== e.target && this.node.contains(el)); this.dragTargets = this.dragTargets.filter(el => el !== e.target && this.node.contains(el));
if (this.dragTargets.length > 0) return; if (this.dragTargets.length > 0) {
return;
}
this.setState({ draggingOver: false }); this.setState({ draggingOver: false });
} }
@ -385,6 +384,7 @@ class UI extends PureComponent {
if (me) { if (me) {
this.props.dispatch(expandHomeTimeline()); this.props.dispatch(expandHomeTimeline());
this.props.dispatch(expandNotifications()); this.props.dispatch(expandNotifications());
this.props.dispatch(initializeNotifications());
this.props.dispatch(fetchGroups('member')); this.props.dispatch(fetchGroups('member'));
setTimeout(() => this.props.dispatch(fetchFilters()), 500); setTimeout(() => this.props.dispatch(fetchFilters()), 500);
@ -393,7 +393,6 @@ class UI extends PureComponent {
componentDidMount() { componentDidMount() {
if (!me) return; if (!me) return;
this.hotkeys.__mousetrap__.stopCallback = (e, element) => { this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName); return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName);
}; };
@ -479,6 +478,10 @@ class UI extends PureComponent {
this.context.router.history.push('/notifications'); this.context.router.history.push('/notifications');
} }
handleHotkeyGoToStart = () => {
this.context.router.history.push('/getting-started');
}
handleHotkeyGoToFavourites = () => { handleHotkeyGoToFavourites = () => {
this.context.router.history.push(`/${meUsername}/favorites`); this.context.router.history.push(`/${meUsername}/favorites`);
} }
@ -520,6 +523,7 @@ class UI extends PureComponent {
back: this.handleHotkeyBack, back: this.handleHotkeyBack,
goToHome: this.handleHotkeyGoToHome, goToHome: this.handleHotkeyGoToHome,
goToNotifications: this.handleHotkeyGoToNotifications, goToNotifications: this.handleHotkeyGoToNotifications,
goToStart: this.handleHotkeyGoToStart,
goToFavourites: this.handleHotkeyGoToFavourites, goToFavourites: this.handleHotkeyGoToFavourites,
goToPinned: this.handleHotkeyGoToPinned, goToPinned: this.handleHotkeyGoToPinned,
goToProfile: this.handleHotkeyGoToProfile, goToProfile: this.handleHotkeyGoToProfile,
@ -528,7 +532,7 @@ class UI extends PureComponent {
goToRequests: this.handleHotkeyGoToRequests, goToRequests: this.handleHotkeyGoToRequests,
} : {}; } : {};
const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : (<FloatingActionButton onClick={this.handleOpenComposeModal} message={intl.formatMessage(messages.publish)} />); const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : <button key='floating-action-button' onClick={this.handleOpenComposeModal} className='floating-action-button' aria-label={intl.formatMessage(messages.publish)}></button>;
return ( return (
<HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused> <HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused>
@ -537,6 +541,7 @@ class UI extends PureComponent {
<SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange}> <SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange}>
{children} {children}
</SwitchingColumnsArea> </SwitchingColumnsArea>
<FooterBar />
{me && floatingActionButton} {me && floatingActionButton}
@ -544,6 +549,7 @@ class UI extends PureComponent {
<LoadingBarContainer className='loading-bar' /> <LoadingBarContainer className='loading-bar' />
<ModalContainer /> <ModalContainer />
<UploadArea active={draggingOver} onClose={this.closeUploadModal} /> <UploadArea active={draggingOver} onClose={this.closeUploadModal} />
{me && <SidebarMenu />}
</div> </div>
</HotKeys> </HotKeys>
); );

View File

@ -1,14 +1,14 @@
import { defineMessages, injectIntl } from 'react-intl'; import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { fromJS, is } from 'immutable'; import { fromJS, is } from 'immutable';
import { throttle } from 'lodash'; import { throttle } from 'lodash';
import classNames from 'classnames'; import classNames from 'classnames';
import { decode } from 'blurhash'; import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen';
import { isFullscreen, requestFullscreen, exitFullscreen } from '../../utils/fullscreen';
import { getPointerPosition } from '../../utils/element_position';
import { displayMedia } from '../../initial_state'; import { displayMedia } from '../../initial_state';
import Icon from '../../components/icon'; import Icon from 'gabsocial/components/icon';
import { decode } from 'blurhash';
import './video.scss'; import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
const messages = defineMessages({ const messages = defineMessages({
play: { id: 'video.play', defaultMessage: 'Play' }, play: { id: 'video.play', defaultMessage: 'Play' },
@ -20,8 +20,6 @@ const messages = defineMessages({
close: { id: 'video.close', defaultMessage: 'Close video' }, close: { id: 'video.close', defaultMessage: 'Close video' },
fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' }, fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' }, exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
warning: { id: 'status.sensitive_warning', defaultMessage: 'Sensitive content' },
hidden: { id: 'status.media_hidden', defaultMessage: 'Media hidden' },
}); });
const formatTime = secondsNum => { const formatTime = secondsNum => {
@ -36,8 +34,61 @@ const formatTime = secondsNum => {
return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`; return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
}; };
export const findElementPosition = el => {
let box;
if (el.getBoundingClientRect && el.parentNode) {
box = el.getBoundingClientRect();
}
if (!box) {
return {
left: 0,
top: 0,
};
}
const docEl = document.documentElement;
const body = document.body;
const clientLeft = docEl.clientLeft || body.clientLeft || 0;
const scrollLeft = window.pageXOffset || body.scrollLeft;
const left = (box.left + scrollLeft) - clientLeft;
const clientTop = docEl.clientTop || body.clientTop || 0;
const scrollTop = window.pageYOffset || body.scrollTop;
const top = (box.top + scrollTop) - clientTop;
return {
left: Math.round(left),
top: Math.round(top),
};
};
export const getPointerPosition = (el, event) => {
const position = {};
const box = findElementPosition(el);
const boxW = el.offsetWidth;
const boxH = el.offsetHeight;
const boxY = box.top;
const boxX = box.left;
let pageY = event.pageY;
let pageX = event.pageX;
if (event.changedTouches) {
pageX = event.changedTouches[0].pageX;
pageY = event.changedTouches[0].pageY;
}
position.y = Math.max(0, Math.min(1, (pageY - boxY) / boxH));
position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));
return position;
};
export default @injectIntl export default @injectIntl
class Video extends PureComponent { class Video extends React.PureComponent {
static propTypes = { static propTypes = {
preview: PropTypes.string, preview: PropTypes.string,
@ -57,6 +108,7 @@ class Video extends PureComponent {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
blurhash: PropTypes.string, blurhash: PropTypes.string,
link: PropTypes.node, link: PropTypes.node,
aspectRatio: PropTypes.number,
}; };
state = { state = {
@ -154,13 +206,11 @@ class Video extends PureComponent {
if (!isNaN(x)) { if (!isNaN(x)) {
var slideamt = x; var slideamt = x;
if (x > 1) { if (x > 1) {
slideamt = 1; slideamt = 1;
} else if (x < 0) { } else if (x < 0) {
slideamt = 0; slideamt = 0;
} }
this.video.volume = slideamt; this.video.volume = slideamt;
this.setState({ volume: slideamt }); this.setState({ volume: slideamt });
} }
@ -294,6 +344,7 @@ class Video extends PureComponent {
} }
handleProgress = () => { handleProgress = () => {
if (!this.video.buffered) return;
if (this.video.buffered.length > 0) { if (this.video.buffered.length > 0) {
this.setState({ buffer: this.video.buffered.end(0) / this.video.duration * 100 }); this.setState({ buffer: this.video.buffered.end(0) / this.video.duration * 100 });
} }
@ -325,7 +376,7 @@ class Video extends PureComponent {
} }
render() { render() {
const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link } = this.props; const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link, aspectRatio } = this.props;
const { containerWidth, currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state; const { containerWidth, currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
const progress = (currentTime / duration) * 100; const progress = (currentTime / duration) * 100;
@ -337,7 +388,15 @@ class Video extends PureComponent {
if (inline && containerWidth) { if (inline && containerWidth) {
width = containerWidth; width = containerWidth;
height = containerWidth / (16 / 9); const minSize = containerWidth / (16 / 9);
if (isPanoramic(aspectRatio)) {
height = Math.max(Math.floor(containerWidth / maximumAspectRatio), minSize);
} else if (isPortrait(aspectRatio)) {
height = Math.max(Math.floor(containerWidth / minimumAspectRatio), minSize);
} else {
height = Math.floor(containerWidth / aspectRatio);
}
playerStyle.height = height; playerStyle.height = height;
} }
@ -352,6 +411,14 @@ class Video extends PureComponent {
preload = 'none'; preload = 'none';
} }
let warning;
if (sensitive) {
warning = <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />;
} else {
warning = <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' />;
}
return ( return (
<div <div
role='menuitem' role='menuitem'
@ -366,6 +433,7 @@ class Video extends PureComponent {
<canvas width={32} height={32} ref={this.setCanvasRef} className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': revealed })} /> <canvas width={32} height={32} ref={this.setCanvasRef} className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': revealed })} />
{revealed && <video {revealed && <video
playsInline
ref={this.setVideoRef} ref={this.setVideoRef}
src={src} src={src}
poster={preview} poster={preview}
@ -389,7 +457,7 @@ class Video extends PureComponent {
<div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed })}> <div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed })}>
<button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}> <button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
<span className='spoiler-button__overlay__label'>{intl.formatMessage(sensitive ? messages.warning : messages.hidden)}</span> <span className='spoiler-button__overlay__label'>{warning}</span>
</button> </button>
</div> </div>