Handle autoPlayGif for avatars and banners

merge-requests/82/merge
Bárbara de Castro Fernandes 2020-06-10 10:30:33 -03:00
rodzic e19f350111
commit 52f3f8ce8d
9 zmienionych plików z 63 dodań i 97 usunięć

Wyświetl plik

@ -1,54 +1,25 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { getSettings } from 'soapbox/actions/settings'; import classNames from 'classnames';
import StillImage from 'soapbox/components/still_image';
const mapStateToProps = state => ({ export default class Avatar extends React.PureComponent {
animate: getSettings(state).get('autoPlayGif'),
});
export class Avatar extends React.PureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map, account: ImmutablePropTypes.map,
size: PropTypes.number, size: PropTypes.number,
style: PropTypes.object, style: PropTypes.object,
inline: PropTypes.bool, inline: PropTypes.bool,
animate: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
inline: false, inline: false,
}; };
state = {
hovering: false,
};
handleMouseEnter = () => {
if (this.props.animate) return;
this.setState({ hovering: true });
}
handleMouseLeave = () => {
if (this.props.animate) return;
this.setState({ hovering: false });
}
render() { render() {
const { account, size, animate, inline } = this.props; const { account, size, inline } = this.props;
if (!account) return null; if (!account) return null;
const { hovering } = this.state;
const src = account.get('avatar');
const staticSrc = account.get('avatar_static');
let className = 'account__avatar';
if (inline) {
className = className + ' account__avatar-inline';
}
// : TODO : remove inline and change all avatars to be sized using css // : TODO : remove inline and change all avatars to be sized using css
const style = !size ? {} : { const style = !size ? {} : {
@ -56,22 +27,14 @@ export class Avatar extends React.PureComponent {
height: `${size}px`, height: `${size}px`,
}; };
if (hovering || animate) {
style.backgroundImage = `url(${src})`;
} else {
style.backgroundImage = `url(${staticSrc})`;
}
return ( return (
<div <StillImage
className={className} className={classNames('account__avatar', { 'account__avatar-inline': inline })}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={style} style={style}
src={account.get('avatar')}
alt=''
/> />
); );
} }
} }
export default connect(mapStateToProps)(Avatar);

Wyświetl plik

@ -1,24 +1,16 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { getSettings } from 'soapbox/actions/settings'; import StillImage from 'soapbox/components/still_image';
const mapStateToProps = state => ({ export default class AvatarComposite extends React.PureComponent {
animate: getSettings(state).get('autoPlayGif'),
});
export default @connect(mapStateToProps)
class AvatarComposite extends React.PureComponent {
static propTypes = { static propTypes = {
accounts: ImmutablePropTypes.list.isRequired, accounts: ImmutablePropTypes.list.isRequired,
animate: PropTypes.bool,
size: PropTypes.number.isRequired, size: PropTypes.number.isRequired,
}; };
renderItem(account, size, index) { renderItem(account, size, index) {
const { animate } = this.props;
let width = 50; let width = 50;
let height = 100; let height = 100;
@ -76,12 +68,10 @@ class AvatarComposite extends React.PureComponent {
bottom: bottom, bottom: bottom,
width: `${width}%`, width: `${width}%`,
height: `${height}%`, height: `${height}%`,
backgroundSize: 'cover',
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
}; };
return ( return (
<div key={account.get('id')} style={style} /> <StillImage key={account.get('id')} src={account.get('avatar')} style={style} />
); );
} }

Wyświetl plik

@ -1,40 +1,23 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { getSettings } from 'soapbox/actions/settings'; import StillImage from 'soapbox/components/still_image';
const mapStateToProps = state => ({ export default class AvatarOverlay extends React.PureComponent {
animate: getSettings(state).get('autoPlayGif'),
});
export class AvatarOverlay extends React.PureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map.isRequired, account: ImmutablePropTypes.map.isRequired,
friend: ImmutablePropTypes.map.isRequired, friend: ImmutablePropTypes.map.isRequired,
animate: PropTypes.bool,
}; };
render() { render() {
const { account, friend, animate } = this.props; const { account, friend } = this.props;
const baseStyle = {
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
};
const overlayStyle = {
backgroundImage: `url(${friend.get(animate ? 'avatar' : 'avatar_static')})`,
};
return ( return (
<div className='account__avatar-overlay'> <div className='account__avatar-overlay'>
<div className='account__avatar-overlay-base' style={baseStyle} /> <StillImage src={account.get('avatar')} className='account__avatar-overlay-base' />
<div className='account__avatar-overlay-overlay' style={overlayStyle} /> <StillImage src={friend.get('avatar')} className='account__avatar-overlay-overlay' />
</div> </div>
); );
} }
} }
export default connect(mapStateToProps)(AvatarOverlay);

Wyświetl plik

@ -27,7 +27,7 @@ class StillImage extends React.PureComponent {
hoverToPlay() { hoverToPlay() {
const { autoPlayGif, src } = this.props; const { autoPlayGif, src } = this.props;
return !autoPlayGif && src.endsWith('.gif'); return !autoPlayGif && (src.endsWith('.gif') || src.startsWith('blob:'));
} }
setCanvasRef = c => { setCanvasRef = c => {

Wyświetl plik

@ -16,7 +16,7 @@ import { NavLink } from 'react-router-dom';
import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container'; import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container';
import ProfileInfoPanel from '../../ui/components/profile_info_panel'; import ProfileInfoPanel from '../../ui/components/profile_info_panel';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { getSettings } from 'soapbox/actions/settings'; import StillImage from 'soapbox/components/still_image';
const messages = defineMessages({ const messages = defineMessages({
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
@ -54,7 +54,6 @@ const mapStateToProps = state => {
return { return {
me, me,
isStaff: isStaff(state.getIn(['accounts', me])), isStaff: isStaff(state.getIn(['accounts', me])),
autoPlayGif: getSettings(state).get('autoPlayGif'),
version: parseVersion(state.getIn(['instance', 'version'])), version: parseVersion(state.getIn(['instance', 'version'])),
}; };
}; };
@ -70,7 +69,6 @@ class Header extends ImmutablePureComponent {
onBlock: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
username: PropTypes.string, username: PropTypes.string,
autoPlayGif: PropTypes.bool,
isStaff: PropTypes.bool.isRequired, isStaff: PropTypes.bool.isRequired,
version: PropTypes.object, version: PropTypes.object,
}; };
@ -226,7 +224,7 @@ class Header extends ImmutablePureComponent {
}; };
render() { render() {
const { account, intl, username, me, autoPlayGif } = this.props; const { account, intl, username, me } = this.props;
const { isSmallScreen } = this.state; const { isSmallScreen } = this.state;
if (!account) { if (!account) {
@ -252,8 +250,7 @@ class Header extends ImmutablePureComponent {
const actionBtn = this.getActionBtn(); const actionBtn = this.getActionBtn();
const menu = this.makeMenu(); const menu = this.makeMenu();
const headerImgSrc = autoPlayGif ? account.get('header') : account.get('header_static'); const headerMissing = (account.get('header').indexOf('/headers/original/missing.png') > -1);
const headerMissing = (headerImgSrc.indexOf('/headers/original/missing.png') > -1);
const avatarSize = isSmallScreen ? 90 : 200; const avatarSize = isSmallScreen ? 90 : 200;
@ -264,7 +261,7 @@ class Header extends ImmutablePureComponent {
{info} {info}
</div> </div>
<img src={headerImgSrc} alt='' className='parallax' /> <StillImage src={account.get('header')} alt='' className='parallax' />
</div> </div>
<div className='account__header__bar'> <div className='account__header__bar'>

Wyświetl plik

@ -1,16 +1,17 @@
import React from 'react'; import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { acctFull } from 'soapbox/utils/accounts'; import { acctFull } from 'soapbox/utils/accounts';
import StillImage from 'soapbox/components/still_image';
const ProfilePreview = ({ account }) => ( const ProfilePreview = ({ account }) => (
<div className='card h-card'> <div className='card h-card'>
<a target='_blank' rel='noopener' href={account.get('url')}> <a target='_blank' rel='noopener' href={account.get('url')}>
<div className='card__img'> <div className='card__img'>
<img alt='' src={account.get('header')} /> <StillImage alt='' src={account.get('header')} />
</div> </div>
<div className='card__bar'> <div className='card__bar'>
<div className='avatar'> <div className='avatar'>
<img alt='' className='u-photo' src={account.get('avatar')} width='48' height='48' /> <StillImage alt='' className='u-photo' src={account.get('avatar')} width='48' height='48' />
</div> </div>
<div className='display-name'> <div className='display-name'>
<span style={{ display: 'none' }}>{account.get('username')}</span> <span style={{ display: 'none' }}>{account.get('username')}</span>

Wyświetl plik

@ -9,7 +9,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import Avatar from 'soapbox/components/avatar'; import Avatar from 'soapbox/components/avatar';
import { shortNumberFormat } from 'soapbox/utils/numbers'; import { shortNumberFormat } from 'soapbox/utils/numbers';
import { acctFull } from 'soapbox/utils/accounts'; import { acctFull } from 'soapbox/utils/accounts';
import { getSettings } from 'soapbox/actions/settings'; import StillImage from 'soapbox/components/still_image';
class UserPanel extends ImmutablePureComponent { class UserPanel extends ImmutablePureComponent {
@ -20,7 +20,7 @@ class UserPanel extends ImmutablePureComponent {
} }
render() { render() {
const { account, intl, domain, autoPlayGif } = this.props; const { account, intl, domain } = this.props;
if (!account) return null; if (!account) return null;
const displayNameHtml = { __html: account.get('display_name_html') }; const displayNameHtml = { __html: account.get('display_name_html') };
const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct'); const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct');
@ -30,7 +30,7 @@ class UserPanel extends ImmutablePureComponent {
<div className='user-panel__container'> <div className='user-panel__container'>
<div className='user-panel__header'> <div className='user-panel__header'>
<img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' /> <StillImage src={account.get('header')} alt='' />
</div> </div>
<div className='user-panel__profile'> <div className='user-panel__profile'>
@ -91,7 +91,6 @@ const mapStateToProps = state => {
return { return {
account: getAccount(state, me), account: getAccount(state, me),
autoPlayGif: getSettings(state).get('autoPlayGif'),
}; };
}; };

Wyświetl plik

@ -24,7 +24,7 @@
background: var(--background-color); background: var(--background-color);
border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0;
img { .still-image {
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -61,7 +61,7 @@
height: 48px; height: 48px;
padding-top: 2px; padding-top: 2px;
img { .still-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block; display: block;

Wyświetl plik

@ -21,7 +21,6 @@
background: var(--accent-color--med); background: var(--accent-color--med);
@media screen and (max-width: 895px) {height: 225px;} @media screen and (max-width: 895px) {height: 225px;}
&--none {height: 125px;} &--none {height: 125px;}
img { img {
object-fit: cover; object-fit: cover;
display: block; display: block;
@ -29,6 +28,23 @@
height: 100%; height: 100%;
margin: 0; margin: 0;
} }
.still-image--play-on-hover::before {
content: 'GIF';
position: absolute;
color: var(--primary-text-color);
background: var(--foreground-color);
top: 6px;
left: 6px;
padding: 2px 6px;
border-radius: 2px;
font-size: 11px;
font-weight: 600;
pointer-events: none;
opacity: 0.9;
transition: opacity 0.1s ease;
line-height: 18px;
}
} }
&__bar { &__bar {
@ -58,6 +74,23 @@
background-size: 200px 200px; background-size: 200px 200px;
} }
.still-image--play-on-hover::before {
content: 'GIF';
position: absolute;
color: var(--primary-text-color);
background: var(--foreground-color);
bottom: 15%;
left: 15%;
padding: 1px 4px;
border-radius: 2px;
font-size: 8px;
font-weight: 600;
pointer-events: none;
opacity: 0.9;
transition: opacity 0.1s ease;
line-height: 13px;
}
@media screen and (max-width: 895px) { @media screen and (max-width: 895px) {
top: -45px; top: -45px;
left: 10px; left: 10px;