mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
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:
commit
adb72403ca
31 changed files with 592 additions and 118 deletions
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
42
apps/rss_feeds/text_importer.py
Normal file
42
apps/rss_feeds/text_importer.py
Normal 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
|
|
@ -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'),
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* =================== */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
BIN
media/img/reader/white_fade.png
Normal file
BIN
media/img/reader/white_fade.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 335 B |
|
@ -257,7 +257,7 @@ body.NB-iphone {
|
|||
.NB-story code {
|
||||
overflow: auto;
|
||||
clear: both;
|
||||
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.NB-story h1,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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' }),
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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});
|
||||
},
|
||||
|
||||
|
|
|
@ -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});
|
||||
},
|
||||
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
},
|
||||
|
|
137
media/js/newsblur/views/text_tab_view.js
Normal file
137
media/js/newsblur/views/text_tab_view.js
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
|
@ -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 %}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue