From cbc50016eb3d0a46e76aca9ed199b036ce20abdb Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 23 Nov 2016 23:34:12 +0100 Subject: [PATCH] Follow/unfollow button outside of dropdown, also make favs/reblogs update indicator instantly and then adjust to failure later if the request fails --- .../components/components/button.jsx | 19 +++++++++----- .../account/components/action_bar.jsx | 2 -- .../features/account/components/header.jsx | 25 ++++++++++++++++--- .../components/features/account/index.jsx | 5 ++-- .../components/reducers/statuses.jsx | 12 +++++++++ 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/app/assets/javascripts/components/components/button.jsx b/app/assets/javascripts/components/components/button.jsx index fe36d40c53..d631290131 100644 --- a/app/assets/javascripts/components/components/button.jsx +++ b/app/assets/javascripts/components/components/button.jsx @@ -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 ( - ); diff --git a/app/assets/javascripts/components/features/account/components/action_bar.jsx b/app/assets/javascripts/components/features/account/components/action_bar.jsx index cd01de2e20..f09dea6abf 100644 --- a/app/assets/javascripts/components/features/account/components/action_bar.jsx +++ b/app/assets/javascripts/components/features/account/components/action_bar.jsx @@ -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 }); } diff --git a/app/assets/javascripts/components/features/account/components/header.jsx b/app/assets/javascripts/components/features/account/components/header.jsx index b3e9e2a9f7..d39a060620 100644 --- a/app/assets/javascripts/components/features/account/components/header.jsx +++ b/app/assets/javascripts/components/features/account/components/header.jsx @@ -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 = } + if (me !== account.get('id')) { + actionBtn = ( +
+ +
+ ); + } + const content = { __html: emojify(account.get('note')) }; const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) }; @@ -45,6 +61,7 @@ const Header = React.createClass({
{info} + {actionBtn}
); @@ -52,4 +69,4 @@ const Header = React.createClass({ }); -export default Header; +export default injectIntl(Header); diff --git a/app/assets/javascripts/components/features/account/index.jsx b/app/assets/javascripts/components/features/account/index.jsx index 818979f8f5..c2cc58bb29 100644 --- a/app/assets/javascripts/components/features/account/index.jsx +++ b/app/assets/javascripts/components/features/account/index.jsx @@ -87,9 +87,8 @@ const Account = React.createClass({ return ( -
- - +
+ {this.props.children} diff --git a/app/assets/javascripts/components/reducers/statuses.jsx b/app/assets/javascripts/components/reducers/statuses.jsx index f42b1a4818..c740b6d64a 100644 --- a/app/assets/javascripts/components/reducers/statuses.jsx +++ b/app/assets/javascripts/components/reducers/statuses.jsx @@ -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: