Lots of work towards the eventual release of recommended feeds. Now can try feeds (maybe taste would've been a better name?).

This commit is contained in:
Samuel Clay 2011-03-15 23:42:27 -04:00
parent 5fa54de53d
commit b87a5de6ce
8 changed files with 132 additions and 66 deletions

View file

@ -49,10 +49,16 @@ class UserSubscription(models.Model):
feed['nt'] = self.unread_count_neutral
feed['ng'] = self.unread_count_negative
feed['active'] = self.active
if not self.active and self.user.profile.is_premium:
feed['active'] = True
self.active = True
self.save()
return feed
def save(self, *args, **kwargs):
if not self.active and self.user.profile.is_premium:
self.active = True
try:
super(UserSubscription, self).save(*args, **kwargs)
except IntegrityError:

View file

@ -308,20 +308,19 @@ def load_single_feed(request):
classifier_tags = MClassifierTag.objects(user_id=user.pk, feed_id=feed_id)
usersub = UserSubscription.objects.get(user=user, feed=feed)
if not usersub:
usersub = UserSubscription.objects.create(user=user, feed=feed)
userstories = []
userstories_db = MUserStory.objects(user_id=user.pk,
feed_id=feed.pk,
read_date__gte=usersub.mark_read_date)
starred_stories = MStarredStory.objects(user_id=user.pk, story_feed_id=feed_id).only('story_guid', 'starred_date')
starred_stories = dict([(story.story_guid, story.starred_date) for story in starred_stories])
if usersub:
userstories_db = MUserStory.objects(user_id=user.pk,
feed_id=feed.pk,
read_date__gte=usersub.mark_read_date)
starred_stories = MStarredStory.objects(user_id=user.pk, story_feed_id=feed_id).only('story_guid', 'starred_date')
starred_stories = dict([(story.story_guid, story.starred_date) for story in starred_stories])
for us in userstories_db:
if hasattr(us.story, 'story_guid') and isinstance(us.story.story_guid, unicode):
userstories.append(us.story.story_guid)
elif hasattr(us.story, 'id') and isinstance(us.story.id, unicode):
userstories.append(us.story.id) # TODO: Remove me after migration from story.id->guid
for us in userstories_db:
if hasattr(us.story, 'story_guid') and isinstance(us.story.story_guid, unicode):
userstories.append(us.story.story_guid)
elif hasattr(us.story, 'id') and isinstance(us.story.id, unicode):
userstories.append(us.story.id) # TODO: Remove me after migration from story.id->guid
for story in stories:
[x.rewind() for x in [classifier_feeds, classifier_authors, classifier_tags, classifier_titles]]
@ -329,16 +328,19 @@ def load_single_feed(request):
now = localtime_for_timezone(datetime.datetime.now(), user.profile.timezone)
story['short_parsed_date'] = format_story_link_date__short(story_date, now)
story['long_parsed_date'] = format_story_link_date__long(story_date, now)
if story['id'] in userstories:
if usersub:
if story['id'] in userstories:
story['read_status'] = 1
elif not story.get('read_status') and story['story_date'] < usersub.mark_read_date:
story['read_status'] = 1
elif not story.get('read_status') and story['story_date'] > usersub.last_read_date:
story['read_status'] = 0
if story['id'] in starred_stories:
story['starred'] = True
starred_date = localtime_for_timezone(starred_stories[story['id']], user.profile.timezone)
story['starred_date'] = format_story_link_date__long(starred_date, now)
else:
story['read_status'] = 1
elif not story.get('read_status') and story['story_date'] < usersub.mark_read_date:
story['read_status'] = 1
elif not story.get('read_status') and story['story_date'] > usersub.last_read_date:
story['read_status'] = 0
if story['id'] in starred_stories:
story['starred'] = True
starred_date = localtime_for_timezone(starred_stories[story['id']], user.profile.timezone)
story['starred_date'] = format_story_link_date__long(starred_date, now)
story['intelligence'] = {
'feed': apply_classifier_feeds(classifier_feeds, feed),
'author': apply_classifier_authors(classifier_authors, story),
@ -352,8 +354,9 @@ def load_single_feed(request):
classifiers = get_classifiers_for_user(user, feed_id, classifier_feeds,
classifier_authors, classifier_titles, classifier_tags)
usersub.feed_opens += 1
usersub.save()
if usersub:
usersub.feed_opens += 1
usersub.save()
diff = datetime.datetime.utcnow()-start
timediff = float("%s.%.2s" % (diff.seconds, (diff.microseconds / 1000)))
@ -369,7 +372,9 @@ def load_single_feed(request):
feed_id=feed.pk)
if dupe_feed_id: data['dupe_feed_id'] = dupe_feed_id
if not usersub:
data.update(feed.canonical())
return data
def load_feed_page(request):

View file

@ -1974,6 +1974,7 @@ background: transparent;
padding-right: 2px;
font-size: 10px;
cursor: pointer;
overflow: hidden;
}
.NB-feeds-header.NB-selected {
@ -1990,10 +1991,10 @@ background: transparent;
.NB-feeds-header .NB-feeds-header-title {
display: block;
padding: 3px 40px 2px 23px;
padding: 0 40px 2px 23px;
text-decoration: none;
color: #F0F0F0;
line-height: 1.3em;
line-height: 18px;
height: 14px;
overflow: hidden;
text-shadow: 0 1px 0 #060607;
@ -2059,18 +2060,11 @@ background: transparent;
display: none;
}
.NB-feeds-header-starred .NB-feeds-header-icon {
background: transparent url('../img/reader/star_blue.png') no-repeat 0 0;
.NB-feeds-header-tryfeed .NB-feeds-header-title {
text-transform: none;
}
.NB-feeds-header-starred .NB-feeds-header-count {
background-color: #11448B;
display: block;
padding: 0 4px;
margin: 2px 3px 0 0;
}
.NB-feeds-header-starred.NB-empty .NB-feeds-header-count {
.NB-feeds-header-tryfeed.NB-empty .NB-feeds-header-count {
display: none;
}
@ -2276,6 +2270,16 @@ background: transparent;
display: none;
}
#story_taskbar .NB-tryfeed-add {
margin: 1px auto 0px;
width: 30px;
height: 14px;
cursor: pointer;
-webkit-box-shadow: #9A9A9A 2px 2px 0px;
-moz-box-shadow: #9A9A9A 2px 2px 0px;
box-shadow: #9A9A9A 2px 2px 0px;
}
.NB-taskbar .NB-task-title {
padding: 7px 0 0 0;
display: block;
@ -3955,10 +3959,10 @@ background: transparent;
background: transparent url('../img/reader/readability.png') no-repeat 0 0;
}
.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-twitter {
background: transparent url('../img/reader/twitter.png') no-repeat 0 0;
background: transparent url('../img/reader/twitter_icon_2.png') no-repeat 0 0;
}
.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-facebook {
background: transparent url('../img/reader/facebook.gif') no-repeat 0 0;
background: transparent url('../img/reader/facebook_icon.png') no-repeat 0 0;
}
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-twitter .NB-menu-manage-image,

View file

@ -131,7 +131,8 @@ NEWSBLUR.log = function(msg) {
$.extend({
favicon: function(feed_favicon) {
if (feed_favicon) return 'data:image/png;base64,' + feed_favicon;
if (feed_favicon && feed_favicon.indexOf('data:image/png;base64,') != -1) return feed_favicon;
else if (feed_favicon) return 'data:image/png;base64,' + feed_favicon;
return NEWSBLUR.Globals.MEDIA_URL + '/img/icons/silk/world.png';
},

View file

@ -36,8 +36,6 @@ NEWSBLUR.AssetModel.Reader = function() {
this.flags = {
'favicons_fetching': false
};
this.DEFAULT_VIEW = NEWSBLUR.Preferences.default_view || 'page';
};
NEWSBLUR.AssetModel.Reader.prototype = {
@ -262,6 +260,7 @@ NEWSBLUR.AssetModel.Reader.prototype = {
for (var s in data.stories) {
this.story_keys[data.stories[s].id] = true;
}
this.feeds[feed_id].feed_address = data.feed_address || this.feeds[feed_id].feed_address;
} else if (data) {
data.stories = _.select(data.stories, function(story) {
if (!self.story_keys[story.id]) {
@ -461,6 +460,12 @@ NEWSBLUR.AssetModel.Reader.prototype = {
return counts;
},
set_feed: function(feed_id, feed) {
var self = this;
return this.feeds[feed_id] = feed;
},
get_feed: function(feed_id) {
var self = this;
@ -622,7 +627,7 @@ NEWSBLUR.AssetModel.Reader.prototype = {
view_setting: function(feed_id, feed_view_setting, callback) {
if (typeof feed_view_setting == 'undefined') {
return NEWSBLUR.Preferences.view_settings[feed_id+''] || this.DEFAULT_VIEW;
return NEWSBLUR.Preferences.view_settings[feed_id+''] || NEWSBLUR.Preferences.default_view;
}
NEWSBLUR.Preferences.view_settings[feed_id+''] = feed_view_setting;

View file

@ -24,13 +24,12 @@
$mouse_indicator: $('#mouse-indicator'),
$feed_link_loader: $('#NB-feeds-list-loader'),
$feeds_progress: $('#NB-progress'),
$header: $('.NB-feeds-header'),
$dashboard: $('.NB-feeds-header-dashboard'),
$river_header: $('.NB-feeds-header-river'),
$starred_header: $('.NB-feeds-header-starred'),
$tryfeed_header: $('.NB-feeds-header-tryfeed'),
$taskbar: $('.taskbar_nav'),
$feed_floater: $('.NB-feed-story-view-floater'),
$recommended_feeds: $('.NB-module-recommended')
$feed_floater: $('.NB-feed-story-view-floater')
};
this.flags = {
'feed_view_images_loaded': {},
@ -240,7 +239,7 @@
$('#NB-splash').hide();
$('#NB-splash-overlay').hide();
this.$s.$body.layout().resizeAll();
this.$s.$header.addClass('NB-active');
this.$s.$dashboard.addClass('NB-active');
if (NEWSBLUR.Globals.is_anonymous) {
this.setup_ftux_signup_callout();
@ -255,7 +254,7 @@
$('.right-pane').hide();
$('#NB-splash').show();
$('#NB-splash-overlay').show();
this.$s.$header.removeClass('NB-active');
this.$s.$dashboard.removeClass('NB-active');
},
iframe_buster_buster: function() {
@ -940,14 +939,15 @@
]),
(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 + ' ago')
$.make('span', { className: 'NB-feedbar-last-updated-date' }, feed.updated ? feed.updated + ' ago' : 'Loading...')
])),
(type == 'story' && $.make('div', { className: 'NB-feedbar-mark-feed-read' }, 'Mark All as Read')),
$.make('div', { className: 'NB-feed-exception-icon' }),
$.make('div', { className: 'NB-feed-unfetched-icon' }),
(type == 'feed' && $.make('div', { className: 'NB-feedlist-manage-icon' }))
]).data('feed_id', feed.id);
NEWSBLUR.log(['make feed', $feed, feed]);
]);
$feed.data('feed_id', feed.id);
$('.NB-feedbar-train-feed, .NB-feedbar-statistics', $feed).tipsy({
gravity: 's',
delayIn: 375
@ -1379,11 +1379,16 @@
this.$s.$feed_stories.empty();
this.$s.$starred_header.removeClass('NB-selected');
this.$s.$river_header.removeClass('NB-selected');
this.$s.$tryfeed_header.removeClass('NB-selected');
$('.NB-selected', this.$s.$feed_list).removeClass('NB-selected');
this.$s.$body.removeClass('NB-view-river');
$('.task_view_page', this.$s.$taskbar).removeClass('NB-disabled');
$('.task_view_page', this.$s.$taskbar).removeClass('NB-task-return');
this.hide_content_pane_feed_counter();
if (this.flags['showing_feed_in_tryfeed_view']) {
this.hide_tryfeed_view();
}
},
open_feed: function(feed_id, force, $feed_link, delay) {
@ -1487,6 +1492,9 @@
_.defer(_.bind(this.open_unread_stories_in_tabs, this));
}
this.hide_stories_progress_bar();
if (this.flags['showing_feed_in_tryfeed_view']) {
this.show_tryfeed_add_button();
}
this.make_content_pane_feed_counter(feed_id);
}
},
@ -1737,7 +1745,13 @@
hide_stories_progress_bar: function() {
var $progress = $('.NB-river-progress', this.$s.$story_taskbar);
$progress.stop().animate({'opacity': 0}, {'duration': 250, 'queue': false});
$progress.stop().animate({'opacity': 0}, {
'duration': 250,
'queue': false,
'complete': function() {
$progress.remove();
}
});
},
// ==========================
@ -4789,8 +4803,6 @@
// =====================
load_recommended_feeds: function() {
var $module = this.$s.$recommended_feeds;
// Reload recommended feeds every 10 minutes.
setInterval(_.bind(function() {
this.load_recommended_feed();
@ -4798,21 +4810,46 @@
},
load_feed_in_tryfeed_view: function(feed_id) {
var feed = {
feed_title: $('.NB-recommended-title', this.$s.$recommended_feeds).text(),
feed_favicon: $('.NB-recommended-favicon', this.$s.$recommended_feeds).attr('src')
};
var $feed = this.make_feed_title_line(feed, false, 'feed');
NEWSBLUR.log(['load_feed_in_tryfeed_view', $feed, feed]);
var $recommended_feeds = $('.NB-module-recommended');
var $tryfeed_container = this.$s.$tryfeed_header.closest('.NB-feeds-header-container');
var feed = {
feed_id : feed_id,
feed_title : $('.NB-recommended-title', $recommended_feeds).text(),
favicon : $('.NB-recommended-favicon', $recommended_feeds).attr('src')
};
this.$s.$tryfeed_header.html($feed);
$tryfeed_container.slideDown(350);
this.reset_feed();
this.model.set_feed(feed_id, feed);
$('.NB-feeds-header-title', this.$s.$tryfeed_header).text(feed.feed_title);
$('.NB-feeds-header-icon', this.$s.$tryfeed_header).attr('src', feed.favicon);
$tryfeed_container.slideDown(350, _.bind(function() {
this.open_feed(feed_id);
this.flags['showing_feed_in_tryfeed_view'] = true;
this.$s.$tryfeed_header.addClass('NB-selected');
}, this));
},
hide_tryfeed_view: function() {
var $tryfeed_container = this.$s.$tryfeed_header.closest('.NB-feeds-header-container');
$tryfeed_container.slideUp(350);
this.$s.$story_taskbar.find('.NB-tryfeed-add').remove();
this.flags['showing_feed_in_tryfeed_view'] = false;
},
show_tryfeed_add_button: function() {
var $add = $.make('div', { className: 'NB-modal-submit' }, [
$.make('div', { className: 'NB-tryfeed-add NB-modal-submit-green NB-modal-submit-button' }, 'Add')
]).css({'opacity': 0});
this.$s.$story_taskbar.find('.NB-taskbar').append($add);
$add.animate({'opacity': 1}, {'duration': 600});
},
add_recommended_feed: function(feed_id) {
var feed = this.model.get_feed(feed_id);
this.open_add_feed_modal({url: feed.feed_address});
var feed_address = this.model.get_feed(feed_id ? feed_id : this.active_feed).feed_address;
this.open_add_feed_modal({url: feed_address});
},
load_recommended_feed: function(direction) {
@ -5272,6 +5309,12 @@
}
});
$.targetIs(e, { tagSelector: '.NB-tryfeed-add' }, function($t, $p){
e.preventDefault();
var feed_id = self.active_feed;
self.add_recommended_feed(feed_id);
});
// = One-offs =====================================================
var clicked = false;

View file

@ -372,6 +372,8 @@ $(document).ready(function() {
<div class="NB-feeds-header-container NB-feeds-header-tryfeed-container">
<div class="NB-feeds-header NB-feeds-header-tryfeed">
<img class="NB-feeds-header-icon" src=""></img>
<div class="NB-feeds-header-title"></div>
</div>
</div>

View file

@ -153,8 +153,8 @@ def format_relative_date(date, future=False):
return "%s hours %s" % ((((diff.seconds / 60) + 15) / 60),
'' if future else 'ago')
def add_object_to_folder(obj, folder, folders, added=False):
if not folder and obj not in folders:
def add_object_to_folder(obj, folder, folders, parent='', added=False):
if not folder and not parent and obj not in folders:
folders.append(obj)
return folders
@ -164,7 +164,7 @@ def add_object_to_folder(obj, folder, folders, added=False):
if f_k == folder and obj not in f_v and not added:
f_v.append(obj)
added = True
folders[k][f_k] = add_object_to_folder(obj, folder, f_v, added)
folders[k][f_k] = add_object_to_folder(obj, folder, f_v, f_k, added)
return folders
def mail_feed_error_to_admin(feed, e):