thredded 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -10
  3. data/app/assets/images/favicons/README.md +3 -0
  4. data/app/assets/images/favicons/amazon.png +0 -0
  5. data/app/assets/images/favicons/github.png +0 -0
  6. data/app/assets/images/favicons/google_branding/logo_calendar_128px.png +0 -0
  7. data/app/assets/images/favicons/google_branding/logo_docs_48px.png +0 -0
  8. data/app/assets/images/favicons/google_branding/logo_drive_48px.png +0 -0
  9. data/app/assets/images/favicons/google_branding/logo_forms_48px.png +0 -0
  10. data/app/assets/images/favicons/google_branding/logo_sheets_48px.png +0 -0
  11. data/app/assets/images/favicons/google_branding/logo_slides_48px.png +0 -0
  12. data/app/assets/images/favicons/stackexchange.png +0 -0
  13. data/app/assets/images/favicons/twitter.png +0 -0
  14. data/app/assets/images/favicons/wikipedia.png +0 -0
  15. data/app/assets/javascripts/thredded/components/user_preferences_form.es6 +16 -1
  16. data/app/assets/stylesheets/thredded/_email.scss +52 -0
  17. data/app/assets/stylesheets/thredded/_thredded.scss +1 -0
  18. data/app/assets/stylesheets/thredded/base/_grid.scss +14 -1
  19. data/app/assets/stylesheets/thredded/base/_typography.scss +4 -0
  20. data/app/assets/stylesheets/thredded/base/_variables.scss +24 -1
  21. data/app/assets/stylesheets/thredded/components/_main-section.scss +6 -0
  22. data/app/assets/stylesheets/thredded/components/_messageboard.scss +4 -1
  23. data/app/assets/stylesheets/thredded/components/_onebox.scss +284 -0
  24. data/app/assets/stylesheets/thredded/components/_post.scss +10 -6
  25. data/app/assets/stylesheets/thredded/components/_topic-header.scss +1 -1
  26. data/app/assets/stylesheets/thredded/components/_topics.scss +5 -5
  27. data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +0 -6
  28. data/app/assets/stylesheets/thredded/layout/_moderation.scss +1 -1
  29. data/app/commands/thredded/autofollow_users.rb +56 -0
  30. data/app/controllers/thredded/preferences_controller.rb +2 -0
  31. data/app/forms/thredded/user_preferences_form.rb +18 -0
  32. data/app/helpers/thredded/application_helper.rb +3 -3
  33. data/app/jobs/thredded/auto_follow_and_notify_job.rb +1 -1
  34. data/app/mailer_previews/thredded/base_mailer_preview.rb +19 -8
  35. data/app/mailers/thredded/base_mailer.rb +1 -1
  36. data/app/models/concerns/thredded/post_common.rb +2 -4
  37. data/app/models/thredded/category.rb +4 -0
  38. data/app/models/thredded/messageboard.rb +12 -6
  39. data/app/models/thredded/private_topic.rb +4 -0
  40. data/app/models/thredded/topic.rb +9 -5
  41. data/app/models/thredded/user_messageboard_preference.rb +24 -0
  42. data/app/models/thredded/user_preference.rb +2 -0
  43. data/app/models/thredded/user_topic_follow.rb +1 -1
  44. data/app/notifiers/thredded/email_notifier.rb +1 -15
  45. data/app/views/thredded/messageboard_groups/new.html.erb +15 -13
  46. data/app/views/thredded/messageboards/_form.html.erb +22 -22
  47. data/app/views/thredded/messageboards/edit.html.erb +3 -1
  48. data/app/views/thredded/messageboards/new.html.erb +3 -1
  49. data/app/views/thredded/moderation/_post.html.erb +1 -1
  50. data/app/views/thredded/moderation/_user_post.html.erb +1 -1
  51. data/app/views/thredded/moderation/activity.html.erb +3 -3
  52. data/app/views/thredded/moderation/history.html.erb +2 -2
  53. data/app/views/thredded/moderation/pending.html.erb +2 -2
  54. data/app/views/thredded/moderation/user.html.erb +43 -41
  55. data/app/views/thredded/moderation/users.html.erb +32 -30
  56. data/app/views/thredded/post_mailer/post_notification.html.erb +21 -12
  57. data/app/views/thredded/posts/_content.html.erb +1 -1
  58. data/app/views/thredded/posts_common/_content.html.erb +1 -3
  59. data/app/views/thredded/preferences/_form.html.erb +25 -8
  60. data/app/views/thredded/private_posts/_content.html.erb +1 -1
  61. data/app/views/thredded/private_topic_mailer/message_notification.html.erb +17 -14
  62. data/app/views/thredded/private_topics/edit.html.erb +21 -19
  63. data/app/views/thredded/topics/edit.html.erb +32 -30
  64. data/app/views/thredded/topics/new.html.erb +8 -6
  65. data/app/views/thredded/topics/show.html.erb +1 -1
  66. data/app/views/thredded/users/_post.html.erb +1 -1
  67. data/bin/rubocop +17 -0
  68. data/config/locales/en.yml +13 -1
  69. data/config/locales/es.yml +14 -0
  70. data/config/locales/pl.yml +13 -0
  71. data/config/locales/pt-BR.yml +12 -0
  72. data/config/locales/ru.yml +197 -0
  73. data/db/migrate/20160329231848_create_thredded.rb +2 -8
  74. data/db/upgrade_migrations/20161113161801_upgrade_v0_8_to_v0_9.rb +6 -5
  75. data/db/upgrade_migrations/20170312131417_upgrade_thredded_v0_10_to_v0_11.rb +20 -0
  76. data/lib/generators/thredded/install/templates/initializer.rb +12 -0
  77. data/lib/thredded.rb +12 -3
  78. data/lib/thredded/content_formatter.rb +16 -25
  79. data/lib/thredded/email_transformer.rb +21 -0
  80. data/lib/thredded/email_transformer/base.rb +47 -0
  81. data/lib/thredded/email_transformer/onebox.rb +20 -0
  82. data/lib/thredded/formatting_demo_content.rb +29 -0
  83. data/lib/thredded/html_pipeline/kramdown_filter.rb +5 -1
  84. data/lib/thredded/html_pipeline/onebox_filter.rb +136 -0
  85. data/lib/thredded/version.rb +1 -1
  86. metadata +62 -22
  87. data/app/commands/thredded/autofollow_mentioned_users.rb +0 -31
  88. data/app/commands/thredded/members_marked_notified.rb +0 -19
  89. data/app/models/thredded/post_notification.rb +0 -18
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'thredded/email_transformer/base'
3
+ module Thredded
4
+ module EmailTransformer
5
+ # Wraps oneboxes with tables, because only tables can have borders in most email clients.
6
+ class Onebox < Base
7
+ def call
8
+ doc.css('aside.onebox').each do |onebox|
9
+ table = Nokogiri::XML::Node.new('table', doc)
10
+ table['class'] = 'onebox-wrapper-table'
11
+ onebox.swap table
12
+ table
13
+ .add_child(Nokogiri::XML::Node.new('tr', doc))
14
+ .add_child(Nokogiri::XML::Node.new('td', doc))
15
+ .add_child(onebox)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ # Content for demo-ing formatting functionality
4
+ module FormattingDemoContent
5
+ class << self
6
+ attr_accessor :parts
7
+ end
8
+ self.parts = [
9
+ <<-'MARKDOWN',
10
+ #### Oneboxes
11
+
12
+ URLs of supported resources are replaced with boxes like these:
13
+
14
+ **Twitter** `https://twitter.com/thredded/status/838824533477982209`:
15
+ https://twitter.com/thredded/status/838824533477982209
16
+ **StackExchange** `http://codegolf.stackexchange.com/questions/45701`:
17
+ http://codegolf.stackexchange.com/questions/45701
18
+ **Amazon** `https://www.amazon.co.uk/dp/0521797071`:
19
+ https://www.amazon.co.uk/dp/0521797071
20
+ **YouTube** `https://www.youtube.com/watch?v=1QP7elXwpLw`:
21
+ https://www.youtube.com/watch?v=1QP7elXwpLw
22
+ **Google Maps** `https://goo.gl/maps/R6nj3Qwf2LR2`:
23
+ https://goo.gl/maps/R6nj3Qwf2LR2
24
+
25
+ Many more resources are [supported](https://github.com/discourse/onebox/tree/master/lib/onebox/engine). Powered by the [onebox](https://github.com/discourse/onebox) library.
26
+ MARKDOWN
27
+ ]
28
+ end
29
+ end
@@ -19,7 +19,11 @@ module Thredded
19
19
 
20
20
  def initialize(text, context = nil, result = nil)
21
21
  super text, context, result
22
- @text.delete! "\r"
22
+ if @text.frozen?
23
+ @text = @text.delete("\r")
24
+ else
25
+ @text.delete! "\r"
26
+ end
23
27
  end
24
28
 
25
29
  # Convert Markdown to HTML using the best available implementation
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+ require 'onebox'
3
+
4
+ module Thredded
5
+ module HtmlPipeline
6
+ class OneboxFilter < ::HTML::Pipeline::Filter
7
+ SANITIZE_CONFIG = Sanitize::Config.merge(
8
+ Sanitize::Config::ONEBOX,
9
+ attributes: {
10
+ 'a' => Sanitize::Config::ONEBOX[:attributes]['a'] + %w(target),
11
+ },
12
+ add_attributes: {
13
+ 'iframe' => {
14
+ 'seamless' => 'seamless',
15
+ 'sandbox' => 'allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox',
16
+ }
17
+ },
18
+ transformers: (Sanitize::Config::ONEBOX[:transformers] || []) + [
19
+ lambda do |env|
20
+ next unless env[:node_name] == 'a'
21
+ a_tag = env[:node]
22
+ a_tag['href'] ||= '#'
23
+ if a_tag['href'] =~ %r{^(?:[a-z]+:)?//}
24
+ a_tag['target'] = '_blank'
25
+ a_tag['rel'] = 'nofollow noopener'
26
+ else
27
+ a_tag.remove_attribute('target')
28
+ end
29
+ end
30
+ ]
31
+ )
32
+
33
+ class << self
34
+ # In development and test, caching is usually disabled.
35
+ # Regardless, always store the onebox in a file cache to enable offline development,
36
+ # persistence between test runs, and to improve performance.
37
+ attr_accessor :onebox_views_cache
38
+ attr_accessor :onebox_data_cache
39
+ end
40
+
41
+ if Rails.env.development? || Rails.env.test?
42
+ self.onebox_views_cache = ActiveSupport::Cache::FileStore.new('tmp/cache/onebox-views')
43
+ self.onebox_data_cache = ActiveSupport::Cache::FileStore.new('tmp/cache/onebox-data')
44
+ end
45
+
46
+ def call
47
+ doc.css('a').each do |element|
48
+ url = element['href'].to_s
49
+ next unless url.present? && url == element.content && on_its_own_line?(element)
50
+ onebox_html = render_onebox_with_cache(url)
51
+ next if onebox_html.empty?
52
+ fixup_paragraph! element
53
+ element.swap onebox_html
54
+ end
55
+ doc
56
+ end
57
+
58
+ private
59
+
60
+ def render_onebox_with_cache(url)
61
+ onebox_views_cache.fetch("onebox-views:#{url}#{':p' if context[:onebox_placeholders]}",
62
+ expires_in: context[:onebox_views_cache_expires_in] || 1.week) do
63
+ render_onebox(url)
64
+ end
65
+ end
66
+
67
+ def render_onebox(url)
68
+ preview = Onebox.preview(url, onebox_options(url))
69
+ if context[:onebox_placeholders]
70
+ %(<p><a href="#{ERB::Util.html_escape(url)}" target="_blank" rel="nofollow noopener">) \
71
+ "#{preview.placeholder_html}</a></p>"
72
+ else
73
+ preview.to_s.strip
74
+ end
75
+ end
76
+
77
+ def onebox_options(_url)
78
+ { cache: context[:onebox_data_cache] || self.class.onebox_data_cache || Rails.cache,
79
+ sanitize_config: SANITIZE_CONFIG }
80
+ end
81
+
82
+ def onebox_views_cache
83
+ context[:onebox_views_cache] || self.class.onebox_views_cache || Rails.cache
84
+ end
85
+
86
+ def on_its_own_line?(element)
87
+ siblings = element.parent.children
88
+ element_index = siblings.index(element)
89
+ all_blank_until_br?(siblings[0...element_index].reverse) &&
90
+ all_blank_until_br?(siblings[element_index + 1..-1])
91
+ end
92
+
93
+ def all_blank_until_br?(nodes)
94
+ nodes.take_while { |node| !node_name?(node, 'br') }
95
+ .all? { |node| node.text? && node.blank? }
96
+ end
97
+
98
+ def fixup_paragraph!(element)
99
+ # Can't have a div inside a paragraph, so split the paragraph
100
+ p = element.parent
101
+ return unless node_name?(p, 'p')
102
+ children_after = p.children[p.children.index(element) + 1..-1]
103
+ remove_leading_blanks! children_after
104
+ # Move the onebox out of and after the paragraph
105
+ p.add_next_sibling element
106
+ # Move all the elements after the onebox to a new paragraph
107
+ unless children_after.empty?
108
+ new_p = Nokogiri::XML::Node.new 'p', doc
109
+ element.add_next_sibling new_p
110
+ children_after.each { |child| new_p.add_child child }
111
+ end
112
+ # The original paragraph might have been split just after a <br> or whitespace, remove them if so:
113
+ remove_leading_blanks! p.children.reverse
114
+ p.remove if p.children.empty?
115
+ end
116
+
117
+ # @param children [Nokogiri::XML::NodeSet]
118
+ def remove_leading_blanks!(children)
119
+ to_remove = children.take_while do |c|
120
+ if node_name?(c, 'br') || c.text? && c.content.blank?
121
+ c.remove
122
+ true
123
+ else
124
+ c.content = c.content.lstrip
125
+ false
126
+ end
127
+ end
128
+ to_remove.each { |c| children.delete(c) }
129
+ end
130
+
131
+ def node_name?(node, node_name)
132
+ node && node.node_name && node.node_name.casecmp(node_name).zero?
133
+ end
134
+ end
135
+ end
136
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
- VERSION = '0.10.1'
3
+ VERSION = '0.11.0'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thredded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.1
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Oliveira
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-03-12 00:00:00.000000000 Z
12
+ date: 2017-03-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pundit
@@ -166,35 +166,27 @@ dependencies:
166
166
  - !ruby/object:Gem::Version
167
167
  version: '0'
168
168
  - !ruby/object:Gem::Dependency
169
- name: html-pipeline
169
+ name: onebox
170
170
  requirement: !ruby/object:Gem::Requirement
171
171
  requirements:
172
- - - ">="
172
+ - - "~>"
173
173
  - !ruby/object:Gem::Version
174
- version: '0'
175
- type: :runtime
176
- prerelease: false
177
- version_requirements: !ruby/object:Gem::Requirement
178
- requirements:
174
+ version: '1.8'
179
175
  - - ">="
180
176
  - !ruby/object:Gem::Version
181
- version: '0'
182
- - !ruby/object:Gem::Dependency
183
- name: html-pipeline-vimeo
184
- requirement: !ruby/object:Gem::Requirement
185
- requirements:
186
- - - ">="
187
- - !ruby/object:Gem::Version
188
- version: '0'
177
+ version: 1.8.3
189
178
  type: :runtime
190
179
  prerelease: false
191
180
  version_requirements: !ruby/object:Gem::Requirement
192
181
  requirements:
182
+ - - "~>"
183
+ - !ruby/object:Gem::Version
184
+ version: '1.8'
193
185
  - - ">="
194
186
  - !ruby/object:Gem::Version
195
- version: '0'
187
+ version: 1.8.3
196
188
  - !ruby/object:Gem::Dependency
197
- name: html-pipeline-youtube
189
+ name: html-pipeline
198
190
  requirement: !ruby/object:Gem::Requirement
199
191
  requirements:
200
192
  - - ">="
@@ -375,6 +367,20 @@ dependencies:
375
367
  - - ">="
376
368
  - !ruby/object:Gem::Version
377
369
  version: '0'
370
+ - !ruby/object:Gem::Dependency
371
+ name: webmock
372
+ requirement: !ruby/object:Gem::Requirement
373
+ requirements:
374
+ - - ">="
375
+ - !ruby/object:Gem::Version
376
+ version: '0'
377
+ type: :development
378
+ prerelease: false
379
+ version_requirements: !ruby/object:Gem::Requirement
380
+ requirements:
381
+ - - ">="
382
+ - !ruby/object:Gem::Version
383
+ version: '0'
378
384
  - !ruby/object:Gem::Dependency
379
385
  name: database_cleaner
380
386
  requirement: !ruby/object:Gem::Requirement
@@ -571,6 +577,20 @@ dependencies:
571
577
  - - ">="
572
578
  - !ruby/object:Gem::Version
573
579
  version: 2.0.1
580
+ - !ruby/object:Gem::Dependency
581
+ name: roadie-rails
582
+ requirement: !ruby/object:Gem::Requirement
583
+ requirements:
584
+ - - ">="
585
+ - !ruby/object:Gem::Version
586
+ version: '0'
587
+ type: :development
588
+ prerelease: false
589
+ version_requirements: !ruby/object:Gem::Requirement
590
+ requirements:
591
+ - - ">="
592
+ - !ruby/object:Gem::Version
593
+ version: '0'
574
594
  - !ruby/object:Gem::Dependency
575
595
  name: i18n-tasks
576
596
  requirement: !ruby/object:Gem::Requirement
@@ -667,6 +687,18 @@ extra_rdoc_files: []
667
687
  files:
668
688
  - MIT-LICENSE
669
689
  - README.md
690
+ - app/assets/images/favicons/README.md
691
+ - app/assets/images/favicons/amazon.png
692
+ - app/assets/images/favicons/github.png
693
+ - app/assets/images/favicons/google_branding/logo_calendar_128px.png
694
+ - app/assets/images/favicons/google_branding/logo_docs_48px.png
695
+ - app/assets/images/favicons/google_branding/logo_drive_48px.png
696
+ - app/assets/images/favicons/google_branding/logo_forms_48px.png
697
+ - app/assets/images/favicons/google_branding/logo_sheets_48px.png
698
+ - app/assets/images/favicons/google_branding/logo_slides_48px.png
699
+ - app/assets/images/favicons/stackexchange.png
700
+ - app/assets/images/favicons/twitter.png
701
+ - app/assets/images/favicons/wikipedia.png
670
702
  - app/assets/images/thredded/breadcrumb-chevron.svg
671
703
  - app/assets/images/thredded/follow.svg
672
704
  - app/assets/images/thredded/moderation.svg
@@ -696,6 +728,7 @@ files:
696
728
  - app/assets/stylesheets/thredded.scss
697
729
  - app/assets/stylesheets/thredded/_base.scss
698
730
  - app/assets/stylesheets/thredded/_dependencies.scss
731
+ - app/assets/stylesheets/thredded/_email.scss
699
732
  - app/assets/stylesheets/thredded/_thredded.scss
700
733
  - app/assets/stylesheets/thredded/base/_alerts.scss
701
734
  - app/assets/stylesheets/thredded/base/_buttons.scss
@@ -717,6 +750,7 @@ files:
717
750
  - app/assets/stylesheets/thredded/components/_main-section.scss
718
751
  - app/assets/stylesheets/thredded/components/_mention-autocomplete.scss
719
752
  - app/assets/stylesheets/thredded/components/_messageboard.scss
753
+ - app/assets/stylesheets/thredded/components/_onebox.scss
720
754
  - app/assets/stylesheets/thredded/components/_pagination.scss
721
755
  - app/assets/stylesheets/thredded/components/_post-form.scss
722
756
  - app/assets/stylesheets/thredded/components/_post.scss
@@ -736,10 +770,9 @@ files:
736
770
  - app/assets/stylesheets/thredded/utilities/_is-compact.scss
737
771
  - app/assets/stylesheets/thredded/utilities/_is-expanded.scss
738
772
  - app/commands/thredded/at_notification_extractor.rb
739
- - app/commands/thredded/autofollow_mentioned_users.rb
773
+ - app/commands/thredded/autofollow_users.rb
740
774
  - app/commands/thredded/create_messageboard.rb
741
775
  - app/commands/thredded/mark_all_read.rb
742
- - app/commands/thredded/members_marked_notified.rb
743
776
  - app/commands/thredded/moderate_post.rb
744
777
  - app/commands/thredded/notify_following_users.rb
745
778
  - app/commands/thredded/notify_private_topic_users.rb
@@ -801,7 +834,6 @@ files:
801
834
  - app/models/thredded/null_user_topic_read_state.rb
802
835
  - app/models/thredded/post.rb
803
836
  - app/models/thredded/post_moderation_record.rb
804
- - app/models/thredded/post_notification.rb
805
837
  - app/models/thredded/private_post.rb
806
838
  - app/models/thredded/private_topic.rb
807
839
  - app/models/thredded/private_user.rb
@@ -949,11 +981,13 @@ files:
949
981
  - app/views/thredded/users/_post.html.erb
950
982
  - app/views/thredded/users/_posts.html.erb
951
983
  - bin/rails
984
+ - bin/rubocop
952
985
  - config/i18n-tasks.yml
953
986
  - config/locales/en.yml
954
987
  - config/locales/es.yml
955
988
  - config/locales/pl.yml
956
989
  - config/locales/pt-BR.yml
990
+ - config/locales/ru.yml
957
991
  - config/routes.rb
958
992
  - db/migrate/20160329231848_create_thredded.rb
959
993
  - db/seeds.rb
@@ -965,6 +999,7 @@ files:
965
999
  - db/upgrade_migrations/20161019150201_upgrade_v0_7_to_v0_8.rb
966
1000
  - db/upgrade_migrations/20161113161801_upgrade_v0_8_to_v0_9.rb
967
1001
  - db/upgrade_migrations/20170125033319_upgrade_v0_9_to_v0_10.rb
1002
+ - db/upgrade_migrations/20170312131417_upgrade_thredded_v0_10_to_v0_11.rb
968
1003
  - lib/generators/thredded/install/USAGE
969
1004
  - lib/generators/thredded/install/install_generator.rb
970
1005
  - lib/generators/thredded/install/templates/initializer.rb
@@ -974,11 +1009,16 @@ files:
974
1009
  - lib/thredded/content_formatter.rb
975
1010
  - lib/thredded/database_seeder.rb
976
1011
  - lib/thredded/db_tools.rb
1012
+ - lib/thredded/email_transformer.rb
1013
+ - lib/thredded/email_transformer/base.rb
1014
+ - lib/thredded/email_transformer/onebox.rb
977
1015
  - lib/thredded/engine.rb
978
1016
  - lib/thredded/errors.rb
1017
+ - lib/thredded/formatting_demo_content.rb
979
1018
  - lib/thredded/html_pipeline/at_mention_filter.rb
980
1019
  - lib/thredded/html_pipeline/autolink_filter.rb
981
1020
  - lib/thredded/html_pipeline/kramdown_filter.rb
1021
+ - lib/thredded/html_pipeline/onebox_filter.rb
982
1022
  - lib/thredded/html_pipeline/wrap_iframes_filter.rb
983
1023
  - lib/thredded/version.rb
984
1024
  - lib/thredded/view_hooks/config.rb
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- module Thredded
3
- class AutofollowMentionedUsers
4
- def initialize(post)
5
- @post = post
6
- end
7
-
8
- def run
9
- autofollowers.each do |user|
10
- Thredded::UserTopicFollow.create_unless_exists(user.id, post.postable_id, :mentioned)
11
- end
12
- end
13
-
14
- def autofollowers
15
- autofollowers = Thredded::AtNotificationExtractor.new(post).run
16
- autofollowers.delete(post.user)
17
- exclude_those_opting_out_of_at_notifications autofollowers
18
- end
19
-
20
- private
21
-
22
- attr_reader :post
23
-
24
- def exclude_those_opting_out_of_at_notifications(members)
25
- members.select do |member|
26
- member.thredded_user_preference.follow_topics_on_mention? &&
27
- member.thredded_user_messageboard_preferences.in(post.messageboard).follow_topics_on_mention?
28
- end
29
- end
30
- end
31
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
- module Thredded
3
- class MembersMarkedNotified
4
- def initialize(post, members)
5
- @post = post
6
- @members = members
7
- end
8
-
9
- def run
10
- members.each do |member|
11
- post.post_notifications.create(email: member.email)
12
- end
13
- end
14
-
15
- private
16
-
17
- attr_reader :post, :members
18
- end
19
- end