Break out nested relationship API keys (#5887)

* Break out nested relationship API keys

This closes #5856 by restoring the existing behavior of the `muting`
and `following` keys (returning booleans rather than truthy or false).
It adds `showing_reblogs` and `muting_notifications` keys:

* `showing_reblogs` returns true if:
  1. You've requested to follow the user, with reblogs shown, or
  2. You are following the user, with reblogs shown.
* `muting_notifications` returns true if you have muted the user and
  their notifications as well.

* Rubocop fix

* Fix pulling reblog/mute status from relationships

I could swear this had passed tests before, but apparently not.
Works now.

* More test fixes

Really, you'd expect this to be more straightforward.
remotes/1727458204337373841/tmp_refs/heads/signup-info-prompt
aschmitz 2017-12-06 09:10:54 -06:00 committed by Eugen Rochko
parent 063a1c2a8b
commit 4de211b80a
6 changed files with 28 additions and 17 deletions

View File

@ -81,7 +81,7 @@ export default class Account extends ImmutablePureComponent {
buttons = <IconButton active icon='unlock-alt' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />; buttons = <IconButton active icon='unlock-alt' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
} else if (muting) { } else if (muting) {
let hidingNotificationsButton; let hidingNotificationsButton;
if (muting.get('notifications')) { if (account.getIn(['relationship', 'muting_notifications'])) {
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />; hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />;
} else { } else {
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />; hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />;
@ -93,7 +93,7 @@ export default class Account extends ImmutablePureComponent {
</div> </div>
); );
} else { } else {
buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following ? true : false} />; buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />;
} }
} }

View File

@ -63,9 +63,8 @@ export default class ActionBar extends React.PureComponent {
if (account.get('id') === me) { if (account.get('id') === me) {
menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' });
} else { } else {
const following = account.getIn(['relationship', 'following']); if (account.getIn(['relationship', 'following'])) {
if (following) { if (account.getIn(['relationship', 'showing_reblogs'])) {
if (following.get('reblogs')) {
menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); menu.push({ text: intl.formatMessage(messages.hideReblogs, { name: account.get('username') }), action: this.props.onReblogToggle });
} else { } else {
menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle });

View File

@ -68,7 +68,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
}, },
onReblogToggle (account) { onReblogToggle (account) {
if (account.getIn(['relationship', 'following', 'reblogs'])) { if (account.getIn(['relationship', 'show_reblogs'])) {
dispatch(followAccount(account.get('id'), false)); dispatch(followAccount(account.get('id'), false));
} else { } else {
dispatch(followAccount(account.get('id'), true)); dispatch(followAccount(account.get('id'), true));

View File

@ -1,15 +1,21 @@
# frozen_string_literal: true # frozen_string_literal: true
class REST::RelationshipSerializer < ActiveModel::Serializer class REST::RelationshipSerializer < ActiveModel::Serializer
attributes :id, :following, :followed_by, :blocking, attributes :id, :following, :showing_reblogs, :followed_by, :blocking,
:muting, :requested, :domain_blocking :muting, :muting_notifications, :requested, :domain_blocking
def id def id
object.id.to_s object.id.to_s
end end
def following def following
instance_options[:relationships].following[object.id] || false instance_options[:relationships].following[object.id] ? true : false
end
def showing_reblogs
(instance_options[:relationships].following[object.id] || {})[:reblogs] ||
(instance_options[:relationships].requested[object.id] || {})[:reblogs] ||
false
end end
def followed_by def followed_by
@ -21,11 +27,15 @@ class REST::RelationshipSerializer < ActiveModel::Serializer
end end
def muting def muting
instance_options[:relationships].muting[object.id] || false instance_options[:relationships].muting[object.id] ? true : false
end
def muting_notifications
(instance_options[:relationships].muting[object.id] || {})[:notifications] || false
end end
def requested def requested
instance_options[:relationships].requested[object.id] || false instance_options[:relationships].requested[object.id] ? true : false
end end
def domain_blocking def domain_blocking

View File

@ -32,7 +32,7 @@ describe Api::V1::Accounts::RelationshipsController do
json = body_as_json json = body_as_json
expect(json).to be_a Enumerable expect(json).to be_a Enumerable
expect(json.first[:following]).to be_truthy expect(json.first[:following]).to be true
expect(json.first[:followed_by]).to be false expect(json.first[:followed_by]).to be false
end end
end end
@ -51,7 +51,8 @@ describe Api::V1::Accounts::RelationshipsController do
expect(json).to be_a Enumerable expect(json).to be_a Enumerable
expect(json.first[:id]).to eq simon.id.to_s expect(json.first[:id]).to eq simon.id.to_s
expect(json.first[:following]).to be_truthy expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
expect(json.first[:followed_by]).to be false expect(json.first[:followed_by]).to be false
expect(json.first[:muting]).to be false expect(json.first[:muting]).to be false
expect(json.first[:requested]).to be false expect(json.first[:requested]).to be false
@ -59,6 +60,7 @@ describe Api::V1::Accounts::RelationshipsController do
expect(json.second[:id]).to eq lewis.id.to_s expect(json.second[:id]).to eq lewis.id.to_s
expect(json.second[:following]).to be false expect(json.second[:following]).to be false
expect(json.second[:showing_reblogs]).to be false
expect(json.second[:followed_by]).to be true expect(json.second[:followed_by]).to be true
expect(json.second[:muting]).to be false expect(json.second[:muting]).to be false
expect(json.second[:requested]).to be false expect(json.second[:requested]).to be false

View File

@ -31,10 +31,10 @@ RSpec.describe Api::V1::AccountsController, type: :controller do
expect(response).to have_http_status(:success) expect(response).to have_http_status(:success)
end end
it 'returns JSON with following=truthy and requested=false' do it 'returns JSON with following=true and requested=false' do
json = body_as_json json = body_as_json
expect(json[:following]).to be_truthy expect(json[:following]).to be true
expect(json[:requested]).to be false expect(json[:requested]).to be false
end end
@ -50,11 +50,11 @@ RSpec.describe Api::V1::AccountsController, type: :controller do
expect(response).to have_http_status(:success) expect(response).to have_http_status(:success)
end end
it 'returns JSON with following=false and requested=truthy' do it 'returns JSON with following=false and requested=true' do
json = body_as_json json = body_as_json
expect(json[:following]).to be false expect(json[:following]).to be false
expect(json[:requested]).to be_truthy expect(json[:requested]).to be true
end end
it 'creates a follow request relation between user and target user' do it 'creates a follow request relation between user and target user' do