Skip to content
Snippets Groups Projects
Commit 59423474 authored by Ondřej Hruška's avatar Ondřej Hruška Committed by Eugen Rochko
Browse files

Refactor Avatar and AvatarOverlay to have 'account' as prop instead of src and staticSrc (#4526)

* Refactored Avatar and AvatarOverlay (DRY) to have 'account' as prop.
Also removed animate attribute from compose navigation bar, which should
have never been there. Added test for avatar overlay.

* fix broken tests

* god dammit another bug in tests! travis please let this pass

* formatting in avatar overlay
parent 22db9472
No related branches found
No related tags found
No related merge requests found
Showing
with 82 additions and 23 deletions
......@@ -70,7 +70,7 @@ export default class Account extends ImmutablePureComponent {
<div className='account'>
<div className='account__wrapper'>
<Permalink key={account.get('id')} className='account__display-name' href={account.get('url')} to={`/accounts/${account.get('id')}`}>
<div className='account__avatar-wrapper'><Avatar src={account.get('avatar')} staticSrc={account.get('avatar_static')} size={36} /></div>
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
<DisplayName account={account} />
</Permalink>
......
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
export default class Avatar extends React.PureComponent {
static propTypes = {
src: PropTypes.string.isRequired,
staticSrc: PropTypes.string,
account: ImmutablePropTypes.map.isRequired,
size: PropTypes.number.isRequired,
style: PropTypes.object,
animate: PropTypes.bool,
......@@ -33,9 +33,12 @@ export default class Avatar extends React.PureComponent {
}
render () {
const { src, size, staticSrc, animate, inline } = this.props;
const { account, size, animate, inline } = this.props;
const { hovering } = this.state;
const src = account.get('avatar');
const staticSrc = account.get('avatar_static');
let className = 'account__avatar';
if (inline) {
......
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
export default class AvatarOverlay extends React.PureComponent {
static propTypes = {
staticSrc: PropTypes.string.isRequired,
overlaySrc: PropTypes.string.isRequired,
account: ImmutablePropTypes.map.isRequired,
friend: ImmutablePropTypes.map.isRequired,
};
render() {
const { staticSrc, overlaySrc } = this.props;
const { account, friend } = this.props;
const baseStyle = {
backgroundImage: `url(${staticSrc})`,
backgroundImage: `url(${account.get('avatar_static')})`,
};
const overlayStyle = {
backgroundImage: `url(${overlaySrc})`,
backgroundImage: `url(${friend.get('avatar_static')})`,
};
return (
......
......@@ -228,9 +228,9 @@ export default class Status extends ImmutablePureComponent {
}
if (account === undefined || account === null) {
statusAvatar = <Avatar src={status.getIn(['account', 'avatar'])} staticSrc={status.getIn(['account', 'avatar_static'])} size={48} />;
statusAvatar = <Avatar account={status.get('account')} size={48} />;
}else{
statusAvatar = <AvatarOverlay staticSrc={status.getIn(['account', 'avatar_static'])} overlaySrc={account.get('avatar_static')} />;
statusAvatar = <AvatarOverlay account={status.get('account')} friend={account} />;
}
return (
......
......@@ -15,7 +15,7 @@ export default class AutosuggestAccount extends ImmutablePureComponent {
return (
<div className='autosuggest-account'>
<div className='autosuggest-account-icon'><Avatar src={account.get('avatar')} staticSrc={account.get('avatar_static')} size={18} /></div>
<div className='autosuggest-account-icon'><Avatar account={account} size={18} /></div>
<DisplayName account={account} />
</div>
);
......
......@@ -19,7 +19,7 @@ export default class NavigationBar extends ImmutablePureComponent {
<div className='navigation-bar'>
<Permalink href={this.props.account.get('url')} to={`/accounts/${this.props.account.get('id')}`}>
<span style={{ display: 'none' }}>{this.props.account.get('acct')}</span>
<Avatar src={this.props.account.get('avatar')} animate size={40} />
<Avatar account={this.props.account} size={40} />
</Permalink>
<div className='navigation-bar__profile'>
......
......@@ -51,7 +51,7 @@ export default class ReplyIndicator extends ImmutablePureComponent {
<div className='reply-indicator__cancel'><IconButton title={intl.formatMessage(messages.cancel)} icon='times' onClick={this.handleClick} /></div>
<a href={status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='reply-indicator__display-name'>
<div className='reply-indicator__display-avatar'><Avatar size={24} src={status.getIn(['account', 'avatar'])} staticSrc={status.getIn(['account', 'avatar_static'])} /></div>
<div className='reply-indicator__display-avatar'><Avatar account={status.get('account')} size={24} /></div>
<DisplayName account={status.get('account')} />
</a>
</div>
......
......@@ -32,7 +32,7 @@ export default class AccountAuthorize extends ImmutablePureComponent {
<div className='account-authorize__wrapper'>
<div className='account-authorize'>
<Permalink href={account.get('url')} to={`/accounts/${account.get('id')}`} className='detailed-status__display-name'>
<div className='account-authorize__avatar'><Avatar src={account.get('avatar')} staticSrc={account.get('avatar_static')} size={48} /></div>
<div className='account-authorize__avatar'><Avatar account={account} size={48} /></div>
<DisplayName account={account} />
</Permalink>
......
......@@ -59,7 +59,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
return (
<div className='detailed-status'>
<a href={status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='detailed-status__display-name'>
<div className='detailed-status__display-avatar'><Avatar src={status.getIn(['account', 'avatar'])} staticSrc={status.getIn(['account', 'avatar_static'])} size={48} /></div>
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={48} /></div>
<DisplayName account={status.get('account')} />
</a>
......
......@@ -46,7 +46,7 @@ export default class ActionsModal extends ImmutablePureComponent {
<a href={this.props.status.getIn(['account', 'url'])} className='status__display-name'>
<div className='status__avatar'>
<Avatar src={this.props.status.getIn(['account', 'avatar'])} staticSrc={this.props.status.getIn(['account', 'avatar_static'])} size={48} />
<Avatar account={this.props.status.get('account')} size={48} />
</div>
<DisplayName account={this.props.status.get('account')} />
......
......@@ -62,7 +62,7 @@ export default class BoostModal extends ImmutablePureComponent {
<a onClick={this.handleAccountClick} href={status.getIn(['account', 'url'])} className='status__display-name'>
<div className='status__avatar'>
<Avatar src={status.getIn(['account', 'avatar'])} staticSrc={status.getIn(['account', 'avatar_static'])} size={48} />
<Avatar account={status.get('account')} size={48} />
</div>
<DisplayName account={status.get('account')} />
......
import { expect } from 'chai';
import { render } from 'enzyme';
import { fromJS } from 'immutable';
import React from 'react';
import Avatar from '../../../app/javascript/mastodon/components/avatar';
describe('<Avatar />', () => {
const src = '/path/to/image.jpg';
const account = fromJS({
username: 'alice',
acct: 'alice',
display_name: 'Alice',
avatar: '/animated/alice.gif',
avatar_static: '/static/alice.jpg',
});
const size = 100;
const wrapper = render(<Avatar src={src} animate size={size} />);
const animated = render(<Avatar account={account} animate size={size} />);
const still = render(<Avatar account={account} size={size} />);
// Autoplay
it('renders a div element with the given src as background', () => {
expect(wrapper.find('div')).to.have.style('background-image', `url(${src})`);
expect(animated.find('div')).to.have.style('background-image', `url(${account.get('avatar')})`);
});
it('renders a div element of the given size', () => {
['width', 'height'].map((attr) => {
expect(wrapper.find('div')).to.have.style(attr, `${size}px`);
expect(animated.find('div')).to.have.style(attr, `${size}px`);
});
});
// Still
it('renders a div element with the given static src as background if not autoplay', () => {
expect(still.find('div')).to.have.style('background-image', `url(${account.get('avatar_static')})`);
});
it('renders a div element of the given size if not autoplay', () => {
['width', 'height'].map((attr) => {
expect(still.find('div')).to.have.style(attr, `${size}px`);
});
});
// TODO add autoplay test if possible
});
import { expect } from 'chai';
import { render } from 'enzyme';
import { fromJS } from 'immutable';
import React from 'react';
import AvatarOverlay from '../../../app/javascript/mastodon/components/avatar_overlay';
describe('<Avatar />', () => {
const account = fromJS({
username: 'alice',
acct: 'alice',
display_name: 'Alice',
avatar: '/animated/alice.gif',
avatar_static: '/static/alice.jpg',
});
const friend = fromJS({
username: 'eve',
acct: 'eve@blackhat.lair',
display_name: 'Evelyn',
avatar: '/animated/eve.gif',
avatar_static: '/static/eve.jpg',
});
const overlay = render(<AvatarOverlay account={account} friend={friend} />);
it('renders account static src as base of overlay avatar', () => {
expect(overlay.find('.account__avatar-overlay-base'))
.to.have.style('background-image', `url(${account.get('avatar_static')})`);
});
it('renders friend static src as overlay of overlay avatar', () => {
expect(overlay.find('.account__avatar-overlay-overlay'))
.to.have.style('background-image', `url(${friend.get('avatar_static')})`);
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment