Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve blocked view of profiles #10491

Merged
merged 3 commits into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ def set_account
end

def load_accounts
return [] if @account.user_hides_network? && current_account.id != @account.id
return [] if hide_results?

default_accounts.merge(paginated_follows).to_a
end

def hide_results?
(@account.user_hides_network? && current_account.id != @account.id) || (current_account && @account.blocking?(current_account))
end

def default_accounts
Account.without_blocking(current_account).includes(:active_relationships, :account_stat).references(:active_relationships)
Account.includes(:active_relationships, :account_stat).references(:active_relationships)
end

def paginated_follows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ def set_account
end

def load_accounts
return [] if @account.user_hides_network? && current_account.id != @account.id
return [] if hide_results?

default_accounts.merge(paginated_follows).to_a
end

def hide_results?
(@account.user_hides_network? && current_account.id != @account.id) || (current_account && @account.blocking?(current_account))
end

def default_accounts
Account.without_blocking(current_account).includes(:passive_relationships, :account_stat).references(:passive_relationships)
Account.includes(:passive_relationships, :account_stat).references(:passive_relationships)
end

def paginated_follows
Expand Down
10 changes: 0 additions & 10 deletions app/controllers/api/v1/accounts/statuses_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
class Api::V1::Accounts::StatusesController < Api::BaseController
before_action -> { authorize_if_got_token! :read, :'read:statuses' }
before_action :set_account
before_action :check_account_suspension
before_action :check_account_block
after_action :insert_pagination_headers

respond_to :json
Expand All @@ -20,14 +18,6 @@ def set_account
@account = Account.find(params[:account_id])
end

def check_account_suspension
gone if @account.suspended?
end

def check_account_block
gone if current_account.present? && @account.blocking?(current_account)
end

def load_statuses
cached_account_statuses
end
Expand Down
5 changes: 0 additions & 5 deletions app/controllers/api/v1/accounts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class Api::V1::AccountsController < Api::BaseController
before_action :require_user!, except: [:show, :create]
before_action :set_account, except: [:create]
before_action :check_account_suspension, only: [:show]
before_action :check_account_block, only: [:show]
before_action :check_enabled_registrations, only: [:create]

respond_to :json
Expand Down Expand Up @@ -76,10 +75,6 @@ def check_account_suspension
gone if @account.suspended?
end

def check_account_block
gone if current_account.present? && @account.blocking?(current_account)
end

def account_params
params.permit(:username, :email, :password, :agreement, :locale)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def load_accounts

def default_accounts
Account
.without_blocking(current_account)
.includes(:favourites, :account_stat)
.references(:favourites)
.where(favourites: { status_id: @status.id })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def load_accounts
end

def default_accounts
Account.without_blocking(current_account).includes(:statuses, :account_stat).references(:statuses)
Account.includes(:statuses, :account_stat).references(:statuses)
end

def paginated_statuses
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/stream_entries_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def account_action_button(account)
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.unfollow')])
end
elsif !(account.memorial? || account.moved?)
link_to account_follow_path(account), class: 'button logo-button', data: { method: :post } do
link_to account_follow_path(account), class: "button logo-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post } do
safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.follow')])
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class Header extends ImmutablePureComponent {
} else if (account.getIn(['relationship', 'requested'])) {
actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />;
} else if (!account.getIn(['relationship', 'blocking'])) {
actionBtn = <Button className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />;
actionBtn = <Button disabled={account.getIn(['relationship', 'blocked_by'])} className={classNames('logo-button', { 'button--destructive': account.getIn(['relationship', 'following']) })} text={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />;
} else if (account.getIn(['relationship', 'blocking'])) {
actionBtn = <Button className='logo-button' text={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />;
}
Expand Down
22 changes: 16 additions & 6 deletions app/javascript/mastodon/features/account_timeline/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl';
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs';

const emptyList = ImmutableList();

const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => {
const path = withReplies ? `${accountId}:with_replies` : accountId;

return {
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()),
featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], ImmutableList()),
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList),
featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], emptyList),
isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']),
hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']),
blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false),
};
};

Expand All @@ -37,26 +40,31 @@ class AccountTimeline extends ImmutablePureComponent {
isLoading: PropTypes.bool,
hasMore: PropTypes.bool,
withReplies: PropTypes.bool,
blockedBy: PropTypes.bool,
};

componentWillMount () {
const { params: { accountId }, withReplies } = this.props;

this.props.dispatch(fetchAccount(accountId));
this.props.dispatch(fetchAccountIdentityProofs(accountId));

if (!withReplies) {
this.props.dispatch(expandAccountFeaturedTimeline(accountId));
}

this.props.dispatch(expandAccountTimeline(accountId, { withReplies }));
}

componentWillReceiveProps (nextProps) {
if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) {
this.props.dispatch(fetchAccount(nextProps.params.accountId));
this.props.dispatch(fetchAccountIdentityProofs(nextProps.params.accountId));

if (!nextProps.withReplies) {
this.props.dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId));
}

this.props.dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies }));
}
}
Expand All @@ -66,7 +74,7 @@ class AccountTimeline extends ImmutablePureComponent {
}

render () {
const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore } = this.props;
const { shouldUpdateScroll, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy } = this.props;

if (!statusIds && isLoading) {
return (
Expand All @@ -76,6 +84,8 @@ class AccountTimeline extends ImmutablePureComponent {
);
}

const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' /> : <FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />;

return (
<Column>
<ColumnBackButton />
Expand All @@ -84,13 +94,13 @@ class AccountTimeline extends ImmutablePureComponent {
prepend={<HeaderContainer accountId={this.props.params.accountId} />}
alwaysPrepend
scrollKey='account_timeline'
statusIds={statusIds}
statusIds={blockedBy ? emptyList : statusIds}
featuredStatusIds={featuredStatusIds}
isLoading={isLoading}
hasMore={hasMore}
onLoadMore={this.handleLoadMore}
shouldUpdateScroll={shouldUpdateScroll}
emptyMessage={<FormattedMessage id='empty_column.account_timeline' defaultMessage='No toots here!' />}
emptyMessage={emptyMessage}
/>
</Column>
);
Expand Down
8 changes: 5 additions & 3 deletions app/javascript/mastodon/features/followers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ScrollableList from '../../components/scrollable_list';
const mapStateToProps = (state, props) => ({
accountIds: state.getIn(['user_lists', 'followers', props.params.accountId, 'items']),
hasMore: !!state.getIn(['user_lists', 'followers', props.params.accountId, 'next']),
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
});

export default @connect(mapStateToProps)
Expand All @@ -31,6 +32,7 @@ class Followers extends ImmutablePureComponent {
shouldUpdateScroll: PropTypes.func,
accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool,
blockedBy: PropTypes.bool,
};

componentWillMount () {
Expand All @@ -50,7 +52,7 @@ class Followers extends ImmutablePureComponent {
}, 300, { leading: true });

render () {
const { shouldUpdateScroll, accountIds, hasMore } = this.props;
const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props;

if (!accountIds) {
return (
Expand All @@ -60,7 +62,7 @@ class Followers extends ImmutablePureComponent {
);
}

const emptyMessage = <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />;
const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' /> : <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />;

return (
<Column>
Expand All @@ -75,7 +77,7 @@ class Followers extends ImmutablePureComponent {
alwaysPrepend
emptyMessage={emptyMessage}
>
{accountIds.map(id =>
{blockedBy ? [] : accountIds.map(id =>
<AccountContainer key={id} id={id} withNote={false} />
)}
</ScrollableList>
Expand Down
8 changes: 5 additions & 3 deletions app/javascript/mastodon/features/following/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ScrollableList from '../../components/scrollable_list';
const mapStateToProps = (state, props) => ({
accountIds: state.getIn(['user_lists', 'following', props.params.accountId, 'items']),
hasMore: !!state.getIn(['user_lists', 'following', props.params.accountId, 'next']),
blockedBy: state.getIn(['relationships', props.params.accountId, 'blocked_by'], false),
});

export default @connect(mapStateToProps)
Expand All @@ -31,6 +32,7 @@ class Following extends ImmutablePureComponent {
shouldUpdateScroll: PropTypes.func,
accountIds: ImmutablePropTypes.list,
hasMore: PropTypes.bool,
blockedBy: PropTypes.bool,
};

componentWillMount () {
Expand All @@ -50,7 +52,7 @@ class Following extends ImmutablePureComponent {
}, 300, { leading: true });

render () {
const { shouldUpdateScroll, accountIds, hasMore } = this.props;
const { shouldUpdateScroll, accountIds, hasMore, blockedBy } = this.props;

if (!accountIds) {
return (
Expand All @@ -60,7 +62,7 @@ class Following extends ImmutablePureComponent {
);
}

const emptyMessage = <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />;
const emptyMessage = blockedBy ? <FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' /> : <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />;

return (
<Column>
Expand All @@ -75,7 +77,7 @@ class Following extends ImmutablePureComponent {
alwaysPrepend
emptyMessage={emptyMessage}
>
{accountIds.map(id =>
{blockedBy ? [] : accountIds.map(id =>
<AccountContainer key={id} id={id} withNote={false} />
)}
</ScrollableList>
Expand Down
3 changes: 2 additions & 1 deletion app/javascript/styles/mastodon/components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
}
}

&:disabled {
&:disabled,
&.disabled {
background-color: $ui-primary-color;
cursor: default;
}
Expand Down
17 changes: 17 additions & 0 deletions app/javascript/styles/mastodon/stream_entries.scss
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,23 @@
}
}

&:disabled,
&.disabled {
svg path:last-child {
fill: $ui-primary-color;
}

&:active,
&:focus,
&:hover {
background: $ui-primary-color;

svg path:last-child {
fill: $ui-primary-color;
}
}
}

&.button--destructive {
&:active,
&:focus,
Expand Down
1 change: 0 additions & 1 deletion app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ class Account < ApplicationRecord
scope :tagged_with, ->(tag) { joins(:accounts_tags).where(accounts_tags: { tag_id: tag }) }
scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc')) }
scope :popular, -> { order('account_stats.followers_count desc') }
scope :without_blocking, ->(account) { account.nil? ? all : where.not(id: Block.where(target_account_id: account.id).pluck(:account_id)) }

delegate :email,
:unconfirmed_email,
Expand Down
6 changes: 5 additions & 1 deletion app/presenters/account_relationships_presenter.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

class AccountRelationshipsPresenter
attr_reader :following, :followed_by, :blocking,
attr_reader :following, :followed_by, :blocking, :blocked_by,
:muting, :requested, :domain_blocking,
:endorsed

Expand All @@ -12,6 +12,7 @@ def initialize(account_ids, current_account_id, **options)
@following = cached[:following].merge(Account.following_map(@uncached_account_ids, @current_account_id))
@followed_by = cached[:followed_by].merge(Account.followed_by_map(@uncached_account_ids, @current_account_id))
@blocking = cached[:blocking].merge(Account.blocking_map(@uncached_account_ids, @current_account_id))
@blocked_by = cached[:blocked_by].merge(Account.blocked_by_map(@uncached_account_ids, @current_account_id))
@muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id))
@requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id))
@domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id))
Expand All @@ -22,6 +23,7 @@ def initialize(account_ids, current_account_id, **options)
@following.merge!(options[:following_map] || {})
@followed_by.merge!(options[:followed_by_map] || {})
@blocking.merge!(options[:blocking_map] || {})
@blocked_by.merge!(options[:blocked_by_map] || {})
@muting.merge!(options[:muting_map] || {})
@requested.merge!(options[:requested_map] || {})
@domain_blocking.merge!(options[:domain_blocking_map] || {})
Expand All @@ -37,6 +39,7 @@ def cached
following: {},
followed_by: {},
blocking: {},
blocked_by: {},
muting: {},
requested: {},
domain_blocking: {},
Expand Down Expand Up @@ -64,6 +67,7 @@ def cache_uncached!
following: { account_id => following[account_id] },
followed_by: { account_id => followed_by[account_id] },
blocking: { account_id => blocking[account_id] },
blocked_by: { account_id => blocked_by[account_id] },
muting: { account_id => muting[account_id] },
requested: { account_id => requested[account_id] },
domain_blocking: { account_id => domain_blocking[account_id] },
Expand Down
6 changes: 5 additions & 1 deletion app/serializers/rest/relationship_serializer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

class REST::RelationshipSerializer < ActiveModel::Serializer
attributes :id, :following, :showing_reblogs, :followed_by, :blocking,
attributes :id, :following, :showing_reblogs, :followed_by, :blocking, :blocked_by,
:muting, :muting_notifications, :requested, :domain_blocking,
:endorsed

Expand All @@ -27,6 +27,10 @@ def blocking
instance_options[:relationships].blocking[object.id] || false
end

def blocked_by
instance_options[:relationships].blocked_by[object.id] || false
end

def muting
instance_options[:relationships].muting[object.id] ? true : false
end
Expand Down
Loading