mirror of
https://github.com/mastodon/mastodon.git
synced 2025-05-11 20:21:10 +00:00
Refactor spoiler button logic into separate SpoilerButton
component (#34257)
This commit is contained in:
parent
5390edc2aa
commit
958953a687
|
@ -12,6 +12,7 @@ import { debounce } from 'lodash';
|
||||||
|
|
||||||
import { AltTextBadge } from 'mastodon/components/alt_text_badge';
|
import { AltTextBadge } from 'mastodon/components/alt_text_badge';
|
||||||
import { Blurhash } from 'mastodon/components/blurhash';
|
import { Blurhash } from 'mastodon/components/blurhash';
|
||||||
|
import { SpoilerButton } from 'mastodon/components/spoiler_button';
|
||||||
import { formatTime } from 'mastodon/features/video';
|
import { formatTime } from 'mastodon/features/video';
|
||||||
|
|
||||||
import { autoPlayGif, displayMedia, useBlurhash } from '../initial_state';
|
import { autoPlayGif, displayMedia, useBlurhash } from '../initial_state';
|
||||||
|
@ -299,7 +300,7 @@ class MediaGallery extends PureComponent {
|
||||||
const { visible } = this.state;
|
const { visible } = this.state;
|
||||||
const width = this.state.width || defaultWidth;
|
const width = this.state.width || defaultWidth;
|
||||||
|
|
||||||
let children, spoilerButton;
|
let children;
|
||||||
|
|
||||||
const style = {};
|
const style = {};
|
||||||
|
|
||||||
|
@ -318,35 +319,11 @@ class MediaGallery extends PureComponent {
|
||||||
children = media.map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} lang={lang} size={size} displayWidth={width} visible={visible || uncached} />);
|
children = media.map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} lang={lang} size={size} displayWidth={width} visible={visible || uncached} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uncached) {
|
|
||||||
spoilerButton = (
|
|
||||||
<button type='button' disabled className='spoiler-button__overlay'>
|
|
||||||
<span className='spoiler-button__overlay__label'>
|
|
||||||
<FormattedMessage id='status.uncached_media_warning' defaultMessage='Preview not available' />
|
|
||||||
<span className='spoiler-button__overlay__action'><FormattedMessage id='status.media.open' defaultMessage='Click to open' /></span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
} else if (!visible) {
|
|
||||||
spoilerButton = (
|
|
||||||
<button type='button' onClick={this.handleOpen} className='spoiler-button__overlay'>
|
|
||||||
<span className='spoiler-button__overlay__label'>
|
|
||||||
{sensitive ? <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /> : <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' />}
|
|
||||||
<span className='spoiler-button__overlay__action'><FormattedMessage id='status.media.show' defaultMessage='Click to show' /></span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`media-gallery media-gallery--layout-${size}`} style={style} ref={this.handleRef}>
|
<div className={`media-gallery media-gallery--layout-${size}`} style={style} ref={this.handleRef}>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
{(!visible || uncached) && (
|
{(!visible || uncached) && <SpoilerButton uncached={uncached} sensitive={sensitive} onClick={this.handleOpen} />}
|
||||||
<div className={classNames('spoiler-button', { 'spoiler-button--click-thru': uncached })}>
|
|
||||||
{spoilerButton}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(visible && !uncached) && (
|
{(visible && !uncached) && (
|
||||||
<div className='media-gallery__actions'>
|
<div className='media-gallery__actions'>
|
||||||
|
|
73
app/javascript/mastodon/components/spoiler_button.tsx
Normal file
73
app/javascript/mastodon/components/spoiler_button.tsx
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
hidden?: boolean;
|
||||||
|
sensitive: boolean;
|
||||||
|
uncached?: boolean;
|
||||||
|
onClick: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SpoilerButton: React.FC<Props> = ({
|
||||||
|
hidden = false,
|
||||||
|
sensitive,
|
||||||
|
uncached = false,
|
||||||
|
onClick,
|
||||||
|
}) => {
|
||||||
|
let warning;
|
||||||
|
let action;
|
||||||
|
|
||||||
|
if (uncached) {
|
||||||
|
warning = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='status.uncached_media_warning'
|
||||||
|
defaultMessage='Preview not available'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
action = (
|
||||||
|
<FormattedMessage id='status.media.open' defaultMessage='Click to open' />
|
||||||
|
);
|
||||||
|
} else if (sensitive) {
|
||||||
|
warning = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='status.sensitive_warning'
|
||||||
|
defaultMessage='Sensitive content'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
action = (
|
||||||
|
<FormattedMessage id='status.media.show' defaultMessage='Click to show' />
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
warning = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='status.media_hidden'
|
||||||
|
defaultMessage='Media hidden'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
action = (
|
||||||
|
<FormattedMessage id='status.media.show' defaultMessage='Click to show' />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames('spoiler-button', {
|
||||||
|
'spoiler-button--hidden': hidden,
|
||||||
|
'spoiler-button--click-thru': uncached,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='spoiler-button__overlay'
|
||||||
|
onClick={onClick}
|
||||||
|
disabled={uncached}
|
||||||
|
>
|
||||||
|
<span className='spoiler-button__overlay__label'>
|
||||||
|
{warning}
|
||||||
|
<span className='spoiler-button__overlay__action'>{action}</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,7 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?reac
|
||||||
import VolumeOffIcon from '@/material-icons/400-24px/volume_off-fill.svg?react';
|
import VolumeOffIcon from '@/material-icons/400-24px/volume_off-fill.svg?react';
|
||||||
import VolumeUpIcon from '@/material-icons/400-24px/volume_up-fill.svg?react';
|
import VolumeUpIcon from '@/material-icons/400-24px/volume_up-fill.svg?react';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { SpoilerButton } from 'mastodon/components/spoiler_button';
|
||||||
import { formatTime, getPointerPosition, fileNameFromURL } from 'mastodon/features/video';
|
import { formatTime, getPointerPosition, fileNameFromURL } from 'mastodon/features/video';
|
||||||
|
|
||||||
import { Blurhash } from '../../components/blurhash';
|
import { Blurhash } from '../../components/blurhash';
|
||||||
|
@ -476,14 +477,6 @@ class Audio extends PureComponent {
|
||||||
const progress = Math.min((currentTime / duration) * 100, 100);
|
const progress = Math.min((currentTime / duration) * 100, 100);
|
||||||
const muted = this.state.muted || volume === 0;
|
const muted = this.state.muted || volume === 0;
|
||||||
|
|
||||||
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 className={classNames('audio-player', { editable, inactive: !revealed })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), aspectRatio: '16 / 9' }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex={0} onKeyDown={this.handleKeyDown}>
|
<div className={classNames('audio-player', { editable, inactive: !revealed })} ref={this.setPlayerRef} style={{ backgroundColor: this._getBackgroundColor(), color: this._getForegroundColor(), aspectRatio: '16 / 9' }} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} tabIndex={0} onKeyDown={this.handleKeyDown}>
|
||||||
|
|
||||||
|
@ -521,14 +514,7 @@ class Audio extends PureComponent {
|
||||||
lang={lang}
|
lang={lang}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed || editable })}>
|
<SpoilerButton hidden={revealed || editable} sensitive={sensitive} onClick={this.toggleReveal} />
|
||||||
<button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
|
|
||||||
<span className='spoiler-button__overlay__label'>
|
|
||||||
{warning}
|
|
||||||
<span className='spoiler-button__overlay__action'><FormattedMessage id='status.media.show' defaultMessage='Click to show' /></span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{(revealed || editable) && <img
|
{(revealed || editable) && <img
|
||||||
src={this.props.poster}
|
src={this.props.poster}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { PureComponent } from 'react';
|
import { PureComponent } from 'react';
|
||||||
|
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import VolumeOffIcon from '@/material-icons/400-24px/volume_off-fill.svg?react';
|
||||||
import VolumeUpIcon from '@/material-icons/400-24px/volume_up-fill.svg?react';
|
import VolumeUpIcon from '@/material-icons/400-24px/volume_up-fill.svg?react';
|
||||||
import { Blurhash } from 'mastodon/components/blurhash';
|
import { Blurhash } from 'mastodon/components/blurhash';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { SpoilerButton } from 'mastodon/components/spoiler_button';
|
||||||
import { playerSettings } from 'mastodon/settings';
|
import { playerSettings } from 'mastodon/settings';
|
||||||
|
|
||||||
import { displayMedia, useBlurhash } from '../../initial_state';
|
import { displayMedia, useBlurhash } from '../../initial_state';
|
||||||
|
@ -549,14 +550,6 @@ 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' />;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The outer wrapper is necessary to avoid reflowing the layout when going into full screen
|
// The outer wrapper is necessary to avoid reflowing the layout when going into full screen
|
||||||
return (
|
return (
|
||||||
<div style={{ aspectRatio }}>
|
<div style={{ aspectRatio }}>
|
||||||
|
@ -599,14 +592,7 @@ class Video extends PureComponent {
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
/>}
|
/>}
|
||||||
|
|
||||||
<div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed || editable })}>
|
<SpoilerButton hidden={revealed || editable} sensitive={sensitive} onClick={this.toggleReveal} />
|
||||||
<button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
|
|
||||||
<span className='spoiler-button__overlay__label'>
|
|
||||||
{warning}
|
|
||||||
<span className='spoiler-button__overlay__action'><FormattedMessage id='status.media.show' defaultMessage='Click to show' /></span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={classNames('video-player__controls', { active: paused || hovered })}>
|
<div className={classNames('video-player__controls', { active: paused || hovered })}>
|
||||||
<div className='video-player__seek' onMouseDown={this.handleMouseDown} ref={this.setSeekRef}>
|
<div className='video-player__seek' onMouseDown={this.handleMouseDown} ref={this.setSeekRef}>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user