fixing merge conflict
|
@ -1,7 +1,7 @@
|
|||
The MIT License
|
||||
===============
|
||||
|
||||
Copyright (c) 2009-2010 Samuel Clay <samuel@ofbrooklyn.com>.
|
||||
Copyright (c) 2009-2012 Samuel Clay, NewsBlur <samuel@newsblur.com>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -145,7 +145,7 @@ these after the installation below.
|
|||
4. Run the development server. At this point, all dependencies should be installed and no
|
||||
additional configuration is needed. If you find that something is not working at this
|
||||
point, please email the resulting output to Samuel Clay at
|
||||
[samuel@ofbrooklyn.com](samuel@ofbrooklyn.com).
|
||||
[samuel@newsblur.com](samuel@newsblur.com).
|
||||
|
||||
./manage.py runserver
|
||||
|
||||
|
@ -230,7 +230,7 @@ reader, and feed importer. To run the test suite:
|
|||
## Author
|
||||
|
||||
* Created by [Samuel Clay](http://www.samuelclay.com).
|
||||
* Email address: <samuel@ofbrooklyn.com>
|
||||
* Email address: <samuel@newsblur.com>
|
||||
* [@samuelclay](http://twitter.com/samuelclay) on Twitter.
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import urllib, urllib2
|
|||
import cookielib
|
||||
import json
|
||||
|
||||
__author__ = "Dananjaya Ramanayake <dananjaya86@gmail.com>, Samuel Clay <samuel@ofbrooklyn.com>"
|
||||
__author__ = "Dananjaya Ramanayake <dananjaya86@gmail.com>, Samuel Clay <samuel@newsblur.com>"
|
||||
__version__ = "1.0"
|
||||
|
||||
API_URL = "http://www.newsblur.com/"
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
"groups": [],
|
||||
"user_permissions": [],
|
||||
"password": "sha1$7b94b$ac9e6cf08d0fa16a67e56e319c0935aeb26db2a2",
|
||||
"email": "samuel@ofbrooklyn.com",
|
||||
"email": "samuel@newsblur.com",
|
||||
"date_joined": "2009-01-04 17:32:58"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"groups": [],
|
||||
"user_permissions": [],
|
||||
"password": "sha1$7b94b$ac9e6cf08d0fa16a67e56e319c0935aeb26db2a2",
|
||||
"email": "samuel@ofbrooklyn.com",
|
||||
"email": "samuel@newsblur.com",
|
||||
"date_joined": "2009-01-04 17:32:58"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
"groups": [],
|
||||
"user_permissions": [],
|
||||
"password": "sha1$7b94b$ac9e6cf08d0fa16a67e56e319c0935aeb26db2a2",
|
||||
"email": "samuel@ofbrooklyn.com",
|
||||
"email": "samuel@newsblur.com",
|
||||
"date_joined": "2009-01-04 17:32:58"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -16,6 +16,7 @@ from django.conf import settings
|
|||
from django.core.mail import mail_admins
|
||||
from django.core.validators import email_re
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.contrib.sites.models import Site
|
||||
from mongoengine.queryset import OperationError
|
||||
from pymongo.helpers import OperationFailure
|
||||
from operator import itemgetter
|
||||
|
@ -33,7 +34,9 @@ try:
|
|||
from apps.rss_feeds.models import Feed, MFeedPage, DuplicateFeed, MStory, MStarredStory, FeedLoadtime
|
||||
except:
|
||||
pass
|
||||
from apps.social.models import MSharedStory, MSocialProfile, MSocialSubscription, MActivity
|
||||
from apps.social.models import MSharedStory, MSocialProfile, MSocialServices
|
||||
from apps.social.models import MSocialSubscription, MActivity
|
||||
from apps.social.views import load_social_page
|
||||
from utils import json_functions as json
|
||||
from utils.user_functions import get_user, ajax_login_required
|
||||
from utils.feed_functions import relative_timesince
|
||||
|
@ -48,9 +51,20 @@ from vendor.timezones.utilities import localtime_for_timezone
|
|||
|
||||
SINGLE_DAY = 60*60*24
|
||||
|
||||
@never_cache
|
||||
@render_to('reader/feeds.xhtml')
|
||||
def index(request):
|
||||
if request.method == "GET" and request.subdomain and request.subdomain != 'dev':
|
||||
username = request.subdomain
|
||||
try:
|
||||
if '.' in username:
|
||||
username = username.split('.')[0]
|
||||
user = User.objects.get(username__iexact=username)
|
||||
except User.DoesNotExist:
|
||||
return HttpResponseRedirect('http://%s%s' % (
|
||||
Site.objects.get_current().domain.replace('www', 'dev'),
|
||||
reverse('index')))
|
||||
return load_social_page(request, user_id=user.pk, username=request.subdomain)
|
||||
|
||||
# XXX TODO: Remove me on launch.
|
||||
if request.method == "GET" and request.user.is_anonymous() and not request.REQUEST.get('letmein'):
|
||||
return {}, 'reader/social_signup.xhtml'
|
||||
|
@ -211,6 +225,7 @@ def load_feeds(request):
|
|||
}
|
||||
social_feeds = MSocialSubscription.feeds(**social_params)
|
||||
social_profile = MSocialProfile.profile(user.pk)
|
||||
social_services = MSocialServices.profile(user.pk)
|
||||
|
||||
user.profile.dashboard_date = datetime.datetime.now()
|
||||
user.profile.save()
|
||||
|
@ -219,6 +234,7 @@ def load_feeds(request):
|
|||
'feeds': feeds.values() if version == 2 else feeds,
|
||||
'social_feeds': social_feeds,
|
||||
'social_profile': social_profile,
|
||||
'social_services': social_services,
|
||||
'folders': json.decode(folders.folders),
|
||||
'starred_count': starred_count,
|
||||
}
|
||||
|
@ -228,11 +244,11 @@ def load_feeds(request):
|
|||
def load_feed_favicons(request):
|
||||
user = get_user(request)
|
||||
feed_ids = request.REQUEST.getlist('feed_ids')
|
||||
user_subs = UserSubscription.objects.select_related('feed').filter(user=user, active=True)
|
||||
if feed_ids and len(feed_ids) > 0:
|
||||
user_subs = user_subs.filter(feed__in=feed_ids)
|
||||
|
||||
if not feed_ids:
|
||||
user_subs = UserSubscription.objects.select_related('feed').filter(user=user, active=True)
|
||||
feed_ids = [sub['feed__pk'] for sub in user_subs.values('feed__pk')]
|
||||
|
||||
feed_ids = [sub['feed__pk'] for sub in user_subs.values('feed__pk')]
|
||||
feed_icons = dict([(i.feed_id, i.data) for i in MFeedIcon.objects(feed_id__in=feed_ids)])
|
||||
|
||||
return feed_icons
|
||||
|
@ -240,10 +256,13 @@ def load_feed_favicons(request):
|
|||
def load_feeds_flat(request):
|
||||
user = request.user
|
||||
include_favicons = request.REQUEST.get('include_favicons', False)
|
||||
update_counts = request.REQUEST.get('update_counts', False)
|
||||
|
||||
feeds = {}
|
||||
iphone_version = "1.2"
|
||||
|
||||
if include_favicons == 'false': include_favicons = False
|
||||
if update_counts == 'false': update_counts = False
|
||||
|
||||
if not user.is_authenticated():
|
||||
return HttpResponseForbidden()
|
||||
|
@ -285,7 +304,23 @@ def load_feeds_flat(request):
|
|||
make_feeds_folder(folder, flat_folder_name, depth+1)
|
||||
|
||||
make_feeds_folder(folders)
|
||||
data = dict(flat_folders=flat_folders, feeds=feeds, user=user.username, iphone_version=iphone_version)
|
||||
|
||||
social_params = {
|
||||
'user_id': user.pk,
|
||||
'include_favicon': include_favicons,
|
||||
'update_counts': update_counts,
|
||||
}
|
||||
social_feeds = MSocialSubscription.feeds(**social_params)
|
||||
social_profile = MSocialProfile.profile(user.pk)
|
||||
|
||||
data = {
|
||||
"flat_folders": flat_folders,
|
||||
"feeds": feeds,
|
||||
"social_feeds": social_feeds,
|
||||
"social_profile": social_profile,
|
||||
"user": user.username,
|
||||
"iphone_version": iphone_version,
|
||||
}
|
||||
return data
|
||||
|
||||
@ratelimit(minutes=1, requests=20)
|
||||
|
@ -643,14 +678,20 @@ def load_river_stories(request):
|
|||
# starred_stories = {}
|
||||
|
||||
# Intelligence classifiers for all feeds involved
|
||||
classifier_feeds = list(MClassifierFeed.objects(user_id=user.pk,
|
||||
feed_id__in=found_feed_ids))
|
||||
classifier_authors = list(MClassifierAuthor.objects(user_id=user.pk,
|
||||
if found_feed_ids:
|
||||
classifier_feeds = list(MClassifierFeed.objects(user_id=user.pk,
|
||||
feed_id__in=found_feed_ids))
|
||||
classifier_titles = list(MClassifierTitle.objects(user_id=user.pk,
|
||||
classifier_authors = list(MClassifierAuthor.objects(user_id=user.pk,
|
||||
feed_id__in=found_feed_ids))
|
||||
classifier_titles = list(MClassifierTitle.objects(user_id=user.pk,
|
||||
feed_id__in=found_feed_ids))
|
||||
classifier_tags = list(MClassifierTag.objects(user_id=user.pk,
|
||||
feed_id__in=found_feed_ids))
|
||||
classifier_tags = list(MClassifierTag.objects(user_id=user.pk,
|
||||
feed_id__in=found_feed_ids))
|
||||
else:
|
||||
classifier_feeds = []
|
||||
classifier_authors = []
|
||||
classifier_titles = []
|
||||
classifier_tags = []
|
||||
classifiers = sort_classifiers_by_feed(user=user, feed_ids=found_feed_ids,
|
||||
classifier_feeds=classifier_feeds,
|
||||
classifier_authors=classifier_authors,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"groups": [],
|
||||
"user_permissions": [],
|
||||
"password": "sha1$d5473$d07ce4495b088ff0f41a62d5113d0189ce8f0096",
|
||||
"email": "samuel@ofbrooklyn.com",
|
||||
"email": "samuel@newsblur.com",
|
||||
"date_joined": "2011-07-18 00:23:49"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
"groups": [],
|
||||
"user_permissions": [],
|
||||
"password": "sha1$7b94b$ac9e6cf08d0fa16a67e56e319c0935aeb26db2a2",
|
||||
"email": "samuel@ofbrooklyn.com",
|
||||
"email": "samuel@newsblur.com",
|
||||
"date_joined": "2009-01-04 17:32:58"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -933,6 +933,8 @@ class Feed(models.Model):
|
|||
text = re.sub(r'\n+', '\n\n', text)
|
||||
text = re.sub(r'\t+', '\t', text)
|
||||
story['text'] = text
|
||||
if '<ins' in story['story_content'] or '<del' in story['story_content']:
|
||||
story['has_modifications'] = True
|
||||
|
||||
return story
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ from vendor import facebook
|
|||
from vendor import tweepy
|
||||
from utils import log as logging
|
||||
from utils.feed_functions import relative_timesince
|
||||
from utils.story_functions import truncate_chars
|
||||
from utils import json_functions as json
|
||||
|
||||
RECOMMENDATIONS_LIMIT = 5
|
||||
|
@ -125,13 +126,19 @@ class MSocialProfile(mongo.Document):
|
|||
if not self.username:
|
||||
self.import_user_fields()
|
||||
if not self.subscription_count:
|
||||
self.count(skip_save=True)
|
||||
self.count_follows(skip_save=True)
|
||||
if self.bio and len(self.bio) > MSocialProfile.bio.max_length:
|
||||
self.bio = self.bio[:80]
|
||||
super(MSocialProfile, self).save(*args, **kwargs)
|
||||
if self.user_id not in self.following_user_ids:
|
||||
self.follow_user(self.user_id)
|
||||
self.count()
|
||||
self.count_follows()
|
||||
|
||||
@property
|
||||
def blurblog_url(self):
|
||||
return "http://%s.%s" % (
|
||||
self.username_slug,
|
||||
Site.objects.get_current().domain.replace('www', 'dev'))
|
||||
|
||||
def recommended_users(self):
|
||||
r = redis.Redis(connection_pool=settings.REDIS_POOL)
|
||||
|
@ -221,7 +228,7 @@ class MSocialProfile(mongo.Document):
|
|||
profile = cls.objects.get(user_id=user_id)
|
||||
except cls.DoesNotExist:
|
||||
return {}
|
||||
return profile.to_json(full=True)
|
||||
return profile.to_json(include_follows=True)
|
||||
|
||||
@classmethod
|
||||
def profiles(cls, user_ids):
|
||||
|
@ -259,7 +266,7 @@ class MSocialProfile(mongo.Document):
|
|||
return params
|
||||
|
||||
def page(self):
|
||||
params = self.to_json(full=True)
|
||||
params = self.to_json(include_follows=True)
|
||||
params.update({
|
||||
'feed_title': self.title,
|
||||
'custom_css': self.custom_css,
|
||||
|
@ -271,8 +278,17 @@ class MSocialProfile(mongo.Document):
|
|||
if self.photo_url:
|
||||
return self.photo_url
|
||||
return settings.MEDIA_URL + 'img/reader/default_profile_photo.png'
|
||||
|
||||
@property
|
||||
def email_photo_url(self):
|
||||
if self.photo_url:
|
||||
if self.photo_url.startswith('//'):
|
||||
self.photo_url = 'http:' + self.photo_url
|
||||
return self.photo_url
|
||||
domain = Site.objects.get_current().domain.replace('www', 'dev')
|
||||
return 'http://' + domain + settings.MEDIA_URL + 'img/reader/default_profile_photo.png'
|
||||
|
||||
def to_json(self, compact=False, full=False, common_follows_with_user=None):
|
||||
def to_json(self, compact=False, include_follows=False, common_follows_with_user=None):
|
||||
# domain = Site.objects.get_current().domain
|
||||
domain = Site.objects.get_current().domain.replace('www', 'dev')
|
||||
params = {
|
||||
|
@ -284,8 +300,7 @@ class MSocialProfile(mongo.Document):
|
|||
'feed_title': self.title,
|
||||
'feed_address': "http://%s%s" % (domain, reverse('shared-stories-rss-feed',
|
||||
kwargs={'user_id': self.user_id, 'username': self.username_slug})),
|
||||
'feed_link': "http://%s%s" % (domain, reverse('load-social-page',
|
||||
kwargs={'user_id': self.user_id, 'username': self.username_slug})),
|
||||
'feed_link': self.blurblog_url,
|
||||
}
|
||||
if not compact:
|
||||
params.update({
|
||||
|
@ -300,11 +315,11 @@ class MSocialProfile(mongo.Document):
|
|||
'stories_last_month': self.stories_last_month,
|
||||
'average_stories_per_month': self.average_stories_per_month,
|
||||
})
|
||||
if full:
|
||||
if include_follows:
|
||||
params.update({
|
||||
'photo_service': self.photo_service,
|
||||
'following_user_ids': self.following_user_ids,
|
||||
'follower_user_ids': self.follower_user_ids,
|
||||
'following_user_ids': self.following_user_ids_without_self,
|
||||
'follower_user_ids': self.follower_user_ids_without_self,
|
||||
})
|
||||
if common_follows_with_user:
|
||||
with_user, _ = MSocialProfile.objects.get_or_create(user_id=common_follows_with_user)
|
||||
|
@ -317,16 +332,28 @@ class MSocialProfile(mongo.Document):
|
|||
|
||||
return params
|
||||
|
||||
@property
|
||||
def following_user_ids_without_self(self):
|
||||
if self.user_id in self.following_user_ids:
|
||||
return [u for u in self.following_user_ids if u != self.user_id]
|
||||
return self.following_user_ids
|
||||
|
||||
@property
|
||||
def follower_user_ids_without_self(self):
|
||||
if self.user_id in self.follower_user_ids:
|
||||
return [u for u in self.follower_user_ids if u != self.user_id]
|
||||
return self.follower_user_ids
|
||||
|
||||
def import_user_fields(self, skip_save=False):
|
||||
user = User.objects.get(pk=self.user_id)
|
||||
self.username = user.username
|
||||
self.email = user.email
|
||||
|
||||
def count(self, skip_save=False):
|
||||
def count_follows(self, skip_save=False):
|
||||
self.subscription_count = UserSubscription.objects.filter(user__pk=self.user_id).count()
|
||||
self.shared_stories_count = MSharedStory.objects.filter(user_id=self.user_id).count()
|
||||
self.following_count = len(self.following_user_ids)
|
||||
self.follower_count = len(self.follower_user_ids)
|
||||
self.following_count = len(self.following_user_ids_without_self)
|
||||
self.follower_count = len(self.follower_user_ids_without_self)
|
||||
if not skip_save:
|
||||
self.save()
|
||||
|
||||
|
@ -340,7 +367,7 @@ class MSocialProfile(mongo.Document):
|
|||
self.following_user_ids.append(user_id)
|
||||
if user_id in self.unfollowed_user_ids:
|
||||
self.unfollowed_user_ids.remove(user_id)
|
||||
self.count()
|
||||
self.count_follows()
|
||||
self.save()
|
||||
|
||||
if self.user_id == user_id:
|
||||
|
@ -349,7 +376,7 @@ class MSocialProfile(mongo.Document):
|
|||
followee, _ = MSocialProfile.objects.get_or_create(user_id=user_id)
|
||||
if self.user_id not in followee.follower_user_ids:
|
||||
followee.follower_user_ids.append(self.user_id)
|
||||
followee.count()
|
||||
followee.count_follows()
|
||||
followee.save()
|
||||
|
||||
following_key = "F:%s:F" % (self.user_id)
|
||||
|
@ -364,6 +391,9 @@ class MSocialProfile(mongo.Document):
|
|||
subscription_user_id=user_id)
|
||||
socialsub.needs_unread_recalc = True
|
||||
socialsub.save()
|
||||
|
||||
from apps.social.tasks import EmailNewFollower
|
||||
EmailNewFollower.delay(follower_user_id=self.user_id, followee_user_id=user_id)
|
||||
|
||||
def is_following_user(self, user_id):
|
||||
return user_id in self.following_user_ids
|
||||
|
@ -382,13 +412,13 @@ class MSocialProfile(mongo.Document):
|
|||
self.following_user_ids.remove(user_id)
|
||||
if user_id not in self.unfollowed_user_ids:
|
||||
self.unfollowed_user_ids.append(user_id)
|
||||
self.count()
|
||||
self.count_follows()
|
||||
self.save()
|
||||
|
||||
followee = MSocialProfile.objects.get(user_id=user_id)
|
||||
if self.user_id in followee.follower_user_ids:
|
||||
followee.follower_user_ids.remove(self.user_id)
|
||||
followee.count()
|
||||
followee.count_follows()
|
||||
followee.save()
|
||||
|
||||
following_key = "F:%s:F" % (self.user_id)
|
||||
|
@ -408,7 +438,49 @@ class MSocialProfile(mongo.Document):
|
|||
follows_inter = [int(f) for f in follows_inter]
|
||||
follows_diff = [int(f) for f in follows_diff]
|
||||
|
||||
if user_id in follows_inter:
|
||||
follows_inter.remove(user_id)
|
||||
if user_id in follows_diff:
|
||||
follows_diff.remove(user_id)
|
||||
|
||||
return follows_inter, follows_diff
|
||||
|
||||
def send_email_for_new_follower(self, follower_user_id):
|
||||
user = User.objects.get(pk=self.user_id)
|
||||
if not user.email or not user.profile.send_emails:
|
||||
return
|
||||
|
||||
follower_profile = MSocialProfile.objects.get(user_id=follower_user_id)
|
||||
photo_url = follower_profile.profile_photo_url
|
||||
if 'graph.facebook.com' in photo_url:
|
||||
follower_profile.photo_url = photo_url + '?type=large'
|
||||
elif 'twimg' in photo_url:
|
||||
follower_profile.photo_url = photo_url.replace('_normal', '')
|
||||
|
||||
common_followers, _ = self.common_follows(follower_user_id, direction='followers')
|
||||
common_followings, _ = self.common_follows(follower_user_id, direction='following')
|
||||
common_followers.remove(self.user_id)
|
||||
common_followings.remove(self.user_id)
|
||||
common_followers = MSocialProfile.profiles(common_followers)
|
||||
common_followings = MSocialProfile.profiles(common_followings)
|
||||
|
||||
data = {
|
||||
'user': user,
|
||||
'follower_profile': follower_profile,
|
||||
'common_followers': common_followers,
|
||||
'common_followings': common_followings,
|
||||
}
|
||||
|
||||
text = render_to_string('mail/email_new_follower.txt', data)
|
||||
html = render_to_string('mail/email_new_follower.xhtml', data)
|
||||
subject = "%s is now following your Blurblog on NewsBlur!" % follower_profile.username
|
||||
msg = EmailMultiAlternatives(subject, text,
|
||||
from_email='NewsBlur <%s>' % settings.HELLO_EMAIL,
|
||||
to=['%s <%s>' % (user.username, user.email)])
|
||||
msg.attach_alternative(html, "text/html")
|
||||
msg.send()
|
||||
|
||||
logging.user(user, "~BB~FM~SBSending email for new follower: %s" % follower_profile.username)
|
||||
|
||||
def save_feed_story_history_statistics(self):
|
||||
"""
|
||||
|
@ -854,6 +926,7 @@ class MSharedStory(mongo.Document):
|
|||
story_permalink = mongo.StringField()
|
||||
story_guid = mongo.StringField(unique_with=('user_id',))
|
||||
story_tags = mongo.ListField(mongo.StringField(max_length=250))
|
||||
posted_to_services = mongo.ListField(mongo.StringField(max_length=20))
|
||||
|
||||
meta = {
|
||||
'collection': 'shared_stories',
|
||||
|
@ -891,7 +964,7 @@ class MSharedStory(mongo.Document):
|
|||
super(MSharedStory, self).save(*args, **kwargs)
|
||||
|
||||
author, _ = MSocialProfile.objects.get_or_create(user_id=self.user_id)
|
||||
author.count()
|
||||
author.count_follows()
|
||||
|
||||
MActivity.new_shared_story(user_id=self.user_id, story_title=self.story_title,
|
||||
comments=self.comments, story_feed_id=self.story_feed_id,
|
||||
|
@ -902,9 +975,18 @@ class MSharedStory(mongo.Document):
|
|||
share_key = "S:%s:%s" % (self.story_feed_id, self.guid_hash)
|
||||
r.srem(share_key, self.user_id)
|
||||
|
||||
comment_key = "C:%s:%s" % (self.story_feed_id, self.guid_hash)
|
||||
r.srem(comment_key, self.user_id)
|
||||
|
||||
MActivity.remove_shared_story(user_id=self.user_id, story_feed_id=self.story_feed_id,
|
||||
story_id=self.story_guid)
|
||||
|
||||
super(MSharedStory, self).delete(*args, **kwargs)
|
||||
|
||||
def set_source_user_id(self, source_user_id, original_comments=None):
|
||||
if source_user_id == self.user_id:
|
||||
return
|
||||
|
||||
def find_source(source_user_id, seen_user_ids):
|
||||
parent_shared_story = MSharedStory.objects.filter(user_id=source_user_id,
|
||||
story_guid=self.story_guid,
|
||||
|
@ -1104,6 +1186,39 @@ class MSharedStory(mongo.Document):
|
|||
profiles = [profile.to_json(compact=True) for profile in profiles]
|
||||
|
||||
return stories, profiles
|
||||
|
||||
def blurblog_permalink(self):
|
||||
profile = MSocialProfile.objects.get(user_id=self.user_id)
|
||||
return "%s/story/%s" % (
|
||||
profile.blurblog_url,
|
||||
self.guid_hash[:6]
|
||||
)
|
||||
|
||||
def generate_post_to_service_message(self):
|
||||
message = self.comments
|
||||
if not message or len(message) < 1:
|
||||
message = self.story_title
|
||||
|
||||
message = truncate_chars(message, 116)
|
||||
message += " " + self.blurblog_permalink()
|
||||
print message
|
||||
|
||||
return message
|
||||
|
||||
def post_to_service(self, service):
|
||||
if service in self.posted_to_services:
|
||||
return
|
||||
|
||||
message = self.generate_post_to_service_message()
|
||||
social_service = MSocialServices.objects.get(user_id=self.user_id)
|
||||
if service == 'twitter':
|
||||
posted = social_service.post_to_twitter(message)
|
||||
elif service == 'facebook':
|
||||
posted = social_service.post_to_facebook(message)
|
||||
|
||||
if posted:
|
||||
self.posted_to_services.append(service)
|
||||
self.save()
|
||||
|
||||
|
||||
class MSocialServices(mongo.Document):
|
||||
|
@ -1154,6 +1269,14 @@ class MSocialServices(mongo.Document):
|
|||
}
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def profile(cls, user_id):
|
||||
try:
|
||||
profile = cls.objects.get(user_id=user_id)
|
||||
except cls.DoesNotExist:
|
||||
return {}
|
||||
return profile.to_json()
|
||||
|
||||
def twitter_api(self):
|
||||
twitter_consumer_key = settings.TWITTER_CONSUMER_KEY
|
||||
twitter_consumer_secret = settings.TWITTER_CONSUMER_SECRET
|
||||
|
@ -1189,7 +1312,7 @@ class MSocialServices(mongo.Document):
|
|||
profile.bio = profile.bio or twitter_user.description
|
||||
profile.website = profile.website or twitter_user.url
|
||||
profile.save()
|
||||
profile.count()
|
||||
profile.count_follows()
|
||||
if not profile.photo_url or not profile.photo_service:
|
||||
self.set_photo('twitter')
|
||||
|
||||
|
@ -1216,7 +1339,7 @@ class MSocialServices(mongo.Document):
|
|||
profile.bio = profile.bio or facebook_user.get('bio')
|
||||
profile.website = profile.website or facebook_user.get('website')
|
||||
profile.save()
|
||||
profile.count()
|
||||
profile.count_follows()
|
||||
if not profile.photo_url or not profile.photo_service:
|
||||
self.set_photo('facebook')
|
||||
|
||||
|
@ -1300,7 +1423,26 @@ class MSocialServices(mongo.Document):
|
|||
hashlib.md5(user.email).hexdigest()
|
||||
profile.save()
|
||||
return profile
|
||||
|
||||
def post_to_twitter(self, message):
|
||||
try:
|
||||
api = self.twitter_api()
|
||||
api.update_status(status=message)
|
||||
except tweepy.TweepError, e:
|
||||
print e
|
||||
return
|
||||
|
||||
return True
|
||||
|
||||
def post_to_facebook(self, message):
|
||||
try:
|
||||
api = self.facebook_api()
|
||||
api.put_wall_post(message=message)
|
||||
except facebook.GraphAPIError, e:
|
||||
print e
|
||||
return
|
||||
|
||||
return True
|
||||
|
||||
class MInteraction(mongo.Document):
|
||||
user_id = mongo.IntField()
|
||||
|
@ -1578,3 +1720,17 @@ class MActivity(mongo.Document):
|
|||
if share_date:
|
||||
a.date = share_date
|
||||
a.save()
|
||||
|
||||
@classmethod
|
||||
def remove_shared_story(cls, user_id, story_feed_id, story_id):
|
||||
try:
|
||||
a = cls.objects.get(user_id=user_id,
|
||||
with_user_id=user_id,
|
||||
category='sharedstory',
|
||||
feed_id=story_feed_id,
|
||||
content_id=story_id)
|
||||
except cls.DoesNotExist:
|
||||
return
|
||||
|
||||
a.delete()
|
||||
|
||||
|
|
18
apps/social/tasks.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from celery.task import Task
|
||||
from apps.social.models import MSharedStory, MSocialProfile
|
||||
|
||||
|
||||
class PostToService(Task):
|
||||
|
||||
def run(self, shared_story_id, service):
|
||||
try:
|
||||
shared_story = MSharedStory.objects.get(id=shared_story_id)
|
||||
shared_story.post_to_service(service)
|
||||
except MSharedStory.DoesNotExist:
|
||||
print "Story not found (%s). Can't post to: %s" % (shared_story_id, service)
|
||||
|
||||
class EmailNewFollower(Task):
|
||||
|
||||
def run(self, follower_user_id, followee_user_id):
|
||||
user_profile = MSocialProfile.objects.get(user_id=followee_user_id)
|
||||
user_profile.send_email_for_new_follower(follower_user_id)
|
|
@ -4,6 +4,7 @@ from apps.social import views
|
|||
urlpatterns = patterns('',
|
||||
url(r'^request_invite/?$', views.request_invite, name='request-invite'),
|
||||
url(r'^share_story/?$', views.mark_story_as_shared, name='mark-story-as-shared'),
|
||||
url(r'^unshare_story/?$', views.mark_story_as_unshared, name='mark-story-as-unshared'),
|
||||
url(r'^load_user_friends/?$', views.load_user_friends, name='load-user-friends'),
|
||||
url(r'^profile/?$', views.profile, name='profile'),
|
||||
url(r'^load_user_profile/?$', views.load_user_profile, name='load-user-profile'),
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.conf import settings
|
|||
from apps.rss_feeds.models import MStory, Feed, MStarredStory
|
||||
from apps.social.models import MSharedStory, MSocialServices, MSocialProfile, MSocialSubscription, MCommentReply
|
||||
from apps.social.models import MRequestInvite, MInteraction, MActivity
|
||||
from apps.social.tasks import PostToService
|
||||
from apps.analyzer.models import MClassifierTitle, MClassifierAuthor, MClassifierFeed, MClassifierTag
|
||||
from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds, apply_classifier_authors, apply_classifier_tags
|
||||
from apps.analyzer.models import get_classifiers_for_user, sort_classifiers_by_feed
|
||||
|
@ -172,11 +173,18 @@ def load_social_page(request, user_id, username=None):
|
|||
page = request.REQUEST.get('page')
|
||||
if page: offset = limit * (int(page) - 1)
|
||||
|
||||
social_profile = MSocialProfile.objects.get(user_id=social_user_id)
|
||||
mstories = MSharedStory.objects(user_id=social_user.pk).order_by('-shared_date')[offset:offset+limit]
|
||||
stories = Feed.format_stories(mstories)
|
||||
|
||||
if not stories:
|
||||
return dict(stories=[])
|
||||
return {
|
||||
"user": user,
|
||||
"stories": [],
|
||||
"feeds": {},
|
||||
"social_user": social_user,
|
||||
"social_profile": social_profile.page(),
|
||||
}
|
||||
|
||||
story_feed_ids = list(set(s['story_feed_id'] for s in stories))
|
||||
feeds = Feed.objects.filter(pk__in=story_feed_ids)
|
||||
|
@ -189,7 +197,19 @@ def load_social_page(request, user_id, username=None):
|
|||
story['shared_date'] = shared_date
|
||||
|
||||
stories, profiles = MSharedStory.stories_with_comments_and_profiles(stories, user, check_all=True)
|
||||
social_profile = MSocialProfile.objects.get(user_id=social_user_id)
|
||||
profiles = dict([(p['user_id'], p) for p in profiles])
|
||||
|
||||
for s, story in enumerate(stories):
|
||||
for u, user_id in enumerate(story['shared_by_friends']):
|
||||
stories[s]['shared_by_friends'][u] = profiles[user_id]
|
||||
for u, user_id in enumerate(story['shared_by_public']):
|
||||
stories[s]['shared_by_public'][u] = profiles[user_id]
|
||||
for c, comment in enumerate(story['comments']):
|
||||
stories[s]['comments'][c]['user'] = profiles[comment['user_id']]
|
||||
if comment['source_user_id']:
|
||||
stories[s]['comments'][c]['source_user'] = profiles[comment['source_user_id']]
|
||||
for r, reply in enumerate(comment['replies']):
|
||||
stories[s]['comments'][c]['replies'][r]['user'] = profiles[reply['user_id']]
|
||||
|
||||
params = {
|
||||
'user': user,
|
||||
|
@ -226,10 +246,14 @@ def mark_story_as_shared(request):
|
|||
story_id = request.POST['story_id']
|
||||
comments = request.POST.get('comments', '')
|
||||
source_user_id = request.POST.get('source_user_id')
|
||||
post_to_services = request.POST.getlist('post_to_services')
|
||||
|
||||
story = MStory.objects(story_feed_id=feed_id, story_guid=story_id).limit(1).first()
|
||||
if not story:
|
||||
return {'code': -1, 'message': 'Story not found. Reload this site.'}
|
||||
return {
|
||||
'code': -1,
|
||||
'message': 'The original story is gone. This would be a nice bug to fix. Speak up.'
|
||||
}
|
||||
|
||||
shared_story = MSharedStory.objects.filter(user_id=request.user.pk,
|
||||
story_feed_id=feed_id,
|
||||
|
@ -240,7 +264,8 @@ def mark_story_as_shared(request):
|
|||
story_values = dict(user_id=request.user.pk, comments=comments,
|
||||
has_comments=bool(comments), **story_db)
|
||||
shared_story = MSharedStory.objects.create(**story_values)
|
||||
shared_story.set_source_user_id(source_user_id)
|
||||
if source_user_id:
|
||||
shared_story.set_source_user_id(int(source_user_id))
|
||||
socialsubs = MSocialSubscription.objects.filter(subscription_user_id=request.user.pk)
|
||||
for socialsub in socialsubs:
|
||||
socialsub.needs_unread_recalc = True
|
||||
|
@ -248,11 +273,9 @@ def mark_story_as_shared(request):
|
|||
logging.user(request, "~FCSharing ~FM%s: ~SB~FB%s" % (story.story_title[:20], comments[:30]))
|
||||
else:
|
||||
shared_story = shared_story[0]
|
||||
# original_comments = shared_story.comments
|
||||
shared_story.comments = comments
|
||||
shared_story.has_comments = bool(comments)
|
||||
shared_story.save()
|
||||
# shared_story.set_source_user_id(source_user_id, original_comments=original_comments)
|
||||
logging.user(request, "~FCUpdating shared story ~FM%s: ~SB~FB%s" % (
|
||||
story.story_title[:20], comments[:30]))
|
||||
|
||||
|
@ -264,8 +287,48 @@ def mark_story_as_shared(request):
|
|||
story = stories[0]
|
||||
story['shared_comments'] = shared_story['comments'] or ""
|
||||
|
||||
if post_to_services:
|
||||
for service in post_to_services:
|
||||
if service not in shared_story.posted_to_services:
|
||||
PostToService.delay(shared_story_id=shared_story.id, service=service)
|
||||
|
||||
return {'code': code, 'story': story, 'user_profiles': profiles}
|
||||
|
||||
@ajax_login_required
|
||||
@json.json_view
|
||||
def mark_story_as_unshared(request):
|
||||
feed_id = int(request.POST['feed_id'])
|
||||
story_id = request.POST['story_id']
|
||||
|
||||
story = MStory.objects(story_feed_id=feed_id, story_guid=story_id).limit(1).first()
|
||||
if not story:
|
||||
return {'code': -1, 'message': 'Story not found. Reload this site.'}
|
||||
|
||||
try:
|
||||
shared_story = MSharedStory.objects.get(user_id=request.user.pk,
|
||||
story_feed_id=feed_id,
|
||||
story_guid=story_id)
|
||||
except MSharedStory.DoesNotExist:
|
||||
return {'code': -1, 'message': 'Shared story not found.'}
|
||||
|
||||
socialsubs = MSocialSubscription.objects.filter(subscription_user_id=request.user.pk)
|
||||
for socialsub in socialsubs:
|
||||
socialsub.needs_unread_recalc = True
|
||||
socialsub.save()
|
||||
logging.user(request, "~FC~SKUn-sharing ~FM%s: ~SB~FB%s" % (shared_story.story_title[:20],
|
||||
shared_story.comments[:30]))
|
||||
shared_story.delete()
|
||||
|
||||
story.count_comments()
|
||||
|
||||
story = Feed.format_story(story)
|
||||
stories, profiles = MSharedStory.stories_with_comments_and_profiles([story],
|
||||
request.user,
|
||||
check_all=True)
|
||||
story = stories[0]
|
||||
|
||||
return {'code': 1, 'message': "Story unshared.", 'story': story, 'user_profiles': profiles}
|
||||
|
||||
@ajax_login_required
|
||||
@json.json_view
|
||||
def save_comment_reply(request):
|
||||
|
@ -354,7 +417,8 @@ def profile(request):
|
|||
user = get_user(request.user)
|
||||
user_id = request.GET.get('user_id', user.pk)
|
||||
user_profile = MSocialProfile.objects.get(user_id=user_id)
|
||||
user_profile = user_profile.to_json(full=True, common_follows_with_user=user.pk)
|
||||
user_profile.count_follows()
|
||||
user_profile = user_profile.to_json(include_follows=True, common_follows_with_user=user.pk)
|
||||
profile_ids = set(user_profile['followers_youknow'] + user_profile['followers_everybody'] +
|
||||
user_profile['following_youknow'] + user_profile['following_everybody'])
|
||||
profiles = MSocialProfile.profiles(profile_ids)
|
||||
|
@ -387,7 +451,7 @@ def load_user_profile(request):
|
|||
|
||||
return {
|
||||
'services': social_services,
|
||||
'user_profile': social_profile.to_json(full=True),
|
||||
'user_profile': social_profile.to_json(include_follows=True),
|
||||
}
|
||||
|
||||
@ajax_login_required
|
||||
|
@ -406,7 +470,7 @@ def save_user_profile(request):
|
|||
|
||||
logging.user(request, "~BB~FRSaving social profile")
|
||||
|
||||
return dict(code=1, user_profile=profile.to_json(full=True))
|
||||
return dict(code=1, user_profile=profile.to_json(include_follows=True))
|
||||
|
||||
@json.json_view
|
||||
def load_user_friends(request):
|
||||
|
@ -420,7 +484,7 @@ def load_user_friends(request):
|
|||
return {
|
||||
'services': social_services,
|
||||
'autofollow': social_services.autofollow,
|
||||
'user_profile': social_profile.to_json(full=True),
|
||||
'user_profile': social_profile.to_json(include_follows=True),
|
||||
'following_profiles': following_profiles,
|
||||
'follower_profiles': follower_profiles,
|
||||
'recommended_users': recommended_users,
|
||||
|
@ -459,7 +523,7 @@ def follow(request):
|
|||
logging.user(request, "~BB~FRFollowing: %s" % follow_profile.username)
|
||||
|
||||
return {
|
||||
"user_profile": profile.to_json(full=True),
|
||||
"user_profile": profile.to_json(include_follows=True),
|
||||
"follow_profile": follow_profile.to_json(common_follows_with_user=request.user.pk),
|
||||
"follow_subscription": follow_subscription,
|
||||
}
|
||||
|
@ -489,7 +553,7 @@ def unfollow(request):
|
|||
logging.user(request, "~BB~FRUnfollowing: %s" % unfollow_profile.username)
|
||||
|
||||
return {
|
||||
'user_profile': profile.to_json(full=True),
|
||||
'user_profile': profile.to_json(include_follows=True),
|
||||
'unfollow_profile': unfollow_profile.to_json(common_follows_with_user=request.user.pk),
|
||||
}
|
||||
|
||||
|
@ -518,7 +582,7 @@ def shared_stories_rss_feed(request, user_id, username):
|
|||
social_profile = MSocialProfile.objects.get(user_id=user_id)
|
||||
|
||||
data = {}
|
||||
data['title'] = social_profile.blog_title
|
||||
data['title'] = social_profile.title
|
||||
link = reverse('shared-stories-public', kwargs={'username': user.username})
|
||||
data['link'] = "http://www.newsblur.com/%s" % link
|
||||
data['description'] = "Stories shared by %s on NewsBlur." % user.username
|
||||
|
@ -600,4 +664,4 @@ def load_interactions(request):
|
|||
return {
|
||||
'interactions': interactions,
|
||||
'page': page,
|
||||
}
|
||||
}
|
||||
|
|
11
assets.yml
|
@ -50,7 +50,7 @@ javascripts:
|
|||
- media/js/vendor/jquery.flot.js
|
||||
- media/js/vendor/jquery.tipsy.js
|
||||
- media/js/vendor/jquery.chosen.js
|
||||
- media/js/vendor/jquery.linkify.js
|
||||
# - media/js/vendor/jquery.linkify.js
|
||||
- media/js/vendor/bootstrap.*.js
|
||||
- media/js/vendor/audio.js
|
||||
- media/js/vendor/socket.io-client.*.js
|
||||
|
@ -90,6 +90,11 @@ javascripts:
|
|||
- media/js/vendor/jquery.tinysort.js
|
||||
- media/js/vendor/jquery.simplemodal-1.3.js
|
||||
- media/js/vendor/jquery.corners.js
|
||||
blurblog:
|
||||
- media/js/vendor/jquery-*.js
|
||||
- media/js/vendor/underscore-*.js
|
||||
- media/js/vendor/underscore.string.js
|
||||
- media/js/vendor/backbone-*.js
|
||||
|
||||
stylesheets:
|
||||
common:
|
||||
|
@ -104,4 +109,6 @@ stylesheets:
|
|||
- media/css/mobile/mobile.css
|
||||
bookmarklet:
|
||||
- media/css/bookmarklet/reset.css
|
||||
- media/css/modals.css
|
||||
- media/css/modals.css
|
||||
blurblog:
|
||||
- media/css/social/social_page.css
|
|
@ -37,7 +37,7 @@
|
|||
"groups": [],
|
||||
"user_permissions": [],
|
||||
"password": "sha1$d5473$d07ce4495b088ff0f41a62d5113d0189ce8f0096",
|
||||
"email": "samuel@ofbrooklyn.com",
|
||||
"email": "samuel@newsblur.com",
|
||||
"date_joined": "2011-07-18 00:23:49"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
199.15.252.50 db02 db02.newsblur.com
|
||||
199.15.253.226 db03 db03.newsblur.com
|
||||
199.15.249.98 db04 db04.newsblur.com
|
||||
199.15.249.99 db05 db05.newsblur.com
|
||||
199.15.249.100 db06 db06.newsblur.com
|
||||
199.15.250.231 task01 task01.newsblur.com
|
||||
199.15.250.250 task02 task02.newsblur.com
|
||||
199.15.250.233 task03 task03.newsblur.com
|
||||
|
|
|
@ -14,7 +14,7 @@ logappend=true
|
|||
|
||||
#port = 27017
|
||||
|
||||
slowms=1000
|
||||
slowms=100
|
||||
|
||||
rest = true
|
||||
#profile = 2
|
||||
|
@ -88,5 +88,3 @@ noauth = true
|
|||
|
||||
# in replica set configuration, specify the name of the replica set
|
||||
replSet = nbset
|
||||
|
||||
journal = true
|
||||
|
|
|
@ -1,36 +1,40 @@
|
|||
upstream app_server {
|
||||
server 127.0.0.1:8000 fail_timeout=10 max_fails=3 ;
|
||||
server app02:8000 fail_timeout=10 max_fails=3 down;
|
||||
}
|
||||
|
||||
upstream icon_server {
|
||||
server 127.0.0.1:3030 fail_timeout=10 max_fails=3 ;
|
||||
server 127.0.0.1:3030 fail_timeout=2 max_fails=3;
|
||||
server 127.0.0.1:8000 backup;
|
||||
}
|
||||
|
||||
# server {
|
||||
# server_name newsblur.com;
|
||||
# rewrite ^(.*) http://www.newsblur.com$1 permanent;
|
||||
# }
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 default_server ssl;
|
||||
|
||||
ssl on;
|
||||
# ssl on;
|
||||
ssl_certificate /home/sclay/newsblur/config/certificates/newsblur.com.crt;
|
||||
ssl_certificate_key /home/sclay/newsblur/config/certificates/newsblur.com.key;
|
||||
|
||||
client_max_body_size 4M;
|
||||
server_name www.newsblur.com push.newsblur.com 199.15.250.228 127.0.0.1;
|
||||
server_name www.newsblur.com newsblur.com dev.newsblur.com *.newsblur.com;
|
||||
|
||||
# if ($host = 'newsblur.com') {
|
||||
# rewrite ^/(.*)$ https://www.newsblur.com/$1 permanent;
|
||||
# }
|
||||
|
||||
if (-f /home/sclay/newsblur/media/maintenance.html) {
|
||||
return 503;
|
||||
}
|
||||
|
||||
error_page 502 @down;
|
||||
location @down {
|
||||
root /home/sclay/newsblur/;
|
||||
rewrite ^(.*)$ /templates/502.html break;
|
||||
}
|
||||
|
||||
error_page 503 @maintenance;
|
||||
location @maintenance {
|
||||
rewrite ^(.*)$ /home/sclay/newsblur/media/maintenance.html break;
|
||||
root /home/sclay/newsblur/;
|
||||
rewrite ^(.*)$ /media/maintenance.html break;
|
||||
}
|
||||
|
||||
location /media/ {
|
||||
|
@ -46,14 +50,14 @@ server {
|
|||
}
|
||||
|
||||
location /favicon.ico {
|
||||
alias /home/sclay/newsblur/media/img/favicon.png;
|
||||
expires max;
|
||||
access_log off;
|
||||
alias /home/sclay/newsblur/media/img/favicon.png;
|
||||
expires max;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ^~ /crossdomain.xml {
|
||||
expires max;
|
||||
alias /home/sclay/newsblur/media/crossdomain.xml;
|
||||
alias /home/sclay/newsblur/media/crossdomain.xml;
|
||||
types {
|
||||
text/x-cross-domain-policy xml;
|
||||
}
|
||||
|
@ -61,19 +65,11 @@ server {
|
|||
|
||||
location ^~ /robots.txt {
|
||||
expires max;
|
||||
alias /home/sclay/newsblur/media/robots.txt;
|
||||
alias /home/sclay/newsblur/media/robots.txt;
|
||||
}
|
||||
|
||||
location /munin/ {
|
||||
alias /var/cache/munin/www/;
|
||||
}
|
||||
|
||||
location /nginx_status {
|
||||
stub_status on;
|
||||
access_log off;
|
||||
allow 127.0.0.1;
|
||||
allow 199.15.250.228;
|
||||
deny all;
|
||||
alias /var/cache/munin/www/;
|
||||
}
|
||||
|
||||
location ^~ /rss_feeds/icon/ {
|
||||
|
@ -82,18 +78,10 @@ server {
|
|||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
|
||||
if (!-f $request_filename) {
|
||||
proxy_pass http://icon_server;
|
||||
break;
|
||||
}
|
||||
proxy_pass http://icon_server;
|
||||
}
|
||||
|
||||
location / {
|
||||
if (-f /home/sclay/newsblur/media/maintenance.html) {
|
||||
return 503;
|
||||
}
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
|
|
|
@ -38,15 +38,15 @@
|
|||
# The default values of these variables are driven from the -D command-line
|
||||
# option or PGDATA environment variable, represented here as ConfigDir.
|
||||
|
||||
data_directory = '/var/lib/postgresql/9.0/main' # use data in another directory
|
||||
data_directory = '/var/lib/postgresql/9.1/main' # use data in another directory
|
||||
# (change requires restart)
|
||||
hba_file = '/etc/postgresql/9.0/main/pg_hba.conf' # host-based authentication file
|
||||
hba_file = '/etc/postgresql/9.1/main/pg_hba.conf' # host-based authentication file
|
||||
# (change requires restart)
|
||||
ident_file = '/etc/postgresql/9.0/main/pg_ident.conf' # ident configuration file
|
||||
ident_file = '/etc/postgresql/9.1/main/pg_ident.conf' # ident configuration file
|
||||
# (change requires restart)
|
||||
|
||||
# If external_pid_file is not explicitly set, no extra PID file is written.
|
||||
external_pid_file = '/var/run/postgresql/9.0-main.pid' # write an extra PID file
|
||||
external_pid_file = '/var/run/postgresql/9.1-main.pid' # write an extra PID file
|
||||
# (change requires restart)
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[program:celery]
|
||||
command=/home/sclay/newsblur/manage.py celeryd --loglevel=INFO -Q new_feeds,push_feeds,update_feeds
|
||||
command=/home/sclay/newsblur/manage.py celeryd --loglevel=INFO -Q new_feeds,work_queue,push_feeds,update_feeds
|
||||
directory=/home/sclay/newsblur
|
||||
user=sclay
|
||||
numprocs=1
|
||||
|
|
29
fabfile.py
vendored
|
@ -41,7 +41,9 @@ env.roledefs ={
|
|||
'db': ['db01.newsblur.com',
|
||||
'db02.newsblur.com',
|
||||
'db03.newsblur.com',
|
||||
'db04.newsblur.com'],
|
||||
'db04.newsblur.com',
|
||||
'db05.newsblur.com',
|
||||
'db06.newsblur.com'],
|
||||
'task': ['task01.newsblur.com',
|
||||
'task02.newsblur.com',
|
||||
'task03.newsblur.com',
|
||||
|
@ -265,13 +267,12 @@ def setup_db():
|
|||
setup_baremetal()
|
||||
setup_db_firewall()
|
||||
setup_db_motd()
|
||||
# setup_rabbitmq()
|
||||
copy_task_settings()
|
||||
setup_memcached()
|
||||
setup_postgres()
|
||||
# setup_postgres()
|
||||
setup_mongo()
|
||||
setup_gunicorn(supervisor=False)
|
||||
setup_redis()
|
||||
# setup_redis()
|
||||
setup_db_munin()
|
||||
|
||||
def setup_task():
|
||||
|
@ -531,6 +532,14 @@ def copy_certificates():
|
|||
run('mkdir -p %s/config/certificates/' % env.NEWSBLUR_PATH)
|
||||
put('config/certificates/comodo/newsblur.com.crt', '%s/config/certificates/' % env.NEWSBLUR_PATH)
|
||||
put('config/certificates/comodo/newsblur.com.key', '%s/config/certificates/' % env.NEWSBLUR_PATH)
|
||||
|
||||
def maintenance_on():
|
||||
with cd(env.NEWSBLUR_PATH):
|
||||
run('mv media/maintenance.html.unused media/maintenance.html')
|
||||
|
||||
def maintenance_off():
|
||||
with cd(env.NEWSBLUR_PATH):
|
||||
run('mv media/maintenance.html media/maintenance.html.unused')
|
||||
|
||||
# ==============
|
||||
# = Setup - DB =
|
||||
|
@ -566,17 +575,17 @@ def setup_memcached():
|
|||
sudo('apt-get -y install memcached')
|
||||
|
||||
def setup_postgres(standby=False):
|
||||
shmmax = 572506112
|
||||
# sudo('apt-get -y install postgresql postgresql-client postgresql-contrib libpq-dev')
|
||||
shmmax = 577060864
|
||||
sudo('apt-get -y install postgresql postgresql-client postgresql-contrib libpq-dev')
|
||||
put('config/postgresql%s.conf' % (
|
||||
('_standby' if standby else ''),
|
||||
), '/etc/postgresql/9.0/main/postgresql.conf', use_sudo=True)
|
||||
), '/etc/postgresql/9.1/main/postgresql.conf', use_sudo=True)
|
||||
sudo('echo "%s" > /proc/sys/kernel/shmmax' % shmmax)
|
||||
sudo('echo "\nkernel.shmmax = %s" > /etc/sysctl.conf' % shmmax)
|
||||
sudo('sysctl -p')
|
||||
|
||||
if standby:
|
||||
put('config/postgresql_recovery.conf', '/var/lib/postgresql/9.0/recovery.conf', use_sudo=True)
|
||||
put('config/postgresql_recovery.conf', '/var/lib/postgresql/9.1/recovery.conf', use_sudo=True)
|
||||
|
||||
sudo('/etc/init.d/postgresql stop')
|
||||
sudo('/etc/init.d/postgresql start')
|
||||
|
@ -587,9 +596,11 @@ def setup_mongo():
|
|||
sudo('echo "deb http://downloads-distro.mongodb.org/repo/debian-sysvinit dist 10gen" >> /etc/apt/sources.list')
|
||||
sudo('apt-get update')
|
||||
sudo('apt-get -y install mongodb-10gen')
|
||||
put('config/mongodb.prod.conf', '/etc/mongodb.conf', use_sudo=True)
|
||||
sudo('/etc/init.d/mongodb restart')
|
||||
|
||||
def setup_redis():
|
||||
redis_version = '2.4.13'
|
||||
redis_version = '2.4.15'
|
||||
with cd(env.VENDOR_PATH):
|
||||
run('wget http://redis.googlecode.com/files/redis-%s.tar.gz' % redis_version)
|
||||
run('tar -xzf redis-%s.tar.gz' % redis_version)
|
||||
|
|
|
@ -6,16 +6,16 @@ import pymongo
|
|||
# ===================
|
||||
|
||||
ADMINS = (
|
||||
('Samuel Clay', 'samuel@ofbrooklyn.com'),
|
||||
('Samuel Clay', 'samuel@newsblur.com'),
|
||||
)
|
||||
|
||||
SERVER_EMAIL = 'server@newsblur.com'
|
||||
HELLO_EMAIL = 'hello@newsblur.com'
|
||||
NEWSBLUR_URL = 'http://www.newsblur.com'
|
||||
|
||||
# ==================
|
||||
# = Global Settngs =
|
||||
# ==================
|
||||
# ===================
|
||||
# = Global Settings =
|
||||
# ===================
|
||||
|
||||
DEBUG = True
|
||||
DEBUG_ASSETS = DEBUG
|
||||
|
@ -29,7 +29,7 @@ CACHE_BACKEND = 'dummy:///'
|
|||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
|
||||
# Set this to the username that is shown on the homepage to unauthenticated users.
|
||||
HOMEPAGE_USERNAME = 'conesus'
|
||||
HOMEPAGE_USERNAME = 'popular'
|
||||
|
||||
# Google Reader OAuth API Keys
|
||||
OAUTH_KEY = 'www.example.com'
|
||||
|
@ -42,6 +42,15 @@ S3_BACKUP_BUCKET = 'newsblur_backups'
|
|||
STRIPE_SECRET = "YOUR-SECRET-API-KEY"
|
||||
STRIPE_PUBLISHABLE = "YOUR-PUBLISHABLE-API-KEY"
|
||||
|
||||
# ===============
|
||||
# = Social APIs =
|
||||
# ===============
|
||||
|
||||
FACEBOOK_APP_ID = '111111111111111'
|
||||
FACEBOOK_SECRET = '99999999999999999999999999999999'
|
||||
TWITTER_CONSUMER_KEY = 'ooooooooooooooooooooo'
|
||||
TWITTER_CONSUMER_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
||||
|
||||
# =============
|
||||
# = Databases =
|
||||
# =============
|
||||
|
@ -80,7 +89,6 @@ BROKER_USER = "newsblur"
|
|||
BROKER_PASSWORD = "newsblur"
|
||||
BROKER_VHOST = "newsblurvhost"
|
||||
|
||||
|
||||
# ===========
|
||||
# = Logging =
|
||||
# ===========
|
||||
|
@ -94,19 +102,4 @@ if len(logging._handlerList) < 1:
|
|||
format='%(asctime)-12s: %(message)s',
|
||||
datefmt='%b %d %H:%M:%S',
|
||||
handler=logging.StreamHandler)
|
||||
<<<<<<< HEAD
|
||||
|
||||
S3_ACCESS_KEY = 'XXX'
|
||||
S3_SECRET = 'SECRET'
|
||||
S3_BACKUP_BUCKET = 'newsblur_backups'
|
||||
|
||||
# ===============
|
||||
# = Social APIs =
|
||||
# ===============
|
||||
|
||||
FACEBOOK_APP_ID = '111111111111111'
|
||||
FACEBOOK_SECRET = '99999999999999999999999999999999'
|
||||
TWITTER_CONSUMER_KEY = 'ooooooooooooooooooooo'
|
||||
TWITTER_CONSUMER_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
||||
=======
|
||||
>>>>>>> jammit
|
||||
|
|
|
@ -378,11 +378,12 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
.NB-feedlists .NB-socialfeeds {
|
||||
border-bottom: 1px solid #A0A0A0;
|
||||
}
|
||||
..NB-feedlists .NB-socialfeeds .feed .feed_title {
|
||||
.NB-feedlists .NB-socialfeeds .feed .feed_title {
|
||||
text-shadow: 0 1px 0 #DAE2E8;
|
||||
}
|
||||
|
||||
|
||||
.NB-feedlists .NB-socialfeeds img.feed_favicon {
|
||||
border-radius: 3px;
|
||||
}
|
||||
/* ============= */
|
||||
/* = Feed List = */
|
||||
/* ============= */
|
||||
|
@ -494,6 +495,10 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
.NB-feedlist .feed.NB-feed-inactive {
|
||||
display: none;
|
||||
}
|
||||
.NB-feedlist .feed.NB-feed-self-blurblog,
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist .feed.NB-feed-self-blurblog {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.NB-feedlist .feed.NB-feed-unfetched {
|
||||
}
|
||||
|
@ -991,7 +996,9 @@ background: transparent;
|
|||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#story_titles .NB-feedbar .feed.NB-feed-social .feed_favicon {
|
||||
border-radius: 3px;
|
||||
}
|
||||
#story_titles .NB-feedbar .feed .feed_title {
|
||||
/* float: left;*/
|
||||
display: block;
|
||||
|
@ -1629,6 +1636,7 @@ background: transparent;
|
|||
z-index: 2;
|
||||
width: 100%;
|
||||
display: none;
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.NB-view-river .NB-feed-story-view-floater {
|
||||
|
@ -1728,7 +1736,6 @@ background: transparent;
|
|||
border-bottom: 1px solid #000;
|
||||
border-top: 1px solid #707070;
|
||||
z-index: 2;
|
||||
opacity: .9;
|
||||
}
|
||||
#story_pane .NB-feed-story-header-feed.NB-feed-story-river-same-feed {
|
||||
z-index: 0;
|
||||
|
@ -1770,8 +1777,12 @@ background: transparent;
|
|||
/* text-shadow: 0 1px 0 #E0E0E0;*/
|
||||
}
|
||||
|
||||
#story_pane .NB-feed-stories .NB-feed-story .NB-feed-story-content div {
|
||||
max-width: 100%;
|
||||
}
|
||||
#story_pane .NB-feed-stories .NB-feed-story img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
#story_pane .NB-feed-story {
|
||||
position: relative;
|
||||
|
@ -2216,10 +2227,6 @@ background: transparent;
|
|||
#story_pane .NB-story-comments-public-header-wrapper {
|
||||
cursor: default;
|
||||
}
|
||||
#story_pane .NB-story-comments-shares-teaser-wrapper {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
#story_pane .NB-story-comments-public-teaser,
|
||||
#story_pane .NB-story-comments-public-header {
|
||||
background-color: #B1B6B4;
|
||||
|
@ -2240,6 +2247,12 @@ background: transparent;
|
|||
color: #404040;
|
||||
text-shadow: 0 1px 0 white;
|
||||
}
|
||||
|
||||
#story_pane .NB-story-comments-shares-teaser-wrapper {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#story_pane .NB-story-comments-shares-teaser {
|
||||
background-color: whiteSmoke;
|
||||
color: #202020;
|
||||
|
@ -2322,6 +2335,11 @@ background: transparent;
|
|||
|
||||
#story_pane .NB-feed-stories.NB-feed-view-story .NB-feed-story {
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#story_pane .NB-feed-stories.NB-feed-view-story .NB-feed-story.NB-selected {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#story_pane .audiojs audio {
|
||||
|
@ -2414,12 +2432,35 @@ background: transparent;
|
|||
text-shadow: 0 1px 0 #F6F6F6;
|
||||
color: #202020;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-optional {
|
||||
text-transform: uppercase;
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost {
|
||||
margin-right: -4px;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter,
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook {
|
||||
float: right;
|
||||
color: #808080;
|
||||
font-size: 10px;
|
||||
text-shadow: 0 1px 0 #F6F6F6;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 0 0 6px;
|
||||
opacity: .4;
|
||||
cursor: pointer;
|
||||
-webkit-filter: grayscale(100%);
|
||||
display: none;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter:hover,
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook:hover {
|
||||
opacity: .7;
|
||||
-webkit-filter: none;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter.NB-active,
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook.NB-active {
|
||||
opacity: 1;
|
||||
-webkit-filter: none;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter {
|
||||
background: transparent url('/media/embed/reader/twitter_icon.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook {
|
||||
background: transparent url('/media/embed/reader/facebook_icon.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-comments {
|
||||
width: 100%;
|
||||
|
@ -2435,15 +2476,28 @@ background: transparent;
|
|||
width: 92%;
|
||||
background-color: #639510;
|
||||
cursor: pointer;
|
||||
-moz-box-shadow:2px 2px 0 #95AB76;
|
||||
-webkit-box-shadow:2px 2px 0 #95AB76;
|
||||
box-shadow:2px 2px 0 #95AB76;
|
||||
-moz-box-shadow: 2px 2px 0 #95AB76;
|
||||
-webkit-box-shadow: 2px 2px 0 #95AB76;
|
||||
box-shadow: 2px 2px 0 #95AB76;
|
||||
text-shadow: 0 1px 0 #101010;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-save.NB-saving {
|
||||
background-color: #b5b4bB;
|
||||
text-shadow: none;
|
||||
}
|
||||
.NB-sideoption-share .NB-sideoption-share-unshare {
|
||||
color: #404040;
|
||||
text-shadow: 0 1px 0 #E0E0E0;
|
||||
line-height: 1;
|
||||
font-size: 11px;
|
||||
padding: 2px 6px;
|
||||
margin: 6px 0;
|
||||
width: 92%;
|
||||
font-weight: normal;
|
||||
-moz-box-shadow: 1px 1px 0 #95AB76;
|
||||
-webkit-box-shadow: 1px 1px 0 #95AB76;
|
||||
box-shadow: 1px 1px 0 #95AB76;
|
||||
}
|
||||
.NB-sideoption-share .NB-error {
|
||||
font-size: 10px;
|
||||
color: #6A1000;
|
||||
|
@ -4995,6 +5049,14 @@ form.opml_import_form input {
|
|||
text-align: center;
|
||||
width: 95%;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-confirm .NB-menu-manage-story-share-unshare {
|
||||
width: 95%;
|
||||
text-align: center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-confirm .NB-sideoption-share-comments {
|
||||
height: 28px;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-confirm .NB-add-folders {
|
||||
float: left;
|
||||
}
|
||||
|
@ -5052,6 +5114,15 @@ form.opml_import_form input {
|
|||
.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-pinboard {
|
||||
background: transparent url('/media/embed/reader/pinboard.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-diigo {
|
||||
background: transparent url('/media/embed/reader/diigo.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-kippt {
|
||||
background: transparent url('/media/embed/reader/kippt.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-evernote {
|
||||
background: transparent url('/media/embed/reader/evernote.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty .NB-menu-manage-thirdparty-googleplus {
|
||||
background: transparent url('/media/embed/reader/googleplus.png') no-repeat 0 0;
|
||||
}
|
||||
|
@ -5110,6 +5181,27 @@ form.opml_import_form input {
|
|||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-pinboard .NB-menu-manage-thirdparty-pinboard {
|
||||
opacity: 1;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-diigo .NB-menu-manage-image,
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-diigo .NB-menu-manage-thirdparty-icon {
|
||||
opacity: .2;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-diigo .NB-menu-manage-thirdparty-diigo {
|
||||
opacity: 1;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-kippt .NB-menu-manage-image,
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-kippt .NB-menu-manage-thirdparty-icon {
|
||||
opacity: .2;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-kippt .NB-menu-manage-thirdparty-kippt {
|
||||
opacity: 1;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-evernote .NB-menu-manage-image,
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-evernote .NB-menu-manage-thirdparty-icon {
|
||||
opacity: .2;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-evernote .NB-menu-manage-thirdparty-evernote {
|
||||
opacity: 1;
|
||||
}
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-googleplus .NB-menu-manage-image,
|
||||
.NB-menu-manage .NB-menu-manage-story-thirdparty.NB-menu-manage-highlight-googleplus .NB-menu-manage-thirdparty-icon {
|
||||
opacity: .2;
|
||||
|
@ -6887,6 +6979,15 @@ form.opml_import_form input {
|
|||
.NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-pinboard] {
|
||||
background: transparent url('/media/embed/reader/pinboard.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-diigo] {
|
||||
background: transparent url('/media/embed/reader/diigo.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-kippt] {
|
||||
background: transparent url('/media/embed/reader/kippt.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-evernote] {
|
||||
background: transparent url('/media/embed/reader/evernote.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-modal-preferences .NB-preference-story-share label[for=NB-preference-story-share-googleplus] {
|
||||
background: transparent url('/media/embed/reader/googleplus.png') no-repeat 0 0;
|
||||
}
|
||||
|
@ -7173,7 +7274,6 @@ form.opml_import_form input {
|
|||
margin: 12px 0;
|
||||
}
|
||||
.NB-static-api table {
|
||||
width: 600px;
|
||||
border-spacing: 0 0;
|
||||
margin: 24px 0 12px 20px;
|
||||
background: transparent url('/media/embed/reader/static_bullet_white.png') no-repeat 0 0;
|
||||
|
@ -7192,7 +7292,6 @@ form.opml_import_form input {
|
|||
white-space: nowrap;
|
||||
/* border-bottom: 1px solid #F6F6f6;*/
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
.NB-static-api table td:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
@ -7443,7 +7542,6 @@ form.opml_import_form input {
|
|||
margin-bottom: 54px;
|
||||
}
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
/* ================= */
|
||||
/* = Friends Modal = */
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* ========== */
|
||||
/* = Global = */
|
||||
/* ========== */
|
||||
|
||||
body {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
|
@ -5,10 +9,31 @@ body {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.NB-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.NB-left {
|
||||
float: left;
|
||||
}
|
||||
.NB-right {
|
||||
float: right;
|
||||
}
|
||||
.NB-raquo {
|
||||
font-size: 18px;
|
||||
vertical-align: baseline;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
/* = Layout = */
|
||||
/* ========== */
|
||||
|
||||
.NB-page {
|
||||
background: #EBC55F url(/media/img/reader/background-control-light.png) repeat 0 0;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
/* = Header = */
|
||||
/* ========== */
|
||||
|
@ -16,7 +41,6 @@ body {
|
|||
header {
|
||||
padding: 64px 14px;
|
||||
text-shadow: 1px 1px 0 #E0E0E0;
|
||||
background-color: #EBC55F;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -128,6 +152,19 @@ header {
|
|||
.NB-title .NB-title-left {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ========= */
|
||||
/* = Story = */
|
||||
/* ========= */
|
||||
|
||||
.NB-mark {
|
||||
margin: 0 auto 36px;
|
||||
max-width: 800px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ===================== */
|
||||
/* = Story Feed Header = */
|
||||
/* ===================== */
|
||||
|
@ -201,7 +238,24 @@ header {
|
|||
#E9EAEF 10%,
|
||||
#F5F8FA 84%
|
||||
);
|
||||
border-top: 1px solid #C0C0C0;
|
||||
}
|
||||
|
||||
.NB-story-header-wrapper {
|
||||
border-bottom: 1px solid #D0D0D0;
|
||||
border-right: 1px solid #909090;
|
||||
border-left: 1px solid #909090;
|
||||
}
|
||||
|
||||
@media all and (max-width: 800px) {
|
||||
.NB-story-header {
|
||||
padding-right: 100px;
|
||||
}
|
||||
}
|
||||
@media all and (max-width: 600px) {
|
||||
.NB-story-header {
|
||||
padding-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.NB-story-title {
|
||||
|
@ -264,30 +318,370 @@ header {
|
|||
font-size: 7px;
|
||||
}
|
||||
|
||||
.NB-story-header .NB-story-modifications-button {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: transparent url('/media/embed/reader/code_icon.png') no-repeat 0 0;
|
||||
float: left;
|
||||
margin: 3px 12px 0px 0px;
|
||||
opacity: .6;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-story-header .NB-story-modifications-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* =========== */
|
||||
/* = Stories = */
|
||||
/* =========== */
|
||||
|
||||
.NB-divider {
|
||||
border-top: 1px solid #F6F6F6;
|
||||
border-bottom: 1px solid #E8E8E8;
|
||||
/* border-top: 1px solid #F6F6F6;*/
|
||||
/* border-bottom: 1px solid #E8E8E8;*/
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.NB-story {
|
||||
margin: 0 28px;
|
||||
padding: 12px 212px 24px 0;
|
||||
max-width: 700px;
|
||||
background-color: #FAFAFA;
|
||||
padding: 0 28px;
|
||||
max-width: 800px;
|
||||
border-right: 1px solid #909090;
|
||||
border-bottom: 1px solid #909090;
|
||||
border-left: 1px solid #909090;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.NB-story a {
|
||||
.NB-story-content {
|
||||
padding: 12px 200px 24px 0;
|
||||
}
|
||||
@media all and (max-width: 800px) {
|
||||
.NB-story-content {
|
||||
padding-right: 100px;
|
||||
}
|
||||
}
|
||||
@media all and (max-width: 700px) {
|
||||
.NB-story-content {
|
||||
padding-right: 50px;
|
||||
}
|
||||
}
|
||||
@media all and (max-width: 600px) {
|
||||
.NB-story-content {
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.NB-story-content a {
|
||||
color: #1F4499;
|
||||
}
|
||||
|
||||
.NB-story a:hover {
|
||||
.NB-story-content a:hover {
|
||||
color: #99481D;
|
||||
}
|
||||
|
||||
.NB-story img {
|
||||
.NB-story-content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.NB-story-content ins {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.NB-story-content del {
|
||||
display: none;
|
||||
}
|
||||
.NB-pref-show-changes .NB-story-content ins {
|
||||
text-decoration: underline;
|
||||
color: #27452D;
|
||||
}
|
||||
.NB-pref-show-changes .NB-story-content del {
|
||||
display: block;
|
||||
color: #661616;
|
||||
}
|
||||
|
||||
/* ======================= */
|
||||
/* = Shares and Comments = */
|
||||
/* ======================= */
|
||||
|
||||
.NB-story-comments a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.NB-story-comments a:hover {
|
||||
color: #99481D;
|
||||
}
|
||||
.NB-story-comments a img {
|
||||
border: none;
|
||||
}
|
||||
.NB-story-comments {
|
||||
margin: 0 0 32px 0;
|
||||
padding: 1px 0 0;
|
||||
max-width: 800px;
|
||||
border-top: 2px solid #353535;
|
||||
border-bottom: 1px solid #353535;
|
||||
font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
.NB-story-comment {
|
||||
border-top: 1px solid #A6A6A6;
|
||||
background-color: #FCFCFC;
|
||||
position: relative;
|
||||
padding: 0 12px 2px 54px;
|
||||
line-height: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.NB-story-comment .NB-user-avatar {
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
top: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-story-comment .NB-user-avatar.NB-story-comment-reshare {
|
||||
top: 22px;
|
||||
left: 6px;
|
||||
z-index: 1;
|
||||
}
|
||||
.NB-story-comment .NB-user-avatar img {
|
||||
border-radius: 6px;
|
||||
margin: 2px 0 0 1px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
.NB-story-comment .NB-user-avatar.NB-story-comment-reshare img {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-author-container {
|
||||
overflow: hidden;
|
||||
margin: 6px 0 0;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-reshares {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 8px;
|
||||
z-index: 0;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-reshares .NB-user-avatar {
|
||||
top: 8px;
|
||||
left: 12px;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-reshares .NB-user-avatar img {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-username {
|
||||
float: left;
|
||||
font-size: 11px;
|
||||
color: #1D4BA6;
|
||||
font-weight: bold;
|
||||
margin: 0 10px 0 0;
|
||||
text-shadow: 0 -1px 0 #F0F0F0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-date {
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
color: #9D9D9D;
|
||||
font-weight: bold;
|
||||
float: left;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-content {
|
||||
float: left;
|
||||
color: #303030;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-reply-button {
|
||||
padding: 4px 24px 4px 12px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-reply-button .NB-story-comment-reply-button-wrapper {
|
||||
text-transform: uppercase;
|
||||
background-color: #E9AF86;
|
||||
color: white;
|
||||
padding: 1px 4px;
|
||||
line-height: 9px;
|
||||
font-size: 9px;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-reply-button:hover .NB-story-comment-reply-button-wrapper {
|
||||
background-color: #DE772B;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-reply-button:active .NB-story-comment-reply-button-wrapper {
|
||||
background-color: #9F3A00;
|
||||
}
|
||||
|
||||
.NB-story-comment-reply {
|
||||
border-top: 1px solid #E0E0E0;
|
||||
padding: 4px 0;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
position: relative;
|
||||
padding: 6px 0 6px 32px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.NB-story-comment-reply .NB-story-comment-reply-photo {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 3px;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.NB-story-comment-edit-button {
|
||||
padding: 4px 24px 4px 12px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-story-comment-edit-button .NB-story-comment-edit-button-wrapper {
|
||||
text-transform: uppercase;
|
||||
background-color: #74A2E7;
|
||||
color: white;
|
||||
padding: 1px 4px;
|
||||
line-height: 9px;
|
||||
font-size: 9px;
|
||||
}
|
||||
.NB-story-comment-edit-button:hover .NB-story-comment-edit-button-wrapper {
|
||||
background-color: #5073BC;
|
||||
}
|
||||
.NB-story-comment-edit-button:active .NB-story-comment-edit-button-wrapper {
|
||||
background-color: #2A3B72;
|
||||
}
|
||||
.NB-story-comment-share-edit-button {
|
||||
padding-right: 0;
|
||||
}
|
||||
.NB-story-comment-reply-content {
|
||||
clear: both;
|
||||
color: #303030;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.NB-story-comment-reply-form {
|
||||
padding-top: 11px;
|
||||
}
|
||||
.NB-story-comment-reply-form .NB-story-comment-reply-username {
|
||||
margin: 1px 8px 6px 0;
|
||||
}
|
||||
.NB-story-comment-reply-form .NB-story-comment-reply-comments {
|
||||
margin: 0 8px 4px 0;
|
||||
width: 62%;
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
}
|
||||
.NB-story-comment-reply-form .NB-modal-submit-button {
|
||||
float: left;
|
||||
font-size: 10px;
|
||||
padding: 2px 8px;
|
||||
line-height: 16px;
|
||||
margin: 0;
|
||||
}
|
||||
.NB-story-comment-reply-form .NB-error {
|
||||
font-size: 10px;
|
||||
color: #6A1000;
|
||||
padding: 4px 0 0;
|
||||
line-height: 14px;
|
||||
font-weight: bold;
|
||||
clear: both;
|
||||
}
|
||||
.NB-story-comments-public-teaser-wrapper,
|
||||
.NB-story-comments-public-header-wrapper {
|
||||
border-top: 1px solid #353535;
|
||||
padding: 1px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-story-comments-public-header-wrapper {
|
||||
cursor: default;
|
||||
}
|
||||
.NB-story-comments-public-teaser,
|
||||
.NB-story-comments-public-header {
|
||||
background-color: #B1B6B4;
|
||||
color: white;
|
||||
text-shadow: 0 1px 0 #505050;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
padding: 2px 12px;
|
||||
overflow: hidden;
|
||||
-webkit-transition: all .12s ease-out;
|
||||
-moz-transition: all .12s ease-out;
|
||||
-o-transition: all .12s ease-out;
|
||||
-ms-transition: all .12s ease-out;
|
||||
}
|
||||
.NB-story-comments-public-header {
|
||||
background-color: whiteSmoke;
|
||||
color: #404040;
|
||||
text-shadow: 0 1px 0 white;
|
||||
}
|
||||
.NB-story-comments-shares-teaser-wrapper {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.NB-story-comments-shares-teaser {
|
||||
background-color: whiteSmoke;
|
||||
color: #202020;
|
||||
cursor: default;
|
||||
text-shadow: 0 1px 0 #FFF;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
padding: 8px 12px 0px;
|
||||
overflow: hidden;
|
||||
height: 27px;
|
||||
-webkit-transition: all .12s ease-out;
|
||||
-moz-transition: all .12s ease-out;
|
||||
-o-transition: all .12s ease-out;
|
||||
-ms-transition: all .12s ease-out;
|
||||
}
|
||||
|
||||
.NB-story-comments-public-teaser-wrapper:hover .NB-story-comments-public-teaser {
|
||||
background-color: #2B478C;
|
||||
background-image: none;
|
||||
}
|
||||
.NB-story-comments-public-teaser b {
|
||||
padding: 0 1px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.NB-story-share-label {
|
||||
display: inline-block;
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
.NB-story-share-profiles {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
height: 24px;
|
||||
padding-top: 2px;
|
||||
margin-top: -4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.NB-story-share-profiles.NB-story-share-profiles-public {
|
||||
float: right;
|
||||
}
|
||||
.NB-story-share-profiles.NB-story-share-profiles-public .NB-story-share-profile {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.NB-story-share-profiles {
|
||||
display: inline-block;
|
||||
}
|
||||
.NB-story-share-profiles .NB-user-avatar {
|
||||
float: left;
|
||||
font-size: 0;
|
||||
vertical-align: middle;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
margin: 0 4px 0 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.NB-story-share-profiles .NB-user-avatar img {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.NB-story-share-profiles .NB-user-username {
|
||||
float: left;
|
||||
}
|
||||
.NB-story-comment .NB-story-comment-content {
|
||||
clear: both;
|
||||
padding: 0 0 6px 0;
|
||||
}
|
BIN
media/img/mobile/SidebarAllMyFiles.icns
Normal file
BIN
media/img/mobile/SidebarLaptop.icns
Normal file
BIN
media/img/mobile/SidebariMac.icns
Normal file
BIN
media/img/mobile/SidebariPad.icns
Normal file
BIN
media/img/mobile/SidebariPhone.icns
Normal file
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
media/img/reader/diigo.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
media/img/reader/evernote.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
media/img/reader/kippt.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
|
@ -19,6 +19,7 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
|||
this.friends = {};
|
||||
this.profile = {};
|
||||
this.user_profile = new NEWSBLUR.Models.User();
|
||||
this.social_services = {};
|
||||
this.user_profiles = new NEWSBLUR.Collections.Users();
|
||||
this.follower_profiles = new NEWSBLUR.Collections.Users();
|
||||
this.following_profiles = new NEWSBLUR.Collections.Users();
|
||||
|
@ -216,7 +217,8 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
|||
}, callback);
|
||||
},
|
||||
|
||||
mark_story_as_shared: function(story_id, feed_id, comments, source_user_id, callback, error_callback) {
|
||||
mark_story_as_shared: function(story_id, feed_id, comments, source_user_id, post_to_services,
|
||||
callback, error_callback) {
|
||||
var pre_callback = _.bind(function(data) {
|
||||
if (data.user_profiles) {
|
||||
this.add_user_profiles(data.user_profiles);
|
||||
|
@ -231,7 +233,28 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
|||
story_id: story_id,
|
||||
feed_id: feed_id,
|
||||
comments: comments,
|
||||
source_user_id: source_user_id
|
||||
source_user_id: source_user_id,
|
||||
post_to_services: post_to_services
|
||||
}, pre_callback, error_callback);
|
||||
} else {
|
||||
error_callback();
|
||||
}
|
||||
},
|
||||
|
||||
mark_story_as_unshared: function(story_id, feed_id, callback, error_callback) {
|
||||
var pre_callback = _.bind(function(data) {
|
||||
if (data.user_profiles) {
|
||||
this.add_user_profiles(data.user_profiles);
|
||||
}
|
||||
var story = this.get_story(story_id);
|
||||
story.set(data.story);
|
||||
callback(data);
|
||||
}, this);
|
||||
|
||||
if (NEWSBLUR.Globals.is_authenticated) {
|
||||
this.make_request('/social/unshare_story', {
|
||||
story_id: story_id,
|
||||
feed_id: feed_id
|
||||
}, pre_callback, error_callback);
|
||||
} else {
|
||||
error_callback();
|
||||
|
@ -272,6 +295,7 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
|||
self.starred_count = subscriptions.starred_count;
|
||||
self.social_feeds.reset(subscriptions.social_feeds);
|
||||
self.user_profile.set(subscriptions.social_profile);
|
||||
self.social_services = subscriptions.social_services;
|
||||
|
||||
if (!_.isEqual(self.favicons, {})) {
|
||||
self.feeds.each(function(feed) {
|
||||
|
@ -431,7 +455,18 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
|||
if (first_load || !page) this.read_stories_river_count = 0;
|
||||
|
||||
var pre_callback = function(data) {
|
||||
return self.load_feed_precallback(data, feed_id, callback, first_load);
|
||||
self.load_feed_precallback(data, feed_id, callback, first_load);
|
||||
|
||||
if (NEWSBLUR.reader.flags['non_premium_river_view']) {
|
||||
var visible_stories = self.stories.visible().length;
|
||||
var max_stories = NEWSBLUR.reader.constants.RIVER_STORIES_FOR_STANDARD_ACCOUNT;
|
||||
console.log(["checking no more stories", visible_stories, max_stories]);
|
||||
if (visible_stories >= max_stories) {
|
||||
self.flags['no_more_stories'] = true;
|
||||
self.stories.trigger('no_more_stories');
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.feed_id = feed_id;
|
||||
|
@ -606,6 +641,12 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
|||
return counts;
|
||||
},
|
||||
|
||||
unfetched_feeds: function() {
|
||||
return this.feeds.filter(function(feed) {
|
||||
return feed.get('active') && !feed.get('fetched_once') && !feed.get('has_exception');
|
||||
});
|
||||
},
|
||||
|
||||
set_feed: function(feed_id, feed) {
|
||||
if (!feed) {
|
||||
feed = feed_id;
|
||||
|
|
|
@ -25,9 +25,8 @@ NEWSBLUR.Models.Feed = Backbone.Model.extend({
|
|||
delete_feed: function(options) {
|
||||
options = options || {};
|
||||
var view = options.view || this.get_view();
|
||||
console.log(["Delete Feed", this, view, view.collection && view.collection.options.title]);
|
||||
|
||||
NEWSBLUR.assets.delete_feed(this.id, view.collection && view.collection.options.title);
|
||||
NEWSBLUR.assets.delete_feed(this.id, view.options.folder_title);
|
||||
view.delete_feed();
|
||||
},
|
||||
|
||||
|
|
|
@ -174,7 +174,6 @@ NEWSBLUR.Collections.Folders = Backbone.Collection.extend({
|
|||
comparator: function(modelA, modelB) {
|
||||
var sort_order = NEWSBLUR.assets.preference('feed_order');
|
||||
|
||||
|
||||
if (modelA.is_feed() != modelB.is_feed()) {
|
||||
// Feeds above folders
|
||||
return modelA.is_feed() ? -1 : 1;
|
||||
|
@ -187,6 +186,11 @@ NEWSBLUR.Collections.Folders = Backbone.Collection.extend({
|
|||
var feedA = modelA.feed;
|
||||
var feedB = modelB.feed;
|
||||
|
||||
if (!feedA || !feedB) {
|
||||
// console.log(["missing feed", feedA, feedB, modelA, modelB]);
|
||||
return !feedA ? 1 : -1;
|
||||
}
|
||||
|
||||
if (sort_order == 'ALPHABETICAL' || !sort_order) {
|
||||
return feedA.get('feed_title').toLowerCase() > feedB.get('feed_title').toLowerCase() ? 1 : -1;
|
||||
} else if (sort_order == 'MOSTUSED') {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
NEWSBLUR.Models.Story = Backbone.Model.extend({
|
||||
|
||||
initialize: function() {
|
||||
this.bind('change:selected', this.change_selected);
|
||||
this.bind('change:comments', this.populate_comments);
|
||||
this.bind('change:comment_count', this.populate_comments);
|
||||
this.populate_comments();
|
||||
|
@ -44,6 +45,10 @@ NEWSBLUR.Models.Story = Backbone.Model.extend({
|
|||
|
||||
mark_read: function(options) {
|
||||
return NEWSBLUR.assets.stories.mark_read(this, options);
|
||||
},
|
||||
|
||||
change_selected: function(model, selected, changes) {
|
||||
model.collection.detect_selected_story(model, selected);
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -59,7 +64,7 @@ NEWSBLUR.Collections.Stories = Backbone.Collection.extend({
|
|||
active_story: null,
|
||||
|
||||
initialize: function() {
|
||||
this.bind('change:selected', this.detect_selected_story, this);
|
||||
// this.bind('change:selected', this.detect_selected_story, this);
|
||||
this.bind('reset', this.clear_previous_stories_stack, this);
|
||||
},
|
||||
|
||||
|
@ -86,11 +91,10 @@ NEWSBLUR.Collections.Stories = Backbone.Collection.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
this.last_read_story_id = story.id;
|
||||
clearTimeout(this.read_story_delay);
|
||||
|
||||
this.read_story_delay = _.delay(_.bind(function() {
|
||||
if (delay || this.last_read_story_id == story.id || delay == 0) {
|
||||
if (!delay || (delay && this.active_story.id == story.id)) {
|
||||
var mark_read_fn = NEWSBLUR.assets.mark_story_as_read;
|
||||
var feed = NEWSBLUR.assets.get_feed(NEWSBLUR.reader.active_feed);
|
||||
if (!feed) {
|
||||
|
@ -246,7 +250,6 @@ NEWSBLUR.Collections.Stories = Backbone.Collection.extend({
|
|||
get_next_unread_story: function(options) {
|
||||
options = options || {};
|
||||
var visible_stories = this.visible_and_unread(options.score, true);
|
||||
console.log(["visible and unread", visible_stories, this, options.score]);
|
||||
if (!visible_stories.length) return;
|
||||
|
||||
if (!this.active_story) {
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
$feedbar: $('.NB-feedbar')
|
||||
};
|
||||
this.flags = {
|
||||
'feed_view_images_loaded': {},
|
||||
'bouncing_callout': false,
|
||||
'has_unfetched_feeds': false,
|
||||
'count_unreads_after_import_working': false,
|
||||
|
@ -51,7 +50,6 @@
|
|||
'fetched_feeds': 0,
|
||||
'page_fill_outs': 0,
|
||||
'recommended_feed_page': 0,
|
||||
'feed_view_positions_timer': 0,
|
||||
'interactions_page': 1,
|
||||
'activities_page': 1
|
||||
};
|
||||
|
@ -61,7 +59,6 @@
|
|||
'iframe_story_positions_keys': [],
|
||||
'feed_view_story_positions_keys': [],
|
||||
'river_feeds_with_unreads': [],
|
||||
'mouse_position_y': parseInt(this.model.preference('lock_mouse_indicator'), 10),
|
||||
'$feed_in_social_feed_list': {}
|
||||
};
|
||||
this.views = {};
|
||||
|
@ -69,7 +66,7 @@
|
|||
this.constants = {
|
||||
FEED_REFRESH_INTERVAL: (1000 * 60) * 1, // 1 minute
|
||||
FILL_OUT_PAGES: 50,
|
||||
RIVER_STORIES_FOR_STANDARD_ACCOUNT: 12
|
||||
RIVER_STORIES_FOR_STANDARD_ACCOUNT: 5
|
||||
};
|
||||
|
||||
// ==================
|
||||
|
@ -120,6 +117,7 @@
|
|||
this.setup_howitworks_hovers();
|
||||
this.setup_interactions_module();
|
||||
this.setup_activities_module();
|
||||
this.setup_unfetched_feed_check();
|
||||
},
|
||||
|
||||
// ========
|
||||
|
@ -149,18 +147,20 @@
|
|||
flag = 'story';
|
||||
}
|
||||
|
||||
this.counts['feed_view_positions_timer'] = 0;
|
||||
this.flags.scrolling_by_selecting_story_title = true;
|
||||
clearTimeout(this.locks.scrolling);
|
||||
this.locks.scrolling = _.delay(_.bind(function() {
|
||||
this.flags.scrolling_by_selecting_story_title = false;
|
||||
}, this), 1000);
|
||||
this.make_content_pane_feed_counter();
|
||||
|
||||
this.switch_taskbar_view(view, flag);
|
||||
NEWSBLUR.app.story_titles.fill_out();
|
||||
// this.flags.fetch_story_locations_in_feed_view = this.flags.fetch_story_locations_in_feed_view ||
|
||||
// _.throttle(_.bind(this.fetch_story_locations_in_feed_view, this), 2000);
|
||||
// this.flags.fetch_story_locations_in_feed_view();
|
||||
this.flags.fetch_story_locations_in_feed_view = this.flags.fetch_story_locations_in_feed_view ||
|
||||
_.throttle(function() {
|
||||
NEWSBLUR.app.story_list.reset_story_positions();
|
||||
}, 2000);
|
||||
this.flags.fetch_story_locations_in_feed_view();
|
||||
},
|
||||
|
||||
apply_resizable_layout: function(refresh) {
|
||||
|
@ -439,8 +439,14 @@
|
|||
}
|
||||
},
|
||||
|
||||
blur_to_page: function() {
|
||||
$(':focus').blur();
|
||||
blur_to_page: function(options) {
|
||||
options = options || {};
|
||||
|
||||
if (options.manage_menu) {
|
||||
$('.NB-menu-manage :focus').blur();
|
||||
} else {
|
||||
$(':focus').blur();
|
||||
}
|
||||
},
|
||||
|
||||
// ==============
|
||||
|
@ -625,10 +631,16 @@
|
|||
dir = '-';
|
||||
}
|
||||
// NEWSBLUR.log(['page_in_story', this.$s.$story_pane, direction, page_height, scroll_height]);
|
||||
if (this.story_view == 'page') {
|
||||
this.$s.$feed_iframe.scrollTo({top:dir+'='+scroll_height, left:'+=0'}, 230, {queue: false});
|
||||
} else if (this.story_view == 'feed') {
|
||||
this.$s.$feed_stories.scrollTo({top:dir+'='+scroll_height, left:'+=0'}, 230, {queue: false});
|
||||
if (this.story_view == 'page' && !this.flags['page_view_showing_feed_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']) {
|
||||
this.$s.$feed_stories.scrollTo({
|
||||
top: dir+'='+scroll_height,
|
||||
left:'+=0'
|
||||
}, 230, {queue: false});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -859,11 +871,6 @@
|
|||
|
||||
reset_feed: function() {
|
||||
$.extend(this.flags, {
|
||||
'iframe_story_locations_fetched': false,
|
||||
'iframe_view_loaded': false,
|
||||
'iframe_view_not_busting': false,
|
||||
'feed_view_images_loaded': {},
|
||||
'feed_view_positions_calculated': false,
|
||||
'scrolling_by_selecting_story_title': false,
|
||||
'page_view_showing_feed_view': false,
|
||||
'feed_view_showing_story_view': false,
|
||||
|
@ -886,11 +893,9 @@
|
|||
'iframe_story_positions_keys': [],
|
||||
'feed_view_story_positions_keys': [],
|
||||
'river_feeds_with_unreads': [],
|
||||
'mouse_position_y': parseInt(this.model.preference('lock_mouse_indicator'), 10),
|
||||
'prefetch_last_story': 0,
|
||||
'prefetch_iteration': 0,
|
||||
'feed_title_floater_story_id': null,
|
||||
'last_read_story_id': null,
|
||||
'$feed_in_social_feed_list': {}
|
||||
});
|
||||
|
||||
|
@ -918,9 +923,7 @@
|
|||
$('.task_view_page', this.$s.$taskbar).removeClass('NB-disabled');
|
||||
$('.task_view_story', this.$s.$taskbar).removeClass('NB-disabled');
|
||||
$('.task_view_page', this.$s.$taskbar).removeClass('NB-task-return');
|
||||
// $('.feed_counts_floater').remove();
|
||||
clearTimeout(this.flags['next_fetch']);
|
||||
this.counts['feed_view_positions_timer'] = 0;
|
||||
|
||||
if (this.flags['showing_feed_in_tryfeed_view'] || this.flags['showing_social_feed_in_tryfeed_view']) {
|
||||
this.hide_tryfeed_view();
|
||||
|
@ -1017,15 +1020,9 @@
|
|||
|
||||
// NEWSBLUR.log(['post_open_feed', data.stories, this.flags]);
|
||||
this.flags['opening_feed'] = false;
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
this.counts['feed_view_positions_timer'] = 0;
|
||||
// this.create_story_titles(stories);
|
||||
// this.make_story_feed_entries(stories, first_load);
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
this.show_feed_hidden_story_title_indicator(true);
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
// this.scroll_story_titles_to_show_selected_story_title();
|
||||
// this.fill_out_story_titles();
|
||||
if (this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
this.show_next_unread_story(true);
|
||||
} else if (this.counts['find_last_unread_on_page_of_feed_stories_load']) {
|
||||
|
@ -1034,27 +1031,9 @@
|
|||
this.select_story_in_feed();
|
||||
}
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
if (!first_load) {
|
||||
var stories_count = this.cache['iframe_story_positions_keys'].length;
|
||||
this.flags['iframe_story_locations_fetched'] = false;
|
||||
NEWSBLUR.app.original_tab_view.fetch_story_locations_in_story_frame();
|
||||
if (this.story_view == 'feed' || this.flags['page_view_showing_feed_view']) {
|
||||
// this.prefetch_story_locations_in_feed_view();
|
||||
}
|
||||
} else {
|
||||
if (this.story_view == 'page') {
|
||||
if (this.flags['iframe_view_loaded']) {
|
||||
NEWSBLUR.log(['Titles loaded, iframe loaded']);
|
||||
NEWSBLUR.app.original_tab_view.fetch_story_locations_in_story_frame();
|
||||
} else {
|
||||
NEWSBLUR.log(['Titles loaded, iframe NOT loaded -- prefetching now']);
|
||||
_.delay(_.bind(function() {
|
||||
NEWSBLUR.app.original_tab_view.prefetch_story_locations_in_story_frame();
|
||||
}, this), 250);
|
||||
}
|
||||
} else if (this.story_view == 'feed') {
|
||||
// this.prefetch_story_locations_in_feed_view();
|
||||
} else if (this.story_view == 'story' && !this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
if (first_load) {
|
||||
if (this.story_view == 'story' &&
|
||||
!this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
this.show_next_story(1);
|
||||
}
|
||||
|
||||
|
@ -1070,6 +1049,7 @@
|
|||
set_correct_story_view_for_feed: function(feed_id, view) {
|
||||
var feed = this.model.get_feed(feed_id);
|
||||
var $original_tabs = $('.task_view_page, .task_view_story');
|
||||
var $page_tab = $('.task_view_page');
|
||||
view = view || this.model.view_setting(feed_id);
|
||||
|
||||
if (feed && feed.get('disabled_page')) {
|
||||
|
@ -1098,7 +1078,11 @@
|
|||
$(this).tipsy('disable');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (feed_id == 'starred') {
|
||||
$page_tab.addClass('NB-disabled-page').addClass('NB-disabled');
|
||||
}
|
||||
|
||||
this.story_view = view;
|
||||
},
|
||||
|
||||
|
@ -1139,7 +1123,7 @@
|
|||
this.flags.river_view = true;
|
||||
$('.task_view_page', this.$s.$taskbar).addClass('NB-disabled');
|
||||
var explicit_view_setting = this.model.view_setting(this.active_feed);
|
||||
if (!explicit_view_setting) {
|
||||
if (!explicit_view_setting || explicit_view_setting == 'page') {
|
||||
explicit_view_setting = 'feed';
|
||||
}
|
||||
this.set_correct_story_view_for_feed(this.active_feed, explicit_view_setting);
|
||||
|
@ -1154,19 +1138,12 @@
|
|||
if (this.active_feed == 'starred') {
|
||||
// NEWSBLUR.log(['post_open_starred_stories', data.stories.length, first_load]);
|
||||
this.flags['opening_feed'] = false;
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
this.counts['feed_view_positions_timer'] = 0;
|
||||
// this.create_story_titles(data.stories, {'river_stories': true});
|
||||
// this.make_story_feed_entries(data.stories, first_load, {'river_stories': true});
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
if (this.counts['select_story_in_feed'] || this.flags['select_story_in_feed']) {
|
||||
this.select_story_in_feed();
|
||||
}
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
// this.prefetch_story_locations_in_feed_view();
|
||||
// this.scroll_story_titles_to_show_selected_story_title();
|
||||
// this.fill_out_story_titles();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1229,10 +1206,6 @@
|
|||
this.flags['non_premium_river_view'] = true;
|
||||
}
|
||||
this.flags['opening_feed'] = false;
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
this.counts['feed_view_positions_timer'] = 0;
|
||||
// this.create_story_titles(data.stories, {'river_stories': true});
|
||||
// this.make_story_feed_entries(data.stories, first_load, {'river_stories': true});
|
||||
this.show_feed_hidden_story_title_indicator(true);
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
|
@ -1244,9 +1217,6 @@
|
|||
} else if (this.counts['select_story_in_feed'] || this.flags['select_story_in_feed']) {
|
||||
this.select_story_in_feed();
|
||||
}
|
||||
// this.scroll_story_titles_to_show_selected_story_title();
|
||||
// this.fill_out_story_titles();
|
||||
// this.prefetch_story_locations_in_feed_view();
|
||||
this.hide_stories_progress_bar();
|
||||
}
|
||||
},
|
||||
|
@ -1306,13 +1276,14 @@
|
|||
|
||||
this.iframe_scroll = null;
|
||||
this.flags['opening_feed'] = true;
|
||||
feed.set('selected', true);
|
||||
feed.set('selected', true, options);
|
||||
this.make_feed_title_in_stories(feed.id);
|
||||
this.$s.$body.addClass('NB-view-river');
|
||||
this.flags.social_view = true;
|
||||
|
||||
var explicit_view_setting = this.model.view_setting(this.active_feed);
|
||||
this.set_correct_story_view_for_feed(this.active_feed, explicit_view_setting);
|
||||
this.set_correct_story_view_for_feed(this.active_feed);
|
||||
|
||||
// TODO: Only make feed the default for blurblogs, not overriding an explicit pref.
|
||||
this.switch_taskbar_view('feed');
|
||||
this.setup_mousemove_on_views();
|
||||
|
||||
|
@ -1323,18 +1294,24 @@
|
|||
|
||||
if (this.story_view == 'page') {
|
||||
_.delay(_.bind(function() {
|
||||
if (!options.delay || feed_id == this.next_feed) {
|
||||
if (!options.delay || feed.id == this.next_feed) {
|
||||
NEWSBLUR.app.original_tab_view.load_feed_iframe();
|
||||
}
|
||||
}, this), options.delay || 0);
|
||||
} else {
|
||||
this.flags['iframe_prevented_from_loading'] = true;
|
||||
}
|
||||
|
||||
if (!options.silent && feed.get('feed_title')) {
|
||||
var slug = _.string.words(_.string.clean(feed.get('feed_title').replace(/[^a-z0-9\. ]/ig, ''))).join('-').toLowerCase();
|
||||
var url = "social/" + feed.get('user_id') + "/" + slug;
|
||||
if (!_.string.include(window.location.pathname, url)) {
|
||||
var params = {};
|
||||
if (_.string.include(window.location.pathname, "social/" + feed.get('user_id'))) {
|
||||
params['replace'] = true;
|
||||
}
|
||||
// console.log(["Navigating to social", url, window.location.pathname]);
|
||||
NEWSBLUR.router.navigate(url);
|
||||
NEWSBLUR.router.navigate(url, params);
|
||||
}
|
||||
} else if (!feed.get('feed_title')) {
|
||||
console.log(["No feed title on social", feed]);
|
||||
|
@ -1350,10 +1327,6 @@
|
|||
|
||||
if (this.active_feed && NEWSBLUR.utils.is_feed_social(this.active_feed)) {
|
||||
this.flags['opening_feed'] = false;
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
this.counts['feed_view_positions_timer'] = 0;
|
||||
// this.create_story_titles(data.stories, {'river_stories': true});
|
||||
// this.make_story_feed_entries(data.stories, first_load, {'river_stories': true});
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
this.show_feed_hidden_story_title_indicator(true);
|
||||
|
@ -1365,9 +1338,6 @@
|
|||
} else if (this.counts['find_last_unread_on_page_of_feed_stories_load']) {
|
||||
this.show_last_unread_story(true);
|
||||
}
|
||||
// this.scroll_story_titles_to_show_selected_story_title();
|
||||
// this.fill_out_story_titles();
|
||||
// this.prefetch_story_locations_in_feed_view();
|
||||
this.hide_stories_progress_bar();
|
||||
|
||||
if (this.flags['showing_social_feed_in_tryfeed_view']) {
|
||||
|
@ -1443,7 +1413,7 @@
|
|||
console.log(["show_stories_error", arguments]);
|
||||
this.hide_stories_progress_bar();
|
||||
|
||||
this.flags['iframe_view_not_busting'] = true;
|
||||
NEWSBLUR.app.original_tab_view.iframe_not_busting();
|
||||
this.model.flags['no_more_stories'] = true;
|
||||
|
||||
var $error = $.make('div', { className: 'NB-feed-error' }, [
|
||||
|
@ -1478,36 +1448,6 @@
|
|||
// = Story Pane - All Views =
|
||||
// ==========================
|
||||
|
||||
// open_story: function(story, $story_title, options) {
|
||||
// var self = this;
|
||||
// var feed_position;
|
||||
// var iframe_position;
|
||||
// options = options || {};
|
||||
// // NEWSBLUR.log(['open_story', this.story_view, story, options]);
|
||||
//
|
||||
// if (this.active_story != story || options.story_id) {
|
||||
// if (this.story_view == 'page') {
|
||||
// var $iframe_story = this.find_story_in_feed_iframe(story);
|
||||
// if (!$iframe_story || !$iframe_story.length || !this.flags['story_titles_loaded']) {
|
||||
// // If the iframe has not yet loaded, we can't touch it.
|
||||
// // So just assume story not found.
|
||||
// this.switch_to_correct_view(false);
|
||||
// feed_position = this.scroll_to_story_in_story_feed(story, $feed_story, options);
|
||||
// NEWSBLUR.app.story_list.show_stories_preference_in_feed_view(true);
|
||||
// } else {
|
||||
// iframe_position = this.scroll_to_story_in_iframe(story, $iframe_story);
|
||||
// this.switch_to_correct_view(iframe_position);
|
||||
// }
|
||||
// } else if (this.story_view == 'feed') {
|
||||
// this.switch_to_correct_view();
|
||||
// feed_position = this.scroll_to_story_in_story_feed(story, $feed_story, options);
|
||||
// NEWSBLUR.app.story_list.show_stories_preference_in_feed_view(true);
|
||||
// } else if (this.story_view == 'story') {
|
||||
// this.open_story_in_story_view(story);
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
|
||||
switch_to_correct_view: function(found_story_in_page) {
|
||||
// NEWSBLUR.log(['Found story', this.story_view, found_story_in_page, this.flags['page_view_showing_feed_view'], this.flags['feed_view_showing_story_view']]);
|
||||
if (found_story_in_page === false) {
|
||||
|
@ -1704,6 +1644,54 @@
|
|||
NEWSBLUR.assets.stories.mark_read(story, {skip_delay: true});
|
||||
},
|
||||
|
||||
send_story_to_diigo: function(story_id) {
|
||||
var story = this.model.get_story(story_id);
|
||||
var url = 'http://www.diigo.com/post?';
|
||||
var url = [
|
||||
url,
|
||||
'url=',
|
||||
encodeURIComponent(story.get('story_permalink')),
|
||||
'&title=',
|
||||
encodeURIComponent(story.get('story_title')),
|
||||
'&tags=',
|
||||
encodeURIComponent(story.get('story_tags').join(', '))
|
||||
].join('');
|
||||
window.open(url, '_blank');
|
||||
NEWSBLUR.assets.stories.mark_read(story, {skip_delay: true});
|
||||
},
|
||||
|
||||
send_story_to_kippt: function(story_id) {
|
||||
var story = this.model.get_story(story_id);
|
||||
var url = 'https://kippt.com/extensions/new/?';
|
||||
var url = [
|
||||
url,
|
||||
'url=',
|
||||
encodeURIComponent(story.get('story_permalink')),
|
||||
'&title=',
|
||||
encodeURIComponent(story.get('story_title')),
|
||||
'&tags=',
|
||||
encodeURIComponent(story.get('story_tags').join(', '))
|
||||
].join('');
|
||||
window.open(url, '_blank');
|
||||
NEWSBLUR.assets.stories.mark_read(story, {skip_delay: true});
|
||||
},
|
||||
|
||||
send_story_to_evernote: function(story_id) {
|
||||
var story = this.model.get_story(story_id);
|
||||
var url = 'https://www.evernote.com/clip.action?';
|
||||
var url = [
|
||||
url,
|
||||
'url=',
|
||||
encodeURIComponent(story.get('story_permalink')),
|
||||
'&title=',
|
||||
encodeURIComponent(story.get('story_title')),
|
||||
'&tags=',
|
||||
encodeURIComponent(story.get('story_tags').join(', '))
|
||||
].join('');
|
||||
window.open(url, '_blank');
|
||||
NEWSBLUR.assets.stories.mark_read(story, {skip_delay: true});
|
||||
},
|
||||
|
||||
send_story_to_googleplus: function(story_id) {
|
||||
var story = this.model.get_story(story_id);
|
||||
var url = 'https://plusone.google.com/_/+1/confirm'; //?hl=en&url=${url}
|
||||
|
@ -2005,53 +1993,6 @@
|
|||
// = Story Pane - Feed View =
|
||||
// ==========================
|
||||
|
||||
make_story_feed_entries: function(stories, first_load, options) {
|
||||
var $feed_view = this.$s.$feed_view;
|
||||
var $stories = this.$s.$feed_stories;
|
||||
var self = this;
|
||||
var unread_view = this.get_unread_view_score();
|
||||
var river_same_feed;
|
||||
var feed = this.model.get_feed(this.active_feed);
|
||||
|
||||
options = options || {};
|
||||
|
||||
if (first_load && !options.refresh_load) {
|
||||
$('.NB-feed-story-endbar', $feed_view).remove();
|
||||
}
|
||||
|
||||
for (var s in stories) {
|
||||
// REMOVED
|
||||
|
||||
var image_count = $('img', $story).length;
|
||||
if (!image_count) {
|
||||
this.flags.feed_view_images_loaded[story.id] = true;
|
||||
} else {
|
||||
// Progressively load the images in each story, so that when one story
|
||||
// loads, the position is calculated and the next story can calculate
|
||||
// its position (atfer its own images are loaded).
|
||||
this.flags.feed_view_images_loaded[story.id] = false;
|
||||
(function($story, story, image_count) {
|
||||
$('img', $story).load(function() {
|
||||
// NEWSBLUR.log(['Loaded image', $story, story, image_count]);
|
||||
if (image_count == 1) {
|
||||
self.flags.feed_view_images_loaded[story.id] = true;
|
||||
} else {
|
||||
image_count--;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
})($story, story, image_count);
|
||||
}
|
||||
}
|
||||
|
||||
if (!stories || !stories.length) {
|
||||
// this.fetch_story_locations_in_feed_view({'reset_timer': true});
|
||||
}
|
||||
|
||||
if (first_load) NEWSBLUR.app.story_list.show_stories_preference_in_feed_view(true);
|
||||
},
|
||||
|
||||
apply_story_styling: function(reset_stories) {
|
||||
var $body = this.$s.$body;
|
||||
$body.removeClass('NB-theme-sans-serif');
|
||||
|
@ -2118,6 +2059,7 @@
|
|||
self.flags.scrolling_by_selecting_story_title = false;
|
||||
}, 550);
|
||||
if (view == 'page') {
|
||||
console.log(["iframe_prevented_from_loading", this.flags['iframe_prevented_from_loading']]);
|
||||
if (this.flags['iframe_prevented_from_loading']) {
|
||||
NEWSBLUR.app.original_tab_view.load_feed_iframe();
|
||||
}
|
||||
|
@ -2142,9 +2084,7 @@
|
|||
'queue': false
|
||||
});
|
||||
|
||||
if (!this.flags['feed_view_positions_calculated']) {
|
||||
// this.prefetch_story_locations_in_feed_view();
|
||||
}
|
||||
NEWSBLUR.app.story_list.reset_story_positions();
|
||||
} else if (view == 'story') {
|
||||
$story_pane.animate({
|
||||
'left': -2 * $feed_iframe.width()
|
||||
|
@ -2452,11 +2392,11 @@
|
|||
$.make('div', { className: 'NB-menu-manage-title' }, 'Intelligence trainer'),
|
||||
$.make('div', { className: 'NB-menu-manage-subtitle' }, 'What you like and dislike.')
|
||||
]),
|
||||
$.make('li', { className: 'NB-menu-separator' }),
|
||||
$.make('li', { className: 'NB-menu-manage-feed NB-menu-manage-delete NB-menu-manage-socialfeed-delete' }, [
|
||||
(feed.get('user_id') != NEWSBLUR.Globals.user_id && $.make('li', { className: 'NB-menu-separator' })),
|
||||
(feed.get('user_id') != NEWSBLUR.Globals.user_id && $.make('li', { className: 'NB-menu-manage-feed NB-menu-manage-delete NB-menu-manage-socialfeed-delete' }, [
|
||||
$.make('div', { className: 'NB-menu-manage-image' }),
|
||||
$.make('div', { className: 'NB-menu-manage-title' }, 'Unfollow')
|
||||
]),
|
||||
])),
|
||||
$.make('li', { className: 'NB-menu-manage-feed NB-menu-manage-delete-confirm NB-menu-manage-socialfeed-delete-confirm' }, [
|
||||
$.make('div', { className: 'NB-menu-manage-image' }),
|
||||
$.make('div', { className: 'NB-menu-manage-title' }, 'Really unfollow?')
|
||||
|
@ -2519,7 +2459,7 @@
|
|||
var starred_class = story.get('starred') ? ' NB-story-starred ' : '';
|
||||
var starred_title = story.get('starred') ? 'Remove bookmark' : 'Save This Story';
|
||||
var shared_class = story.get('shared') ? ' NB-story-shared ' : '';
|
||||
var shared_title = story.get('shared') ? 'Shared' : 'Share story';
|
||||
var shared_title = story.get('shared') ? 'Shared' : 'Post to blurblog';
|
||||
story.story_share_menu_view = new NEWSBLUR.Views.StoryShareView({
|
||||
model: story
|
||||
});
|
||||
|
@ -2571,6 +2511,21 @@
|
|||
}, this)).bind('mouseleave', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Email story').parent().removeClass('NB-menu-manage-highlight-pinboard');
|
||||
}, this))),
|
||||
(NEWSBLUR.Preferences['story_share_diigo'] && $.make('div', { className: 'NB-menu-manage-thirdparty-icon NB-menu-manage-thirdparty-diigo'}).bind('mouseenter', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Diigo').parent().addClass('NB-menu-manage-highlight-diigo');
|
||||
}, this)).bind('mouseleave', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Email story').parent().removeClass('NB-menu-manage-highlight-diigo');
|
||||
}, this))),
|
||||
(NEWSBLUR.Preferences['story_share_kippt'] && $.make('div', { className: 'NB-menu-manage-thirdparty-icon NB-menu-manage-thirdparty-kippt'}).bind('mouseenter', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Kippt').parent().addClass('NB-menu-manage-highlight-kippt');
|
||||
}, this)).bind('mouseleave', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Email story').parent().removeClass('NB-menu-manage-highlight-kippt');
|
||||
}, this))),
|
||||
(NEWSBLUR.Preferences['story_share_evernote'] && $.make('div', { className: 'NB-menu-manage-thirdparty-icon NB-menu-manage-thirdparty-evernote'}).bind('mouseenter', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Evernote').parent().addClass('NB-menu-manage-highlight-evernote');
|
||||
}, this)).bind('mouseleave', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Email story').parent().removeClass('NB-menu-manage-highlight-evernote');
|
||||
}, this))),
|
||||
(NEWSBLUR.Preferences['story_share_googleplus'] && $.make('div', { className: 'NB-menu-manage-thirdparty-icon NB-menu-manage-thirdparty-googleplus'}).bind('mouseenter', _.bind(function(e) {
|
||||
$(e.target).siblings('.NB-menu-manage-title').text('Google+').parent().addClass('NB-menu-manage-highlight-googleplus');
|
||||
}, this)).bind('mouseleave', _.bind(function(e) {
|
||||
|
@ -2606,6 +2561,12 @@
|
|||
this.send_story_to_readability(story.id);
|
||||
} else if ($target.hasClass('NB-menu-manage-thirdparty-pinboard')) {
|
||||
this.send_story_to_pinboard(story.id);
|
||||
} else if ($target.hasClass('NB-menu-manage-thirdparty-diigo')) {
|
||||
this.send_story_to_diigo(story.id);
|
||||
} else if ($target.hasClass('NB-menu-manage-thirdparty-kippt')) {
|
||||
this.send_story_to_kippt(story.id);
|
||||
} else if ($target.hasClass('NB-menu-manage-thirdparty-evernote')) {
|
||||
this.send_story_to_evernote(story.id);
|
||||
} else if ($target.hasClass('NB-menu-manage-thirdparty-googleplus')) {
|
||||
this.send_story_to_googleplus(story.id);
|
||||
} else if ($target.hasClass('NB-menu-manage-thirdparty-instapaper')) {
|
||||
|
@ -2794,7 +2755,7 @@
|
|||
});
|
||||
|
||||
// Hide menu on esc.
|
||||
$('input,textarea', $manage_menu_container).bind('keydown', 'esc', function(e) {
|
||||
$('input,textarea', $manage_menu_container).bind('keydown.manage_menu', 'esc', function(e) {
|
||||
e.preventDefault();
|
||||
self.flags['showing_confirm_input_on_manage_menu'] = false;
|
||||
self.hide_manage_menu(type, $item, true);
|
||||
|
@ -2857,7 +2818,7 @@
|
|||
}
|
||||
$('.NB-task-manage').removeClass('NB-hover');
|
||||
|
||||
this.blur_to_page();
|
||||
this.blur_to_page({manage_menu: true});
|
||||
},
|
||||
|
||||
// ========================
|
||||
|
@ -3132,7 +3093,7 @@
|
|||
var $confirm = $('.NB-menu-manage-story-share-confirm');
|
||||
|
||||
$share.removeClass('NB-menu-manage-story-share-cancel');
|
||||
var text = 'Share story';
|
||||
var text = 'Post to blurblog';
|
||||
if (shared) {
|
||||
text = 'Shared';
|
||||
$share.addClass('NB-active');
|
||||
|
@ -3167,7 +3128,6 @@
|
|||
this.model.preference('unread_view', value);
|
||||
}
|
||||
this.flags['unread_threshold_temporarily'] = null;
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
this.switch_feed_view_unread_view(value);
|
||||
this.show_feed_hidden_story_title_indicator(true);
|
||||
this.show_story_titles_above_intelligence_level({'animate': true, 'follow': true});
|
||||
|
@ -3323,26 +3283,35 @@
|
|||
}
|
||||
}
|
||||
|
||||
if ((this.story_view == 'feed' || this.flags['page_view_showing_feed_view']) &&
|
||||
NEWSBLUR.assets.preference('feed_view_single_story')) {
|
||||
// No need to show/hide feed view stories under single_story preference.
|
||||
// If the user switches to feed/page, then no animation is happening
|
||||
// and this will work anyway.
|
||||
var active_story = this.active_story;
|
||||
var $active_story = this.active_story && this.active_story.story_view.$el;
|
||||
if ($active_story && $active_story.length || true) {
|
||||
$stories_show = $stories_show.not('.NB-feed-story');
|
||||
$stories_hide = $stories_hide.not('.NB-feed-story');
|
||||
}
|
||||
console.log(["single story", $stories_show.length, $stories_hide.length, this.active_story, active_story && active_story.id]);
|
||||
}
|
||||
|
||||
if (!options['animate']) {
|
||||
$stories_hide.css({'display': 'none'});
|
||||
$stories_show.css({'display': 'block'});
|
||||
NEWSBLUR.app.story_titles.fill_out();
|
||||
}
|
||||
|
||||
if (this.story_view == 'feed' && !this.model.preference('feed_view_single_story')) {
|
||||
if ($stories_show.filter(':visible').length != $stories_show.length
|
||||
|| $stories_hide.filter(':visible').length != 0) {
|
||||
NEWSBLUR.log(['Show/Hide stories', $stories_show.filter(':visible').length, $stories_show.length, $stories_hide.filter(':visible').length, $stories_hide.length]);
|
||||
setTimeout(function() {
|
||||
self.flags['feed_view_positions_calculated'] = false;
|
||||
// self.prefetch_story_locations_in_feed_view();
|
||||
}, 500);
|
||||
}
|
||||
if (!NEWSBLUR.assets.preference('feed_view_single_story')) {
|
||||
_.delay(function() {
|
||||
NEWSBLUR.app.story_list.reset_story_positions();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
if (options['animate'] && options['follow'] &&
|
||||
($stories_hide.length || $stories_show.length)) {
|
||||
// NEWSBLUR.log(['Showing correct stories', this.story_view, this.flags['feed_view_positions_calculated'], unread_view_name, $stories_show.length, $stories_hide.length]);
|
||||
// NEWSBLUR.log(['Showing correct stories', this.story_view, unread_view_name, $stories_show.length, $stories_hide.length]);
|
||||
if (this.model.preference('animations')) {
|
||||
$stories_hide.slideUp(500, function() {
|
||||
NEWSBLUR.app.story_titles.fill_out();
|
||||
|
@ -3390,7 +3359,7 @@
|
|||
// this.socket.refresh_feeds = _.debounce(_.bind(this.force_feeds_refresh, this), 1000*10);
|
||||
this.socket.on('connect', _.bind(function() {
|
||||
var active_feeds = this.send_socket_active_feeds();
|
||||
console.log(["Connected to real-time pubsub with " + active_feeds.length + " feeds."]);
|
||||
// console.log(["Connected to real-time pubsub with " + active_feeds.length + " feeds."]);
|
||||
this.socket.on('feed:update', _.bind(function(feed_id, message) {
|
||||
console.log(['Real-time feed update', feed_id, message]);
|
||||
this.force_feeds_refresh(false, false, feed_id);
|
||||
|
@ -3474,7 +3443,7 @@
|
|||
});
|
||||
}
|
||||
}, refresh_interval);
|
||||
console.log(["Setting refresh interval to every " + refresh_interval/1000 + " seconds."]);
|
||||
// console.log(["Setting refresh interval to every " + refresh_interval/1000 + " seconds."]);
|
||||
},
|
||||
|
||||
force_feed_refresh: function(feed_id, new_feed_id) {
|
||||
|
@ -3614,6 +3583,7 @@
|
|||
position = position - 8; // Compensate for mouse indicator height.
|
||||
}
|
||||
this.$s.$mouse_indicator.css('top', position);
|
||||
this.cache.mouse_position_y = position;
|
||||
},
|
||||
|
||||
// ==========================
|
||||
|
@ -4048,7 +4018,7 @@
|
|||
follow_user_in_tryfeed: function(feed_id) {
|
||||
var self = this;
|
||||
var socialsub = this.model.get_feed(feed_id);
|
||||
this.model.follow_user(socialsub.user_id, function(data) {
|
||||
this.model.follow_user(socialsub.get('user_id'), function(data) {
|
||||
NEWSBLUR.app.feed_list.make_social_feeds();
|
||||
self.open_social_stories(feed_id);
|
||||
});
|
||||
|
@ -4159,6 +4129,21 @@
|
|||
}, $.noop);
|
||||
},
|
||||
|
||||
// ===================
|
||||
// = Unfetched Feeds =
|
||||
// ===================
|
||||
|
||||
setup_unfetched_feed_check: function() {
|
||||
this.locks.unfetched_feed_check = setInterval(_.bind(function() {
|
||||
var unfetched_feeds = NEWSBLUR.assets.unfetched_feeds();
|
||||
if (unfetched_feeds.length) {
|
||||
_.each(unfetched_feeds, _.bind(function(feed) {
|
||||
this.force_instafetch_stories(feed.id);
|
||||
}, this));
|
||||
}
|
||||
}, this), 60*10*1000);
|
||||
},
|
||||
|
||||
// ==========
|
||||
// = Events =
|
||||
// ==========
|
||||
|
@ -4997,6 +4982,13 @@
|
|||
e.preventDefault();
|
||||
self.open_next_unread_story_across_feeds();
|
||||
});
|
||||
$document.bind('keydown', 'c', function(e) {
|
||||
e.preventDefault();
|
||||
NEWSBLUR.app.story_list.scroll_to_selected_story(self.active_story, {
|
||||
scroll_to_comments: true,
|
||||
scroll_offset: -50
|
||||
});
|
||||
});
|
||||
$document.bind('keydown', 'm', function(e) {
|
||||
e.preventDefault();
|
||||
self.show_last_unread_story();
|
||||
|
@ -5058,6 +5050,7 @@
|
|||
});
|
||||
$document.bind('keydown', 'u', function(e) {
|
||||
e.preventDefault();
|
||||
if (!self.active_story) return;
|
||||
var story_id = self.active_story.id;
|
||||
var story = self.model.get_story(story_id);
|
||||
if (self.active_story && !self.active_story.get('read_status')) {
|
||||
|
|
|
@ -461,7 +461,7 @@ _.extend(NEWSBLUR.ReaderIntro.prototype, {
|
|||
self.advance_import_carousel(0);
|
||||
$loading.removeClass('NB-active');
|
||||
NEWSBLUR.log(['Error', data, status, e]);
|
||||
$error.text("There was a problem uploading your OPML file. Try e-mailing it to samuel@ofbrooklyn.com.");
|
||||
$error.text("There was a problem uploading your OPML file. Try e-mailing it to samuel@newsblur.com.");
|
||||
$error.slideDown(300);
|
||||
},
|
||||
data: formData,
|
||||
|
|
|
@ -206,7 +206,7 @@ NEWSBLUR.ReaderKeyboard.prototype = {
|
|||
]),
|
||||
$.make('div', { className: 'NB-keyboard-group' }, [
|
||||
$.make('div', { className: 'NB-keyboard-shortcut' }, [
|
||||
$.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Share story'),
|
||||
$.make('div', { className: 'NB-keyboard-shortcut-explanation' }, 'Post to blurblog'),
|
||||
$.make('div', { className: 'NB-keyboard-shortcut-key' }, [
|
||||
'shift',
|
||||
$.make('span', '+'),
|
||||
|
|
|
@ -493,6 +493,18 @@ _.extend(NEWSBLUR.ReaderPreferences.prototype, {
|
|||
$.make('input', { type: 'checkbox', id: 'NB-preference-story-share-pinboard', name: 'story_share_pinboard' }),
|
||||
$.make('label', { 'for': 'NB-preference-story-share-pinboard' })
|
||||
]),
|
||||
$.make('div', { className: 'NB-preference-option', title: 'Diigo' }, [
|
||||
$.make('input', { type: 'checkbox', id: 'NB-preference-story-share-diigo', name: 'story_share_diigo' }),
|
||||
$.make('label', { 'for': 'NB-preference-story-share-diigo' })
|
||||
]),
|
||||
$.make('div', { className: 'NB-preference-option', title: 'Kippt' }, [
|
||||
$.make('input', { type: 'checkbox', id: 'NB-preference-story-share-kippt', name: 'story_share_kippt' }),
|
||||
$.make('label', { 'for': 'NB-preference-story-share-kippt' })
|
||||
]),
|
||||
$.make('div', { className: 'NB-preference-option', title: 'Evernote' }, [
|
||||
$.make('input', { type: 'checkbox', id: 'NB-preference-story-share-evernote', name: 'story_share_evernote' }),
|
||||
$.make('label', { 'for': 'NB-preference-story-share-evernote' })
|
||||
]),
|
||||
$.make('div', { className: 'NB-preference-option', title: 'Google+' }, [
|
||||
$.make('input', { type: 'checkbox', id: 'NB-preference-story-share-googleplus', name: 'story_share_googleplus' }),
|
||||
$.make('label', { 'for': 'NB-preference-story-share-googleplus' })
|
||||
|
|
|
@ -7,7 +7,7 @@ NEWSBLUR.ReaderSendEmail = function(story_id, options) {
|
|||
this.model = NEWSBLUR.assets;
|
||||
this.story_id = story_id;
|
||||
this.story = this.model.get_story(story_id);
|
||||
this.feed_id = this.story.story_feed_id;
|
||||
this.feed_id = this.story.get('story_feed_id');
|
||||
this.feed = this.model.get_feed(this.feed_id);
|
||||
|
||||
this.runner();
|
||||
|
|
|
@ -51,7 +51,7 @@ _.extend(NEWSBLUR.ReaderSocialProfile.prototype, {
|
|||
]),
|
||||
$.make('td', [
|
||||
$.make('fieldset', [
|
||||
$.make('legend', 'People you also follow'),
|
||||
$.make('legend', 'People you know'),
|
||||
$.make('div', { className: 'NB-modal-section NB-profile-following-youknow' })
|
||||
]),
|
||||
$.make('fieldset', [
|
||||
|
@ -71,7 +71,7 @@ _.extend(NEWSBLUR.ReaderSocialProfile.prototype, {
|
|||
]),
|
||||
$.make('td', [
|
||||
$.make('fieldset', [
|
||||
$.make('legend', 'People you follow'),
|
||||
$.make('legend', 'People you know'),
|
||||
$.make('div', { className: 'NB-modal-section NB-profile-followers-youknow' })
|
||||
]),
|
||||
$.make('fieldset', [
|
||||
|
@ -146,9 +146,8 @@ _.extend(NEWSBLUR.ReaderSocialProfile.prototype, {
|
|||
return $.make('div', { className: 'NB-profile-link', title: user.get('username') }, [
|
||||
$.make('img', { src: user.get('photo_url') })
|
||||
]).tipsy({
|
||||
delayIn: 50,
|
||||
gravity: 's',
|
||||
fade: true,
|
||||
delayIn: 1,
|
||||
offset: 3
|
||||
}).data('user_id', user_id);
|
||||
}));
|
||||
|
|
|
@ -17,6 +17,41 @@ NEWSBLUR.utils = {
|
|||
return score;
|
||||
},
|
||||
|
||||
generate_shadow: _.memoize(function(feed) {
|
||||
if (!feed) return '';
|
||||
var color = feed.get('favicon_color');
|
||||
|
||||
if (!color) {
|
||||
return '0 1px 0 #222';
|
||||
}
|
||||
|
||||
var r = parseInt(color.substr(0, 2), 16);
|
||||
var g = parseInt(color.substr(2, 2), 16);
|
||||
var b = parseInt(color.substr(4, 2), 16);
|
||||
|
||||
if (feed.is_light()) {
|
||||
return [
|
||||
'0 1px 0 ',
|
||||
'rgb(',
|
||||
[r+35, g+35, b+35].join(','),
|
||||
')'
|
||||
].join('');
|
||||
} else {
|
||||
return [
|
||||
'0 1px 0 ',
|
||||
'rgb(',
|
||||
[
|
||||
parseInt(r*(6/8), 10),
|
||||
parseInt(g*(6/8), 10),
|
||||
parseInt(b*(6/8), 10)
|
||||
].join(','),
|
||||
')'
|
||||
].join('');
|
||||
}
|
||||
}, function(feed) {
|
||||
return "" + feed.id;
|
||||
}),
|
||||
|
||||
generate_gradient: _.memoize(function(feed, type) {
|
||||
if (!feed) return '';
|
||||
var color = feed.get('favicon_color');
|
||||
|
@ -26,7 +61,7 @@ NEWSBLUR.utils = {
|
|||
var g = parseInt(color.substr(2, 2), 16);
|
||||
var b = parseInt(color.substr(4, 2), 16);
|
||||
|
||||
if (type == 'border' || (type == 'shadow' && !feed.is_light())) {
|
||||
if (type == 'border') {
|
||||
return [
|
||||
(type == 'border' ? '1px solid ' : '') + 'rgb(',
|
||||
[
|
||||
|
@ -36,12 +71,6 @@ NEWSBLUR.utils = {
|
|||
].join(','),
|
||||
')'
|
||||
].join('');
|
||||
} else if (type == 'shadow') {
|
||||
return [
|
||||
'rgb(',
|
||||
[r+35, g+35, b+35].join(','),
|
||||
')'
|
||||
].join('');
|
||||
} else if (type == 'webkit') {
|
||||
return [
|
||||
'-webkit-gradient(',
|
||||
|
|
|
@ -52,7 +52,7 @@ NEWSBLUR.About.prototype = {
|
|||
]),
|
||||
$.make('li', [
|
||||
'E-mail: ',
|
||||
$.make('a', { href: 'mailto:samuel@ofbrooklyn.com' }, 'samuel@ofbrooklyn.com')
|
||||
$.make('a', { href: 'mailto:samuel@newsblur.com' }, 'samuel@newsblur.com')
|
||||
]),
|
||||
$.make('li', { className: 'last' }, [
|
||||
'Made in: ',
|
||||
|
|
|
@ -118,7 +118,7 @@ NEWSBLUR.Faq.prototype = {
|
|||
$.make('div', { className: 'NB-faq-question' }, 'Help! I have an issue and it\'s not mentioned here.'),
|
||||
$.make('div', { className: 'NB-faq-answer last' }, [
|
||||
'Please, please, please e-mail ',
|
||||
$.make('a', { href: 'mailto:samuel@ofbrooklyn.com' }, 'samuel@ofbrooklyn.com'),
|
||||
$.make('a', { href: 'mailto:samuel@newsblur.com' }, 'samuel@newsblur.com'),
|
||||
'. If you have an issue it is entirely possible that other people do, too.'
|
||||
])
|
||||
])
|
||||
|
|
|
@ -181,7 +181,9 @@ NEWSBLUR.Views.FeedList = Backbone.View.extend({
|
|||
});
|
||||
}
|
||||
if (!feed_view) {
|
||||
feed_view = model.views[0];
|
||||
feed_view = _.detect(model.views, _.bind(function(view) {
|
||||
return !!view.$el.closest(this.$s.$feed_lists).length;
|
||||
}, this));
|
||||
}
|
||||
|
||||
if (feed_view) {
|
||||
|
@ -195,7 +197,6 @@ NEWSBLUR.Views.FeedList = Backbone.View.extend({
|
|||
// console.log(["scroll_to_show_selected_feed", feed_view, feed_view.$el, is_feed_visible]);
|
||||
|
||||
if (!is_feed_visible) {
|
||||
var container_offset = $feed_lists.position().top;
|
||||
var scroll = feed_view.$el.position().top;
|
||||
var container = $feed_lists.scrollTop();
|
||||
var height = $feed_lists.outerHeight();
|
||||
|
|
|
@ -137,9 +137,13 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
|
|||
}
|
||||
|
||||
if (feed.is_social()) {
|
||||
extra_classes += ' NB-feed-social';
|
||||
if (feed.get('subscription_user_id') && !feed.get('shared_stories_count')) {
|
||||
extra_classes += ' NB-feed-inactive';
|
||||
}
|
||||
if (feed.get('subscription_user_id') == NEWSBLUR.Globals.user_id) {
|
||||
extra_classes += ' NB-feed-self-blurblog';
|
||||
}
|
||||
}
|
||||
|
||||
return extra_classes;
|
||||
|
|
|
@ -2,21 +2,32 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'handle_scroll_feed_iframe', 'handle_mousemove_iframe_view', 'setup_events');
|
||||
this.cache = {
|
||||
iframe: {},
|
||||
prefetch_iteration: 0,
|
||||
iframe_fetching_story_locations: false,
|
||||
iframe_story_locations_fetched: false
|
||||
};
|
||||
this.flags = {};
|
||||
this.locks = {
|
||||
iframe_buster_buster: false
|
||||
};
|
||||
this.reset_flags();
|
||||
this.unload_feed_iframe();
|
||||
this.setElement(NEWSBLUR.reader.$s.$feed_iframe);
|
||||
|
||||
this.setup_events();
|
||||
this.collection.bind('change:selected', this.toggle_selected_story, this);
|
||||
this.collection.bind('reset', this.reset_story_positions, this);
|
||||
this.collection.bind('add', this.reset_story_positions, this);
|
||||
|
||||
},
|
||||
|
||||
reset_flags: function() {
|
||||
this.cache = {
|
||||
iframe: {},
|
||||
prefetch_iteration: 0
|
||||
};
|
||||
this.flags = {
|
||||
iframe_fetching_story_locations: false,
|
||||
iframe_story_locations_fetched: false
|
||||
};
|
||||
this.counts = {
|
||||
positions_timer: 0
|
||||
};
|
||||
this.locks = {
|
||||
iframe_buster_buster: false
|
||||
};
|
||||
},
|
||||
|
||||
setup_events: function() {
|
||||
|
@ -148,9 +159,9 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
|
||||
|
||||
if (!this.flags['iframe_view_not_busting']) {
|
||||
var feed_id = this.active_feed;
|
||||
var feed_id = NEWSBLUR.reader.active_feed;
|
||||
_.delay(_.bind(function() {
|
||||
if (feed_id == this.active_feed) {
|
||||
if (feed_id == NEWSBLUR.reader.active_feed) {
|
||||
this.flags['iframe_view_not_busting'] = true;
|
||||
}
|
||||
}, this), 200);
|
||||
|
@ -212,16 +223,15 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
var stories = NEWSBLUR.assets.stories;
|
||||
var $iframe = this.$el.contents();
|
||||
var prefetch_tries_left = 3;
|
||||
this.cache['prefetch_iteration'] += 1;
|
||||
|
||||
NEWSBLUR.log(['Prefetching', !this.flags['iframe_fetching_story_locations'], !this.flags['iframe_story_locations_fetched']]);
|
||||
if (!this.flags['iframe_loaded']) return;
|
||||
|
||||
this.cache['prefetch_iteration'] += 1;
|
||||
NEWSBLUR.log(['Prefetching Original', !this.flags['iframe_fetching_story_locations'], !this.flags['iframe_story_locations_fetched']]);
|
||||
if (!this.flags['iframe_fetching_story_locations']
|
||||
&& !this.flags['iframe_story_locations_fetched']) {
|
||||
// $iframe.unbind('scroll').scroll($.rescope(this.handle_scroll_feed_iframe, this));
|
||||
// $iframe
|
||||
// .unbind('mousemove.reader')
|
||||
// .bind('mousemove.reader', $.rescope(this.handle_mousemove_iframe_view, this));
|
||||
|
||||
this.setup_events();
|
||||
|
||||
var last_story_index = this.cache.iframe_story_positions_keys.length;
|
||||
var last_story_position = _.last(this.cache.iframe_story_positions_keys);
|
||||
var last_story = this.cache.iframe_story_positions[last_story_position];
|
||||
|
@ -229,7 +239,7 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
if (last_story) {
|
||||
$last_story = this.find_story_in_feed_iframe(last_story, $iframe);
|
||||
}
|
||||
NEWSBLUR.log(['last_story', last_story_index, last_story_position, last_story, $last_story]);
|
||||
// NEWSBLUR.log(['last_story', last_story_index, last_story_position, last_story, $last_story]);
|
||||
var last_story_same_position;
|
||||
if ($last_story && $last_story.length) {
|
||||
last_story_same_position = parseInt($last_story.offset().top, 10)==last_story_position;
|
||||
|
@ -246,7 +256,7 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
if (last_story_same_position && i < last_story_index) return true;
|
||||
|
||||
var $story = this.find_story_in_feed_iframe(story, $iframe);
|
||||
NEWSBLUR.log(['Pre-fetching', i, last_story_index, last_story_same_position, $story, story.get('story_title')]);
|
||||
// NEWSBLUR.log(['Pre-fetching', i, last_story_index, last_story_same_position, $story, story.get('story_title')]);
|
||||
if (!$story ||
|
||||
!$story.length ||
|
||||
this.flags['iframe_fetching_story_locations'] ||
|
||||
|
@ -273,12 +283,16 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
this.prefetch_story_locations_in_story_frame();
|
||||
}
|
||||
}, this), 1000);
|
||||
} else {
|
||||
this.fetch_story_locations_in_story_frame();
|
||||
}
|
||||
},
|
||||
|
||||
fetch_story_locations_in_story_frame: function($iframe) {
|
||||
fetch_story_locations_in_story_frame: function($iframe, options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
if (!$iframe) $iframe = this.$el.contents();
|
||||
if (options.reset_timer) this.counts['positions_timer'] = 0;
|
||||
|
||||
this.flags['iframe_fetching_story_locations'] = true;
|
||||
this.flags['iframe_story_locations_fetched'] = false;
|
||||
|
@ -291,36 +305,64 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
});
|
||||
|
||||
NEWSBLUR.assets.stories.any(_.bind(function(story, i) {
|
||||
if (story['story_feed_id'] == this.active_feed ||
|
||||
"social:" + story['social_user_id'] == this.active_feed) {
|
||||
if (story.get('story_feed_id') == NEWSBLUR.reader.active_feed ||
|
||||
"social:" + story.get('social_user_id') == NEWSBLUR.reader.active_feed) {
|
||||
var $story = this.find_story_in_feed_iframe(story, $iframe);
|
||||
// NEWSBLUR.log(['Fetching story', i, story.get('story_title'), $story]);
|
||||
|
||||
if (self.cache['story_misses'] > 5) {
|
||||
NEWSBLUR.log(['iFrame view entirely loaded', self.cache['story_misses'], self.cache.iframe_stories]);
|
||||
// NEWSBLUR.log(['iFrame view entirely loaded', self.cache['story_misses'], self.cache.iframe_stories]);
|
||||
self.flags['iframe_story_locations_fetched'] = true;
|
||||
self.flags['iframe_fetching_story_locations'] = false;
|
||||
clearInterval(self.flags['iframe_scroll_snapback_check']);
|
||||
return true;
|
||||
}
|
||||
} else if (story && story['story_feed_id'] != this.active_feed &&
|
||||
"social:" + story['social_user_id'] != this.active_feed) {
|
||||
NEWSBLUR.log(['Switched off iframe early', this.active_feed, story['story_feed_id'], story['social_user_id']]);
|
||||
} else if (story && story.get('story_feed_id') != NEWSBLUR.reader.active_feed &&
|
||||
"social:" + story.get('social_user_id') != NEWSBLUR.reader.active_feed) {
|
||||
NEWSBLUR.log(['Switched off iframe early', NEWSBLUR.reader.active_feed, story.get('story_feed_id'), story.get('social_user_id')]);
|
||||
return true;
|
||||
}
|
||||
}, this));
|
||||
|
||||
NEWSBLUR.log(['Original view entirely loaded', _.keys(self.cache.iframe_stories).length + " stories", this.counts['positions_timer']/1000 + " sec delay"]);
|
||||
|
||||
this.counts['positions_timer'] = Math.max(this.counts['positions_timer']*2, 1000);
|
||||
clearTimeout(this.flags['next_fetch']);
|
||||
this.flags['next_fetch'] = _.delay(_.bind(this.fetch_story_locations_in_story_frame, this),
|
||||
this.counts['positions_timer']);
|
||||
},
|
||||
|
||||
reset_story_positions: function(models) {
|
||||
if (!models || !models.length) {
|
||||
models = NEWSBLUR.assets.stories;
|
||||
}
|
||||
if (!models.length) return;
|
||||
|
||||
this.flags['iframe_fetching_story_locations'] = false;
|
||||
this.flags['iframe_story_locations_fetched'] = false;
|
||||
|
||||
if (NEWSBLUR.reader.flags['story_titles_loaded']) {
|
||||
NEWSBLUR.log(['iframe loaded, titles loaded (early)']);
|
||||
this.fetch_story_locations_in_story_frame();
|
||||
} else {
|
||||
this.prefetch_story_locations_in_story_frame();
|
||||
}
|
||||
},
|
||||
|
||||
// ===========
|
||||
// = Actions =
|
||||
// ===========
|
||||
|
||||
iframe_not_busting: function() {
|
||||
this.flags['iframe_not_busting'] = true;
|
||||
},
|
||||
|
||||
unload_feed_iframe: function() {
|
||||
var $taskbar_view_page = $('.NB-taskbar .task_view_page');
|
||||
$taskbar_view_page.removeClass('NB-task-return');
|
||||
|
||||
// REMOVE ME, this disabled the iframe buster buster
|
||||
// NEWSBLUR.reader.flags['iframe_view_loaded'] = false;
|
||||
clearInterval(this.flags['iframe_scroll_snapback_check']);
|
||||
|
||||
this.flags['iframe_story_locations_fetched'] = false;
|
||||
NEWSBLUR.reader.flags['iframe_prevented_from_loading'] = false;
|
||||
|
||||
|
@ -332,7 +374,11 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
});
|
||||
|
||||
$.extend(this.flags, {
|
||||
'iframe_scroll_snapback_check': false
|
||||
'iframe_loaded': false,
|
||||
'iframe_scroll_snapback_check': false,
|
||||
'iframe_view_not_busting': false,
|
||||
'iframe_fetching_story_locations': false,
|
||||
'iframe_story_locations_fetched': false
|
||||
});
|
||||
|
||||
this.$el.removeAttr('src');
|
||||
|
@ -347,6 +393,8 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
|
||||
this.unload_feed_iframe();
|
||||
|
||||
this.flags['iframe_loaded'] = true;
|
||||
|
||||
var page_url = '/reader/page/'+feed_id;
|
||||
if (NEWSBLUR.reader.flags['social_view']) {
|
||||
var feed = NEWSBLUR.assets.get_feed(feed_id);
|
||||
|
@ -360,27 +408,26 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
|
||||
this.$el.attr('src', page_url);
|
||||
this.enable_iframe_buster_buster();
|
||||
if (NEWSBLUR.reader.flags['iframe_view_loaded']) {
|
||||
NEWSBLUR.log(['Titles loaded, iframe loaded']);
|
||||
var $iframe = this.$el.contents();
|
||||
this.fetch_story_locations_in_story_frame($iframe);
|
||||
} else {
|
||||
NEWSBLUR.log(['Titles loaded, iframe NOT loaded -- prefetching now']);
|
||||
_.delay(_.bind(function() {
|
||||
this.prefetch_story_locations_in_story_frame();
|
||||
}, this), 500);
|
||||
}
|
||||
_.delay(_.bind(function() {
|
||||
this.prefetch_story_locations_in_story_frame();
|
||||
}, this), 500);
|
||||
|
||||
this.setup_events();
|
||||
this.$el.ready(function() {
|
||||
|
||||
|
||||
if (feed_id != NEWSBLUR.reader.active_feed) {
|
||||
console.log(["Switched feed, unloading iframe"]);
|
||||
self.unload_feed_iframe();
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
self.$el.load(function() {
|
||||
self.return_to_snapback_position(true);
|
||||
});
|
||||
}, 50);
|
||||
self.flags['iframe_scroll_snapback_check'] = setInterval(function() {
|
||||
// NEWSBLUR.log(['Checking scroll', self.iframe_scroll, self.flags.iframe_scroll_snap_back_prepared]);
|
||||
// NEWSBLUR.log(['Checking scroll', self.iframe_scroll, self.flags.iframe_scroll_snap_back_prepared, self.flags['iframe_scroll_snapback_check']]);
|
||||
if (self.iframe_scroll && self.flags.iframe_scroll_snap_back_prepared) {
|
||||
self.return_to_snapback_position();
|
||||
} else {
|
||||
|
@ -430,18 +477,17 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
|
||||
setup_feed_page_iframe_load: function() {
|
||||
this.$el.load(_.bind(function() {
|
||||
NEWSBLUR.reader.flags['iframe_view_loaded'] = true;
|
||||
this.disable_iframe_buster_buster();
|
||||
this.setup_events();
|
||||
if (NEWSBLUR.reader.flags['story_titles_loaded']) {
|
||||
NEWSBLUR.log(['iframe loaded, titles loaded']);
|
||||
this.fetch_story_locations_in_story_frame($iframe_contents);
|
||||
this.fetch_story_locations_in_story_frame();
|
||||
}
|
||||
// try {
|
||||
var $iframe_contents = this.$el.contents();
|
||||
$iframe_contents.find('a')
|
||||
.unbind('click.NB-taskbar')
|
||||
.bind('click.NB-taskbar', function(e) {
|
||||
.bind('click.NB-taskbar', _.bind(function(e) {
|
||||
var href = $(this).attr('href');
|
||||
if (href.indexOf('#') == 0) {
|
||||
e.preventDefault();
|
||||
|
@ -458,7 +504,7 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
return false;
|
||||
}
|
||||
this.taskbar_show_return_to_page();
|
||||
});
|
||||
}, this));
|
||||
// } catch(e) {
|
||||
// // Not on local domain. Ignore.
|
||||
// }
|
||||
|
@ -505,10 +551,10 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
this.locks.iframe_buster_buster = setInterval(function() {
|
||||
if (prevent_bust > 0) {
|
||||
prevent_bust -= 2;
|
||||
if (!self.flags['iframe_view_loaded'] &&
|
||||
if (self.flags['iframe_story_locations_fetched'] &&
|
||||
!self.flags['iframe_view_not_busting'] &&
|
||||
_.contains(['page', 'story'], self.story_view) &&
|
||||
self.active_feed) {
|
||||
NEWSBLUR.reader.active_feed) {
|
||||
$('.NB-feed-frame').attr('src', '');
|
||||
window.top.location = '/reader/buster';
|
||||
$('.task_view_feed').click();
|
||||
|
@ -592,7 +638,8 @@ NEWSBLUR.Views.OriginalTabView = Backbone.View.extend({
|
|||
toggle_selected_story: function(model, selected, options) {
|
||||
if (selected &&
|
||||
NEWSBLUR.reader.story_view == 'page' &&
|
||||
!options.selected_in_original) {
|
||||
!options.selected_in_original &&
|
||||
!options.selected_by_scrolling) {
|
||||
var found = this.scroll_to_selected_story(model);
|
||||
NEWSBLUR.reader.switch_to_correct_view(found);
|
||||
if (!found) {
|
||||
|
|
|
@ -98,7 +98,7 @@ NEWSBLUR.Views.SocialProfileBadge = Backbone.View.extend({
|
|||
|
||||
follow_user: function() {
|
||||
this.$('.NB-loading').addClass('NB-active');
|
||||
NEWSBLUR.reader.model.follow_user(this.model.get('user_id'), _.bind(function(data, follow_user) {
|
||||
NEWSBLUR.assets.follow_user(this.model.get('user_id'), _.bind(function(data, follow_user) {
|
||||
this.$('.NB-loading').removeClass('NB-active');
|
||||
this.model.set(follow_user);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ NEWSBLUR.Views.StoryComment = Backbone.View.extend({
|
|||
]),
|
||||
$.make('div', { className: 'NB-story-comment-author-container' }, [
|
||||
(this.model.get('source_user_id') && $.make('div', { className: 'NB-story-comment-reshares' }, [
|
||||
NEWSBLUR.Views.ProfileThumb.create(this.model.get('source_user_id'))
|
||||
NEWSBLUR.Views.ProfileThumb.create(this.model.get('source_user_id')).render().el
|
||||
])),
|
||||
$.make('div', { className: 'NB-story-comment-username' }, this.user.get('username')),
|
||||
$.make('div', { className: 'NB-story-comment-date' }, this.model.get('shared_date') + ' ago'),
|
||||
|
@ -101,7 +101,8 @@ NEWSBLUR.Views.StoryComment = Backbone.View.extend({
|
|||
this.remove_social_comment_reply_form();
|
||||
}, this));
|
||||
$('input', $form).focus();
|
||||
// this.fetch_story_locations_in_feed_view();
|
||||
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
},
|
||||
|
||||
remove_social_comment_reply_form: function() {
|
||||
|
@ -118,7 +119,7 @@ NEWSBLUR.Views.StoryComment = Backbone.View.extend({
|
|||
|
||||
if (!comment_reply || comment_reply.length <= 1) {
|
||||
this.remove_social_comment_reply_form();
|
||||
// this.fetch_story_locations_in_feed_view();
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -133,7 +134,7 @@ NEWSBLUR.Views.StoryComment = Backbone.View.extend({
|
|||
_.bind(function(data) {
|
||||
this.model.set(data.comment);
|
||||
this.render();
|
||||
// this.fetch_story_locations_in_feed_view();
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
}, this), _.bind(function(data) {
|
||||
var message = data && data.message || "Sorry, this reply could not be posted. Probably a bug.";
|
||||
if (!NEWSBLUR.Globals.is_authenticated) {
|
||||
|
@ -143,7 +144,7 @@ NEWSBLUR.Views.StoryComment = Backbone.View.extend({
|
|||
$submit.removeClass('NB-disabled').text('Post');
|
||||
$form.find('.NB-error').remove();
|
||||
$form.append($error);
|
||||
// this.fetch_story_locations_in_feed_view();
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
}, this));
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ NEWSBLUR.Views.StoryCommentsView = Backbone.View.extend({
|
|||
}, this));
|
||||
|
||||
this.$('.NB-story-comments-public-teaser-wrapper').replaceWith($comments);
|
||||
// this.fetch_story_locations_in_feed_view();
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
}, this));
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
this.model.bind('change:intelligence', this.render_header, this);
|
||||
|
||||
// Binding directly instead of using event delegation. Need for speed.
|
||||
this.$el.bind('mouseenter', this.mouseenter);
|
||||
this.$el.bind('mouseleave', this.mouseleave);
|
||||
// this.$el.bind('mouseenter', this.mouseenter);
|
||||
// this.$el.bind('mouseleave', this.mouseleave);
|
||||
|
||||
if (!this.options.feed_floater) {
|
||||
this.model.story_view = this;
|
||||
|
@ -47,7 +47,8 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
model: this.model,
|
||||
el: this.el
|
||||
}).template({
|
||||
story: this.model
|
||||
story: this.model,
|
||||
social_services: NEWSBLUR.assets.social_services
|
||||
});
|
||||
this.$el.html(this.template(params));
|
||||
this.toggle_classes();
|
||||
|
@ -73,8 +74,8 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
feed : NEWSBLUR.reader.flags.river_view && this.feed,
|
||||
tag : _.first(this.model.get("story_tags")),
|
||||
title : this.make_story_title(),
|
||||
authors_score : this.classifiers.authors[this.model.get('story_authors')],
|
||||
tags_score : this.classifiers.tags,
|
||||
authors_score : this.classifiers && this.classifiers.authors[this.model.get('story_authors')],
|
||||
tags_score : this.classifiers && this.classifiers.tags,
|
||||
options : this.options
|
||||
};
|
||||
},
|
||||
|
@ -98,7 +99,7 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
<% if (story.get("story_tags", []).length) { %>\
|
||||
<div class="NB-feed-story-tags">\
|
||||
<% _.each(story.get("story_tags"), function(tag) { %>\
|
||||
<div class="NB-feed-story-tag <% if (tags_score[tag]) { %>NB-score-<%= tags_score[tag] %><% } %>">\
|
||||
<div class="NB-feed-story-tag <% if (tags_score && tags_score[tag]) { %>NB-score-<%= tags_score[tag] %><% } %>">\
|
||||
<%= tag %>\
|
||||
</div>\
|
||||
<% }) %>\
|
||||
|
@ -119,6 +120,9 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
<% } %>\
|
||||
<%= story.get("long_parsed_date") %>\
|
||||
</span>\
|
||||
<% if (story.get("starred_date")) { %>\
|
||||
<span class="NB-feed-story-starred-date"><%= story.get("starred_date") %></span>\
|
||||
<% } %>\
|
||||
<% } %>\
|
||||
</div>\
|
||||
</div>\
|
||||
|
@ -141,7 +145,7 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
</div>\
|
||||
<div class="NB-sideoption NB-feed-story-share">\
|
||||
<div class="NB-sideoption-icon"> </div>\
|
||||
<div class="NB-sideoption-title"><%= story.get("shared") ? "Shared" : "Share this story" %></div>\
|
||||
<div class="NB-sideoption-title"><%= story.get("shared") ? "Shared" : "Post to Blurblog" %></div>\
|
||||
</div>\
|
||||
<%= story_share_view %>\
|
||||
</div>\
|
||||
|
@ -156,7 +160,7 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
$header.css('background-image', NEWSBLUR.utils.generate_gradient(this.feed, 'moz'));
|
||||
$header.css('borderTop', NEWSBLUR.utils.generate_gradient(this.feed, 'border'));
|
||||
$header.css('borderBottom', NEWSBLUR.utils.generate_gradient(this.feed, 'border'));
|
||||
$header.css('textShadow', '0 1px 0 ' + NEWSBLUR.utils.generate_gradient(this.feed, 'shadow'));
|
||||
$header.css('textShadow', NEWSBLUR.utils.generate_shadow(this.feed));
|
||||
},
|
||||
|
||||
make_story_title: function() {
|
||||
|
@ -174,9 +178,12 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
},
|
||||
|
||||
render_comments: function() {
|
||||
var $original_comments = this.$('.NB-feed-story-share-container,.NB-feed-story-comments');
|
||||
if (this.model.get("comment_count") || this.model.get("share_count")) {
|
||||
var $comments = new NEWSBLUR.Views.StoryCommentsView({model: this.model}).render().el;
|
||||
this.$('.NB-feed-story-share-container,.NB-feed-story-comments').replaceWith($comments);
|
||||
$original_comments.replaceWith($comments);
|
||||
} else if ($original_comments.length) {
|
||||
$original_comments.replaceWith($.make('div', { className: 'NB-feed-story-share-container' }));
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -246,6 +253,7 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
(NEWSBLUR.reader.story_view == 'feed' ||
|
||||
(NEWSBLUR.reader.story_view == 'page' &&
|
||||
NEWSBLUR.reader.flags['page_view_showing_feed_view']))) {
|
||||
NEWSBLUR.app.story_list.show_stories_preference_in_feed_view();
|
||||
NEWSBLUR.app.story_list.scroll_to_selected_story(model, options);
|
||||
}
|
||||
},
|
||||
|
@ -348,10 +356,6 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
return false;
|
||||
},
|
||||
|
||||
mark_story_as_shared: function() {
|
||||
NEWSBLUR.reader.mark_story_as_shared(this.model.id, {'source': 'sideoption'});
|
||||
},
|
||||
|
||||
hide_story_changes: function() {
|
||||
var $button = this.$('.NB-feed-story-hide-changes');
|
||||
|
||||
|
@ -364,6 +368,7 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
}
|
||||
$button.css('opacity', 1).fadeOut(400);
|
||||
$button.tipsy('hide').tipsy('disable');
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
},
|
||||
|
||||
open_feed: function() {
|
||||
|
|
|
@ -5,20 +5,29 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
|
|||
initialize: function() {
|
||||
this.collection.bind('reset', this.reset_flags, this);
|
||||
this.collection.bind('reset', this.render, this);
|
||||
this.collection.bind('reset', this.reset_story_positions, this);
|
||||
this.collection.bind('add', this.add, this);
|
||||
this.collection.bind('change:selected', this.show_correct_feed_in_feed_title_floater, this);
|
||||
this.collection.bind('add', this.reset_story_positions, this);
|
||||
this.collection.bind('no_more_stories', this.show_no_more_stories, this);
|
||||
this.$el.bind('mousemove', _.bind(this.handle_mousemove_feed_view, this));
|
||||
// this.$el.scroll(_.bind(this.handle_scroll_feed_view, this));
|
||||
this.$el.scroll(_.bind(this.handle_scroll_feed_view, this));
|
||||
this.reset_flags();
|
||||
},
|
||||
|
||||
reset_flags: function() {
|
||||
this.cache = {
|
||||
story_pane_position: null,
|
||||
feed_title_floater_feed_id: null
|
||||
feed_title_floater_feed_id: null,
|
||||
feed_view_story_positions: {},
|
||||
feed_view_story_positions_keys: []
|
||||
};
|
||||
this.flags = {
|
||||
feed_view_images_loaded: {},
|
||||
mousemove_timeout: false
|
||||
};
|
||||
this.counts = {
|
||||
positions_timer: 0
|
||||
};
|
||||
},
|
||||
|
||||
// ==========
|
||||
|
@ -59,17 +68,16 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
|
|||
scroll_to_selected_story: function(story, options) {
|
||||
options = options || {};
|
||||
if (!story || !story.story_view) return;
|
||||
|
||||
if (!options.immediate) {
|
||||
clearTimeout(NEWSBLUR.reader.locks.scrolling);
|
||||
NEWSBLUR.reader.flags.scrolling_by_selecting_story_title = true;
|
||||
}
|
||||
var $story = story.story_view.$el;
|
||||
|
||||
|
||||
if (NEWSBLUR.assets.preference('feed_view_single_story')) return;
|
||||
if (!NEWSBLUR.assets.preference('animations')) options.immediate = true;
|
||||
if (options.scroll_to_comments) {
|
||||
$story = $('.NB-feed-story-comments', $story);
|
||||
}
|
||||
|
||||
clearTimeout(NEWSBLUR.reader.locks.scrolling);
|
||||
NEWSBLUR.reader.flags.scrolling_by_selecting_story_title = true;
|
||||
this.$el.scrollable().stop();
|
||||
this.$el.scrollTo($story, {
|
||||
duration: options.immediate ? 0 : 340,
|
||||
|
@ -78,8 +86,6 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
|
|||
offset: options.scroll_offset || 0,
|
||||
queue: false,
|
||||
onAfter: function() {
|
||||
if (options.immediate) return;
|
||||
|
||||
NEWSBLUR.reader.locks.scrolling = setTimeout(function() {
|
||||
NEWSBLUR.reader.flags.scrolling_by_selecting_story_title = false;
|
||||
}, 100);
|
||||
|
@ -134,39 +140,42 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
|
|||
},
|
||||
|
||||
show_stories_preference_in_feed_view: function(is_creating) {
|
||||
var $feed_view = NEWSBLUR.reader.$s.$feed_view;
|
||||
var $feed_view_stories = $(".NB-feed-story", $feed_view);
|
||||
var $stories = NEWSBLUR.reader.$s.$feed_stories;
|
||||
var story = NEWSBLUR.reader.active_story;
|
||||
|
||||
if (story && NEWSBLUR.assets.preference('feed_view_single_story')) {
|
||||
// NEWSBLUR.log(['show_stories_preference_in_feed_view', is_creating, NEWSBLUR.assets.preference('feed_view_single_story'), $feed_view_stories.length + " stories"]);
|
||||
$stories.removeClass('NB-feed-view-feed').addClass('NB-feed-view-story');
|
||||
$feed_view_stories.css({'display': 'none'});
|
||||
if (is_creating) this.$s.$feed_stories.scrollTop('0px');
|
||||
var $current_story = this.get_current_story_from_story_titles($feed_view_stories);
|
||||
if ($current_story && $current_story.length) {
|
||||
$current_story.css({'display': 'block'});
|
||||
}
|
||||
if (NEWSBLUR.reader.active_story &&
|
||||
NEWSBLUR.assets.preference('feed_view_single_story')) {
|
||||
this.$el.removeClass('NB-feed-view-feed').addClass('NB-feed-view-story');
|
||||
NEWSBLUR.reader.$s.$feed_stories.scrollTop('0px');
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
} else {
|
||||
$stories.removeClass('NB-feed-view-story').addClass('NB-feed-view-feed');
|
||||
if (!is_creating) {
|
||||
NEWSBLUR.reader.show_story_titles_above_intelligence_level({'animate': false});
|
||||
}
|
||||
this.$el.removeClass('NB-feed-view-story').addClass('NB-feed-view-feed');
|
||||
NEWSBLUR.reader.show_story_titles_above_intelligence_level({'animate': false});
|
||||
}
|
||||
NEWSBLUR.app.story_list.cache.story_pane_position = null;
|
||||
this.cache.story_pane_position = null;
|
||||
},
|
||||
|
||||
// =============
|
||||
// = Positions =
|
||||
// =============
|
||||
|
||||
is_feed_loaded_for_location_fetch: function() {
|
||||
var images_begun = _.keys(this.flags.feed_view_images_loaded).length;
|
||||
if (images_begun) {
|
||||
var images_loaded = _.keys(this.flags.feed_view_images_loaded).length &&
|
||||
_.all(_.values(this.flags.feed_view_images_loaded), _.identity);
|
||||
return !!images_loaded;
|
||||
}
|
||||
|
||||
return !!images_begun;
|
||||
},
|
||||
|
||||
prefetch_story_locations_in_feed_view: function() {
|
||||
var self = this;
|
||||
var stories = NEWSBLUR.assets.stories;
|
||||
|
||||
// NEWSBLUR.log(['Prefetching', this.flags['feed_view_positions_calculated'], this.flags.feed_view_images_loaded, (_.keys(this.flags.feed_view_images_loaded).length > 0 || this.cache.feed_view_story_positions_keys.length > 0)]);
|
||||
NEWSBLUR.log(['Prefetching Feed', this.flags['feed_view_positions_calculated'], this.flags.feed_view_images_loaded, (_.keys(this.flags.feed_view_images_loaded).length > 0 || this.cache.feed_view_story_positions_keys.length > 0), _.keys(this.flags.feed_view_images_loaded).length,
|
||||
_.values(this.flags.feed_view_images_loaded), this.is_feed_loaded_for_location_fetch()]);
|
||||
|
||||
if (!NEWSBLUR.assets.stories.size()) return;
|
||||
|
||||
if (!this.flags['feed_view_positions_calculated']) {
|
||||
|
||||
$.extend(this.cache, {
|
||||
|
@ -174,29 +183,25 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
|
|||
'feed_view_story_positions_keys': []
|
||||
});
|
||||
|
||||
for (var s in stories) {
|
||||
var story = stories[s];
|
||||
// var $story = self.cache.feed_view_stories[story.id];
|
||||
// this.determine_feed_view_story_position($story, story);
|
||||
// NEWSBLUR.log(['Pre-fetching', $story, story.get('story_title'), this.flags.feed_view_images_loaded[story.id]]);
|
||||
// if (!$story || !$story.length || this.flags['feed_view_positions_calculated']) break;
|
||||
}
|
||||
}
|
||||
if ((_.keys(this.flags.feed_view_images_loaded).length > 0 ||
|
||||
this.cache.feed_view_story_positions_keys.length > 0) &&
|
||||
(this.flags.feed_view_images_loaded.length &&
|
||||
_.all(_.values(this.flags.feed_view_images_loaded)))) {
|
||||
NEWSBLUR.assets.stories.any(_.bind(function(story) {
|
||||
this.determine_feed_view_story_position(story);
|
||||
var $story = story.story_view.$el;
|
||||
if (!$story || !$story.length || this.flags['feed_view_positions_calculated']) {
|
||||
return true;
|
||||
}
|
||||
}, this));
|
||||
|
||||
setTimeout(_.bind(function() {
|
||||
if (!this.flags['feed_view_positions_calculated']) {
|
||||
this.prefetch_story_locations_in_feed_view();
|
||||
}
|
||||
}, this), 2000);
|
||||
}
|
||||
|
||||
if (this.is_feed_loaded_for_location_fetch()) {
|
||||
this.fetch_story_locations_in_feed_view({'reset_timer': true});
|
||||
} else {
|
||||
// NEWSBLUR.log(['Still loading feed view...', _.keys(this.flags.feed_view_images_loaded).length, this.cache.feed_view_story_positions_keys.length, this.flags.feed_view_images_loaded]);
|
||||
}
|
||||
|
||||
if (!this.flags['feed_view_positions_calculated']) {
|
||||
setTimeout(function() {
|
||||
if (!self.flags['feed_view_positions_calculated']) {
|
||||
self.prefetch_story_locations_in_feed_view();
|
||||
}
|
||||
}, 2000);
|
||||
NEWSBLUR.log(['Still loading feed view...', _.keys(this.flags.feed_view_images_loaded).length, this.cache.feed_view_story_positions_keys.length, this.flags.feed_view_images_loaded]);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -204,60 +209,95 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
|
|||
options = options || {};
|
||||
var stories = NEWSBLUR.assets.stories;
|
||||
if (!stories || !stories.length) return;
|
||||
if (options.reset_timer) this.counts['feed_view_positions_timer'] = 0;
|
||||
if (options.reset_timer) this.counts['positions_timer'] = 0;
|
||||
|
||||
$.extend(this.cache, {
|
||||
'feed_view_story_positions': {},
|
||||
'feed_view_story_positions_keys': []
|
||||
});
|
||||
|
||||
for (var s in stories) {
|
||||
var story = stories[s];
|
||||
var $story = this.cache.feed_view_stories[story.id];
|
||||
this.determine_feed_view_story_position($story, story);
|
||||
}
|
||||
NEWSBLUR.assets.stories.each(_.bind(function(story) {
|
||||
this.determine_feed_view_story_position(story);
|
||||
}, this));
|
||||
|
||||
this.flags['feed_view_positions_calculated'] = true;
|
||||
// NEWSBLUR.log(['Feed view entirely loaded', NEWSBLUR.assets.stories.length + " stories", this.counts['feed_view_positions_timer']/1000 + " sec delay"]);
|
||||
// NEWSBLUR.log(['Feed view entirely loaded', NEWSBLUR.assets.stories.length + " stories", this.counts['positions_timer']/1000 + " sec delay"]);
|
||||
|
||||
this.counts['feed_view_positions_timer'] = Math.max(this.counts['feed_view_positions_timer']*2, 1000);
|
||||
this.counts['positions_timer'] = Math.max(this.counts['positions_timer']*2, 1000);
|
||||
clearTimeout(this.flags['next_fetch']);
|
||||
this.flags['next_fetch'] = _.delay(_.bind(this.fetch_story_locations_in_feed_view, this),
|
||||
this.counts['feed_view_positions_timer']);
|
||||
this.counts['positions_timer']);
|
||||
},
|
||||
|
||||
determine_feed_view_story_position: function($story, story) {
|
||||
if ($story && $story.is(':visible')) {
|
||||
determine_feed_view_story_position: function(story) {
|
||||
var $story = story.story_view.$el;
|
||||
if (story && $story.is(':visible')) {
|
||||
var position_original = parseInt($story.position().top, 10);
|
||||
var position_offset = parseInt($story.offsetParent().scrollTop(), 10);
|
||||
var position = position_original + position_offset;
|
||||
this.cache.feed_view_story_positions[position] = story;
|
||||
this.cache.feed_view_story_positions_keys.push(position);
|
||||
this.cache.feed_view_story_positions_keys.sort(function(a, b) { return a-b; });
|
||||
// NEWSBLUR.log(['Positioning story', position, $story, story, this.cache.feed_view_story_positions_keys]);
|
||||
// NEWSBLUR.log(['Positioning story', position, story.get('story_title')]);
|
||||
}
|
||||
},
|
||||
|
||||
check_feed_view_scrolled_to_bottom: function() {
|
||||
var $story_titles = this.$s.$story_titles;
|
||||
var $feed_view = this.$s.$feed_view;
|
||||
|
||||
if (!this.model.flags['no_more_stories']) {
|
||||
console.log(["check_feed_view_scrolled_to_bottom"]);
|
||||
var $last_story = $('.NB-feed-story', $feed_view).last();
|
||||
var container_offset = $feed_view.position().top;
|
||||
if (!NEWSBLUR.assets.flags['no_more_stories']) {
|
||||
var last_story = NEWSBLUR.assets.stories.last();
|
||||
var $last_story = last_story.story_view.$el;
|
||||
var container_offset = this.$el.position().top;
|
||||
var full_height = ($last_story.offset() && $last_story.offset().top) + $last_story.height() - container_offset;
|
||||
var visible_height = $feed_view.height();
|
||||
var scroll_y = $feed_view.scrollTop();
|
||||
var visible_height = this.$el.height();
|
||||
var scroll_y = this.$el.scrollTop();
|
||||
|
||||
// Fudge factor is simply because it looks better at 13 pixels off.
|
||||
if ((visible_height + 26) >= full_height) {
|
||||
// NEWSBLUR.log(['Feed view scroll', full_height, container_offset, visible_height, scroll_y]);
|
||||
this.load_page_of_feed_stories();
|
||||
NEWSBLUR.log(['Feed view scroll', full_height, container_offset, visible_height, scroll_y]);
|
||||
NEWSBLUR.reader.load_page_of_feed_stories();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
reset_story_positions: function(models) {
|
||||
if (!models || !models.length) {
|
||||
models = NEWSBLUR.assets.stories;
|
||||
}
|
||||
if (!models.length) return;
|
||||
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
|
||||
if (this.cache.story_pane_position == null) {
|
||||
this.cache.story_pane_position = this.$el.offsetParent().offset().top;
|
||||
}
|
||||
|
||||
models.each(_.bind(function(story) {
|
||||
var image_count = story.story_view.$('.NB-feed-story-content img').length;
|
||||
if (!image_count) {
|
||||
// console.log(["No images", story.get('story_title')]);
|
||||
this.flags.feed_view_images_loaded[story.id] = true;
|
||||
} else if (!this.flags.feed_view_images_loaded[story.id]) {
|
||||
// Progressively load the images in each story, so that when one story
|
||||
// loads, the position is calculated and the next story can calculate
|
||||
// its position (after its own images are loaded).
|
||||
this.flags.feed_view_images_loaded[story.id] = false;
|
||||
(function(story, image_count) {
|
||||
story.story_view.$('.NB-feed-story-content img').load(function() {
|
||||
// NEWSBLUR.log(['Loaded image', story.get('story_title'), image_count]);
|
||||
if (image_count <= 1) {
|
||||
NEWSBLUR.app.story_list.flags.feed_view_images_loaded[story.id] = true;
|
||||
} else {
|
||||
image_count--;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
})(story, image_count);
|
||||
}
|
||||
}, this));
|
||||
|
||||
this.prefetch_story_locations_in_feed_view();
|
||||
},
|
||||
|
||||
// ==========
|
||||
// = Events =
|
||||
// ==========
|
||||
|
@ -276,63 +316,58 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
|
|||
}
|
||||
|
||||
NEWSBLUR.reader.cache.mouse_position_y = e.pageY;
|
||||
if (this.cache.story_pane_position == null) {
|
||||
this.cache.story_pane_position = NEWSBLUR.reader.$s.$feed_stories.offsetParent().offset().top;
|
||||
}
|
||||
NEWSBLUR.reader.$s.$mouse_indicator.css('top', NEWSBLUR.reader.cache.mouse_position_y - this.cache.story_pane_position - 8);
|
||||
|
||||
if (this.flags['mousemove_timeout']) {
|
||||
if (this.flags['mousemove_timeout'] ||
|
||||
NEWSBLUR.reader.flags['scrolling_by_selecting_story_title']) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
self.flags['mousemove_timeout'] = false;
|
||||
}, 30);
|
||||
|
||||
// if (!this.flags['mousemove_timeout']
|
||||
// && !this.flags['switching_to_feed_view']
|
||||
// && !this.flags.scrolling_by_selecting_story_title
|
||||
// && this.story_view != 'story') {
|
||||
// var from_top = this.cache.mouse_position_y + this.$s.$feed_stories.scrollTop();
|
||||
// var offset = this.cache.story_pane_position;
|
||||
// var position = from_top - offset;
|
||||
// var positions = this.cache.feed_view_story_positions_keys;
|
||||
// var closest = $.closest(position, positions);
|
||||
// var story = this.cache.feed_view_story_positions[positions[closest]];
|
||||
// this.flags['mousemove_timeout'] = true;
|
||||
// if (story == this.active_story) return;
|
||||
// // NEWSBLUR.log(['Mousemove feed view', from_top, closest, positions[closest]]);
|
||||
// NEWSBLUR.app.story_titles.scroll_to_selected_story(story);
|
||||
var from_top = NEWSBLUR.reader.cache.mouse_position_y + this.$el.scrollTop();
|
||||
var offset = this.cache.story_pane_position;
|
||||
var position = from_top - offset;
|
||||
var positions = this.cache.feed_view_story_positions_keys;
|
||||
var closest = $.closest(position, positions);
|
||||
var story = this.cache.feed_view_story_positions[positions[closest]];
|
||||
|
||||
// }
|
||||
if (!story) return;
|
||||
if (!story.get('selected')) {
|
||||
story.set('selected', true, {selected_by_scrolling: true, mouse: true, immediate: true});
|
||||
}
|
||||
},
|
||||
|
||||
handle_scroll_feed_view: function(elem, e) {
|
||||
var self = this;
|
||||
var story_view = NEWSBLUR.reader.story_view;
|
||||
|
||||
// NEWSBLUR.log(['handle_scroll_feed_view', this.story_view, this.flags['switching_to_feed_view'], this.flags['scrolling_by_selecting_story_title']]);
|
||||
if ((this.story_view == 'feed' ||
|
||||
(this.story_view == 'page' && this.flags['page_view_showing_feed_view'])) &&
|
||||
!this.flags['scrolling_by_selecting_story_title'] &&
|
||||
// NEWSBLUR.log(['handle_scroll_feed_view', story_view, NEWSBLUR.reader.flags['switching_to_feed_view'], NEWSBLUR.reader.flags['scrolling_by_selecting_story_title']]);
|
||||
if ((story_view == 'feed' ||
|
||||
(story_view == 'page' && NEWSBLUR.reader.flags['page_view_showing_feed_view'])) &&
|
||||
!NEWSBLUR.reader.flags['scrolling_by_selecting_story_title'] &&
|
||||
!NEWSBLUR.assets.preference('feed_view_single_story')) {
|
||||
var from_top = this.cache.mouse_position_y + this.$s.$feed_stories.scrollTop();
|
||||
var from_top = NEWSBLUR.reader.cache.mouse_position_y + this.$el.scrollTop();
|
||||
var offset = this.cache.story_pane_position;
|
||||
var position = from_top - offset;
|
||||
var positions = this.cache.feed_view_story_positions_keys;
|
||||
var closest = $.closest(position, positions);
|
||||
var story = this.cache.feed_view_story_positions[positions[closest]];
|
||||
// NEWSBLUR.log(['Scroll feed view', from_top, e, closest, positions[closest], this.cache.feed_view_story_positions_keys, positions, self.cache]);
|
||||
NEWSBLUR.app.story_titles.scroll_to_selected_story(story);
|
||||
|
||||
if (!story) return;
|
||||
// console.log(["Scroll Feed", from_top, offset, position, closest, story.get('story_title')]);
|
||||
if (!story.get('selected')) {
|
||||
story.set('selected', true, {selected_by_scrolling: true, mouse: true, immediate: true});
|
||||
}
|
||||
|
||||
this.check_feed_view_scrolled_to_bottom();
|
||||
}
|
||||
|
||||
if ((this.flags.river_view || this.flags.social_view) &&
|
||||
if ((NEWSBLUR.reader.flags['river_view'] || NEWSBLUR.reader.flags['social_view']) &&
|
||||
!NEWSBLUR.assets.preference('feed_view_single_story')) {
|
||||
var story;
|
||||
if (this.flags.scrolling_by_selecting_story_title) {
|
||||
if (NEWSBLUR.reader.flags['scrolling_by_selecting_story_title']) {
|
||||
story = this.active_story;
|
||||
} else {
|
||||
var from_top = Math.max(1, this.$s.$feed_stories.scrollTop());
|
||||
var from_top = Math.max(1, this.$el.scrollTop());
|
||||
var positions = this.cache.feed_view_story_positions_keys;
|
||||
var closest = $.closest(from_top, positions);
|
||||
story = this.cache.feed_view_story_positions[positions[closest]];
|
||||
|
|
|
@ -3,6 +3,9 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
events: {
|
||||
"click .NB-feed-story-share" : "toggle_feed_story_share_dialog",
|
||||
"click .NB-sideoption-share-save" : "mark_story_as_shared",
|
||||
"click .NB-sideoption-share-unshare" : "mark_story_as_unshared",
|
||||
"click .NB-sideoption-share-crosspost-twitter" : "toggle_twitter",
|
||||
"click .NB-sideoption-share-crosspost-facebook" : "toggle_facebook",
|
||||
"keyup .NB-sideoption-share-comments" : "update_share_button_label"
|
||||
},
|
||||
|
||||
|
@ -12,7 +15,8 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
|
||||
render: function() {
|
||||
this.$el.html(this.template({
|
||||
story: this.model
|
||||
story: this.model,
|
||||
social_services: NEWSBLUR.assets.social_services
|
||||
}));
|
||||
|
||||
return this;
|
||||
|
@ -22,10 +26,18 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
<div class="NB-sideoption-share-wrapper">\
|
||||
<div class="NB-sideoption-share">\
|
||||
<div class="NB-sideoption-share-wordcount"></div>\
|
||||
<div class="NB-sideoption-share-optional">Optional</div>\
|
||||
<div class="NB-sideoption-share-crosspost">\
|
||||
<% if (social_services.twitter.twitter_uid) { %>\
|
||||
<div class="NB-sideoption-share-crosspost-twitter"></div>\
|
||||
<% } %>\
|
||||
<% if (social_services.facebook.facebook_uid) { %>\
|
||||
<div class="NB-sideoption-share-crosspost-facebook"></div>\
|
||||
<% } %>\
|
||||
</div>\
|
||||
<div class="NB-sideoption-share-title">Comments:</div>\
|
||||
<textarea class="NB-sideoption-share-comments"><%= story.get("shared_comments") %></textarea>\
|
||||
<div class="NB-menu-manage-story-share-save NB-modal-submit-green NB-sideoption-share-save NB-modal-submit-button">Share</div>\
|
||||
<div class="NB-menu-manage-story-share-unshare NB-modal-submit-grey NB-sideoption-share-unshare NB-modal-submit-button">Delete share</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
'),
|
||||
|
@ -38,6 +50,9 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
var $story_content = this.$('.NB-feed-story-content');
|
||||
var $comment_input = this.$('.NB-sideoption-share-comments');
|
||||
var $story_comments = this.$('.NB-feed-story-comments');
|
||||
var $unshare_button = this.$('.NB-sideoption-share-unshare');
|
||||
var $twitter_button = this.$('.NB-sideoption-share-crosspost-twitter');
|
||||
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
||||
|
||||
if (options.close ||
|
||||
($sideoption.hasClass('NB-active') && !options.resize_open)) {
|
||||
|
@ -59,14 +74,20 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
}, {
|
||||
'duration': 300,
|
||||
'easing': 'easeInOutQuint',
|
||||
'queue': false
|
||||
// 'complete': _.bind(this.fetch_story_locations_in_feed_view, this, {'reset_timer': true})
|
||||
'queue': false,
|
||||
'complete': function() {
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
}
|
||||
});
|
||||
$story_content.removeData('original_height');
|
||||
}
|
||||
} else {
|
||||
// Open/resize
|
||||
this.$('.NB-error').remove();
|
||||
$sideoption.addClass('NB-active');
|
||||
$unshare_button.toggleClass('NB-hidden', !this.model.get("shared"));
|
||||
$twitter_button.toggleClass('NB-active', !!NEWSBLUR.assets.preference('post_to_twitter'));
|
||||
$facebook_button.toggleClass('NB-active', !!NEWSBLUR.assets.preference('post_to_facebook'));
|
||||
var $share_clone = $share.clone();
|
||||
var full_height = $share_clone.css({
|
||||
'height': 'auto',
|
||||
|
@ -100,8 +121,10 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
}, {
|
||||
'duration': 350,
|
||||
'easing': 'easeInOutQuint',
|
||||
'queue': false
|
||||
// 'complete': _.bind(this.fetch_story_locations_in_feed_view, this, {'reset_timer': true})
|
||||
'queue': false,
|
||||
'complete': function() {
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
}
|
||||
}).data('original_height', original_height);
|
||||
}
|
||||
this.update_share_button_label();
|
||||
|
@ -109,38 +132,72 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
e.preventDefault();
|
||||
this.mark_story_as_shared({'source': 'sideoption'});
|
||||
}, this);
|
||||
$('.NB-sideoption-share-comments', $share).bind('keydown', 'ctrl+return,meta+return', share);
|
||||
var $comments = $('.NB-sideoption-share-comments', $share);
|
||||
$comments.unbind('keydown.story_share')
|
||||
.bind('keydown.story_share', 'ctrl+return', share)
|
||||
.bind('keydown.story_share', 'meta+return', share);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
mark_story_as_shared: function(options) {
|
||||
options = options || {};
|
||||
var $share_star = this.model.story_title_view.$('.NB-storytitles-share');
|
||||
var $share_button = this.$('.NB-sideoption-share-save');
|
||||
var $share_button_menu = $('.NB-menu-manage-story-share-save');
|
||||
var $share_menu = $share_button_menu.closest('.NB-sideoption-share');
|
||||
var $share_sideoption = this.model.story_view.$('.NB-feed-story-share .NB-sideoption-title');
|
||||
var $comments_sideoptions = this.$('.NB-sideoption-share-comments');
|
||||
var $comments_menu = $('.NB-sideoption-share-comments', $share_menu);
|
||||
var comments = _.string.trim((options.source == 'menu' ? $comments_menu : $comments_sideoptions).val());
|
||||
var feed = NEWSBLUR.reader.model.get_feed(NEWSBLUR.reader.active_feed);
|
||||
var feed = NEWSBLUR.assets.get_feed(NEWSBLUR.reader.active_feed);
|
||||
var source_user_id = feed && feed.get('user_id');
|
||||
var post_to_services = _.compact([
|
||||
NEWSBLUR.assets.preference('post_to_twitter') && 'twitter',
|
||||
NEWSBLUR.assets.preference('post_to_facebook') && 'facebook'
|
||||
]);
|
||||
|
||||
this.model.set("shared", true);
|
||||
$share_button.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
||||
$share_button_menu.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
||||
NEWSBLUR.assets.mark_story_as_shared(this.model.id, this.model.get('story_feed_id'), comments, source_user_id, _.bind(function() {
|
||||
this.toggle_feed_story_share_dialog({'close': true});
|
||||
NEWSBLUR.reader.hide_confirm_story_share_menu_item(true);
|
||||
$share_button.removeClass('NB-saving').removeClass('NB-disabled').text('Share');
|
||||
$share_sideoption.text('Shared').closest('.NB-sideoption');
|
||||
this.model.story_view.$el.addClass('NB-story-shared');
|
||||
$comments_menu.val(comments);
|
||||
$comments_sideoptions.val(comments);
|
||||
this.model.story_view.render_comments();
|
||||
|
||||
$share_star.attr({'title': 'Shared!'});
|
||||
NEWSBLUR.assets.mark_story_as_shared(this.model.id, this.model.get('story_feed_id'), comments, source_user_id, post_to_services, _.bind(this.post_share_story, this, true), _.bind(function(data) {
|
||||
this.post_share_error(data, true);
|
||||
}, this));
|
||||
|
||||
NEWSBLUR.reader.blur_to_page();
|
||||
},
|
||||
|
||||
mark_story_as_unshared: function(options) {
|
||||
options = options || {};
|
||||
var $unshare_button = this.$('.NB-sideoption-share-unshare');
|
||||
var $unshare_button_menu = $('.NB-menu-manage-story-share-unshare');
|
||||
var $share_menu = $unshare_button_menu.closest('.NB-sideoption-share');
|
||||
|
||||
$unshare_button.addClass('NB-saving').addClass('NB-disabled').text('Deleting...');
|
||||
NEWSBLUR.assets.mark_story_as_unshared(this.model.id, this.model.get('story_feed_id'), _.bind(this.post_share_story, this, false), _.bind(function(data) {
|
||||
this.post_share_error(data, false);
|
||||
}, this));
|
||||
|
||||
NEWSBLUR.reader.blur_to_page();
|
||||
},
|
||||
|
||||
post_share_story: function(shared) {
|
||||
this.model.set("shared", shared);
|
||||
|
||||
var $share_star = this.model.story_title_view.$('.NB-storytitles-share');
|
||||
var $share_button = this.$('.NB-sideoption-share-save');
|
||||
var $unshare_button = this.$('.NB-sideoption-share-unshare');
|
||||
var $share_sideoption = this.model.story_view.$('.NB-feed-story-share .NB-sideoption-title');
|
||||
var $comments_sideoptions = this.$('.NB-sideoption-share-comments');
|
||||
var shared_text = this.model.get('shared') ? 'Shared' : 'Unshared';
|
||||
|
||||
this.toggle_feed_story_share_dialog({'close': true});
|
||||
NEWSBLUR.reader.hide_confirm_story_share_menu_item(true);
|
||||
$share_button.removeClass('NB-saving').removeClass('NB-disabled').text('Share');
|
||||
$unshare_button.removeClass('NB-saving').removeClass('NB-disabled').text('Delete Share');
|
||||
$share_sideoption.text(shared_text).closest('.NB-sideoption');
|
||||
this.model.story_view.$el.toggleClass('NB-story-shared', this.model.get('shared'));
|
||||
this.model.story_view.render_comments();
|
||||
|
||||
if (this.model.get('shared')) {
|
||||
$share_star.attr({'title': shared_text + '!'});
|
||||
$share_star.tipsy({
|
||||
gravity: 'sw',
|
||||
fade: true,
|
||||
|
@ -157,25 +214,34 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
tipsy.disable();
|
||||
}
|
||||
}, 850);
|
||||
// this.fetch_story_locations_in_feed_view({'reset_timer': true});
|
||||
}, this), _.bind(function(data) {
|
||||
var message = data && data.message || "Sorry, this story could not be shared. Probably a bug.";
|
||||
if (!NEWSBLUR.Globals.is_authenticated) {
|
||||
message = "You need to be logged in to share a story.";
|
||||
}
|
||||
var $error = $.make('div', { className: 'NB-error' }, message);
|
||||
$share_button.removeClass('NB-saving').removeClass('NB-disabled').text('Share');
|
||||
$share_button.siblings('.NB-error').remove();
|
||||
$share_button.after($error);
|
||||
if ($share_button_menu.length) {
|
||||
$share_button_menu.removeClass('NB-disabled').text('Share');
|
||||
$share_button_menu.siblings('.NB-error').remove();
|
||||
$share_button_menu.after($error.clone());
|
||||
}
|
||||
this.toggle_feed_story_share_dialog({'resize_open': true});
|
||||
}, this));
|
||||
}
|
||||
|
||||
NEWSBLUR.reader.blur_to_page();
|
||||
NEWSBLUR.app.story_list.fetch_story_locations_in_feed_view();
|
||||
},
|
||||
|
||||
post_share_error: function(data, shared) {
|
||||
var $share_button = this.$('.NB-sideoption-share-save');
|
||||
var $unshare_button = this.$('.NB-sideoption-share-unshare');
|
||||
var $share_button_menu = $('.NB-menu-manage-story-share-save');
|
||||
var message = data && data.message || ("Sorry, this story could not be " + (shared ? "" : "un") + "shared. Probably a bug.");
|
||||
console.log(["post_share_error", data, shared, message]);
|
||||
|
||||
if (!NEWSBLUR.Globals.is_authenticated) {
|
||||
message = "You need to be logged in to share a story.";
|
||||
}
|
||||
var $error = $.make('div', { className: 'NB-error' }, message);
|
||||
|
||||
$share_button.removeClass('NB-saving').removeClass('NB-disabled').text('Share');
|
||||
$unshare_button.removeClass('NB-saving').removeClass('NB-disabled').text('Delete Share');
|
||||
$share_button.siblings('.NB-error').remove();
|
||||
$share_button.after($error);
|
||||
|
||||
if ($share_button_menu.length) {
|
||||
$share_button_menu.removeClass('NB-disabled').text('Share');
|
||||
$share_button_menu.siblings('.NB-error').remove();
|
||||
$share_button_menu.after($error.clone());
|
||||
}
|
||||
this.toggle_feed_story_share_dialog({'resize_open': true});
|
||||
},
|
||||
|
||||
update_share_button_label: function() {
|
||||
|
@ -195,6 +261,30 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
|||
count_selected_words_when_sharing_story: function($feed_story) {
|
||||
var $wordcount = $('.NB-sideoption-share-wordcount', $feed_story);
|
||||
|
||||
},
|
||||
|
||||
toggle_twitter: function() {
|
||||
var $twitter_button = this.$('.NB-sideoption-share-crosspost-twitter');
|
||||
|
||||
if (NEWSBLUR.assets.preference('post_to_twitter')) {
|
||||
NEWSBLUR.assets.preference('post_to_twitter', false);
|
||||
} else {
|
||||
NEWSBLUR.assets.preference('post_to_twitter', true);
|
||||
}
|
||||
|
||||
$twitter_button.toggleClass('NB-active', NEWSBLUR.assets.preference('post_to_twitter'));
|
||||
},
|
||||
|
||||
toggle_facebook: function() {
|
||||
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
||||
|
||||
if (NEWSBLUR.assets.preference('post_to_facebook')) {
|
||||
NEWSBLUR.assets.preference('post_to_facebook', false);
|
||||
} else {
|
||||
NEWSBLUR.assets.preference('post_to_facebook', true);
|
||||
}
|
||||
|
||||
$facebook_button.toggleClass('NB-active', NEWSBLUR.assets.preference('post_to_facebook'));
|
||||
}
|
||||
|
||||
});
|
|
@ -4,7 +4,7 @@ NEWSBLUR.Views.StoryTitlesView = Backbone.View.extend({
|
|||
|
||||
events: {
|
||||
"click .NB-feed-story-premium-only a" : function() {
|
||||
NEWSBLUR.reader.open_feedchooser_dialog();
|
||||
NEWSBLUR.reader.open_feedchooser_modal();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -12,6 +12,7 @@ NEWSBLUR.Views.StoryTitlesView = Backbone.View.extend({
|
|||
_.bindAll(this, 'scroll');
|
||||
this.collection.bind('reset', this.render, this);
|
||||
this.collection.bind('add', this.add, this);
|
||||
this.collection.bind('no_more_stories', this.check_premium_river, this);
|
||||
NEWSBLUR.reader.$s.$story_titles.scroll(this.scroll);
|
||||
},
|
||||
|
||||
|
@ -38,6 +39,7 @@ NEWSBLUR.Views.StoryTitlesView = Backbone.View.extend({
|
|||
var collection = this.collection;
|
||||
if (options.added) {
|
||||
var $stories = _.map(this.collection.models.slice(-1 * options.added), function(story) {
|
||||
if (story.story_title_view) return;
|
||||
return new NEWSBLUR.Views.StoryTitleView({
|
||||
model: story,
|
||||
collection: collection
|
||||
|
@ -62,6 +64,7 @@ NEWSBLUR.Views.StoryTitlesView = Backbone.View.extend({
|
|||
this.$('.NB-feed-story-premium-only').remove();
|
||||
this.$el.append($notice);
|
||||
},
|
||||
|
||||
// ===========
|
||||
// = Actions =
|
||||
// ===========
|
||||
|
@ -148,6 +151,11 @@ NEWSBLUR.Views.StoryTitlesView = Backbone.View.extend({
|
|||
}
|
||||
},
|
||||
|
||||
check_premium_river: function() {
|
||||
this.show_no_more_stories();
|
||||
this.append_river_premium_only_notification();
|
||||
},
|
||||
|
||||
end_loading: function() {
|
||||
var $endbar = NEWSBLUR.reader.$s.$story_titles.find('.NB-story-titles-end-stories-line');
|
||||
$endbar.remove();
|
||||
|
@ -155,10 +163,6 @@ NEWSBLUR.Views.StoryTitlesView = Backbone.View.extend({
|
|||
|
||||
if (NEWSBLUR.assets.flags['no_more_stories']) {
|
||||
this.show_no_more_stories();
|
||||
} else if (NEWSBLUR.reader.flags['non_premium_river_view'] &&
|
||||
this.collection.visible().length >= NEWSBLUR.reader.constants.RIVER_STORIES_FOR_STANDARD_ACCOUNT) {
|
||||
this.show_no_more_stories();
|
||||
this.append_river_premium_only_notification();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
30
settings.py
|
@ -10,7 +10,7 @@ from utils import jammit
|
|||
# ===================
|
||||
|
||||
ADMINS = (
|
||||
('Samuel Clay', 'samuel@ofbrooklyn.com'),
|
||||
('Samuel Clay', 'samuel@newsblur.com'),
|
||||
)
|
||||
|
||||
SERVER_EMAIL = 'server@newsblur.com'
|
||||
|
@ -94,6 +94,7 @@ MIDDLEWARE_CLASSES = (
|
|||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'apps.profile.middleware.LastSeenMiddleware',
|
||||
'apps.profile.middleware.SQLLogToConsoleMiddleware',
|
||||
'subdomains.middleware.SubdomainMiddleware',
|
||||
# 'debug_toolbar.middleware.DebugToolbarMiddleware',
|
||||
)
|
||||
|
||||
|
@ -180,6 +181,16 @@ TEST_RUNNER = "utils.testrunner.TestRunner"
|
|||
SESSION_COOKIE_NAME = 'newsblur_sessionid'
|
||||
SESSION_COOKIE_AGE = 60*60*24*365*2 # 2 years
|
||||
|
||||
# ==============
|
||||
# = Subdomains =
|
||||
# ==============
|
||||
|
||||
SUBDOMAIN_URLCONFS = {
|
||||
None: 'urls',
|
||||
'www': 'urls',
|
||||
}
|
||||
REMOVE_WWW_FROM_DOMAIN = True
|
||||
|
||||
# ===========
|
||||
# = Logging =
|
||||
# ===========
|
||||
|
@ -240,6 +251,10 @@ ZEBRA_ENABLE_APP = True
|
|||
import djcelery
|
||||
djcelery.setup_loader()
|
||||
CELERY_ROUTES = {
|
||||
"work-queue": {
|
||||
"queue": "work_queue",
|
||||
"binding_key": "work_queue"
|
||||
},
|
||||
"new-feeds": {
|
||||
"queue": "new_feeds",
|
||||
"binding_key": "new_feeds"
|
||||
|
@ -254,6 +269,11 @@ CELERY_ROUTES = {
|
|||
},
|
||||
}
|
||||
CELERY_QUEUES = {
|
||||
"work_queue": {
|
||||
"exchange": "work_queue",
|
||||
"exchange_type": "direct",
|
||||
"binding_key": "work_queue",
|
||||
},
|
||||
"new_feeds": {
|
||||
"exchange": "new_feeds",
|
||||
"exchange_type": "direct",
|
||||
|
@ -270,13 +290,13 @@ CELERY_QUEUES = {
|
|||
"binding_key": "update_feeds"
|
||||
},
|
||||
}
|
||||
CELERY_DEFAULT_QUEUE = "update_feeds"
|
||||
BROKER_BACKEND = "redis"
|
||||
CELERY_DEFAULT_QUEUE = "work_queue"
|
||||
BROKER_BACKEND = "redis"
|
||||
BROKER_URL = "redis://db01:6379/0"
|
||||
CELERY_REDIS_HOST = "db01"
|
||||
CELERY_REDIS_HOST = "db01"
|
||||
|
||||
CELERYD_PREFETCH_MULTIPLIER = 1
|
||||
CELERY_IMPORTS = ("apps.rss_feeds.tasks", )
|
||||
CELERY_IMPORTS = ("apps.rss_feeds.tasks", "apps.social.tasks", )
|
||||
CELERYD_CONCURRENCY = 4
|
||||
CELERY_IGNORE_RESULT = True
|
||||
CELERY_ACKS_LATE = True # Retry if task fails
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
{% block body %}{% endblock body %}
|
||||
|
||||
- Samuel Clay, @samuelclay
|
||||
- Samuel & Roy
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Stay up to date and in touch with me, yr. developer, in a few different ways:
|
||||
NewsBlur is your social news reader. A new sound of an old instrument.
|
||||
|
||||
Stay up to date and in touch with us, yr. developers, in a few different ways:
|
||||
|
||||
* Follow @samuelclay on Twitter: http://twitter.com/samuelclay/
|
||||
* Follow @newsblur on Twitter: http://twitter.com/newsblur/
|
||||
* Follow @samuelclay on GitHub: http://github.com/samuelclay/
|
||||
|
||||
{% block resources_header %}There are a few resources you can use if you end up loving NewsBlur:{% endblock resources_header %}
|
||||
{% block resources_header %}To get the most out of NewsBlur, here are a few resources:{% endblock resources_header %}
|
||||
|
||||
* Read the NewsBlur Blog: http://blog.newsblur.com
|
||||
* Get support on NewsBlur's Get Satisfaction: http://getsatisfaction.com/newsblur/
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
{% block body %}{% endblock %}
|
||||
|
||||
<p style="line-height:20px;">- Samuel Clay, <a href="http://twitter.com/samuelclay" style="text-decoration:none">@samuelclay</a></p>
|
||||
<p style="line-height:20px;clear: both;">- Samuel & Roy</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -28,22 +28,22 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<p style="line-height:20px;">Stay up to date and in touch with me, yr. developer, in a few different ways:</p>
|
||||
<p style="line-height:20px;">NewsBlur is your social news reader. A new sound of an old instrument.</p>
|
||||
<p style="line-height:20px;">Stay up to date and in touch with us, yr. developers, in a few different ways:</p>
|
||||
<p style="line-height: 20px;">
|
||||
<ul style="list-style: none;">
|
||||
<li style="line-height:22px;"><a href="http://twitter.com/samuelclay/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/twitter_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @samuelclay on Twitter</a>.</li>
|
||||
<li style="line-height:22px;"><a href="http://twitter.com/newsblur/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/twitter.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @newsblur on Twitter</a>.</li>
|
||||
<li style="line-height:22px;"><a href="http://github.com/samuelclay/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/github_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @samuelclay on GitHub</a>. ← I live on props.</li>
|
||||
<li style="line-height:22px;"><a href="http://github.com/samuelclay/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/github_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @samuelclay on GitHub</a>.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p style="line-height: 20px;">{% block resources_header %}There are a couple resources you can use if you end up loving NewsBlur:{% endblock resources_header %}</p>
|
||||
<p style="line-height: 20px;">{% block resources_header %}To get the most out of NewsBlur, here are a few resources:{% endblock resources_header %}</p>
|
||||
<p style="line-height: 20px;">
|
||||
<ul style="list-style: none;">
|
||||
<li style="line-height:22px;"><a href="http://blog.newsblur.com" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/favicon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Read the NewsBlur Blog</a>.</li>
|
||||
<li style="line-height:22px;"><a href="http://getsatisfaction.com/newsblur/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/getsatisfaction.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Get support on NewsBlur's Get Satisfaction</a>.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p style="line-height: 20px;">There's plenty of ways to use NewsBlur beyond the website:</p>
|
||||
<p style="line-height: 20px;">There's plenty of ways to use NewsBlur beyond the web:</p>
|
||||
<p style="line-height: 20px;">
|
||||
<ul style="list-style: none;">
|
||||
<li style="line-height:22px;"><a href="http://www.newsblur.com/iphone/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/iphone_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Download the free iPhone App</a>.</li>
|
||||
|
|
|
@ -6,3 +6,5 @@
|
|||
<p style="line-height: 20px;">Spend a few days trying out NewsBlur. I hope you end up loving it.</p>
|
||||
<p style="line-height: 20px;">If you really do love using NewsBlur you should purchase a fancy <b>premium account</b> for only $12/year (nights and weekends and all major public holidays included). You get to support an independent developer, help feed his dog, and contribute to the long-term health of NewsBlur.</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block resources_header %}There are a couple resources you can use if you end up loving NewsBlur:{% endblock resources_header %}
|
14
templates/mail/email_new_follower.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends "mail/email_base.txt" %}
|
||||
|
||||
{% block body %}Say hello to your newest follower: {{ follower_profile.username }}.
|
||||
|
||||
{% if common_followers %}
|
||||
You follow {{ common_followers|length }} {{ common_followers|pluralize:"person,people" }} who follow{{ common_followers|pluralize:"s," }} {{ follower_profile.username }}:
|
||||
|
||||
{% for follower in common_followers %} * {{ follower.username }}: {{ follower.blurblog_url }}
|
||||
{% endfor %}{% endif %}
|
||||
|
||||
{% if common_followings %}You follow {{ common_followings|length }} {{ common_followings|pluralize:"person,people" }} that {{ follower_profile.username }} also follows:
|
||||
|
||||
{% for following in common_followings %} * {{ following.username }}: {{ following.blurblog_url }}
|
||||
{% endfor %}{% endif %}{% endblock %}
|
36
templates/mail/email_new_follower.xhtml
Normal file
|
@ -0,0 +1,36 @@
|
|||
{% extends "mail/email_base.xhtml" %}
|
||||
|
||||
{% block body %}
|
||||
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">
|
||||
Say hello to your newest follower:
|
||||
</p>
|
||||
<div style="margin: 24px 0;font-size: 24px;text-align: center;">
|
||||
<a href="{{ follower_profile.blurblog_url }}"><img src="{{ follower_profile.photo_url }}" style="max-width: 200px; max-height: 200px;margin: 0 auto;border-radius: 3px;border: none;"></a>
|
||||
<div style="margin: 8px 0 0 0;font-weight: bold;"><a href="{{ follower_profile.blurblog_url }}" style="color: #404040;text-decoration: none">{{ follower_profile.username }}</a></div>
|
||||
</div>
|
||||
|
||||
{% if common_followers %}
|
||||
<div style="clear: both; overflow: hidden">
|
||||
<p style="margin: 12px 0 12px;line-height: 16px;clear: both;">You follow {{ common_followers|length }} {{ common_followers|pluralize:"person,people" }} who follow{{ common_followers|pluralize:"s," }} {{ follower_profile.username }}:</p>
|
||||
{% for follower in common_followers %}
|
||||
<div style="margin: 0 12px 12px 0; float: left;">
|
||||
<a href="{{ follower.blurblog_url }}"><img src="{{ follower.email_photo_url }}" style="float: left; border-radius: 3px;margin-right: 6px; width: 24px; height: 24px;border: none;"></a>
|
||||
<a href="{{ follower.blurblog_url }}" style="color: #404040;text-decoration: none">{{ follower.username }}</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if common_followings %}
|
||||
<div style="clear: both; overflow: hidden">
|
||||
<p style="display: block; margin: 12px 0 12px;line-height: 16px;clear: both;">You and {{ follower_profile.username }} both follow {{ common_followings|length }} {{ common_followings|pluralize:"person,people" }}:</p>
|
||||
{% for following in common_followings %}
|
||||
<div style="margin: 0 12px 12px 0; float: left;">
|
||||
<a href="{{ following.blurblog_url }}"><img src="{{ following.email_photo_url }}" style="float: left; border-radius: 3px;margin-right: 6px; width: 24px; height: 24px;border: none;"></a>
|
||||
<a href="{{ following.blurblog_url }}" style="color: #404040;text-decoration: none">{{ following.username }}</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -80,7 +80,7 @@
|
|||
<div class="NB-signup-optional">
|
||||
{% if login_form.errors %}
|
||||
{% for field, error in login_form.errors.items %}
|
||||
<a href="mailto:samuel@ofbrooklyn.com?subject=Forgot%20Password%20on%20NewsBlur&body=Hello!%20My%20username%20is:%20" class="NB-splash-link">Forgot password?</a>
|
||||
<a href="mailto:password@newsblur.com?subject=Forgot%20Password%20on%20NewsBlur&body=Hello!%20My%20username%20is:%20" class="NB-splash-link">Forgot password?</a>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
Optional
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
{% load utils_tags %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{ social_profile.feed_title }}</title>
|
||||
<link rel="alternate" type="application/rss+xml" href="{% url shared-stories-rss-feed social_profile.user_id social_profile.username|slugify %}" title="{{ social_profile.feed_title }} RSS feed">
|
||||
<link rel="shortcut icon" HREF="{{ social_profile.photo_url }}">
|
||||
<link rel="stylesheet" href="{{ MEDIA_URL }}css/social/social_page.css" type="text/css" media="screen" title="no title" charset="utf-8">
|
||||
<link rel="shortcut icon" HREF="{{ social_profile.photo_url }}">
|
||||
|
||||
{% include_stylesheets "blurblog" %}
|
||||
|
||||
{% if social_profile.custom_css %}
|
||||
<style type="text/css" media="screen">
|
||||
{{ social_profile.custom_css|safe }}
|
||||
|
@ -15,9 +19,10 @@
|
|||
|
||||
<body>
|
||||
|
||||
<div class="NB-page">
|
||||
<header class="NB-header">
|
||||
<h1 class="NB-title {% if not social_profile.bio %}NB-title-no-bio{% endif %}">
|
||||
<a href="{% url index %}social/{{ social_profile.user_id }}/{{ social_profile.username|slugify }}" class="NB-title-logo">
|
||||
<a href="http://{% current_domain %}/social/{{ social_profile.user_id }}/{{ social_profile.username|slugify }}" class="NB-title-logo">
|
||||
<img src="{{ MEDIA_URL }}img/logo_128.png" class="NB-hover-off" />
|
||||
<img src="{{ MEDIA_URL }}img/logo_newsblur_512.png" class="NB-hover-on" />
|
||||
</a>
|
||||
|
@ -58,8 +63,7 @@
|
|||
<div class="NB-feed NB-feed-{{ story.feed.favicon_text_color }}" style="
|
||||
background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.16, #{{ story.feed.favicon_color }}), color-stop(0.84, #{{ story.feed.favicon_fade }}) );
|
||||
background-image: -moz-linear-gradient( center bottom, #{{ story.feed.favicon_color }} 16%, #{{ story.feed.favicon_fade }} 84% );
|
||||
border-top-color: #{{ story.feed.favicon_border }};
|
||||
border-bottom-color: #{{ story.feed.favicon_border }};
|
||||
border: 1px solid #{{ story.feed.favicon_border }};
|
||||
">
|
||||
{% if story.feed %}
|
||||
<div class="NB-feed-favicon">
|
||||
|
@ -71,31 +75,116 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="NB-story-header">
|
||||
{% if story.story_authors %}
|
||||
<div class="NB-story-author">{{ story.story_authors }}</div>
|
||||
{% endif %}
|
||||
{% if story.story_tags %}
|
||||
<div class="NB-story-tags">
|
||||
{% for story_tag in story.story_tags %}
|
||||
<div class="NB-story-tag">{{ story_tag }}</div>
|
||||
{% endfor %}
|
||||
<div class="NB-story-header-wrapper">
|
||||
<div class="NB-story-header">
|
||||
{% if story.story_authors %}
|
||||
<div class="NB-story-author">{{ story.story_authors }}</div>
|
||||
{% endif %}
|
||||
{% if story.story_tags %}
|
||||
<div class="NB-story-tags">
|
||||
{% for story_tag in story.story_tags %}
|
||||
<div class="NB-story-tag">{{ story_tag }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="NB-story-title">
|
||||
<a href="{{ story.story_permalink }}">{{ story.story_title }}</a>
|
||||
</div>
|
||||
<div class="NB-story-date">
|
||||
{% if story.has_modifications %}
|
||||
<div class="NB-story-modifications-button" title="Show story changes"></div>
|
||||
{% endif %}
|
||||
|
||||
{{ story.shared_date|date:"l, F j<\s\u\p>S</\s\u\p>, Y <\s\m\a\l\l>\a\t</\s\m\a\l\l> g:i A"|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="NB-story-title">
|
||||
<a href="{{ story.story_permalink }}">{{ story.story_title }}</a>
|
||||
</div>
|
||||
<div class="NB-story-date">
|
||||
{{ story.shared_date|date:"g:i A <\s\m\a\l\l>\o\n</\s\m\a\l\l> l, F j<\s\u\p>S</\s\u\p>, Y"|safe }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="NB-story">
|
||||
<div class="NB-story-content">{{ story.story_content|safe }}</div>
|
||||
|
||||
{% if story.share_count %}
|
||||
<div class="NB-story-comments">
|
||||
<div class="NB-story-comments-shares-teaser-wrapper">
|
||||
<div class="NB-story-comments-shares-teaser">
|
||||
{% if story.share_count %}
|
||||
<div class="NB-right">
|
||||
Shared by
|
||||
<b>{{ story.share_count }}</b>
|
||||
{{ story.share_count|pluralize:"person, people" }}
|
||||
</div>
|
||||
{% if story.share_count_public %}
|
||||
<div class="NB-story-share-profiles NB-story-share-profiles-public">
|
||||
{% for share_user in story.shared_by_public %}
|
||||
<a href="{{ share_user.feed_link }}" class="NB-user-avatar" title="{{ share_user.username }}">
|
||||
<img src="{{ share_user.photo_url }}">
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if story.share_count %}
|
||||
{% if story.share_count_friends %}
|
||||
<div class="NB-story-share-label">Shared by: </div>
|
||||
<div class="NB-story-share-profiles NB-story-share-profiles-friends">
|
||||
{% for share_user in story.shared_by_friends %}
|
||||
<a href="{{ share_user.feed_link }}" class="NB-user-avatar" title="{{ share_user.username }}">
|
||||
<img src="{{ share_user.photo_url }}">
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% for comment in story.comments %}
|
||||
<div class="NB-story-comment">
|
||||
<a href="{{ comment.user.feed_link }}" class="NB-user-avatar {% if comment.source_user_id %}NB-story-comment-reshare{% endif %}">
|
||||
<img src="{{ comment.user.photo_url }}">
|
||||
</a>
|
||||
<div class="NB-story-comment-author-container">
|
||||
{% if comment.source_user_id %}
|
||||
<div class="NB-story-comment-reshares">
|
||||
<a href="{{ comment.source_user.feed_link }}" class="NB-user-avatar" title="{{ comment.source_user.username }}">
|
||||
<img src="{{ comment.source_user.photo_url }}">
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<a href="{{ comment.user.feed_link }}" class="NB-story-comment-username">{{ comment.user.username }}</a>
|
||||
<div class="NB-story-comment-date">{{ comment.shared_date }} ago</div>
|
||||
<div class="NB-story-comment-reply-button">
|
||||
<div class="NB-story-comment-reply-button-wrapper">reply</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="NB-story-comment-content">
|
||||
{{ comment.comments }}
|
||||
</div>
|
||||
{% if comment.replies %}
|
||||
<div class="NB-story-comment-replies">
|
||||
{% for reply in comment.replies %}
|
||||
<div class="NB-story-comment-reply">
|
||||
<a href="{{ reply.user.feed_link }}">
|
||||
<img class="NB-user-avatar NB-story-comment-reply-photo" src="{{ reply.user.photo_url }}" />
|
||||
</a>
|
||||
<a href="{{ reply.user.feed_link }}" class="NB-story-comment-username NB-story-comment-reply-username">{{ reply.user.username }}</a>
|
||||
<div class="NB-story-comment-date NB-story-comment-reply-date">{{ reply.publish_date }} ago</div>
|
||||
<div class="NB-story-comment-reply-content">{{ reply.comments }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
||||
{% include_javascripts "blurblog" %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -20,7 +20,7 @@
|
|||
<ul class="NB-about-who">
|
||||
<li>Hand-crafted by: <a href="http://www.samuelclay.com">Samuel Clay</a></li>
|
||||
<li>Talk to him on Twitter: <a href="http://twitter.com/samuelclay">@samuelclay</a></li>
|
||||
<li>E-mail: <a href="mailto:samuel@ofbrooklyn.com">samuel@ofbrooklyn.com</a></li>
|
||||
<li>E-mail: <a href="mailto:samuel@newsblur.com">samuel@newsblur.com</a></li>
|
||||
<li class="last">Created in: <a href="http://www.newyorkfieldguide.com">New York City</a> (mostly on the A train)</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -14,17 +14,22 @@
|
|||
<div class="NB-module">
|
||||
<h5 class="NB-module-title">Introduction to the API</h5>
|
||||
<div class="NB-module-content">
|
||||
<p><a href="/">NewsBlur</a> is an RSS feed reader with intelligence.</p>
|
||||
<p><a href="/">NewsBlur</a> is a social news reader with intelligence. A new sound of
|
||||
an old instrument.</p>
|
||||
<p>NewsBlur's API allows users to retrieve their feeds, feed counts, feed icons, feed
|
||||
statistics, and individual feed stories. No API key is required, but you are required
|
||||
to authenticate before using any of the API endpoints. Please be considerate, and don't
|
||||
hammer our servers.</p>
|
||||
<p>It is a very nice thing to note that this entire API is open-source, including
|
||||
<p>We're quite pleased to point out that this entire API is open-source, including
|
||||
the implementation of the endpoints. You can find the source of the
|
||||
<a href="http://github.com/samuelclay/NewsBlur/tree/master/apps/reader/views.py">/reader/ views</a>,
|
||||
<a href="http://github.com/samuelclay/NewsBlur/tree/master/apps/rss_feeds/views.py">/rss_feeds/ views</a>,
|
||||
<a href="http://github.com/samuelclay/NewsBlur/tree/master/apps/reader/views.py">/reader/ views source</a>,
|
||||
<a href="http://github.com/samuelclay/NewsBlur/tree/master/apps/social/views.py">/social/ views source</a>,
|
||||
<a href="http://github.com/samuelclay/NewsBlur/tree/master/apps/rss_feeds/views.py">/rss_feeds/ views source</a>,
|
||||
as well as
|
||||
<a href="http://github.com/samuelclay/NewsBlur/tree/master/templates/static/api.yml">the API definitions in YAML</a>.</p>
|
||||
<p>We love pull requests. If you want to add an endpoint, modify output, or make
|
||||
something better, <a href="http://github.com/samuelclay/NewsBlur">NewsBlur's repo
|
||||
on Github</a> is the place to make that happen.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
- key: email
|
||||
desc: "Email address"
|
||||
optional: true
|
||||
example: "samuel@ofbrooklyn.com"
|
||||
example: "samuel@newsblur.com"
|
||||
|
||||
- feeds:
|
||||
- url: /rss_feeds/search_feed
|
||||
|
@ -108,7 +108,7 @@
|
|||
To use inline data images, you can use this syntax:
|
||||
<pre><code><img src="data:image/png;base64,[IMAGE_DATA_STRING]" /></code></pre>
|
||||
params:
|
||||
- key: feeds
|
||||
- key: feed_ids
|
||||
desc: " Array of feed ids. Leave empty to retrieve all active (enabled) feeds."
|
||||
optional: true
|
||||
example: "[1, 2, 3]"
|
||||
|
@ -231,7 +231,9 @@
|
|||
- key: story_id
|
||||
desc: "List of story ids to mark as read."
|
||||
required: true
|
||||
example: "[12, 24, 36]"
|
||||
example: >
|
||||
["http://blog.newsblur.com/post/1",
|
||||
"http://blog.newsblur.com/post/2"]
|
||||
- key: feed_id
|
||||
desc: "Feed id that each story is from."
|
||||
required: true
|
||||
|
@ -309,7 +311,239 @@
|
|||
optional: true
|
||||
default: "0"
|
||||
example: "7"
|
||||
|
||||
|
||||
- social:
|
||||
- url: /social/share_story
|
||||
method: POST
|
||||
short_desc: "Share a story with optional comments."
|
||||
long_desc:
|
||||
- "Share a story with optional comments. The story is shared on the user's blurblog."
|
||||
params:
|
||||
- key: feed_id
|
||||
desc: "Feed id that the story is from."
|
||||
required: true
|
||||
example: "42"
|
||||
- key: story_id
|
||||
desc: "Story id to share."
|
||||
required: true
|
||||
example: "http://blog.newsblur.com/post/1"
|
||||
- key: comments
|
||||
desc: "The meat of the share."
|
||||
optional: true
|
||||
example: "42"
|
||||
- key: source_user_id
|
||||
desc: >
|
||||
If the story is being re-shared from another blurblog, note the
|
||||
user_id of the original sharer.
|
||||
optional: true
|
||||
example: "128"
|
||||
- key: post_to_services
|
||||
desc: "List of services to cross-post to. Can be 'twitter' and/or 'facebook'."
|
||||
optional: true
|
||||
example: "['twitter', 'facebook']"
|
||||
- url: /social/unshare_story
|
||||
method: POST
|
||||
short_desc: "Remove a shared story from user's blurblog."
|
||||
long_desc:
|
||||
- >
|
||||
Removes a shared story from a user's blurblog. Unshares the story and
|
||||
removes the comments. Any replies will also be deleted. This may change.
|
||||
params:
|
||||
- key: feed_id
|
||||
desc: "Feed id that the story is from."
|
||||
required: true
|
||||
example: "42"
|
||||
- key: story_id
|
||||
desc: "Story id to remove the existing share."
|
||||
required: true
|
||||
example: "http://blog.newsblur.com/post/1"
|
||||
- url: /social/load_user_friends
|
||||
method: GET
|
||||
short_desc: "Lists of user profiles: followers, followings, etc."
|
||||
long_desc:
|
||||
- This lists the user profiles of followers and followings of a user.
|
||||
- Also returns information related to which sharing services a user is using.
|
||||
- url: /social/profile
|
||||
method: GET
|
||||
short_desc: "Public profile of a user."
|
||||
long_desc:
|
||||
- "Public profile of a user. Includes common followers and common followings."
|
||||
params:
|
||||
- key: user_id
|
||||
desc: "User id of user"
|
||||
required: true
|
||||
example: "42"
|
||||
- url: /social/load_user_profile
|
||||
method: GET
|
||||
short_desc: "Private details of the current user's profile and connected services."
|
||||
long_desc:
|
||||
- "Private details of the current user's profile and connected services."
|
||||
- url: /social/save_user_profile
|
||||
method: POST
|
||||
short_desc: "Saves a user's profile details."
|
||||
long_desc:
|
||||
- "Saves a user's profile details."
|
||||
params:
|
||||
- key: location
|
||||
desc: "Hometown"
|
||||
optional: true
|
||||
example: "New York City"
|
||||
- key: bio
|
||||
desc: "160 character bio."
|
||||
optional: true
|
||||
example: "Developer. API Designer."
|
||||
- key: website
|
||||
desc: "Website address"
|
||||
optional: true
|
||||
example: "http://www.samuelclay.com"
|
||||
- key: photo_service
|
||||
desc: "Which photo service to use: twitter, facebook, gravatar."
|
||||
optional: true
|
||||
example: "twitter"
|
||||
- url: /social/interactions
|
||||
method: GET
|
||||
short_desc: "Interactions between a user and other users."
|
||||
long_desc:
|
||||
- "Interactions between a user and other users."
|
||||
- Currently only serves HTML. Email samuel@newsblur.com if you want this data in JSON.
|
||||
- url: /social/follow
|
||||
method: POST
|
||||
short_desc: "Follow a user and subscribe to their blurblog."
|
||||
long_desc:
|
||||
- "Follow a user and subscribe to their blurblog."
|
||||
params:
|
||||
- key: user_id
|
||||
desc: "ID of user to follow."
|
||||
required: true
|
||||
example: "42"
|
||||
- url: /social/unfollow
|
||||
method: POST
|
||||
short_desc: "Unfollow a user and unsubscribe from their blurblog."
|
||||
long_desc:
|
||||
- "Unfollow a user and unsubscribe from their blurblog."
|
||||
params:
|
||||
- key: user_id
|
||||
desc: "ID of user to unfollow."
|
||||
required: true
|
||||
example: "42"
|
||||
- url: /social/feed_trainer
|
||||
method: GET
|
||||
short_desc: "Get the intelligence classifiers for a blurblog."
|
||||
long_desc:
|
||||
- "Get the intelligence classifiers for a blurblog."
|
||||
params:
|
||||
- key: user_id
|
||||
desc: "ID of blurblog's user."
|
||||
required: true
|
||||
example: "42"
|
||||
- url: /social/comments
|
||||
method: GET
|
||||
short_desc: "Get all public comments on a shared story."
|
||||
long_desc:
|
||||
- "Get all public comments on a shared story."
|
||||
- >
|
||||
If you want comments from friends, they are already attached to the
|
||||
story from either <code>reader/feed/:id</code> or
|
||||
<code>/social/stories/:user_id</code>.
|
||||
params:
|
||||
- key: story_id
|
||||
desc: "ID of shared story."
|
||||
required: true
|
||||
example: "http://blog.newsblur.com/post/1"
|
||||
- key: feed_id
|
||||
desc: "ID of feed for the shared story."
|
||||
required: true
|
||||
example: "42"
|
||||
- url: /social/save_comment_reply
|
||||
method: POST
|
||||
short_desc: "Saves a reply to a comment."
|
||||
long_desc:
|
||||
- "Saves a reply to a comment."
|
||||
- "Comments can have a number of replies, but they are all one-level deep."
|
||||
- >
|
||||
Replying to a comment sends notifications to both original commenter and to
|
||||
every other replier to the comment.
|
||||
params:
|
||||
- key: story_feed_id
|
||||
desc: "ID of feed the story belongs to."
|
||||
required: true
|
||||
example: "42"
|
||||
- key: story_id
|
||||
desc: "ID of story being commented on."
|
||||
required: true
|
||||
example: "http://blog.newsblur.com/post/1"
|
||||
- key: comment_user_id
|
||||
desc: "ID of user who left the original comment that is now being replied to."
|
||||
required: true
|
||||
example: "64"
|
||||
- key: reply_comments
|
||||
desc: "The content of the reply."
|
||||
required: true
|
||||
example: "Brilliant analysis."
|
||||
- key: original_message
|
||||
desc: >
|
||||
If editing an existing reply, provide the original reply so the correct
|
||||
reply can be overwritten.
|
||||
optional: true
|
||||
example: "Brilliant analysis, bro."
|
||||
- url: /social/find_friends
|
||||
method: GET
|
||||
short_desc: "Search for a user by username, email, or blurblog title."
|
||||
long_desc:
|
||||
- "Search for a user by username, email, or blurblog title."
|
||||
params:
|
||||
- key: query
|
||||
desc: "Username, email, or part of a blurblog title."
|
||||
required: true
|
||||
example: "samuel"
|
||||
- url: /social/rss/:user_id/:username
|
||||
method: GET
|
||||
short_desc: "RSS feed for a blurblog."
|
||||
long_desc:
|
||||
- "RSS feed for a blurblog."
|
||||
tips:
|
||||
- >
|
||||
The <code>username</code> url parameter is optional. It's just recommended
|
||||
if you have it.
|
||||
- url: /social/stories/:user_id/:username
|
||||
method: GET
|
||||
short_desc: "Shared stories from a user's blurblog."
|
||||
long_desc:
|
||||
- "Shared stories from a user's blurblog."
|
||||
- "Comments, replies, and profiles from followed users are automatically included."
|
||||
tips:
|
||||
- >
|
||||
The <code>username</code> url parameter is optional. It's just recommended
|
||||
if you have it.
|
||||
- url: /social/page/:user_id/:username
|
||||
method: GET
|
||||
short_desc: "A user's shared stories blurblog in HTML."
|
||||
long_desc:
|
||||
- "A user's shared stories blurblog in HTML."
|
||||
- "This may also live at a custom URL, which is specified in the user's full profile."
|
||||
tips:
|
||||
- >
|
||||
The <code>username</code> url parameter is optional. It's just recommended
|
||||
if you have it.
|
||||
- url: /social/settings/:user_id/:username
|
||||
method: GET
|
||||
short_desc: "A user's full profile."
|
||||
long_desc:
|
||||
- "A user's full profile."
|
||||
tips:
|
||||
- >
|
||||
The <code>username</code> url parameter is optional. It's just recommended
|
||||
if you have it.
|
||||
- url: /social/statistics/:user_id/:name
|
||||
method: GET
|
||||
short_desc: "Get statistics and history for a blurblog."
|
||||
long_desc:
|
||||
- "Get statistics and history for a blurblog."
|
||||
tips:
|
||||
- >
|
||||
The <code>username</code> url parameter is optional. It's just recommended
|
||||
if you have it.
|
||||
|
||||
- "feed management":
|
||||
- url: /reader/add_url
|
||||
method: POST
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
How I can prevent NewsBlur from loading the Original view (without using an iFrame buster)?
|
||||
</div>
|
||||
<div class="NB-faq-answer last">
|
||||
<p>If you would like to opt-out of the Original view, simply email <a href="mailto:samuel@ofbrooklyn.com">Samuel Clay</a> and let him know. He will place your site on an opt-out list.</p>
|
||||
<p>If you would like to opt-out of the Original view, simply email <a href="mailto:samuel@newsblur.com">Samuel Clay</a> and let him know. He will place your site on an opt-out list.</p>
|
||||
<p>Note that users will still be able to read the Feed view. However, consider that when in the Original view, your ads and original content are unaffected. Consider instead placing an exception rule in your iFrame buster code that looks for 'www.newsblur.com' in the URL and prevents your iFrame buster from running.</p>
|
||||
</div>
|
||||
</li>
|
||||
|
@ -174,7 +174,7 @@
|
|||
Help! I have an issue and it's not mentioned here.
|
||||
</div>
|
||||
<div class="NB-faq-answer last">
|
||||
Please, please, please e-mail <a href="mailto:samuel@ofbrooklyn.com">samuel@ofbrooklyn.com</a>. If you have an issue it is entirely possible that other people do, too.
|
||||
Please, please, please e-mail <a href="mailto:samuel@newsblur.com">samuel@newsblur.com</a>. If you have an issue it is entirely possible that other people do, too.
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
Thank you for your interest in NewsBlur. NewsBlur is built by a solo developer:
|
||||
<ul>
|
||||
<li><a href="http://www.samuelclay.com">Samuel Clay</a>, founder, <a href="mailto:samuel@ofbrooklyn.com">samuel@ofbrooklyn.com</a>, <a href="http://twitter.com/samuelclay">@samuelclay</a></li>
|
||||
<li><a href="http://www.samuelclay.com">Samuel Clay</a>, founder, <a href="mailto:samuel@newsblur.com">samuel@newsblur.com</a>, <a href="http://twitter.com/samuelclay">@samuelclay</a></li>
|
||||
</ul>
|
||||
Contact Samuel for interviews, comments, and questions about NewsBlur. As another
|
||||
ambitious New Yorker, he is happy to talk about NewsBlur.
|
||||
|
|
31
utils/bootstrap_intel.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
import sys
|
||||
from mongoengine.queryset import OperationError
|
||||
from mongoengine.base import ValidationError
|
||||
from apps.analyzer.models import MClassifierFeed
|
||||
from apps.analyzer.models import MClassifierAuthor
|
||||
from apps.analyzer.models import MClassifierTag
|
||||
from apps.analyzer.models import MClassifierTitle
|
||||
|
||||
for classifier_cls in [MClassifierFeed, MClassifierAuthor,
|
||||
MClassifierTag, MClassifierTitle]:
|
||||
print " ================================================================= "
|
||||
print " Now on %s " % classifier_cls.__name__
|
||||
print " ================================================================= "
|
||||
classifiers = classifier_cls.objects.filter(social_user_id__exists=False)
|
||||
count = classifiers.count()
|
||||
print " ---> Found %s classifiers" % count
|
||||
for i, classifier in enumerate(classifiers):
|
||||
if i % 1000 == 0:
|
||||
print " ---> %s / %s" % (i, count)
|
||||
sys.stdout.flush()
|
||||
classifier.social_user_id = 0
|
||||
try:
|
||||
classifier.save()
|
||||
except OperationError, e:
|
||||
print " ***> Operation error on: %s" % e
|
||||
sys.stdout.flush()
|
||||
# classifier.delete()
|
||||
except ValidationError, e:
|
||||
print " ***> ValidationError error on: %s" % e
|
||||
print " ***> Original classifier: %s" % classifier.__dict__
|
||||
|
|
@ -11,6 +11,7 @@ graph_config = {
|
|||
'celery_update_feeds.label': 'Celery - Update Feeds',
|
||||
'celery_new_feeds.label': 'Celery - New Feeds',
|
||||
'celery_push_feeds.label': 'Celery - Push Feeds',
|
||||
'celery_work_queue.label': 'Celery - Work Queue',
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +29,7 @@ def calculate_metrics():
|
|||
'celery_update_feeds': r.llen("update_feeds"),
|
||||
'celery_new_feeds': r.llen("new_feeds"),
|
||||
'celery_push_feeds': r.llen("push_feeds"),
|
||||
'celery_work_queue': r.llen("work_queue"),
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -146,7 +146,6 @@ class bunch(dict):
|
|||
else:
|
||||
self.__setitem__(item, value)
|
||||
|
||||
|
||||
class MLStripper(HTMLParser):
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
@ -159,4 +158,16 @@ class MLStripper(HTMLParser):
|
|||
def strip_tags(html):
|
||||
s = MLStripper()
|
||||
s.feed(html)
|
||||
return s.get_data()
|
||||
return s.get_data()
|
||||
|
||||
def truncate_chars(value, max_length):
|
||||
if len(value) <= max_length:
|
||||
return value
|
||||
|
||||
truncd_val = value[:max_length]
|
||||
if value[max_length] != " ":
|
||||
rightmost_space = truncd_val.rfind(" ")
|
||||
if rightmost_space != -1:
|
||||
truncd_val = truncd_val[:rightmost_space]
|
||||
|
||||
return truncd_val + "..."
|
|
@ -12,7 +12,7 @@ register = template.Library()
|
|||
@register.simple_tag
|
||||
def current_domain():
|
||||
current_site = Site.objects.get_current()
|
||||
return current_site and current_site.domain
|
||||
return current_site and current_site.domain.replace('www', 'dev')
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def localdatetime(context, date, date_format):
|
||||
|
|