mirror of
https://github.com/viq/NewsBlur.git
synced 2025-08-31 14:11:05 +00:00
Completely changing how subscriptions are counted. Now happens after page load. Also retooled Google Reader import to load, count, and fetch after page load so the user is not kept waiting. Progress bars for everything.
This commit is contained in:
parent
db3bdbc0d5
commit
aa99517511
11 changed files with 216 additions and 73 deletions
|
@ -3,8 +3,8 @@ from apps.feed_import import views
|
|||
|
||||
urlpatterns = patterns('apps.feed_import.views',
|
||||
url(r'^opml_upload$', views.opml_upload, name='opml-upload'),
|
||||
url(r'^authorize/$', views.reader_authorize, name='opml-reader-authorize'),
|
||||
url(r'^callback/$', views.reader_callback, name='opml-reader-callback'),
|
||||
url(r'^signup/$', views.import_signup, name='import-signup')
|
||||
url(r'^authorize/$', views.reader_authorize, name='google-reader-authorize'),
|
||||
url(r'^callback/$', views.reader_callback, name='google-reader-callback'),
|
||||
url(r'^signup/$', views.import_signup, name='import-signup'),
|
||||
url(r'^import_from_google_reader/$', views.import_from_google_reader, name='import-from-google-reader')
|
||||
)
|
||||
|
|
|
@ -55,7 +55,7 @@ def reader_authorize(request):
|
|||
"scope=%s&oauth_callback=http://%s%s") % (
|
||||
scope,
|
||||
Site.objects.get_current().domain,
|
||||
reverse('opml-reader-callback'),
|
||||
reverse('google-reader-callback'),
|
||||
)
|
||||
authorize_url = 'https://www.google.com/accounts/OAuthAuthorizeToken'
|
||||
|
||||
|
@ -131,7 +131,7 @@ def import_from_google_reader(request):
|
|||
scope = "http://www.google.com/reader/api"
|
||||
sub_url = "%s/0/subscription/list" % scope
|
||||
code = 0
|
||||
|
||||
|
||||
if request.user.is_authenticated():
|
||||
user_tokens = OAuthToken.objects.filter(user=request.user)
|
||||
if user_tokens.count():
|
||||
|
@ -144,6 +144,7 @@ def import_from_google_reader(request):
|
|||
reader_importer = GoogleReaderImporter(content, request.user)
|
||||
reader_importer.process()
|
||||
code = 1
|
||||
del request.session['import_from_google_reader']
|
||||
|
||||
return dict(code=code)
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ def index(request):
|
|||
feature_form = None
|
||||
if request.user.is_staff:
|
||||
feature_form = FeatureForm()
|
||||
|
||||
|
||||
howitworks_page = random.randint(0, 5)
|
||||
return render_to_response('reader/feeds.xhtml', {
|
||||
'login_form': login_form,
|
||||
|
@ -100,14 +100,8 @@ def load_feeds(request):
|
|||
return data
|
||||
|
||||
user_subs = UserSubscription.objects.select_related('feed').filter(user=user)
|
||||
updated_count = 0
|
||||
|
||||
for sub in user_subs:
|
||||
if updated_count < 200 and sub.needs_unread_recalc:
|
||||
# > 200 means that we counted enough, just move to refresh during live.
|
||||
sub.calculate_feed_scores()
|
||||
updated_count += 1
|
||||
|
||||
feeds[sub.feed.pk] = {
|
||||
'id': sub.feed.pk,
|
||||
'feed_title': sub.feed.feed_title,
|
||||
|
|
|
@ -12,6 +12,7 @@ import re
|
|||
class Command(BaseCommand):
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option("-a", "--all", dest="all", action="store_true", help="All feeds [for a user, or everybody]"),
|
||||
make_option("-s", "--silent", dest="silent", action="store_true", help="Inverse verbosity."),
|
||||
make_option("-u", "--user", dest="user", nargs=1, help="Specify user id or username"),
|
||||
make_option("-d", "--daemon", dest="daemonize", action="store_true"),
|
||||
)
|
||||
|
@ -32,7 +33,7 @@ class Command(BaseCommand):
|
|||
feeds = feeds.filter(user__username=options['user'])
|
||||
|
||||
for f in feeds:
|
||||
f.calculate_feed_scores()
|
||||
f.calculate_feed_scores(silent=options['silent'])
|
||||
|
||||
def daemonize():
|
||||
"""
|
||||
|
|
|
@ -506,7 +506,7 @@ a img {
|
|||
/* = Feeds Progress Bar = */
|
||||
/* ====================== */
|
||||
|
||||
#NB-feeds-progress {
|
||||
#NB-progress {
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
|
@ -522,11 +522,11 @@ a img {
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
.NB-feeds-progress-container {
|
||||
.NB-progress-container {
|
||||
border-top: 1px solid #E0E0E0;
|
||||
}
|
||||
|
||||
#NB-feeds-progress .NB-feeds-progress-close {
|
||||
#NB-progress .NB-progress-close {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
float: right;
|
||||
|
@ -535,19 +535,47 @@ a img {
|
|||
background: transparent url('../img/icons/close.png') no-repeat 0 0;
|
||||
}
|
||||
|
||||
#NB-feeds-progress .NB-feeds-progress-title {
|
||||
#NB-progress .NB-progress-title {
|
||||
padding: 5px 15px 0;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
#NB-feeds-progress .NB-feeds-progress-bar {
|
||||
#NB-progress .NB-progress-bar {
|
||||
height:6px;
|
||||
margin:6px 50px 0;
|
||||
}
|
||||
|
||||
#NB-feeds-progress .NB-feeds-progress-counts {
|
||||
#NB-progress .NB-progress-link {
|
||||
display: none;
|
||||
margin: -2px 0 0;
|
||||
}
|
||||
|
||||
#NB-progress .NB-progress-link a {
|
||||
-moz-box-shadow:1px 1px 1px #202020;
|
||||
-webkit-box-shadow:1px 1px 1px #202020;
|
||||
box-shadow:1px 1px 1px #202020;
|
||||
-moz-border-radius:4px;
|
||||
border-radius: 4px;
|
||||
border:1px solid #606060;
|
||||
font-size:12px;
|
||||
margin:0 4px 0;
|
||||
padding:0px 8px;
|
||||
text-decoration:none;
|
||||
text-transform:uppercase;
|
||||
background-color: #217412;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#NB-progress.NB-progress-error .NB-progress-link {
|
||||
display: block;
|
||||
}
|
||||
#NB-progress.NB-progress-error .NB-progress-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#NB-progress .NB-progress-counts {
|
||||
float: left;
|
||||
font-size: 10px;
|
||||
color: #B0B0B0;
|
||||
|
@ -555,7 +583,7 @@ a img {
|
|||
width: 50px;
|
||||
}
|
||||
|
||||
#NB-feeds-progress .NB-feeds-progress-percentage {
|
||||
#NB-progress .NB-progress-percentage {
|
||||
float: right;
|
||||
clear: both;
|
||||
color: #B0B0B0;
|
||||
|
@ -1923,12 +1951,13 @@ a.NB-splash-link:hover {
|
|||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.NB-add .NB-opml-reader-oauth {
|
||||
.NB-add .NB-google-reader-oauth {
|
||||
margin: 4px 0 6px 0;
|
||||
text-decoration: none;
|
||||
float: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ================ */
|
||||
/* = Manage Feeds = */
|
||||
/* ================ */
|
||||
|
|
|
@ -478,6 +478,10 @@ NEWSBLUR.AssetModel.Reader.prototype = {
|
|||
}, callback, callback, {
|
||||
'ajax_group': 'statistics'
|
||||
});
|
||||
},
|
||||
|
||||
start_import_from_google_reader: function(callback) {
|
||||
this.make_request('/import/import_from_google_reader/', {}, callback);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
$intelligence_slider: $('.NB-intelligence-slider'),
|
||||
$mouse_indicator: $('#mouse-indicator'),
|
||||
$feed_link_loader: $('#NB-feeds-list-loader'),
|
||||
$feeds_progress: $('#NB-feeds-progress')
|
||||
$feeds_progress: $('#NB-progress')
|
||||
};
|
||||
this.flags = {
|
||||
'feed_view_images_loaded': {},
|
||||
|
@ -63,7 +63,6 @@
|
|||
this.start_import_from_google_reader();
|
||||
} else {
|
||||
this.load_feeds();
|
||||
this.setup_feed_refresh();
|
||||
}
|
||||
this.apply_resizable_layout();
|
||||
this.cornerize_buttons();
|
||||
|
@ -538,7 +537,6 @@
|
|||
this.make_feeds_folder($feed_list, folders, 0);
|
||||
this.$s.$feed_link_loader.fadeOut(250);
|
||||
|
||||
this.check_feed_fetch_progress();
|
||||
|
||||
if (!folders.length) {
|
||||
this.setup_ftux_add_feed_callout();
|
||||
|
@ -550,6 +548,11 @@
|
|||
|
||||
$('.feed', $feed_list).tsort('.feed_title');
|
||||
$('.folder', $feed_list).tsort('.folder_title');
|
||||
|
||||
if (NEWSBLUR.Globals.is_authenticated) {
|
||||
this.start_count_unreads_after_import();
|
||||
this.force_feed_refresh($.rescope(this.finish_count_unreads_after_import, this));
|
||||
}
|
||||
},
|
||||
|
||||
make_feeds_folder: function($feeds, items, depth) {
|
||||
|
@ -669,35 +672,39 @@
|
|||
var $progress = this.$s.$feeds_progress;
|
||||
var percentage = parseInt(this.counts['fetched_feeds'] / (this.counts['unfetched_feeds'] + this.counts['fetched_feeds']) * 100, 10);
|
||||
|
||||
var titles = [
|
||||
"Fetching your feeds",
|
||||
"Fishing for feeds",
|
||||
"Herding feeds",
|
||||
"Fetching your feeds",
|
||||
"Feeds are being fetched"
|
||||
];
|
||||
$('.NB-feeds-progress-title', $progress).text(titles[Math.floor(Math.random()*titles.length)]);
|
||||
$('.NB-feeds-progress-counts-fetched', $progress).text(this.counts['fetched_feeds']);
|
||||
$('.NB-feeds-progress-counts-total', $progress).text(this.counts['unfetched_feeds'] + this.counts['fetched_feeds']);
|
||||
$('.NB-feeds-progress-percentage', $progress).text(percentage + '%');
|
||||
$('.NB-feeds-progress-bar', $progress).progressbar({
|
||||
$('.NB-progress-title', $progress).text('Fetching your feeds');
|
||||
$('.NB-progress-counts', $progress).show();
|
||||
$('.NB-progress-counts-fetched', $progress).text(this.counts['fetched_feeds']);
|
||||
$('.NB-progress-counts-total', $progress).text(this.counts['unfetched_feeds'] + this.counts['fetched_feeds']);
|
||||
$('.NB-progress-percentage', $progress).show().text(percentage + '%');
|
||||
$('.NB-progress-bar', $progress).progressbar({
|
||||
value: percentage
|
||||
});
|
||||
|
||||
if (!$progress.is(':visible')) {
|
||||
setTimeout(function() {
|
||||
$progress.css({'display': 'block', 'opacity': 0}).animate({
|
||||
'opacity': 1,
|
||||
'bottom': 31
|
||||
}, {
|
||||
'duration': 750
|
||||
});
|
||||
self.$s.$feed_list.animate({'bottom': 73}, {'duration': 750});
|
||||
self.show_progress_bar();
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
show_progress_bar: function($progress) {
|
||||
$progress = $progress || this.$s.$feeds_progress;
|
||||
|
||||
if (!$progress.is(':visible')) {
|
||||
$progress.css({'display': 'block', 'opacity': 0}).animate({
|
||||
'opacity': 1,
|
||||
'bottom': 31
|
||||
}, {
|
||||
'queue': false,
|
||||
'duration': 750
|
||||
});
|
||||
|
||||
this.$s.$feed_list.animate({'bottom': 73}, {'duration': 750, 'queue': false});
|
||||
}
|
||||
},
|
||||
|
||||
hide_unfetched_feed_progress: function(permanent) {
|
||||
hide_progress_bar: function(permanent) {
|
||||
var $progress = this.$s.$feeds_progress;
|
||||
|
||||
if (permanent) {
|
||||
|
@ -709,11 +716,20 @@
|
|||
'bottom': 0
|
||||
}, {
|
||||
'duration': 750,
|
||||
'queue': false,
|
||||
'complete': function() {
|
||||
$progress.css({'display': 'none'});
|
||||
}
|
||||
});
|
||||
this.$s.$feed_list.animate({'bottom': '30px'}, {'duration': 750});
|
||||
this.$s.$feed_list.animate({'bottom': '30px'}, {'duration': 750, 'queue': false});
|
||||
},
|
||||
|
||||
hide_unfetched_feed_progress: function(permanent) {
|
||||
if (permanent) {
|
||||
this.model.preference('hide_fetch_progress', true);
|
||||
}
|
||||
|
||||
this.hide_progress_bar();
|
||||
},
|
||||
|
||||
load_sortable_feeds: function() {
|
||||
|
@ -2655,31 +2671,126 @@
|
|||
// =============================
|
||||
// = Import from Google Reader =
|
||||
// =============================
|
||||
|
||||
|
||||
start_import_from_google_reader: function() {
|
||||
|
||||
var self = this;
|
||||
var $progress = this.$s.$feeds_progress;
|
||||
var $bar = $('.NB-progress-bar', $progress);
|
||||
var percentage = 0;
|
||||
|
||||
$('.NB-progress-title', $progress).text('Importing from Google Reader');
|
||||
$('.NB-progress-counts', $progress).hide();
|
||||
$('.NB-progress-percentage', $progress).hide();
|
||||
$bar.progressbar({
|
||||
value: percentage
|
||||
});
|
||||
|
||||
var animate = function() {
|
||||
var time = 50;
|
||||
if (percentage > 90) {
|
||||
time = 500;
|
||||
} else if (percentage > 80) {
|
||||
time = 400;
|
||||
} else if (percentage > 70) {
|
||||
time = 300;
|
||||
} else if (percentage > 60) {
|
||||
time = 200;
|
||||
} else if (percentage > 50) {
|
||||
time = 100;
|
||||
}
|
||||
setTimeout(function() {
|
||||
if (!self.flags['import_from_google_reader_finished']) {
|
||||
percentage += 1;
|
||||
$bar.progressbar({value: percentage});
|
||||
animate();
|
||||
}
|
||||
}, time);
|
||||
};
|
||||
animate();
|
||||
|
||||
this.show_progress_bar();
|
||||
|
||||
this.model.start_import_from_google_reader($.rescope(this.finish_import_from_google_reader, this));
|
||||
},
|
||||
|
||||
|
||||
finish_import_from_google_reader: function(e, data) {
|
||||
if (data.code >= 1) {
|
||||
this.start_count_unreads_after_import();
|
||||
}
|
||||
var $progress = this.$s.$feeds_progress;
|
||||
var $bar = $('.NB-progress-bar', $progress);
|
||||
this.flags['import_from_google_reader_finished'] = true;
|
||||
|
||||
if (data.code >= 1) {
|
||||
$bar.progressbar({value: 100});
|
||||
this.load_feeds();
|
||||
} else {
|
||||
NEWSBLUR.log(['Import Error!', data]);
|
||||
this.$s.$feed_link_loader.fadeOut(250);
|
||||
$progress.addClass('NB-progress-error');
|
||||
$('.NB-progress-title', $progress).text('Error importing Google Reader');
|
||||
$('.NB-progress-link', $progress).html($.make('a', { href: NEWSBLUR.URLs['google-reader-authorize'], className: 'NB-splash-link' }, 'Try importing again'));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
start_count_unreads_after_import: function() {
|
||||
|
||||
var self = this;
|
||||
var $progress = this.$s.$feeds_progress;
|
||||
var $bar = $('.NB-progress-bar', $progress);
|
||||
var percentage = 0;
|
||||
var factor = 17500 * _.keys(this.model.feeds).length / 40000;
|
||||
|
||||
$('.NB-progress-title', $progress).text('Counting is difficult');
|
||||
$('.NB-progress-counts', $progress).hide();
|
||||
$('.NB-progress-percentage', $progress).hide();
|
||||
$bar.progressbar({
|
||||
value: percentage
|
||||
});
|
||||
|
||||
var animate = function() {
|
||||
// 17,500 ticks
|
||||
var time = factor;
|
||||
if (percentage > 90) {
|
||||
time = factor * 100;
|
||||
} else if (percentage > 80) {
|
||||
time = factor * 50;
|
||||
} else if (percentage > 70) {
|
||||
time = factor * 20;
|
||||
} else if (percentage > 60) {
|
||||
time = factor * 8;
|
||||
} else if (percentage > 50) {
|
||||
time = factor * 2;
|
||||
}
|
||||
setTimeout(function() {
|
||||
if (!self.flags['count_unreads_after_import_finished']) {
|
||||
percentage += 1;
|
||||
$bar.progressbar({value: percentage});
|
||||
animate();
|
||||
}
|
||||
}, time);
|
||||
};
|
||||
animate();
|
||||
|
||||
setTimeout(function() {
|
||||
if (!self.flags['count_unreads_after_import_finished']) {
|
||||
self.show_progress_bar();
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
|
||||
|
||||
finish_count_unreads_after_import: function(e, data) {
|
||||
this.setup_feed_refresh();
|
||||
// this.hide
|
||||
this.post_feed_refresh(e, data);
|
||||
$('.NB-progress-bar', this.$s.$feeds_progress).progressbar({
|
||||
value: 100
|
||||
});
|
||||
this.flags['count_unreads_after_import_finished'] = true;
|
||||
this.$s.$feed_link_loader.fadeOut(250);
|
||||
this.setup_feed_refresh();
|
||||
if (!this.flags['has_unfetched_feeds']) {
|
||||
this.hide_progress_bar();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// ==========
|
||||
// = Events =
|
||||
// ==========
|
||||
|
||||
|
||||
handle_clicks: function(elem, e) {
|
||||
var self = this;
|
||||
// var start = (new Date().getMilliseconds());
|
||||
|
@ -2868,7 +2979,7 @@
|
|||
e.preventDefault();
|
||||
self.lock_mouse_indicator();
|
||||
});
|
||||
$.targetIs(e, { tagSelector: '.NB-feeds-progress-close' }, function($t, $p){
|
||||
$.targetIs(e, { tagSelector: '.NB-progress-close' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
self.hide_unfetched_feed_progress(true);
|
||||
});
|
||||
|
|
|
@ -61,7 +61,7 @@ NEWSBLUR.ReaderAddFeed.prototype = {
|
|||
'Import feeds'
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset-fields' }, [
|
||||
$.make('a', { href: NEWSBLUR.URLs['opml-reader-authorize'], className: 'NB-opml-reader-oauth NB-modal-submit-save NB-modal-submit-button' }, [
|
||||
$.make('a', { href: NEWSBLUR.URLs['google-reader-authorize'], className: 'NB-google-reader-oauth NB-modal-submit-save NB-modal-submit-button' }, [
|
||||
'Import from Google Reader',
|
||||
$.make('img', { className: 'NB-add-google-reader-arrow', src: NEWSBLUR.Globals['MEDIA_URL']+'img/icons/silk/arrow_right.png' })
|
||||
]),
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
'view_settings': {}
|
||||
};
|
||||
NEWSBLUR.URLs = {
|
||||
'opml-reader-authorize': "{% url opml-reader-authorize %}"
|
||||
'google-reader-authorize': "{% url google-reader-authorize %}"
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
{% endif %}
|
||||
|
||||
<div class="NB-signup-orline {% if signup_form.errors %}NB-signup-orline-reduced{% endif %}">— <span class="NB-signup-orline-or">or</span> —</div>
|
||||
<a href="{% url opml-reader-authorize %}" class="NB-splash-link NB-signup-google">Import from<br /><img src="{{ MEDIA_URL }}img/reader/google-reader-logo.png" width="112" height="24" /></a>
|
||||
<a href="{% url google-reader-authorize %}" class="NB-splash-link NB-signup-google">Import from<br /><img src="{{ MEDIA_URL }}img/reader/google-reader-logo.png" width="112" height="24" /></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -268,17 +268,18 @@
|
|||
|
||||
<ul class="left-center" id="feed_list"></ul>
|
||||
|
||||
<div id="NB-feeds-progress">
|
||||
<div class="NB-feeds-progress-container">
|
||||
<div class="NB-feeds-progress-close"></div>
|
||||
<div class="NB-feeds-progress-title">Fetching your feeds</div>
|
||||
<div class="NB-feeds-progress-percentage"></div>
|
||||
<div class="NB-feeds-progress-counts">
|
||||
<span class="NB-feeds-progress-counts-fetched"></span>
|
||||
<div id="NB-progress">
|
||||
<div class="NB-progress-container">
|
||||
<div class="NB-progress-close"></div>
|
||||
<div class="NB-progress-title">Fetching your feeds</div>
|
||||
<div class="NB-progress-percentage"></div>
|
||||
<div class="NB-progress-link"></div>
|
||||
<div class="NB-progress-counts">
|
||||
<span class="NB-progress-counts-fetched"></span>
|
||||
/
|
||||
<span class="NB-feeds-progress-counts-total"></span>
|
||||
<span class="NB-progress-counts-total"></span>
|
||||
</div>
|
||||
<div class="NB-feeds-progress-bar"></div>
|
||||
<div class="NB-progress-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -264,7 +264,9 @@ class Dispatcher:
|
|||
user_subs = UserSubscription.objects.filter(feed=feed)
|
||||
for sub in user_subs:
|
||||
cache.delete('usersub:%s' % sub.user_id)
|
||||
sub.calculate_feed_scores(silent=True)
|
||||
# sub.calculate_feed_scores(silent=True)
|
||||
sub.needs_unread_recalc = True
|
||||
sub.save()
|
||||
if ret_entries.get(ENTRY_NEW) or ret_entries.get(ENTRY_UPDATED):
|
||||
feed.get_stories(force=True)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue