Separating out favicon loading from feed loading. This will hopefully reduce initial page load speed.

This commit is contained in:
Samuel Clay 2011-04-05 19:24:12 -04:00
parent e88d78a39c
commit 87d078239a
6 changed files with 80 additions and 13 deletions

View file

@ -11,7 +11,8 @@ urlpatterns = patterns('',
url(r'^load_feed_page', views.load_feed_page, name='load-feed-page'),
url(r'^load_feeds_iphone', views.load_feeds_iphone, name='load-feeds-iphone'),
url(r'^load_feeds', views.load_feeds, name='load-feeds'),
url(r'^load_river_stories', views.load_river_stories, name='load-river-storiesw'),
url(r'^load_feed_favicons', views.load_feed_favicons, name='load-feed-favicons'),
url(r'^load_river_stories', views.load_river_stories, name='load-river-stories'),
url(r'^refresh_feeds', views.refresh_feeds, name='refresh-feeds'),
url(r'^load_starred_stories', views.load_starred_stories, name='load-starred-stories'),
url(r'^mark_all_as_read', views.mark_all_as_read, name='mark-all-as-read'),

View file

@ -23,6 +23,7 @@ from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds
from apps.analyzer.models import get_classifiers_for_user
from apps.reader.models import UserSubscription, UserSubscriptionFolders, MUserStory, Feature
from apps.reader.forms import SignupForm, LoginForm, FeatureForm
from apps.rss_feeds.models import FeedIcon
try:
from apps.rss_feeds.models import Feed, MFeedPage, DuplicateFeed, MStory, MStarredStory, FeedLoadtime
except:
@ -142,7 +143,7 @@ def load_feeds(request):
UserSubscriptionFolders.objects.filter(user=user)[1:].delete()
folders = UserSubscriptionFolders.objects.get(user=user)
user_subs = UserSubscription.objects.select_related('feed', 'feed__feed_icon').filter(user=user)
user_subs = UserSubscription.objects.select_related('feed').filter(user=user)
for sub in user_subs:
feeds[sub.feed.pk] = sub.canonical()
@ -169,6 +170,23 @@ def load_feeds(request):
}
return data
@json.json_view
def load_feed_favicons(request):
user = get_user(request)
feed_ids = request.REQUEST.getlist('feed_ids')
user_subs = UserSubscription.objects.select_related('feed').filter(user=user)
if not request.REQUEST.get('load_all'):
user_subs = user_subs.filter(active=True)
if feed_ids:
user_subs = user_subs.filter(feed__in=feed_ids)
favicons = {}
for sub in user_subs:
favicons[sub.feed.pk] = FeedIcon.objects.get(feed__pk=sub.feed.pk).data
return favicons
@ajax_login_required
@json.json_view
def load_feeds_iphone(request):
@ -255,10 +273,11 @@ def refresh_feeds(request):
feeds[sub.feed.pk]['favicon'] = sub.feed.icon.data
feeds[sub.feed.pk]['favicon_color'] = sub.feed.icon.color
feeds[sub.feed.pk]['favicon_fetching'] = bool(not (sub.feed.icon.not_found or sub.feed.icon.data))
diff = datetime.datetime.utcnow()-start
timediff = float("%s.%.2s" % (diff.seconds, (diff.microseconds / 1000)))
# logging.user(request.user, "~FBRefreshing %s feeds (%s seconds)" % (user_subs.count(), timediff))
if settings.DEBUG:
diff = datetime.datetime.utcnow()-start
timediff = float("%s.%.2s" % (diff.seconds, (diff.microseconds / 1000)))
logging.user(request.user, "~FBRefreshing %s feeds (%s seconds)" % (user_subs.count(), timediff))
return {'feeds': feeds}

View file

@ -70,7 +70,6 @@ class Feed(models.Model):
'feed_link': self.feed_link,
'updated': relative_timesince(self.last_update),
'subs': self.num_subscribers,
'favicon': self.icon.data,
'favicon_color': self.icon.color,
'favicon_fetching': bool(not (self.icon.not_found or self.icon.data))
}

View file

@ -130,9 +130,11 @@ NEWSBLUR.log = function(msg) {
$.extend({
favicon: function(feed_favicon) {
favicon: function(feed_favicon, empty_on_missing) {
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;
else if (empty_on_missing) return 'data:image/png;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
return NEWSBLUR.Globals.MEDIA_URL + '/img/icons/silk/world.png';
},

View file

@ -25,6 +25,7 @@ NEWSBLUR.AssetModel.Reader = function() {
}
};
this.feeds = {};
this.favicons = {};
this.folders = [];
this.stories = {};
this.story_keys = {};
@ -210,12 +211,39 @@ NEWSBLUR.AssetModel.Reader.prototype = {
});
self.folders = subscriptions.folders;
self.starred_count = subscriptions.starred_count;
if (!_.isEqual(self.favicons, {})) {
_.each(self.feeds, function(feed) {
feed.favicon = self.favicons[feed.id];
});
}
callback();
};
this.make_request('/reader/load_feeds', {}, pre_callback, error_callback);
},
load_feed_favicons: function(callback, loaded_once, load_all) {
var pre_callback = _.bind(function(favicons) {
this.favicons = favicons;
if (!_.isEqual(this.feeds, {})) {
_.each(this.feeds, _.bind(function(feed) {
feed.favicon = favicons[feed.id];
}, this));
}
callback();
}, this);
var data = {
load_all : load_all
};
if (loaded_once) {
data['feed_ids'] = _.compact(_.map(this.feeds, function(feed) {
return !feed.favicon && feed.id;
}));
}
this.make_request('/reader/load_feed_favicons', data, pre_callback);
},
load_feed: function(feed_id, page, first_load, callback) {
var self = this;

View file

@ -36,7 +36,8 @@
'bouncing_callout': false,
'has_unfetched_feeds': false,
'count_unreads_after_import_working': false,
'import_from_google_reader_working': false
'import_from_google_reader_working': false,
'favicons_downloaded': false
};
this.locks = {};
this.counts = {
@ -770,6 +771,7 @@
if ($('#feed_list').length) {
$('.NB-callout-ftux .NB-callout-text').text('Loading feeds...');
this.$s.$feed_link_loader.css({'display': 'block'});
this.flags['favicons_downloaded'] = false;
this.model.load_feeds($.rescope(this.make_feeds, this));
}
},
@ -805,10 +807,10 @@
if (NEWSBLUR.Globals.is_authenticated && this.flags['has_chosen_feeds']) {
_.delay(_.bind(this.start_count_unreads_after_import, this), 1000);
this.force_feeds_refresh($.rescope(this.finish_count_unreads_after_import, this), true);
} else if (!this.flags['has_chosen_feeds'] && folders.length) {
} else if (!this.flags['has_chosen_feeds'] && this.flags['favicons_downloaded'] && folders.length) {
_.defer(_.bind(this.open_feedchooser_modal, this), 100);
return;
} else if (NEWSBLUR.Globals.is_authenticated) {
} else if (NEWSBLUR.Globals.is_authenticated && !folders.length) {
this.setup_ftux_add_feed_callout();
}
@ -823,6 +825,23 @@
this.force_feed_refresh();
}
this.add_url_from_querystring();
_.defer(_.bind(function() {
this.model.load_feed_favicons($.rescope(this.make_feed_favicons, this), this.flags['favicons_downloaded'], this.flags['has_chosen_feeds']);
}, this));
},
make_feed_favicons: function() {
var model = this.model;
this.flags['favicons_downloaded'] = true;
$('.feed_favicon', this.$s.$feed_list).each(function() {
var $feed_favicon = $(this);
var feed_id = $feed_favicon.closest('.feed').attr('data-id');
$feed_favicon.attr('src', $.favicon(model.get_feed(feed_id).favicon));
});
if (!this.flags['has_chosen_feeds'] && this.model.folders.length) {
_.defer(_.bind(this.open_feedchooser_modal, this), 100);
}
},
sort_feeds: function($feeds) {
@ -904,13 +923,12 @@
exception_class += ' NB-feed-inactive';
}
var feed_counts_floater = this.make_feed_counts_floater(feed.ps, feed.nt, feed.ng, true);
var $feed = _.template('\
<<%= list_type %> class="feed <%= unread_class %> <%= exception_class %> <% if (toplevel) { %>NB-toplevel<% } %>" data-id="<%= feed.id %>">\
<div class="feed_counts">\
<%= feed_counts_floater %>\
</div>\
<img class="feed_favicon" src="<%= $.favicon(feed.favicon) %>">\
<img class="feed_favicon" src="<%= $.favicon(feed.favicon, true) %>">\
<span class="feed_title">\
<%= feed.feed_title %>\
<% if (type == "story") { %>\