Merge branch 'master' of github.com:samuelclay/NewsBlur

* 'master' of github.com:samuelclay/NewsBlur:
  Fixing text shadows.
  Styling reply/edit buttons.
  Forcing a decent timelimit on story cleanup task.
  Fixing broken profile editor dialog.
  Changing story scroll offset on blurblogs.
  Fixing blurblog scrolling on iphone. Fixed offset of folder menu. Changing modal shadow.
  Launching read folder with All stories and not just unread stories.
  Oldest first goes back two weeks on all stories.
  Using mark_read_date in all stories read_filter by folder.
  Fixing all read_filter for folders by including hidden feeds. Also marking stories beyond the unread cutoff as read, hoping the redis store of read stories takes care of the rest.
  Speeding up All Site Stories. Also beta-ing river with read_filter of all (not just unread).
This commit is contained in:
Samuel Clay 2013-01-14 10:21:04 -08:00
commit d782b6106f
15 changed files with 135 additions and 76 deletions

View file

@ -132,7 +132,7 @@ class UserSubscription(models.Model):
current_time = int(time.time() + 60*60*24)
if order == 'oldest':
byscorefunc = r.zrangebyscore
if read_filter == 'unread' or True:
if read_filter == 'unread':
min_score = int(time.mktime(self.mark_read_date.timetuple())) + 1
else:
now = datetime.datetime.now()

View file

@ -50,7 +50,8 @@ class CleanAnalytics(Task):
class CleanStories(Task):
name = 'clean-stories'
time_limit = 60 * 60 # 1 hour
def run(self, **kwargs):
days_ago = (datetime.datetime.utcnow() -
datetime.timedelta(days=settings.DAYS_OF_UNREAD*5))

View file

@ -724,6 +724,8 @@ def load_river_stories__redis(request):
order = request.REQUEST.get('order', 'newest')
read_filter = request.REQUEST.get('read_filter', 'unread')
now = localtime_for_timezone(datetime.datetime.now(), user.profile.timezone)
UNREAD_CUTOFF = (datetime.datetime.utcnow() -
datetime.timedelta(days=settings.DAYS_OF_UNREAD))
if not feed_ids:
usersubs = UserSubscription.objects.filter(user=user, active=True)
@ -740,8 +742,25 @@ def load_river_stories__redis(request):
found_feed_ids = list(set([story['story_feed_id'] for story in stories]))
stories, user_profiles = MSharedStory.stories_with_comments_and_profiles(stories, user.pk)
feed_marked_read_dates = None
if read_filter == 'all':
feed_marked_read_dates = dict((us.feed_id, us.mark_read_date)
for us in UserSubscription.objects.filter(user=user,
feed__in=found_feed_ids).only(
'feed', 'mark_read_date'))
# Find starred stories
if found_feed_ids:
if read_filter == 'all':
story_ids = [story['id'] for story in stories]
userstories_db = MUserStory.objects(user_id=user.pk,
feed_id__in=found_feed_ids,
story_id__in=story_ids
).only('story_id').hint([('user_id', 1),
('feed_id', 1),
('story_id', 1)])
userstories = set(us.story_id for us in userstories_db)
else:
userstories = []
starred_stories = MStarredStory.objects(
user_id=user.pk,
story_feed_id__in=found_feed_ids
@ -749,6 +768,7 @@ def load_river_stories__redis(request):
starred_stories = dict([(story.story_guid, story.starred_date)
for story in starred_stories])
else:
userstories = []
starred_stories = {}
# Intelligence classifiers for all feeds involved
@ -772,9 +792,17 @@ def load_river_stories__redis(request):
classifier_titles=classifier_titles,
classifier_tags=classifier_tags)
# Just need to format stories
for story in stories:
story['read_status'] = 0
if read_filter == 'all':
if story['id'] in userstories:
story['read_status'] = 1
elif story['story_date'] < feed_marked_read_dates[story['story_feed_id']]:
story['read_status'] = 1
elif story['story_date'] < UNREAD_CUTOFF:
story['read_status'] = 1
story_date = localtime_for_timezone(story['story_date'], 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)

View file

@ -12,8 +12,8 @@
padding: 8px;
-moz-box-shadow: 8px 8px 15px #505050;
-webkit-box-shadow: 8px 8px 15px #505050;
box-shadow: 8px 8px 15px #505050;
border: 1px solid #303030;
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px, rgba(255, 255, 255, 0.4) 0px 0px 300px 0px;
border: 1px solid rgba(5, 5, 5,.6);
}
/* =================== */

View file

@ -1707,11 +1707,11 @@ background: transparent;
position: absolute;
}
#story_pane .NB-story-iframe {
#story_pane .NB-text-view {
left: 200%;
top: 0;
}
#story_pane .NB-text-view {
#story_pane .NB-story-iframe {
left: 300%;
top: 0;
}
@ -2364,7 +2364,14 @@ background: transparent;
line-height: 9px;
font-size: 9px;
height: 9px;
border-top: 1px solid rgba(255, 255, 255, .15);
border-left: 1px solid rgba(255, 255, 255, .15);
border-bottom: 1px solid rgba(0, 0, 0, .1);
border-right: 1px solid rgba(0, 0, 0, .1);
text-shadow: 0 1px 0 rgba(0, 0, 0, .1);
}
#story_pane .NB-story-comment .NB-story-comment-reply-button:hover .NB-story-comment-reply-button-wrapper {
background-color: #DE772B;
}
@ -2384,7 +2391,7 @@ background: transparent;
overflow: hidden;
clear: both;
position: relative;
padding: 6px 0 6px 32px;
padding: 5px 0 7px 32px;
line-height: 18px;
}
#story_pane .NB-story-comment-reply .NB-story-comment-reply-photo {
@ -2398,7 +2405,7 @@ background: transparent;
}
#story_pane .NB-story-comment-edit-button {
padding: 4px 8px 4px 12px;
padding: 3px 8px 5px 12px;
float: left;
cursor: pointer;
}
@ -2410,6 +2417,11 @@ background: transparent;
line-height: 9px;
font-size: 9px;
height: 9px;
border-top: 1px solid rgba(255, 255, 255, .15);
border-left: 1px solid rgba(255, 255, 255, .15);
border-bottom: 1px solid rgba(0, 0, 0, .1);
border-right: 1px solid rgba(0, 0, 0, .1);
text-shadow: 0 1px 0 rgba(0, 0, 0, .1);
}
#story_pane .NB-story-comment-edit-button:hover .NB-story-comment-edit-button-wrapper {
background-color: #5073BC;
@ -2488,7 +2500,7 @@ background: transparent;
#story_pane .NB-story-comments-public-header {
background-color: #A0A0A0;
color: #FFF;
text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
text-shadow: 0 1px 0 rgba(0, 0, 0, .5);
background-image: -webkit-gradient(
linear,
@ -3226,7 +3238,7 @@ background: transparent;
.NB-taskbar .NB-task-view-switch-arrow {
position: absolute;
top: 8px;
right: -8px;
left: -8px;
width: 16px;
height: 16px;
background: transparent url('/media/embed/icons/silk/arrow_switch.png') no-repeat center 0px;

View file

@ -479,9 +479,6 @@ header {
padding: 12px 78px 0 28px;
position: relative;
}
.NB-unauthenticated .NB-story-content {
padding-right: 228px;
}
/*@media all and (max-width: 800px) {
.NB-story-content {
padding-right: 100px;

View file

@ -536,8 +536,8 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
this.make_request('/reader/river_stories', {
feeds: feeds,
page: page,
order: this.view_setting(feed_id, 'order')
// read_filter: this.view_setting(feed_id, 'read_filter')
order: this.view_setting(feed_id, 'order'),
read_filter: this.view_setting(feed_id, 'read_filter')
}, pre_callback, error_callback, {
'ajax_group': (page ? 'feed_page' : 'feed'),
'request_type': 'GET'

View file

@ -228,6 +228,18 @@ NEWSBLUR.Collections.Folders = Backbone.Collection.extend({
}
});
},
feeds_with_unreads: function(options) {
options = options || {};
return _.compact(_.flatten(this.map(function(item) {
if (item.is_feed()) {
return item.feed.has_unreads(options) && item.feed;
} else if (item.is_folder()) {
return item.folders.feeds_with_unreads(options);
}
})));
},
propagate_feed_selected: function() {
if (this.parent_folder) {

View file

@ -1403,8 +1403,14 @@
NEWSBLUR.router.navigate(url);
}
}
var feeds = this.list_feeds_with_unreads_in_folder($folder, false, true);
var visible_only = this.model.view_setting(this.active_feed, 'read_filter') == 'unread';
var feeds;
if (visible_only) {
feeds = this.list_feeds_with_unreads_in_folder(this.active_folder.folders, false, visible_only);
} else {
feeds = this.active_folder.feed_ids_in_folder();
}
this.cache['river_feeds_with_unreads'] = feeds;
this.hide_stories_error();
this.show_stories_progress_bar(feeds.length);
@ -1452,29 +1458,28 @@
}
},
list_feeds_with_unreads_in_folder: function($folder, counts_only, visible_only) {
list_feeds_with_unreads_in_folder: function(folder, counts_only, visible_only) {
var model = this.model;
var unread_view = this.get_unread_view_name();
$folder = $folder || this.$s.$feed_list;
folder = folder || this.active_folder.folders;
var $feeds = $('.feed:not(.NB-empty)', $folder);
var feeds = _.compact(_.map($('.feed:not(.NB-empty)', $folder), function(o) {
var feed_id = parseInt($(o).data('id'), 10);
var feed = model.get_feed(feed_id);
if (!feed) {
return;
} else if (counts_only && !visible_only) {
if (!folder || folder.get('fake')) {
folder = NEWSBLUR.assets.folders;
}
var feeds = _.compact(_.map(folder.feeds_with_unreads(), function(feed) {
if (counts_only && !visible_only) {
return feed.get('ps') + feed.get('nt') + feed.get('ng');
} else if (counts_only && visible_only) {
if (unread_view == 'positive') return feed.get('ps');
if (unread_view == 'neutral') return feed.get('ps') + feed.get('nt');
if (unread_view == 'negative') return feed.get('ps') + feed.get('nt') + feed.get('ng');
} else if (!counts_only && visible_only) {
if (unread_view == 'positive') return feed.get('ps') && feed_id;
if (unread_view == 'neutral') return (feed.get('ps') || feed.get('nt')) && feed_id;
if (unread_view == 'negative') return (feed.get('ps') || feed.get('nt') || feed.get('ng')) && feed_id;
if (unread_view == 'positive') return feed.get('ps') && feed.id;
if (unread_view == 'neutral') return (feed.get('ps') || feed.get('nt')) && feed.id;
if (unread_view == 'negative') return (feed.get('ps') || feed.get('nt') || feed.get('ng')) && feed.id;
} else {
return (feed.get('ps') || feed.get('nt') || feed.get('ng')) && feed_id;
return (feed.get('ps') || feed.get('nt') || feed.get('ng')) && feed.id;
}
}));
@ -1759,7 +1764,10 @@
NEWSBLUR.app.original_tab_view.iframe_not_busting();
this.model.flags['no_more_stories'] = true;
message = message || "Oh no! <br> There was an error!";
if (!message || message == 'error') {
message = "Oh no! <br> There was an error!";
}
if (data && data.status) {
if (data.status == 502) {
message = "NewsBlur is down right now. <br> Try again soon.";
@ -2345,8 +2353,8 @@
var $taskbar_buttons = $('.NB-taskbar .task_button_view');
var $feed_view = this.$s.$feed_view;
var $feed_iframe = this.$s.$feed_iframe;
var $page_to_feed_arrow = $('.NB-taskbar .NB-task-view-page-to-feed-arrow');
var $feed_to_story_arrow = $('.NB-taskbar .NB-task-view-feed-to-story-arrow');
var $to_feed_arrow = $('.NB-taskbar .NB-task-view-to-feed-arrow');
var $to_story_arrow = $('.NB-taskbar .NB-task-view-to-story-arrow');
var $to_text_arrow = $('.NB-taskbar .NB-task-view-to-text-arrow');
if (!options.skip_save_type && this.story_view != view) {
@ -2354,17 +2362,17 @@
}
this.hide_stories_error();
$page_to_feed_arrow.hide();
$feed_to_story_arrow.hide();
$to_feed_arrow.hide();
$to_story_arrow.hide();
$to_text_arrow.hide();
this.flags['page_view_showing_feed_view'] = false;
this.flags['feed_view_showing_story_view'] = false;
this.flags['temporary_story_view'] = false;
if (options.skip_save_type == 'page') {
$page_to_feed_arrow.show();
$to_feed_arrow.show();
this.flags['page_view_showing_feed_view'] = true;
} else if (options.skip_save_type == 'story') {
$feed_to_story_arrow.show();
$to_story_arrow.show();
this.flags['feed_view_showing_story_view'] = true;
} else if (options.skip_save_type == 'text') {
$to_text_arrow.show();
@ -2413,7 +2421,7 @@
});
NEWSBLUR.app.story_list.reset_story_positions();
} else if (view == 'story') {
} else if (view == 'text') {
$story_pane.animate({
'left': -2 * $feed_iframe.width()
}, {
@ -2421,11 +2429,11 @@
'duration': this.model.preference('animations') ? 550 : 0,
'queue': false
});
NEWSBLUR.app.story_tab_view.load_story_iframe();
NEWSBLUR.app.text_tab_view.load_story();
if (!this.active_story) {
this.show_next_story(1);
}
} else if (view == 'text') {
} else if (view == 'story') {
$story_pane.animate({
'left': -3 * $feed_iframe.width()
}, {
@ -2433,7 +2441,7 @@
'duration': this.model.preference('animations') ? 550 : 0,
'queue': false
});
NEWSBLUR.app.text_tab_view.load_story();
NEWSBLUR.app.story_tab_view.load_story_iframe();
if (!this.active_story) {
this.show_next_story(1);
}
@ -2451,20 +2459,20 @@
// view = 'page';
} else if ($active.hasClass('task_view_feed')) {
view = 'page';
} else if ($active.hasClass('task_view_story')) {
view = 'feed';
} else if ($active.hasClass('task_view_text')) {
view = 'story';
view = 'feed';
} else if ($active.hasClass('task_view_story')) {
view = 'text';
}
} else if (direction == 1) {
if ($active.hasClass('task_view_page')) {
view = 'feed';
} else if ($active.hasClass('task_view_feed')) {
view = 'story';
} else if ($active.hasClass('task_view_story')) {
view = 'text';
} else if ($active.hasClass('task_view_text')) {
// view = 'story';
view = 'story';
} else if ($active.hasClass('task_view_story')) {
// view = 'text';
}
}
@ -2775,10 +2783,10 @@
])),
$.make('li', { className: 'NB-menu-separator' }),
$.make('li', { className: 'NB-menu-subitem NB-menu-manage-controls NB-menu-manage-controls-feed' }, [
(NEWSBLUR.Globals.is_admin && $.make('ul', { className: 'segmented-control NB-menu-manage-view-setting-order' }, [
$.make('ul', { className: 'segmented-control NB-menu-manage-view-setting-order' }, [
$.make('li', { className: 'NB-view-setting-order-newest NB-active' }, 'Newest first'),
$.make('li', { className: 'NB-view-setting-order-oldest' }, 'Oldest')
])),
]),
$.make('ul', { className: 'segmented-control NB-menu-manage-view-setting-readfilter' }, [
$.make('li', { className: 'NB-view-setting-readfilter-all NB-active' }, 'All stories'),
$.make('li', { className: 'NB-view-setting-readfilter-unread' }, 'Unread only')
@ -2834,7 +2842,11 @@
$.make('ul', { className: 'segmented-control NB-menu-manage-view-setting-order' }, [
$.make('li', { className: 'NB-view-setting-order-newest NB-active' }, 'Newest first'),
$.make('li', { className: 'NB-view-setting-order-oldest' }, 'Oldest')
])
]),
(NEWSBLUR.Globals.is_admin && $.make('ul', { className: 'segmented-control NB-menu-manage-view-setting-readfilter' }, [
$.make('li', { className: 'NB-view-setting-readfilter-all NB-active' }, 'All stories'),
$.make('li', { className: 'NB-view-setting-readfilter-unread' }, 'Unread only')
]))
]),
$.make('li', { className: 'NB-menu-separator' }),
$.make('li', { className: 'NB-menu-item NB-menu-manage-move NB-menu-manage-folder-move' }, [
@ -3698,7 +3710,6 @@
get_unread_count: function(visible_only, feed_id) {
var total = 0;
var $folder;
feed_id = feed_id || this.active_feed;
var feed = this.model.get_feed(feed_id);
@ -3719,12 +3730,7 @@
}
return total;
} else if (this.flags['river_view'] && !this.flags['social_view']) {
if (feed_id == 'river:') {
$folder = this.$s.$feed_list;
} else {
$folder = $('li.folder.NB-selected');
}
var counts = this.list_feeds_with_unreads_in_folder($folder, true, visible_only);
var counts = this.list_feeds_with_unreads_in_folder(this.active_folder.folders, true, visible_only);
return _.reduce(counts, function(m, c) { return m + c; }, 0);
} else if (this.flags['river_view'] && this.flags['social_view']) {
var unread_score = this.get_unread_view_score();

View file

@ -70,7 +70,7 @@ _.extend(NEWSBLUR.ReaderProfileEditor.prototype, {
'Privacy',
(!NEWSBLUR.Globals.is_premium && $.make('div', { className: 'NB-profile-privacy-notpremium' }, [
'You must have a ',
$.make('div', { className: 'NB-splash-link NB-premium' }, 'premium account'),
$.make('div', { className: 'NB-splash-link NB-premium-link' }, 'premium account'),
' to change privacy.'
]))
]),
@ -462,7 +462,7 @@ _.extend(NEWSBLUR.ReaderProfileEditor.prototype, {
e.preventDefault();
self.set_active_color($t);
});
$.targetIs(e, { tagSelector: '.NB-premium' }, function($t, $p) {
$.targetIs(e, { tagSelector: '.NB-premium-link' }, function($t, $p) {
e.preventDefault();
self.close_and_load_feedchooser();
});

View file

@ -64,8 +64,9 @@ NEWSBLUR.Views.SocialPage = Backbone.View.extend({
},
scroll_to_story: function(story_view, run) {
$('body').scrollTo(story_view.$mark, {
offset: -32,
$('html,body').stop().animate({
scrollTop: story_view.$mark.offset().top - 8
}, {
duration: run == 1 ? 1000 : 500,
easing: run == 1 ? 'easeInQuint' : 'easeOutQuint',
queue: false

View file

@ -19,7 +19,8 @@ NEWSBLUR.Views.SocialPageStory = Backbone.View.extend({
initialize: function() {
var story_id = this.$el.data("storyId");
var feed_id = this.$el.data("feedId");
var story_guid = this.$el.data("guid");
// attr because .data munges numeral guids (ex: 002597 vs. a05bd2)
var story_guid = ""+this.$el.attr("data-guid");
var user_comments = this.$el.data("userComments");
var shared = this.$el.hasClass('NB-story-shared');
var $sideoptions = this.$('.NB-feed-story-sideoptions-container');

View file

@ -257,7 +257,7 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
return;
}
if (this.$el.offset().top > $(window).height() - 194) {
if (this.$el.offset().top > $(window).height() - 246) {
this.$el.addClass('NB-hover-inverse');
}
},

View file

@ -166,15 +166,7 @@
<div class="task_button_background"></div>
<div class="NB-task-image"></div>
<span class="NB-task-title">Feed</span>
<div class="NB-task-view-switch-arrow NB-task-view-feed-to-story-arrow"></div>
</div>
</li>
<li class="task_button task_button_view task_view_story">
<div class="NB-task-button-wrapper">
<div class="task_button_background"></div>
<div class="NB-task-image"></div>
<span class="NB-task-title">Story</span>
<div class="NB-task-view-switch-arrow NB-task-view-to-text-arrow"></div>
<div class="NB-task-view-switch-arrow NB-task-view-to-feed-arrow"></div>
</div>
</li>
<li class="task_button task_button_view task_view_text">
@ -182,6 +174,15 @@
<div class="task_button_background"></div>
<div class="NB-task-image"></div>
<span class="NB-task-title">Text</span>
<div class="NB-task-view-switch-arrow NB-task-view-to-text-arrow"></div>
</div>
</li>
<li class="task_button task_button_view task_view_story">
<div class="NB-task-button-wrapper">
<div class="task_button_background"></div>
<div class="NB-task-image"></div>
<span class="NB-task-title">Story</span>
<div class="NB-task-view-switch-arrow NB-task-view-to-story-arrow"></div>
</div>
</li>
</ul>
@ -233,10 +234,10 @@
<div class="NB-feed-story-view-floater"></div>
<ul class="NB-feed-stories"></ul>
</div>
<iframe id="story_iframe" class="NB-story-iframe"></iframe>
<div class="NB-text-view">
<div class="NB-text-view-detail"></div>
</div>
<iframe id="story_iframe" class="NB-story-iframe"></iframe>
</div>
</div>

View file

@ -184,9 +184,9 @@
</script>
<script>
if ($(window).width() < 600) {
$('meta[name=viewport]').attr('content','initial-scale=0.9, maximum-scale=1.5');
}
// if ($(window).width() < 600) {
// $('meta[name=viewport]').attr('content','initial-scale=0.9, maximum-scale=1.5');
// }
</script>
</body>