From d3b67461735f9a1c38a7eee655a8131bcf6a0cbf Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 2 Sep 2017 20:44:41 +0200 Subject: [PATCH] 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 --- .../mastodon/containers/account_container.js | 2 +- .../features/account/components/header.js | 4 +-- .../containers/header_container.js | 2 +- .../mastodon/locales/defaultMessages.json | 2 +- app/javascript/mastodon/locales/en.json | 2 +- app/lib/activitypub/activity/undo.rb | 2 ++ app/services/process_interaction_service.rb | 4 +++ app/services/unfollow_service.rb | 30 +++++++++++++++---- 8 files changed, 37 insertions(+), 11 deletions(-) diff --git a/app/javascript/mastodon/containers/account_container.js b/app/javascript/mastodon/containers/account_container.js index ca1efd0e..7c77cb76 100644 --- a/app/javascript/mastodon/containers/account_container.js +++ b/app/javascript/mastodon/containers/account_container.js @@ -32,7 +32,7 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ onFollow (account) { - if (account.getIn(['relationship', 'following'])) { + if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) { if (this.unfollowModal) { dispatch(openModal('CONFIRM', { message: @{account.get('acct')} }} />, diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index 8f4dd352..6eb51a5c 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -11,7 +11,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; const messages = defineMessages({ unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, 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 = () => { @@ -102,7 +102,7 @@ export default class Header extends ImmutablePureComponent { if (account.getIn(['relationship', 'requested'])) { actionBtn = (
- +
); } else if (!account.getIn(['relationship', 'blocking'])) { diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js index baa81bbc..dcee78b3 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js @@ -38,7 +38,7 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ onFollow (account) { - if (account.getIn(['relationship', 'following'])) { + if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) { if (this.unfollowModal) { dispatch(openModal('CONFIRM', { message: @{account.get('acct')} }} />, diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index b13d1646..a0cb8f97 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -436,7 +436,7 @@ "id": "account.follow" }, { - "defaultMessage": "Awaiting approval", + "defaultMessage": "Awaiting approval. Click to cancel follow request", "id": "account.requested" }, { diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index aac87ac7..6d9b9c20 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -12,7 +12,7 @@ "account.mute": "Mute @{name}", "account.posts": "Posts", "account.report": "Report @{name}", - "account.requested": "Awaiting approval", + "account.requested": "Awaiting approval. Click to cancel follow request", "account.share": "Share @{name}'s profile", "account.unblock": "Unblock @{name}", "account.unblock_domain": "Unhide {domain}", diff --git a/app/lib/activitypub/activity/undo.rb b/app/lib/activitypub/activity/undo.rb index 097b1dba..4b0905de 100644 --- a/app/lib/activitypub/activity/undo.rb +++ b/app/lib/activitypub/activity/undo.rb @@ -33,6 +33,8 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity if @account.following?(target_account) @account.unfollow!(target_account) + elsif @account.requested?(target_account) + FollowRequest.find_by(account: @account, target_account: target_account)&.destroy else delete_later!(object_uri) end diff --git a/app/services/process_interaction_service.rb b/app/services/process_interaction_service.rb index cc99cde0..d04e926e 100644 --- a/app/services/process_interaction_service.rb +++ b/app/services/process_interaction_service.rb @@ -67,10 +67,13 @@ class ProcessInteractionService < BaseService def follow!(account, target_account) follow = account.follow!(target_account) + FollowRequest.find_by(account: account, target_account: target_account)&.destroy NotifyService.new.call(target_account, follow) end def follow_request!(account, target_account) + return if account.requested?(target_account) + follow_request = FollowRequest.create!(account: account, target_account: target_account) NotifyService.new.call(target_account, follow_request) end @@ -88,6 +91,7 @@ class ProcessInteractionService < BaseService def unfollow!(account, target_account) account.unfollow!(target_account) + FollowRequest.find_by(account: account, target_account: target_account)&.destroy end def reflect_block!(account, target_account) diff --git a/app/services/unfollow_service.rb b/app/services/unfollow_service.rb index bf151ee2..73a64929 100644 --- a/app/services/unfollow_service.rb +++ b/app/services/unfollow_service.rb @@ -5,15 +5,35 @@ class UnfollowService < BaseService # @param [Account] source_account Where to unfollow from # @param [Account] target_account Which to unfollow def call(source_account, target_account) - follow = source_account.unfollow!(target_account) - return unless follow - create_notification(follow) unless target_account.local? - UnmergeWorker.perform_async(target_account.id, source_account.id) - follow + @source_account = source_account + @target_account = target_account + + unfollow! || undo_follow_request! end 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) if follow.target_account.ostatus? NotificationWorker.perform_async(build_xml(follow), follow.account_id, follow.target_account_id)