about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/javascript/mastodon/containers/account_container.js2
-rw-r--r--app/javascript/mastodon/features/account/components/header.js4
-rw-r--r--app/javascript/mastodon/features/account_timeline/containers/header_container.js2
-rw-r--r--app/javascript/mastodon/locales/defaultMessages.json2
-rw-r--r--app/javascript/mastodon/locales/en.json2
-rw-r--r--app/lib/activitypub/activity/undo.rb2
-rw-r--r--app/services/process_interaction_service.rb4
-rw-r--r--app/services/unfollow_service.rb28
8 files changed, 36 insertions, 10 deletions
diff --git a/app/javascript/mastodon/containers/account_container.js b/app/javascript/mastodon/containers/account_container.js
index ca1efd0e5..7c77cb764 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: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js
index 8f4dd352d..6eb51a5c7 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 = (
           <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>
         );
       } 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 baa81bbc2..dcee78b3e 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: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index b13d1646d..a0cb8f978 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 aac87ac70..6d9b9c208 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 097b1dba4..4b0905de2 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 cc99cde03..d04e926e7 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 bf151ee28..73a64929f 100644
--- a/app/services/unfollow_service.rb
+++ b/app/services/unfollow_service.rb
@@ -5,14 +5,34 @@ 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)
+    @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
-    create_notification(follow) unless target_account.local?
-    UnmergeWorker.perform_async(target_account.id, source_account.id)
+
+    follow.destroy!
+    create_notification(follow) unless @target_account.local?
+    UnmergeWorker.perform_async(@target_account.id, @source_account.id)
     follow
   end
 
-  private
+  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?