Merge branch 'master' into circular

* master:
  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).
  Launching Text View.
  Paging in text view when on temporarily. Also auto-selecting first story when temporarily opening text view.
  Fixing two small bugs in text view.
  Hiding text view for non-staff.
  Fixing the last of the state errors on text view. Should be good to ship.
  Adding a white fade to text view for non-premium.
  Adding premium requirement for Text view.
  Temporarily loading text view on shift+enter. Adding keyboard shortcuts.
  Fitting story count floater, and then hiding it when it doesn't fit entirely.
  Selecting first story in text view in folders. Showing unread count floater even in text view.
  Correcting a few glitches in text view. Shaping up nicely. Just need premium only.
  Showing the story we do have when text view fails.
  Text view. Needs a few tweaks and a premium only view.
This commit is contained in:
Samuel Clay 2013-01-10 16:06:05 -08:00
commit adb72403ca
31 changed files with 592 additions and 118 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

@ -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

@ -22,6 +22,7 @@ from mongoengine.queryset import OperationError, Q
from mongoengine.base import ValidationError
from vendor.timezones.utilities import localtime_for_timezone
from apps.rss_feeds.tasks import UpdateFeeds, PushFeeds
from apps.rss_feeds.text_importer import TextImporter
from apps.search.models import SearchStarredStory, SearchFeed
from utils import json_functions as json
from utils import feedfinder, feedparser
@ -1410,6 +1411,7 @@ class MStory(mongo.Document):
story_original_content_z = mongo.BinaryField()
story_latest_content = mongo.StringField()
story_latest_content_z = mongo.BinaryField()
original_text_z = mongo.BinaryField()
story_content_type = mongo.StringField(max_length=255)
story_author_name = mongo.StringField()
story_permalink = mongo.StringField()
@ -1465,17 +1467,19 @@ class MStory(mongo.Document):
super(MStory, self).delete(*args, **kwargs)
@classmethod
def find_story(cls, story_feed_id, story_id):
def find_story(cls, story_feed_id, story_id, original_only=False):
from apps.social.models import MSharedStory
original_found = True
story = cls.objects(story_feed_id=story_feed_id,
story_guid=story_id).limit(1).first()
if not story:
original_found = False
if not story and not original_only:
story = MSharedStory.objects.filter(story_feed_id=story_feed_id,
story_guid=story_id).limit(1).first()
if not story:
if not story and not original_only:
story = MStarredStory.objects.filter(story_feed_id=story_feed_id,
story_guid=story_id).limit(1).first()
@ -1543,6 +1547,18 @@ class MStory(mongo.Document):
self.share_count = shares.count()
self.share_user_ids = [s['user_id'] for s in shares]
self.save()
def fetch_original_text(self, force=False, request=None):
original_text_z = self.original_text_z
if not original_text_z or force:
ti = TextImporter(self, request=request)
original_text = ti.fetch()
else:
logging.user(request, "~FYFetching ~FGoriginal~FY story text, ~SBfound.")
original_text = zlib.decompress(original_text_z)
return original_text
class MStarredStory(mongo.Document):

View file

@ -0,0 +1,42 @@
import requests
import zlib
from django.conf import settings
from vendor.readability import readability
from utils import log as logging
class TextImporter:
def __init__(self, story, request=None):
self.story = story
self.request = request
@property
def headers(self):
return {
'User-Agent': 'NewsBlur Content Fetcher - %s '
'(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)' % (
settings.NEWSBLUR_URL
),
'Connection': 'close',
}
def fetch(self):
html = requests.get(self.story.story_permalink, headers=self.headers)
original_text_doc = readability.Document(html.text, url=html.url, debug=settings.DEBUG)
content = original_text_doc.summary(html_partial=True)
if content:
self.story.original_text_z = zlib.compress(content)
self.story.save()
logging.user(self.request, "~SN~FYFetched ~FGoriginal text~FY: now ~SB%s bytes~SN vs. was ~SB%s bytes" % (
len(unicode(content)),
self.story.story_content_z and len(zlib.decompress(self.story.story_content_z))
))
else:
logging.user(self.request, "~SN~FRFailed~FY to fetch ~FGoriginal text~FY: was ~SB%s bytes" % (
len(zlib.decompress(self.story.story_content_z))
))
return content

View file

@ -13,4 +13,5 @@ urlpatterns = patterns('',
url(r'^exception_change_feed_link', views.exception_change_feed_link, name='exception-change-feed-link'),
url(r'^status', views.status, name='status'),
url(r'^load_single_feed', views.load_single_feed, name='feed-canonical'),
url(r'^original_text', views.original_text, name='original-text'),
)

View file

@ -13,11 +13,13 @@ from apps.rss_feeds.models import MFeedFetchHistory, MPageFetchHistory, MFeedPus
from apps.rss_feeds.models import MFeedIcon
from apps.analyzer.models import get_classifiers_for_user
from apps.reader.models import UserSubscription
from apps.rss_feeds.models import MStory
from utils.user_functions import ajax_login_required
from utils import json_functions as json, feedfinder
from utils.feed_functions import relative_timeuntil, relative_timesince
from utils.user_functions import get_user
from utils.view_functions import get_argument_or_404
from utils.view_functions import required_params
@json.json_view
@ -399,4 +401,25 @@ def status(request):
feeds = Feed.objects.filter(last_update__gte=hour_ago).order_by('-last_update')
return render_to_response('rss_feeds/status.xhtml', {
'feeds': feeds
}, context_instance=RequestContext(request))
}, context_instance=RequestContext(request))
@required_params('story_id', feed_id=int)
@json.json_view
def original_text(request):
story_id = request.GET['story_id']
feed_id = request.GET['feed_id']
force = request.GET.get('force', False)
story, _ = MStory.find_story(story_id=story_id, story_feed_id=feed_id)
if not story:
logging.user(request, "~FYFetching ~FGoriginal~FY story text: ~FRstory not found")
return {'code': -1, 'message': 'Story not found.'}
original_text = story.fetch_original_text(force=force, request=request)
return {
'feed_id': feed_id,
'story_id': story_id,
'original_text': original_text,
}

View file

@ -22,11 +22,11 @@ from apps.reader.models import UserSubscription, MUserStory
from apps.analyzer.models import MClassifierFeed, MClassifierAuthor, MClassifierTag, MClassifierTitle
from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds, apply_classifier_authors, apply_classifier_tags
from apps.rss_feeds.models import Feed, MStory
from apps.rss_feeds.text_importer import TextImporter
from apps.profile.models import Profile, MSentEmail
from vendor import facebook
from vendor import tweepy
from vendor import pynliner
from vendor.readability import readability
from utils import log as logging
from utils import json_functions as json
from utils.feed_functions import relative_timesince
@ -1245,7 +1245,7 @@ class MSharedStory(mongo.Document):
story_content_z = mongo.BinaryField()
story_original_content = mongo.StringField()
story_original_content_z = mongo.BinaryField()
original_article_z = mongo.BinaryField()
original_text_z = mongo.BinaryField()
story_content_type = mongo.StringField(max_length=255)
story_author_name = mongo.StringField()
story_permalink = mongo.StringField()
@ -1959,25 +1959,8 @@ class MSharedStory(mongo.Document):
return image_sizes
def fetch_original_text(self):
headers = {
'User-Agent': 'NewsBlur Content Fetcher - %s '
'(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)' % (
settings.NEWSBLUR_URL
),
'Connection': 'close',
}
html = requests.get(self.story_permalink, headers=headers).text
original_text_doc = readability.Document(html)
content = original_text_doc.content()
self.original_article_z = content and zlib.compress(content)
self.save()
logging.debug(" ---> ~SN~FGFetched original text on shared story: now ~SB%s bytes~SN vs. was ~SB%s bytes" % (
len(unicode(content)),
len(zlib.decompress(self.story_content_z))
))
ti = TextImporter(self)
original_text_doc = ti.fetch()
return original_text_doc

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

@ -46,6 +46,18 @@ a img {
line-height: 12px;
}
/* ================ */
/* = Restrictions = */
/* ================ */
.NB-staff-only {
display: none !important;
}
.NB-staff .NB-staff-only {
display: block !important;
}
/* ==================== */
/* = Styling & Themes = */
/* ==================== */
@ -1683,7 +1695,8 @@ background: transparent;
}
#story_pane .NB-feed-iframe,
#story_pane .NB-story-iframe {
#story_pane .NB-story-iframe,
#story_pane .NB-text-view {
width: 100%;
height: 100%;
border: 0;
@ -1694,10 +1707,14 @@ background: transparent;
position: absolute;
}
#story_pane .NB-story-iframe {
#story_pane .NB-text-view {
left: 200%;
top: 0;
}
#story_pane .NB-story-iframe {
left: 300%;
top: 0;
}
/* ================================ */
/* = Feed View Feed Title Floater = */
@ -1881,10 +1898,14 @@ background: transparent;
/* text-shadow: 0 1px 0 #E0E0E0;*/
}
#story_pane .NB-feed-stories .NB-feed-story .NB-feed-story-content div {
.NB-feed-story .NB-feed-story-content div {
max-width: 100%;
}
#story_pane .NB-feed-stories .NB-feed-story .NB-feed-story-content img {
.NB-feed-story .NB-feed-story-content pre,
.NB-feed-story .NB-feed-story-content code {
white-space: normal;
}
.NB-feed-story .NB-feed-story-content img {
max-width: 100% !important;
width: auto;
height: auto !important;
@ -2165,6 +2186,57 @@ background: transparent;
#story_pane .NB-story-hide-changes .NB-feed-story-content del {
display: none;
}
/* ============= */
/* = Text View = */
/* ============= */
#story_pane .NB-text-view-detail .NB-feed-story-content {
min-height: 120px;
}
#story_pane .NB-premium-only .NB-text-view-detail .NB-feed-story-content {
max-height: 300px;
overflow: hidden;
}
.NB-text-view-premium-only {
border-top: 1px solid #C0C0C0;
font-size: 13px;
text-align: center;
padding: 12px 0;
font-weight: bold;
margin: -32px 200px 42px 28px;
cursor: default;
max-width: 700px;
position: relative;
}
.NB-text-view-premium-only .NB-feed-story-premium-only-divider {
position: absolute;
width: 100%;
height: 50px;
background: transparent url('/media/embed/reader/white_fade.png') repeat-x 0 0;
top: -51px;
left: 0;
background-size: 25px 50px;
}
.NB-text-view-premium-only img {
width: 16px;
height: 16px;
vertical-align: text-bottom;
margin: 0 -2px 0 2px;
}
.NB-premium-only .NB-feed-story-sideoptions-container {
bottom: 60px;
}
/* ============ */
/* = Comments = */
/* ============ */
#story_pane .NB-feed-story-comments {
margin: -24px 200px 32px 28px;
/* padding: 1px 0 0;*/
@ -2543,7 +2615,7 @@ background: transparent;
background: -moz-linear-gradient(center bottom, #bababa 0%, #dadada 100%);
}
#story_pane .NB-feed-stories .NB-feed-story {
.NB-feed-story {
margin: 0;
clear: both;
overflow: hidden;
@ -3154,7 +3226,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;
@ -3342,6 +3414,9 @@ background: transparent;
.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_text .NB-task-image {
background: transparent url('/media/embed/icons/silk/application_view_columns.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');
}
@ -6997,10 +7072,10 @@ form.opml_import_form input {
background: transparent url('/media/embed/icons/silk/lock.png') no-repeat 0 0;
}
.NB-modal-feedchooser .NB-feedchooser-premium-bullets li.NB-5 .NB-feedchooser-premium-bullet-image {
background: transparent url('/media/embed/icons/silk/lorry.png') no-repeat 0 0;
background: transparent url('/media/embed/icons/silk/star.png') no-repeat 0 0;
}
.NB-modal-feedchooser .NB-feedchooser-premium-bullets li.NB-6 .NB-feedchooser-premium-bullet-image {
background: transparent url('/media/embed/icons/silk/star.png') no-repeat 0 0;
background: transparent url('/media/embed/icons/silk/lorry.png') no-repeat 0 0;
}
.NB-modal-feedchooser .NB-feedchooser-premium-bullets li.NB-7 .NB-feedchooser-premium-bullet-image {
background: transparent url('/media/embed/icons/silk/lightbulb.png') no-repeat 0 0;

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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

View file

@ -257,7 +257,7 @@ body.NB-iphone {
.NB-story code {
overflow: auto;
clear: both;
white-space: normal;
}
.NB-story h1,

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'
@ -1359,6 +1359,16 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
this.make_request('/oauth/unfollow_twitter_account', {'username': username}, callback);
},
fetch_original_text: function(story_id, feed_id, callback, error_callback) {
this.make_request('/rss_feeds/original_text', {
story_id: story_id,
feed_id: feed_id
}, callback, error_callback, {
request_type: 'GET',
ajax_group: 'statistics'
});
},
recalculate_story_scores: function(feed_id, options) {
options = options || {};
this.stories.each(_.bind(function(story, i) {

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

@ -29,6 +29,7 @@
$feed_stories: $('.NB-feed-stories'),
$feed_iframe: $('.NB-feed-iframe'),
$story_iframe: $('.NB-story-iframe'),
$text_view: $('.NB-text-view'),
$intelligence_slider: $('.NB-intelligence-slider'),
$mouse_indicator: $('#mouse-indicator'),
$feed_link_loader: $('#NB-feeds-list-loader'),
@ -113,6 +114,7 @@
NEWSBLUR.app.story_list = new NEWSBLUR.Views.StoryListView({collection: NEWSBLUR.assets.stories});
NEWSBLUR.app.original_tab_view = new NEWSBLUR.Views.OriginalTabView({collection: NEWSBLUR.assets.stories});
NEWSBLUR.app.story_tab_view = new NEWSBLUR.Views.StoryTabView({collection: NEWSBLUR.assets.stories});
NEWSBLUR.app.text_tab_view = new NEWSBLUR.Views.TextTabView({collection: NEWSBLUR.assets.stories});
NEWSBLUR.app.feed_selector = new NEWSBLUR.Views.FeedSelector();
NEWSBLUR.app.follow_requests_module = new NEWSBLUR.Views.FollowRequestsModule();
@ -156,6 +158,9 @@
} else if (this.flags['feed_view_showing_story_view']) {
view = 'story';
flag = 'story';
} else if (this.flags['temporary_story_view']) {
view = 'text';
flag = 'text';
}
this.flags.scrolling_by_selecting_story_title = true;
@ -182,8 +187,10 @@
(NEWSBLUR.reader.layout.contentLayout.panes.center &&
NEWSBLUR.reader.layout.contentLayout.panes.center.width() < 700)) {
this.$s.$feed_view.addClass('NB-feed-story-view-narrow');
this.$s.$text_view.addClass('NB-feed-story-view-narrow');
} else {
this.$s.$feed_view.removeClass('NB-feed-story-view-narrow');
this.$s.$text_view.removeClass('NB-feed-story-view-narrow');
}
},
@ -487,7 +494,6 @@
var story = NEWSBLUR.assets.stories.get_next_story(direction, {
score: this.get_unread_view_score()
});
if (story) {
story.set('selected', true);
}
@ -743,16 +749,26 @@
dir = '-';
}
// NEWSBLUR.log(['page_in_story', this.$s.$story_pane, direction, page_height, scroll_height]);
if (this.story_view == 'page' && !this.flags['page_view_showing_feed_view']) {
if (this.story_view == 'page' &&
!this.flags['page_view_showing_feed_view'] &&
!this.flags['temporary_story_view']) {
this.$s.$feed_iframe.scrollTo({
top: dir+'='+scroll_height,
left:'+=0'
}, 230, {queue: false});
} else if (this.story_view == 'feed' || this.flags['page_view_showing_feed_view']) {
} else if ((this.story_view == 'feed' &&
!this.flags['temporary_story_view']) ||
this.flags['page_view_showing_feed_view']) {
this.$s.$feed_stories.scrollTo({
top: dir+'='+scroll_height,
left:'+=0'
}, 230, {queue: false});
} else if (this.story_view == 'text' ||
this.flags['temporary_story_view']) {
this.$s.$text_view.scrollTo({
top: dir+'='+scroll_height,
left:'+=0'
}, 230, {queue: false});
}
this.show_mouse_indicator();
@ -991,6 +1007,7 @@
'scrolling_by_selecting_story_title': false,
'page_view_showing_feed_view': false,
'feed_view_showing_story_view': false,
'temporary_story_view': false,
'story_titles_loaded': false,
'iframe_prevented_from_loading': false,
'pause_feed_refreshing': false,
@ -1067,6 +1084,7 @@
NEWSBLUR.app.feed_selector.hide_feed_selector();
NEWSBLUR.app.original_tab_view.unload_feed_iframe();
NEWSBLUR.app.story_tab_view.unload_story_iframe();
NEWSBLUR.app.text_tab_view.unload();
},
reload_feed: function(options) {
@ -1146,6 +1164,7 @@
} else {
NEWSBLUR.app.original_tab_view.unload_feed_iframe();
NEWSBLUR.app.story_tab_view.unload_story_iframe();
NEWSBLUR.app.text_tab_view.unload();
this.flags['iframe_prevented_from_loading'] = true;
}
this.setup_mousemove_on_views();
@ -1190,7 +1209,7 @@
this.make_story_titles_pane_counter();
this.find_story_with_action_preference_on_open_feed();
if (this.story_view == 'story' &&
if (_.contains(['story', 'text'], this.story_view) &&
!this.active_story &&
!this.counts['find_next_unread_on_page_of_feed_stories_load']) {
this.show_next_story(1);
@ -1384,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);
@ -1417,41 +1442,44 @@
} else 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.hide_stories_progress_bar();
if (NEWSBLUR.Globals.is_anonymous) {
this.show_tryout_signup_button();
} else if (first_load) {
this.make_story_titles_pane_counter();
this.find_story_with_action_preference_on_open_feed();
if (_.contains(['story', 'text'], this.story_view) &&
!this.active_story &&
!this.counts['find_next_unread_on_page_of_feed_stories_load']) {
this.show_next_story(1);
}
}
}
},
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;
}
}));
@ -1683,7 +1711,8 @@
// = Story loading =
// =================
show_stories_progress_bar: function(feeds_loading) {
show_stories_progress_bar: function(feeds_loading, message) {
message = message || "Fetching stories";
if (NEWSBLUR.app.story_unread_counter) {
NEWSBLUR.app.story_unread_counter.remove();
}
@ -1703,11 +1732,17 @@
else unreads = this.get_unread_count(false) / 10;
this.animate_progress_bar($bar, unreads / 10);
$('.NB-river-progress-text', $progress).text('Fetching stories');
$('.NB-river-progress-text', $progress).text(message);
// Center the progress bar
var i_width = $progress.width();
var o_width = this.$s.$story_taskbar.width();
var left = (o_width / 2.0) - (i_width / 2.0);
var view_taskbar_width = $('.taskbar_nav_view').width();
if (left < view_taskbar_width) {
left += view_taskbar_width - left + 12;
}
$progress.css({'left': left});
},
@ -1722,14 +1757,17 @@
});
},
show_stories_error: function(data) {
show_stories_error: function(data, message) {
NEWSBLUR.log(["show_stories_error", data]);
this.hide_stories_progress_bar();
NEWSBLUR.app.original_tab_view.iframe_not_busting();
this.model.flags['no_more_stories'] = true;
var 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.";
@ -1753,6 +1791,12 @@
var i_width = $error.width();
var o_width = this.$s.$story_taskbar.width();
var left = (o_width / 2.0) - (i_width / 2.0);
var view_taskbar_width = $('.taskbar_nav_view').width();
if (left < view_taskbar_width) {
left += view_taskbar_width - left + 12;
}
$error.css({'left': left});
NEWSBLUR.app.story_titles.end_loading();
@ -1785,6 +1829,7 @@
// NEWSBLUR.log(['turn on feed view', this.flags['page_view_showing_feed_view'], this.flags['feed_view_showing_story_view']]);
this.flags['page_view_showing_feed_view'] = true;
this.flags['feed_view_showing_story_view'] = false;
this.flags['temporary_story_view'] = false;
this.switch_taskbar_view('feed', {skip_save_type: 'page'});
NEWSBLUR.app.story_list.show_stories_preference_in_feed_view();
}
@ -1793,11 +1838,19 @@
// NEWSBLUR.log(['turn off feed view', this.flags['page_view_showing_feed_view'], this.flags['feed_view_showing_story_view']]);
this.flags['page_view_showing_feed_view'] = false;
this.flags['feed_view_showing_story_view'] = false;
this.flags['temporary_story_view'] = false;
this.switch_taskbar_view('page');
} else if (this.flags['feed_view_showing_story_view']) {
// NEWSBLUR.log(['turn off story view', this.flags['page_view_showing_feed_view'], this.flags['feed_view_showing_story_view']]);
this.flags['page_view_showing_feed_view'] = false;
this.flags['feed_view_showing_story_view'] = false;
this.flags['temporary_story_view'] = false;
this.switch_taskbar_view(this.story_view, {skip_save_type: true});
} else if (this.flags['temporary_story_view']) {
// NEWSBLUR.log(['turn off story view', this.flags['page_view_showing_feed_view'], this.flags['feed_view_showing_story_view']]);
this.flags['page_view_showing_feed_view'] = false;
this.flags['feed_view_showing_story_view'] = false;
this.flags['temporary_story_view'] = false;
this.switch_taskbar_view(this.story_view, {skip_save_type: true});
}
}
@ -2098,13 +2151,14 @@
collection: collection
}).render();
}
NEWSBLUR.app.story_unread_counter.$el.css({'opacity': 0});
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.animate({'opacity': .2}, {'duration': 1000, 'queue': false});
}, 500);
NEWSBLUR.app.story_unread_counter.$el.animate({
'opacity': .2
}, {'duration': 600, 'queue': false});
}, 200);
},
@ -2299,22 +2353,30 @@
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) {
this.model.view_setting(this.active_feed, {'view': view});
}
$page_to_feed_arrow.hide();
$feed_to_story_arrow.hide();
this.hide_stories_error();
$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();
this.flags['temporary_story_view'] = true;
} else {
$taskbar_buttons.removeClass('NB-active');
$('.task_button_view.task_view_'+view).addClass('NB-active');
@ -2359,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()
}, {
@ -2367,6 +2429,18 @@
'duration': this.model.preference('animations') ? 550 : 0,
'queue': false
});
NEWSBLUR.app.text_tab_view.load_story();
if (!this.active_story) {
this.show_next_story(1);
}
} else if (view == 'story') {
$story_pane.animate({
'left': -3 * $feed_iframe.width()
}, {
'easing': 'easeInOutQuint',
'duration': this.model.preference('animations') ? 550 : 0,
'queue': false
});
NEWSBLUR.app.story_tab_view.load_story_iframe();
if (!this.active_story) {
this.show_next_story(1);
@ -2385,16 +2459,20 @@
// view = 'page';
} else if ($active.hasClass('task_view_feed')) {
view = 'page';
} else if ($active.hasClass('task_view_story')) {
} else if ($active.hasClass('task_view_text')) {
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 = 'text';
} else if ($active.hasClass('task_view_text')) {
view = 'story';
} else if ($active.hasClass('task_view_story')) {
// view = 'story';
// view = 'text';
}
}
@ -2705,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')
@ -2764,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' }, [
@ -3628,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);
@ -3649,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();
@ -3951,8 +4027,10 @@
this.hide_mouse_indicator();
if (this.story_view == 'story' ||
this.flags['feed_view_showing_story_view']) {
// this.hide_mouse_indicator();
this.story_view == 'text' ||
this.flags['feed_view_showing_story_view'] ||
this.flags['temporary_story_view']) {
this.hide_mouse_indicator();
} else {
_.delay(_.bind(this.show_mouse_indicator, this), 350);
}
@ -5042,6 +5120,10 @@
e.preventDefault();
self.switch_taskbar_view('story');
});
$.targetIs(e, { tagSelector: '.task_view_text' }, function($t, $p){
e.preventDefault();
self.switch_taskbar_view('text');
});
$.targetIs(e, { tagSelector: '.NB-task-return' }, function($t, $p){
e.preventDefault();
NEWSBLUR.app.original_tab_view.load_feed_iframe();
@ -5370,6 +5452,14 @@
e.preventDefault();
NEWSBLUR.app.story_tab_view.open_story(null, true);
});
$document.bind('keydown', 'shift+enter', function(e) {
e.preventDefault();
NEWSBLUR.app.text_tab_view.load_story(null, true);
});
$document.bind('keydown', 'shift+return', function(e) {
e.preventDefault();
NEWSBLUR.app.text_tab_view.load_story(null, true);
});
$document.bind('keydown', 'space', function(e) {
e.preventDefault();
self.page_in_story(0.4, 1);

View file

@ -105,13 +105,13 @@ NEWSBLUR.ReaderFeedchooser.prototype = {
]),
$.make('li', { className: 'NB-5' }, [
$.make('div', { className: 'NB-feedchooser-premium-bullet-image' }),
'You feed my poor, hungry dog for ',
$.make('span', { className: 'NB-feedchooser-hungry-dog' }, '6 days'),
$.make('img', { className: 'NB-feedchooser-premium-poor-hungry-dog', src: NEWSBLUR.Globals.MEDIA_URL + '/img/reader/shiloh.jpg' })
'Text view conveniently extracts the story'
]),
$.make('li', { className: 'NB-6' }, [
$.make('div', { className: 'NB-feedchooser-premium-bullet-image' }),
'You are directly supporting a young startup'
'You feed my poor, hungry dog for ',
$.make('span', { className: 'NB-feedchooser-hungry-dog' }, '6 days'),
$.make('img', { className: 'NB-feedchooser-premium-poor-hungry-dog', src: NEWSBLUR.Globals.MEDIA_URL + '/img/reader/shiloh.jpg' })
]),
$.make('li', { className: 'NB-7' }, [
$.make('div', { className: 'NB-feedchooser-premium-bullet-image' }),

View file

@ -88,15 +88,29 @@ NEWSBLUR.ReaderKeyboard.prototype = {
])
]),
$.make('div', { className: 'NB-keyboard-shortcut NB-last' }, [
$.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Open in Story view'),
$.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Quick search for a site'),
$.make('div', { className: 'NB-keyboard-shortcut-key' }, [
'enter'
'g'
]),
$.make('div', { className: 'NB-keyboard-shortcut-image' }, [
$.make('img', { src: NEWSBLUR.Globals.MEDIA_URL + '/img/reader/keyboard_enter.png', width: 268, height: 29 })
])
])
]),
$.make('div', { className: 'NB-keyboard-group' }, [
$.make('div', { className: 'NB-keyboard-shortcut' }, [
$.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Open in Story view'),
$.make('div', { className: 'NB-keyboard-shortcut-key' }, [
'enter'
])
]),
$.make('div', { className: 'NB-keyboard-shortcut NB-last' }, [
$.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Open in Text view'),
$.make('div', { className: 'NB-keyboard-shortcut-key' }, [
'shift+enter'
])
])
]),
$.make('div', { className: 'NB-keyboard-group' }, [
$.make('div', { className: 'NB-keyboard-shortcut' }, [
$.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Page down'),

View file

@ -7,7 +7,6 @@ NEWSBLUR.ReaderSocialProfile = function(user_id, options) {
this.model = NEWSBLUR.assets;
this.profiles = new NEWSBLUR.Collections.Users();
user_id = parseInt(_.string.ltrim(user_id, 'social:'), 10);
NEWSBLUR.log(["user_id", user_id]);
this.runner(user_id);
};

View file

@ -99,8 +99,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

@ -61,6 +61,16 @@ NEWSBLUR.Views.FeedCount = Backbone.View.extend({
var i_width = this.$el.width();
var o_width = NEWSBLUR.reader.$s.$story_taskbar.width();
var left = (o_width / 2.0) - (i_width / 2.0);
var view_taskbar_width = $('.taskbar_nav_view').width();
var story_buttons_offset = $(".taskbar_nav_story").position().left;
if (i_width + 12 > (story_buttons_offset - view_taskbar_width)) {
this.$el.hide();
}
if (left < view_taskbar_width + 12) {
left += view_taskbar_width - left + 12;
}
this.$el.css({'left': left});
},

View file

@ -59,6 +59,17 @@ NEWSBLUR.Views.FolderCount = Backbone.View.extend({
var i_width = this.$el.width();
var o_width = NEWSBLUR.reader.$s.$story_taskbar.width();
var left = (o_width / 2.0) - (i_width / 2.0);
var view_taskbar_width = $('.taskbar_nav_view').width();
var story_buttons_offset = $(".taskbar_nav_story").position().left;
if (i_width + 12 > (story_buttons_offset - view_taskbar_width)) {
this.$el.hide();
}
if (left < view_taskbar_width + 12) {
left += view_taskbar_width - left + 12;
}
this.$el.css({'left': left});
},

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

@ -30,12 +30,14 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
this.model.bind('change:starred', this.toggle_starred, this);
this.model.bind('change:intelligence', this.render_header, this);
this.model.bind('change:intelligence', this.toggle_score, this);
this.model.bind('change:shared', this.render_comments, this);
this.model.bind('change:comments', this.render_comments, this);
// Binding directly instead of using event delegation. Need for speed.
// this.$el.bind('mouseenter', this.mouseenter);
// this.$el.bind('mouseleave', this.mouseleave);
if (!this.options.feed_floater) {
if (!this.options.feed_floater && !this.options.text_view) {
this.model.story_view = this;
}
},
@ -56,6 +58,9 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
profile: NEWSBLUR.assets.user_profile
});
this.$el.html(this.template(params));
if (this.feed) {
this.$el.toggleClass('NB-inverse', this.feed.is_light());
}
this.toggle_classes();
this.toggle_read_status();
this.toggle_score();
@ -75,10 +80,10 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
get_render_params: function() {
this.feed = NEWSBLUR.assets.get_feed(this.model.get('story_feed_id'));
this.classifiers = NEWSBLUR.assets.classifiers[this.model.get('story_feed_id')];
var show_feed_title = NEWSBLUR.reader.flags.river_view || this.options.show_feed_title;
return {
story : this.model,
feed : NEWSBLUR.reader.flags.river_view && this.feed,
feed : show_feed_title && this.feed,
tag : _.first(this.model.get("story_tags")),
title : this.make_story_title(),
authors_score : this.classifiers && this.classifiers.authors[this.model.get('story_authors')],
@ -139,7 +144,9 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
<%= story_header %>\
<div class="NB-feed-story-shares-container"></div>\
<div class="NB-feed-story-content">\
<%= story.get("story_content") %>\
<% if (!options.skip_content) { %>\
<%= story.get("story_content") %>\
<% } %>\
</div>\
<div class="NB-feed-story-comments-container"></div>\
<div class="NB-feed-story-sideoptions-container">\
@ -176,9 +183,10 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
$header.css('textShadow', NEWSBLUR.utils.generate_shadow(this.feed));
},
make_story_title: function() {
var title = this.model.get('story_title');
var classifiers = NEWSBLUR.assets.classifiers[this.model.get('story_feed_id')];
make_story_title: function(story) {
story = story || this.model;
var title = story.get('story_title');
var classifiers = NEWSBLUR.assets.classifiers[story.get('story_feed_id')];
var feed_titles = classifiers && classifiers.titles || [];
_.each(feed_titles, function(score, title_classifier) {
@ -229,9 +237,6 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
var unread_view = NEWSBLUR.reader.get_unread_view_score();
var score = story.score();
if (this.feed) {
this.$el.toggleClass('NB-inverse', this.feed.is_light());
}
this.$el.toggleClass('NB-river-story', NEWSBLUR.reader.flags.river_view);
this.$el.toggleClass('NB-story-starred', !!story.get('starred'));
this.$el.toggleClass('NB-story-shared', !!story.get('shared'));
@ -279,7 +284,8 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
NEWSBLUR.app.story_list.scroll_to_selected_story(model, options);
}
if (NEWSBLUR.reader.flags['feed_view_showing_story_view']) {
if (NEWSBLUR.reader.flags['feed_view_showing_story_view'] ||
NEWSBLUR.reader.flags['temporary_story_view']) {
NEWSBLUR.reader.switch_to_correct_view();
}
},

View file

@ -243,8 +243,6 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
this.model.social_page_story.$el.toggleClass('NB-story-shared', this.model.get('shared'));
this.model.social_page_story.replace_shares_and_comments(data);
} else {
this.model.story_view.$el.toggleClass('NB-story-shared', this.model.get('shared'));
this.model.story_view.render_comments();
NEWSBLUR.reader.hide_confirm_story_share_menu_item(true);
}

View file

@ -3,7 +3,8 @@ NEWSBLUR.Views.StoryTitlesView = Backbone.View.extend({
el: '.NB-story-titles',
events: {
"click .NB-feed-story-premium-only a" : function() {
"click .NB-feed-story-premium-only a" : function(e) {
e.preventDefault();
NEWSBLUR.reader.open_feedchooser_modal();
}
},

View file

@ -0,0 +1,137 @@
NEWSBLUR.Views.TextTabView = Backbone.View.extend({
events: {
"click .NB-premium-only a" : function(e) {
e.preventDefault();
NEWSBLUR.reader.open_feedchooser_modal();
}
},
initialize: function() {
this.setElement(NEWSBLUR.reader.$s.$text_view);
this.collection.bind('change:selected', this.select_story, this);
this.$story = this.$('.NB-text-view-detail');
},
// ===========
// = Actions =
// ===========
load_story: function(story, is_temporary) {
if (!story) story = NEWSBLUR.reader.active_story;
if (!story && is_temporary) {
NEWSBLUR.reader.show_next_story(1);
story = NEWSBLUR.reader.active_story;
}
if (!story) return;
if (is_temporary) {
NEWSBLUR.reader.switch_taskbar_view('text', {
skip_save_type: is_temporary ? 'text' : false
});
}
if (this.story == story) return;
this.story = story;
this.$story.html(new NEWSBLUR.Views.StoryDetailView({
model: this.story,
show_feed_title: true,
skip_content: true,
text_view: true
}).render().el);
this.show_loading();
NEWSBLUR.assets.fetch_original_text(story.get('id'), story.get('story_feed_id'),
_.bind(this.render, this),
_.bind(this.error, this));
},
render: function(data) {
if (data.story_id != this.story.get('id') ||
data.feed_id != this.story.get('story_feed_id')) {
return;
}
var original_text = data.original_text;
this.hide_loading();
var $content = this.$('.NB-feed-story-content');
if (original_text.length < (this.story.get('story_content').length / 3)) {
this.error();
} else {
$content.html(original_text);
NEWSBLUR.reader.make_story_titles_pane_counter();
}
$content.css('opacity', 0);
$content.show();
$content.animate({
'opacity': 1
}, {
duration: 250,
queue: false
});
if (!NEWSBLUR.Globals.is_premium) {
this.append_premium_only_notification();
}
},
unload: function() {
var $content = this.$('.NB-text-view-detail');
$content.empty();
},
show_loading: function() {
NEWSBLUR.reader.hide_stories_error();
NEWSBLUR.reader.show_stories_progress_bar(10, "Fetching text");
},
hide_loading: function() {
NEWSBLUR.reader.hide_stories_progress_bar();
},
error: function() {
this.hide_loading();
NEWSBLUR.reader.show_stories_error({}, "Sorry, the story\'s text<br />could not be extracted.");
var $content = this.$('.NB-feed-story-content');
$content.html(this.story.get('story_content'));
},
append_premium_only_notification: function() {
var $content = this.$('.NB-feed-story-content');
var $notice = $.make('div', { className: 'NB-text-view-premium-only' }, [
$.make('div', { className: 'NB-feed-story-premium-only-divider'}),
$.make('div', { className: 'NB-feed-story-premium-only-text'}, [
'The full ',
$.make('img', { src: NEWSBLUR.Globals['MEDIA_URL'] + 'img/icons/silk/application_view_columns.png' }),
' Text view is a ',
$.make('a', { href: '#', className: 'NB-splash-link' }, 'premium feature'),
'.'
])
]);
$notice.hide();
this.$('.NB-feed-story-premium-only').remove();
$content.after($notice);
this.$el.addClass('NB-premium-only');
$notice.css('opacity', 0);
$notice.show();
$notice.animate({'opacity': 1}, {'duration': 250, 'queue': false});
},
// ==========
// = Events =
// ==========
select_story: function(story, selected) {
if (selected && NEWSBLUR.reader.story_view == 'text') {
if (NEWSBLUR.reader.flags['temporary_story_view']) {
NEWSBLUR.reader.switch_to_correct_view();
}
this.load_story(story);
}
}
});

View file

@ -105,7 +105,7 @@
{% endif %}
</head>
<body class="{% block bodyclass %}{% endblock %}">
<body class="{% block bodyclass %}{% endblock %} {% if user.is_staff %}NB-staff{% endif %} {% if user_profile.is_premium %}NB-premium{% endif %}">
{% block header %}{% endblock %}

View file

@ -166,7 +166,15 @@
<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 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">
<div class="NB-task-button-wrapper">
<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">
@ -174,6 +182,7 @@
<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>
@ -225,6 +234,9 @@
<div class="NB-feed-story-view-floater"></div>
<ul class="NB-feed-stories"></ul>
</div>
<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

@ -1,5 +1,6 @@
import traceback
import sys
import inspect
from pprint import pprint
class ConsoleExceptionMiddleware:
@ -7,6 +8,8 @@ class ConsoleExceptionMiddleware:
exc_info = sys.exc_info()
print "######################## Exception #############################"
print '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info())))
print "----------------------------------------------------------------"
pprint(inspect.trace()[-1][0].f_locals)
print "################################################################"
#pprint(request)

View file

@ -16,6 +16,10 @@ def getlogger():
def user(u, msg, request=None):
from apps.statistics.models import MAnalyticsPageLoad
if not u:
return debug(msg)
platform = '------'
time_elapsed = ""
if isinstance(u, WSGIRequest) or request: