diff --git a/apps/reader/views.py b/apps/reader/views.py index 8f8844ba6..245e34d06 100644 --- a/apps/reader/views.py +++ b/apps/reader/views.py @@ -24,7 +24,7 @@ except: pass from utils import json from utils.user_functions import get_user, ajax_login_required -from utils.feed_functions import fetch_address_from_page +from utils.feed_functions import fetch_address_from_page, format_relative_date SINGLE_DAY = 60*60*24 @@ -114,6 +114,7 @@ def load_feeds(request): 'ps': sub.unread_count_positive, 'nt': sub.unread_count_neutral, 'ng': sub.unread_count_negative, + 'updated': format_relative_date(sub.feed.last_update), } data = dict(feeds=feeds, folders=json.decode(folders.folders)) @@ -257,7 +258,10 @@ def load_single_feed(request): usersub.feed_opens += 1 usersub.save() - data = dict(stories=stories, feed_tags=feed_tags, feed_authors=feed_authors, classifiers=classifiers) + data = dict(stories=stories, + feed_tags=feed_tags, + feed_authors=feed_authors, + classifiers=classifiers) return data def load_feed_page(request): diff --git a/media/css/reader.css b/media/css/reader.css index a84dfc313..243c4d0f8 100644 --- a/media/css/reader.css +++ b/media/css/reader.css @@ -562,11 +562,28 @@ background: transparent; display: none; } +#story_titles .NB-feedbar .NB-feedbar-last-updated { + color: #808080; + text-shadow: 0 1px 0 #e6e6e6; + position: absolute; + right: 54px; + font-size: 9px; + line-height: 15px; + font-weight: bold; + margin: 3px 0 2px; + width: 150px; + text-transform: uppercase; +} + #story_titles .NB-feedbar.NB-feedbar-hover .NB-feedbar-manage-feed, #story_titles .NB-feedbar.NB-feedbar-hover .NB-feedbar-mark-feed-read { display: block; } +#story_titles .NB-feedbar.NB-feedbar-hover .NB-feedbar-last-updated { + display: none; +} + #story_titles .NB-feedbar .NB-feedbar-mark-feed-read:hover { background-color: #00609f; } diff --git a/media/js/newsblur/reader.js b/media/js/newsblur/reader.js index 7f045f0d7..c304df0b0 100644 --- a/media/js/newsblur/reader.js +++ b/media/js/newsblur/reader.js @@ -536,7 +536,6 @@ $('.unread_count', $feed_list).corner('4px'); if (!$folder.length) { - this.load_feed_browser(); this.setup_ftux_add_feed_callout(); } else { $('.NB-task-manage').removeClass('NB-disabled'); @@ -553,7 +552,7 @@ if (typeof item == "number") { var feed = this.model.feeds[item]; - var $feed = this.make_feed_title_line(feed, true); + var $feed = this.make_feed_title_line(feed, true, 'feed'); $feeds.append($feed); } else if (typeof item == "object") { for (var o in item) { @@ -575,7 +574,7 @@ return $feeds.children(); }, - make_feed_title_line: function(feed, list_item) { + make_feed_title_line: function(feed, list_item, type) { var unread_class = ''; if (feed.ps) { unread_class += ' unread_positive'; @@ -612,7 +611,11 @@ $.make('img', { className: 'feed_favicon', src: this.google_favicon_url + feed.feed_link }), $.make('span', { className: 'feed_title' }, feed.feed_title), $.make('div', { className: 'NB-feedbar-manage-feed' }), - $.make('div', { className: 'NB-feedbar-mark-feed-read' }, 'Mark All as Read') + (type == 'story' && $.make('div', { className: 'NB-feedbar-last-updated' }, [ + $.make('span', { className: 'NB-feedbar-last-updated-label' }, 'Updated: '), + $.make('span', { className: 'NB-feedbar-last-updated-date' }, feed.updated) + ])), + (type == 'story' && $.make('div', { className: 'NB-feedbar-mark-feed-read' }, 'Mark All as Read')) ]).data('feed_id', feed.id); return $feed; @@ -1163,7 +1166,7 @@ make_content_pane_feed_counter: function(feed_id) { var $content_pane = this.$s.$content_pane; var feed = this.model.get_feed(feed_id); - var $counter = this.make_feed_title_line(feed); + var $counter = this.make_feed_title_line(feed, false, 'counter'); $('.feed', $content_pane).remove(); $('#story_taskbar', $content_pane).append($counter); @@ -1483,7 +1486,7 @@ var feed = this.model.get_feed(feed_id); var $feedbar = $.make('div', { className: 'NB-feedbar' }, [ - this.make_feed_title_line(feed), + this.make_feed_title_line(feed, false, 'story'), $.make('div', { className: 'NB-feedbar-intelligence' }, [ $.make('div', { className: 'NB-feed-sentiment NB-feed-like' }), $.make('div', { className: 'NB-feed-sentiment NB-feed-dislike' }) @@ -2221,7 +2224,7 @@ for (var f in updated_feeds) { var feed_id = updated_feeds[f]; var feed = this.model.get_feed(feed_id); - var $feed = this.make_feed_title_line(feed, true); + var $feed = this.make_feed_title_line(feed, true, 'feed'); var $feed_on_page = this.find_feed_in_feed_list(feed_id); var selected = $feed_on_page.hasClass('selected'); if (selected) { diff --git a/utils/feed_functions.py b/utils/feed_functions.py index 815362f46..10acbdd5c 100644 --- a/utils/feed_functions.py +++ b/utils/feed_functions.py @@ -67,4 +67,21 @@ def fetch_address_from_page(url, existing_feed=None): feed = Feed(feed_address=feed_finder_url) feed.save() feed.update() - return feed \ No newline at end of file + return feed + +def format_relative_date(date): + if not date or date < datetime.datetime(2010, 1, 1): + return "Soon" + + now = datetime.datetime.now() + diff = now - date + if diff < datetime.timedelta(minutes=60): + return "%s minutes ago" % (diff.seconds / 60) + elif datetime.timedelta(minutes=60) <= diff < datetime.timedelta(minutes=90): + return "1 hour ago" + elif diff >= datetime.timedelta(minutes=90): + dec = (diff.seconds / 60) % 60 + if dec >= 30: + return "%s.5 hours ago" % (diff.seconds / 60 / 60) + else: + return "%s hours ago" % (diff.seconds / 60 / 60) \ No newline at end of file