From c52e5c562bf11d47f3dcf4d23fdc50c93021b95a Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Wed, 2 May 2012 16:46:00 -0700 Subject: [PATCH 01/10] Copying server settings. --- .gitignore | 3 ++- fabfile.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 179db1dcd..5432c850e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ xcuserdata .xcodeproj/ push.xcodeproj/project.pbxproj *.mode1v3 *.pbxuser -media/maintenance.html \ No newline at end of file +media/maintenance.html +config/settings \ No newline at end of file diff --git a/fabfile.py b/fabfile.py index a4f350ce4..9f3abaf88 100644 --- a/fabfile.py +++ b/fabfile.py @@ -240,6 +240,7 @@ def setup_app(): setup_vps() setup_app_firewall() setup_app_motd() + copy_app_settings() setup_gunicorn(supervisor=True) update_gunicorn() @@ -249,6 +250,7 @@ def setup_db(): setup_db_firewall() setup_db_motd() # setup_rabbitmq() + copy_task_settings() setup_memcached() setup_postgres() setup_mongo() @@ -260,6 +262,7 @@ def setup_task(): setup_vps() setup_task_firewall() setup_task_motd() + copy_task_settings() enable_celery_supervisor() setup_gunicorn(supervisor=False) update_gunicorn() @@ -495,6 +498,9 @@ def setup_node(): sudo('ufw allow 8888') put('config/supervisor_node.conf', '/etc/supervisor/conf.d/node.conf', use_sudo=True) +def copy_app_settings(): + put('config/settings/app_settings.py', '%s/local_settings.py' % env.NEWSBLUR_PATH) + run('echo "\nSERVER_NAME = \\\\"`hostname`\\\\"" >> %s/local_settings.py' % env.NEWSBLUR_PATH) # ============== # = Setup - DB = @@ -572,6 +578,10 @@ def setup_task_motd(): def enable_celery_supervisor(): put('config/supervisor_celeryd.conf', '/etc/supervisor/conf.d/celeryd.conf', use_sudo=True) +def copy_task_settings(): + put('config/settings/task_settings.py', '%s/local_settings.py' % env.NEWSBLUR_PATH) + run('echo "\nSERVER_NAME = \\\\"`hostname`\\\\"" >> %s/local_settings.py' % env.NEWSBLUR_PATH) + # ====== # = S3 = # ====== From 740cba15860fb2976090a0723dff7ea393eb69c8 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Thu, 3 May 2012 13:45:00 -0700 Subject: [PATCH 02/10] Adding NEWSBLUR.reader.count_unreads_across_all_sites() --- media/js/newsblur/reader.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/media/js/newsblur/reader.js b/media/js/newsblur/reader.js index 95425b741..c21d2634b 100644 --- a/media/js/newsblur/reader.js +++ b/media/js/newsblur/reader.js @@ -1924,6 +1924,17 @@ // = Feed Header = // =============== + count_unreads_across_all_sites: function() { + return _.reduce(this.model.feeds, function(m, v) { + if (v.active) { + m['positive'] += v.ps; + m['neutral'] += v.nt; + m['negative'] += v.ng; + } + return m; + }, {'positive': 0, 'negative': 0, 'neutral': 0}); + }, + update_header_counts: function(skip_sites, unread_view) { if (!skip_sites) { var feeds_count = _.select(this.model.feeds, function(f) { @@ -1934,14 +1945,7 @@ } } - var unread_counts = _.reduce(this.model.feeds, function(m, v) { - if (v.active) { - m['positive'] += v.ps; - m['neutral'] += v.nt; - m['negative'] += v.ng; - } - return m; - }, {'positive': 0, 'negative': 0, 'neutral': 0}); + var unread_counts = this.count_unreads_across_all_sites(); _(['positive', 'neutral', 'negative']).each(function(level) { // This is for .NB-feeds-header-count var $count = $('.NB-feeds-header-'+level); From 5f167251bbdfc4b1268a5051ab62008b153f1437 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Thu, 3 May 2012 18:33:29 -0700 Subject: [PATCH 03/10] Adding backup restore for psql. --- fabfile.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/fabfile.py b/fabfile.py index 9f3abaf88..5724c8eef 100644 --- a/fabfile.py +++ b/fabfile.py @@ -545,17 +545,19 @@ def setup_mongo(): sudo('apt-get -y install mongodb-10gen') def setup_redis(): + redis_version = '2.4.13' with cd(env.VENDOR_PATH): - run('wget http://redis.googlecode.com/files/redis-2.4.2.tar.gz') - run('tar -xzf redis-2.4.2.tar.gz') - run('rm redis-2.4.2.tar.gz') - with cd(os.path.join(env.VENDOR_PATH, 'redis-2.4.2')): + run('wget http://redis.googlecode.com/files/redis-%s.tar.gz' % redis_version) + run('tar -xzf redis-%s.tar.gz' % redis_version) + run('rm redis-%s.tar.gz' % redis_version) + with cd(os.path.join(env.VENDOR_PATH, 'redis-%s' % redis_version)): sudo('make install') put('config/redis-init', '/etc/init.d/redis', use_sudo=True) sudo('chmod u+x /etc/init.d/redis') put('config/redis.conf', '/etc/redis.conf', use_sudo=True) sudo('mkdir -p /var/lib/redis') sudo('update-rc.d redis defaults') + sudo('/etc/init.d/redis stop') sudo('/etc/init.d/redis start') def setup_db_munin(): @@ -582,6 +584,19 @@ def copy_task_settings(): put('config/settings/task_settings.py', '%s/local_settings.py' % env.NEWSBLUR_PATH) run('echo "\nSERVER_NAME = \\\\"`hostname`\\\\"" >> %s/local_settings.py' % env.NEWSBLUR_PATH) + +# ============== +# = Tasks - DB = +# ============== + +def restore_postgres(): + backup_date = '2012-05-03-08-00' + run('PYTHONPATH=/home/sclay/newsblur python s3.py get backup_postgresql_%s.sql.gz' % backup_date) + sudo('su postgres -c "createuser -U newsblur"') + sudo('su postgres -c "createdb newsblur -O newsblur"') + sudo('su postgres -c "pg_restore --role=newsblur --dbname=newsblur backup_postgresql_%s.sql.gz"' % backup_date) + + # ====== # = S3 = # ====== From 8f28e8e52e8c2f963abae280a58aff4224a504ea Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Thu, 3 May 2012 18:51:40 -0700 Subject: [PATCH 04/10] db01 -> db02 --- settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/settings.py b/settings.py index 962424451..1b18a7d07 100644 --- a/settings.py +++ b/settings.py @@ -270,8 +270,8 @@ CELERY_QUEUES = { } CELERY_DEFAULT_QUEUE = "update_feeds" BROKER_BACKEND = "redis" -BROKER_URL = "redis://db01:6379/0" -CELERY_REDIS_HOST = "db01" +BROKER_URL = "redis://db02:6379/0" +CELERY_REDIS_HOST = "db02" CELERYD_PREFETCH_MULTIPLIER = 1 CELERY_IMPORTS = ("apps.rss_feeds.tasks", ) @@ -313,7 +313,7 @@ class MasterSlaveRouter(object): # ========= REDIS = { - 'host': 'db01', + 'host': 'db02', } # ================== @@ -360,4 +360,4 @@ REDIS_POOL = redis.ConnectionPool(host=REDIS['host'], port=6379, db=0) JAMMIT = jammit.JammitAssets(NEWSBLUR_DIR) if DEBUG: - MIDDLEWARE_CLASSES += ('utils.mongo_raw_log_middleware.SqldumpMiddleware',) \ No newline at end of file + MIDDLEWARE_CLASSES += ('utils.mongo_raw_log_middleware.SqldumpMiddleware',) From 7f7887c680510206ef084a607c21e5cfacf7a02b Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Thu, 3 May 2012 19:09:36 -0700 Subject: [PATCH 05/10] db02 -> db01. --- settings.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/settings.py b/settings.py index 1b18a7d07..a5adf9c44 100644 --- a/settings.py +++ b/settings.py @@ -270,8 +270,8 @@ CELERY_QUEUES = { } CELERY_DEFAULT_QUEUE = "update_feeds" BROKER_BACKEND = "redis" -BROKER_URL = "redis://db02:6379/0" -CELERY_REDIS_HOST = "db02" +BROKER_URL = "redis://db01:6379/0" +CELERY_REDIS_HOST = "db01" CELERYD_PREFETCH_MULTIPLIER = 1 CELERY_IMPORTS = ("apps.rss_feeds.tasks", ) @@ -313,7 +313,7 @@ class MasterSlaveRouter(object): # ========= REDIS = { - 'host': 'db02', + 'host': 'db01', } # ================== From 87912917748a5a6d782707b8d40c769bb7c7ed97 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Sun, 6 May 2012 16:26:54 -0700 Subject: [PATCH 06/10] Closing #52: Adding delicious to sharing services and preferences. Thanks @palewire for the suggestion. --- media/css/reader.css | 13 +++++++++++++ media/img/reader/delicious.png | Bin 0 -> 2038 bytes media/js/newsblur/reader.js | 21 +++++++++++++++++++++ media/js/newsblur/reader_preferences.js | 4 ++++ 4 files changed, 38 insertions(+) create mode 100644 media/img/reader/delicious.png diff --git a/media/css/reader.css b/media/css/reader.css index d2192ff55..8375458a9 100644 --- a/media/css/reader.css +++ b/media/css/reader.css @@ -4441,6 +4441,9 @@ background: transparent; .NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-tumblr { background: transparent url('/media/embed/reader/tumblr.png') no-repeat 0 0; } +.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-delicious { + background: transparent url('/media/embed/reader/delicious.png') no-repeat 0 0; +} .NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-pinboard { background: transparent url('/media/embed/reader/pinboard.png') no-repeat 0 0; } @@ -4488,6 +4491,13 @@ background: transparent; .NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-tumblr .NB-menu-manage-thirdparty-tumblr { opacity: 1; } +.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-delicious .NB-menu-manage-image, +.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-delicious .NB-menu-manage-thirdparty-icon { + opacity: .2; +} +.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-delicious .NB-menu-manage-thirdparty-delicious { + opacity: 1; +} .NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-pinboard .NB-menu-manage-image, .NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-pinboard .NB-menu-manage-thirdparty-icon { opacity: .2; @@ -5795,6 +5805,9 @@ background: transparent; .NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-tumblr] { background: transparent url('/media/embed/reader/tumblr.png') no-repeat 0 0; } +.NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-delicious] { + background: transparent url('/media/embed/reader/delicious.png') no-repeat 0 0; +} .NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-pinboard] { background: transparent url('/media/embed/reader/pinboard.png') no-repeat 0 0; } diff --git a/media/img/reader/delicious.png b/media/img/reader/delicious.png new file mode 100644 index 0000000000000000000000000000000000000000..14c27eb9159a3d8a0abd58d2fec8a30ad2b6e297 GIT binary patch literal 2038 zcmeHGu?@p83}c%fkg=nuAak$E0lA~M70E#g1=m9WQ*BWslLZroDbfQW0T*1+_uzfU z)BywVekV*f;7M+Dj!1;-eywF$t4IA)6_afGoPf&5M7`!m^$59D#Uz_PC!q3C^Z6~m w-?J3ij7 Date: Mon, 7 May 2012 15:11:10 -0700 Subject: [PATCH 07/10] New preference: delay to mark a story as read. --- media/css/reader.css | 16 ++-- media/js/newsblur/reader.js | 46 ++++++++---- media/js/newsblur/reader_keyboard.js | 18 ++--- media/js/newsblur/reader_preferences.js | 97 ++++++++++++++++++++----- templates/base.html | 1 + 5 files changed, 130 insertions(+), 48 deletions(-) diff --git a/media/css/reader.css b/media/css/reader.css index 8375458a9..8d2446816 100644 --- a/media/css/reader.css +++ b/media/css/reader.css @@ -5600,7 +5600,7 @@ background: transparent; margin-right: 0; } -.NB-modal-keyboard .NB-keyboard-shortcut .NB-keyboard-shortcut-key { +.NB-keyboard-shortcut-key { border-radius: 6px; -webkit-border-radius: 6px; -moz-border-radius: 6px; @@ -5617,12 +5617,12 @@ background: transparent; margin: 0 4px 0 0; } -.NB-modal-keyboard .NB-keyboard-shortcut .NB-keyboard-shortcut-key span { +.NB-keyboard-shortcut-key span { color: #A0A0A0; padding: 0 4px; } -.NB-modal-keyboard .NB-keyboard-shortcut .NB-keyboard-shortcut-explanation { +.NB-keyboard-shortcut-explanation { float: right; font-size: 14px; font-weight: bold; @@ -5631,11 +5631,11 @@ background: transparent; color: #404030; text-shadow: 1px 1px 0 #E0E0E0; } -.NB-modal-keyboard .NB-keyboard-shortcut .NB-keyboard-shortcut-image { +.NB-keyboard-shortcut-image { clear: both; } -.NB-modal-keyboard .NB-keyboard-shortcut .NB-keyboard-shortcut-image img { +.NB-keyboard-shortcut-image img { margin: 8px 0 0 0; border: 1px solid #202020; width: 268px; @@ -5781,6 +5781,12 @@ background: transparent; -webkit-box-shadow:2px 2px 0 #D0D0D0; box-shadow:2px 2px 0 #D0D0D0; } +.NB-modal-preferences .NB-preference-readstorydelay .NB-tangle-readstorydelay { + display: inline-block; + margin: 0 16px 0 8px; + top: 2px; + width: 100px; +} .NB-modal-preferences .NB-preference.NB-preference-story-share .NB-preference-option { float: left; margin: 0 8px 4px 0; diff --git a/media/js/newsblur/reader.js b/media/js/newsblur/reader.js index 7cea7811d..3e518c3c0 100644 --- a/media/js/newsblur/reader.js +++ b/media/js/newsblur/reader.js @@ -962,15 +962,14 @@ this.active_story = story; this.mark_story_title_as_selected($next_story_title); this.mark_story_as_read(story.id); - this.mark_story_as_read_in_feed_view(story, {'animate': this.story_view == 'feed'}); } } }, - mark_story_as_read_in_feed_view: function(story, options) { - if (!story) return; + mark_story_as_read_in_feed_view: function(story_id, options) { + if (!story_id) return; options = options || {}; - $story = this.cache.feed_view_stories[story.id] || this.find_story_in_feed_view(story.id); + $story = this.cache.feed_view_stories[story_id] || this.find_story_in_feed_view(story_id); if ($story) { $story.addClass('read'); } @@ -1730,6 +1729,7 @@ 'feed_title_floater_feed_id': null, 'feed_title_floater_story_id': null, 'last_feed_view_story_feed_id': null, + 'last_read_story_id': null, '$feed_in_feed_list': {}, '$feed_counts_in_feed_list': {} }); @@ -2227,7 +2227,6 @@ if (this.active_story != story) { this.active_story = story; this.mark_story_title_as_selected($story_title); - this.mark_story_as_read_in_feed_view(story, {'animate': true}); this.unload_story_iframe(); // Used when auto-tracking the user as they move over the feed/page. @@ -2502,14 +2501,29 @@ // $story_title.parent('.story').next('.story').children('a').addClass('after_selected'); }, - mark_story_as_read: function(story_id) { + mark_story_as_read: function(story_id, skip_delay) { var self = this; - var $story_title = this.find_story_in_story_titles(story_id); - var feed_id = parseInt($story_title.data('feed_id'), 10) || this.active_feed; + var delay = this.model.preference('read_story_delay'); + + if (skip_delay) { + delay = 0; + } else if (delay == -1) { + return; + } - this.model.mark_story_as_read(story_id, feed_id, function(read) { - self.update_read_count(story_id, feed_id, false, read); - }); + this.cache.last_read_story_id = story_id; + clearTimeout(this.cache.read_story_delay); + + this.cache.read_story_delay = _.delay(_.bind(function() { + if (skip_delay || this.cache.last_read_story_id == story_id || delay == 0) { + var $story_title = this.find_story_in_story_titles(story_id); + var feed_id = parseInt($story_title.data('feed_id'), 10) || this.active_feed; + this.model.mark_story_as_read(story_id, feed_id, function(read) { + self.update_read_count(story_id, feed_id, false, read); + }); + this.mark_story_as_read_in_feed_view(story_id, {'animate': this.story_view == 'feed'}); + } + }, this), delay * 1000); }, mark_story_as_unread: function(story_id, feed_id) { @@ -2640,7 +2654,7 @@ if (_.includes(this.active_feed, folder_name)) { $('.story:not(.read)', this.$s.$story_titles).addClass('read'); _.each(this.model.stories, _.bind(function(story) { - this.mark_story_as_read_in_feed_view(story); + this.mark_story_as_read_in_feed_view(story.id); }, this)); } }, @@ -6217,7 +6231,7 @@ $.targetIs(e, { tagSelector: 'a.mark_story_as_read' }, function($t, $p){ e.preventDefault(); var story_id = $t.attr('href').slice(1).split('/'); - self.mark_story_as_read(story_id); + self.mark_story_as_read(story_id, true); }); $.targetIs(e, { tagSelector: '.NB-feed-story-premium-only a' }, function($t, $p){ e.preventDefault(); @@ -6941,7 +6955,7 @@ e.preventDefault(); self.page_in_story(0.65, -1); }); - $document.bind('keydown', 'u', function(e) { + $document.bind('keydown', 'shift+u', function(e) { e.preventDefault(); if (self.flags['sidebar_closed']) { self.open_sidebar(); @@ -7013,12 +7027,12 @@ e.preventDefault(); self.open_river_stories(); }); - $document.bind('keydown', 'shift+u', function(e) { + $document.bind('keydown', 'u', function(e) { e.preventDefault(); var story_id = self.active_story.id; console.log(["self.active_story", self.active_story]); if (self.active_story && !self.active_story.read_status) { - self.mark_story_as_read(story_id); + self.mark_story_as_read(story_id, true); } else if (self.active_story && self.active_story.read_status) { self.mark_story_as_unread(story_id); } diff --git a/media/js/newsblur/reader_keyboard.js b/media/js/newsblur/reader_keyboard.js index e9c04be1d..a7dd48619 100644 --- a/media/js/newsblur/reader_keyboard.js +++ b/media/js/newsblur/reader_keyboard.js @@ -120,11 +120,13 @@ NEWSBLUR.ReaderKeyboard.prototype = { 'n' ]) ]), - $.make('div', { className: 'NB-keyboard-shortcut NB-last' }, [ - $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Hide Sidebar'), - $.make('div', { className: 'NB-keyboard-shortcut-key' }, [ - 'u' - ]) + $.make('div', { className: 'NB-keyboard-group' }, [ + $.make('div', { className: 'NB-keyboard-shortcut' }, [ + $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Toggle read/unread'), + $.make('div', { className: 'NB-keyboard-shortcut-key' }, [ + 'u' + ]) + ]) ]) ]), $.make('div', { className: 'NB-keyboard-group' }, [ @@ -204,15 +206,13 @@ NEWSBLUR.ReaderKeyboard.prototype = { ]) ]) ]), - $.make('div', { className: 'NB-keyboard-group' }, [ - $.make('div', { className: 'NB-keyboard-shortcut' }, [ - $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Toggle read/unread'), + $.make('div', { className: 'NB-keyboard-shortcut NB-last' }, [ + $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Hide Sidebar'), $.make('div', { className: 'NB-keyboard-shortcut-key' }, [ 'shift', $.make('span', '+'), 'u' ]) - ]) ]) ]); }, diff --git a/media/js/newsblur/reader_preferences.js b/media/js/newsblur/reader_preferences.js index f0ca526d6..01fd95bed 100644 --- a/media/js/newsblur/reader_preferences.js +++ b/media/js/newsblur/reader_preferences.js @@ -313,6 +313,37 @@ _.extend(NEWSBLUR.ReaderPreferences.prototype, { 'When opening a site' ]) ]), + $.make('div', { className: 'NB-preference NB-preference-readstorydelay' }, [ + $.make('div', { className: 'NB-preference-options' }, [ + $.make('div', [ + $.make('input', { id: 'NB-preference-readstorydelay-1', type: 'radio', name: 'read_story_delay', value: '0' }), + $.make('label', { 'for': 'NB-preference-readstorydelay-1' }, [ + 'Immediately' + ]) + ]), + $.make('div', [ + $.make('input', { id: 'NB-preference-readstorydelay-2', type: 'radio', name: 'read_story_delay', value: '1' }), + $.make('label', { 'for': 'NB-preference-readstorydelay-2' }, [ + 'After ', + $.make('span', { className: 'NB-tangle-readstorydelay', 'data-var': 'delay' }), + $.make('span', { className: 'NB-tangle-seconds' }, ' second.') + ]) + ]), + $.make('div', [ + $.make('input', { id: 'NB-preference-readstorydelay-0', type: 'radio', name: 'read_story_delay', value: "-1" }), + $.make('label', { 'for': 'NB-preference-readstorydelay-0' }, [ + 'Manually by hitting ', + $.make('div', { className: 'NB-keyboard-shortcut-key', + style: 'display: inline; float: none' }, [ + 'u' + ]) + ]) + ]) + ]), + $.make('div', { className: 'NB-preference-label'}, [ + 'Mark a story as read' + ]) + ]), $.make('div', { className: 'NB-preference NB-preference-hidestorychanges' }, [ $.make('div', { className: 'NB-preference-options' }, [ $.make('div', [ @@ -519,8 +550,10 @@ _.extend(NEWSBLUR.ReaderPreferences.prototype, { }, select_preferences: function() { + var $modal = this.$modal; + if (NEWSBLUR.Preferences.timezone) { - $('select[name=timezone] option', this.$modal).each(function() { + $('select[name=timezone] option', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.timezone) { $(this).attr('selected', true); return false; @@ -528,85 +561,91 @@ _.extend(NEWSBLUR.ReaderPreferences.prototype, { }); } - $('input[name=default_view]', this.$modal).each(function() { + $('input[name=default_view]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.default_view) { $(this).attr('checked', true); return false; } }); - $('input[name=story_pane_anchor]', this.$modal).each(function() { + $('input[name=story_pane_anchor]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.story_pane_anchor) { $(this).attr('checked', true); return false; } }); - $('input[name=new_window]', this.$modal).each(function() { + $('input[name=new_window]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.new_window) { $(this).attr('checked', true); return false; } }); - $('input[name=hide_read_feeds]', this.$modal).each(function() { + $('input[name=hide_read_feeds]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.hide_read_feeds) { $(this).attr('checked', true); return false; } }); - $('input[name=feed_order]', this.$modal).each(function() { + $('input[name=feed_order]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.feed_order) { $(this).attr('checked', true); return false; } }); - $('input[name=ssl]', this.$modal).each(function() { + $('input[name=ssl]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.ssl) { $(this).attr('checked', true); return false; } }); - $('input[name=show_unread_counts_in_title]', this.$modal).each(function() { + $('input[name=show_unread_counts_in_title]', $modal).each(function() { if (NEWSBLUR.Preferences.show_unread_counts_in_title) { $(this).attr('checked', true); return false; } }); - $('input[name=open_feed_action]', this.$modal).each(function() { + $('input[name=open_feed_action]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.open_feed_action) { $(this).attr('checked', true); return false; } }); - $('input[name=hide_story_changes]', this.$modal).each(function() { + $('input[name=read_story_delay]', $modal).each(function() { + if ($(this).val() == ""+NEWSBLUR.Preferences.read_story_delay) { + $(this).attr('checked', true); + return false; + } + }); + $('input[name=hide_story_changes]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.hide_story_changes) { $(this).attr('checked', true); return false; } }); - $('input[name=feed_view_single_story]', this.$modal).each(function() { + $('input[name=feed_view_single_story]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.feed_view_single_story) { $(this).attr('checked', true); return false; } }); - $('input[name=animations]', this.$modal).each(function() { + $('input[name=animations]', $modal).each(function() { if ($(this).val() == ""+NEWSBLUR.Preferences.animations) { $(this).attr('checked', true); return false; } }); - $('input[name=folder_counts]', this.$modal).each(function() { + $('input[name=folder_counts]', $modal).each(function() { if ($(this).val() == ""+NEWSBLUR.Preferences.folder_counts) { $(this).attr('checked', true); return false; } }); - $('input[name=show_tooltips]', this.$modal).each(function() { + $('input[name=show_tooltips]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.show_tooltips) { $(this).attr('checked', true); return false; } }); - $('input[name=story_styling]', this.$modal).each(function() { + $('input[name=story_styling]', $modal).each(function() { if ($(this).val() == NEWSBLUR.Preferences.story_styling) { $(this).attr('checked', true); return false; @@ -616,10 +655,32 @@ _.extend(NEWSBLUR.ReaderPreferences.prototype, { var share_preferences = _.select(_.keys(NEWSBLUR.Preferences), function(p) { return p.indexOf('story_share') != -1; }); - _.each(share_preferences, _.bind(function(share) { + _.each(share_preferences, function(share) { var share_name = share.match(/story_share_(.*)/)[1]; - $('input#NB-preference-story-share-'+share_name, this.$modal).attr('checked', NEWSBLUR.Preferences[share]); - }, this)); + $('input#NB-preference-story-share-'+share_name, $modal).attr('checked', NEWSBLUR.Preferences[share]); + }); + + $(".NB-tangle-readstorydelay", $modal).slider({ + range: 'min', + min: 1, + max: 60, + step: 1, + value: NEWSBLUR.Preferences.read_story_delay > 0 ? NEWSBLUR.Preferences.read_story_delay : 1, + slide: _.bind(this.slide_read_story_delay_slider, this) + }); + this.slide_read_story_delay_slider(); + }, + + slide_read_story_delay_slider: function(e, ui) { + var value = (ui && ui.value) || + (NEWSBLUR.Preferences.read_story_delay > 0 ? NEWSBLUR.Preferences.read_story_delay : 1); + $(".NB-tangle-seconds", this.$modal).text(value == 1 ? value + ' second.' : value + ' seconds.'); + if (NEWSBLUR.Preferences.read_story_delay > 0 || ui) { + $("#NB-preference-readstorydelay-2", this.$modal).attr('checked', true).val(value); + if (ui) { + this.enable_save(); + } + } }, serialize_preferences: function() { diff --git a/templates/base.html b/templates/base.html index 2eab701cc..d3f049abf 100644 --- a/templates/base.html +++ b/templates/base.html @@ -39,6 +39,7 @@ 'feed_order' : 'ALPHABETICAL', 'ssl' : 0, 'open_feed_action' : 0, + 'read_story_delay' : 0, 'hide_story_changes' : 1, 'feed_view_single_story' : 0, 'animations' : true, From f683d9bd262cf89fd602dc71387ba3ca67c71b94 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Mon, 7 May 2012 15:26:33 -0700 Subject: [PATCH 08/10] Fixing keyboard dialog. --- media/js/newsblur/reader_keyboard.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/media/js/newsblur/reader_keyboard.js b/media/js/newsblur/reader_keyboard.js index a7dd48619..afdafe964 100644 --- a/media/js/newsblur/reader_keyboard.js +++ b/media/js/newsblur/reader_keyboard.js @@ -120,13 +120,11 @@ NEWSBLUR.ReaderKeyboard.prototype = { 'n' ]) ]), - $.make('div', { className: 'NB-keyboard-group' }, [ - $.make('div', { className: 'NB-keyboard-shortcut' }, [ - $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Toggle read/unread'), - $.make('div', { className: 'NB-keyboard-shortcut-key' }, [ - 'u' - ]) - ]) + $.make('div', { className: 'NB-keyboard-shortcut NB-last' }, [ + $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Toggle read/unread'), + $.make('div', { className: 'NB-keyboard-shortcut-key' }, [ + 'u' + ]) ]) ]), $.make('div', { className: 'NB-keyboard-group' }, [ @@ -206,12 +204,14 @@ NEWSBLUR.ReaderKeyboard.prototype = { ]) ]) ]), - $.make('div', { className: 'NB-keyboard-shortcut NB-last' }, [ - $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Hide Sidebar'), - $.make('div', { className: 'NB-keyboard-shortcut-key' }, [ - 'shift', - $.make('span', '+'), - 'u' + $.make('div', { className: 'NB-keyboard-group' }, [ + $.make('div', { className: 'NB-keyboard-shortcut' }, [ + $.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Hide Sidebar'), + $.make('div', { className: 'NB-keyboard-shortcut-key' }, [ + 'shift', + $.make('span', '+'), + 'u' + ]) ]) ]) ]); From 1bb442a9d01f295658f96874e8dcb05ced9d577f Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Mon, 7 May 2012 16:26:31 -0700 Subject: [PATCH 09/10] Being much more aggressive about certain sites trying to take over the iframe. Blocking nytimes.com, twitter.com, and stackoverflow.com from even allowing an Original view. --- apps/rss_feeds/models.py | 11 +++++++++++ media/css/reader.css | 6 ++++++ media/js/newsblur/reader.js | 18 ++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/apps/rss_feeds/models.py b/apps/rss_feeds/models.py index 190d4ee89..2ec3adcf3 100644 --- a/apps/rss_feeds/models.py +++ b/apps/rss_feeds/models.py @@ -32,6 +32,12 @@ from utils.diff import HTMLDiff ENTRY_NEW, ENTRY_UPDATED, ENTRY_SAME, ENTRY_ERR = range(4) +BROKEN_PAGE_URLS = [ + 'nytimes.com', + 'stackoverflow.com', + 'twitter.com', +] + class Feed(models.Model): feed_address = models.URLField(max_length=255, db_index=True) feed_address_locked = models.NullBooleanField(default=False, blank=True, null=True) @@ -111,6 +117,11 @@ class Feed(models.Model): feed['exception_type'] = None feed['exception_code'] = self.exception_code + for broken_page in BROKEN_PAGE_URLS: + if broken_page in self.feed_link: + feed['disabled_page'] = True + break + if full: feed['feed_tags'] = json.decode(self.data.popular_tags) if self.data.popular_tags else [] feed['feed_authors'] = json.decode(self.data.popular_authors) if self.data.popular_authors else [] diff --git a/media/css/reader.css b/media/css/reader.css index 8d2446816..24bcbde02 100644 --- a/media/css/reader.css +++ b/media/css/reader.css @@ -2491,12 +2491,18 @@ background: transparent; .NB-taskbar .task_button.task_view_page.NB-exception-page .NB-task-image { background-image: url('/media/embed/icons/silk/exclamation.png'); } +.NB-taskbar .task_button.task_view_page.NB-disabled-page .NB-task-image { + background-image: url('/media/embed/icons/silk/error.png'); +} .NB-taskbar .task_button.task_view_feed .NB-task-image { background: transparent url('/media/embed/icons/silk/application_view_list.png') no-repeat 0 0; } .NB-taskbar .task_button.task_view_story .NB-task-image { background: transparent url('/media/embed/icons/silk/application_view_gallery.png') no-repeat 0 0; } +.NB-taskbar .task_button.task_view_story.NB-disabled-page .NB-task-image { + background-image: url('/media/embed/icons/silk/error.png'); +} .NB-taskbar .task_button.task_story_next_positive .NB-task-image { background: transparent url('/media/embed/icons/silk/bullet_green.png') no-repeat 0 0; } diff --git a/media/js/newsblur/reader.js b/media/js/newsblur/reader.js index 3e518c3c0..6790b6c80 100644 --- a/media/js/newsblur/reader.js +++ b/media/js/newsblur/reader.js @@ -1753,6 +1753,7 @@ $('.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_story', this.$s.$taskbar).removeClass('NB-disabled'); $('.task_view_page', this.$s.$taskbar).removeClass('NB-task-return'); this.hide_content_pane_feed_counter(); // $('.feed_counts_floater').remove(); @@ -1913,8 +1914,20 @@ view = 'feed'; } $('.task_view_page').addClass('NB-exception-page'); + } else if (feed && feed.disabled_page) { + if (view == 'page') { + view = 'feed'; + } + $('.task_view_page').addClass('NB-disabled-page') + .addClass('NB-disabled'); + $('.task_view_story').addClass('NB-disabled-page') + .addClass('NB-disabled'); } else { - $('.task_view_page').removeClass('NB-exception-page'); + $('.task_view_page').removeClass('NB-disabled-page') + .removeClass('NB-disabled') + .removeClass('NB-exception-page'); + $('.task_view_story').removeClass('NB-disabled-page') + .removeClass('NB-disabled'); } this.story_view = view; @@ -3079,7 +3092,6 @@ unload_feed_iframe: function() { var $feed_iframe = this.$s.$feed_iframe; var $taskbar_view_page = $('.NB-taskbar .task_view_page'); - $taskbar_view_page.removeClass('NB-disabled'); $taskbar_view_page.removeClass('NB-task-return'); this.flags['iframe_view_loaded'] = false; @@ -4023,6 +4035,8 @@ if (view == 'page' && feed && feed.has_exception && feed.exception_type == 'page') { this.open_feed_exception_modal(this.active_feed); return; + } else if (_.contains(['page', 'story'], view) && feed && feed.disabled_page) { + view = 'feed'; } else if ($('.task_button_view.task_view_'+view).hasClass('NB-disabled')) { return; } From 852202899dcbc21711c2fd3d7b7717193c75cae9 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Mon, 7 May 2012 17:16:32 -0700 Subject: [PATCH 10/10] Don't know how I feel about this change, but http://gizmodo.com/author/mat-honan.xml is failing when 'Safari/X' is in the user agent, but only with http opener. Ugh. --- utils/feed_fetcher.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/utils/feed_fetcher.py b/utils/feed_fetcher.py index 4209c2162..bb2f342c6 100644 --- a/utils/feed_fetcher.py +++ b/utils/feed_fetcher.py @@ -58,7 +58,7 @@ class FetchFeed: modified = None etag = None - USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_1) AppleWebKit/534.48.3 (KHTML, like Gecko) Version/5.1 Safari/534.48.3 (NewsBlur Feed Fetcher - %s subscriber%s - %s)' % ( + USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.2.3 (KHTML, like Gecko) Version/5.2 (NewsBlur Feed Fetcher - %s subscriber%s - %s)' % ( self.feed.num_subscribers, 's' if self.feed.num_subscribers != 1 else '', settings.NEWSBLUR_URL @@ -253,9 +253,10 @@ class ProcessFeed: unicode(self.feed)[:30], hub_url)) PushSubscription.objects.subscribe(self_url, feed=self.feed, hub=hub_url) - logging.debug(u' ---> [%-30s] ~FYParsed Feed: new=~FG~SB%s~SN~FY up=~FY~SB%s~SN same=~FY%s err=~FR~SB%s' % ( + logging.debug(u' ---> [%-30s] ~FYParsed Feed: new=~FG~SB%s~SN~FY up=~FY~SB%s~SN same=~FY%s err=~FR~SB%s~SN~FY total=~SB%s' % ( unicode(self.feed)[:30], - ret_values[ENTRY_NEW], ret_values[ENTRY_UPDATED], ret_values[ENTRY_SAME], ret_values[ENTRY_ERR])) + ret_values[ENTRY_NEW], ret_values[ENTRY_UPDATED], ret_values[ENTRY_SAME], ret_values[ENTRY_ERR], + len(self.fpf.entries))) self.feed.update_all_statistics(full=bool(ret_values[ENTRY_NEW]), force=self.options['force']) self.feed.trim_feed() self.feed.save_feed_history(200, "OK") @@ -337,7 +338,7 @@ class Dispatcher: feed.num_subscribers, rand, quick)) continue - + ffeed = FetchFeed(feed_id, self.options) ret_feed, fetched_feed = ffeed.fetch()