Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Adding a spoiler tag #333

Closed
wants to merge 1 commit into from

6 participants

@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).

@lahwran

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.

@lahwran

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?

@lahwran

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

@nallar

I would also love to see this accepted.

@spladug
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.

@spladug spladug closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 30, 2012
  1. @Tailszefox

    Added spoiler tag

    Tailszefox authored
This page is out of date. Refresh to see the latest.
View
35 r2/r2/controllers/api.py
@@ -716,6 +716,28 @@ def POST_unmarknsfw(self, thing):
# flag search indexer that something has changed
changed(thing)
+
+ @noresponse(VUser(),
+ VModhash(),
+ VSrCanAlter('id'),
+ thing = VByName('id'))
+ def POST_markspoiler(self, thing):
+ thing.spoiler = True
+ thing._commit()
+
+ # flag search indexer that something has changed
+ changed(thing)
+
+ @noresponse(VUser(),
+ VModhash(),
+ VSrCanAlter('id'),
+ thing = VByName('id'))
+ def POST_unmarkspoiler(self, thing):
+ thing.spoiler = False
+ thing._commit()
+
+ # flag search indexer that something has changed
+ changed(thing)
@noresponse(VUser(), VModhash(),
thing = VByName('id'))
@@ -1264,6 +1286,7 @@ def POST_upload_sr_img(self, file, header, sponsor, name, form_id, img_type):
over_18 = VBoolean('over_18'),
allow_top = VBoolean('allow_top'),
show_media = VBoolean('show_media'),
+ allow_spoilers = VBoolean('allow_spoilers'),
show_cname_sidebar = VBoolean('show_cname_sidebar'),
type = VOneOf('type', ('public', 'private', 'restricted', 'archived')),
link_type = VOneOf('link_type', ('any', 'link', 'self')),
@@ -1281,8 +1304,8 @@ def POST_site_admin(self, form, jquery, name, ip, sr,
redir = False
kw = dict((k, v) for k, v in kw.iteritems()
if k in ('name', 'title', 'domain', 'description', 'over_18',
- 'show_media', 'show_cname_sidebar', 'type', 'link_type', 'lang',
- "css_on_cname", "header_title",
+ 'show_media', 'allow_spoilers', 'show_cname_sidebar', 'type', 'link_type',
+ 'lang', "css_on_cname", "header_title",
'allow_top'))
#if a user is banned, return rate-limit errors
@@ -2064,6 +2087,14 @@ def POST_setflairenabled(self, form, jquery, flair_enabled):
setattr(c.user, 'flair_%s_enabled' % c.site._id, flair_enabled)
c.user._commit()
jquery.refresh()
+
+ @validatedForm(VUser(),
+ VModhash(),
+ spoilers_enabled = VBoolean("spoilers_enabled"))
+ def POST_setspoilersenabled(self, form, jquery, spoilers_enabled):
+ setattr(c.user, 'allow_spoilers_%d' % c.site._id, spoilers_enabled)
+ c.user._commit()
+ jquery.refresh()
@validatedForm(
VFlairManager(),
View
1  r2/r2/lib/js.py
@@ -243,6 +243,7 @@ def outputs(self):
"login.js",
"analytics.js",
"flair.js",
+ "spoilers.js",
"reddit.js",
"utils.js",
)
View
1  r2/r2/lib/jsontemplates.py
@@ -252,6 +252,7 @@ class LinkJsonTemplate(ThingJsonTemplate):
clicked = "clicked",
hidden = "hidden",
over_18 = "over_18",
+ spoiler = "spoiler",
likes = "likes",
domain = "domain",
title = "title",
View
19 r2/r2/lib/pages/pages.py
@@ -504,6 +504,11 @@ def __init__(self, site = None):
self.flair_prefs = FlairPrefs()
else:
self.flair_prefs = None
+
+ if c.user_is_loggedin and c.site.allow_spoilers:
+ self.spoilers_prefs = SpoilersPrefs()
+ else:
+ self.spoilers_prefs = None
CachedTemplate.__init__(self)
@@ -2629,6 +2634,20 @@ def __init__(self, user=None):
matching_template=matching_template,
wrapped_user=wrapped_user)
+class SpoilersPrefs(CachedTemplate):
+ def __init__(self):
+ sr_spoilers_enabled = getattr(c.site, 'allow_spoilers', False)
+ user_spoilers_enabled = getattr(c.user, 'allow_spoilers_%s' % c.site._id,
+ True)
+
+ wrapped_user = WrappedUser(c.user, subreddit=c.site,
+ force_show_flair=True,
+ include_flair_selector=True)
+ CachedTemplate.__init__(
+ self,
+ sr_spoilers_enabled=sr_spoilers_enabled,
+ user_spoilers_enabled=user_spoilers_enabled,
+ wrapped_user=wrapped_user)
class FriendList(UserList):
"""Friend list on /pref/friends"""
View
19 r2/r2/lib/pages/things.py
@@ -34,7 +34,8 @@ class PrintableButtons(Styled):
def __init__(self, style, thing,
show_delete = False, show_report = True,
show_distinguish = False, show_marknsfw = False,
- show_unmarknsfw = False, show_indict = False, is_link=False, **kw):
+ show_unmarknsfw = False, show_markspoiler = False, show_unmarkspoiler = False,
+ show_indict = False, is_link=False, **kw):
show_ignore = (thing.show_reports or
(thing.reveal_trial_info and not thing.show_spam))
approval_checkmark = getattr(thing, "approval_checkmark", None)
@@ -56,6 +57,8 @@ def __init__(self, style, thing,
show_distinguish = show_distinguish,
show_marknsfw = show_marknsfw,
show_unmarknsfw = show_unmarknsfw,
+ show_markspoiler = show_markspoiler,
+ show_unmarkspoiler = show_unmarkspoiler,
**kw)
class BanButtons(PrintableButtons):
@@ -88,6 +91,18 @@ def __init__(self, thing, comments = True, delete = True, report = True):
show_unmarknsfw = True
else:
show_unmarknsfw = False
+
+ allow_spoilers = getattr(thing.subreddit, "allow_spoilers", False)
+
+ if (thing.can_ban or is_author) and not thing.spoiler and allow_spoilers:
+ show_markspoiler = True
+ else:
+ show_markspoiler = False
+
+ if (thing.can_ban or is_author) and thing.spoiler and allow_spoilers:
+ show_unmarkspoiler = True
+ else:
+ show_unmarkspoiler = False
# do we show the delete button?
show_delete = is_author and delete and not thing._deleted
@@ -128,6 +143,8 @@ def __init__(self, thing, comments = True, delete = True, report = True):
show_distinguish = show_distinguish,
show_marknsfw = show_marknsfw,
show_unmarknsfw = show_unmarknsfw,
+ show_markspoiler = show_markspoiler,
+ show_unmarkspoiler = show_unmarkspoiler,
show_comments = comments,
# promotion
promoted = thing.promoted,
View
5 r2/r2/lib/wrapped.pyx
@@ -460,11 +460,14 @@ class CachedTemplate(Templated):
getattr(c.user, "gold", False),
template_hash]
- # if viewing a single subreddit, take flair settings into account.
+ # if viewing a single subreddit, take flair and spoilers settings into account.
if c.user and hasattr(c.site, '_id'):
keys.extend([
c.site.flair_enabled, c.site.flair_position,
c.user.flair_enabled_in_sr(c.site._id),
+ c.user.pref_show_flair,
+ c.site.allow_spoilers,
+ c.user.spoilers_enabled_in_sr(c.site._id),
c.user.pref_show_flair])
keys = [make_cachable(x, *a) for x in keys]
View
3  r2/r2/models/account.py
@@ -543,6 +543,9 @@ def system_user(cls):
def flair_enabled_in_sr(self, sr_id):
return getattr(self, 'flair_%d_enabled' % sr_id, True)
+
+ def spoilers_enabled_in_sr(self, sr_id):
+ return getattr(self, 'allow_spoilers_%d' % sr_id, True)
class FakeAccount(Account):
_nodb = True
View
19 r2/r2/models/link.py
@@ -51,6 +51,7 @@ class Link(Thing, Printable):
_defaults = dict(is_self = False,
over_18 = False,
nsfw_str = False,
+ spoiler = False,
reported = 0, num_comments = 0,
moderator_banned = False,
banned_before_moderator = False,
@@ -226,6 +227,14 @@ def keep_item(self, wrapped):
if is_nsfw or is_from_nsfw_sr:
return False
+ # hide spoilered links if the user doesn't want to see them
+ if(c.user_is_loggedin):
+ is_spoiler = bool(wrapped.spoiler)
+ show_spoilers = getattr(user, 'allow_spoilers_%d' % wrapped.subreddit._id, True)
+
+ if(is_spoiler and not show_spoilers):
+ return False
+
return True
# none of these things will change over a link's lifetime
@@ -358,9 +367,11 @@ def add_props(cls, user, wrapped):
item.over_18 = bool(item.over_18 or item.subreddit.over_18 or
item.nsfw_str)
item.nsfw = item.over_18 and user.pref_label_nsfw
-
item.is_author = (user == item.author)
+ if item.spoiler and not getattr(item.subreddit, "allow_spoilers", False):
+ item.spoiler = False
+
item.thumbnail_sprited = False
# always show a promo author their own thumbnail
if item.promoted and (user_is_admin or item.is_author) and item.has_thumbnail:
@@ -371,6 +382,12 @@ def add_props(cls, user, wrapped):
item.thumbnail_sprited = True
else:
item.thumbnail = ""
+ elif item.spoiler:
+ if show_media:
+ item.thumbnail = "spoiler"
+ item.thumbnail_sprited = True
+ else:
+ item.thumbnail = ""
elif not show_media:
item.thumbnail = ""
elif item.has_thumbnail:
View
1  r2/r2/models/modaction.py
@@ -63,6 +63,7 @@ class ModAction(tdb_cassandra.UuidThing, Printable):
'type': _('type'),
'link_type': _('link type'),
'over_18': _('toggle viewers must be over 18'),
+ 'allow_spoilers': _('toggle allow spoiler posts'),
'allow_top': _('toggle allow in default set'),
'show_media': _('toggle show thumbnail images of content'),
'domain': _('domain'),
View
1  r2/r2/models/subreddit.py
@@ -66,6 +66,7 @@ class Subreddit(Thing, Printable):
css_on_cname = True,
domain = None,
over_18 = False,
+ allow_spoilers = False,
mod_actions = 0,
sponsorship_text = "this reddit is sponsored by",
sponsorship_url = None,
View
20 r2/r2/public/static/css/reddit.css
@@ -2740,6 +2740,21 @@ form input[type=radio] {margin: 2px .5em 0 0; }
border-radius: 3px;
}
+.entry .buttons li.spoiler-stamp {
+ font-size: x-small;
+}
+
+.spoiler-stamp acronym {
+ color: #336699;
+ font-size: x-small;
+ text-decoration: none;
+ padding: 0 2px;
+ border: 1px solid #5f99cf !important;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+}
+
.entry .buttons li.trial-stamp, .entry .buttons li.reported-stamp {
border: 1px solid black !important;
padding: 0 4px;
@@ -2813,6 +2828,11 @@ form input[type=radio] {margin: 2px .5em 0 0; }
background-image: url(../nsfw2.png); /* SPRITE */
}
+.thumbnail.spoiler {
+ height: 70px;
+ background-image: url(../spoiler2.png); /* SPRITE */
+}
+
.thumbnail.self {
height: 50px;
background-image: url(../self_default2.png); /* SPRITE */
View
8 r2/r2/public/static/js/spoilers.js
@@ -0,0 +1,8 @@
+$(function() {
+ // Event handlers for sidebar spoilers prefs.
+ $(".spoilerstoggle").submit(function() {
+ return post_form(this, 'setspoilersenabled');
+ });
+
+ $(".spoilerstoggle input").change(function() { $(this).parent().submit(); });
+});
View
BIN  r2/r2/public/static/spoiler2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
8 r2/r2/templates/createsubreddit.html
@@ -163,6 +163,14 @@
${_("show thumbnail images of content")}
</label>
</li>
+ <li>
+ <input class="nomargin" type="checkbox"
+ name="allow_spoilers" id="allow_spoilers"
+ ${thing.site and thing.site.allow_spoilers and "checked='checked'" or ""}/>
+ <label for="allow spoilers">
+ ${_("allow posts to be tagged as spoilers")}
+ </label>
+ </li>
</ul>
</div>
</%utils:line_field>
View
9 r2/r2/templates/link.html
@@ -73,6 +73,13 @@
</acronym>
</li>
%endif
+ %if thing.spoiler:
+ <li class="rounded spoiler-stamp stamp">
+ <acronym title="${_('Spoiler content')}">
+ ${_("SPOILER")}
+ </acronym>
+ </li>
+ %endif
${self.buttons()}
${self.admintagline()}
</ul>
@@ -153,7 +160,7 @@
</%def>
<%def name="thing_css_class(what)" buffered="True">
-${parent.thing_css_class(what)} ${"over18" if thing.over_18 else ""}
+${parent.thing_css_class(what)} ${"over18" if thing.over_18 else ""} ${"spoiler" if thing.spoiler else ""}
</%def>
<%def name="subreddit()" buffered="True">
View
6 r2/r2/templates/printablebuttons.html
@@ -64,6 +64,12 @@
%if thing.show_unmarknsfw:
<li>${ynbutton(_("un-nsfw"), _("unmarked"), "unmarknsfw")}</li>
%endif
+ %if thing.show_markspoiler:
+ <li>${ynbutton(_("spoiler"), _("spoilered"), "markspoiler")}</li>
+ %endif
+ %if thing.show_unmarkspoiler:
+ <li>${ynbutton(_("un-spoiler"), _("unspoilered"), "unmarkspoiler")}</li>
+ %endif
</%def>
<%def name="distinguish_setter(name, value=None)">
View
33 r2/r2/templates/spoilersprefs.html
@@ -0,0 +1,33 @@
+## The contents of this file are subject to the Common Public Attribution
+## License Version 1.0. (the "License"); you may not use this file except in
+## compliance with the License. You may obtain a copy of the License at
+## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
+## License Version 1.1, but Sections 14 and 15 have been added to cover use of
+## software over a computer network and provide for limited attribution for the
+## Original Developer. In addition, Exhibit A has been modified to be consistent
+## with Exhibit B.
+##
+## Software distributed under the License is distributed on an "AS IS" basis,
+## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+## the specific language governing rights and limitations under the License.
+##
+## The Original Code is Reddit.
+##
+## The Original Developer is the Initial Developer. The Initial Developer of
+## the Original Code is CondeNet, Inc.
+##
+## All portions of the code written by CondeNet are Copyright (c) 2006-2010
+## CondeNet, Inc. All Rights Reserved.
+################################################################################
+
+%if thing.sr_spoilers_enabled:
+ <form class="toggle spoilerstoggle">
+ <input id="spoilers_enabled" type="checkbox" name="spoilers_enabled"
+ %if thing.user_spoilers_enabled:
+ checked="checked"
+ %endif
+ >
+ ${_("Show spoilers on this reddit.")}
+ </form>
+%endif
+
View
4 r2/r2/templates/subredditinfobar.html
@@ -61,6 +61,10 @@ <h1 class="hover redditname">
%if thing.flair_prefs:
${thing.flair_prefs}
%endif
+
+ %if thing.spoilers_prefs:
+ ${thing.spoilers_prefs}
+ %endif
%if thing.sr.description:
${thing.sr.usertext}
Something went wrong with that request. Please try again.