Follow/unfollow button outside of dropdown, also make favs/reblogs update indicator instantly and
then adjust to failure later if the request fails
This commit is contained in:
parent
7cee27f517
commit
cbc50016eb
|
@ -7,7 +7,14 @@ const Button = React.createClass({
|
|||
onClick: React.PropTypes.func,
|
||||
disabled: React.PropTypes.bool,
|
||||
block: React.PropTypes.bool,
|
||||
secondary: React.PropTypes.bool
|
||||
secondary: React.PropTypes.bool,
|
||||
size: React.PropTypes.number,
|
||||
},
|
||||
|
||||
getDefaultProps () {
|
||||
return {
|
||||
size: 36
|
||||
};
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
|
@ -32,16 +39,16 @@ const Button = React.createClass({
|
|||
fontWeight: '500',
|
||||
letterSpacing: '0',
|
||||
textTransform: 'uppercase',
|
||||
padding: '0 16px',
|
||||
height: '36px',
|
||||
padding: `0 ${this.props.size / 2.25}px`,
|
||||
height: `${this.props.size}px`,
|
||||
cursor: 'pointer',
|
||||
lineHeight: '36px',
|
||||
lineHeight: `${this.props.size}px`,
|
||||
borderRadius: '4px',
|
||||
textDecoration: 'none'
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<button className={`button ${this.props.secondary ? 'button-secondary' : ''}`} disabled={this.props.disabled} onClick={this.handleClick} style={style}>
|
||||
<button className={`button ${this.props.secondary ? 'button-secondary' : ''}`} disabled={this.props.disabled} onClick={this.handleClick} style={{ ...style, ...this.props.style }}>
|
||||
{this.props.text || this.props.children}
|
||||
</button>
|
||||
);
|
||||
|
|
|
@ -58,10 +58,8 @@ const ActionBar = React.createClass({
|
|||
} else if (account.getIn(['relationship', 'blocking'])) {
|
||||
menu.push({ text: intl.formatMessage(messages.unblock), action: this.props.onBlock });
|
||||
} else if (account.getIn(['relationship', 'following'])) {
|
||||
menu.push({ text: intl.formatMessage(messages.unfollow), action: this.props.onFollow });
|
||||
menu.push({ text: intl.formatMessage(messages.block), action: this.props.onBlock });
|
||||
} else {
|
||||
menu.push({ text: intl.formatMessage(messages.follow), action: this.props.onFollow });
|
||||
menu.push({ text: intl.formatMessage(messages.block), action: this.props.onBlock });
|
||||
}
|
||||
|
||||
|
|
|
@ -2,22 +2,30 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import emojify from '../../../emoji';
|
||||
import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import IconButton from '../../../components/icon_button';
|
||||
|
||||
const messages = defineMessages({
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
});
|
||||
|
||||
const Header = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
me: React.PropTypes.number.isRequired
|
||||
me: React.PropTypes.number.isRequired,
|
||||
onFollow: React.PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
render () {
|
||||
const { account, me } = this.props;
|
||||
const { account, me, intl } = this.props;
|
||||
|
||||
let displayName = account.get('display_name');
|
||||
let info = '';
|
||||
let actionBtn = '';
|
||||
|
||||
if (displayName.length === 0) {
|
||||
displayName = account.get('username');
|
||||
|
@ -27,6 +35,14 @@ const Header = React.createClass({
|
|||
info = <span style={{ position: 'absolute', top: '10px', right: '10px', opacity: '0.7', display: 'inline-block', verticalAlign: 'top', background: 'rgba(0, 0, 0, 0.4)', color: '#fff', textTransform: 'uppercase', fontSize: '11px', fontWeight: '500', padding: '4px', borderRadius: '4px' }}><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>
|
||||
}
|
||||
|
||||
if (me !== account.get('id')) {
|
||||
actionBtn = (
|
||||
<div style={{ position: 'absolute', top: '10px', left: '20px' }}>
|
||||
<IconButton size={26} icon={account.getIn(['relationship', 'following']) ? 'user-times' : 'user-plus'} active={account.getIn(['relationship', 'following'])} title={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const content = { __html: emojify(account.get('note')) };
|
||||
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
|
||||
|
||||
|
@ -45,6 +61,7 @@ const Header = React.createClass({
|
|||
<div style={{ color: '#616b86', fontSize: '14px' }} className='account__header__content' dangerouslySetInnerHTML={content} />
|
||||
|
||||
{info}
|
||||
{actionBtn}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -52,4 +69,4 @@ const Header = React.createClass({
|
|||
|
||||
});
|
||||
|
||||
export default Header;
|
||||
export default injectIntl(Header);
|
||||
|
|
|
@ -87,9 +87,8 @@ const Account = React.createClass({
|
|||
return (
|
||||
<Column>
|
||||
<ColumnBackButton />
|
||||
<Header account={account} me={me} />
|
||||
|
||||
<ActionBar account={account} me={me} onFollow={this.handleFollow} onBlock={this.handleBlock} onMention={this.handleMention} />
|
||||
<Header account={account} me={me} onFollow={this.handleFollow} />
|
||||
<ActionBar account={account} me={me} onBlock={this.handleBlock} onMention={this.handleMention} />
|
||||
|
||||
{this.props.children}
|
||||
</Column>
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import {
|
||||
REBLOG_REQUEST,
|
||||
REBLOG_SUCCESS,
|
||||
REBLOG_FAIL,
|
||||
UNREBLOG_SUCCESS,
|
||||
FAVOURITE_REQUEST,
|
||||
FAVOURITE_SUCCESS,
|
||||
FAVOURITE_FAIL,
|
||||
UNFAVOURITE_SUCCESS
|
||||
} from '../actions/interactions';
|
||||
import {
|
||||
|
@ -82,6 +86,14 @@ export default function statuses(state = initialState, action) {
|
|||
case FAVOURITE_SUCCESS:
|
||||
case UNFAVOURITE_SUCCESS:
|
||||
return normalizeStatus(state, action.response);
|
||||
case FAVOURITE_REQUEST:
|
||||
return state.setIn([action.status.get('id'), 'favourited'], true);
|
||||
case FAVOURITE_FAIL:
|
||||
return state.setIn([action.status.get('id'), 'favourited'], false);
|
||||
case REBLOG_REQUEST:
|
||||
return state.setIn([action.status.get('id'), 'reblogged'], true);
|
||||
case REBLOG_FAIL:
|
||||
return state.setIn([action.status.get('id'), 'reblogged'], false);
|
||||
case TIMELINE_REFRESH_SUCCESS:
|
||||
case TIMELINE_EXPAND_SUCCESS:
|
||||
case ACCOUNT_TIMELINE_FETCH_SUCCESS:
|
||||
|
|
Reference in a new issue