]> cat aescling's git repositories - mastodon.git/commitdiff
Follow requests send e-mail notifications, but are excluded from notifications API
authorEugen Rochko <eugen@zeonfederated.com>
Mon, 26 Dec 2016 20:52:03 +0000 (21:52 +0100)
committerEugen Rochko <eugen@zeonfederated.com>
Mon, 26 Dec 2016 20:52:03 +0000 (21:52 +0100)
Better initial state for unlisted/nsfw toggles

app/assets/javascripts/components/features/compose/components/compose_form.jsx
app/assets/javascripts/components/features/follow_requests/components/account_authorize.jsx
app/controllers/api/v1/notifications_controller.rb
app/mailers/notification_mailer.rb
app/models/follow_request.rb
app/models/notification.rb
app/models/user.rb
app/services/follow_service.rb
app/services/notify_service.rb
app/views/notification_mailer/follow_request.text.erb [new file with mode: 0644]
config/locales/en.yml

index 760b0efd10eb6bca48da44986a86464da6c7d355..012e39c9112569f7aa8630ed215c42e06568a380 100644 (file)
@@ -20,6 +20,7 @@ const messages = defineMessages({
 const ComposeForm = React.createClass({
 
   propTypes: {
+    intl: React.PropTypes.object.isRequired,
     text: React.PropTypes.string.isRequired,
     suggestion_token: React.PropTypes.string,
     suggestions: ImmutablePropTypes.list,
@@ -129,7 +130,7 @@ const ComposeForm = React.createClass({
           <span style={{ display: 'inline-block', verticalAlign: 'middle', marginBottom: '14px', marginLeft: '8px', color: '#9baec8' }}><FormattedMessage id='compose_form.private' defaultMessage='Mark as private' /></span>
         </label>
 
-        <Motion defaultStyle={{ opacity: 100, height: 39.5 }} style={{ opacity: spring(this.props.private ? 0 : 100), height: spring(this.props.private ? 0 : 39.5) }}>
+        <Motion defaultStyle={{ opacity: this.props.private ? 0 : 100, height: this.props.private ? 39.5 : 0 }} style={{ opacity: spring(this.props.private ? 0 : 100), height: spring(this.props.private ? 0 : 39.5) }}>
           {({ opacity, height }) =>
             <label style={{ display: 'block', lineHeight: '24px', verticalAlign: 'middle', height: `${height}px`, overflow: 'hidden', opacity: opacity / 100 }}>
               <Toggle checked={this.props.unlisted} onChange={this.handleChangeListability} />
@@ -138,7 +139,7 @@ const ComposeForm = React.createClass({
           }
         </Motion>
 
-        <Motion defaultStyle={{ opacity: 100, height: 39.5 }} style={{ opacity: spring(this.props.media_count === 0 ? 0 : 100), height: spring(this.props.media_count === 0 ? 0 : 39.5) }}>
+        <Motion defaultStyle={{ opacity: 0, height: 0 }} style={{ opacity: spring(this.props.media_count === 0 ? 0 : 100), height: spring(this.props.media_count === 0 ? 0 : 39.5) }}>
           {({ opacity, height }) =>
             <label style={{ display: 'block', lineHeight: '24px', verticalAlign: 'middle', height: `${height}px`, overflow: 'hidden', opacity: opacity / 100 }}>
               <Toggle checked={this.props.sensitive} onChange={this.handleChangeSensitivity} />
index c16488aea1bb44f8f5b91a953f3ffd1d3356ca2b..0d41d192f2e1ea32e7ba30829d7cc7f1408aaeeb 100644 (file)
@@ -35,7 +35,7 @@ const AccountAuthorize = ({ intl, account, onAuthorize, onReject }) => {
   return (
     <div>
       <div style={outerStyle}>
-        <Permalink href={account.get('url')} className='detailed-status__display-name' style={{ display: 'block', overflow: 'hidden', marginBottom: '15px' }}>
+        <Permalink href={account.get('url')} to={`/accounts/${account.get('id')}`} className='detailed-status__display-name' style={{ display: 'block', overflow: 'hidden', marginBottom: '15px' }}>
           <div style={{ float: 'left', marginRight: '10px' }}><Avatar src={account.get('avatar')} size={48} /></div>
           <DisplayName account={account} />
         </Permalink>
index a24e0beb715e155db893e58e9bdde6ef4062d01b..c8f162cb02e2329c6f4184cb00a11ed43b01da56 100644 (file)
@@ -7,7 +7,7 @@ class Api::V1::NotificationsController < ApiController
   respond_to :json
 
   def index
-    @notifications = Notification.where(account: current_account).paginate_by_max_id(20, params[:max_id], params[:since_id])
+    @notifications = Notification.where(account: current_account).browserable.paginate_by_max_id(20, params[:max_id], params[:since_id])
     @notifications = cache_collection(@notifications, Notification)
     statuses       = @notifications.select { |n| !n.target_status.nil? }.map(&:target_status)
 
index 7b2cac7f3c69fa7c7b8b0768bb620c6d60ff01e5..a1b084682fc9f78505749a70fb84a27b609ebd8e 100644 (file)
@@ -40,4 +40,13 @@ class NotificationMailer < ApplicationMailer
       mail to: @me.user.email, subject: I18n.t('notification_mailer.reblog.subject', name: @account.acct)
     end
   end
+
+  def follow_request(recipient, notification)
+    @me      = recipient
+    @account = notification.from_account
+
+    I18n.with_locale(@me.user.locale || I18n.default_locale) do
+      mail to: @me.user.email, subject: I18n.t('notification_mailer.follow_request.subject', name: @account.acct)
+    end
+  end
 end
index b46065d53c61fa5abd89e42b39b98536522ffdf3..8eef3abf446546f3ab71c3c07ac1ff78e3ac3810 100644 (file)
@@ -6,6 +6,8 @@ class FollowRequest < ApplicationRecord
   belongs_to :account
   belongs_to :target_account, class_name: 'Account'
 
+  has_one :notification, as: :activity, dependent: :destroy
+
   validates :account, :target_account, presence: true
   validates :account_id, uniqueness: { scope: :target_account_id }
 
index 9d076ad417d5c98ccd7aa37b078b0656940776db..c0b5c45a8c7df387d1310ce8a44a7d41be1a39bd 100644 (file)
@@ -8,16 +8,18 @@ class Notification < ApplicationRecord
   belongs_to :from_account, class_name: 'Account'
   belongs_to :activity, polymorphic: true
 
-  belongs_to :mention,   foreign_type: 'Mention',   foreign_key: 'activity_id'
-  belongs_to :status,    foreign_type: 'Status',    foreign_key: 'activity_id'
-  belongs_to :follow,    foreign_type: 'Follow',    foreign_key: 'activity_id'
-  belongs_to :favourite, foreign_type: 'Favourite', foreign_key: 'activity_id'
+  belongs_to :mention,        foreign_type: 'Mention',       foreign_key: 'activity_id'
+  belongs_to :status,         foreign_type: 'Status',        foreign_key: 'activity_id'
+  belongs_to :follow,         foreign_type: 'Follow',        foreign_key: 'activity_id'
+  belongs_to :follow_request, foreign_type: 'FollowRequest', foreign_key: 'activity_id'
+  belongs_to :favourite,      foreign_type: 'Favourite',     foreign_key: 'activity_id'
 
   validates :account_id, uniqueness: { scope: [:activity_type, :activity_id] }
 
   STATUS_INCLUDES = [:account, :stream_entry, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, :media_attachments, :tags, mentions: :account]].freeze
 
   scope :cache_ids, -> { select(:id, :updated_at, :activity_type, :activity_id) }
+  scope :browserable, -> { where.not(activity_type: ['FollowRequest']) }
 
   cache_associated :from_account, status: STATUS_INCLUDES, mention: [status: STATUS_INCLUDES], favourite: [:account, status: STATUS_INCLUDES], follow: :account
 
@@ -30,7 +32,7 @@ class Notification < ApplicationRecord
     when 'Status'
       :reblog
     else
-      activity_type.downcase.to_sym
+      activity_type.underscore.to_sym
     end
   end
 
@@ -43,6 +45,10 @@ class Notification < ApplicationRecord
     end
   end
 
+  def browserable?
+    type != :follow_request
+  end
+
   class << self
     def reload_stale_associations!(cached_items)
       account_ids = cached_items.map(&:from_account_id).uniq
@@ -61,7 +67,7 @@ class Notification < ApplicationRecord
 
   def set_from_account
     case activity_type
-    when 'Status', 'Follow', 'Favourite'
+    when 'Status', 'Follow', 'Favourite', 'FollowRequest'
       self.from_account_id = activity(false)&.account_id
     when 'Mention'
       self.from_account_id = activity(false)&.status&.account_id
index 3fc028a6a4544bb68627d7d3ceda5880d506d193..d5a52da06fb0c0d79d26ef0b578f26a520de1bcc 100644 (file)
@@ -15,7 +15,7 @@ class User < ApplicationRecord
   scope :admins,   -> { where(admin: true) }
 
   has_settings do |s|
-    s.key :notification_emails, defaults: { follow: false, reblog: false, favourite: false, mention: false }
+    s.key :notification_emails, defaults: { follow: false, reblog: false, favourite: false, mention: false, follow_request: true }
     s.key :interactions, defaults: { must_be_follower: false, must_be_following: false }
   end
 
index a73ec344d064e8d8e5d6378f32da2c4206245ab3..555f01b6d6606bca145b8e7fce2d647cd2322085 100644 (file)
@@ -20,7 +20,12 @@ class FollowService < BaseService
   private
 
   def request_follow(source_account, target_account)
-    FollowRequest.create!(account: source_account, target_account: target_account)
+    return unless target_account.local?
+
+    follow_request = FollowRequest.create!(account: source_account, target_account: target_account)
+    NotifyService.new.call(target_account, follow_request)
+
+    follow_request
   end
 
   def direct_follow(source_account, target_account)
index 8263c43765eea697fc02f4a231365d116cdde3a1..2fb1d39193e4acde683173b5c86ba290d0854da2 100644 (file)
@@ -32,6 +32,10 @@ class NotifyService < BaseService
     false
   end
 
+  def blocked_follow_request?
+    false
+  end
+
   def blocked?
     blocked   = @recipient.suspended?                                                                                             # Skip if the recipient account is suspended anyway
     blocked ||= @recipient.id == @notification.from_account.id                                                                    # Skip for interactions with self
@@ -45,6 +49,7 @@ class NotifyService < BaseService
 
   def create_notification
     @notification.save!
+    return unless @notification.browserable?
     FeedManager.instance.broadcast(@recipient.id, type: 'notification', message: FeedManager.instance.inline_render(@recipient, 'api/v1/notifications/show', @notification))
   end
 
diff --git a/app/views/notification_mailer/follow_request.text.erb b/app/views/notification_mailer/follow_request.text.erb
new file mode 100644 (file)
index 0000000..c0d38ec
--- /dev/null
@@ -0,0 +1,5 @@
+<%= display_name(@me) %>,
+
+<%= t('notification_mailer.follow_request.body', name: @account.acct) %>
+
+<%= web_url("follow_requests") %>
index e5916dd766ebe52800b58f721526645154de2822..760078862089848e405eec5647d3fc4b4248f7ed 100644 (file)
@@ -54,6 +54,9 @@ en:
     follow:
       body: "%{name} is now following you!"
       subject: "%{name} is now following you"
+    follow_request:
+      body: "%{name} has requested to follow you"
+      subject: 'Pending follower: %{name}'
     mention:
       body: 'You were mentioned by %{name} in:'
       subject: You were mentioned by %{name}