Browse Source

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
tags/v1.4rc1
kawax 2 years ago
parent
commit
383c0b7802
7 changed files with 97 additions and 15 deletions
  1. +13
    -4
      app/javascript/mastodon/components/avatar.js
  2. +30
    -0
      app/javascript/mastodon/components/avatar_overlay.js
  3. +12
    -3
      app/javascript/mastodon/components/status.js
  4. +3
    -4
      app/javascript/mastodon/features/notifications/components/notification.js
  5. +12
    -0
      app/javascript/styles/_mixins.scss
  6. +1
    -0
      app/javascript/styles/application.scss
  7. +26
    -4
      app/javascript/styles/components.scss

+ 13
- 4
app/javascript/mastodon/components/avatar.js View File

@@ -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
- 0
app/javascript/mastodon/components/avatar_overlay.js View 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;

+ 12
- 3
app/javascript/mastodon/components/status.js View File

@@ -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,

+ 3
- 4
app/javascript/mastodon/features/notifications/components/notification.js View File

@@ -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
- 0
app/javascript/styles/_mixins.scss View 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
- 0
app/javascript/styles/application.scss View File

@@ -1,3 +1,4 @@
@import 'mixins';
@import 'variables';
@import 'fonts/roboto';
@import 'fonts/roboto-mono';

+ 26
- 4
app/javascript/styles/components.scss View File

@@ -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…
Cancel
Save