FEATURE: add "email in-reply-to user option"

We no longer include previous replies as "context", instead
we include and excerpt of the post being replied to at the bottom
of notifications, this information was previously missing.

Users may opt in to emailing previous replies if they wish
or opt out of "in-reply-to" which makes sense in some email clients that
are smarter about displaying a tree of replies.
This commit is contained in:
Sam Saffron
2016-02-26 00:05:40 +11:00
parent a01b2a48d5
commit 820a435af8
14 changed files with 92 additions and 36 deletions

View File

@@ -158,6 +158,7 @@ const User = RestModel.extend({
'external_links_in_new_tab',
'email_digests',
'email_direct',
'email_in_reply_to',
'email_private_messages',
'email_previous_replies',
'dynamic_favicon',

View File

@@ -180,6 +180,7 @@
<label>{{i18n 'user.email_previous_replies.title'}}</label>
{{combo-box valueAttribute="value" content=previousRepliesOptions value=model.user_option.email_previous_replies}}
</div>
{{preference-checkbox labelKey="user.email_in_reply_to" checked=model.user_option.email_in_reply_to}}
{{preference-checkbox labelKey="user.email_private_messages" checked=model.user_option.email_private_messages}}
{{preference-checkbox labelKey="user.email_direct" checked=model.user_option.email_direct}}
<span class="pref-mailing-list-mode">{{preference-checkbox labelKey="user.mailing_list_mode" checked=model.user_option.mailing_list_mode}}</span>

View File

@@ -193,9 +193,9 @@ class UserNotifications < ActionMailer::Base
include UserNotificationsHelper
end
def self.get_context_posts(post, topic_user)
user_option = topic_user.try(:user).try(:user_option)
if user_option && (user_option.email_previous_replies == UserOption.previous_replies_type[:never])
def self.get_context_posts(post, topic_user, user)
if user.user_option.email_previous_replies == UserOption.previous_replies_type[:never]
return []
end
@@ -210,7 +210,7 @@ class UserNotifications < ActionMailer::Base
.order('created_at desc')
.limit(SiteSetting.email_posts_context)
if topic_user && topic_user.last_emailed_post_number && user_option.try(:email_previous_replies) == UserOption.previous_replies_type[:unless_emailed]
if topic_user && topic_user.last_emailed_post_number && user.user_option.email_previous_replies == UserOption.previous_replies_type[:unless_emailed]
context_posts = context_posts.where("post_number > ?", topic_user.last_emailed_post_number)
end
@@ -280,7 +280,7 @@ class UserNotifications < ActionMailer::Base
context = ""
tu = TopicUser.get(post.topic_id, user)
context_posts = self.class.get_context_posts(post, tu)
context_posts = self.class.get_context_posts(post, tu, user)
# make .present? cheaper
context_posts = context_posts.to_a
@@ -296,11 +296,13 @@ class UserNotifications < ActionMailer::Base
if opts[:use_template_html]
topic_excerpt = post.excerpt.gsub("\n", " ") if post.is_first_post? && post.excerpt
else
in_reply_to_post = post.reply_to_post if user.user_option.email_in_reply_to
html = UserNotificationRenderer.new(Rails.configuration.paths["app/views"]).render(
template: 'email/notification',
format: :html,
locals: { context_posts: context_posts,
post: post,
in_reply_to_post: in_reply_to_post,
classes: RTL.new(user).css_class
}
)

View File

@@ -16,6 +16,7 @@ class UserOption < ActiveRecord::Base
self.automatically_unpin_topics = SiteSetting.default_topics_automatic_unpin
self.email_private_messages = SiteSetting.default_email_private_messages
self.email_previous_replies = SiteSetting.default_email_previous_replies
self.email_in_reply_to = SiteSetting.default_email_in_reply_to
self.enable_quoting = SiteSetting.default_other_enable_quoting
self.external_links_in_new_tab = SiteSetting.default_other_external_links_in_new_tab

View File

@@ -14,7 +14,8 @@ class UserOptionSerializer < ApplicationSerializer
:edit_history_public,
:auto_track_topics_after_msecs,
:new_topic_duration_minutes,
:email_previous_replies
:email_previous_replies,
:email_in_reply_to
def include_edit_history_public?

View File

@@ -21,7 +21,8 @@ class UserUpdater
:digest_after_days,
:new_topic_duration_minutes,
:auto_track_topics_after_msecs,
:email_previous_replies
:email_previous_replies,
:email_in_reply_to
]
def initialize(actor, user)
@@ -53,10 +54,10 @@ class UserUpdater
save_options = false
OPTION_ATTR.each do |attribute|
if attributes[attribute].present?
save_options = true
OPTION_ATTR.each do |attribute|
if attributes.key?(attribute)
save_options = true
if [true,false].include?(user.user_option.send(attribute))
val = attributes[attribute].to_s == 'true'

View File

@@ -1,4 +1,4 @@
<table class='post-wrapper <%= post.whisper? ? "whisper" : "" %>'>
<table class='post-wrapper <%= post.whisper? ? "whisper" : "" %> <%= use_excerpt ? "excerpt" : ""%>'>
<tbody>
<tr>
<td>
@@ -23,7 +23,7 @@
</td>
</tr>
<tr>
<td class='body'><%= format_for_email(post.cooked) %></td>
<td class='body'><%= format_for_email(use_excerpt ? post.excerpt : post.cooked) %></td>
</tr>
</tbody>
</table>

View File

@@ -2,17 +2,22 @@
<div class='header-instructions'>%{header_instructions}</div>
<%= render partial: 'email/post', locals: { post: post } %>
<%= render partial: 'email/post', locals: { post: post, use_excerpt: false } %>
<% if in_reply_to_post.present? || context_posts.present? %>
<div class='footer'>%{respond_instructions}</div>
<hr>
<% end %>
<% if in_reply_to_post.present? %>
<h4 class='.previous-discussion'><%= t "user_notifications.in_reply_to" %></h4>
<%= render partial: 'email/post', locals: { post: in_reply_to_post, use_excerpt: true} %>
<% end %>
<% if context_posts.present? %>
<div class='footer'>%{respond_instructions}</div>
<hr>
<h4 class='.previous-discussion'><%= t "user_notifications.previous_discussion" %></h4>
<% context_posts.each do |p| %>
<%= render partial: 'email/post', locals: { post: p } %>
<%= render partial: 'email/post', locals: { post: p, use_excerpt: false } %>
<% end %>
<% end %>