Skip to content
This repository

Adding a spoiler tag #333

Closed
wants to merge 1 commit into from

6 participants

Tailszefox Chris Horne dxgiovanni RainbowCrash Ross Allan Neil Williams
Tailszefox

This is an implementation of the following feature request: http://www.reddit.com/r/ideasfortheadmins/comments/oqnxk/on_behalf_of_the_entire_book_and_tvshow_subreddit/

This adds a "spoiler" tag, which acts the same way as a NSFW tag: submissions can be marked as being spoilers, and get a new thumbnail and a stamp. A submission can be marked as both being a spoiler and being NSFW (NSFW taking precedence).

The spoiler setting can be changed on a per-community basis: if it's not enabled, submissions cannot be marked as spoilers (it is off by default). When enabled, users also have the ability, through a checkbox in the sidebar, to enable or disable the display of spoilered submissions (just like they can choose to hide NSFW submissions, except this works on a per-community basis).

Chris Horne

I would love to see this accepted.

dxgiovanni

Would LOVE to see this implemented. There are currently some per-community workarounds remapping the NSFW tag that can lead to very comical results.

RainbowCrash

Hoping to hear a status update on this from the admins. It would be seriously great to have this feature.

Chris Horne

I heard recently that it was already implemented once, but it was removed quickly because of negative feedback.

RainbowCrash

Wait, as in this pull request was implemented?

Chris Horne

no, something similar which added subcategories of NSFW tags, iirc including spoiler

Ross Allan

I would also love to see this accepted.

Neil Williams
Owner

I'm going to close this as we'd rather implement a sitewide spoiler option via extending the link flair framework. Thanks for the pull request.

Neil Williams spladug closed this July 15, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jan 30, 2012
Tailszefox Added spoiler tag 4e4233b
This page is out of date. Refresh to see the latest.
35  r2/r2/controllers/api.py
@@ -716,6 +716,28 @@ def POST_unmarknsfw(self, thing):
716 716
 
717 717
         # flag search indexer that something has changed
718 718
         changed(thing)
  719
+        
  720
+    @noresponse(VUser(),
  721
+                VModhash(),
  722
+                VSrCanAlter('id'),
  723
+                thing = VByName('id'))
  724
+    def POST_markspoiler(self, thing):
  725
+        thing.spoiler = True
  726
+        thing._commit()
  727
+
  728
+        # flag search indexer that something has changed
  729
+        changed(thing)
  730
+
  731
+    @noresponse(VUser(),
  732
+                VModhash(),
  733
+                VSrCanAlter('id'),
  734
+                thing = VByName('id'))
  735
+    def POST_unmarkspoiler(self, thing):
  736
+        thing.spoiler = False
  737
+        thing._commit()
  738
+
  739
+        # flag search indexer that something has changed
  740
+        changed(thing)
719 741
 
720 742
     @noresponse(VUser(), VModhash(),
721 743
                 thing = VByName('id'))
@@ -1264,6 +1286,7 @@ def POST_upload_sr_img(self, file, header, sponsor, name, form_id, img_type):
1264 1286
                    over_18 = VBoolean('over_18'),
1265 1287
                    allow_top = VBoolean('allow_top'),
1266 1288
                    show_media = VBoolean('show_media'),
  1289
+                   allow_spoilers = VBoolean('allow_spoilers'),
1267 1290
                    show_cname_sidebar = VBoolean('show_cname_sidebar'),
1268 1291
                    type = VOneOf('type', ('public', 'private', 'restricted', 'archived')),
1269 1292
                    link_type = VOneOf('link_type', ('any', 'link', 'self')),
@@ -1281,8 +1304,8 @@ def POST_site_admin(self, form, jquery, name, ip, sr,
1281 1304
         redir = False
1282 1305
         kw = dict((k, v) for k, v in kw.iteritems()
1283 1306
                   if k in ('name', 'title', 'domain', 'description', 'over_18',
1284  
-                           'show_media', 'show_cname_sidebar', 'type', 'link_type', 'lang',
1285  
-                           "css_on_cname", "header_title", 
  1307
+                           'show_media', 'allow_spoilers', 'show_cname_sidebar', 'type', 'link_type', 
  1308
+                           'lang', "css_on_cname", "header_title", 
1286 1309
                            'allow_top'))
1287 1310
 
1288 1311
         #if a user is banned, return rate-limit errors
@@ -2064,6 +2087,14 @@ def POST_setflairenabled(self, form, jquery, flair_enabled):
2064 2087
         setattr(c.user, 'flair_%s_enabled' % c.site._id, flair_enabled)
2065 2088
         c.user._commit()
2066 2089
         jquery.refresh()
  2090
+        
  2091
+    @validatedForm(VUser(),
  2092
+                   VModhash(),
  2093
+                   spoilers_enabled = VBoolean("spoilers_enabled"))
  2094
+    def POST_setspoilersenabled(self, form, jquery, spoilers_enabled):
  2095
+        setattr(c.user, 'allow_spoilers_%d' % c.site._id, spoilers_enabled)
  2096
+        c.user._commit()
  2097
+        jquery.refresh()
2067 2098
 
2068 2099
     @validatedForm(
2069 2100
         VFlairManager(),
1  r2/r2/lib/js.py
@@ -243,6 +243,7 @@ def outputs(self):
243 243
     "login.js",
244 244
     "analytics.js",
245 245
     "flair.js",
  246
+    "spoilers.js",
246 247
     "reddit.js",
247 248
     "utils.js",
248 249
 )
1  r2/r2/lib/jsontemplates.py
@@ -252,6 +252,7 @@ class LinkJsonTemplate(ThingJsonTemplate):
252 252
                                                 clicked      = "clicked",
253 253
                                                 hidden       = "hidden",
254 254
                                                 over_18      = "over_18",
  255
+                                                spoiler      = "spoiler",
255 256
                                                 likes        = "likes",
256 257
                                                 domain       = "domain",
257 258
                                                 title        = "title",
19  r2/r2/lib/pages/pages.py
@@ -504,6 +504,11 @@ def __init__(self, site = None):
504 504
             self.flair_prefs = FlairPrefs()
505 505
         else:
506 506
             self.flair_prefs = None
  507
+            
  508
+        if c.user_is_loggedin and c.site.allow_spoilers:
  509
+            self.spoilers_prefs = SpoilersPrefs()
  510
+        else:
  511
+            self.spoilers_prefs = None
507 512
 
508 513
         CachedTemplate.__init__(self)
509 514
 
@@ -2629,6 +2634,20 @@ def __init__(self, user=None):
2629 2634
                            matching_template=matching_template,
2630 2635
                            wrapped_user=wrapped_user)
2631 2636
 
  2637
+class SpoilersPrefs(CachedTemplate):
  2638
+    def __init__(self):
  2639
+        sr_spoilers_enabled = getattr(c.site, 'allow_spoilers', False)
  2640
+        user_spoilers_enabled = getattr(c.user, 'allow_spoilers_%s' % c.site._id,
  2641
+                                     True)
  2642
+        
  2643
+        wrapped_user = WrappedUser(c.user, subreddit=c.site,
  2644
+                                   force_show_flair=True,
  2645
+                                   include_flair_selector=True)
  2646
+        CachedTemplate.__init__(
  2647
+            self,
  2648
+            sr_spoilers_enabled=sr_spoilers_enabled,
  2649
+            user_spoilers_enabled=user_spoilers_enabled,
  2650
+            wrapped_user=wrapped_user)
2632 2651
 
2633 2652
 class FriendList(UserList):
2634 2653
     """Friend list on /pref/friends"""
19  r2/r2/lib/pages/things.py
@@ -34,7 +34,8 @@ class PrintableButtons(Styled):
34 34
     def __init__(self, style, thing,
35 35
                  show_delete = False, show_report = True,
36 36
                  show_distinguish = False, show_marknsfw = False,
37  
-                 show_unmarknsfw = False, show_indict = False, is_link=False, **kw):
  37
+                 show_unmarknsfw = False, show_markspoiler = False, show_unmarkspoiler = False,
  38
+                 show_indict = False, is_link=False, **kw):
38 39
         show_ignore = (thing.show_reports or
39 40
                        (thing.reveal_trial_info and not thing.show_spam))
40 41
         approval_checkmark = getattr(thing, "approval_checkmark", None)
@@ -56,6 +57,8 @@ def __init__(self, style, thing,
56 57
                         show_distinguish = show_distinguish,
57 58
                         show_marknsfw = show_marknsfw,
58 59
                         show_unmarknsfw = show_unmarknsfw,
  60
+                        show_markspoiler = show_markspoiler,
  61
+                        show_unmarkspoiler = show_unmarkspoiler,
59 62
                         **kw)
60 63
         
61 64
 class BanButtons(PrintableButtons):
@@ -88,6 +91,18 @@ def __init__(self, thing, comments = True, delete = True, report = True):
88 91
             show_unmarknsfw = True
89 92
         else:
90 93
             show_unmarknsfw = False
  94
+            
  95
+        allow_spoilers = getattr(thing.subreddit, "allow_spoilers", False)
  96
+        
  97
+        if (thing.can_ban or is_author) and not thing.spoiler and allow_spoilers:
  98
+            show_markspoiler = True
  99
+        else:
  100
+            show_markspoiler = False
  101
+
  102
+        if (thing.can_ban or is_author) and thing.spoiler and allow_spoilers:
  103
+            show_unmarkspoiler = True
  104
+        else:
  105
+            show_unmarkspoiler = False
91 106
 
92 107
         # do we show the delete button?
93 108
         show_delete = is_author and delete and not thing._deleted
@@ -128,6 +143,8 @@ def __init__(self, thing, comments = True, delete = True, report = True):
128 143
                                   show_distinguish = show_distinguish,
129 144
                                   show_marknsfw = show_marknsfw,
130 145
                                   show_unmarknsfw = show_unmarknsfw,
  146
+                                  show_markspoiler = show_markspoiler,
  147
+                                  show_unmarkspoiler = show_unmarkspoiler,
131 148
                                   show_comments = comments,
132 149
                                   # promotion
133 150
                                   promoted = thing.promoted,
5  r2/r2/lib/wrapped.pyx
@@ -460,11 +460,14 @@ class CachedTemplate(Templated):
460 460
                 getattr(c.user, "gold", False),
461 461
                 template_hash]
462 462
 
463  
-        # if viewing a single subreddit, take flair settings into account.
  463
+        # if viewing a single subreddit, take flair and spoilers settings into account.
464 464
         if c.user and hasattr(c.site, '_id'):
465 465
             keys.extend([
466 466
                 c.site.flair_enabled, c.site.flair_position,
467 467
                 c.user.flair_enabled_in_sr(c.site._id),
  468
+                c.user.pref_show_flair,
  469
+                c.site.allow_spoilers,
  470
+                c.user.spoilers_enabled_in_sr(c.site._id),
468 471
                 c.user.pref_show_flair])
469 472
         keys = [make_cachable(x, *a) for x in keys]
470 473
 
3  r2/r2/models/account.py
@@ -543,6 +543,9 @@ def system_user(cls):
543 543
 
544 544
     def flair_enabled_in_sr(self, sr_id):
545 545
         return getattr(self, 'flair_%d_enabled' % sr_id, True)
  546
+        
  547
+    def spoilers_enabled_in_sr(self, sr_id):
  548
+        return getattr(self, 'allow_spoilers_%d' % sr_id, True)
546 549
 
547 550
 class FakeAccount(Account):
548 551
     _nodb = True
19  r2/r2/models/link.py
@@ -51,6 +51,7 @@ class Link(Thing, Printable):
@@ -226,6 +227,14 @@ def keep_item(self, wrapped):
@@ -358,9 +367,11 @@ def add_props(cls, user, wrapped):
@@ -371,6 +382,12 @@ def add_props(cls, user, wrapped):
1  r2/r2/models/modaction.py
@@ -63,6 +63,7 @@ class ModAction(tdb_cassandra.UuidThing, Printable):
63 63
                      'type': _('type'),
64 64
                      'link_type': _('link type'),
65 65
                      'over_18': _('toggle viewers must be over 18'),
  66
+                     'allow_spoilers': _('toggle allow spoiler posts'),
66 67
                      'allow_top': _('toggle allow in default set'),
67 68
                      'show_media': _('toggle show thumbnail images of content'),
68 69
                      'domain': _('domain'),
1  r2/r2/models/subreddit.py
@@ -66,6 +66,7 @@ class Subreddit(Thing, Printable):
66 66
                      css_on_cname = True,
67 67
                      domain = None,
68 68
                      over_18 = False,
  69
+                     allow_spoilers = False,
69 70
                      mod_actions = 0,
70 71
                      sponsorship_text = "this reddit is sponsored by",
71 72
                      sponsorship_url = None,
20  r2/r2/public/static/css/reddit.css
@@ -2740,6 +2740,21 @@ form input[type=radio] {margin: 2px .5em 0 0; }
2740 2740
     border-radius: 3px;
2741 2741
 }
2742 2742
 
  2743
+.entry .buttons li.spoiler-stamp {
  2744
+    font-size: x-small;
  2745
+}
  2746
+
  2747
+.spoiler-stamp acronym {
  2748
+    color: #336699;
  2749
+    font-size: x-small;
  2750
+    text-decoration: none;
  2751
+    padding: 0 2px;
  2752
+    border: 1px solid #5f99cf !important;
  2753
+    -moz-border-radius: 3px;
  2754
+    -webkit-border-radius: 3px;
  2755
+    border-radius: 3px;
  2756
+}
  2757
+
2743 2758
 .entry .buttons li.trial-stamp, .entry .buttons li.reported-stamp {
2744 2759
     border: 1px solid black !important;
2745 2760
     padding: 0 4px;
@@ -2813,6 +2828,11 @@ form input[type=radio] {margin: 2px .5em 0 0; }
2813 2828
     background-image: url(../nsfw2.png); /* SPRITE */
2814 2829
 }
2815 2830
 
  2831
+.thumbnail.spoiler {
  2832
+    height: 70px;
  2833
+    background-image: url(../spoiler2.png); /* SPRITE */
  2834
+}
  2835
+
2816 2836
 .thumbnail.self {
2817 2837
     height: 50px;
2818 2838
     background-image: url(../self_default2.png); /* SPRITE */
8  r2/r2/public/static/js/spoilers.js
... ...
@@ -0,0 +1,8 @@
  1
+$(function() {
  2
+    // Event handlers for sidebar spoilers prefs.
  3
+    $(".spoilerstoggle").submit(function() {
  4
+        return post_form(this, 'setspoilersenabled');
  5
+    });
  6
+    
  7
+    $(".spoilerstoggle input").change(function() { $(this).parent().submit(); });
  8
+});
BIN  r2/r2/public/static/spoiler2.png
8  r2/r2/templates/createsubreddit.html
@@ -163,6 +163,14 @@
163 163
             ${_("show thumbnail images of content")}
164 164
           </label>
165 165
         </li>
  166
+        <li>
  167
+          <input class="nomargin" type="checkbox" 
  168
+                 name="allow_spoilers" id="allow_spoilers"
  169
+                 ${thing.site and thing.site.allow_spoilers and "checked='checked'" or ""}/>
  170
+          <label for="allow spoilers">
  171
+            ${_("allow posts to be tagged as spoilers")}
  172
+          </label>
  173
+        </li>
166 174
       </ul>
167 175
     </div>
168 176
   </%utils:line_field>
9  r2/r2/templates/link.html
@@ -73,6 +73,13 @@
@@ -153,7 +160,7 @@
6  r2/r2/templates/printablebuttons.html
@@ -64,6 +64,12 @@
64 64
   %if thing.show_unmarknsfw:
65 65
     <li>${ynbutton(_("un-nsfw"), _("unmarked"), "unmarknsfw")}</li>
66 66
   %endif
  67
+  %if thing.show_markspoiler:
  68
+    <li>${ynbutton(_("spoiler"), _("spoilered"), "markspoiler")}</li>
  69
+  %endif
  70
+  %if thing.show_unmarkspoiler:
  71
+    <li>${ynbutton(_("un-spoiler"), _("unspoilered"), "unmarkspoiler")}</li>
  72
+  %endif
67 73
 </%def>
68 74
 
69 75
 <%def name="distinguish_setter(name, value=None)">
33  r2/r2/templates/spoilersprefs.html
... ...
@@ -0,0 +1,33 @@
  1
+## The contents of this file are subject to the Common Public Attribution
  2
+## License Version 1.0. (the "License"); you may not use this file except in
  3
+## compliance with the License. You may obtain a copy of the License at
  4
+## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
  5
+## License Version 1.1, but Sections 14 and 15 have been added to cover use of
  6
+## software over a computer network and provide for limited attribution for the
  7
+## Original Developer. In addition, Exhibit A has been modified to be consistent
  8
+## with Exhibit B.
  9
+##
  10
+## Software distributed under the License is distributed on an "AS IS" basis,
  11
+## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  12
+## the specific language governing rights and limitations under the License.
  13
+##
  14
+## The Original Code is Reddit.
  15
+##
  16
+## The Original Developer is the Initial Developer.  The Initial Developer of
  17
+## the Original Code is CondeNet, Inc.
  18
+##
  19
+## All portions of the code written by CondeNet are Copyright (c) 2006-2010
  20
+## CondeNet, Inc. All Rights Reserved.
  21
+################################################################################
  22
+
  23
+%if thing.sr_spoilers_enabled:
  24
+  <form class="toggle spoilerstoggle">
  25
+    <input id="spoilers_enabled" type="checkbox" name="spoilers_enabled"
  26
+        %if thing.user_spoilers_enabled:
  27
+          checked="checked"
  28
+        %endif
  29
+        >
  30
+    ${_("Show spoilers on this reddit.")}
  31
+  </form>
  32
+%endif
  33
+
4  r2/r2/templates/subredditinfobar.html
@@ -61,6 +61,10 @@ <h1 class="hover redditname">
61 61
   %if thing.flair_prefs:
62 62
     ${thing.flair_prefs}
63 63
   %endif
  64
+  
  65
+  %if thing.spoilers_prefs:
  66
+    ${thing.spoilers_prefs}
  67
+  %endif
64 68
 
65 69
   %if thing.sr.description:
66 70
     ${thing.sr.usertext}
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.