forked from treehouse/mastodon
Merge remote-tracking branch 'glitchsoc/master' into gs-master
commit
d2b28ea51d
|
@ -6,7 +6,7 @@ import IconButton from './icon_button';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { isIOS } from 'flavours/glitch/util/is_mobile';
|
import { isIOS } from 'flavours/glitch/util/is_mobile';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { autoPlayGif } from 'flavours/glitch/util/initial_state';
|
import { autoPlayGif, displaySensitiveMedia } from 'flavours/glitch/util/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
hidden: {
|
hidden: {
|
||||||
|
@ -208,7 +208,7 @@ export default class MediaGallery extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
visible: !this.props.sensitive,
|
visible: !this.props.sensitive || displaySensitiveMedia,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
|
@ -265,6 +265,7 @@ export default class MediaGallery extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className='media-spoiler'
|
className='media-spoiler'
|
||||||
|
type='button'
|
||||||
onClick={handleOpen}
|
onClick={handleOpen}
|
||||||
>
|
>
|
||||||
<span className='media-spoiler__warning'>
|
<span className='media-spoiler__warning'>
|
||||||
|
|
|
@ -326,6 +326,7 @@ export default class Status extends ImmutablePureComponent {
|
||||||
{Component => (<Component
|
{Component => (<Component
|
||||||
preview={video.get('preview_url')}
|
preview={video.get('preview_url')}
|
||||||
src={video.get('url')}
|
src={video.get('url')}
|
||||||
|
inline
|
||||||
sensitive={status.get('sensitive')}
|
sensitive={status.get('sensitive')}
|
||||||
letterbox={settings.getIn(['media', 'letterbox'])}
|
letterbox={settings.getIn(['media', 'letterbox'])}
|
||||||
fullwidth={settings.getIn(['media', 'fullwidth'])}
|
fullwidth={settings.getIn(['media', 'fullwidth'])}
|
||||||
|
|
|
@ -58,6 +58,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
|
||||||
<Video
|
<Video
|
||||||
preview={video.get('preview_url')}
|
preview={video.get('preview_url')}
|
||||||
src={video.get('url')}
|
src={video.get('url')}
|
||||||
|
inline
|
||||||
sensitive={status.get('sensitive')}
|
sensitive={status.get('sensitive')}
|
||||||
letterbox={settings.getIn(['media', 'letterbox'])}
|
letterbox={settings.getIn(['media', 'letterbox'])}
|
||||||
fullwidth={settings.getIn(['media', 'fullwidth'])}
|
fullwidth={settings.getIn(['media', 'fullwidth'])}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import BundleContainer from '../containers/bundle_container';
|
||||||
import ColumnLoading from './column_loading';
|
import ColumnLoading from './column_loading';
|
||||||
import DrawerLoading from './drawer_loading';
|
import DrawerLoading from './drawer_loading';
|
||||||
import BundleColumnError from './bundle_column_error';
|
import BundleColumnError from './bundle_column_error';
|
||||||
import { Drawer, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, DirectTimeline, FavouritedStatuses, ListTimeline } from 'flavours/glitch/util/async-components';
|
import { Drawer, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, DirectTimeline, FavouritedStatuses, BookmarkedStatuses, ListTimeline } from 'flavours/glitch/util/async-components';
|
||||||
|
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import detectPassiveEvents from 'detect-passive-events';
|
||||||
import { scrollRight } from 'flavours/glitch/util/scroll';
|
import { scrollRight } from 'flavours/glitch/util/scroll';
|
||||||
|
@ -25,6 +25,7 @@ const componentMap = {
|
||||||
'HASHTAG': HashtagTimeline,
|
'HASHTAG': HashtagTimeline,
|
||||||
'DIRECT': DirectTimeline,
|
'DIRECT': DirectTimeline,
|
||||||
'FAVOURITES': FavouritedStatuses,
|
'FAVOURITES': FavouritedStatuses,
|
||||||
|
'BOOKMARKS': BookmarkedStatuses,
|
||||||
'LIST': ListTimeline,
|
'LIST': ListTimeline,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { throttle } from 'lodash';
|
import { throttle } from 'lodash';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isFullscreen, requestFullscreen, exitFullscreen } from 'flavours/glitch/util/fullscreen';
|
import { isFullscreen, requestFullscreen, exitFullscreen } from 'flavours/glitch/util/fullscreen';
|
||||||
|
import { displaySensitiveMedia } from 'flavours/glitch/util/initial_state';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
play: { id: 'video.play', defaultMessage: 'Play' },
|
play: { id: 'video.play', defaultMessage: 'Play' },
|
||||||
|
@ -97,6 +98,7 @@ export default class Video extends React.PureComponent {
|
||||||
letterbox: PropTypes.bool,
|
letterbox: PropTypes.bool,
|
||||||
fullwidth: PropTypes.bool,
|
fullwidth: PropTypes.bool,
|
||||||
detailed: PropTypes.bool,
|
detailed: PropTypes.bool,
|
||||||
|
inline: PropTypes.bool,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,14 +107,21 @@ export default class Video extends React.PureComponent {
|
||||||
duration: 0,
|
duration: 0,
|
||||||
paused: true,
|
paused: true,
|
||||||
dragging: false,
|
dragging: false,
|
||||||
|
containerWidth: false,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
hovered: false,
|
hovered: false,
|
||||||
muted: false,
|
muted: false,
|
||||||
revealed: !this.props.sensitive,
|
revealed: !this.props.sensitive || displaySensitiveMedia,
|
||||||
};
|
};
|
||||||
|
|
||||||
setPlayerRef = c => {
|
setPlayerRef = c => {
|
||||||
this.player = c;
|
this.player = c;
|
||||||
|
|
||||||
|
if (c) {
|
||||||
|
this.setState({
|
||||||
|
containerWidth: c.offsetWidth,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setVideoRef = c => {
|
setVideoRef = c => {
|
||||||
|
@ -246,12 +255,23 @@ export default class Video extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed } = this.props;
|
const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed } = this.props;
|
||||||
const { currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
|
const { containerWidth, currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
|
||||||
const progress = (currentTime / duration) * 100;
|
const progress = (currentTime / duration) * 100;
|
||||||
|
const playerStyle = {};
|
||||||
|
|
||||||
|
let { width, height } = this.props;
|
||||||
|
|
||||||
|
if (inline && containerWidth) {
|
||||||
|
width = containerWidth;
|
||||||
|
height = containerWidth / (16/9);
|
||||||
|
|
||||||
|
playerStyle.width = width;
|
||||||
|
playerStyle.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('video-player', { inactive: !revealed, detailed, inline: width && height && !fullscreen, fullscreen, letterbox, 'full-width': fullwidth })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
<div className={classNames('video-player', { inactive: !revealed, detailed, inline: width && height && !fullscreen, fullscreen, letterbox, 'full-width': fullwidth })} style={playerStyle} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||||
<video
|
<video
|
||||||
ref={this.setVideoRef}
|
ref={this.setVideoRef}
|
||||||
src={src}
|
src={src}
|
||||||
|
@ -271,7 +291,7 @@ export default class Video extends React.PureComponent {
|
||||||
onProgress={this.handleProgress}
|
onProgress={this.handleProgress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}>
|
<button type='button' className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}>
|
||||||
<span className='video-player__spoiler__title'><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span>
|
<span className='video-player__spoiler__title'><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span>
|
||||||
<span className='video-player__spoiler__subtitle'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
|
<span className='video-player__spoiler__subtitle'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -290,10 +310,10 @@ export default class Video extends React.PureComponent {
|
||||||
|
|
||||||
<div className='video-player__buttons-bar'>
|
<div className='video-player__buttons-bar'>
|
||||||
<div className='video-player__buttons left'>
|
<div className='video-player__buttons left'>
|
||||||
<button aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button>
|
<button type='button' aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button>
|
||||||
<button aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
|
<button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
|
||||||
|
|
||||||
{!onCloseVideo && <button aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><i className='fa fa-fw fa-eye' /></button>}
|
{!onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><i className='fa fa-fw fa-eye' /></button>}
|
||||||
|
|
||||||
{(detailed || fullscreen) &&
|
{(detailed || fullscreen) &&
|
||||||
<span>
|
<span>
|
||||||
|
@ -305,9 +325,9 @@ export default class Video extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='video-player__buttons right'>
|
<div className='video-player__buttons right'>
|
||||||
{(!fullscreen && onOpenVideo) && <button aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><i className='fa fa-fw fa-expand' /></button>}
|
{(!fullscreen && onOpenVideo) && <button type='button' aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><i className='fa fa-fw fa-expand' /></button>}
|
||||||
{onCloseVideo && <button aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><i className='fa fa-fw fa-compress' /></button>}
|
{onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><i className='fa fa-fw fa-compress' /></button>}
|
||||||
<button aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><i className={classNames('fa fa-fw', { 'fa-arrows-alt': !fullscreen, 'fa-compress': fullscreen })} /></button>
|
<button type='button' aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><i className={classNames('fa fa-fw', { 'fa-arrows-alt': !fullscreen, 'fa-compress': fullscreen })} /></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -161,6 +161,12 @@
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-modal {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.extended-video-player {
|
.extended-video-player {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -176,12 +182,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-modal {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-modal__closer {
|
.media-modal__closer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -307,7 +307,7 @@
|
||||||
|
|
||||||
&.inline {
|
&.inline {
|
||||||
video {
|
video {
|
||||||
object-fit: cover;
|
object-fit: contain;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
|
|
|
@ -13,6 +13,7 @@ const getMeta = (prop) => initialState && initialState.meta && initialState.meta
|
||||||
|
|
||||||
export const reduceMotion = getMeta('reduce_motion');
|
export const reduceMotion = getMeta('reduce_motion');
|
||||||
export const autoPlayGif = getMeta('auto_play_gif');
|
export const autoPlayGif = getMeta('auto_play_gif');
|
||||||
|
export const displaySensitiveMedia = getMeta('display_sensitive_media');
|
||||||
export const unfollowModal = getMeta('unfollow_modal');
|
export const unfollowModal = getMeta('unfollow_modal');
|
||||||
export const boostModal = getMeta('boost_modal');
|
export const boostModal = getMeta('boost_modal');
|
||||||
export const favouriteModal = getMeta('favourite_modal');
|
export const favouriteModal = getMeta('favourite_modal');
|
||||||
|
|
Loading…
Reference in New Issue