commit: 383c0b780282e4ca2a9df2086166a576eef0f296
parent: bf8031e984a95827fd50591ea5ae3dbc4c2f004b
Author: kawax <kawaxbiz@gmail.com>
Date: Wed, 3 May 2017 18:43:37 +0900
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
Diffstat:
7 files changed, 97 insertions(+), 15 deletions(-)
diff --git a/app/javascript/mastodon/components/avatar.js b/app/javascript/mastodon/components/avatar.js
@@ -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;
diff --git a/app/javascript/mastodon/components/avatar_overlay.js b/app/javascript/mastodon/components/avatar_overlay.js
@@ -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;
diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js
@@ -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,
diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js
@@ -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>
);
}
diff --git a/app/javascript/styles/_mixins.scss b/app/javascript/styles/_mixins.scss
@@ -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;
+}
diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss
@@ -1,3 +1,4 @@
+@import 'mixins';
@import 'variables';
@import 'fonts/roboto';
@import 'fonts/roboto-mono';
diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss
@@ -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 {