mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
Backend for marking feeds/folders as read at a specific timestamp.
This commit is contained in:
parent
b250369312
commit
d8ed12f15b
7 changed files with 88 additions and 63 deletions
|
@ -404,31 +404,37 @@ class UserSubscription(models.Model):
|
|||
r.srem(read_stories_key, *stale_story_hashes)
|
||||
r.srem("RS:%s" % self.feed_id, *stale_story_hashes)
|
||||
|
||||
def mark_feed_read(self):
|
||||
def mark_feed_read(self, cutoff_date=None):
|
||||
if (self.unread_count_negative == 0
|
||||
and self.unread_count_neutral == 0
|
||||
and self.unread_count_positive == 0
|
||||
and not self.needs_unread_recalc):
|
||||
return
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
|
||||
recount = True
|
||||
# Use the latest story to get last read time.
|
||||
if cutoff_date:
|
||||
cutoff_date = cutoff_date + datetime.timedelta(seconds=1)
|
||||
else:
|
||||
latest_story = MStory.objects(story_feed_id=self.feed.pk).order_by('-story_date').only('story_date').limit(1)
|
||||
if latest_story and len(latest_story) >= 1:
|
||||
latest_story_date = latest_story[0]['story_date']\
|
||||
+ datetime.timedelta(seconds=1)
|
||||
cutoff_date = (latest_story[0]['story_date']
|
||||
+ datetime.timedelta(seconds=1))
|
||||
else:
|
||||
latest_story_date = now
|
||||
cutoff_date = datetime.datetime.utcnow()
|
||||
recount = False
|
||||
|
||||
self.last_read_date = latest_story_date
|
||||
self.mark_read_date = latest_story_date
|
||||
self.last_read_date = cutoff_date
|
||||
self.mark_read_date = cutoff_date
|
||||
self.oldest_unread_story_date = cutoff_date
|
||||
if not recount:
|
||||
self.unread_count_negative = 0
|
||||
self.unread_count_positive = 0
|
||||
self.unread_count_neutral = 0
|
||||
self.unread_count_updated = now
|
||||
self.oldest_unread_story_date = now
|
||||
self.unread_count_updated = cutoff_date
|
||||
self.needs_unread_recalc = False
|
||||
else:
|
||||
self.needs_unread_recalc = True
|
||||
|
||||
self.save()
|
||||
|
||||
|
|
|
@ -1271,9 +1271,11 @@ def mark_story_as_unread(request):
|
|||
def mark_feed_as_read(request):
|
||||
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
|
||||
feed_ids = request.REQUEST.getlist('feed_id')
|
||||
cutoff_timestamp = int(request.REQUEST.get('cutoff_timestamp', 0))
|
||||
multiple = len(feed_ids) > 1
|
||||
code = 1
|
||||
errors = []
|
||||
cutoff_date = datetime.datetime.fromtimestamp(cutoff_timestamp) if cutoff_timestamp else None
|
||||
|
||||
for feed_id in feed_ids:
|
||||
if 'social:' in feed_id:
|
||||
|
@ -1300,7 +1302,7 @@ def mark_feed_as_read(request):
|
|||
continue
|
||||
|
||||
try:
|
||||
marked_read = sub.mark_feed_read()
|
||||
marked_read = sub.mark_feed_read(cutoff_date=cutoff_date)
|
||||
if marked_read:
|
||||
r.publish(request.user.username, 'feed:%s' % feed_id)
|
||||
except IntegrityError, e:
|
||||
|
|
|
@ -245,18 +245,21 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
|||
}, callback);
|
||||
},
|
||||
|
||||
mark_feed_as_read: function(feed_id, callback) {
|
||||
mark_feed_as_read: function(feed_id, cutoff_timestamp, mark_active, callback) {
|
||||
var self = this;
|
||||
var feed_ids = _.isArray(feed_id)
|
||||
? _.select(feed_id, function(f) { return f; })
|
||||
: [feed_id];
|
||||
|
||||
this.make_request('/reader/mark_feed_as_read', {
|
||||
feed_id: feed_ids
|
||||
feed_id: feed_ids,
|
||||
cutoff_timestamp: cutoff_timestamp
|
||||
}, callback);
|
||||
|
||||
if (feed_id == NEWSBLUR.reader.active_feed) {
|
||||
if (mark_active) {
|
||||
this.stories.each(function(story) {
|
||||
if (cutoff_timestamp &&
|
||||
parseInt(story.get('story_timestamp'), 10) > cutoff_timestamp) return;
|
||||
story.set('read_status', true);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1922,44 +1922,33 @@
|
|||
}
|
||||
},
|
||||
|
||||
mark_feed_as_read: function(feed_id) {
|
||||
mark_feed_as_read: function(feed_id, days_back) {
|
||||
feed_id = feed_id || this.active_feed;
|
||||
|
||||
this.model.mark_feed_as_read([feed_id]);
|
||||
this.mark_feed_as_read_update_counts(feed_id);
|
||||
|
||||
if (feed_id == this.active_feed) {
|
||||
this.model.stories.each(function(story) {
|
||||
story.set('read_status', true);
|
||||
});
|
||||
var cutoff_timestamp = NEWSBLUR.utils.days_back_to_timestamp(days_back);
|
||||
if (!days_back && this.model.stories.length &&
|
||||
this.model.stories.first().get('story_feed_id') == feed_id &&
|
||||
NEWSBLUR.assets.view_setting(feed_id, 'order') == 'newest') {
|
||||
cutoff_timestamp = this.model.stories.first().get('story_timestamp');
|
||||
}
|
||||
|
||||
this.model.mark_feed_as_read([feed_id], cutoff_timestamp, feed_id == this.active_feed, _.bind(function() {
|
||||
this.feeds_unread_count(feed_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
mark_folder_as_read: function(folder) {
|
||||
mark_folder_as_read: function(folder, days_back) {
|
||||
var folder = folder || this.active_folder;
|
||||
var feeds = folder.feed_ids_in_folder();
|
||||
var cutoff_timestamp = NEWSBLUR.utils.days_back_to_timestamp(days_back);
|
||||
if (!days_back && this.model.stories.length &&
|
||||
_.contains(feeds, this.model.stories.first().get('story_feed_id')) &&
|
||||
NEWSBLUR.assets.view_setting(folder.id, 'order') == 'newest') {
|
||||
cutoff_timestamp = this.model.stories.first().get('story_timestamp');
|
||||
}
|
||||
|
||||
this.model.mark_feed_as_read(feeds);
|
||||
_.each(feeds, _.bind(function(feed_id) {
|
||||
this.mark_feed_as_read_update_counts(feed_id);
|
||||
this.model.mark_feed_as_read(feeds, cutoff_timestamp, folder == this.active_folder, _.bind(function() {
|
||||
this.feeds_unread_count(feeds);
|
||||
}, this));
|
||||
|
||||
if (folder == this.active_folder) {
|
||||
this.model.stories.each(function(story) {
|
||||
story.set('read_status', true);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
mark_feed_as_read_update_counts: function(feed_id) {
|
||||
if (feed_id) {
|
||||
var feed = this.model.get_feed(feed_id);
|
||||
if (!feed) return;
|
||||
|
||||
feed.set('ps', 0);
|
||||
feed.set('nt', 0);
|
||||
feed.set('ng', 0);
|
||||
}
|
||||
},
|
||||
|
||||
open_story_trainer: function(story_id, feed_id, options) {
|
||||
|
@ -4150,6 +4139,12 @@
|
|||
}, this), Math.random() * delay);
|
||||
},
|
||||
|
||||
feeds_unread_count: function(feed_ids, options) {
|
||||
options = options || {};
|
||||
|
||||
this.model.feed_unread_count(feed_ids, options.callback);
|
||||
},
|
||||
|
||||
update_interactions_count: function() {
|
||||
this.model.interactions_count(function(data) {
|
||||
NEWSBLUR.app.sidebar_header.update_interactions_count(data.interactions_count);
|
||||
|
|
|
@ -210,6 +210,13 @@ NEWSBLUR.utils = {
|
|||
}
|
||||
|
||||
return interval;
|
||||
},
|
||||
|
||||
days_back_to_timestamp: function(days_back) {
|
||||
days_back = days_back || 0;
|
||||
var now = Math.round((new Date()).getTime() / 1000);
|
||||
|
||||
return now - (days_back * 60*60*24);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
|
|||
"dblclick .feed_counts" : "mark_feed_as_read",
|
||||
"dblclick" : "open_feed_link",
|
||||
"click .NB-feedbar-mark-feed-read" : "mark_feed_as_read",
|
||||
"click .NB-feedbar-mark-feed-read-time" : "mark_feed_as_read_days",
|
||||
"click .NB-feedbar-mark-feed-read-expand" : "expand_mark_read",
|
||||
"click .NB-feedbar-train-feed" : "open_trainer",
|
||||
"click .NB-feedbar-statistics" : "open_statistics",
|
||||
|
@ -69,10 +70,10 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
|
|||
<% if (type == "story") { %>\
|
||||
<div class="NB-feedbar-mark-feed-read-container">\
|
||||
<div class="NB-feedbar-mark-feed-read"><div class="NB-icon"></div></div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-1d">1d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-3d">3d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-7d">7d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-14d">14d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="1">1d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="3">3d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="7">7d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="14">14d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-expand"></div>\
|
||||
</div>\
|
||||
<div class="NB-story-title-indicator">\
|
||||
|
@ -285,7 +286,7 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
|
|||
return false;
|
||||
},
|
||||
|
||||
mark_feed_as_read: function(e) {
|
||||
mark_feed_as_read: function(e, days) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
@ -294,13 +295,18 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
|
|||
_.delay(_.bind(function() {
|
||||
this.flags.double_click = false;
|
||||
}, this), 500);
|
||||
NEWSBLUR.reader.mark_feed_as_read(this.model.id);
|
||||
NEWSBLUR.reader.mark_feed_as_read(this.model.id, days);
|
||||
this.$('.NB-feedbar-mark-feed-read-container').fadeOut(400);
|
||||
if (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
mark_feed_as_read_days: function(e) {
|
||||
var days = parseInt($(e.target).data('days'), 10);
|
||||
this.mark_feed_as_read(e, days);
|
||||
},
|
||||
|
||||
expand_mark_read: function() {
|
||||
var $container = this.$(".NB-feedbar-mark-feed-read-container");
|
||||
var $markread = this.$(".NB-feedbar-mark-feed-read");
|
||||
|
|
|
@ -17,6 +17,7 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
|
|||
"click .NB-feedlist-collapse-icon" : "collapse_folder",
|
||||
"click .NB-feedbar-mark-feed-read" : "mark_folder_as_read",
|
||||
"click .NB-feedbar-mark-feed-read-expand" : "expand_mark_read",
|
||||
"click .NB-feedbar-mark-feed-read-time" : "mark_folder_as_read_days",
|
||||
"click .NB-feedbar-options" : "open_options_popover",
|
||||
"click .NB-story-title-indicator" : "show_hidden_story_titles",
|
||||
"mouseenter" : "add_hover_inverse",
|
||||
|
@ -106,10 +107,10 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
|
|||
<% if (feedbar) { %>\
|
||||
<div class="NB-feedbar-mark-feed-read-container">\
|
||||
<div class="NB-feedbar-mark-feed-read"><div class="NB-icon"></div></div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-1d">1d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-3d">3d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-7d">7d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time NB-14d">14d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="1">1d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="3">3d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="7">7d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-time" data-days="14">14d</div>\
|
||||
<div class="NB-feedbar-mark-feed-read-expand"></div>\
|
||||
</div>\
|
||||
<div class="NB-story-title-indicator">\
|
||||
|
@ -360,11 +361,16 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
|
|||
}
|
||||
},
|
||||
|
||||
mark_folder_as_read: function() {
|
||||
NEWSBLUR.reader.mark_folder_as_read();
|
||||
mark_folder_as_read: function(days_back) {
|
||||
NEWSBLUR.reader.mark_folder_as_read(this.model, days_back);
|
||||
this.$('.NB-feedbar-mark-feed-read').fadeOut(400);
|
||||
},
|
||||
|
||||
mark_folder_as_read_days: function(e) {
|
||||
var days = parseInt($(e.target).data('days'), 10);
|
||||
this.mark_folder_as_read(days);
|
||||
},
|
||||
|
||||
expand_mark_read: function() {
|
||||
NEWSBLUR.Views.FeedTitleView.prototype.expand_mark_read.call(this);
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue