Merge branch 'saved'

* saved:
  Removed transition.
  Showing saved stories explainer for empty saved stories.
  Removing mark read button in story titles bar when on saved view.
  No feed rss for saved stories by feed.
  Counting saved stories when not count exists.
  Count feed_id starred stories when totals don't match.
  Switching to upserts for saved stories.
  Fixing size on emails.
  Adding renew links to premium grace and expire emails.
  Adding renew links to premium grace and expire emails.
  Better sizing on intelligence slider. Takes all segments into account when resizing.
  Narrow classes should be applied at initial drawing.
  Fixing spacing on intelligence slider.
  Updating story feed starred counts on marking starred and unstarred on both backend and client.
  Fixing numerous bugs around saved story views.
  Showing correct stories when switching intelligence slider.
  Showing starred stories when in starred view mode.
  Showing starred counts on every feed. Just needs reading and bug fixes.
  Adding feed counts for saved stories. Need to show counts next to feeds.
This commit is contained in:
Samuel Clay 2014-06-03 14:24:07 -07:00
commit 5c02fc8296
33 changed files with 365 additions and 182 deletions

View file

@ -733,7 +733,7 @@ def api_save_new_story(request):
}
story = MStarredStory.objects.create(**story_db)
logging.user(request, "~FCStarring by ~SBIFTTT~SN: ~SB%s~SN in ~SB%s" % (story_db['story_title'][:50], original_feed and original_feed))
MStarredStoryCounts.count_tags_for_user(user.pk)
MStarredStoryCounts.count_for_user(user.pk)
except OperationError:
logging.user(request, "~FCAlready starred by ~SBIFTTT~SN: ~SB%s" % (story_db['story_title'][:50]))
pass

View file

@ -620,7 +620,7 @@ NewsBlur""" % {'user': self.user.username, 'feeds': subs.count()}
email_type='premium_expire_grace')
day_ago = datetime.datetime.now() - datetime.timedelta(days=360)
for email in emails_sent:
if email.date_sent > day_ago:
if email.date_sent > day_ago and not force:
logging.user(self.user, "~SN~FMNot sending premium expire grace email, already sent before.")
return
@ -652,7 +652,7 @@ NewsBlur""" % {'user': self.user.username, 'feeds': subs.count()}
email_type='premium_expire')
day_ago = datetime.datetime.now() - datetime.timedelta(days=360)
for email in emails_sent:
if email.date_sent > day_ago:
if email.date_sent > day_ago and not force:
logging.user(self.user, "~FM~SBNot sending premium expire email, already sent before.")
return

View file

@ -3,6 +3,7 @@ import time
import boto
import redis
import requests
import random
import zlib
from django.shortcuts import get_object_or_404
from django.shortcuts import render
@ -538,6 +539,12 @@ def load_single_feed(request, feed_id):
else:
stories = []
message = "You must be a premium subscriber to search."
elif read_filter == 'starred':
mstories = MStarredStory.objects(
user_id=user.pk,
story_feed_id=feed_id
).order_by('%sstarred_date' % ('-' if order == 'newest' else ''))[offset:offset+limit]
stories = Feed.format_stories(mstories)
elif usersub and (read_filter == 'unread' or order == 'oldest'):
stories = usersub.get_stories(order=order, read_filter=read_filter, offset=offset, limit=limit,
default_cutoff_date=user.profile.unread_cutoff)
@ -919,7 +926,7 @@ def load_river_stories__redis(request):
code = 1
user_search = None
offset = (page-1) * limit
limit = page * limit - 1
limit = page * limit
story_date_order = "%sstory_date" % ('' if order == 'oldest' else '-')
if story_hashes:
@ -944,6 +951,12 @@ def load_river_stories__redis(request):
stories = []
mstories = []
message = "You must be a premium subscriber to search."
elif read_filter == 'starred':
mstories = MStarredStory.objects(
user_id=user.pk,
story_feed_id__in=feed_ids
).order_by('%sstarred_date' % ('-' if order == 'newest' else ''))[offset:offset+limit]
stories = Feed.format_stories(mstories)
else:
usersubs = UserSubscription.subs_for_feeds(user.pk, feed_ids=feed_ids,
read_filter=read_filter)
@ -981,10 +994,13 @@ def load_river_stories__redis(request):
# Find starred stories
if found_feed_ids:
starred_stories = MStarredStory.objects(
user_id=user.pk,
story_feed_id__in=found_feed_ids
).only('story_hash', 'starred_date')
if read_filter == 'starred':
starred_stories = mstories
else:
starred_stories = MStarredStory.objects(
user_id=user.pk,
story_feed_id__in=found_feed_ids
).only('story_hash', 'starred_date')
starred_stories = dict([(story.story_hash, dict(starred_date=story.starred_date,
user_tags=story.user_tags))
for story in starred_stories])
@ -1012,11 +1028,13 @@ def load_river_stories__redis(request):
classifier_titles=classifier_titles,
classifier_tags=classifier_tags)
# Just need to format stories
nowtz = localtime_for_timezone(now, user.profile.timezone)
for story in stories:
story['read_status'] = 0
if read_filter == 'starred':
story['read_status'] = 1
else:
story['read_status'] = 0
if read_filter == 'all' or query:
if (unread_feed_story_hashes is not None and
story['story_hash'] not in unread_feed_story_hashes):
@ -1795,6 +1813,7 @@ def _mark_story_as_starred(request):
message = ""
if story_hash:
story, _ = MStory.find_story(story_hash=story_hash)
feed_id = story and story.story_feed_id
else:
story, _ = MStory.find_story(story_feed_id=feed_id, story_id=story_id)
@ -1822,6 +1841,7 @@ def _mark_story_as_starred(request):
story_feed_id=feed_id,
story_id=starred_story.story_guid)
new_user_tags = user_tags
MStarredStoryCounts.adjust_count(request.user.pk, feed_id=feed_id, amount=1)
else:
starred_story = starred_story[0]
new_user_tags = list(set(user_tags) - set(starred_story.user_tags or []))
@ -1830,29 +1850,13 @@ def _mark_story_as_starred(request):
starred_story.save()
for tag in new_user_tags:
try:
story_count = MStarredStoryCounts.objects.get(user_id=request.user.pk,
tag=tag)
except MStarredStoryCounts.DoesNotExist:
story_count = MStarredStoryCounts.objects.create(user_id=request.user.pk,
tag=tag)
if not story_count.count:
story_count.count = 0
story_count.count += 1
story_count.save()
MStarredStoryCounts.adjust_count(request.user.pk, tag=tag, amount=1)
for tag in removed_user_tags:
try:
story_count = MStarredStoryCounts.objects.get(user_id=request.user.pk,
tag=tag)
story_count.count -= 1
story_count.save()
if story_count.count <= 0:
story_count.delete()
except MStarredStoryCounts.DoesNotExist:
pass
MStarredStoryCounts.schedule_count_tags_for_user(request.user.pk)
MStarredStoryCounts.count_tags_for_user(request.user.pk, total_only=True)
MStarredStoryCounts.adjust_count(request.user.pk, tag=tag, amount=-1)
if random.random() < 0.01:
MStarredStoryCounts.schedule_count_tags_for_user(request.user.pk)
MStarredStoryCounts.count_for_user(request.user.pk, total_only=True)
starred_counts = MStarredStoryCounts.user_counts(request.user.pk)
if created:
@ -1889,6 +1893,7 @@ def _mark_story_as_unstarred(request):
starred_story = starred_story[0]
logging.user(request, "~FCUnstarring: ~SB%s" % (starred_story.story_title[:50]))
user_tags = starred_story.user_tags
feed_id = starred_story.story_feed_id
MActivity.remove_starred_story(user_id=request.user.pk,
story_feed_id=starred_story.story_feed_id,
story_id=starred_story.story_guid)
@ -1897,18 +1902,16 @@ def _mark_story_as_unstarred(request):
starred_story.save()
except NotUniqueError:
starred_story.delete()
MStarredStoryCounts.adjust_count(request.user.pk, feed_id=feed_id, amount=-1)
for tag in user_tags:
try:
story_count = MStarredStoryCounts.objects.get(user_id=request.user.pk,
tag=tag)
story_count.count -= 1
story_count.save()
if story_count.count <= 0:
story_count.delete()
MStarredStoryCounts.adjust_count(request.user.pk, tag=tag, amount=-1)
except MStarredStoryCounts.DoesNotExist:
pass
# MStarredStoryCounts.schedule_count_tags_for_user(request.user.pk)
MStarredStoryCounts.count_tags_for_user(request.user.pk, total_only=True)
MStarredStoryCounts.count_for_user(request.user.pk, total_only=True)
starred_counts = MStarredStoryCounts.user_counts(request.user.pk)
else:
code = -1

View file

@ -2190,8 +2190,9 @@ class MStarredStory(mongo.Document):
class MStarredStoryCounts(mongo.Document):
user_id = mongo.IntField()
tag = mongo.StringField(max_length=128)
feed_id = mongo.IntField()
slug = mongo.StringField(max_length=128)
count = mongo.IntField()
count = mongo.IntField(default=0)
meta = {
'collection': 'starred_stories_counts',
@ -2202,59 +2203,117 @@ class MStarredStoryCounts(mongo.Document):
@property
def rss_url(self, secret_token=None):
if self.feed_id:
return
if not secret_token:
user = User.objects.select_related('profile').get(pk=self.user_id)
secret_token = user.profile.secret_token
slug = self.slug if self.slug else ""
return "%s/reader/starred_rss/%s/%s/%s" % (settings.NEWSBLUR_URL, self.user_id,
secret_token, self.slug)
secret_token, slug)
@classmethod
def user_counts(cls, user_id, include_total=False, try_counting=True):
counts = cls.objects.filter(user_id=user_id)
counts = sorted([{'tag': c.tag,
'count': c.count,
'feed_address': c.rss_url}
'feed_address': c.rss_url,
'feed_id': c.feed_id}
for c in counts],
key=lambda x: (x.get('tag', '') or '').lower())
if counts == [] and try_counting:
cls.count_tags_for_user(user_id)
total = 0
feed_total = 0
for c in counts:
if not c['tag'] and not c['feed_id']:
total = c['count']
if c['feed_id']:
feed_total += c['count']
if try_counting and (total != feed_total or not len(counts)):
user = User.objects.get(pk=user_id)
logging.user(user, "~FC~SBCounting~SN saved stories (%s total vs. %s counted)..." %
(total, feed_total))
cls.count_for_user(user_id)
return cls.user_counts(user_id, include_total=include_total,
try_counting=False)
if include_total:
for c in counts:
if c['tag'] == "":
return counts, c['count']
return counts, 0
return counts, total
return counts
@classmethod
def schedule_count_tags_for_user(cls, user_id):
ScheduleCountTagsForUser.apply_async(kwargs=dict(user_id=user_id))
@classmethod
def count_tags_for_user(cls, user_id, total_only=False):
user_tags = []
if not total_only:
all_tags = MStarredStory.objects(user_id=user_id,
user_tags__exists=True).item_frequencies('user_tags')
user_tags = sorted([(k, v) for k, v in all_tags.items() if int(v) > 0 and k],
key=lambda x: x[0].lower(),
reverse=True)
cls.objects(user_id=user_id).delete()
for tag, count in dict(user_tags).items():
cls.objects.create(user_id=user_id, tag=tag, slug=slugify(tag), count=count)
total_stories_count = MStarredStory.objects(user_id=user_id).count()
cls.objects.filter(user_id=user_id, tag="").update_one(set__count=total_stories_count,
upsert=True)
return dict(total=total_stories_count, tags=user_tags)
@classmethod
def count_for_user(cls, user_id, total_only=False):
user_tags = []
user_feeds = []
if not total_only:
cls.objects(user_id=user_id).delete()
user_tags = cls.count_tags_for_user(user_id)
user_feeds = cls.count_feeds_for_user(user_id)
total_stories_count = MStarredStory.objects(user_id=user_id).count()
cls.objects(user_id=user_id, tag=None, feed_id=None).update_one(set__count=total_stories_count,
upsert=True)
return dict(total=total_stories_count, tags=user_tags, feeds=user_feeds)
@classmethod
def count_tags_for_user(cls, user_id):
all_tags = MStarredStory.objects(user_id=user_id,
user_tags__exists=True).item_frequencies('user_tags')
user_tags = sorted([(k, v) for k, v in all_tags.items() if int(v) > 0 and k],
key=lambda x: x[0].lower(),
reverse=True)
for tag, count in dict(user_tags).items():
cls.objects(user_id=user_id, tag=tag, slug=slugify(tag)).update_one(set__count=count,
upsert=True)
return user_tags
@classmethod
def count_feeds_for_user(cls, user_id):
all_feeds = MStarredStory.objects(user_id=user_id).item_frequencies('story_feed_id')
user_feeds = dict([(k, v) for k, v in all_feeds.items() if v])
# Clean up None'd and 0'd feed_ids, so they can be counted against the total
if user_feeds.get(None, False):
user_feeds[0] = user_feeds.get(0, 0)
user_feeds[0] += user_feeds.get(None)
del user_feeds[None]
if user_feeds.get(0, False):
user_feeds[-1] = user_feeds.get(0, 0)
del user_feeds[0]
for feed_id, count in user_feeds.items():
cls.objects(user_id=user_id,
feed_id=feed_id,
slug="feed:%s" % feed_id).update_one(set__count=count,
upsert=True)
return user_feeds
@classmethod
def adjust_count(cls, user_id, feed_id=None, tag=None, amount=0):
params = dict(user_id=user_id)
if feed_id:
params['feed_id'] = feed_id
if tag:
params['tag'] = tag
cls.objects(**params).update_one(inc__count=amount, upsert=True)
story_count = cls.objects.get(**params)
if story_count.count <= 0:
story_count.delete()
class MFetchHistory(mongo.Document):
feed_id = mongo.IntField(unique=True)
feed_fetch_history = mongo.DynamicField()

View file

@ -222,4 +222,4 @@ class ScheduleCountTagsForUser(Task):
def run(self, user_id):
from apps.rss_feeds.models import MStarredStoryCounts
MStarredStoryCounts.count_tags_for_user(user_id)
MStarredStoryCounts.count_for_user(user_id)

View file

@ -558,7 +558,9 @@ a img {
.NB-feedlist-hide-read-feeds .NB-feedlist .feed.NB-feed-self-blurblog {
display: block;
}
.NB-intelligence-starred .NB-feedlist .feed.NB-feed-self-blurblog {
display: none;
}
.NB-feedlist .feed.NB-feed-unfetched {
}
@ -833,6 +835,9 @@ a img {
.NB-feedlist-hide-read-feeds .NB-feedlist .feed {
display: none;
}
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_starred .unread_starred {
display: block;
}
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_positive .unread_positive {
display: block;
}
@ -889,6 +894,13 @@ a img {
/* border-top: 1px solid rgba(255, 255, 255, .4);*/
border-bottom: 1px solid rgba(0, 0, 0, .1);
}
.unread_count_starred {
background-color: #506B9A;
text-shadow: 0 1px 0 rgba(0, 0, 0, .3);
border-bottom: 1px solid rgba(0, 0, 0, .2);
/* text-shadow: none;*/
}
.unread_count_positive {
background-color: #6EA74A;
text-shadow: 0 1px 0 rgba(0, 0, 0, .3);
@ -907,6 +919,11 @@ a img {
/* text-shadow: 0 1px 0 rgba(0, 0, 0, .3);*/
}
.unread_view_starred .unread_count {
padding-left: 6px;
padding-right: 6px;
}
.unread_view_positive .unread_count {
padding-left: 6px;
padding-right: 6px;
@ -919,6 +936,9 @@ a img {
/* Showing unread counts above threshold */
.unread_view_starred .unread_starred .unread_count_starred {
display: block;
}
.unread_view_positive .unread_positive .unread_count_positive {
display: block;
}
@ -934,6 +954,9 @@ a img {
display: block;
}
.unread_view_starred .unread_starred {
font-weight: bold;
}
.unread_view_positive .unread_positive {
font-weight: bold;
}
@ -962,6 +985,10 @@ a img {
display: block;
}
.NB-starred-folder .unread_starred .unread_count_positive {
display: block;
}
/* ====================== */
/* = Feeds Progress Bar = */
/* ====================== */
@ -1191,6 +1218,9 @@ a img {
font-weight: bold;
float: right;
}
.NB-intelligence-starred .NB-feedbar .NB-feedbar-mark-feed-read-container {
display: none;
}
.NB-feedbar .NB-feedbar-mark-feed-read,
.NB-feedbar .NB-feedbar-mark-feed-read-expand,
.NB-feedbar .NB-feedbar-mark-feed-read-time {
@ -1401,6 +1431,9 @@ a img {
.NB-feedbar .NB-story-title-indicator .NB-story-title-indicator-count {
float: left;
}
.NB-feedbar .NB-story-title-indicator .NB-story-title-indicator-count .unread_count_starred {
display: none;
}
.NB-feedbar .NB-story-title-indicator.unread_threshold_negative {
display: none;
}
@ -1528,6 +1561,10 @@ a img {
background: transparent url('/media/embed/icons/circular/g_icn_hidden.png') no-repeat 13px 6px;
background-size: 8px;
}
#story_titles .NB-story-title.NB-story-starred .NB-storytitles-sentiment {
background: transparent url('/media/embed/icons/circular/g_icn_starred.png') no-repeat 13px 6px;
background-size: 8px;
}
#story_titles .NB-story-title.NB-story-starred .NB-storytitles-star,
#story_titles .NB-story-title.read.NB-story-starred .NB-storytitles-star {
@ -2304,6 +2341,11 @@ body {
/* display: none;*/
}
.NB-feed-story.NB-story-starred .NB-feed-story-sentiment {
background: transparent url('/media/embed/icons/circular/g_icn_starred.png') no-repeat 4px 4px;
background-size: 8px;
}
.NB-feed-story.NB-story-positive .NB-feed-story-sentiment {
background: transparent url('/media/embed/icons/circular/g_icn_focus.png') no-repeat 4px 4px;
background-size: 8px;
@ -3657,6 +3699,10 @@ body {
background: transparent url('/media/embed/icons/circular/g_icn_focus.png') no-repeat 6px 2px;
background-size: 8px;
}
.NB-feeds-header-dashboard .NB-feeds-header-starred {
background: transparent url('/media/embed/icons/circular/g_icn_starred.png') no-repeat 6px 2px;
background-size: 8px;
}
.NB-feeds-header-dashboard .NB-feeds-header-right {
position: relative;
}
@ -3998,6 +4044,13 @@ background: transparent;
background-image: url('/media/embed/icons/circular/exclamation.png');
background-size: 16px;
}
.NB-taskbar .NB-task-story-next-starred .NB-task-image {
background: transparent url('/media/embed/icons/circular/g_icn_starred.png') no-repeat 0 0;
background-size: 8px;
width: 8px;
height: 8px;
margin-top: 5px;
}
.NB-taskbar .NB-task-story-next-positive .NB-task-image {
background: transparent url('/media/embed/icons/circular/g_icn_focus.png') no-repeat 0 0;
background-size: 8px;
@ -4830,6 +4883,12 @@ form.opml_import_form input {
background-size: 8px;
}
.NB-taskbar-intelligence .NB-taskbar-intelligence-starred {
right: -4px;
background: transparent url(/media/embed/icons/circular/g_icn_starred.png) no-repeat 0 0;
background-size: 8px;
}
.NB-intelligence-slider {
display: inline-block;
}
@ -4842,13 +4901,13 @@ form.opml_import_form input {
position: relative;
padding: 5px 8px 4px;
}
.NB-narrow .NB-intelligence-slider .NB-intelligence-slider-blue .NB-intelligence-label {
.NB-narrow-pane-blue .NB-intelligence-slider .NB-intelligence-slider-blue .NB-intelligence-label {
display: none;
}
.NB-narrow .NB-intelligence-slider .NB-intelligence-slider-green .NB-intelligence-label {
.NB-narrow-pane-green .NB-intelligence-slider .NB-intelligence-slider-green .NB-intelligence-label {
display: none;
}
.NB-extra-narrow .NB-intelligence-slider .NB-intelligence-slider-yellow .NB-intelligence-label {
.NB-narrow-pane-yellow .NB-intelligence-slider .NB-intelligence-slider-yellow .NB-intelligence-label {
display: none;
}
.NB-intelligence-slider img {
@ -4863,14 +4922,14 @@ form.opml_import_form input {
height: 12px;
margin: -1px 5px -1px 0px;
}
.NB-narrow .NB-intelligence-slider .NB-intelligence-slider-green img {
margin: 1px 8px 2px;
.NB-narrow-pane-green .NB-intelligence-slider .NB-intelligence-slider-green img {
margin: 1px 6px 2px;
}
.NB-narrow .NB-intelligence-slider .NB-intelligence-slider-blue img {
margin: 1px 8px 2px;
.NB-narrow-pane-blue .NB-intelligence-slider .NB-intelligence-slider-blue img {
margin: -1px 4px 0px;
}
.NB-extra-narrow .NB-intelligence-slider .NB-intelligence-slider-yellow img {
margin: 1px 8px 2px;
.NB-narrow-pane-yellow .NB-intelligence-slider .NB-intelligence-slider-yellow img {
margin: 1px 6px 2px;
}
/* ===================== */

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

View file

@ -234,6 +234,8 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
var pre_callback = function(data) {
if (data.starred_counts) {
self.starred_feeds.reset(data.starred_counts, {parse: true});
var feed = self.get_feed(story.get('story_feed_id'));
if (feed && feed.views) _.invoke(feed.views, 'render');
}
if (selected) {
@ -257,6 +259,8 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
var pre_callback = function(data) {
if (data.starred_counts) {
self.starred_feeds.reset(data.starred_counts, {parse: true, update: true});
var feed = self.get_feed(story.get('story_feed_id'));
if (feed && feed.views) _.invoke(feed.views, 'render');
}
if (selected && self.starred_feeds.get(selected)) {
@ -1101,6 +1105,8 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
},
view_setting: function(feed_id, setting, callback) {
if (NEWSBLUR.reader.flags['feed_list_showing_starred'] &&
setting == 'read_filter') return "starred";
if (feed_id == "river:global" && setting == "order") return "newest";
if (_.isUndefined(setting) || _.isString(setting)) {
setting = setting || 'view';

View file

@ -137,10 +137,13 @@ NEWSBLUR.Models.Feed = Backbone.Model.extend({
},
unread_counts: function() {
var starred_feed = NEWSBLUR.assets.starred_feeds.get_feed(this.id);
return {
ps: this.get('ps') || 0,
nt: this.get('nt') || 0,
ng: this.get('ng') || 0
ng: this.get('ng') || 0,
st: starred_feed && starred_feed.get('count') || 0
};
},
@ -158,6 +161,9 @@ NEWSBLUR.Models.Feed = Backbone.Model.extend({
return !!(this.get('ng') || this.get('nt') || this.get('ps'));
} else if (unread_view == 0) {
return !!(this.get('nt') || this.get('ps'));
} else if (unread_view >= 2) {
var starred_feed = NEWSBLUR.assets.starred_feeds.get_feed(this.id);
return starred_feed && starred_feed.get('count');
} else if (unread_view > 0) {
return !!(this.get('ps'));
}

View file

@ -26,7 +26,7 @@ NEWSBLUR.Models.StarredFeed = Backbone.Model.extend({
},
tag_slug: function() {
return Inflector.sluggify(this.get('tag'));
return Inflector.sluggify(this.get('tag') || '');
}
});
@ -37,15 +37,10 @@ NEWSBLUR.Collections.StarredFeeds = Backbone.Collection.extend({
parse: function(models) {
_.each(models, function(feed) {
feed.id = 'starred:' + feed.tag;
feed.id = 'starred:' + (feed.tag || feed.feed_id);
// feed.selected = false;
feed.ps = feed.count;
});
// Remove below, only used for transition to tag/feed_id.
models = _.filter(models, function(feed) {
return feed['tag'];
});
return models;
},
@ -83,6 +78,12 @@ NEWSBLUR.Collections.StarredFeeds = Backbone.Collection.extend({
all_tags: function() {
return this.pluck('tag');
},
get_feed: function(feed_id) {
return this.detect(function(feed) {
return feed.get('feed_id') == feed_id;
});
}
});

View file

@ -19,7 +19,7 @@ NEWSBLUR.Models.Story = Backbone.Model.extend({
score: function() {
if (NEWSBLUR.reader.flags['starred_view']) {
return 1;
return 2;
} else {
return NEWSBLUR.utils.compute_story_score(this);
}
@ -349,6 +349,7 @@ NEWSBLUR.Collections.Stories = Backbone.Collection.extend({
clear_previous_stories_stack: function() {
this.previous_stories_stack = [];
this.active_story = null;
},
select_previous_story: function() {

View file

@ -236,6 +236,12 @@
$windows.removeClass('NB-narrow');
}
var pane = this.layout.outerLayout.panes.west;
var width = this.layout.outerLayout.state.west.size;
pane.toggleClass("NB-narrow-pane-blue", width < 290);
pane.toggleClass("NB-narrow-pane-green", width < 254);
pane.toggleClass("NB-narrow-pane-yellow", width < 236);
this.apply_tipsy_titles();
},
@ -400,6 +406,8 @@
this.$s.$story_titles.append(story_titles_bin.children());
this.resize_window();
}
this.adjust_for_narrow_window();
},
apply_tipsy_titles: function() {
@ -437,8 +445,7 @@
var feed_pane_size = state.size;
$('#NB-splash').css('left', feed_pane_size);
$pane.toggleClass("NB-narrow", this.layout.outerLayout.state.west.size < 240);
$pane.toggleClass("NB-extra-narrow", this.layout.outerLayout.state.west.size < 218);
this.adjust_for_narrow_window();
this.flags.set_feed_pane_size = this.flags.set_feed_pane_size || _.debounce( _.bind(function() {
var feed_pane_size = this.layout.outerLayout.state.west.size;
this.model.preference('feed_pane_size', feed_pane_size);
@ -603,8 +610,12 @@
show_next_unread_story: function() {
var unread_count = this.get_total_unread_count();
if (unread_count) {
if (this.flags['feed_list_showing_starred']) {
this.slide_intelligence_slider(0);
this.flags['feed_list_showing_starred'] = false;
this.open_next_unread_story_across_feeds();
} else if (unread_count) {
var next_story = NEWSBLUR.assets.stories.get_next_unread_story();
if (next_story) {
this.counts['find_next_unread_on_page_of_feed_stories_load'] = 0;
@ -624,8 +635,8 @@
open_next_unread_story_across_feeds: function(force_next_feed) {
var unread_count = !force_next_feed && this.active_feed && this.get_total_unread_count();
if (!unread_count) {
if (!unread_count && !this.flags['feed_list_showing_starred']) {
if (this.flags.river_view && !this.flags.social_view) {
var $next_folder = this.get_next_unread_folder(1);
var folder = NEWSBLUR.assets.folders.get_view($next_folder);
@ -1252,7 +1263,7 @@
this.active_folder.folder_view.$el,
this.active_folder,
options);
} else {
} else if (this.active_feed) {
this.open_feed(this.active_feed, options);
}
@ -1308,7 +1319,6 @@
NEWSBLUR.app.story_titles.show_loading(options);
}
NEWSBLUR.app.taskbar_info.hide_stories_error();
// this.show_stories_progress_bar();
this.iframe_scroll = null;
this.set_correct_story_view_for_feed(feed.id);
this.make_feed_title_in_stories();
@ -1613,18 +1623,19 @@
},
post_open_starred_stories: function(data, first_load) {
if (this.flags['starred_view']) {
// NEWSBLUR.log(['post_open_starred_stories', data.stories.length, first_load]);
this.flags['opening_feed'] = false;
if (this.counts['select_story_in_feed'] || this.flags['select_story_in_feed']) {
this.select_story_in_feed();
}
if (first_load) {
this.find_story_with_action_preference_on_open_feed();
}
// this.show_story_titles_above_intelligence_level({'animate': false});
this.flags['story_titles_loaded'] = true;
if (!this.flags['starred_view']) return;
// NEWSBLUR.log(['post_open_starred_stories', data.stories.length, first_load]);
this.flags['opening_feed'] = false;
if (this.counts['select_story_in_feed'] || this.flags['select_story_in_feed']) {
this.select_story_in_feed();
}
if (first_load) {
this.find_story_with_action_preference_on_open_feed();
}
this.make_story_titles_pane_counter();
// this.show_story_titles_above_intelligence_level({'animate': false});
this.flags['story_titles_loaded'] = true;
},
// =================
@ -1680,6 +1691,7 @@
var visible_only = this.model.view_setting(this.active_feed, 'read_filter') == 'unread';
if (NEWSBLUR.reader.flags.search) visible_only = false;
if (NEWSBLUR.reader.flags.feed_list_showing_starred) visible_only = false;
var feeds;
if (visible_only) {
feeds = _.pluck(this.active_folder.feeds_with_unreads(), 'id');
@ -2298,6 +2310,11 @@
// =====================
make_story_titles_pane_counter: function(options) {
if (NEWSBLUR.app.story_unread_counter) {
NEWSBLUR.app.story_unread_counter.remove();
NEWSBLUR.app.story_unread_counter.destroy();
}
options = options || {
'fade': true
};
@ -2312,14 +2329,7 @@
if (!feed && !folder) return;
if (this.active_feed == 'river:global') return;
if (NEWSBLUR.app.story_unread_counter) {
NEWSBLUR.app.story_unread_counter.remove();
}
if (feed) {
if (NEWSBLUR.app.story_unread_counter) {
NEWSBLUR.app.story_unread_counter.destroy();
}
NEWSBLUR.app.story_unread_counter = new NEWSBLUR.Views.UnreadCount({
model: feed
}).render();
@ -2331,15 +2341,12 @@
} else {
collection = folder.folder_view.collection;
}
if (NEWSBLUR.app.story_unread_counter) {
NEWSBLUR.app.story_unread_counter.destroy();
}
NEWSBLUR.app.story_unread_counter = new NEWSBLUR.Views.UnreadCount({
collection: collection
}).render();
}
if (options.fade) {
if (options.fade && NEWSBLUR.app.story_unread_counter) {
NEWSBLUR.app.story_unread_counter.$el.css({'opacity': 0});
this.$s.$story_taskbar.append(NEWSBLUR.app.story_unread_counter.$el);
_.delay(function() {
@ -2348,14 +2355,13 @@
'opacity': .2
}, {'duration': 600, 'queue': false});
}, 200);
} else {
} else if (NEWSBLUR.app.story_unread_counter) {
this.$s.$story_taskbar.append(NEWSBLUR.app.story_unread_counter.$el);
_.delay(function() {
NEWSBLUR.app.story_unread_counter.center();
NEWSBLUR.app.story_unread_counter.$el.css({'opacity': .2});
}, 200);
}
},
// ===========
@ -3860,12 +3866,17 @@
var $slider = this.$s.$intelligence_slider;
var $focus = $(".NB-intelligence-slider-green", $slider);
var $unread = $(".NB-intelligence-slider-yellow", $slider);
var unread_view = this.get_unread_view_score();
var unread_view = this.get_unread_view_name();
var all_mode = !NEWSBLUR.assets.preference('hide_read_feeds');
var starred_mode = this.flags['feed_list_showing_starred'];
if (!NEWSBLUR.assets.feeds.size()) return;
var view_not_empty;
if (unread_view >= 1) {
if (unread_view == 'starred') {
view_not_empty = NEWSBLUR.assets.starred_feeds.any(function(feed) {
return feed.get('count');
});
} else if (unread_view == 'positive') {
view_not_empty = NEWSBLUR.assets.feeds.any(function(feed) {
return feed.get('ps');
}) || NEWSBLUR.assets.social_feeds.any(function(feed) {
@ -3879,13 +3890,22 @@
});
}
$(".NB-feeds-list-empty").remove();
if (!view_not_empty && !all_mode) {
console.log(["toggle_focus_in_slider", unread_view, view_not_empty, starred_mode]);
if (!view_not_empty && !all_mode && !starred_mode) {
var $empty = $.make("div", { className: "NB-feeds-list-empty" }, [
'You have no unread stories',
unread_view >= 1 ? " in Focus mode." : ".",
unread_view == 'positive' ? " in Focus mode." : ".",
$.make('br'),
$.make('br'),
unread_view >= 1 ? 'Switch to All or Unread.' : ""
unread_view == 'positive' ? 'Switch to All or Unread.' : ""
]);
this.$s.$feed_list.after($empty);
} else if (!view_not_empty && starred_mode) {
var $empty = $.make("div", { className: "NB-feeds-list-empty" }, [
'You have no saved stories.',
$.make('br'),
$.make('br'),
'Switch to All or Unread.'
]);
this.$s.$feed_list.after($empty);
}
@ -3905,7 +3925,10 @@
var $slider = this.$s.$intelligence_slider;
var real_value = value;
if (value < 0) {
var showing_starred = this.flags['feed_list_showing_starred'];
this.flags['feed_list_showing_starred'] = value == 2;
if (value <= -1) {
value = 0;
if (!initial_load) {
NEWSBLUR.assets.preference('hide_read_feeds', 0);
@ -3916,6 +3939,11 @@
NEWSBLUR.assets.preference('hide_read_feeds', 1);
}
NEWSBLUR.assets.preference('unread_view', 0);
} else if (value >= 2) {
if (!initial_load) {
NEWSBLUR.assets.preference('hide_read_feeds', 1);
}
NEWSBLUR.assets.preference('unread_view', 2);
} else if (value > 0) {
if (!initial_load) {
NEWSBLUR.assets.preference('hide_read_feeds', 1);
@ -3929,13 +3957,18 @@
}
this.show_story_titles_above_intelligence_level({'animate': true, 'follow': true});
this.toggle_focus_in_slider();
if (!initial_load && this.flags['feed_list_showing_starred'] != showing_starred) {
this.reload_feed();
}
NEWSBLUR.app.sidebar_header.toggle_hide_read_preference();
NEWSBLUR.app.sidebar_header.count();
NEWSBLUR.assets.folders.update_all_folder_visibility();
NEWSBLUR.app.feed_list.scroll_to_selected();
$('.NB-active', $slider).removeClass('NB-active');
if (real_value < 0) {
if (this.flags['feed_list_showing_starred']) {
$('.NB-intelligence-slider-blue', $slider).addClass('NB-active');
} else if (real_value < 0) {
$('.NB-intelligence-slider-red', $slider).addClass('NB-active');
} else if (real_value > 0) {
$('.NB-intelligence-slider-green', $slider).addClass('NB-active');
@ -3945,7 +3978,9 @@
},
move_intelligence_slider: function(direction) {
var value = this.model.preference('unread_view') + direction;
var unread_view = this.model.preference('unread_view');
if (!this.model.preference('hide_read_feeds')) unread_view = -1;
var value = unread_view + direction;
this.slide_intelligence_slider(value);
},
@ -3959,21 +3994,25 @@
this.$s.$body.removeClass('NB-intelligence-positive')
.removeClass('NB-intelligence-neutral')
.removeClass('NB-intelligence-negative')
.removeClass('NB-intelligence-starred')
.addClass('NB-intelligence-'+unread_view_name);
$sidebar.removeClass('unread_view_positive')
.removeClass('unread_view_neutral')
.removeClass('unread_view_negative')
.removeClass('unread_view_starred')
.addClass('unread_view_'+unread_view_name);
$next_story_button.removeClass('NB-task-story-next-positive')
.removeClass('NB-task-story-next-neutral')
.removeClass('NB-task-story-next-negative')
.removeClass('NB-task-story-next-starred')
.addClass('NB-task-story-next-'+unread_view_name);
$story_title_indicator.removeClass('unread_threshold_positive')
.removeClass('unread_threshold_neutral')
.removeClass('unread_threshold_negative')
.removeClass('unread_threshold_starred')
.addClass('unread_threshold_'+unread_view_name);
NEWSBLUR.assets.stories.each(function(story){
@ -3982,6 +4021,7 @@
},
get_unread_view_score: function() {
if (this.flags['feed_list_showing_starred']) return -1;
if (this.flags['unread_threshold_temporarily']) {
var score_name = this.flags['unread_threshold_temporarily'];
if (score_name == 'neutral') {
@ -4002,7 +4042,9 @@
if (typeof unread_view == 'undefined') {
unread_view = this.get_unread_view_score();
}
if (this.flags['feed_list_showing_starred']) return 'starred';
return (unread_view > 0
? 'positive'
: unread_view < 0
@ -4045,6 +4087,8 @@
return counts['ps'] + counts['nt'];
} else if (unread_view_name == 'negative') {
return counts['ps'] + counts['nt'] + counts['ng'];
} else if (unread_view_name == 'starred') {
return counts['st'];
}
},
@ -5482,6 +5526,8 @@
unread_value = 0;
} else if ($t.hasClass('NB-intelligence-slider-green')) {
unread_value = 1;
} else if ($t.hasClass('NB-intelligence-slider-blue')) {
unread_value = 2;
}
self.slide_intelligence_slider(unread_value);

View file

@ -14,7 +14,7 @@ NEWSBLUR.Views.ReaderTaskbarInfo = Backbone.View.extend({
center: function(force) {
var count_width = this.$el.width();
var left_buttons_offset = $('.NB-taskbar-view').outerWidth(true);
var right_buttons_offset = $(".NB-taskbar-layout").position().left;
var right_buttons_offset = $(".NB-taskbar-options-container").position().left;
var usable_space = right_buttons_offset - left_buttons_offset;
var left = (usable_space / 2) - (count_width / 2) + left_buttons_offset;
// console.log(["Taskbar info center", count_width, left, left_buttons_offset, right_buttons_offset, usable_space]);

View file

@ -167,7 +167,7 @@ NEWSBLUR.Views.FeedList = Backbone.View.extend({
options = options || {};
var $starred_feeds = $('.NB-starred-feeds', this.$s.$starred_feeds);
var $feeds = _.compact(NEWSBLUR.assets.starred_feeds.map(function(feed) {
if (feed.get('tag') == "") return;
if (feed.get('tag') == "" || !feed.get('tag')) return;
var feed_view = new NEWSBLUR.Views.FeedTitleView({
model: feed,
type: 'feed',

View file

@ -148,6 +148,7 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
extra_classes: function() {
var feed = this.model;
var extra_classes = '';
var starred_feed = NEWSBLUR.assets.starred_feeds.get_feed(feed.id);
if (feed.get('ps')) {
extra_classes += ' unread_positive';
@ -158,6 +159,9 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
if (feed.get('ng')) {
extra_classes += ' unread_negative';
}
if ((starred_feed && starred_feed.get('count')) || feed.is_starred()) {
extra_classes += ' unread_starred';
}
if (feed.is_feed()) {
if (feed.get('has_exception') && feed.get('exception_type') == 'feed') {
@ -188,7 +192,10 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
if (this.counts_view) {
this.counts_view.destroy();
}
this.counts_view = new NEWSBLUR.Views.UnreadCount({model: this.model}).render();
this.counts_view = new NEWSBLUR.Views.UnreadCount({
model: this.model,
include_starred: true
}).render();
this.$('.feed_counts').html(this.counts_view.el);
if (this.options.type == 'story') {
this.$('.NB-story-title-indicator-count').html(this.counts_view.$el.clone());
@ -248,7 +255,7 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
add_extra_classes: function() {
var extra_classes = this.extra_classes();
$(this.el).removeClass("unread_positive unread_neutral unread_negative");
$(this.el).removeClass("unread_positive unread_neutral unread_negative unread_starred");
$(this.el).addClass(extra_classes);
},

View file

@ -60,6 +60,7 @@ NEWSBLUR.Views.SidebarHeader = Backbone.View.extend({
toggle_hide_read_preference: function() {
var hide_read_feeds = NEWSBLUR.assets.preference('hide_read_feeds');
if (NEWSBLUR.reader.flags['feed_list_showing_starred']) hide_read_feeds = true;
this.$('.NB-feeds-header-sites').toggleClass('NB-feedlist-hide-read-feeds', !!hide_read_feeds);
$("body").toggleClass("NB-feedlist-hide-read-feeds", !!hide_read_feeds);
},

View file

@ -134,6 +134,7 @@ NEWSBLUR.Views.StoryTitlesHeader = Backbone.View.extend({
if (!is_feed_load) return;
if (!NEWSBLUR.reader.active_feed) return;
if (NEWSBLUR.reader.flags.search) return;
if (NEWSBLUR.reader.flags['feed_list_showing_starred']) return;
NEWSBLUR.reader.flags['unread_threshold_temporarily'] = null;
var unread_view_name = NEWSBLUR.reader.get_unread_view_name();

View file

@ -6,6 +6,10 @@ NEWSBLUR.Views.UnreadCount = Backbone.View.extend({
_.bindAll(this, 'render');
if (!this.options.stale) {
if (this.model) {
var starred_feed = NEWSBLUR.assets.starred_feeds.get_feed(this.model.id);
if (starred_feed) {
starred_feed.bind('change:count', this.render, this);
}
this.model.bind('change:ps', this.render, this);
this.model.bind('change:nt', this.render, this);
this.model.bind('change:ng', this.render, this);
@ -37,11 +41,15 @@ NEWSBLUR.Views.UnreadCount = Backbone.View.extend({
if (counts['ng']) {
unread_class += ' unread_negative';
}
if ((counts['st'] && this.options.include_starred) || (this.model && this.model.is_starred())) {
unread_class += ' unread_starred';
}
this.$el.html(this.template({
ps : counts['ps'],
nt : counts['nt'],
ng : counts['ng'],
st : this.options.include_starred && counts['st'],
unread_class : unread_class
}));
@ -68,6 +76,11 @@ NEWSBLUR.Views.UnreadCount = Backbone.View.extend({
<span class="unread_count unread_count_negative <% if (ng) { %>unread_count_full<% } else { %>unread_count_empty<% } %>">\
<%= ng %>\
</span>\
<% if (st) { %>\
<span class="unread_count unread_count_starred <% if (st) { %>unread_count_full<% } else { %>unread_count_empty<% } %>">\
<%= st %>\
</span>\
<% } %>\
</div>\
'),
@ -78,7 +91,7 @@ NEWSBLUR.Views.UnreadCount = Backbone.View.extend({
center: function() {
var count_width = this.$el.width();
var left_buttons_offset = $('.NB-taskbar-view').outerWidth(true);
var right_buttons_offset = $(".NB-taskbar-layout").position().left;
var right_buttons_offset = $(".NB-taskbar-options-container").position().left;
var usable_space = right_buttons_offset - left_buttons_offset;
var left = (usable_space / 2) - (count_width / 2) + left_buttons_offset;

View file

@ -34,7 +34,7 @@
NEWSBLUR.Preferences = {
'unread_view' : 0,
'lock_mouse_indicator' : 100,
'feed_pane_size' : {% firstof user_profile.feed_pane_size 242 %},
'feed_pane_size' : {% firstof user_profile.feed_pane_size 258 %},
'hide_getting_started' : {{ user_profile.hide_getting_started|yesno:"true,false" }},
'has_setup_feeds' : {{ user_profile.has_setup_feeds|yesno:"true,false" }},
'has_found_friends' : {{ user_profile.has_found_friends|yesno:"true,false" }},

View file

@ -1,7 +1,7 @@
{% extends "mail/email_base.xhtml" %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Your shared story is now on your Blurblog</p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Your shared story is now on your Blurblog</p>
<p style="line-height: 20px;">You can view your Blurblog here: {{ blurblog_url }}</p>
<p style="line-height: 20px;">Your Blurblog also has an RSS feed: {{ blurblog_rss }}</p>
<p style="line-height: 20px;">{% if shared_stories > 1 %}You've already shared {{ shared_stories }} stories, but you may not have known that your shared stories are on your Blurblog.{% else %}You just shared your first story on NewsBlur. All of your shared stories are available on your Blurblog.{% endif %}</p>

View file

@ -2,7 +2,7 @@
{% load utils_tags %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">
You have a follow request:
</p>
<div style="margin: 24px 0;font-size: 24px;text-align: center;">

View file

@ -3,7 +3,7 @@
{% load utils_tags %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Forgot your password? No problem.</p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Forgot your password? No problem.</p>
<p style="line-height: 20px;">You can change your password by visiting this link:</p>
<p style="line-height: 20px;"><a href="http://{% current_domain %}{{ user.profile.autologin_url }}?next=/profile/forgot_password_return">http://{% current_domain %}{{ user.profile.autologin_url }}?next=/profile/forgot_password_return</a></p>
<p style="line-height: 20px;">You will be auto-logged into your account and presented with a form to change your password.</p>

View file

@ -3,7 +3,7 @@
{% load utils_tags %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Hey {{ user.username }}, we're launching a new NewsBlur...</p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Hey {{ user.username }}, we're launching a new NewsBlur...</p>
<p style="line-height: 20px;">{% if months_ago >= 1 %}It's been {{ months_ago }} month{{ months_ago|pluralize }} since you last saw NewsBlur. A lot has changed since then.{% else %}You've recently been on NewsBlur, but a lot has changed since even then.{% endif %} NewsBlur is now a social news reader. We just launched shared stories and if you miss the old Google Reader features, you'll love the new NewsBlur.</p>
<p style="line-height: 20px;">We've worked hard to make a great app, so congratulations on discovering a handcrafted experience.</p>
<p style="line-height: 20px;">Here are some easy ways to have a great time on NewsBlur:</p>

View file

@ -3,7 +3,7 @@
{% load utils_tags %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Welcome to NewsBlur, {{ user.username }}.</p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Welcome to NewsBlur, {{ user.username }}.</p>
<p style="line-height: 20px;">Thanks for trying out NewsBlur! I hope NewsBlur can make your daily reading more personal, sociable, and pleasurable.</p>
<p style="line-height: 20px;">Here are some ways to make NewsBlur work for you:</p>
<p style="line-height: 20px;">

View file

@ -1,7 +1,7 @@
{% extends "mail/email_base.xhtml" %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">
Say hello to your newest follower:
</p>
<div style="margin: 24px 0;font-size: 24px;text-align: center;">

View file

@ -1,7 +1,7 @@
{% extends "mail/email_base.xhtml" %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Thank you, thank you, thank you!</p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Thank you, thank you, thank you!</p>
<p style="line-height: 20px;">A <b>huge</b> thanks for going premium.</p>
<p style="line-height: 20px;">Your subscription goes a long way towards funding the further development of NewsBlur.</p>
<p style="line-height: 20px;">There's still a ton of great work to be done, and you are personally keeping the dream alive. Thanks again, paying users like you make this entire endeavor worthwhile.</p>

View file

@ -3,7 +3,7 @@
{% load utils_tags %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Your free account is ready, {{ user.username }}.</p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Your free account is ready, {{ user.username }}.</p>
<p style="line-height: 20px;">Thanks again for trying out NewsBlur! Your account is ready to go. Just log right in and start reading.</p>
<p style="line-height: 20px;">http://{% current_domain dev=True %}{{ user.profile.autologin_url }}</p>
<p style="line-height: 20px;">I made NewsBlur because I wanted a better way to read the news and talk about it with people. I hope you love it, too.</p>

View file

@ -4,14 +4,8 @@
{% block body %}Hey {{ user.username }}, your premium account has just expired.
{% if months_ago >= 1 %}It's been {{ months_ago }} month{{ months_ago|pluralize }} since you last saw NewsBlur. We just launched a full-scale re-design, complete with shared stories (blurblogs) and native iOS/Android apps. If you miss the old Google Reader features, you'll love the new NewsBlur.{% else %}You've recently been on NewsBlur, but now your premium account is going to expire!{% endif %}
You now have a free account with all the limitations of a free account. But that doesn't mean you can't renew your premium subscription and enjoy the many benefits of using NewsBlur.
Your premium account has just expired, but that doesn't mean you can't renew your premium subscription and enjoy the many benefits of using NewsBlur.
Here are some easy ways to have a great time on NewsBlur:
* Follow friends from Twitter, Facebook, and NewsBlur: http://{% current_domain %}{{ user.profile.autologin_url }}
* Visit the popular blurblog, The People Have Spoken: http://popular.newsblur.com
* Renew your premium account for only $24/year: http://{% current_domain %}{{ user.profile.autologin_url }}?next=chooser
Renew now: http://{% current_domain %}{{ user.profile.autologin_url }}?next=chooser
Spend a few days trying out NewsBlur again. We hope you love it.{% endblock body %}

View file

@ -3,30 +3,9 @@
{% load utils_tags %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Hey {{ user.username }}, your premium account has just expired.</p>
<p style="line-height: 20px;">{% if months_ago >= 1 %}It's been {{ months_ago }} month{{ months_ago|pluralize }} since you last saw NewsBlur. We just launched a full-scale re-design, complete with shared stories (blurblogs) and native iOS/Android apps. If you miss the old Google Reader features, you'll love the new NewsBlur.{% else %}You've recently been on NewsBlur, but now your premium account is going to expire!{% endif %}</p>
<p style="line-height: 20px;">Your premium account has just expired, but that doesn't mean you can't renew your premium subscription and enjoy the many benefits of using NewsBlur.</p>
<p style="line-height: 20px;">Here are some easy ways to have a great time on NewsBlur:</p>
<p style="line-height: 20px;">
<ul style="list-style: none;">
<li style="line-height:22px;"><img src="http://{% current_domain %}/media/img/icons/circular/share.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> <a href="http://{% current_domain %}{{ user.profile.autologin_url }}" style="text-decoration:none">Follow friends from Twitter, Facebook, and NewsBlur</a>.</li>
<li style="line-height:22px;"><img src="http://{% current_domain %}/media/img/reader/popular_thumb.jpg?1" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Visit the popular blurblog: <a href="http://popular.newsblur.com" style="text-decoration:none">The People Have Spoken</a>.</li>
<li style="line-height:22px;"><img src="http://{% current_domain %}/media/img/reader/hamburger_l.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> <a href="http://{% current_domain %}{{ user.profile.autologin_url }}?next=chooser" style="text-decoration:none">Renew your premium account for only $24/year</a>.</li>
</ul>
</p>
<p style="border-top: 1px solid #C0C0C0;padding: 24px 0 12px;text-align:center"><b>NEW:</b> Sharing and discussing stories with friends</p>
<p><img src="http://f.cl.ly/items/0S2m3D3v0v041q0e2I04/Comments.png" style="width:550px;height:643px;border: 1px solid #505050;display: block;margin: 0 auto;"></p>
<p style="border-top: 1px solid #C0C0C0;padding: 24px 0 12px;text-align:center"><b>IT'S FUN:</b> There's serendipity in your news reader</p>
<p><img src="http://f.cl.ly/items/2w2R1X013q3T1r1p3t1M/Profile.png" style="width:550px;height:632px;border: 1px solid #505050;display: block;margin: 0 auto;"></p>
<p style="border-top: 1px solid #C0C0C0;padding: 24px 0 12px;text-align:center"><b>IMPROVED:</b> Everything is now incredibly fast</p>
<p><img src="http://f.cl.ly/items/3w2t0u3H133o0y1F2y04/Speed.png" style="width:550px;height:268px;border: 1px solid #505050;display: block;margin: 0 auto;"></p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Hey {{ user.username }}, your premium account has just expired.</p>
<p style="line-height: 20px;">You now have a free account with all the limitations of a free account. But that doesn't mean you can't renew your premium subscription and enjoy the many benefits of using NewsBlur.</p>
<p style="line-height: 20px;">Renew now: <a href="http://{% current_domain %}{{ user.profile.autologin_url }}?next=chooser">http://{% current_domain %}{{ user.profile.autologin_url }}?next=chooser</a></p>
<p style="line-height: 20px;">Spend a few days trying out <a href="http://{% current_domain %}{{ user.profile.autologin_url }}">NewsBlur</a> again. We hope you love it.</p>
{% endblock %}

View file

@ -4,10 +4,12 @@
{% block body %}Hey {{ user.username }}, your premium account is about to expire...
{% if months_ago >= 1 %}It's been {{ months_ago }} month{{ months_ago|pluralize }} since you last saw NewsBlur. A lot has changed since then.{% else %}You've recently been on NewsBlur, but a lot has changed since even then.{% endif %} We just launched a full-scale re-design, complete with shared stories (blurblogs) and native iOS/Android apps. If you miss the old Google Reader features, you'll love the new NewsBlur.
Your premium account was set to expire today, but you've been given a free month grace period, so you can continue using your premium account to try out NewsBlur.
{% if months_ago >= 1 %}It's been {{ months_ago }} month{{ months_ago|pluralize }} since you last saw NewsBlur. A lot has changed since then. We just launched a full-scale re-design, complete with shared stories (blurblogs) and native iOS/Android apps. If you miss the old Google Reader features, you'll love the new NewsBlur.{% else %}You've recently been on NewsBlur, so maybe you didn't mean to transition back to the free account? Maybe you just need to renew your premium account? Let's help you do that.{% endif %}
Renew now: http://{% current_domain %}{{ user.profile.autologin_url }}?next=chooser
Here are some easy ways to have a great time on NewsBlur:
* Follow friends from Twitter, Facebook, and NewsBlur: http://{% current_domain %}{{ user.profile.autologin_url }}

View file

@ -3,9 +3,10 @@
{% load utils_tags %}
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Hey {{ user.username }}, your premium account is about to expire...</p>
<p style="line-height: 20px;">{% if months_ago >= 1 %}It's been {{ months_ago }} month{{ months_ago|pluralize }} since you last saw NewsBlur. A lot has changed since then.{% else %}You've recently been on NewsBlur, but a lot has changed since even then.{% endif %} We just launched a full-scale re-design, complete with shared stories (blurblogs) and native iOS/Android apps. If you miss the old Google Reader features, you'll love the new NewsBlur.</p>
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Hey {{ user.username }}, your premium account is about to expire...</p>
<p style="line-height: 20px;">Your premium account was set to expire today, but you've been given a free month grace period, so you can continue using your premium account to try out NewsBlur.</p>
<p style="line-height: 20px;">{% if months_ago >= 1 %}It's been {{ months_ago }} month{{ months_ago|pluralize }} since you last saw NewsBlur. A lot has changed since then. We just launched a full-scale re-design, complete with shared stories (blurblogs) and native iOS/Android apps. If you miss the old Google Reader features, you'll love the new NewsBlur.{% else %}You've recently been on NewsBlur, so maybe you didn't mean to transition back to the free account? Maybe you just need to renew your premium account? Let's help you do that.{% endif %} </p>
<p style="line-height: 20px;">Renew now: <a href="http://{% current_domain %}{{ user.profile.autologin_url }}?next=chooser">http://{% current_domain %}{{ user.profile.autologin_url }}?next=renew</a></p>
<p style="line-height: 20px;">Here are some easy ways to have a great time on NewsBlur:</p>
<p style="line-height: 20px;">
<ul style="list-style: none;">

View file

@ -7,7 +7,7 @@
On a story entitled "<a href="{{ shared_story.blurblog_permalink }}">{{ shared_story.story_title }}</a>" from <img src="{{ story_feed.favicon_url_fqdn }}" style="width: 16px;height: 16px;vertical-align: bottom"> {{ story_feed.feed_title }}...
</p>
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;line-height: 48px;">
<p style="font-size: 24px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;line-height: 48px;">
<a href="{{ reply_user_profile.blurblog_url }}"><img src="{{ reply_user_profile.email_photo_url }}" style="width: 48px; height: 48px;margin: 0 12px 0 0;border-radius: 3px;border: none;float: left"></a> {{ reply_user_profile.username }} replied to you:
</p>

View file

@ -146,6 +146,10 @@
<img src="{{ MEDIA_URL }}embed/icons/circular/g_icn_focus.png">
<span class="NB-intelligence-label">Focus</span>
</li>
<li class="NB-intelligence-slider-control NB-intelligence-slider-blue">
<img src="{{ MEDIA_URL }}embed/icons/circular/clock.png">
<span class="NB-intelligence-label">Saved</span>
</li>
</ul>
</div>
</div>