kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Handle autoPlayGif for avatars and banners
rodzic
e19f350111
commit
52f3f8ce8d
|
@ -1,54 +1,25 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
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 => ({
|
||||
animate: getSettings(state).get('autoPlayGif'),
|
||||
});
|
||||
|
||||
export class Avatar extends React.PureComponent {
|
||||
export default class Avatar extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
size: PropTypes.number,
|
||||
style: PropTypes.object,
|
||||
inline: PropTypes.bool,
|
||||
animate: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
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() {
|
||||
const { account, size, animate, inline } = this.props;
|
||||
const { account, size, inline } = this.props;
|
||||
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
|
||||
const style = !size ? {} : {
|
||||
|
@ -56,22 +27,14 @@ export class Avatar extends React.PureComponent {
|
|||
height: `${size}px`,
|
||||
};
|
||||
|
||||
if (hovering || animate) {
|
||||
style.backgroundImage = `url(${src})`;
|
||||
} else {
|
||||
style.backgroundImage = `url(${staticSrc})`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
<StillImage
|
||||
className={classNames('account__avatar', { 'account__avatar-inline': inline })}
|
||||
style={style}
|
||||
src={account.get('avatar')}
|
||||
alt=''
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Avatar);
|
||||
|
|
|
@ -1,24 +1,16 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
animate: getSettings(state).get('autoPlayGif'),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
class AvatarComposite extends React.PureComponent {
|
||||
export default class AvatarComposite extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
accounts: ImmutablePropTypes.list.isRequired,
|
||||
animate: PropTypes.bool,
|
||||
size: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
renderItem(account, size, index) {
|
||||
const { animate } = this.props;
|
||||
|
||||
let width = 50;
|
||||
let height = 100;
|
||||
|
@ -76,12 +68,10 @@ class AvatarComposite extends React.PureComponent {
|
|||
bottom: bottom,
|
||||
width: `${width}%`,
|
||||
height: `${height}%`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
|
||||
};
|
||||
|
||||
return (
|
||||
<div key={account.get('id')} style={style} />
|
||||
<StillImage key={account.get('id')} src={account.get('avatar')} style={style} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,40 +1,23 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
animate: getSettings(state).get('autoPlayGif'),
|
||||
});
|
||||
|
||||
export class AvatarOverlay extends React.PureComponent {
|
||||
export default class AvatarOverlay extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
friend: ImmutablePropTypes.map.isRequired,
|
||||
animate: PropTypes.bool,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { account, friend, animate } = this.props;
|
||||
|
||||
const baseStyle = {
|
||||
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
|
||||
};
|
||||
|
||||
const overlayStyle = {
|
||||
backgroundImage: `url(${friend.get(animate ? 'avatar' : 'avatar_static')})`,
|
||||
};
|
||||
const { account, friend } = this.props;
|
||||
|
||||
return (
|
||||
<div className='account__avatar-overlay'>
|
||||
<div className='account__avatar-overlay-base' style={baseStyle} />
|
||||
<div className='account__avatar-overlay-overlay' style={overlayStyle} />
|
||||
<StillImage src={account.get('avatar')} className='account__avatar-overlay-base' />
|
||||
<StillImage src={friend.get('avatar')} className='account__avatar-overlay-overlay' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(AvatarOverlay);
|
||||
|
|
|
@ -27,7 +27,7 @@ class StillImage extends React.PureComponent {
|
|||
|
||||
hoverToPlay() {
|
||||
const { autoPlayGif, src } = this.props;
|
||||
return !autoPlayGif && src.endsWith('.gif');
|
||||
return !autoPlayGif && (src.endsWith('.gif') || src.startsWith('blob:'));
|
||||
}
|
||||
|
||||
setCanvasRef = c => {
|
||||
|
|
|
@ -16,7 +16,7 @@ import { NavLink } from 'react-router-dom';
|
|||
import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container';
|
||||
import ProfileInfoPanel from '../../ui/components/profile_info_panel';
|
||||
import { debounce } from 'lodash';
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
|
||||
const messages = defineMessages({
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
|
@ -54,7 +54,6 @@ const mapStateToProps = state => {
|
|||
return {
|
||||
me,
|
||||
isStaff: isStaff(state.getIn(['accounts', me])),
|
||||
autoPlayGif: getSettings(state).get('autoPlayGif'),
|
||||
version: parseVersion(state.getIn(['instance', 'version'])),
|
||||
};
|
||||
};
|
||||
|
@ -70,7 +69,6 @@ class Header extends ImmutablePureComponent {
|
|||
onBlock: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
username: PropTypes.string,
|
||||
autoPlayGif: PropTypes.bool,
|
||||
isStaff: PropTypes.bool.isRequired,
|
||||
version: PropTypes.object,
|
||||
};
|
||||
|
@ -226,7 +224,7 @@ class Header extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { account, intl, username, me, autoPlayGif } = this.props;
|
||||
const { account, intl, username, me } = this.props;
|
||||
const { isSmallScreen } = this.state;
|
||||
|
||||
if (!account) {
|
||||
|
@ -252,8 +250,7 @@ class Header extends ImmutablePureComponent {
|
|||
const actionBtn = this.getActionBtn();
|
||||
const menu = this.makeMenu();
|
||||
|
||||
const headerImgSrc = autoPlayGif ? account.get('header') : account.get('header_static');
|
||||
const headerMissing = (headerImgSrc.indexOf('/headers/original/missing.png') > -1);
|
||||
const headerMissing = (account.get('header').indexOf('/headers/original/missing.png') > -1);
|
||||
|
||||
const avatarSize = isSmallScreen ? 90 : 200;
|
||||
|
||||
|
@ -264,7 +261,7 @@ class Header extends ImmutablePureComponent {
|
|||
{info}
|
||||
</div>
|
||||
|
||||
<img src={headerImgSrc} alt='' className='parallax' />
|
||||
<StillImage src={account.get('header')} alt='' className='parallax' />
|
||||
</div>
|
||||
|
||||
<div className='account__header__bar'>
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { acctFull } from 'soapbox/utils/accounts';
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
|
||||
const ProfilePreview = ({ account }) => (
|
||||
<div className='card h-card'>
|
||||
<a target='_blank' rel='noopener' href={account.get('url')}>
|
||||
<div className='card__img'>
|
||||
<img alt='' src={account.get('header')} />
|
||||
<StillImage alt='' src={account.get('header')} />
|
||||
</div>
|
||||
<div className='card__bar'>
|
||||
<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 className='display-name'>
|
||||
<span style={{ display: 'none' }}>{account.get('username')}</span>
|
||||
|
|
|
@ -9,7 +9,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
|||
import Avatar from 'soapbox/components/avatar';
|
||||
import { shortNumberFormat } from 'soapbox/utils/numbers';
|
||||
import { acctFull } from 'soapbox/utils/accounts';
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
|
||||
class UserPanel extends ImmutablePureComponent {
|
||||
|
||||
|
@ -20,7 +20,7 @@ class UserPanel extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { account, intl, domain, autoPlayGif } = this.props;
|
||||
const { account, intl, domain } = this.props;
|
||||
if (!account) return null;
|
||||
const displayNameHtml = { __html: account.get('display_name_html') };
|
||||
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__header'>
|
||||
<img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' />
|
||||
<StillImage src={account.get('header')} alt='' />
|
||||
</div>
|
||||
|
||||
<div className='user-panel__profile'>
|
||||
|
@ -91,7 +91,6 @@ const mapStateToProps = state => {
|
|||
|
||||
return {
|
||||
account: getAccount(state, me),
|
||||
autoPlayGif: getSettings(state).get('autoPlayGif'),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
background: var(--background-color);
|
||||
border-radius: 4px 4px 0 0;
|
||||
|
||||
img {
|
||||
.still-image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -61,7 +61,7 @@
|
|||
height: 48px;
|
||||
padding-top: 2px;
|
||||
|
||||
img {
|
||||
.still-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
background: var(--accent-color--med);
|
||||
@media screen and (max-width: 895px) {height: 225px;}
|
||||
&--none {height: 125px;}
|
||||
|
||||
img {
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
|
@ -29,6 +28,23 @@
|
|||
height: 100%;
|
||||
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 {
|
||||
|
@ -58,6 +74,23 @@
|
|||
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) {
|
||||
top: -45px;
|
||||
left: 10px;
|
||||
|
|
Ładowanie…
Reference in New Issue