From 5448f36c3126b179e20ef4edd55a30a80a5ddf82 Mon Sep 17 00:00:00 2001 From: spez Date: Fri, 7 Nov 2008 10:31:25 -0800 Subject: [PATCH] Replaced the subreddit box on the side with a bar across the top that lists reddits. Removed all subreddit-subscribe checkboxes. Limited the number of reddits that can make up a frontpag (to 25 for now). Removed links to /reddit/mine and instead show a user's subscriptions in a sidebox on /reddits. --- r2/r2/config/routing.py | 2 +- r2/r2/controllers/__init__.py | 3 +- r2/r2/controllers/api.py | 18 +--- r2/r2/controllers/listingcontroller.py | 8 +- r2/r2/controllers/reddit_base.py | 9 ++ r2/r2/controllers/validator/validator.py | 12 --- r2/r2/lib/menus.py | 52 +++++---- r2/r2/lib/pages/pages.py | 102 +++++++++++++----- r2/r2/lib/strings.py | 2 +- r2/r2/lib/wrapped.py | 4 + r2/r2/models/subreddit.py | 32 ++---- r2/r2/public/static/droparrowwhite.gif | Bin 0 -> 67 bytes r2/r2/public/static/eye.png | Bin 0 -> 633 bytes r2/r2/public/static/key_green.png | Bin 703 -> 0 bytes r2/r2/public/static/key_red.png | Bin 724 -> 0 bytes r2/r2/public/static/over18_icon.png | Bin 0 -> 306 bytes r2/r2/public/static/pencil-gray.png | Bin 0 -> 546 bytes r2/r2/public/static/pencil.png | Bin 0 -> 450 bytes r2/r2/public/static/reddit.css | 128 ++++++++++++++++++++--- r2/r2/public/static/reddit_piece.js | 95 ++++++++++++++--- r2/r2/public/static/sr-add-button.png | Bin 0 -> 985 bytes r2/r2/public/static/sr-remove-button.png | Bin 0 -> 1452 bytes r2/r2/public/static/star.png | Bin 0 -> 566 bytes r2/r2/public/static/subreddit.js | 14 ++- r2/r2/public/static/utils.js | 16 --- r2/r2/public/static/vote_piece.js | 2 +- r2/r2/templates/base.html | 2 + r2/r2/templates/navmenu.html | 20 ++-- r2/r2/templates/printable.html | 3 +- r2/r2/templates/reddit.html | 1 + r2/r2/templates/redditheader.html | 8 +- r2/r2/templates/subreddit.html | 51 ++++++--- r2/r2/templates/subredditbox.html | 11 +- r2/r2/templates/subredditinfobar.html | 8 +- r2/r2/templates/subreddittopbar.html | 29 +++++ r2/r2/templates/subscriptionbox.html | 36 +++++++ r2/r2/templates/userlist.html | 10 +- r2/r2/templates/utils.html | 4 +- 38 files changed, 470 insertions(+), 212 deletions(-) create mode 100644 r2/r2/public/static/droparrowwhite.gif create mode 100644 r2/r2/public/static/eye.png delete mode 100644 r2/r2/public/static/key_green.png delete mode 100644 r2/r2/public/static/key_red.png create mode 100644 r2/r2/public/static/over18_icon.png create mode 100644 r2/r2/public/static/pencil-gray.png create mode 100755 r2/r2/public/static/pencil.png create mode 100644 r2/r2/public/static/sr-add-button.png create mode 100644 r2/r2/public/static/sr-remove-button.png create mode 100644 r2/r2/public/static/star.png create mode 100644 r2/r2/templates/subreddittopbar.html create mode 100644 r2/r2/templates/subscriptionbox.html diff --git a/r2/r2/config/routing.py b/r2/r2/config/routing.py index 5f32b8b83..4a42671fa 100644 --- a/r2/r2/config/routing.py +++ b/r2/r2/config/routing.py @@ -51,7 +51,7 @@ def make_map(global_conf={}, app_conf={}): mc('/reddits/:where', controller='reddits', action='listing', where = 'popular', requirements=dict(where="popular|new|banned")) - + mc('/reddits/mine/:where', controller='myreddits', action='listing', where='subscriber', requirements=dict(where='subscriber|contributor|moderator')) diff --git a/r2/r2/controllers/__init__.py b/r2/r2/controllers/__init__.py index 96ed1b36f..dddad0535 100644 --- a/r2/r2/controllers/__init__.py +++ b/r2/r2/controllers/__init__.py @@ -28,12 +28,13 @@ from listingcontroller import BrowseController from listingcontroller import RecommendedController from listingcontroller import MessageController from listingcontroller import RedditsController -from listingcontroller import MyredditsController from listingcontroller import ByIDController as ByidController from listingcontroller import RandomrisingController from listingcontroller import UserController from listingcontroller import CommentsController +from listingcontroller import MyredditsController + from feedback import FeedbackController from front import FrontController from buttons import ButtonsController diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index 041a92fec..b446e4f23 100644 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -102,21 +102,6 @@ class ApiController(RedditController): content = listing).render() return res - @Json - @validate(dest = nop('dest')) - def POST_subscriptions(self, res, dest): - """Updates a user's subscriptions after fiddling with them in the sr - sidebar""" - subs = {} - for k, v in request.post.iteritems(): - if k.startswith('sr_sel_chx_'): - subs[k[11:]] = (v == 'on') - - for sr in Subreddit._by_fullname(subs.keys(), data = True, - return_dict = False): - self._subscribe(sr, subs[sr._fullname]) - res._redirect(dest) - @Json @validate(VCaptcha(), name=VRequired('name', errors.NO_NAME), @@ -406,12 +391,11 @@ class ApiController(RedditController): self._login(res, user, dest, rem) - + @Json @validate(VUser(), VModhash(), container = VByName('id'), type = VOneOf('location', ('moderator', 'contributor'))) - @Json def POST_leave(self, res, container, type): if container and c.user: res._hide("pre_" + container._fullname) diff --git a/r2/r2/controllers/listingcontroller.py b/r2/r2/controllers/listingcontroller.py index e3604c799..9da3240ac 100644 --- a/r2/r2/controllers/listingcontroller.py +++ b/r2/r2/controllers/listingcontroller.py @@ -238,7 +238,6 @@ class HotController(FixListing, ListingController): def title(self): return c.site.title - @validate(VSrMask('srs')) def GET_listing(self, **env): self.infotext = request.get.get('deleted') and strings.user_deleted return ListingController.GET_listing(self, **env) @@ -262,7 +261,6 @@ class ToplinksController(ListingController): def query(self): return c.site.get_links('toplinks', 'all') - @validate(VSrMask('srs')) def GET_listing(self, **env): return ListingController.GET_listing(self, **env) @@ -280,8 +278,7 @@ class NewController(ListingController): else: return c.site.get_links('new', 'all') - @validate(VSrMask('srs'), - sort = VMenu('controller', NewMenu)) + @validate(sort = VMenu('controller', NewMenu)) def GET_listing(self, sort, **env): self.sort = sort return ListingController.GET_listing(self, **env) @@ -297,8 +294,7 @@ class BrowseController(ListingController): return c.site.get_links(self.sort, self.time) # TODO: this is a hack with sort. - @validate(VSrMask('srs'), - sort = VOneOf('sort', ('top', 'controversial')), + @validate(sort = VOneOf('sort', ('top', 'controversial')), time = VMenu('where', ControversyTimeMenu)) def GET_listing(self, sort, time, **env): self.sort = sort diff --git a/r2/r2/controllers/reddit_base.py b/r2/r2/controllers/reddit_base.py index 1ccba649a..d11261e3e 100644 --- a/r2/r2/controllers/reddit_base.py +++ b/r2/r2/controllers/reddit_base.py @@ -347,6 +347,14 @@ def set_colors(): if color_rx.match(request.get.get('bordercolor') or ''): c.bordercolor = request.get.get('bordercolor') +def set_recent_reddits(): + names = read_user_cookie('recent_reddits') + c.recent_reddits = [] + if names: + names = filter(None, names.split(',')) + c.recent_reddits = Subreddit._by_fullname(names, data = True, + return_dict = False) + def ratelimit_agents(): user_agent = request.user_agent for s in g.agents: @@ -484,6 +492,7 @@ class RedditController(BaseController): set_iface_lang() set_content_lang() set_colors() + set_recent_reddits() # set some environmental variables in case we hit an abort if not isinstance(c.site, FakeSubreddit): diff --git a/r2/r2/controllers/validator/validator.py b/r2/r2/controllers/validator/validator.py index 5d191f3cc..0e000eaa9 100644 --- a/r2/r2/controllers/validator/validator.py +++ b/r2/r2/controllers/validator/validator.py @@ -115,18 +115,6 @@ class VRequired(Validator): else: return item -class VSrMask(Validator): - def run(self, masks): - # only work for main reddit - if c.site == Default and masks: - mask_sr = MaskedSR() - masks = [m.split(":")[:2] for m in masks.split(',')] - masks = dict((k, int(v)) for k, v in masks) - mask_sr.set_mask(masks) - c.site = mask_sr - c.subreddit_sidebox = True - c.subreddit_checkboxes = True - class VLink(Validator): def __init__(self, param, redirect = True, *a, **kw): Validator.__init__(self, param, *a, **kw) diff --git a/r2/r2/lib/menus.py b/r2/r2/lib/menus.py index 6d6e96fcb..139fba138 100644 --- a/r2/r2/lib/menus.py +++ b/r2/r2/lib/menus.py @@ -115,6 +115,7 @@ menu = MenuHandler(hot = _('hot'), details = _("details"), # reddits + home = _("home"), about = _("about"), edit = _("edit"), banned = _("banned"), @@ -177,6 +178,7 @@ def menu_style(type): d = dict(heavydrop = ('dropdown', 'heavydrop'), lightdrop = ('dropdown', 'lightdrop'), tabdrop = ('dropdown', 'tabdrop'), + srdrop = ('dropdown', 'srdrop'), flatlist = ('flatlist', ''), tabmenu = ('tabmenu', ''), ) @@ -191,11 +193,14 @@ class NavMenu(Styled): can be used to set individualized CSS.""" def __init__(self, options, default = None, title = '', type = "dropdown", - base_path = '', **kw): + base_path = '', separator = '|', **kw): self.options = options self.base_path = base_path kw['style'], kw['css_class'] = menu_style(type) + #used by flatlist to delimit menu items + self.separator = separator + # since the menu contains the path info, it's buttons need a # configuration pass to get them pointing to the proper urls for opt in self.options: @@ -204,32 +209,23 @@ class NavMenu(Styled): # selected holds the currently selected button defined as the # one whose path most specifically matches the current URL # (possibly None) - self.selected = None + self.default = default + self.selected = self.find_selected() + + Styled.__init__(self, title = title, **kw) + + def find_selected(self): maybe_selected = [o for o in self.options if o.is_selected()] if maybe_selected: # pick the button with the most restrictive pathing maybe_selected.sort(lambda x, y: len(y.bare_path) - len(x.bare_path)) - self.selected = maybe_selected[0] - elif default: + return maybe_selected[0] + elif self.default: #lookup the menu with the 'dest' that matches 'default' for opt in self.options: - if opt.dest == default: - self.selected = opt - break - - Styled.__init__(self, title = title, **kw) - -# def render(self, **kw): -# prefix = unicode((c.lang, kw.get('style'), self.base_path, c.site.name, -# self.selected and self.selected.title)).encode('utf8') -# key = unicode([(opt.title, opt.path) for opt in self]).encode('utf8') -# r = cache.get(prefix + key) -# if not r: -# r = Styled.render(self, **kw) -# cache.set(prefix + key, r, g.page_cache_time) -# return r - + if opt.dest == self.default: + return opt def __repr__(self): return "" @@ -295,6 +291,17 @@ class NavButton(Styled): when it is different from self.title)""" return self.title +class SubredditButton(NavButton): + def __init__(self, sr): + self.sr = sr + NavButton.__init__(self, sr.name, sr.path, False) + + def build(self, base_path = ''): + self.path = self.sr.path + + def is_selected(self): + return c.site == self.sr + class NamedButton(NavButton): """Convenience class for handling the majority of NavButtons @@ -499,6 +506,11 @@ class NumCommentsMenu(SimpleGetMenu): return "" return SimpleGetMenu.render(self, **kw) +class SubredditMenu(NavMenu): + def find_selected(self): + """Always return False so the title is always displayed""" + return None + # -------------------- # TODO: move to admin area class AdminReporterMenu(SortMenu): diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index a07de7c47..da1c7377f 100644 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -30,7 +30,8 @@ from pylons.controllers.util import abort from r2.lib.captcha import get_iden from r2.lib.filters import spaceCompress, _force_unicode, _force_utf8 -from r2.lib.menus import NavButton, NamedButton, NavMenu, PageNameNav, JsButton, menu +from r2.lib.menus import NavButton, NamedButton, NavMenu, PageNameNav, JsButton +from r2.lib.menus import SubredditButton, SubredditMenu, menu from r2.lib.strings import plurals, rand_strings, strings from r2.lib.utils import title_to_url, query_string, UrlParser from r2.lib.template_helpers import add_sr, get_domain @@ -93,12 +94,9 @@ class Reddit(Wrapped): if infotext: self.infobar = InfoBar(message = infotext) - #c.subredditbox is set by VSRMask - self.subreddit_sidebox = False - #don't show the sidebox on cnames - if c.subreddit_sidebox and not c.cname: - self.subreddit_sidebox = True - self.subreddit_checkboxes = c.site == Default + self.srtopbar = None + if not c.cname: + self.srtopbar = SubredditTopBar() if c.user_is_loggedin and self.show_sidebar: self._content = PaneStack([ShareLink(), content]) @@ -119,9 +117,6 @@ class Reddit(Wrapped): if not isinstance(c.site, FakeSubreddit) and not c.cname: ps.append(SubredditInfoBar()) - if self.subreddit_sidebox: - ps.append(SubredditBox(self.subreddit_checkboxes)) - if self.submit_box: ps.append(SideBox(_('Submit a link'), '/submit', 'submit', @@ -264,10 +259,11 @@ class SubredditInfoBar(Wrapped): c.site.is_moderator(c.user) or c.user_is_admin buttons = [NavButton(plurals.moderators, 'moderators')] + if c.site.type != 'public': + buttons.append(NavButton(plurals.contributors, 'contributors')) + if is_moderator: buttons.append(NamedButton('edit')) - if c.site.type != 'public': - buttons.append(NavButton(plurals.contributors, 'contributors')) buttons.extend([NavButton(menu.banusers, 'banned'), NamedButton('spam')]) return [NavMenu(buttons, type = "flatlist", base_path = "/about/")] @@ -517,11 +513,13 @@ class SubredditsPage(Reddit): NamedButton("new")] if c.user_is_admin: buttons.append(NamedButton("banned")) - if c.user_is_loggedin: - #add the aliases to "my reddits" stays highlighted - buttons.append(NamedButton("mine", aliases=['/reddits/mine/subscriber', - '/reddits/mine/contributor', - '/reddits/mine/moderator'])) + + #removing the 'my reddits' listing for now + #if c.user_is_loggedin: + # #add the aliases to "my reddits" stays highlighted + # buttons.append(NamedButton("mine", aliases=['/reddits/mine/subscriber', + # '/reddits/mine/contributor', + # '/reddits/mine/moderator'])) return [PageNameNav('reddits'), @@ -531,6 +529,11 @@ class SubredditsPage(Reddit): return self.content_stack(self.searchbar, self.nav_menu, self.sr_infobar, self._content) + def rightbox(self): + ps = Reddit.rightbox(self) + ps.append(SubscriptionBox()) + return ps + class MySubredditsPage(SubredditsPage): """Same functionality as SubredditsPage, without the search box.""" @@ -630,19 +633,52 @@ class Over18(Wrapped): """The creepy 'over 18' check page for nsfw content.""" pass +class SubredditTopBar(Wrapped): + """The horizontal strip at the top of most pages for navigating + user-created reddits.""" + def __init__(self): + Wrapped.__init__(self) + + my_reddits = [] + sr_ids = Subreddit.user_subreddits(c.user if c.user_is_loggedin else None) + if sr_ids: + my_reddits = Subreddit._byID(sr_ids, True, + return_dict = False) + my_reddits.sort(key = lambda sr: sr.name.lower()) + + drop_down_buttons = [] + for sr in my_reddits: + drop_down_buttons.append(SubredditButton(sr)) + + #leaving the 'home' option out for now + #drop_down_buttons.insert(0, NamedButton(_('home'), sr_path = False, + # css_class = 'top-option', + # dest = '/')) + drop_down_buttons.append(NamedButton(_('edit'), sr_path = False, + css_class = 'bottom-option', + dest = '/reddits/')) + self.sr_dropdown = SubredditMenu(drop_down_buttons, + title = _('my reddits'), + type = 'srdrop') + + + pop_reddits = Subreddit.default_srs(c.content_langs, limit = 30) + buttons = [SubredditButton(sr) for sr in c.recent_reddits] + for sr in pop_reddits: + if sr not in c.recent_reddits: + buttons.append(SubredditButton(sr)) + + self.sr_bar = NavMenu(buttons, type='flatlist', separator = '-', + _id = 'sr-bar') + class SubredditBox(Wrapped): """A content pane that has the lists of subreddits that go in the right pane by default""" - def __init__(self, checkboxes = True): + def __init__(self): Wrapped.__init__(self) - - self.checkboxes = checkboxes - if checkboxes: - self.title = _('Customize your reddit') - self.subtitle = _('Select which communities you want to see') - else: - self.title = _('Other reddit communities') - self.subtitle = 'Visit your subscribed reddits (in bold) or explore new ones' + + self.title = _('Other reddit communities') + self.subtitle = 'Visit your subscribed reddits (in bold) or explore new ones' self.create_link = ('/reddits/', menu.more) self.more_link = ('/reddits/create', _('create')) @@ -680,6 +716,16 @@ class SubredditBox(Wrapped): self.cols = ((col1, col2)) self.mine = my_reddits +class SubscriptionBox(Wrapped): + """The list of reddits a user is currently subscribed to to go in + the right pane.""" + def __init__(self): + sr_ids = Subreddit.user_subreddits(c.user if c.user_is_loggedin else None) + srs = Subreddit._byID(sr_ids, True, return_dict = False) + srs.sort(key = lambda sr: sr.name.lower()) + b = IDBuilder([sr._fullname for sr in srs]) + self.reddits = LinkListing(b).listing().things + class CreateSubreddit(Wrapped): """reddit creation form.""" def __init__(self, site = None, name = ''): @@ -1061,7 +1107,7 @@ class ContributorList(UserList): @property def table_title(self): - return plurals.contributors + return _("contributors to %(reddit)s") % dict(reddit = c.site.name) def user_ids(self): return c.site.contributors @@ -1076,7 +1122,7 @@ class ModList(UserList): @property def table_title(self): - return plurals.moderators + return _("moderators to %(reddit)s") % dict(reddit = c.site.name) def user_ids(self): return c.site.moderators diff --git a/r2/r2/lib/strings.py b/r2/r2/lib/strings.py index ec80848fa..3e80d7268 100644 --- a/r2/r2/lib/strings.py +++ b/r2/r2/lib/strings.py @@ -89,7 +89,7 @@ string_dict = dict( moderator = _('below are the reddits that you have moderator access to.') ), - sr_subscribe = _('click the checkbox next to a reddit to subscribe'), + sr_subscribe = _('click the ![add](/static/sr-add-button.png) or ![remove](/static/sr-remove-button.png) buttons to choose which reddits appear on your front page.'), searching_a_reddit = _('you\'re searching within the [%(reddit_name)s](%(reddit_link)s) reddit. '+ 'you can also search within [all reddits](%(all_reddits_link)s)'), diff --git a/r2/r2/lib/wrapped.py b/r2/r2/lib/wrapped.py index 302a49710..31a3e9236 100644 --- a/r2/r2/lib/wrapped.py +++ b/r2/r2/lib/wrapped.py @@ -36,6 +36,10 @@ class Wrapped(object): def __getattr__(self, attr): #print "GETATTR: " + str(attr) + #one would think this would never happen + if attr == 'lookups': + raise AttributeError, attr + res = None found = False for lookup in self.lookups: diff --git a/r2/r2/models/subreddit.py b/r2/r2/models/subreddit.py index da77225bb..9123909d9 100644 --- a/r2/r2/models/subreddit.py +++ b/r2/r2/models/subreddit.py @@ -33,6 +33,7 @@ from r2.lib.strings import strings, Score from r2.lib.filters import _force_unicode import os.path +import random class Subreddit(Thing, Printable): _defaults = dict(static_path = g.static_path, @@ -235,7 +236,7 @@ class Subreddit(Thing, Printable): rels = (SRMember._fast_query(wrapped, [user], names) if user else {}) defaults = Subreddit.default_srs(c.content_langs, ids = True) for item in wrapped: - if user and not user.has_subscribed: + if not user or not user.has_subscribed: item.subscriber = item._id in defaults else: item.subscriber = rels.get((item, user, 'subscriber')) @@ -293,7 +294,11 @@ class Subreddit(Thing, Printable): """subreddits that appear in a user's listings. returns the default srs if there are no subscriptions.""" if user and user.has_subscribed: - return Subreddit.reverse_subscriber_ids(user) + sr_ids = Subreddit.reverse_subscriber_ids(user) + if len(sr_ids) > 25: + return random.sample(sr_ids, 25) + else: + return sr_ids else: return cls.default_srs(c.content_langs, ids = True) @@ -503,29 +508,6 @@ class DefaultSR(FakeSubreddit): def title(self): return _("reddit.com: what's new online!") -class MaskedSR(DefaultSR): - def set_mask(self, mask): - self.show_sr = [] - self.hide_sr = [] - for k, v in mask.iteritems(): - if v: - self.show_sr.append(k) - else: - self.hide_sr.append(k) - self.show_sr = Subreddit._by_fullname(self.show_sr, - return_dict = False) - self.show_sr = [s._id for s in self.show_sr] - self.hide_sr = Subreddit._by_fullname(self.hide_sr, - return_dict = False) - self.hide_sr = [s._id for s in self.hide_sr] - - def get_links(self, sort, time): - user = c.user if c.user_is_loggedin else None - sr_ids = Subreddit.user_subreddits(user) - sr_ids = [s for s in sr_ids if s not in self.hide_sr] - sr_ids.extend(self.show_sr) - return self.get_links_sr_ids(sr_ids, sort, time) - class MultiReddit(DefaultSR): name = 'multi' diff --git a/r2/r2/public/static/droparrowwhite.gif b/r2/r2/public/static/droparrowwhite.gif new file mode 100644 index 0000000000000000000000000000000000000000..96ada71de7a2277a840ba47847dabf41cc90f0a4 GIT binary patch literal 67 zcmZ?wbhEHb6lD-#XkcXc4+e@qSr{1@7#VaJfB+=Jz$Devzw-23{>5|nZgd|!ZBe9~ Q8dA{9ma*)Wl_-NX0NlJ5vH$=8 literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/eye.png b/r2/r2/public/static/eye.png new file mode 100644 index 0000000000000000000000000000000000000000..aaca263723f56928cfb7b52b372019b41adc7ba0 GIT binary patch literal 633 zcmV-<0*3vGP)PwIBNynBGXHYEmd@6@&h=b->fOqvpyP?{Fjr<03k3+;9r8fA*$cfDRa?t0jQ zP!c5OLYbnOLiOT8j3|k7Ytj5|!?tZ`Rj3+nSE_XJo@-tPff#5HGy`?Ql{rs4{SW3~ z-`f4u4bKwqPg6UM6Grdef7;P$2589ji$^OjAK!49_WSJ`&uu&m6gC{kIr{k4V693x zxw4cJRw-uAg2V$$I#+Ob)+<4UFP> zY$lKy#YSjslaH$Qfv9}uwQ@C(T7UNH%(%VsR%>VT60)tx1PV>5V8kE$ev5&PntRo@ zLkf4+9z4M$fX~CHq-a#OYUOWsb(ergwDh$K#nN-vN~z`2R5J5VH2z~+{|Ybwrj$Vw Tw|^VS00000NkvXXu0mjf%3LNY literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/key_green.png b/r2/r2/public/static/key_green.png deleted file mode 100644 index d40740396cbefe1b8204f4f91a696f6d04eec2e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 703 zcmV;w0zmzVP)7oX;fYS5fR?a$bad^&iuHSu~`3%VTtO}r!shMd`!61c%6R9aJGSh8X%)P*raU)hwAiO6D z)GH7M>Os=K8*y(FIo?C~yJ{<%*U%nBM$Zz%Wh5q=k@+A)HgpoHzyZX@8&HV#!QWjA z`_+cv-}i0Xg^24s7I-VE#u4*AQoR#N?{>t-#LOH})WMk9;P)owvi_IE6!o^=Lf3R#&PVCy|Gc4obnhMMwvBLinP_YpwW)P1ST? zrfe04-x)FNzro&t&e;ir^8^J56p&nqIY_fO@GcRuAKQt!4<44sunkb-j=jm5S_@$&_dyonDz^$r}kLbDn<^FJI)(KksQ7G*l%&dIcv63Kcm5d9~ zQDnp25a#b;Oe2ojja#pmUoF|#dr&8W-hPZ#rZfF!J@DLVkx!Vn%)K#giqbQ`G;LE> ldR%0)iYQ5Amu3}R{|RMS>3;1N)RF)I002ovPDHLkV1l&ZPDKC! diff --git a/r2/r2/public/static/key_red.png b/r2/r2/public/static/key_red.png deleted file mode 100644 index 00dec80d84e295960ce1dc1e67697a8069cb7a81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 724 zcmV;_0xSKAP)=9*v8X6NkdoU^aazxO>Vty1fS|IPFA`#=BZd0!0x%|@E*DQYFc zidz4?|1UTlpHa1z$-iOIg+%ZnQjsB2R#X#Tr{Ted2AOdDs}+f*j@9m<$JfEa*}}fu z$Uu!uVR`;0;@|EO4KAB>8K9(jc-t7&WL*OqnZl|T>Q$3eco5NP3qIQ<&p8a!QIGS6W&aB5E#BpfI5WT`4B&yh2*=4=+qeq6S+tU zjo@mtVQtBbHKz~paBq_C0>lQ|ub z=4%l8pochl2-25Zn0s1)*=J>VcWxI34LaCQZ%qyuwbiOY=1)rmIuZ4hkWM*>a`}+` zW{jB`eyBpfxcN{3dS$(N!tr`6)T-XByta8o literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/pencil-gray.png b/r2/r2/public/static/pencil-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..70fd0cf5eb4828a9d6cfbcf81bc695b01352945c GIT binary patch literal 546 zcmV+-0^R+IP)alAVX48G9)B~5x)%!7A*Mp@1KK%12Z%8>eZ{Iq@?g^*tl_{yu3UgA0JRPko*1n z_f4BNG2u~dVPOGOed5H4SFc{Ze*GFK$i~Ko-3Ewic6N54>wyNJIdg`epa0pjXJut& zOt@474SVwB$)7)efUW|1_vOo%K-EB5CR}Deefsp*uU|l49y@mI{{8#K#l;W>C>mN@ zTk)$#(NJ4k8yy`DaS2?t;ji1)*XHeYVLKG9cz;DFG~$3EFlo{xH#fIEd-hmbS|Y1{ zcWk*qa5B51_V-J>t{+{_!odRyrTF;xy1F_J4vzl*exU!fwY6{GzWwIS8<+dbO(HTl z?;c=ydW3;r;0=rX^-E7cHURYiqvptwBWh}D7r{VKP;lbJiF;kzIV2Pryo#Wys6q1A z^S2-k*RNmSwr!i4nHew@0E3T(g$1Y@D9$P-_3gq|?oC-gzrXm#!0`DKGmDrs$VtY= z#y}f1H8lkU1gxyA!o$NMMm}28`*Qaj8Nr_{Oiw<){`2rPn|ydZ$US(#;|)^}#VGG_ kW<3}we|K3MPy`^r0LY&a{KyQi0{{R307*qoM6N<$f~qRq1}l<=psl5*5Xz9i;M}s*NP=ugs7Q#8Z;Dyx|}!`#}xw_C3!B-yaPC&0j)XcpuX@rNfq|q}N(wJOjA& z>u+z?dfJEuLePrqzy!)73pvLjxk4d6XNZt?hm_iYES{i}J5y3l?}PPNYDBR7oPc~6 zL^d)Bi4Q2L3pnp!nFxN9c2E+=@XAl&+;2m6a~kZj1r3Mz3C=hmUG<{+vWR@t4q?fJ zhFc(ozZD#Mx`^Q~g1v=K6!QnfuqyD4>U4EjF0eamL}Jx| z%&`kR-H+3GBYr*Qx}frLU4`%n9(`uSomzw)t%%NagXkA*R5Mbv9VLDp1wMo$cOMa~ s3Wm%r7^bwK$2$}-<~D8p`#1iScU4^XCLAA~0ssI207*qoM6N<$g3sK(Qvd(} literal 0 HcmV?d00001 diff --git a/r2/r2/public/static/reddit.css b/r2/r2/public/static/reddit.css index 02d311dd0..5e3dd3ed3 100644 --- a/r2/r2/public/static/reddit.css +++ b/r2/r2/public/static/reddit.css @@ -94,7 +94,7 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } background-color: #cee3f8; } -#header-img {} +#header-img {margin-top: 2px;} #header-top { position: absolute; @@ -138,7 +138,7 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } .dropdown-title { } -.dropdown .drop-choices { +.drop-choices { position: absolute; left: 0px; /* top gets set in js */ visibility: hidden; @@ -148,15 +148,16 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } white-space: nowrap; line-height: normal; margin-top: 1px; + display: inline; } -.dropdown a.choice { +.drop-choices a.choice { cursor: pointer; padding: 0px 3px 0px 3px; display: block; } -.dropdown a.choice:hover { +.drop-choices a.choice:hover { background-color: #c7def7; } @@ -177,7 +178,7 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } color: gray; } -.dropdown.lightdrop .drop-choices { +.drop-choices.lightdrop { margin-top: 2px; } @@ -198,10 +199,9 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } padding-bottom: 0; border:none; } -.dropdown.tabdrop .drop-choices {margin-top: 2px;} +.drop-choices.tabdrop {margin-top: 2px;} .dropdown-title.tabdrop { display: none } - .tabmenu { list-style-type: none; white-space: nowrap; @@ -223,6 +223,7 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } background-color: white; border: 1px solid #5f99cf; border-bottom: 1px solid white; + z-index: 100; } #search { @@ -265,7 +266,7 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } } .subredditbox { - border: 1px dotted gray; + border: 1px solid gray; } .subredditbox h4 { @@ -333,9 +334,7 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } } .sidebox { - border: gray solid 1px; - border-bottom: black solid 1px; - border-right: black solid 1px; + border: 1px solid gray; padding-left: 44px; } .sidebox .spacer { margin-bottom: 5px } @@ -356,9 +355,7 @@ input[type=checkbox], input[type=radio] { margin-top: .4em; } .raisedbox { padding: 5px; background: #E0E0E0; - border: gray solid 1px; - border-bottom: black solid 1px; - border-right: black solid 1px; + border: 1px solid gray; } .raisedbox h3 { @@ -642,6 +639,29 @@ before enabling */ margin-right: 15px; } +.infobar { + background-color: #f6e69f; + padding: 5px 10px; + margin: 5px 310px 5px 0px; + border: 1px solid orange; + font-size: small; +} + +.infobar img { + display: inline; + vertical-align: middle; +} + +.menuarea { + border-bottom: 1px dotted gray; + padding: 5px 10px; + margin: 5px 310px 5px 5px; + font-size: larger; +} + +.menuarea .spacer {display: inline; margin-right: 15px} + + /*top link*/ a.star { text-decoration: none; color: #ff8b60 } @@ -832,9 +852,23 @@ a.star { text-decoration: none; color: #ff8b60 } .subreddit { margin-bottom: 10px; } .subreddit p { margin-top: 0px; margin-bottom: 1px; } -.subreddit .description {font-size: small; } +.subreddit .description {font-size: small; max-width: 60em;} .subreddit .key {display: block;} .subreddit .title { font-size: medium; margin-right: 5px; } +.subreddit .midcol { margin-right: 5px } + +.sr-toggle-button { + width: 54px; + height: 18px; + margin-bottom: 5px; + cursor: pointer; +} +.sr-toggle-button.add { background-image: url(/static/sr-add-button.png) } +.sr-toggle-button.remove { background-image: url(/static/sr-remove-button.png)} + +.sr-type-img { + margin-right: 2px; +} .commentbody { } @@ -1523,7 +1557,6 @@ ul#image-preview-list .description pre { float: left; } - /* Socialite */ .socialite.instructions ul { margin: 10px; @@ -1600,4 +1633,67 @@ ul#image-preview-list .description pre { background-position: bottom left; } +#sr-header-area { + padding: 3px 0; + background-color: #369; + white-space: nowrap; + overflow: hidden; + text-transform: uppercase; + } +.dropdown.srdrop .selected { + background: transparent url(/static/droparrowwhite.gif) no-repeat scroll center right; + padding-right: 21px; + margin: 0 5px; + color: white; + font-weight: normal; + } + +.srdrop .choice.top-option { + font-style: italic; + border-bottom: 1px dotted #369; +} + +.srdrop .choice.bottom-option { + font-style: italic; + border-top: 1px dotted #369; +} + + +#sr-bar .separator {color: white} +#sr-bar a {color: white;} + +#sr-more-link { + color: white; + background-color: #369; + position: absolute; + right: 0px; + padding: 0 5px 0 15px; + font-weight: bold; + margin: 0 1px; +} + +#sr-more-link:hover {text-decoration: underline;} + +.subscription-box { + border: 1px solid gray; + padding: 0 10px; + } + +.subscription-box li { + clear: left; + margin-bottom: 10px; +} + +.subscription-box .sr-toggle-button { + margin-right: 5px; + float: left; +} + +.subscription-box .title { + font-size: medium; + color: blue; + margin-right: 5px; +} + +.subscription-box h1{ text-align: center; } diff --git a/r2/r2/public/static/reddit_piece.js b/r2/r2/public/static/reddit_piece.js index c8d386422..768055e6a 100644 --- a/r2/r2/public/static/reddit_piece.js +++ b/r2/r2/public/static/reddit_piece.js @@ -3,20 +3,13 @@ var cur_menu = null; //track the current open menu var have_open = false; function open_menu(menu) { - for (var i=0; i< menu.childNodes.length; i++) { - child = menu.childNodes[i]; - if (child.className == "drop-choices") { - child.style.visibility = 'visible'; - child.style.top = menu.offsetHeight + 'px'; + var child = menu.nextSibling; + if (child.className.indexOf("drop-choices") == -1) return; + + child.style.visibility = 'visible'; + child.style.top = (menu.offsetTop + menu.offsetHeight) + 'px'; + child.style.left = menu.offsetLeft + 'px'; - //expand the choices to width of the menu. fixes a - //highlighting issue in FF2 - if (menu.offsetWidth > child.offsetWidth) { - child.style.width = menu.offsetWidth + 'px'; - } - break; - } - } menu.onclick = null; cur_menu = menu; have_open = true; @@ -26,8 +19,8 @@ function close_menus() { uls = document.getElementsByTagName('DIV'); for (var i=0; i -1) { ul.style.visibility = 'hidden'; menu.onclick = function() { return open_menu(this); @@ -74,6 +67,8 @@ function init() { /*updateMods();*/ } stc = $("siteTable_comments"); + + update_reddit_count(); } function deletetoggle(link, type) { @@ -286,11 +281,77 @@ function set_sort(where, sort) { return true; } - - function disable_ui(name) { var help = $(name + "-help"); var gone = $(name + "-gone"); help.parentNode.innerHTML = gone.innerHTML; redditRequest('disable_ui', {id: name}); } + +function update_reddit_count() { + if (!cur_site || !logged) return; + + var decay_factor = .9; //precentage to keep + var decay_period = 86400; //num of seconds between updates + var num_recent = 10; //num of recent reddits to report + var num_count = 100; //num of reddits to actually count + + var date_key = '_date'; + var cur_date = new Date(); + var count_cookie = 'reddit_counts'; + var recent_cookie = 'recent_reddits'; + var reddit_counts = readCookie(count_cookie); + + //init the reddit_counts dict + if (reddit_counts) reddit_counts = reddit_counts.parseJSON(); + else { + reddit_counts = {}; + reddit_counts[date_key] = cur_date.toString(); + } + + var last_reset = new Date(reddit_counts[date_key]); + var decay = cur_date - last_reset > decay_period * 1000; + var names = []; + + //incrmenet the count on the current reddit + reddit_counts[cur_site] = (reddit_counts[cur_site] || 0) + 1; + + //collect the reddit names (for sorting) and decay the view counts + //if necessary + for (var sr_name in reddit_counts) { + if (sr_name == date_key || Object.prototype[sr_name]) continue; + + if (decay && sr_name != cur_site) { + //compute the new count val + var val = Math.floor(decay_factor * reddit_counts[sr_name]); + if (val > 0) reddit_counts[sr_name] = val; + else delete reddit_counts[sr_name]; + } + + if (reddit_counts[sr_name]) names.push(sr_name); + } + + //sort the names by the view counts + names.sort(function(n1, n2) {return reddit_counts[n2] - reddit_counts[n1];}); + + //update the last decay date + if (decay) reddit_counts[date_key] = cur_date.toString(); + + //build the list of names to report as "recent" + var recent_reddits = ""; + for (var i = 0; i < names.length; i++) { + var sr_name = names[i]; + if (i < num_recent) { + recent_reddits += names[i] + ','; + } else if (i >= num_count && sr_name != cur_site) { + delete reddit_counts[sr_name]; + } + } + + //set the two cookies: one for the counts, one for the final + //recent list + createCookie(count_cookie, reddit_counts.toJSONString()); + if (recent_reddits) { + createCookie(recent_cookie, recent_reddits); + } +} diff --git a/r2/r2/public/static/sr-add-button.png b/r2/r2/public/static/sr-add-button.png new file mode 100644 index 0000000000000000000000000000000000000000..eed1884d79e9832c685600d75d2d911ad4425e4c GIT binary patch literal 985 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 Ef`N_!eE var a = new Image(); a.src = "${static('aupmod.png')}"; diff --git a/r2/r2/templates/navmenu.html b/r2/r2/templates/navmenu.html index 4fdb7c130..2213fc6bf 100644 --- a/r2/r2/templates/navmenu.html +++ b/r2/r2/templates/navmenu.html @@ -39,15 +39,17 @@ %elif thing.title: ${thing.title} %endif -
- %for option in thing: - %if option != thing.selected: - ${plain_link(option.title, option.path, _sr_path = option.sr_path, - _class = "choice")} - %endif - %endfor -
+ +
+ %for option in thing: + %if option != thing.selected: + ${plain_link(option.title, option.path, _sr_path = option.sr_path, + _class = "choice" + " " + option.css_class)} + %endif + %endfor +
+ %endif @@ -68,7 +70,7 @@ %>
  • %if i > 0: - ${separator()} + ${separator(thing.separator)} %endif ${content}
  • diff --git a/r2/r2/templates/printable.html b/r2/r2/templates/printable.html index d6ea1a020..e36f386bf 100644 --- a/r2/r2/templates/printable.html +++ b/r2/r2/templates/printable.html @@ -222,7 +222,8 @@ ${self.RenderPrintable()} link = _link() if fmt: link = fmt % {fmt_param: link} - link = link.replace("\n", " ").replace(" <", " <").replace("> ", "> ") + ##who knows? + ##link = link.replace("\n", " ").replace(" <", " <").replace("> ", "> ") %> %if clicked: diff --git a/r2/r2/templates/reddit.html b/r2/r2/templates/reddit.html index 603a9724b..1025f0607 100644 --- a/r2/r2/templates/reddit.html +++ b/r2/r2/templates/reddit.html @@ -95,6 +95,7 @@ <%def name="javascript_run()"> var class_dict = ${class_dict()}; var where = ${path_info()}; + var cur_site = "${c.site._fullname if not c.default_sr else ''}"; window.onload = init; window.onpageshow = function(evt) { if (evt.persisted) init() diff --git a/r2/r2/templates/redditheader.html b/r2/r2/templates/redditheader.html index facbc8587..8f8e1d907 100644 --- a/r2/r2/templates/redditheader.html +++ b/r2/r2/templates/redditheader.html @@ -29,6 +29,10 @@ <%namespace file="utils.html" import="plain_link, text_with_js, img_link, separator"/>