Make "unfollow" undo pending outgoing follow request too (#4781)

* Make "unfollow" undo pending outgoing follow request too

* Add cancel button to web UI when awaiting follow request approval

* Make the hourglass button do the cancelling
rebase/4.0.0rc2
Eugen Rochko 2017-09-02 20:44:41 +02:00 committed by GitHub
parent 2a5d1d5a1b
commit d3b6746173
8 changed files with 37 additions and 11 deletions

View File

@ -32,7 +32,7 @@ const makeMapStateToProps = () => {
const mapDispatchToProps = (dispatch, { intl }) => ({ const mapDispatchToProps = (dispatch, { intl }) => ({
onFollow (account) { onFollow (account) {
if (account.getIn(['relationship', 'following'])) { if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
if (this.unfollowModal) { if (this.unfollowModal) {
dispatch(openModal('CONFIRM', { dispatch(openModal('CONFIRM', {
message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,

View File

@ -11,7 +11,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
const messages = defineMessages({ const messages = defineMessages({
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
follow: { id: 'account.follow', defaultMessage: 'Follow' }, follow: { id: 'account.follow', defaultMessage: 'Follow' },
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {
@ -102,7 +102,7 @@ export default class Header extends ImmutablePureComponent {
if (account.getIn(['relationship', 'requested'])) { if (account.getIn(['relationship', 'requested'])) {
actionBtn = ( actionBtn = (
<div className='account--action-button'> <div className='account--action-button'>
<IconButton size={26} disabled icon='hourglass' title={intl.formatMessage(messages.requested)} /> <IconButton size={26} active icon='hourglass' title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />
</div> </div>
); );
} else if (!account.getIn(['relationship', 'blocking'])) { } else if (!account.getIn(['relationship', 'blocking'])) {

View File

@ -38,7 +38,7 @@ const makeMapStateToProps = () => {
const mapDispatchToProps = (dispatch, { intl }) => ({ const mapDispatchToProps = (dispatch, { intl }) => ({
onFollow (account) { onFollow (account) {
if (account.getIn(['relationship', 'following'])) { if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
if (this.unfollowModal) { if (this.unfollowModal) {
dispatch(openModal('CONFIRM', { dispatch(openModal('CONFIRM', {
message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,

View File

@ -436,7 +436,7 @@
"id": "account.follow" "id": "account.follow"
}, },
{ {
"defaultMessage": "Awaiting approval", "defaultMessage": "Awaiting approval. Click to cancel follow request",
"id": "account.requested" "id": "account.requested"
}, },
{ {

View File

@ -12,7 +12,7 @@
"account.mute": "Mute @{name}", "account.mute": "Mute @{name}",
"account.posts": "Posts", "account.posts": "Posts",
"account.report": "Report @{name}", "account.report": "Report @{name}",
"account.requested": "Awaiting approval", "account.requested": "Awaiting approval. Click to cancel follow request",
"account.share": "Share @{name}'s profile", "account.share": "Share @{name}'s profile",
"account.unblock": "Unblock @{name}", "account.unblock": "Unblock @{name}",
"account.unblock_domain": "Unhide {domain}", "account.unblock_domain": "Unhide {domain}",

View File

@ -33,6 +33,8 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity
if @account.following?(target_account) if @account.following?(target_account)
@account.unfollow!(target_account) @account.unfollow!(target_account)
elsif @account.requested?(target_account)
FollowRequest.find_by(account: @account, target_account: target_account)&.destroy
else else
delete_later!(object_uri) delete_later!(object_uri)
end end

View File

@ -67,10 +67,13 @@ class ProcessInteractionService < BaseService
def follow!(account, target_account) def follow!(account, target_account)
follow = account.follow!(target_account) follow = account.follow!(target_account)
FollowRequest.find_by(account: account, target_account: target_account)&.destroy
NotifyService.new.call(target_account, follow) NotifyService.new.call(target_account, follow)
end end
def follow_request!(account, target_account) def follow_request!(account, target_account)
return if account.requested?(target_account)
follow_request = FollowRequest.create!(account: account, target_account: target_account) follow_request = FollowRequest.create!(account: account, target_account: target_account)
NotifyService.new.call(target_account, follow_request) NotifyService.new.call(target_account, follow_request)
end end
@ -88,6 +91,7 @@ class ProcessInteractionService < BaseService
def unfollow!(account, target_account) def unfollow!(account, target_account)
account.unfollow!(target_account) account.unfollow!(target_account)
FollowRequest.find_by(account: account, target_account: target_account)&.destroy
end end
def reflect_block!(account, target_account) def reflect_block!(account, target_account)

View File

@ -5,15 +5,35 @@ class UnfollowService < BaseService
# @param [Account] source_account Where to unfollow from # @param [Account] source_account Where to unfollow from
# @param [Account] target_account Which to unfollow # @param [Account] target_account Which to unfollow
def call(source_account, target_account) def call(source_account, target_account)
follow = source_account.unfollow!(target_account) @source_account = source_account
return unless follow @target_account = target_account
create_notification(follow) unless target_account.local?
UnmergeWorker.perform_async(target_account.id, source_account.id) unfollow! || undo_follow_request!
follow
end end
private private
def unfollow!
follow = Follow.find_by(account: @source_account, target_account: @target_account)
return unless follow
follow.destroy!
create_notification(follow) unless @target_account.local?
UnmergeWorker.perform_async(@target_account.id, @source_account.id)
follow
end
def undo_follow_request!
follow_request = FollowRequest.find_by(account: @source_account, target_account: @target_account)
return unless follow_request
follow_request.destroy!
create_notification(follow_request) unless @target_account.local?
follow_request
end
def create_notification(follow) def create_notification(follow)
if follow.target_account.ostatus? if follow.target_account.ostatus?
NotificationWorker.perform_async(build_xml(follow), follow.account_id, follow.target_account_id) NotificationWorker.perform_async(build_xml(follow), follow.account_id, follow.target_account_id)