Show boosted user's avatar (#2518)
* Show boosted user's avatar * add .status__avatar-boost * margin * apply to notifications too. * account__avatar-boost * Add inline prop to Avatar component * Add AvatarOverlay component * rename mixins.scss * move files for latest master * fixed for webpack
This commit is contained in:
		
							parent
							
								
									6eaaa3bec5
								
							
						
					
					
						commit
						dd06d92caf
					
				
					 7 changed files with 97 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -25,9 +25,15 @@ class Avatar extends React.PureComponent {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { src, size, staticSrc, animate } = this.props;
 | 
			
		||||
    const { src, size, staticSrc, animate, inline } = this.props;
 | 
			
		||||
    const { hovering } = this.state;
 | 
			
		||||
 | 
			
		||||
    let className = 'account__avatar';
 | 
			
		||||
 | 
			
		||||
    if (inline) {
 | 
			
		||||
      className = className + ' account__avatar-inline';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const style = {
 | 
			
		||||
      ...this.props.style,
 | 
			
		||||
      width: `${size}px`,
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +49,7 @@ class Avatar extends React.PureComponent {
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
      <div
 | 
			
		||||
        className='account__avatar'
 | 
			
		||||
        className={className}
 | 
			
		||||
        onMouseEnter={this.handleMouseEnter}
 | 
			
		||||
        onMouseLeave={this.handleMouseLeave}
 | 
			
		||||
        style={style}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,11 +64,14 @@ Avatar.propTypes = {
 | 
			
		|||
  staticSrc: PropTypes.string,
 | 
			
		||||
  size: PropTypes.number.isRequired,
 | 
			
		||||
  style: PropTypes.object,
 | 
			
		||||
  animate: PropTypes.bool
 | 
			
		||||
  animate: PropTypes.bool,
 | 
			
		||||
  inline: PropTypes.bool
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Avatar.defaultProps = {
 | 
			
		||||
  animate: false
 | 
			
		||||
  animate: false,
 | 
			
		||||
  size: 20,
 | 
			
		||||
  inline: false
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Avatar;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								app/javascript/mastodon/components/avatar_overlay.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/javascript/mastodon/components/avatar_overlay.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
import React from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
 | 
			
		||||
class AvatarOverlay extends React.PureComponent {
 | 
			
		||||
  render() {
 | 
			
		||||
    const {staticSrc, overlaySrc} = this.props;
 | 
			
		||||
 | 
			
		||||
    const baseStyle = {
 | 
			
		||||
      backgroundImage: `url(${staticSrc})`
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const overlayStyle = {
 | 
			
		||||
      backgroundImage: `url(${overlaySrc})`
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className='account__avatar-overlay'>
 | 
			
		||||
        <div className="account__avatar-overlay-base" style={baseStyle} />
 | 
			
		||||
        <div className="account__avatar-overlay-overlay" style={overlayStyle} />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AvatarOverlay.propTypes = {
 | 
			
		||||
  staticSrc: PropTypes.string.isRequired,
 | 
			
		||||
  overlaySrc: PropTypes.string.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default AvatarOverlay;
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ import React from 'react';
 | 
			
		|||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import Avatar from './avatar';
 | 
			
		||||
import AvatarOverlay from './avatar_overlay';
 | 
			
		||||
import RelativeTimestamp from './relative_timestamp';
 | 
			
		||||
import DisplayName from './display_name';
 | 
			
		||||
import MediaGallery from './media_gallery';
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,8 @@ class Status extends ImmutablePureComponent {
 | 
			
		|||
 | 
			
		||||
  render () {
 | 
			
		||||
    let media = '';
 | 
			
		||||
    const { status, ...other } = this.props;
 | 
			
		||||
    let statusAvatar;
 | 
			
		||||
    const { status, account, ...other } = this.props;
 | 
			
		||||
 | 
			
		||||
    if (status === null) {
 | 
			
		||||
      return <div />;
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +60,7 @@ class Status extends ImmutablePureComponent {
 | 
			
		|||
            <FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name: <a onClick={this.handleAccountClick.bind(this, status.getIn(['account', 'id']))} href={status.getIn(['account', 'url'])} className='status__display-name muted'><strong dangerouslySetInnerHTML={displayNameHTML} /></a> }} />
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <Status {...other} wrapped={true} status={status.get('reblog')} />
 | 
			
		||||
          <Status {...other} wrapped={true} status={status.get('reblog')} account={status.get('account')} />
 | 
			
		||||
        </div>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +75,12 @@ class Status extends ImmutablePureComponent {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (account === undefined || account === null) {
 | 
			
		||||
      statusAvatar = <Avatar src={status.getIn(['account', 'avatar'])} staticSrc={status.getIn(['account', 'avatar_static'])} size={48}/>;
 | 
			
		||||
    }else{
 | 
			
		||||
      statusAvatar = <AvatarOverlay staticSrc={status.getIn(['account', 'avatar_static'])} overlaySrc={account.get('avatar_static')} />;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className={this.props.muted ? 'status muted' : 'status'}>
 | 
			
		||||
        <div className='status__info'>
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +90,7 @@ class Status extends ImmutablePureComponent {
 | 
			
		|||
 | 
			
		||||
          <a onClick={this.handleAccountClick.bind(this, status.getIn(['account', 'id']))} 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} />
 | 
			
		||||
              {statusAvatar}
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <DisplayName account={status.get('account')} />
 | 
			
		||||
| 
						 | 
				
			
			@ -106,6 +114,7 @@ Status.contextTypes = {
 | 
			
		|||
 | 
			
		||||
Status.propTypes = {
 | 
			
		||||
  status: ImmutablePropTypes.map,
 | 
			
		||||
  account: ImmutablePropTypes.map,
 | 
			
		||||
  wrapped: PropTypes.bool,
 | 
			
		||||
  onReply: PropTypes.func,
 | 
			
		||||
  onFavourite: PropTypes.func,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ import React from 'react';
 | 
			
		|||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import StatusContainer from '../../../containers/status_container';
 | 
			
		||||
import AccountContainer from '../../../containers/account_container';
 | 
			
		||||
import Avatar from '../../../components/avatar';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
import Permalink from '../../../components/permalink';
 | 
			
		||||
import emojify from '../../../emoji';
 | 
			
		||||
| 
						 | 
				
			
			@ -37,11 +38,10 @@ class Notification extends ImmutablePureComponent {
 | 
			
		|||
          <div className='notification__favourite-icon-wrapper'>
 | 
			
		||||
            <i className='fa fa-fw fa-star star-icon'/>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <FormattedMessage id='notification.favourite' defaultMessage='{name} favourited your status' values={{ name: link }} />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <StatusContainer id={notification.get('status')} muted={true} />
 | 
			
		||||
        <StatusContainer id={notification.get('status')} account={notification.get('account')} muted={true} />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -53,11 +53,10 @@ class Notification extends ImmutablePureComponent {
 | 
			
		|||
          <div className='notification__favourite-icon-wrapper'>
 | 
			
		||||
            <i className='fa fa-fw fa-retweet' />
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <FormattedMessage id='notification.reblog' defaultMessage='{name} boosted your status' values={{ name: link }} />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <StatusContainer id={notification.get('status')} muted={true} />
 | 
			
		||||
        <StatusContainer id={notification.get('status')} account={notification.get('account')} muted={true} />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								app/javascript/styles/_mixins.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/javascript/styles/_mixins.scss
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
@mixin avatar-radius() {
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
  background: transparent no-repeat;
 | 
			
		||||
  background-position: 50%;
 | 
			
		||||
  background-clip: padding-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin avatar-size($size:48px) {
 | 
			
		||||
  width: $size;
 | 
			
		||||
  height: $size;
 | 
			
		||||
  background-size: $size $size;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
@import 'mixins';
 | 
			
		||||
@import 'variables';
 | 
			
		||||
@import 'fonts/roboto';
 | 
			
		||||
@import 'fonts/roboto-mono';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -673,11 +673,33 @@ a.status__content__spoiler-link {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
.account__avatar {
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
  background: transparent no-repeat;
 | 
			
		||||
  background-position: 50%;
 | 
			
		||||
  background-clip: padding-box;
 | 
			
		||||
  @include avatar-radius();
 | 
			
		||||
  position: relative;
 | 
			
		||||
 | 
			
		||||
  &-inline {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account__avatar-overlay {
 | 
			
		||||
  @include avatar-size(48px);
 | 
			
		||||
 | 
			
		||||
  &-base {
 | 
			
		||||
    @include avatar-radius();
 | 
			
		||||
    @include avatar-size(36px);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-overlay {
 | 
			
		||||
    @include avatar-radius();
 | 
			
		||||
    @include avatar-size(24px);
 | 
			
		||||
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account__relationship {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue