Merge branch 'android' of https://github.com/samuelclay/NewsBlur into android
4
.gitignore
vendored
|
@ -4,6 +4,8 @@ logs/*.pid
|
|||
*.pyc
|
||||
static/*
|
||||
local_settings.py
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
media/iphone/NewsBlur/build
|
||||
media/iphone/build
|
||||
build/
|
||||
|
@ -24,8 +26,8 @@ media/maintenance.html.unused
|
|||
config/settings
|
||||
static.tgz
|
||||
media/css/circular
|
||||
|
||||
config/settings
|
||||
config/secrets
|
||||
|
||||
# ----------------------
|
||||
# Android
|
||||
|
|
|
@ -95,7 +95,10 @@ class MClassifierFeed(mongo.Document):
|
|||
|
||||
def __unicode__(self):
|
||||
user = User.objects.get(pk=self.user_id)
|
||||
feed = Feed.objects.get(pk=self.feed_id) if self.feed_id else None
|
||||
if self.feed_id:
|
||||
feed = Feed.objects.get(pk=self.feed_id)
|
||||
else:
|
||||
feed = User.objects.get(pk=self.social_user_id)
|
||||
return "%s - %s/%s: (%s) %s" % (user, self.feed_id, self.social_user_id, self.score, feed)
|
||||
|
||||
|
||||
|
@ -132,15 +135,19 @@ def apply_classifier_tags(classifiers, story):
|
|||
if score > 0: return classifier.score
|
||||
return score
|
||||
|
||||
def apply_classifier_feeds(classifiers, feed, social_user_id=None):
|
||||
def apply_classifier_feeds(classifiers, feed, social_user_ids=None):
|
||||
if not feed: return 0
|
||||
feed_id = feed if isinstance(feed, int) else feed.pk
|
||||
|
||||
if social_user_ids and not isinstance(social_user_ids, list):
|
||||
social_user_ids = [social_user_ids]
|
||||
|
||||
for classifier in classifiers:
|
||||
if classifier.feed_id == feed_id:
|
||||
# print 'Feeds: %s -- %s' % (classifier.feed_id, feed.pk)
|
||||
return classifier.score
|
||||
if social_user_id and not classifier.feed_id and social_user_id == classifier.social_user_id:
|
||||
if (social_user_ids and not classifier.feed_id and
|
||||
classifier.social_user_id in social_user_ids):
|
||||
return classifier.score
|
||||
return 0
|
||||
|
||||
|
|
|
@ -286,6 +286,12 @@ def share_story(request, token):
|
|||
shared_story.save()
|
||||
logging.user(profile.user, "~BM~FY~SBUpdating~SN shared story from site: ~SB%s: %s" % (story_url, comments))
|
||||
|
||||
socialsub = MSocialSubscription.objects.get(user_id=profile.user.pk,
|
||||
subscription_user_id=profile.user.pk)
|
||||
socialsub.mark_story_ids_as_read([shared_story.story_guid],
|
||||
shared_story.story_feed_id,
|
||||
request=request)
|
||||
|
||||
shared_story.publish_update_to_subscribers()
|
||||
|
||||
response = HttpResponse(json.encode({
|
||||
|
|
|
@ -227,18 +227,20 @@ class GoogleReaderImporter(Importer):
|
|||
feeds_xml = self.send_request(sub_url)
|
||||
else:
|
||||
feeds_xml = self.xml
|
||||
self.process_feeds(feeds_xml)
|
||||
if feeds_xml:
|
||||
self.process_feeds(feeds_xml)
|
||||
|
||||
def send_request(self, url):
|
||||
user_tokens = OAuthToken.objects.filter(user=self.user)
|
||||
|
||||
if user_tokens.count():
|
||||
user_token = user_tokens[0]
|
||||
credential = pickle.loads(base64.b64decode(user_token.credential))
|
||||
http = httplib2.Http()
|
||||
http = credential.authorize(http)
|
||||
content = http.request(url)
|
||||
return content and content[1]
|
||||
if user_token.credential:
|
||||
credential = pickle.loads(base64.b64decode(user_token.credential))
|
||||
http = httplib2.Http()
|
||||
http = credential.authorize(http)
|
||||
content = http.request(url)
|
||||
return content and content[1]
|
||||
|
||||
def process_feeds(self, feeds_xml):
|
||||
self.clear_feeds()
|
||||
|
|
|
@ -195,7 +195,10 @@ NewsBlur""" % {'user': self.user.username, 'feeds': subs.count()}
|
|||
if not self.user.email or not self.send_emails:
|
||||
return
|
||||
|
||||
if self.is_premium and not force:
|
||||
sent_email, created = MSentEmail.objects.get_or_create(receiver_user_id=self.user.pk,
|
||||
email_type='new_premium')
|
||||
|
||||
if not created and not force:
|
||||
return
|
||||
|
||||
user = self.user
|
||||
|
|
|
@ -11,10 +11,10 @@ from utils import log as logging
|
|||
|
||||
class LoginForm(forms.Form):
|
||||
username = forms.CharField(label=_("Username or Email"), max_length=30,
|
||||
widget=forms.TextInput(attrs={'tabindex': 1}),
|
||||
widget=forms.TextInput(attrs={'tabindex': 1, 'class': 'NB-input'}),
|
||||
error_messages={'required': 'Please enter a username.'})
|
||||
password = forms.CharField(label=_("Password"),
|
||||
widget=forms.PasswordInput(attrs={'tabindex': 2}),
|
||||
widget=forms.PasswordInput(attrs={'tabindex': 2, 'class': 'NB-input'}),
|
||||
required=False)
|
||||
# error_messages={'required': 'Please enter a password.'})
|
||||
|
||||
|
@ -69,17 +69,17 @@ class LoginForm(forms.Form):
|
|||
class SignupForm(forms.Form):
|
||||
username = forms.RegexField(regex=r'^\w+$',
|
||||
max_length=30,
|
||||
widget=forms.TextInput(),
|
||||
widget=forms.TextInput(attrs={'class': 'NB-input'}),
|
||||
label=_(u'username'),
|
||||
error_messages={
|
||||
'required': 'Please enter a username.',
|
||||
'invalid': "Your username may only contain letters and numbers."
|
||||
})
|
||||
email = forms.EmailField(widget=forms.TextInput(attrs=dict(maxlength=75)),
|
||||
email = forms.EmailField(widget=forms.TextInput(attrs={'maxlength': 75, 'class': 'NB-input'}),
|
||||
label=_(u'email address'),
|
||||
required=False)
|
||||
# error_messages={'required': 'Please enter your email.'})
|
||||
password = forms.CharField(widget=forms.PasswordInput(),
|
||||
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'NB-input'}),
|
||||
label=_(u'password'),
|
||||
required=False)
|
||||
# error_messages={'required': 'Please enter a password.'})
|
||||
|
|
|
@ -555,7 +555,7 @@ class MUserStory(mongo.Document):
|
|||
user_id = mongo.IntField()
|
||||
feed_id = mongo.IntField()
|
||||
read_date = mongo.DateTimeField()
|
||||
story_id = mongo.StringField(unique_with=('user_id', 'feed_id'))
|
||||
story_id = mongo.StringField()
|
||||
story_date = mongo.DateTimeField()
|
||||
story = mongo.ReferenceField(MStory, dbref=True)
|
||||
found_story = mongo.GenericReferenceField()
|
||||
|
@ -569,6 +569,7 @@ class MUserStory(mongo.Document):
|
|||
],
|
||||
'allow_inheritance': False,
|
||||
'index_drop_dups': True,
|
||||
'cascade': False,
|
||||
}
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
|
|
@ -41,7 +41,6 @@ class CollectStats(Task):
|
|||
def run(self, **kwargs):
|
||||
logging.debug(" ---> Collecting stats...")
|
||||
MStatistics.collect_statistics()
|
||||
MStatistics.delete_old_stats()
|
||||
|
||||
|
||||
class CollectFeedback(Task):
|
||||
|
@ -50,4 +49,19 @@ class CollectFeedback(Task):
|
|||
def run(self, **kwargs):
|
||||
logging.debug(" ---> Collecting feedback...")
|
||||
MFeedback.collect_feedback()
|
||||
|
||||
|
||||
class CleanAnalytics(Task):
|
||||
name = 'clean-analytics'
|
||||
|
||||
def run(self, **kwargs):
|
||||
logging.debug(" ---> Cleaning analytics... %s page loads and %s feed fetches" % (
|
||||
settings.MONGOANALYTICSDB.nbanalytics.page_loads.count(),
|
||||
settings.MONGOANALYTICSDB.nbanalytics.feed_fetches.count(),
|
||||
))
|
||||
day_ago = datetime.datetime.utcnow() - datetime.timedelta(days=2)
|
||||
settings.MONGOANALYTICSDB.nbanalytics.feed_fetches.remove({
|
||||
"date": {"$lt": day_ago},
|
||||
})
|
||||
settings.MONGOANALYTICSDB.nbanalytics.page_loads.remove({
|
||||
"date": {"$lt": day_ago},
|
||||
})
|
|
@ -30,7 +30,7 @@ from apps.reader.forms import SignupForm, LoginForm, FeatureForm
|
|||
from apps.rss_feeds.models import MFeedIcon
|
||||
from apps.statistics.models import MStatistics
|
||||
try:
|
||||
from apps.rss_feeds.models import Feed, MFeedPage, DuplicateFeed, MStory, MStarredStory, FeedLoadtime
|
||||
from apps.rss_feeds.models import Feed, MFeedPage, DuplicateFeed, MStory, MStarredStory
|
||||
except:
|
||||
pass
|
||||
from apps.social.models import MSharedStory, MSocialProfile, MSocialServices
|
||||
|
@ -106,7 +106,7 @@ def welcome(request, **kwargs):
|
|||
social_profile = MSocialProfile.get_user(user.pk)
|
||||
|
||||
if request.method == "POST":
|
||||
if request.POST.get('submit') == 'login':
|
||||
if request.POST.get('submit', '').startswith('log'):
|
||||
login_form = LoginForm(request.POST, prefix='login')
|
||||
signup_form = SignupForm(prefix='signup')
|
||||
else:
|
||||
|
@ -123,6 +123,7 @@ def welcome(request, **kwargs):
|
|||
'signup_form' : signup_form,
|
||||
'statistics' : statistics,
|
||||
'social_profile' : social_profile,
|
||||
'post_request' : request.method == 'POST',
|
||||
}, "reader/welcome.xhtml"
|
||||
|
||||
@never_cache
|
||||
|
@ -541,7 +542,6 @@ def load_single_feed(request, feed_id):
|
|||
if timediff > 0.50 else "")
|
||||
logging.user(request, "~FYLoading feed: ~SB%s%s (%s/%s) %s" % (
|
||||
feed.feed_title[:22], ('~SN/p%s' % page) if page > 1 else '', order, read_filter, time_breakdown))
|
||||
FeedLoadtime.objects.create(feed=feed, loadtime=timediff)
|
||||
|
||||
data = dict(stories=stories,
|
||||
user_profiles=user_profiles,
|
||||
|
@ -563,13 +563,34 @@ def load_feed_page(request, feed_id):
|
|||
raise Http404
|
||||
|
||||
feed = Feed.get_by_id(feed_id)
|
||||
|
||||
if (feed.has_page and
|
||||
not feed.has_page_exception and
|
||||
settings.BACKED_BY_AWS['pages_on_s3'] and
|
||||
feed.s3_page):
|
||||
if settings.PROXY_S3_PAGES:
|
||||
key = settings.S3_PAGES_BUCKET.get_key(feed.s3_pages_key)
|
||||
compressed_data = key.get_contents_as_string()
|
||||
response = HttpResponse(compressed_data, mimetype="text/html; charset=utf-8")
|
||||
response['Content-Encoding'] = 'gzip'
|
||||
|
||||
logging.user(request, "~FYLoading original page, proxied: ~SB%s bytes" %
|
||||
(len(compressed_data)))
|
||||
return response
|
||||
else:
|
||||
logging.user(request, "~FYLoading original page, non-proxied")
|
||||
return HttpResponseRedirect('//%s/%s' % (settings.S3_PAGES_BUCKET_NAME,
|
||||
feed.s3_pages_key))
|
||||
|
||||
data = MFeedPage.get_data(feed_id=feed_id)
|
||||
|
||||
if not data or not feed.has_page or feed.has_page_exception:
|
||||
logging.user(request, "~FYLoading original page, ~FRmissing")
|
||||
return render(request, 'static/404_original_page.xhtml', {},
|
||||
content_type='text/html',
|
||||
status=404)
|
||||
|
||||
logging.user(request, "~FYLoading original page, from the db")
|
||||
return HttpResponse(data, mimetype="text/html; charset=utf-8")
|
||||
|
||||
@json.json_view
|
||||
|
|
|
@ -6,8 +6,11 @@ import scipy.cluster
|
|||
import urlparse
|
||||
import struct
|
||||
import operator
|
||||
import gzip
|
||||
import BmpImagePlugin, PngImagePlugin, Image
|
||||
from boto.s3.key import Key
|
||||
from StringIO import StringIO
|
||||
from django.conf import settings
|
||||
from apps.rss_feeds.models import MFeedPage, MFeedIcon
|
||||
from utils.feed_functions import timelimit, TimeoutError
|
||||
|
||||
|
@ -28,7 +31,10 @@ class IconImporter(object):
|
|||
if not self.force and self.feed.favicon_not_found:
|
||||
# print 'Not found, skipping...'
|
||||
return
|
||||
if not self.force and not self.feed.favicon_not_found and self.feed_icon.icon_url:
|
||||
if (not self.force and
|
||||
not self.feed.favicon_not_found and
|
||||
self.feed_icon.icon_url and
|
||||
self.feed.s3_icon):
|
||||
# print 'Found, but skipping...'
|
||||
return
|
||||
image, image_file, icon_url = self.fetch_image_from_page_data()
|
||||
|
@ -46,15 +52,19 @@ class IconImporter(object):
|
|||
color = self.determine_dominant_color_in_image(image)
|
||||
image_str = self.string_from_image(image)
|
||||
|
||||
if (self.feed_icon.color != color or
|
||||
if (self.force or
|
||||
self.feed_icon.color != color or
|
||||
self.feed_icon.data != image_str or
|
||||
self.feed_icon.icon_url != icon_url or
|
||||
self.feed_icon.not_found):
|
||||
self.feed_icon.not_found or
|
||||
(settings.BACKED_BY_AWS.get('icons_on_s3') and not self.feed.s3_icon)):
|
||||
self.feed_icon.data = image_str
|
||||
self.feed_icon.icon_url = icon_url
|
||||
self.feed_icon.color = color
|
||||
self.feed_icon.not_found = False
|
||||
self.feed_icon.save()
|
||||
if settings.BACKED_BY_AWS.get('icons_on_s3'):
|
||||
self.save_to_s3(image_str)
|
||||
self.feed.favicon_color = color
|
||||
self.feed.favicon_not_found = False
|
||||
else:
|
||||
|
@ -63,7 +73,16 @@ class IconImporter(object):
|
|||
|
||||
self.feed.save()
|
||||
return not self.feed.favicon_not_found
|
||||
|
||||
|
||||
def save_to_s3(self, image_str):
|
||||
k = Key(settings.S3_ICONS_BUCKET)
|
||||
k.key = self.feed.s3_icons_key
|
||||
k.set_metadata('Content-Type', 'image/png')
|
||||
k.set_contents_from_string(image_str.decode('base64'))
|
||||
k.set_acl('public-read')
|
||||
|
||||
self.feed.s3_icon = True
|
||||
|
||||
def load_icon(self, image_file, index=None):
|
||||
'''
|
||||
Load Windows ICO image.
|
||||
|
@ -146,6 +165,15 @@ class IconImporter(object):
|
|||
image_file = None
|
||||
if self.page_data:
|
||||
content = self.page_data
|
||||
elif settings.BACKED_BY_AWS.get('pages_on_s3') and self.feed.s3_page:
|
||||
key = settings.S3_PAGES_BUCKET.get_key(self.feed.s3_pages_key)
|
||||
compressed_content = key.get_contents_as_string()
|
||||
stream = StringIO(compressed_content)
|
||||
gz = gzip.GzipFile(fileobj=stream)
|
||||
try:
|
||||
content = gz.read()
|
||||
except IOError:
|
||||
content = None
|
||||
else:
|
||||
content = MFeedPage.get_data(feed_id=self.feed.pk)
|
||||
url = self._url_from_html(content)
|
||||
|
@ -172,6 +200,9 @@ class IconImporter(object):
|
|||
|
||||
def get_image_from_url(self, url):
|
||||
# print 'Requesting: %s' % url
|
||||
if not url:
|
||||
return None, None
|
||||
|
||||
@timelimit(30)
|
||||
def _1(url):
|
||||
try:
|
||||
|
|
97
apps/rss_feeds/migrations/0059_s3_pages_and_icons.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'Feed.s3_page'
|
||||
db.add_column('feeds', 's3_page',
|
||||
self.gf('django.db.models.fields.NullBooleanField')(default=False, null=True, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
# Adding field 'Feed.s3_icon'
|
||||
db.add_column('feeds', 's3_icon',
|
||||
self.gf('django.db.models.fields.NullBooleanField')(default=False, null=True, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'Feed.s3_page'
|
||||
db.delete_column('feeds', 's3_page')
|
||||
|
||||
# Deleting field 'Feed.s3_icon'
|
||||
db.delete_column('feeds', 's3_icon')
|
||||
|
||||
|
||||
models = {
|
||||
'rss_feeds.duplicatefeed': {
|
||||
'Meta': {'object_name': 'DuplicateFeed'},
|
||||
'duplicate_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'duplicate_feed_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}),
|
||||
'duplicate_link': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}),
|
||||
'feed': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'duplicate_addresses'", 'to': "orm['rss_feeds.Feed']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'rss_feeds.feed': {
|
||||
'Meta': {'ordering': "['feed_title']", 'object_name': 'Feed', 'db_table': "'feeds'"},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
|
||||
'active_premium_subscribers': ('django.db.models.fields.IntegerField', [], {'default': '-1', 'db_index': 'True'}),
|
||||
'active_subscribers': ('django.db.models.fields.IntegerField', [], {'default': '-1', 'db_index': 'True'}),
|
||||
'average_stories_per_month': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'branch_from_feed': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.Feed']", 'null': 'True', 'blank': 'True'}),
|
||||
'creation': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'days_to_trim': ('django.db.models.fields.IntegerField', [], {'default': '90'}),
|
||||
'errors_since_good': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'etag': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'exception_code': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'favicon_color': ('django.db.models.fields.CharField', [], {'max_length': '6', 'null': 'True', 'blank': 'True'}),
|
||||
'favicon_not_found': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'feed_address': ('django.db.models.fields.URLField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'feed_address_locked': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
|
||||
'feed_link': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '1000', 'null': 'True', 'blank': 'True'}),
|
||||
'feed_link_locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'feed_title': ('django.db.models.fields.CharField', [], {'default': "'[Untitled]'", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'fetched_once': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'has_feed_exception': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
|
||||
'has_page': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'has_page_exception': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
|
||||
'hash_address_and_link': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64', 'db_index': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_push': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
|
||||
'known_good': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
|
||||
'last_load_time': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'last_modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_update': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
|
||||
'min_to_decay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'next_scheduled_update': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
|
||||
'num_subscribers': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'premium_subscribers': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'queued_date': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
|
||||
's3_icon': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
|
||||
's3_page': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
|
||||
'stories_last_month': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'rss_feeds.feeddata': {
|
||||
'Meta': {'object_name': 'FeedData'},
|
||||
'feed': ('utils.fields.AutoOneToOneField', [], {'related_name': "'data'", 'unique': 'True', 'to': "orm['rss_feeds.Feed']"}),
|
||||
'feed_classifier_counts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'feed_tagline': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'popular_authors': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
|
||||
'popular_tags': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
|
||||
'story_count_history': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'rss_feeds.feedloadtime': {
|
||||
'Meta': {'object_name': 'FeedLoadtime'},
|
||||
'date_accessed': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'feed': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rss_feeds.Feed']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'loadtime': ('django.db.models.fields.FloatField', [], {})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['rss_feeds']
|
|
@ -29,8 +29,7 @@ from utils.feed_functions import levenshtein_distance
|
|||
from utils.feed_functions import timelimit, TimeoutError
|
||||
from utils.feed_functions import relative_timesince
|
||||
from utils.feed_functions import seconds_timesince
|
||||
from utils.story_functions import strip_tags
|
||||
from utils.diff import HTMLDiff
|
||||
from utils.story_functions import strip_tags, htmldiff
|
||||
|
||||
ENTRY_NEW, ENTRY_UPDATED, ENTRY_SAME, ENTRY_ERR = range(4)
|
||||
|
||||
|
@ -69,6 +68,8 @@ class Feed(models.Model):
|
|||
last_load_time = models.IntegerField(default=0)
|
||||
favicon_color = models.CharField(max_length=6, null=True, blank=True)
|
||||
favicon_not_found = models.BooleanField(default=False)
|
||||
s3_page = models.NullBooleanField(default=False, blank=True, null=True)
|
||||
s3_icon = models.NullBooleanField(default=False, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table="feeds"
|
||||
|
@ -87,14 +88,27 @@ class Feed(models.Model):
|
|||
|
||||
@property
|
||||
def favicon_url(self):
|
||||
if settings.BACKED_BY_AWS['icons_on_s3'] and self.s3_icon:
|
||||
return "http://%s/%s.png" % (settings.S3_ICONS_BUCKET_NAME, self.pk)
|
||||
return reverse('feed-favicon', kwargs={'feed_id': self.pk})
|
||||
|
||||
@property
|
||||
def favicon_url_fqdn(self):
|
||||
if settings.BACKED_BY_AWS['icons_on_s3'] and self.s3_icon:
|
||||
return self.favicon_url
|
||||
return "http://%s%s" % (
|
||||
Site.objects.get_current().domain,
|
||||
self.favicon_url
|
||||
)
|
||||
|
||||
@property
|
||||
def s3_pages_key(self):
|
||||
return "%s.gz.html" % self.pk
|
||||
|
||||
@property
|
||||
def s3_icons_key(self):
|
||||
return "%s.png" % self.pk
|
||||
|
||||
def canonical(self, full=False, include_favicon=True):
|
||||
feed = {
|
||||
'id': self.pk,
|
||||
|
@ -114,6 +128,8 @@ class Feed(models.Model):
|
|||
'favicon_text_color': self.favicon_text_color(),
|
||||
'favicon_fetching': self.favicon_fetching,
|
||||
'favicon_url': self.favicon_url,
|
||||
's3_page': self.s3_page,
|
||||
's3_icon': self.s3_icon,
|
||||
}
|
||||
|
||||
if include_favicon:
|
||||
|
@ -780,8 +796,7 @@ class Feed(models.Model):
|
|||
original_content = zlib.decompress(existing_story.story_content_z)
|
||||
# print 'Type: %s %s' % (type(original_content), type(story_content))
|
||||
if story_content and len(story_content) > 10:
|
||||
diff = HTMLDiff(unicode(original_content), story_content)
|
||||
story_content_diff = diff.getDiff()
|
||||
story_content_diff = htmldiff(unicode(original_content), unicode(story_content))
|
||||
else:
|
||||
story_content_diff = original_content
|
||||
# logging.debug("\t\tDiff: %s %s %s" % diff.getStats())
|
||||
|
@ -1311,6 +1326,7 @@ class MStory(mongo.Document):
|
|||
'index_drop_dups': True,
|
||||
'ordering': ['-story_date'],
|
||||
'allow_inheritance': False,
|
||||
'cascade': False,
|
||||
}
|
||||
|
||||
@property
|
||||
|
|
|
@ -6,6 +6,9 @@ import feedparser
|
|||
import time
|
||||
import urllib2
|
||||
import httplib
|
||||
import gzip
|
||||
import StringIO
|
||||
from boto.s3.key import Key
|
||||
from django.conf import settings
|
||||
from utils import log as logging
|
||||
from apps.rss_feeds.models import MFeedPage
|
||||
|
@ -77,6 +80,9 @@ class PageImporter(object):
|
|||
response = requests.get(feed_link, headers=self.headers)
|
||||
except requests.exceptions.TooManyRedirects:
|
||||
response = requests.get(feed_link)
|
||||
except AttributeError:
|
||||
self.save_no_page()
|
||||
return
|
||||
try:
|
||||
data = response.text
|
||||
except (LookupError, TypeError):
|
||||
|
@ -169,10 +175,35 @@ class PageImporter(object):
|
|||
|
||||
def save_page(self, html):
|
||||
if html and len(html) > 100:
|
||||
feed_page, created = MFeedPage.objects.get_or_create(feed_id=self.feed.pk, auto_save=True)
|
||||
feed_page.page_data = html
|
||||
if not created:
|
||||
feed_page.save()
|
||||
if settings.BACKED_BY_AWS.get('pages_on_s3'):
|
||||
k = Key(settings.S3_PAGES_BUCKET)
|
||||
k.key = self.feed.s3_pages_key
|
||||
k.set_metadata('Content-Encoding', 'gzip')
|
||||
k.set_metadata('Content-Type', 'text/html')
|
||||
k.set_metadata('Access-Control-Allow-Origin', '*')
|
||||
out = StringIO.StringIO()
|
||||
f = gzip.GzipFile(fileobj=out, mode='w')
|
||||
f.write(html)
|
||||
f.close()
|
||||
compressed_html = out.getvalue()
|
||||
k.set_contents_from_string(compressed_html)
|
||||
k.set_acl('public-read')
|
||||
|
||||
if not self.feed.s3_page:
|
||||
try:
|
||||
feed_page = MFeedPage.objects.get(feed_id=self.feed.pk)
|
||||
feed_page.delete()
|
||||
logging.debug(' --->> [%-30s] ~FYTransfering page data to S3...' % (self.feed))
|
||||
except MFeedPage.DoesNotExist:
|
||||
pass
|
||||
|
||||
self.feed.s3_page = True
|
||||
self.feed.save()
|
||||
else:
|
||||
feed_page.save(force_insert=True)
|
||||
return feed_page
|
||||
try:
|
||||
feed_page = MFeedPage.objects.get(feed_id=self.feed.pk)
|
||||
feed_page.page_data = html
|
||||
feed_page.save()
|
||||
except MFeedPage.DoesNotExist:
|
||||
feed_page = MFeedPage.objects.create(feed_id=self.feed.pk, page_data=html)
|
||||
return feed_page
|
||||
|
|
|
@ -449,7 +449,6 @@ class MSocialProfile(mongo.Document):
|
|||
logging.user(user, "~FMDisabled emails, skipping.")
|
||||
return
|
||||
if self.user_id == follower_user_id:
|
||||
logging.user(user, "~FMDisabled emails, skipping.")
|
||||
return
|
||||
|
||||
emails_sent = MSentEmail.objects.filter(receiver_user_id=user.pk,
|
||||
|
@ -918,7 +917,7 @@ class MSocialSubscription(mongo.Document):
|
|||
read_stories = MUserStory.objects(user_id=self.user_id,
|
||||
feed_id__in=story_feed_ids,
|
||||
story_id__in=story_ids)
|
||||
read_stories_ids = [rs.story_id for rs in read_stories]
|
||||
read_stories_ids = list(set(rs.story_id for rs in read_stories))
|
||||
|
||||
oldest_unread_story_date = now
|
||||
unread_stories_db = []
|
||||
|
@ -953,7 +952,7 @@ class MSocialSubscription(mongo.Document):
|
|||
for story in stories:
|
||||
scores = {
|
||||
'feed' : apply_classifier_feeds(classifier_feeds, story['story_feed_id'],
|
||||
social_user_id=self.subscription_user_id),
|
||||
social_user_ids=self.subscription_user_id),
|
||||
'author' : apply_classifier_authors(classifier_authors, story),
|
||||
'tags' : apply_classifier_tags(classifier_tags, story),
|
||||
'title' : apply_classifier_titles(classifier_titles, story),
|
||||
|
|
|
@ -145,7 +145,7 @@ def load_social_stories(request, user_id, username=None):
|
|||
|
||||
story['intelligence'] = {
|
||||
'feed': apply_classifier_feeds(classifier_feeds, story['story_feed_id'],
|
||||
social_user_id=social_user_id),
|
||||
social_user_ids=social_user_id),
|
||||
'author': apply_classifier_authors(classifier_authors, story),
|
||||
'tags': apply_classifier_tags(classifier_tags, story),
|
||||
'title': apply_classifier_titles(classifier_titles, story),
|
||||
|
@ -248,6 +248,8 @@ def load_river_blurblog(request):
|
|||
# Intelligence classifiers for all feeds involved
|
||||
if story_feed_ids:
|
||||
classifier_feeds = list(MClassifierFeed.objects(user_id=user.pk,
|
||||
social_user_id__in=social_user_ids))
|
||||
classifier_feeds = classifier_feeds + list(MClassifierFeed.objects(user_id=user.pk,
|
||||
feed_id__in=story_feed_ids))
|
||||
classifier_authors = list(MClassifierAuthor.objects(user_id=user.pk,
|
||||
feed_id__in=story_feed_ids))
|
||||
|
@ -260,11 +262,6 @@ def load_river_blurblog(request):
|
|||
classifier_authors = []
|
||||
classifier_titles = []
|
||||
classifier_tags = []
|
||||
classifiers = sort_classifiers_by_feed(user=user, feed_ids=story_feed_ids,
|
||||
classifier_feeds=classifier_feeds,
|
||||
classifier_authors=classifier_authors,
|
||||
classifier_titles=classifier_titles,
|
||||
classifier_tags=classifier_tags)
|
||||
|
||||
# Just need to format stories
|
||||
for story in stories:
|
||||
|
@ -282,7 +279,8 @@ def load_river_blurblog(request):
|
|||
starred_date = localtime_for_timezone(starred_stories[story['id']], user.profile.timezone)
|
||||
story['starred_date'] = format_story_link_date__long(starred_date, now)
|
||||
story['intelligence'] = {
|
||||
'feed': apply_classifier_feeds(classifier_feeds, story['story_feed_id']),
|
||||
'feed': apply_classifier_feeds(classifier_feeds, story['story_feed_id'],
|
||||
social_user_ids=story['friend_user_ids']),
|
||||
'author': apply_classifier_authors(classifier_authors, story),
|
||||
'tags': apply_classifier_tags(classifier_tags, story),
|
||||
'title': apply_classifier_titles(classifier_titles, story),
|
||||
|
@ -294,6 +292,11 @@ def load_river_blurblog(request):
|
|||
story['shared_date'] = format_story_link_date__long(shared_date, now)
|
||||
story['shared_comments'] = strip_tags(shared_stories[story['id']]['comments'])
|
||||
|
||||
classifiers = sort_classifiers_by_feed(user=user, feed_ids=story_feed_ids,
|
||||
classifier_feeds=classifier_feeds,
|
||||
classifier_authors=classifier_authors,
|
||||
classifier_titles=classifier_titles,
|
||||
classifier_tags=classifier_tags)
|
||||
|
||||
diff = time.time() - start
|
||||
timediff = round(float(diff), 2)
|
||||
|
|
|
@ -8,5 +8,4 @@ class Command(BaseCommand):
|
|||
|
||||
def handle(self, *args, **options):
|
||||
MStatistics.collect_statistics()
|
||||
|
||||
MStatistics.delete_old_stats()
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
import datetime
|
||||
import mongoengine as mongo
|
||||
import urllib2
|
||||
from django.db.models import Avg, Count
|
||||
from django.conf import settings
|
||||
from apps.rss_feeds.models import MFeedFetchHistory, MPageFetchHistory, MFeedPushHistory
|
||||
from apps.rss_feeds.models import FeedLoadtime
|
||||
from apps.social.models import MSharedStory
|
||||
from apps.profile.models import Profile
|
||||
from utils import json_functions as json
|
||||
|
@ -57,24 +55,22 @@ class MStatistics(mongo.Document):
|
|||
@classmethod
|
||||
def collect_statistics(cls):
|
||||
now = datetime.datetime.now()
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
cls.collect_statistics_feeds_fetched(last_day)
|
||||
cls.collect_statistics_feeds_fetched()
|
||||
print "Feeds Fetched: %s" % (datetime.datetime.now() - now)
|
||||
cls.collect_statistics_premium_users(last_day)
|
||||
cls.collect_statistics_premium_users()
|
||||
print "Premiums: %s" % (datetime.datetime.now() - now)
|
||||
cls.collect_statistics_standard_users(last_day)
|
||||
cls.collect_statistics_standard_users()
|
||||
print "Standard users: %s" % (datetime.datetime.now() - now)
|
||||
cls.collect_statistics_sites_loaded(last_day)
|
||||
cls.collect_statistics_sites_loaded()
|
||||
print "Sites loaded: %s" % (datetime.datetime.now() - now)
|
||||
cls.collect_statistics_stories_shared(last_day)
|
||||
cls.collect_statistics_stories_shared()
|
||||
print "Stories shared: %s" % (datetime.datetime.now() - now)
|
||||
cls.collect_statistics_for_db()
|
||||
print "DB Stats: %s" % (datetime.datetime.now() - now)
|
||||
|
||||
@classmethod
|
||||
def collect_statistics_feeds_fetched(cls, last_day=None):
|
||||
if not last_day:
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
def collect_statistics_feeds_fetched(cls):
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
last_month = datetime.datetime.now() - datetime.timedelta(days=30)
|
||||
|
||||
feeds_fetched = MFeedFetchHistory.objects.filter(fetch_date__gte=last_day).count()
|
||||
|
@ -100,19 +96,17 @@ class MStatistics(mongo.Document):
|
|||
return feeds_fetched
|
||||
|
||||
@classmethod
|
||||
def collect_statistics_premium_users(cls, last_day=None):
|
||||
if not last_day:
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
|
||||
def collect_statistics_premium_users(cls):
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
|
||||
premium_users = Profile.objects.filter(last_seen_on__gte=last_day, is_premium=True).count()
|
||||
cls.objects(key='premium_users').update_one(upsert=True, set__key='premium_users', set__value=premium_users)
|
||||
|
||||
return premium_users
|
||||
|
||||
@classmethod
|
||||
def collect_statistics_standard_users(cls, last_day=None):
|
||||
if not last_day:
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
def collect_statistics_standard_users(cls):
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
|
||||
standard_users = Profile.objects.filter(last_seen_on__gte=last_day, is_premium=False).count()
|
||||
cls.objects(key='standard_users').update_one(upsert=True, set__key='standard_users', set__value=standard_users)
|
||||
|
@ -120,9 +114,7 @@ class MStatistics(mongo.Document):
|
|||
return standard_users
|
||||
|
||||
@classmethod
|
||||
def collect_statistics_sites_loaded(cls, last_day=None):
|
||||
if not last_day:
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
def collect_statistics_sites_loaded(cls):
|
||||
now = datetime.datetime.now()
|
||||
sites_loaded = []
|
||||
avg_time_taken = []
|
||||
|
@ -130,13 +122,39 @@ class MStatistics(mongo.Document):
|
|||
for hour in range(24):
|
||||
start_hours_ago = now - datetime.timedelta(hours=hour)
|
||||
end_hours_ago = now - datetime.timedelta(hours=hour+1)
|
||||
aggregates = dict(count=Count('loadtime'), avg=Avg('loadtime'))
|
||||
load_times = FeedLoadtime.objects.filter(
|
||||
date_accessed__lte=start_hours_ago,
|
||||
date_accessed__gte=end_hours_ago
|
||||
).aggregate(**aggregates)
|
||||
sites_loaded.append(load_times['count'] or 0)
|
||||
avg_time_taken.append(load_times['avg'] or 0)
|
||||
|
||||
load_times = settings.MONGOANALYTICSDB.nbanalytics.page_loads.aggregate([{
|
||||
"$match": {
|
||||
"date": {
|
||||
"$gte": end_hours_ago,
|
||||
"$lte": start_hours_ago,
|
||||
},
|
||||
"path": {
|
||||
"$in": [
|
||||
"/reader/feed/",
|
||||
"/social/stories/",
|
||||
"/reader/river_stories/",
|
||||
"/social/river_stories/",
|
||||
]
|
||||
}
|
||||
},
|
||||
}, {
|
||||
"$group": {
|
||||
"_id" : 1,
|
||||
"count" : {"$sum": 1},
|
||||
"avg" : {"$avg": "$duration"},
|
||||
},
|
||||
}])
|
||||
|
||||
count = 0
|
||||
avg = 0
|
||||
if load_times['result']:
|
||||
count = load_times['result'][0]['count']
|
||||
avg = load_times['result'][0]['avg']
|
||||
|
||||
sites_loaded.append(count)
|
||||
avg_time_taken.append(avg)
|
||||
|
||||
sites_loaded.reverse()
|
||||
avg_time_taken.reverse()
|
||||
|
||||
|
@ -152,9 +170,7 @@ class MStatistics(mongo.Document):
|
|||
cls.objects(key=key).update_one(upsert=True, set__key=key, set__value=value)
|
||||
|
||||
@classmethod
|
||||
def collect_statistics_stories_shared(cls, last_day=None):
|
||||
if not last_day:
|
||||
last_day = datetime.datetime.now() - datetime.timedelta(hours=24)
|
||||
def collect_statistics_stories_shared(cls):
|
||||
now = datetime.datetime.now()
|
||||
stories_shared = []
|
||||
|
||||
|
@ -182,11 +198,6 @@ class MStatistics(mongo.Document):
|
|||
lag = db_functions.mongo_max_replication_lag(settings.MONGODB)
|
||||
cls.set('mongodb_replication_lag', lag)
|
||||
|
||||
@classmethod
|
||||
def delete_old_stats(cls):
|
||||
now = datetime.datetime.now()
|
||||
old_age = now - datetime.timedelta(days=7)
|
||||
FeedLoadtime.objects.filter(date_accessed__lte=old_age).delete()
|
||||
|
||||
class MFeedback(mongo.Document):
|
||||
date = mongo.StringField()
|
||||
|
@ -268,8 +279,21 @@ class MAnalyticsPageLoad(mongo.Document):
|
|||
|
||||
@classmethod
|
||||
def clean_path(cls, path):
|
||||
if path and path.startswith('/reader/feed/'):
|
||||
if not path:
|
||||
return
|
||||
|
||||
if path.startswith('/reader/feed'):
|
||||
path = '/reader/feed/'
|
||||
elif path.startswith('/social/stories'):
|
||||
path = '/social/stories/'
|
||||
elif path.startswith('/reader/river_stories'):
|
||||
path = '/reader/river_stories/'
|
||||
elif path.startswith('/social/river_stories'):
|
||||
path = '/social/river_stories/'
|
||||
elif path.startswith('/reader/page/'):
|
||||
path = '/reader/page/'
|
||||
elif path.startswith('/api/check_share_on_site'):
|
||||
path = '/api/check_share_on_site/'
|
||||
|
||||
return path
|
||||
|
||||
|
@ -326,6 +350,9 @@ class MAnalyticsFetcher(mongo.Document):
|
|||
@classmethod
|
||||
def add(cls, feed_id, feed_fetch, feed_process,
|
||||
page, icon, total, feed_code):
|
||||
server_name = settings.SERVER_NAME
|
||||
if 'app' in server_name: return
|
||||
|
||||
if icon and page:
|
||||
icon -= page
|
||||
if page and feed_process:
|
||||
|
@ -334,7 +361,6 @@ class MAnalyticsFetcher(mongo.Document):
|
|||
page -= feed_fetch
|
||||
if feed_process and feed_fetch:
|
||||
feed_process -= feed_fetch
|
||||
server_name = settings.SERVER_NAME
|
||||
|
||||
cls.objects.create(feed_id=feed_id, feed_fetch=feed_fetch,
|
||||
feed_process=feed_process,
|
||||
|
|
|
@ -50,7 +50,7 @@ javascripts:
|
|||
- media/js/vendor/jquery.tipsy.js
|
||||
- media/js/vendor/jquery.chosen.js
|
||||
- media/js/vendor/jquery.effects.core.js
|
||||
- media/js/vendor/jquery.effects.slide.js
|
||||
- media/js/vendor/jquery.effects.slideOffscreen.js
|
||||
# - media/js/vendor/jquery.linkify.js
|
||||
- media/js/vendor/bootstrap.*.js
|
||||
- media/js/vendor/audio.js
|
||||
|
@ -65,7 +65,7 @@ javascripts:
|
|||
- media/js/newsblur/reader/reader_utils.js
|
||||
- media/js/newsblur/reader/reader.js
|
||||
- media/js/newsblur/reader/*.js
|
||||
- media/js/newsblur/static/*.js
|
||||
- media/js/newsblur/welcome/*.js
|
||||
mobile:
|
||||
- media/js/vendor/jquery-1.7.2.js
|
||||
- media/js/mobile/jquery.mobile-1.0b1.js
|
||||
|
|
|
@ -4,13 +4,12 @@
|
|||
199.15.250.229 app02 app02.newsblur.com push
|
||||
199.15.252.156 app03 app03.newsblur.com dev
|
||||
199.15.252.109 app04 app04.newsblur.com www
|
||||
# 199.15.253.218 db01 db01.newsblur.com
|
||||
199.15.249.101 db01 db01.newsblur.com
|
||||
199.15.252.50 db02 db02.newsblur.com
|
||||
199.15.253.226 db03 db03.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.249.101 db07 db07.newsblur.com
|
||||
199.15.250.231 task01 task01.newsblur.com
|
||||
199.15.250.250 task02 task02.newsblur.com
|
||||
|
@ -19,3 +18,7 @@
|
|||
199.15.252.106 task05 task05.newsblur.com
|
||||
199.15.252.107 task06 task06.newsblur.com
|
||||
199.15.252.108 task07 task07.newsblur.com
|
||||
199.15.251.144 task08 task08.newsblur.com
|
||||
199.15.251.154 task09 task09.newsblur.com
|
||||
199.15.251.137 task10 task10.newsblur.com
|
||||
199.15.251.155 task11 task11.newsblur.com
|
||||
|
|
90
config/mongodb.ec2.conf
Normal file
|
@ -0,0 +1,90 @@
|
|||
# mongodb.conf
|
||||
|
||||
# Where to store the data.
|
||||
|
||||
# Note: if you run mongodb as a non-root user (recommended) you may
|
||||
# need to create and set permissions for this directory manually,
|
||||
# e.g., if the parent directory isn't mutable by the mongodb user.
|
||||
dbpath=/srv/db/mongodb
|
||||
|
||||
#where to log
|
||||
logpath=/var/log/mongodb/mongodb.log
|
||||
|
||||
logappend=true
|
||||
|
||||
#port = 27017
|
||||
|
||||
slowms=100
|
||||
|
||||
rest = true
|
||||
#profile = 2
|
||||
# Enables periodic logging of CPU utilization and I/O wait
|
||||
#cpu = true
|
||||
|
||||
# Turn on/off security. Off is currently the default
|
||||
noauth = true
|
||||
#auth = true
|
||||
|
||||
# Verbose logging output.
|
||||
#verbose = true
|
||||
|
||||
# Inspect all client data for validity on receipt (useful for
|
||||
# developing drivers)
|
||||
#objcheck = true
|
||||
|
||||
# Enable db quota management
|
||||
#quota = true
|
||||
|
||||
# Set oplogging level where n is
|
||||
# 0=off (default)
|
||||
# 1=W
|
||||
# 2=R
|
||||
# 3=both
|
||||
# 7=W+some reads
|
||||
#diaglog = 0
|
||||
|
||||
# Diagnostic/debugging option
|
||||
#nocursors = true
|
||||
|
||||
# Ignore query hints
|
||||
#nohints = true
|
||||
|
||||
# Disable the HTTP interface (Defaults to localhost:27018).
|
||||
#nohttpinterface = true
|
||||
|
||||
# Turns off server-side scripting. This will result in greatly limited
|
||||
# functionality
|
||||
#noscripting = true
|
||||
|
||||
# Turns off table scans. Any query that would do a table scan fails.
|
||||
#notablescan = true
|
||||
|
||||
# Disable data file preallocation.
|
||||
#noprealloc = true
|
||||
|
||||
# Specify .ns file size for new databases.
|
||||
# nssize = <size>
|
||||
|
||||
# Accout token for Mongo monitoring server.
|
||||
#mms-token = <token>
|
||||
|
||||
# Server name for Mongo monitoring server.
|
||||
#mms-name = <server-name>
|
||||
|
||||
# Ping interval for Mongo monitoring server.
|
||||
#mms-interval = <seconds>
|
||||
|
||||
# Replication Options
|
||||
|
||||
# in master/slave replicated mongo databases, specify here whether
|
||||
# this is a slave or master
|
||||
#slave = true
|
||||
#source = master.example.com
|
||||
# Slave only: specify a single database to replicate
|
||||
#only = master.example.com
|
||||
# or
|
||||
#master = true
|
||||
#source = slave.example.com
|
||||
|
||||
# in replica set configuration, specify the name of the replica set
|
||||
replSet = nbset
|
|
@ -8,7 +8,7 @@
|
|||
dbpath=/var/lib/mongodb
|
||||
|
||||
#where to log
|
||||
logpath=/var/log/mongodb
|
||||
logpath=/var/log/mongodb/mongodb.log
|
||||
|
||||
logappend=true
|
||||
|
||||
|
|
103
fabfile.py
vendored
|
@ -34,31 +34,43 @@ env.roledefs ={
|
|||
'app': ['app01.newsblur.com',
|
||||
'app02.newsblur.com',
|
||||
'app03.newsblur.com',
|
||||
'app04.newsblur.com'],
|
||||
'app04.newsblur.com',
|
||||
],
|
||||
'dev': ['dev.newsblur.com'],
|
||||
'web': ['app01.newsblur.com',
|
||||
'app02.newsblur.com',
|
||||
'app04.newsblur.com'],
|
||||
'app04.newsblur.com',
|
||||
],
|
||||
'db': ['db01.newsblur.com',
|
||||
'db02.newsblur.com',
|
||||
'db03.newsblur.com',
|
||||
'db04.newsblur.com',
|
||||
'db05.newsblur.com',
|
||||
'db06.newsblur.com'],
|
||||
'db05.newsblur.com',
|
||||
],
|
||||
'task': ['task01.newsblur.com',
|
||||
'task02.newsblur.com',
|
||||
'task03.newsblur.com',
|
||||
'task04.newsblur.com',
|
||||
'task05.newsblur.com',
|
||||
'task06.newsblur.com',
|
||||
'task07.newsblur.com'],
|
||||
'task07.newsblur.com',
|
||||
'task08.newsblur.com',
|
||||
'task09.newsblur.com',
|
||||
'task10.newsblur.com',
|
||||
'task11.newsblur.com',
|
||||
],
|
||||
'vps': ['task01.newsblur.com',
|
||||
'task02.newsblur.com',
|
||||
'task03.newsblur.com',
|
||||
'task04.newsblur.com',
|
||||
'task08.newsblur.com',
|
||||
'task09.newsblur.com',
|
||||
'task10.newsblur.com',
|
||||
'task11.newsblur.com',
|
||||
'app01.newsblur.com',
|
||||
'app02.newsblur.com',
|
||||
'app03.newsblur.com'],
|
||||
'app03.newsblur.com',
|
||||
],
|
||||
}
|
||||
|
||||
# ================
|
||||
|
@ -66,8 +78,8 @@ env.roledefs ={
|
|||
# ================
|
||||
|
||||
def server():
|
||||
env.NEWSBLUR_PATH = "/home/sclay/newsblur"
|
||||
env.VENDOR_PATH = "/home/sclay/code"
|
||||
env.NEWSBLUR_PATH = "/home/%s/newsblur" % env.user
|
||||
env.VENDOR_PATH = "/home/%s/code" % env.user
|
||||
|
||||
def app():
|
||||
server()
|
||||
|
@ -92,6 +104,11 @@ def task():
|
|||
def vps():
|
||||
server()
|
||||
env.roles = ['vps']
|
||||
|
||||
def ec2():
|
||||
env.user = 'ubuntu'
|
||||
env.key_filename = ['/Users/sclay/.ec2/sclay.pem']
|
||||
server()
|
||||
|
||||
# ==========
|
||||
# = Deploy =
|
||||
|
@ -263,7 +280,6 @@ def setup_app():
|
|||
setup_app_firewall()
|
||||
setup_app_motd()
|
||||
copy_app_settings()
|
||||
copy_certificates()
|
||||
configure_nginx()
|
||||
setup_gunicorn(supervisor=True)
|
||||
update_gunicorn()
|
||||
|
@ -278,12 +294,15 @@ def setup_db():
|
|||
setup_db_firewall()
|
||||
setup_db_motd()
|
||||
copy_task_settings()
|
||||
setup_memcached()
|
||||
setup_postgres(standby=False)
|
||||
# setup_mongo()
|
||||
# setup_memcached()
|
||||
# setup_postgres(standby=False)
|
||||
setup_mongo()
|
||||
setup_gunicorn(supervisor=False)
|
||||
setup_redis()
|
||||
# setup_redis()
|
||||
setup_db_munin()
|
||||
|
||||
if env.user == 'ubuntu':
|
||||
setup_db_mdadm()
|
||||
|
||||
def setup_task():
|
||||
setup_common()
|
||||
|
@ -318,14 +337,15 @@ def setup_installs():
|
|||
run('mkdir -p %s' % env.VENDOR_PATH)
|
||||
|
||||
def setup_user():
|
||||
# run('useradd -c "NewsBlur" -m conesus -s /bin/zsh')
|
||||
# run('useradd -c "NewsBlur" -m newsblur -s /bin/zsh')
|
||||
# run('openssl rand -base64 8 | tee -a ~conesus/.password | passwd -stdin conesus')
|
||||
run('mkdir -p ~/.ssh && chmod 700 ~/.ssh')
|
||||
run('rm -fr ~/.ssh/id_dsa*')
|
||||
run('ssh-keygen -t dsa -f ~/.ssh/id_dsa -N ""')
|
||||
run('touch ~/.ssh/authorized_keys')
|
||||
put("~/.ssh/id_dsa.pub", "authorized_keys")
|
||||
run('mv authorized_keys ~/.ssh/')
|
||||
run('echo `cat authorized_keys` >> ~/.ssh/authorized_keys')
|
||||
run('rm authorized_keys')
|
||||
|
||||
def add_machine_to_ssh():
|
||||
put("~/.ssh/id_dsa.pub", "local_keys")
|
||||
|
@ -371,7 +391,7 @@ def setup_psycopg():
|
|||
|
||||
def setup_python():
|
||||
# sudo('easy_install -U pip')
|
||||
sudo('easy_install -U fabric django==1.3.1 readline pyflakes iconv celery django-celery django-celery-with-redis django-compress South django-extensions pymongo==2.2.0 stripe BeautifulSoup pyyaml nltk lxml oauth2 pytz boto seacucumber django_ses mongoengine redis requests django-subdomains psutil python-gflags')
|
||||
sudo('easy_install -U fabric django==1.3.1 readline pyflakes iconv celery django-celery django-celery-with-redis django-compress South django-extensions pymongo==2.2.0 stripe BeautifulSoup pyyaml nltk lxml oauth2 pytz boto seacucumber django_ses mongoengine redis requests django-subdomains psutil python-gflags cssutils')
|
||||
|
||||
put('config/pystartup.py', '.pystartup')
|
||||
# with cd(os.path.join(env.NEWSBLUR_PATH, 'vendor/cjson')):
|
||||
|
@ -392,11 +412,12 @@ def setup_hosts():
|
|||
|
||||
def config_pgbouncer():
|
||||
put('config/pgbouncer.conf', '/etc/pgbouncer/pgbouncer.ini', use_sudo=True)
|
||||
put('config/pgbouncer_userlist.txt', '/etc/pgbouncer/userlist.txt', use_sudo=True)
|
||||
# put('config/pgbouncer_userlist.txt', '/etc/pgbouncer/userlist.txt', use_sudo=True)
|
||||
put('config/secrets/pgbouncer_auth.conf', '/etc/pgbouncer/userlist.txt', use_sudo=True)
|
||||
sudo('echo "START=1" > /etc/default/pgbouncer')
|
||||
sudo('su postgres -c "/etc/init.d/pgbouncer stop"', pty=False)
|
||||
with settings(warn_only=True):
|
||||
sudo('pkill pgbouncer')
|
||||
sudo('pkill -9 pgbouncer')
|
||||
run('sleep 2')
|
||||
sudo('/etc/init.d/pgbouncer start', pty=False)
|
||||
|
||||
|
@ -442,15 +463,15 @@ def setup_forked_mongoengine():
|
|||
with settings(warn_only=True):
|
||||
run('git checkout master')
|
||||
run('git branch -D dev')
|
||||
run('git remote add sclay git://github.com/samuelclay/mongoengine.git')
|
||||
run('git fetch sclay')
|
||||
run('git checkout -b dev sclay/dev')
|
||||
run('git pull sclay dev')
|
||||
run('git remote add %s git://github.com/samuelclay/mongoengine.git' % env.user)
|
||||
run('git fetch %s' % env.user)
|
||||
run('git checkout -b dev %s/dev' % env.user)
|
||||
run('git pull %s dev' % env.user)
|
||||
|
||||
def switch_forked_mongoengine():
|
||||
with cd(os.path.join(env.VENDOR_PATH, 'mongoengine')):
|
||||
run('git co dev')
|
||||
run('git pull sclay dev --force')
|
||||
run('git pull %s dev --force' % env.user)
|
||||
# run('git checkout .')
|
||||
# run('git checkout master')
|
||||
# run('get branch -D dev')
|
||||
|
@ -485,6 +506,7 @@ def configure_nginx():
|
|||
sudo("chmod 0755 /etc/init.d/nginx")
|
||||
sudo("/usr/sbin/update-rc.d -f nginx defaults")
|
||||
sudo("/etc/init.d/nginx restart")
|
||||
copy_certificates()
|
||||
|
||||
def setup_vps():
|
||||
# VPS suffer from severe time drift. Force blunt hourly time recalibration.
|
||||
|
@ -575,9 +597,18 @@ def setup_db_firewall():
|
|||
sudo('ufw allow from 199.15.248.0/21 to any port 5432 ') # PostgreSQL
|
||||
sudo('ufw allow from 199.15.248.0/21 to any port 27017') # MongoDB
|
||||
sudo('ufw allow from 199.15.248.0/21 to any port 28017') # MongoDB web
|
||||
# sudo('ufw allow from 199.15.248.0/21 to any port 5672 ') # RabbitMQ
|
||||
sudo('ufw allow from 199.15.248.0/21 to any port 6379 ') # Redis
|
||||
sudo('ufw allow from 199.15.248.0/21 to any port 11211 ') # Memcached
|
||||
|
||||
# EC2
|
||||
sudo('ufw delete allow from 23.22.0.0/16 to any port 5432 ') # PostgreSQL
|
||||
sudo('ufw delete allow from 23.22.0.0/16 to any port 27017') # MongoDB
|
||||
sudo('ufw delete allow from 23.22.0.0/16 to any port 6379 ') # Redis
|
||||
sudo('ufw delete allow from 23.22.0.0/16 to any port 11211 ') # Memcached
|
||||
sudo('ufw allow from 23.20.0.0/16 to any port 5432 ') # PostgreSQL
|
||||
sudo('ufw allow from 23.20.0.0/16 to any port 27017') # MongoDB
|
||||
sudo('ufw allow from 23.20.0.0/16 to any port 6379 ') # Redis
|
||||
sudo('ufw allow from 23.20.0.0/16 to any port 11211 ') # Memcached
|
||||
sudo('ufw --force enable')
|
||||
|
||||
def setup_db_motd():
|
||||
|
@ -628,7 +659,8 @@ 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)
|
||||
put('config/mongodb.%s.conf' % ('prod' if env.user != 'ubuntu' else 'ec2'),
|
||||
'/etc/mongodb.conf', use_sudo=True)
|
||||
sudo('/etc/init.d/mongodb restart')
|
||||
|
||||
def setup_redis():
|
||||
|
@ -651,8 +683,10 @@ def setup_db_munin():
|
|||
sudo('cp -frs %s/config/munin/mongo* /etc/munin/plugins/' % env.NEWSBLUR_PATH)
|
||||
sudo('cp -frs %s/config/munin/pg_* /etc/munin/plugins/' % env.NEWSBLUR_PATH)
|
||||
with cd(env.VENDOR_PATH):
|
||||
run('git clone git://github.com/samuel/python-munin.git')
|
||||
run('sudo python python-munin/setup.py install')
|
||||
with settings(warn_only=True):
|
||||
run('git clone git://github.com/samuel/python-munin.git')
|
||||
with cd(os.path.join(env.VENDOR_PATH, 'python-munin')):
|
||||
run('sudo python setup.py install')
|
||||
|
||||
def enable_celerybeat():
|
||||
with cd(env.NEWSBLUR_PATH):
|
||||
|
@ -662,6 +696,19 @@ def enable_celerybeat():
|
|||
sudo('supervisorctl reread')
|
||||
sudo('supervisorctl update')
|
||||
|
||||
def setup_db_mdadm():
|
||||
sudo('apt-get -y install xfsprogs mdadm')
|
||||
sudo('yes | mdadm --create /dev/md0 --level=0 -c256 --raid-devices=4 /dev/xvdf /dev/xvdg /dev/xvdh /dev/xvdi')
|
||||
sudo('mkfs.xfs /dev/md0')
|
||||
sudo('mkdir -p /srv/db')
|
||||
sudo('mount -t xfs -o rw,nobarrier,noatime,nodiratime /dev/md0 /srv/db')
|
||||
sudo('mkdir -p /srv/db/mongodb')
|
||||
sudo('chown mongodb.mongodb /srv/db/mongodb')
|
||||
sudo("echo 'DEVICE /dev/xvdf /dev/xvdg /dev/xvdh /dev/xvdi' | sudo tee -a /etc/mdadm/mdadm.conf")
|
||||
sudo("mdadm --examine --scan | sudo tee -a /etc/mdadm/mdadm.conf")
|
||||
sudo("echo '/dev/md0 /srv/db xfs rw,nobarrier,noatime,nodiratime,noauto 0 0' | sudo tee -a /etc/fstab")
|
||||
sudo("sudo update-initramfs -u -v -k `uname -r`")
|
||||
|
||||
# ================
|
||||
# = Setup - Task =
|
||||
# ================
|
||||
|
@ -697,7 +744,7 @@ def restore_postgres(port=5432):
|
|||
|
||||
def restore_mongo():
|
||||
backup_date = '2012-07-24-09-00'
|
||||
run('PYTHONPATH=/home/sclay/newsblur python s3.py get backup_mongo_%s.tgz' % backup_date)
|
||||
run('PYTHONPATH=/home/%s/newsblur python s3.py get backup_mongo_%s.tgz' % (env.user, backup_date))
|
||||
run('tar -xf backup_mongo_%s.tgz' % backup_date)
|
||||
run('mongorestore backup_mongo_%s' % backup_date)
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ OAUTH_SECRET = 'SECRET_KEY_FROM_GOOGLE'
|
|||
S3_ACCESS_KEY = 'XXX'
|
||||
S3_SECRET = 'SECRET'
|
||||
S3_BACKUP_BUCKET = 'newsblur_backups'
|
||||
S3_PAGES_BUCKET_NAME = 'pages-XXX.newsblur.com'
|
||||
S3_ICONS_BUCKET_NAME = 'icons-XXX.newsblur.com'
|
||||
|
||||
STRIPE_SECRET = "YOUR-SECRET-API-KEY"
|
||||
STRIPE_PUBLISHABLE = "YOUR-PUBLISHABLE-API-KEY"
|
||||
|
@ -76,19 +78,19 @@ MONGODB_SLAVE = {
|
|||
'host': '127.0.0.1'
|
||||
}
|
||||
|
||||
# Celery RabbitMQ Broker
|
||||
BROKER_HOST = "127.0.0.1"
|
||||
# Celery RabbitMQ/Redis Broker
|
||||
CELERY_REDIS_HOST = "127.0.0.1"
|
||||
BROKER_URL = "redis://127.0.0.1:6379/0"
|
||||
|
||||
REDIS = {
|
||||
'host': '127.0.0.1',
|
||||
}
|
||||
|
||||
# AMQP - RabbitMQ server
|
||||
BROKER_HOST = "db01.newsblur.com"
|
||||
BROKER_PORT = 5672
|
||||
BROKER_USER = "newsblur"
|
||||
BROKER_PASSWORD = "newsblur"
|
||||
BROKER_VHOST = "newsblurvhost"
|
||||
BACKED_BY_AWS = {
|
||||
'pages_on_s3': False,
|
||||
'icons_on_s3': False,
|
||||
'stories_on_dynamodb': False,
|
||||
}
|
||||
|
||||
# ===========
|
||||
# = Logging =
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
padding: 2px;
|
||||
margin: 2px 4px 2px;
|
||||
border: 1px solid #606060;
|
||||
-moz-box-shadow:2px 2px 0 #D0D0D0;
|
||||
-webkit-box-shadow:2px 2px 0 #D0D0D0;
|
||||
box-shadow:2px 2px 0 #D0D0D0;
|
||||
-moz-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
-webkit-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
|
@ -117,9 +117,9 @@
|
|||
padding: 2px;
|
||||
margin: 0px 4px 6px;
|
||||
border: 1px solid #606060;
|
||||
-moz-box-shadow:2px 2px 0 #D0D0D0;
|
||||
-webkit-box-shadow:2px 2px 0 #D0D0D0;
|
||||
box-shadow:2px 2px 0 #D0D0D0;
|
||||
-moz-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
-webkit-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
}
|
||||
|
||||
.NB-modal .NB-modal-field input[type=checkbox] {
|
||||
|
@ -205,9 +205,9 @@
|
|||
text-transform: uppercase;
|
||||
margin: 2px 4px 2px;
|
||||
border: 1px solid #606060;
|
||||
-moz-box-shadow:2px 2px 0 #D0D0D0;
|
||||
-webkit-box-shadow:2px 2px 0 #D0D0D0;
|
||||
box-shadow:2px 2px 0 #D0D0D0;
|
||||
-moz-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
-webkit-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
cursor: pointer;
|
||||
|
|
|
@ -16,7 +16,12 @@ body {
|
|||
background-color: white;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.NB-layout {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
a, a:active, a:hover, a:visited, button {
|
||||
outline: none;
|
||||
}
|
||||
|
@ -367,7 +372,7 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
border-bottom: 1px solid #A0A0A0;
|
||||
}
|
||||
.NB-feedlists .NB-socialfeeds .feed .feed_title {
|
||||
text-shadow: 0 1px 0 #DAE2E8;
|
||||
text-shadow: 0 1px 0 rgba(250, 250, 250, .4);
|
||||
}
|
||||
.NB-feedlists .NB-socialfeeds img.feed_favicon {
|
||||
border-radius: 3px;
|
||||
|
@ -574,12 +579,11 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
line-height: 1.3em;
|
||||
height: 14px;
|
||||
overflow: hidden;
|
||||
text-shadow: 0 1px 0 #EBF3FA;
|
||||
text-shadow: 0 1px 0 rgba(250, 250, 250, .4);
|
||||
}
|
||||
|
||||
.NB-feedlist .feed.selected .feed_title,
|
||||
.NB-feedlist .feed.NB-selected .feed_title {
|
||||
text-shadow: 0 1px 0 #FFC97D;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
|
@ -625,41 +629,50 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.NB-feedlist .folder .folder_title .feed_counts_floater {
|
||||
.NB-feedlists .folder .folder_title .feed_counts_floater,
|
||||
.NB-feeds-header .feed_counts_floater {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.NB-feedlist .folder .folder_title .NB-feedlist-collapse-icon {
|
||||
.NB-feedlist .folder .folder_title .NB-feedlist-collapse-icon,
|
||||
.NB-feeds-header .NB-feedlist-collapse-icon {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 4px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: transparent url('/media/embed/icons/silk/toggle_minus.png') no-repeat 0 0;
|
||||
background: transparent url('/media/embed/reader/toggle_minus.png') no-repeat 0 0;
|
||||
background-size: 16px;
|
||||
opacity: .6;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.NB-feedlist .folder.NB-folder-collapsed .folder_title .NB-feedlist-collapse-icon {
|
||||
background-image: url('/media/embed/icons/silk/toggle_plus.png');
|
||||
.NB-feedlist .folder.NB-folder-collapsed .folder_title .NB-feedlist-collapse-icon,
|
||||
.NB-feeds-header.NB-folder-collapsed .NB-feedlist-collapse-icon {
|
||||
background-image: url('/media/embed/reader/toggle_plus.png');
|
||||
background-size: 16px;
|
||||
}
|
||||
|
||||
.NB-feedlist .folder .folder_title:hover .NB-feedlist-collapse-icon:hover {
|
||||
.NB-feedlist .folder .folder_title:hover .NB-feedlist-collapse-icon:hover,
|
||||
.NB-feeds-header:hover .NB-feedlist-collapse-icon:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
.NB-feedlist .folder .folder_title:hover .NB-feedlist-collapse-icon {
|
||||
.NB-feedlist .folder .folder_title:hover .NB-feedlist-collapse-icon,
|
||||
.NB-feeds-header:hover .NB-feedlist-collapse-icon {
|
||||
/*.NB-feedlist .folder.NB-showing-menu > .folder_title .NB-feedlist-collapse-icon {*/
|
||||
display: block;
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.NB-feedlist .folder .folder_title:hover .feed_counts_floater,
|
||||
.NB-feeds-header:hover .feed_counts_floater,
|
||||
.NB-feedlist .folder.NB-showing-menu > .folder_title .feed_counts_floater {
|
||||
margin-right: 24px;
|
||||
}
|
||||
.NB-feedlist .folder .folder_title.NB-feedlist-folder-title-recently-collapsed:hover .feed_counts_floater {
|
||||
.NB-feedlist .folder .folder_title.NB-feedlist-folder-title-recently-collapsed:hover .feed_counts_floater,
|
||||
.NB-feeds-header.NB-feedlist-folder-title-recently-collapsed:hover .feed_counts_floater {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
@ -688,17 +701,29 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
display: none;
|
||||
}
|
||||
.NB-feedlist .feed.selected,
|
||||
.NB-feedlist .feed.NB-selected {
|
||||
background: #f6a828 url('/media/css/jquery-ui/images/ui-bg_highlight-hard_35_f6a828_1x100.png') 0 50% repeat-x;
|
||||
border-top: 1px solid #A8A8A8;
|
||||
border-bottom: 1px solid #A8A8A8;
|
||||
.NB-feedlist .feed.NB-selected,
|
||||
.NB-feeds-header.NB-selected {
|
||||
background-color: #F6A828;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F7BA55), to(#F6A828));
|
||||
background: -moz-linear-gradient(center top , #F7BA55 0%, #F6A828 100%);
|
||||
border-top: 1px solid #C59977;
|
||||
border-bottom: 1px solid #C59977;
|
||||
}
|
||||
.NB-feedlist .folder.NB-selected > .folder_title {
|
||||
background: #f6a828 url('/media/css/jquery-ui/images/ui-bg_highlight-hard_35_f6a828_1x100.png') 0 50% repeat-x;
|
||||
border-top: 1px solid #A8A8A8;
|
||||
border-bottom: 1px solid #A8A8A8;
|
||||
background-color: #F6A828;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F7BA55), to(#F6A828));
|
||||
background: -moz-linear-gradient(center top , #F7BA55 0%, #F6A828 100%);
|
||||
border-top: 1px solid #C59977;
|
||||
border-bottom: 1px solid #C59977;
|
||||
text-shadow: 1px 1px 0 #FAC898;
|
||||
}
|
||||
.NB-feedlist .feed.NB-feed-selector-selected {
|
||||
background-color: #7AC0FE;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#A7D3FE), to(#7AC0FE));
|
||||
background: -moz-linear-gradient(center top , #A7D3FE 0%, #7AC0FE 100%);
|
||||
border-top: 1px solid #789FC6;
|
||||
border-bottom: 1px solid #789FC6;
|
||||
}
|
||||
|
||||
|
||||
.NB-feedlist .NB-feeds-list-highlight {
|
||||
|
@ -715,29 +740,31 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
border: none !important;
|
||||
}
|
||||
|
||||
.NB-feedlist .folder_title .unread_count {
|
||||
.NB-feedlists .folder_title .unread_count {
|
||||
margin-top: -3px;
|
||||
line-height: 20px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.NB-feedlist .folder_title .unread_count {
|
||||
text-shadow: none;
|
||||
.NB-feeds-header .unread_count {
|
||||
margin-top: 2px;
|
||||
line-height: 18px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist .feed {
|
||||
display: none;
|
||||
}
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist.unread_view_positive .unread_positive {
|
||||
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_positive .unread_positive {
|
||||
display: block;
|
||||
}
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist.unread_view_neutral .unread_positive,
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist.unread_view_neutral .unread_neutral {
|
||||
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_neutral .unread_positive,
|
||||
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_neutral .unread_neutral {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist.unread_view_negative .unread_positive,
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist.unread_view_negative .unread_neutral,
|
||||
.NB-feedlist-hide-read-feeds .NB-feedlist.unread_view_negative .unread_negative {
|
||||
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_negative .unread_positive,
|
||||
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_negative .unread_neutral,
|
||||
.NB-feedlist-hide-read-feeds .NB-sidebar.unread_view_negative .unread_negative {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
@ -747,6 +774,20 @@ body.NB-theme-serif #story_pane .NB-feed-story-content {
|
|||
.NB-feedlist-hide-read-feeds .NB-feedlist .feed.selected {
|
||||
display: block;
|
||||
}
|
||||
#feed_list.NB-feedlist.NB-selector-active .feed,
|
||||
.NB-sidebar .NB-socialfeeds-folder.NB-selector-active .feed {
|
||||
display: none;
|
||||
}
|
||||
#feed_list.NB-feedlist.NB-selector-active .feed.NB-feed-selector-active,
|
||||
.NB-socialfeeds-folder.NB-selector-active .feed.NB-feed-selector-active {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
.NB-feedlist.NB-selector-active .NB-folder-collapsed .folder,
|
||||
.NB-socialfeeds-folder.NB-selector-active {
|
||||
display: block !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* ================= */
|
||||
/* = Unread Counts = */
|
||||
|
@ -1183,7 +1224,8 @@ background: transparent;
|
|||
}
|
||||
|
||||
#story_titles .NB-feedbar .folder ul.folder,
|
||||
#story_titles .NB-feedbar .folder .NB-feedlist-collapse-icon {
|
||||
#story_titles .NB-feedbar .folder .NB-feedlist-collapse-icon,
|
||||
.NB-feeds-header .NB-feedlist-collapse-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -1291,6 +1333,7 @@ background: transparent;
|
|||
color: #272727;
|
||||
line-height: 1em;
|
||||
background-color: white;
|
||||
border-bottom: 1px solid #FFF;
|
||||
}
|
||||
.NB-story-pane-west #story_titles .story {
|
||||
padding-right: 4px;
|
||||
|
@ -1307,7 +1350,6 @@ background: transparent;
|
|||
height: 20px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
/* background: transparent url('/media/embed/icons/silk/bullet_orange.png') no-repeat 6px 2px;*/
|
||||
}
|
||||
|
||||
#story_titles .story.NB-story-positive .NB-storytitles-sentiment {
|
||||
|
@ -1523,11 +1565,11 @@ background: transparent;
|
|||
}
|
||||
#story_titles .story.NB-selected {
|
||||
color: #304080;
|
||||
border-top: 1px solid #D7DDE6;
|
||||
background: #dadada url('/media/css/jquery-ui/images/dadada_40x100_textures_03_highlight_soft_75.png') 0 50% repeat-x;
|
||||
}
|
||||
#story_titles .story.after_selected {
|
||||
border-top: 1px solid #D7DDE6;
|
||||
border-top: 1px solid #6EADF5;
|
||||
border-bottom: 1px solid #6EADF5;
|
||||
background-color: #D2E6FD;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#E9EFF5), to(#E2EEFB));
|
||||
background: -moz-linear-gradient(center top , #E9EFF5 0%, #E2EEFB 100%);
|
||||
}
|
||||
|
||||
#story_titles .NB-story-titles-end-stories-line {
|
||||
|
@ -2041,19 +2083,25 @@ background: transparent;
|
|||
#story_pane .NB-feed-story-view-narrow .NB-feed-story-content {
|
||||
margin-right: 28px;
|
||||
}
|
||||
#story_pane .NB-feed-story-content ins {
|
||||
.NB-modal-preferences ins,
|
||||
#story_pane .NB-feed-story-content ins,
|
||||
.NB-pref-hide-changes #story_pane .NB-story-show-changes .NB-feed-story-content ins {
|
||||
text-decoration: underline;
|
||||
color: #27452D;
|
||||
color: #27652F;
|
||||
}
|
||||
#story_pane .NB-feed-story-content del {
|
||||
.NB-modal-preferences del,
|
||||
#story_pane .NB-feed-story-content del,
|
||||
.NB-pref-hide-changes #story_pane .NB-story-show-changes .NB-feed-story-content del {
|
||||
display: inline;
|
||||
color: #661616;
|
||||
color: #861616;
|
||||
}
|
||||
.NB-pref-hide-changes #story_pane .NB-feed-story-content ins {
|
||||
.NB-pref-hide-changes #story_pane .NB-feed-story-content ins,
|
||||
#story_pane .NB-story-hide-changes .NB-feed-story-content ins {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
.NB-pref-hide-changes #story_pane .NB-feed-story-content del {
|
||||
.NB-pref-hide-changes #story_pane .NB-feed-story-content del,
|
||||
#story_pane .NB-story-hide-changes .NB-feed-story-content del {
|
||||
display: none;
|
||||
}
|
||||
#story_pane .NB-feed-story-comments {
|
||||
|
@ -2729,6 +2777,9 @@ background: transparent;
|
|||
display: block;
|
||||
font-size: 20px;
|
||||
}
|
||||
.NB-is-anonymous .content-pane .feed_counts_floater {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.content-pane .feed_counts_floater .unread_count {
|
||||
float: right;
|
||||
|
@ -2833,7 +2884,7 @@ background: transparent;
|
|||
|
||||
.NB-feeds-header-container {
|
||||
position: relative;
|
||||
height: 20px;
|
||||
height: 24px;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
@ -2844,22 +2895,17 @@ background: transparent;
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
height: 22px;
|
||||
border-top: 1px solid #303030;
|
||||
border-bottom: 1px solid #E9E9E9;
|
||||
padding-right: 2px;
|
||||
font-size: 10px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.NB-feeds-header.NB-selected {
|
||||
background: #f6a828 url('/media/css/jquery-ui/images/ui-bg_highlight-hard_35_f6a828_1x100.png') 0 50% repeat-x;
|
||||
}
|
||||
|
||||
.NB-feeds-header .NB-feeds-header-icon {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
top: 3px;
|
||||
left: 2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
@ -2870,8 +2916,8 @@ background: transparent;
|
|||
padding: 0 40px 2px 23px;
|
||||
text-decoration: none;
|
||||
color: #F0F0F0;
|
||||
line-height: 18px;
|
||||
height: 14px;
|
||||
line-height: 22px;
|
||||
height: 22px;
|
||||
overflow: hidden;
|
||||
text-shadow: 0 1px 0 #060607;
|
||||
text-transform: uppercase;
|
||||
|
@ -2881,6 +2927,10 @@ background: transparent;
|
|||
color: #C1C1C1;
|
||||
}
|
||||
|
||||
.NB-feeds-header.NB-selected {
|
||||
border-top: 1px solid #303030;
|
||||
}
|
||||
|
||||
.NB-feeds-header.NB-selected .NB-feeds-header-title {
|
||||
text-shadow: 0 1px 0 #FFC97D;
|
||||
color: #000000;
|
||||
|
@ -3158,7 +3208,8 @@ background: transparent;
|
|||
overflow: hidden;
|
||||
}
|
||||
#story_taskbar .NB-tryfeed-add,
|
||||
#story_taskbar .NB-tryfeed-follow {
|
||||
#story_taskbar .NB-tryfeed-follow,
|
||||
#story_taskbar .NB-tryout-signup {
|
||||
margin: 2px auto 0px;
|
||||
width: 60px;
|
||||
height: 14px;
|
||||
|
@ -3229,10 +3280,6 @@ background: transparent;
|
|||
left: 12px;
|
||||
background: transparent url('/media/embed/icons/silk/arrow_down.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-taskbar .task_button.task_button_signup .NB-task-image {
|
||||
left: 12px;
|
||||
background: transparent url('/media/embed/icons/media-devices/imac.png') no-repeat 0 0;
|
||||
}
|
||||
|
||||
.NB-taskbar .task_button_background {
|
||||
z-index: 0;
|
||||
|
@ -3388,7 +3435,7 @@ form.opml_import_form input {
|
|||
/* =============== */
|
||||
|
||||
#NB-splash {
|
||||
z-index: 0;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -3466,6 +3513,7 @@ form.opml_import_form input {
|
|||
|
||||
.NB-splash-info .NB-splash-links .NB-splash-link {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
line-height: 12px;
|
||||
margin: 0;
|
||||
float: left;
|
||||
|
@ -3490,6 +3538,7 @@ form.opml_import_form input {
|
|||
}
|
||||
.NB-splash-info .NB-splash-links .NB-splash-link.NB-splash-link-logo a {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
|
@ -4469,6 +4518,9 @@ form.opml_import_form input {
|
|||
.NB-account .NB-module.NB-module-account .NB-module-account-stats {
|
||||
min-height: 0;
|
||||
}
|
||||
.NB-account .NB-module.NB-module-account .NB-module-stats-counts {
|
||||
overflow: hidden;
|
||||
}
|
||||
.NB-account .NB-module.NB-module-account .NB-module-stats-count {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -8626,3 +8678,32 @@ form.opml_import_form input {
|
|||
.NB-interaction-sharedstory-content {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ================= */
|
||||
/* = Feed Selector = */
|
||||
/* ================= */
|
||||
|
||||
.NB-feeds-selector {
|
||||
display: none;
|
||||
background-color: #434343;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#434343), to(#696969));
|
||||
background: -moz-linear-gradient(center top , #4E4E4E 0%, #696969 100%);
|
||||
border-bottom: 1px solid #E9E9E9;
|
||||
overflow: hidden;
|
||||
}
|
||||
.NB-feeds-selector-input {
|
||||
border-radius: 16px;
|
||||
border: 1px solid #5F5F5F;
|
||||
font-weight: bold;
|
||||
width: 88%;
|
||||
padding: 1px 8px;
|
||||
margin: 4px auto;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.NB-feeds-selector-input:focus {
|
||||
border: 1px solid #5F5F5F;
|
||||
box-shadow: 0 1px 0 #B1B1B1;
|
||||
}
|
|
@ -401,21 +401,13 @@ header {
|
|||
|
||||
.NB-story-date {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
right: 28px;
|
||||
top: 12px;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: silver;
|
||||
color: #D0D4D7;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@media all and (max-width: 800px) {
|
||||
.NB-story-date {
|
||||
top: 6px;
|
||||
}
|
||||
.NB-story-date-break {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@media all and (max-width: 500px) {
|
||||
.NB-story-date {
|
||||
position: static;
|
||||
|
@ -971,7 +963,6 @@ header {
|
|||
}
|
||||
.NB-story-share-label {
|
||||
display: inline-block;
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
.NB-story-share-profiles {
|
||||
display: inline-block;
|
||||
|
|
601
media/css/welcome.css
Normal file
|
@ -0,0 +1,601 @@
|
|||
.NB-welcome .NB-body-inner {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
.NB-welcome .NB-splash-info.NB-splash-top .NB-splash-title {
|
||||
display: none;
|
||||
}
|
||||
.NB-welcome .NB-splash-info.NB-splash-top,
|
||||
.NB-welcome .NB-splash-info.NB-splash-bottom {
|
||||
height: 6px;
|
||||
position: absolute;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4B638C), to(#23364D));
|
||||
background: -moz-linear-gradient(center top , #4B638C 0%, #23364D 100%);
|
||||
border-bottom: 1px solid #000D41;
|
||||
border-top: none;
|
||||
}
|
||||
.NB-welcome .NB-splash-info.NB-splash-bottom {
|
||||
position: static;
|
||||
}
|
||||
.NB-welcome .NB-splash-info.NB-splash-bottom .NB-splash-links {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.NB-welcome .NB-taskbar-sidebar-toggle-open {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
/* = Common = */
|
||||
/* ========== */
|
||||
|
||||
.NB-welcome .NB-inner {
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
.NB-welcome .NB-splash-links {
|
||||
overflow: hidden;
|
||||
}
|
||||
.NB-button {
|
||||
border: 1px solid #07360F;
|
||||
font-size: 12px;
|
||||
padding: 4px 12px;
|
||||
text-transform: uppercase;
|
||||
margin: 2px 4px 2px;
|
||||
-moz-box-shadow:2px 2px 0 rgba(35, 35, 35, 0.4);
|
||||
-webkit-box-shadow:2px 2px 0 rgba(35, 35, 35, 0.4);
|
||||
box-shadow:2px 2px 0 rgba(35, 35, 35, 0.4);
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: #404040;
|
||||
}
|
||||
.NB-button:active {
|
||||
-moz-box-shadow:1px 1px 0 rgba(35, 35, 35, 0.6);
|
||||
-webkit-box-shadow:1px 1px 0 rgba(35, 35, 35, 0.6);
|
||||
box-shadow:1px 1px 0 rgba(35, 35, 35, 0.6);
|
||||
}
|
||||
.NB-welcome-container.NB-welcome-tryout {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
/* = Header = */
|
||||
/* ========== */
|
||||
|
||||
.NB-welcome-header {
|
||||
background-color: #238232;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#69A1D1), to(#E5B568));
|
||||
background: -moz-linear-gradient(center top , #69A1D1 0%, #E5B568 100%) repeat scroll 0 0 transparent;
|
||||
height: 400px;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 2px rgba(10, 10, 10, 0.3);
|
||||
}
|
||||
|
||||
.NB-welcome-header .NB-welcome-header-logo {
|
||||
padding: 108px 0 0 0;
|
||||
text-align: center;
|
||||
width: 460px;
|
||||
}
|
||||
.NB-welcome-header .NB-welcome-header-tagline {
|
||||
margin: 36px 0 0 0;
|
||||
font-size: 22px;
|
||||
text-shadow: 0 1px 0 rgba(35,35,35,0.35);
|
||||
text-align: center;
|
||||
width: 460px;
|
||||
}
|
||||
.NB-welcome-header .NB-welcome-header-tagline b {
|
||||
padding: 2px 8px;
|
||||
background-color: rgba(205, 205, 205, 0.1);
|
||||
font-weight: normal;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.NB-welcome-header-image {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.NB-welcome-header-image img.NB-1 {
|
||||
height: 300px;
|
||||
position: absolute;
|
||||
bottom: -350px;
|
||||
right: -40px;
|
||||
border-radius: 2px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.NB-welcome-header-image.NB-active img.NB-1 {
|
||||
bottom: 0px;
|
||||
}
|
||||
.NB-welcome-header-image img.NB-2 {
|
||||
opacity: 0;
|
||||
height: 300px;
|
||||
position: absolute;
|
||||
bottom: -300px;
|
||||
right: 0;
|
||||
border-radius: 2px;
|
||||
margin-right: 100px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.NB-welcome-header-image img.NB-3 {
|
||||
opacity: 0;
|
||||
height: 300px;
|
||||
position: absolute;
|
||||
bottom: -300px;
|
||||
right: -24px;
|
||||
border-radius: 2px;
|
||||
margin-right: 140px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.NB-welcome-header-captions {
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 32px;
|
||||
overflow: hidden;
|
||||
text-shadow: 0 1px 0 rgba(35,35,35,0.35);
|
||||
padding-left: 64px;
|
||||
}
|
||||
.NB-welcome-header-caption {
|
||||
float: left;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
padding: 36px 12px 12px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.NB-welcome-header-caption.NB-welcome-header-caption-signin {
|
||||
color: #E8F64A;
|
||||
}
|
||||
.NB-welcome-header-caption span {
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
-webkit-transition: all 1s ease-in-out;
|
||||
-moz-transition: all 1s ease-in-out;
|
||||
-o-transition: all 1s ease-in-out;
|
||||
-ms-transition: all 1s ease-in-out;
|
||||
}
|
||||
.NB-welcome-header-caption:hover span {
|
||||
-webkit-transition: all .25s ease-in-out;
|
||||
-moz-transition: all .25s ease-in-out;
|
||||
-o-transition: all .25s ease-in-out;
|
||||
-ms-transition: all .25s ease-in-out;
|
||||
}
|
||||
.NB-welcome-header-caption.NB-active span {
|
||||
color: #FDC85B;
|
||||
background-color: rgba(235, 235, 235, 0.1);
|
||||
}
|
||||
|
||||
.NB-welcome-header-actions {
|
||||
margin: 36px 0 0;
|
||||
line-height: 16px;
|
||||
}
|
||||
.NB-welcome-header-action {
|
||||
float: left;
|
||||
}
|
||||
.NB-welcome-header-action-subtext {
|
||||
text-align: center;
|
||||
line-height: 24px;
|
||||
padding: 0 12px;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: white;
|
||||
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.4);
|
||||
}
|
||||
.NB-welcome-header-actions img {
|
||||
vertical-align: top;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.NB-welcome-header-actions .NB-welcome-header-action-arrow {
|
||||
display: none;
|
||||
}
|
||||
.NB-welcome-header-actions .NB-active .NB-welcome-header-action-bolt {
|
||||
display: none;
|
||||
}
|
||||
.NB-welcome-header-actions .NB-active .NB-welcome-header-action-arrow {
|
||||
display: block;
|
||||
}
|
||||
.NB-welcome-header-actions .NB-button {
|
||||
float: left;
|
||||
font-size: 16px;
|
||||
padding: 6px 10px;
|
||||
margin: 0 24px;
|
||||
text-transform: none;
|
||||
text-shadow: 0 1px 0 rgba(235, 235, 235, 0.4);
|
||||
background-color: #F5FFE2;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F5FFE2), to(#E8FACA));
|
||||
background: -moz-linear-gradient(center top, #F5FFE2 0%, #E8FACA 100%);
|
||||
}
|
||||
.NB-welcome-header-actions .NB-button:hover {
|
||||
background-color: #F4DD43;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F4DD43), to(#F1D526));
|
||||
background: -moz-linear-gradient(center top, #F4DD43 0%, #F1D526 100%);
|
||||
}
|
||||
.NB-welcome-header-actions .NB-button:active {
|
||||
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.4);
|
||||
background-color: #E97326;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#E97326), to(#D94B0D));
|
||||
background: -moz-linear-gradient(center top, #E97326 0%, #D94B0D 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* ================== */
|
||||
/* = Login / Signup = */
|
||||
/* ================== */
|
||||
|
||||
.NB-welcome-header-account {
|
||||
position: absolute;
|
||||
bottom: -350px;
|
||||
right: 12px;
|
||||
width: 400px;
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
background-color: rgba(245, 245, 245, 0.4);
|
||||
padding: 36px 36px 12px;
|
||||
}
|
||||
.NB-welcome-header-account.NB-active {
|
||||
bottom: 0;
|
||||
}
|
||||
.NB-welcome-header-account .NB-module-header-login {
|
||||
width: 142px;
|
||||
margin: 0 50px 0 0;
|
||||
padding: 0 4px;
|
||||
float: left;
|
||||
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.3);
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-module-header-signup {
|
||||
width: 142px;
|
||||
margin: 0;
|
||||
padding: 0 4px;
|
||||
float: left;
|
||||
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.3);
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-login {
|
||||
padding: 0 4px;
|
||||
margin: 12px 50px 0 12px;
|
||||
width: 146px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-signup {
|
||||
float: left;
|
||||
width: 146px;
|
||||
padding: 0 4px;
|
||||
margin: 12px 0 0;
|
||||
height: 206px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-import-signup {
|
||||
float: left;
|
||||
width: 146px;
|
||||
padding: 0 0 64px 0;
|
||||
margin: 0 24px 0 12px;
|
||||
height: 206px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-import-signup-text {
|
||||
text-align: center;
|
||||
width: 190px;
|
||||
}
|
||||
.NB-welcome-header-account .NB-import-signup-text h3 {
|
||||
margin-top: 48px;
|
||||
color: #20843D;
|
||||
}
|
||||
.NB-welcome-header-account .NB-import-signup-text p {
|
||||
color: #636363;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-signup-orline {
|
||||
margin: 30px auto 24px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 10px;
|
||||
color: #F9F9F9;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-signup-orline-reduced {
|
||||
margin: 0px auto 0px;
|
||||
}
|
||||
.NB-welcome-header-account .NB-signup-orline .NB-signup-orline-or {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-signup-optional {
|
||||
float: right;
|
||||
text-transform: uppercase;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-weight: bold;
|
||||
font-size: 9px;
|
||||
line-height: 17px;
|
||||
}
|
||||
.NB-welcome-header-account .NB-signup-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-import-signup {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-signup .NB-signup-google {
|
||||
margin: 12px auto;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account input[type=text],
|
||||
.NB-welcome-header-account input[type=password] {
|
||||
border: 1px solid rgba(35, 35, 35, 0.5);
|
||||
display:block;
|
||||
font-size:13px;
|
||||
margin:0 0 12px;
|
||||
padding:5px;
|
||||
width:134px;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account input[type=text]:focus,
|
||||
.NB-welcome-header-account input[type=password]:focus {
|
||||
border-color: #739BBE;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account input[type=submit] {
|
||||
outline: none;
|
||||
width: 146px; /* 174=input-width + 5*2=padding + 2=border */
|
||||
margin: 4px 5px 0 0;
|
||||
padding: 4px 10px 5px;
|
||||
text-shadow: 0 -1px 0 rgba(35, 35, 35, 0.4);
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
border: 1px solid rgba(35, 35, 35, 0.5);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account input[type=hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account label,
|
||||
.NB-welcome-header-account .NB-account-label {
|
||||
margin: 0;
|
||||
color: #FFFFD5;
|
||||
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.3);
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-account-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-account-text {
|
||||
font-size: 13px;
|
||||
color: #90A0B0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-account-text a {
|
||||
text-decoration: none;
|
||||
color: #3E4773;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .NB-account-text a:hover {
|
||||
color: #0E1763;
|
||||
}
|
||||
|
||||
.NB-welcome-header-account .errorlist {
|
||||
list-style: none;
|
||||
font-size: 12px;
|
||||
color: #AF4D18;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ============ */
|
||||
/* = Features = */
|
||||
/* ============ */
|
||||
|
||||
.NB-welcome-features {
|
||||
margin: 48px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.NB-welcome-features .NB-feature {
|
||||
float: left;
|
||||
width: 204px;
|
||||
margin: 0 36px 0 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.NB-welcome-features img {
|
||||
width: 200px;
|
||||
height: 175px;
|
||||
box-shadow: 0 0 3px rgba(30, 30, 30, 0.3);
|
||||
}
|
||||
.NB-welcome-features .NB-feature-caption {
|
||||
font-weight: bold;
|
||||
font-size: 24px;
|
||||
margin: 24px 0 0;
|
||||
}
|
||||
.NB-welcome-features .NB-feature-text {
|
||||
color: #808080;
|
||||
margin: 24px 0 0;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
/* =========== */
|
||||
/* = Pricing = */
|
||||
/* =========== */
|
||||
|
||||
.NB-welcome-pricing {
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
margin: 48px 0 0;
|
||||
padding: 36px 0;
|
||||
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px solid #F0F0F0;
|
||||
border-bottom: 1px solid #F0F0F0;
|
||||
}
|
||||
.NB-welcome-pricing p {
|
||||
line-height: 24px;
|
||||
}
|
||||
.NB-welcome-pricing .NB-price {
|
||||
float: right;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 16px;
|
||||
}
|
||||
.NB-pricing {
|
||||
margin: 12px 0;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
.NB-pricing th,
|
||||
.NB-pricing td {
|
||||
padding: 10px 8px;
|
||||
text-align: left;
|
||||
line-height: 16px;
|
||||
width: 33%;
|
||||
vertical-align: top;
|
||||
}
|
||||
.NB-pricing th {
|
||||
border-right: 1px solid #E4E4E4;
|
||||
}
|
||||
.NB-pricing td {
|
||||
border-top: 1px solid #E4E4E4;
|
||||
border-right: 1px solid #E4E4E4;
|
||||
}
|
||||
.NB-pricing .NB-last {
|
||||
border-right: none;
|
||||
}
|
||||
.NB-pricing .NB-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.NB-pricing .NB-shiloh {
|
||||
display: block;
|
||||
float: left;
|
||||
border: 1px solid #606060;
|
||||
height: 54px;
|
||||
margin: 0 12px 0 0;
|
||||
}
|
||||
|
||||
/* ============ */
|
||||
/* = Activity = */
|
||||
/* ============ */
|
||||
|
||||
.NB-welcome-activity {
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
padding: 36px 0;
|
||||
}
|
||||
.NB-welcome-activity .NB-module {
|
||||
width: 47%;
|
||||
}
|
||||
.NB-welcome-activity .NB-module-features {
|
||||
float: right;
|
||||
}
|
||||
.NB-welcome-activity .NB-module-stats {
|
||||
float: left;
|
||||
margin-right: 3%;
|
||||
}
|
||||
.NB-welcome-activity .NB-module .NB-module-header {
|
||||
display: none;
|
||||
}
|
||||
.NB-welcome-activity .NB-module .NB-module-stats-counts {
|
||||
overflow: hidden;
|
||||
}
|
||||
.NB-welcome-activity .NB-module-stats .NB-module-content-header-hour {
|
||||
margin-top: 36px;
|
||||
}
|
||||
.NB-welcome-activity .NB-module-stats-count-graph {
|
||||
margin-left: 4px;
|
||||
}
|
||||
.NB-welcome-activity .NB-graph-bar {
|
||||
width: 4px;
|
||||
}
|
||||
.NB-welcome-activity .NB-graph-value {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
/* ========== */
|
||||
/* = Footer = */
|
||||
/* ========== */
|
||||
|
||||
.NB-welcome-footer {
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
padding: 48px 0 52px;
|
||||
color: #363C53;
|
||||
line-height: 24px;
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1px solid #F0F0F0;
|
||||
}
|
||||
.NB-welcome-footer .NB-footer-logo {
|
||||
vertical-align: text-bottom;
|
||||
position: relative;
|
||||
bottom: -4px;
|
||||
}
|
||||
.NB-welcome-footer .NB-splash-link {
|
||||
color: #363C53;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 1px 0 rgba(245, 245, 245, 0.4);
|
||||
}
|
||||
.NB-welcome-footer .NB-splash-link:hover {
|
||||
color: #822216;
|
||||
}
|
||||
.NB-welcome-footer .NB-footer-icons {
|
||||
float: right;
|
||||
}
|
||||
.NB-welcome-footer .NB-footer-icons a {
|
||||
line-height: 0;
|
||||
margin: 0 12px 0 0;
|
||||
float: right;
|
||||
}
|
||||
.NB-welcome-footer .NB-footer-icons a img {
|
||||
vertical-align: middle;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
position: relative;
|
||||
bottom: -4px;
|
||||
opacity: .8;
|
||||
-webkit-transition: all .25s ease-in-out;
|
||||
-moz-transition: all .25s ease-in-out;
|
||||
-o-transition: all .25s ease-in-out;
|
||||
-ms-transition: all .25s ease-in-out;
|
||||
}
|
||||
.NB-welcome-footer .NB-footer-icons a img:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.NB-welcome-footer .NB-twitter-avatar {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
box-shadow: 0 0 1px #C0C0C0;
|
||||
vertical-align: bottom;
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
margin: 0 2px 0 4px;
|
||||
border-radius: 2px;
|
||||
}
|
BIN
media/img/favicon.ico
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
media/img/favicon_32.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
media/img/favicon_64.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
media/img/logo_144.png
Normal file
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 30 KiB |
BIN
media/img/originals/iOS - Collapse Icon.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
media/img/originals/logo_newsblur.png
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
media/img/originals/toggle.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
media/img/reader/32-Arrow-Down.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
media/img/reader/32-Arrow-Left.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
media/img/reader/32-Arrow-Right.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
media/img/reader/32-Arrow-Up.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
media/img/reader/32-Power.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
media/img/reader/download_computer.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
media/img/reader/search_icon.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
media/img/reader/search_icon2.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
media/img/reader/toggle_minus.png
Normal file
After Width: | Height: | Size: 787 B |
BIN
media/img/reader/toggle_plus.png
Normal file
After Width: | Height: | Size: 992 B |
BIN
media/img/welcome/Google_Reader_logo.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
media/img/welcome/feature_1.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
media/img/welcome/feature_1_original.png
Normal file
After Width: | Height: | Size: 196 KiB |
BIN
media/img/welcome/feature_2.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
media/img/welcome/feature_3.png
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
media/img/welcome/feature_4.png
Normal file
After Width: | Height: | Size: 103 KiB |
BIN
media/img/welcome/fleuron.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
media/img/welcome/github_favicon.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
media/img/welcome/header-android-original.png
Normal file
After Width: | Height: | Size: 2 MiB |
BIN
media/img/welcome/header-android.jpg
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
media/img/welcome/header-android.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
media/img/welcome/header-ios-original.png
Normal file
After Width: | Height: | Size: 718 KiB |
BIN
media/img/welcome/header-ios.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
media/img/welcome/header-ios.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
media/img/welcome/header-web-original.png
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
media/img/welcome/header-web.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
media/img/welcome/header1.jpg
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
media/img/welcome/twitter_favicon.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
|
@ -118,8 +118,8 @@
|
|||
} else if ([category isEqualToString:@"comment_like"]) {
|
||||
withUserUsername = [[activity objectForKey:@"with_user"] objectForKey:@"username"];
|
||||
txt = [NSString stringWithFormat:@"%@ favorited %@'s comment on %@:\n%@", username, withUserUsername, title, comment];
|
||||
} else if ([category isEqualToString:@"sharedstory"]) {
|
||||
if ([content isEqualToString:@""] || content == nil) {
|
||||
} else if ([category isEqualToString:@"sharedstory"]) {
|
||||
if ([content class] == [NSNull class] || [content isEqualToString:@""] || content == nil) {
|
||||
txt = [NSString stringWithFormat:@"%@ shared %@.", username, title];
|
||||
} else {
|
||||
txt = [NSString stringWithFormat:@"%@ shared %@:\n%@", username, title, comment];
|
||||
|
@ -130,7 +130,7 @@
|
|||
} else if ([category isEqualToString:@"feedsub"]) {
|
||||
txt = [NSString stringWithFormat:@"You subscribed to %@.", content];
|
||||
} else if ([category isEqualToString:@"signup"]) {
|
||||
txt = [NSString stringWithFormat:@"You signed up for NewsBlur.", content];
|
||||
txt = [NSString stringWithFormat:@"You signed up for NewsBlur."];
|
||||
}
|
||||
|
||||
NSString *txtWithTime = [NSString stringWithFormat:@"%@\n%@", txt, time];
|
||||
|
|
|
@ -100,7 +100,6 @@
|
|||
[self showFolderPicker];
|
||||
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
NSLog(@"%@", self.siteTable.frame);
|
||||
self.siteTable.hidden = NO;
|
||||
self.siteScrollView.frame = CGRectMake(self.siteScrollView.frame.origin.x,
|
||||
self.siteScrollView.frame.origin.y,
|
||||
|
@ -278,6 +277,7 @@
|
|||
[request setDelegate:self];
|
||||
[request setDidFinishSelector:@selector(requestFinished:)];
|
||||
[request setDidFailSelector:@selector(requestFailed:)];
|
||||
[request setTimeOutSeconds:30];
|
||||
[request startAsynchronous];
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ static UIFont *indicatorFont = nil;
|
|||
[backgroundColor set];
|
||||
|
||||
CGContextFillRect(context, r);
|
||||
NSLog(@"WIDTH is %f", rect.size.width);
|
||||
// set site title
|
||||
UIColor *textColor;
|
||||
UIFont *font;
|
||||
|
|
|
@ -122,14 +122,16 @@
|
|||
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
if ((appDelegate.isSocialRiverView || appDelegate.isRiverView || appDelegate.isSocialView)) {
|
||||
if ((appDelegate.isSocialRiverView ||
|
||||
appDelegate.isSocialView ||
|
||||
[appDelegate.activeFolder isEqualToString:@"everything"])) {
|
||||
settingsButton.enabled = NO;
|
||||
} else {
|
||||
settingsButton.enabled = YES;
|
||||
}
|
||||
|
||||
if (appDelegate.isSocialRiverView ||
|
||||
[appDelegate.activeFolder isEqualToString:@"All Stories"]) {
|
||||
[appDelegate.activeFolder isEqualToString:@"everything"]) {
|
||||
feedMarkReadButton.enabled = NO;
|
||||
} else {
|
||||
feedMarkReadButton.enabled = YES;
|
||||
|
@ -152,11 +154,6 @@
|
|||
[appDelegate.storyDetailViewController clearStory];
|
||||
[self checkScroll];
|
||||
}
|
||||
|
||||
NSString *title = appDelegate.isRiverView ?
|
||||
appDelegate.activeFolder :
|
||||
[appDelegate.activeFeed objectForKey:@"feed_title"];
|
||||
NSLog(@"title %@", title);
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
|
@ -266,14 +263,6 @@
|
|||
[self.storyTitlesTable reloadData];
|
||||
[storyTitlesTable scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
|
||||
}
|
||||
int readStoriesCount = 0;
|
||||
if (self.feedPage > 1) {
|
||||
for (id story in appDelegate.activeFeedStories) {
|
||||
if ([[story objectForKey:@"read_status"] intValue] == 1) {
|
||||
readStoriesCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSString *theFeedDetailURL;
|
||||
|
||||
|
@ -284,11 +273,10 @@
|
|||
self.feedPage];
|
||||
} else {
|
||||
theFeedDetailURL = [NSString stringWithFormat:
|
||||
@"http://%@/reader/river_stories/?feeds=%@&page=%d&read_stories_count=%d",
|
||||
@"http://%@/reader/river_stories/?feeds=%@&page=%d",
|
||||
NEWSBLUR_URL,
|
||||
[appDelegate.activeFolderFeeds componentsJoinedByString:@"&feeds="],
|
||||
self.feedPage,
|
||||
readStoriesCount];
|
||||
self.feedPage];
|
||||
}
|
||||
|
||||
[self cancelRequests];
|
||||
|
@ -973,10 +961,11 @@
|
|||
self.actionSheet_ = nil;
|
||||
return;
|
||||
}
|
||||
NSString *title = appDelegate.isRiverView ?
|
||||
appDelegate.activeFolder :
|
||||
[appDelegate.activeFeed objectForKey:@"feed_title"];
|
||||
UIActionSheet *options = [[UIActionSheet alloc]
|
||||
NSString *title = appDelegate.isRiverView ?
|
||||
appDelegate.activeFolder :
|
||||
[appDelegate.activeFeed objectForKey:@"feed_title"];
|
||||
|
||||
UIActionSheet *options = [[UIActionSheet alloc]
|
||||
initWithTitle:title
|
||||
delegate:self
|
||||
cancelButtonTitle:nil
|
||||
|
@ -985,20 +974,19 @@
|
|||
|
||||
self.actionSheet_ = options;
|
||||
|
||||
if (![title isEqualToString:@"Everything"]) {
|
||||
NSString *deleteText = [NSString stringWithFormat:@"Delete %@",
|
||||
appDelegate.isRiverView ?
|
||||
@"this entire folder" :
|
||||
@"this site"];
|
||||
[options addButtonWithTitle:deleteText];
|
||||
options.destructiveButtonIndex = 0;
|
||||
|
||||
NSString *moveText = @"Move to another folder";
|
||||
[options addButtonWithTitle:moveText];
|
||||
|
||||
NSString *deleteText = [NSString stringWithFormat:@"Delete %@",
|
||||
appDelegate.isRiverView ?
|
||||
@"this entire folder" :
|
||||
@"this site"];
|
||||
[options addButtonWithTitle:deleteText];
|
||||
options.destructiveButtonIndex = 0;
|
||||
|
||||
NSString *moveText = @"Move to another folder";
|
||||
[options addButtonWithTitle:moveText];
|
||||
|
||||
if (!appDelegate.isRiverView) {
|
||||
NSString *fetchText = @"Insta-fetch stories";
|
||||
[options addButtonWithTitle:fetchText];
|
||||
|
||||
}
|
||||
|
||||
options.cancelButtonIndex = [options addButtonWithTitle:@"Cancel"];
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "NewsBlurAppDelegate.h"
|
||||
#import "UnreadCountView.h"
|
||||
#import "ABTableViewCell.h"
|
||||
|
||||
@class NewsBlurAppDelegate;
|
||||
|
@ -20,8 +21,6 @@
|
|||
int _positiveCount;
|
||||
int _neutralCount;
|
||||
int _negativeCount;
|
||||
NSString *_positiveCountStr;
|
||||
NSString *_neutralCountStr;
|
||||
NSString *_negativeCountStr;
|
||||
BOOL isSocial;
|
||||
}
|
||||
|
@ -33,8 +32,6 @@
|
|||
@property (assign, nonatomic) int neutralCount;
|
||||
@property (assign, nonatomic) int negativeCount;
|
||||
@property (assign, nonatomic) BOOL isSocial;
|
||||
@property (nonatomic) NSString *positiveCountStr;
|
||||
@property (nonatomic) NSString *neutralCountStr;
|
||||
@property (nonatomic) NSString *negativeCountStr;
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,17 +8,10 @@
|
|||
|
||||
#import "NewsBlurAppDelegate.h"
|
||||
#import "FeedTableCell.h"
|
||||
#import "UnreadCountView.h"
|
||||
#import "ABTableViewCell.h"
|
||||
#import "UIView+TKCategory.h"
|
||||
|
||||
static UIFont *textFont = nil;
|
||||
static UIFont *indicatorFont = nil;
|
||||
static UIColor *indicatorWhiteColor = nil;
|
||||
static UIColor *indicatorBlackColor = nil;
|
||||
static UIColor *positiveBackgroundColor = nil;
|
||||
static UIColor *neutralBackgroundColor = nil;
|
||||
static UIColor *negativeBackgroundColor = nil;
|
||||
static CGFloat *psColors = nil;
|
||||
|
||||
@implementation FeedTableCell
|
||||
|
||||
|
@ -28,24 +21,12 @@ static CGFloat *psColors = nil;
|
|||
@synthesize positiveCount = _positiveCount;
|
||||
@synthesize neutralCount = _neutralCount;
|
||||
@synthesize negativeCount = _negativeCount;
|
||||
@synthesize positiveCountStr;
|
||||
@synthesize neutralCountStr;
|
||||
@synthesize negativeCountStr;
|
||||
@synthesize isSocial;
|
||||
|
||||
+ (void) initialize{
|
||||
if (self == [FeedTableCell class]) {
|
||||
textFont = [UIFont boldSystemFontOfSize:18];
|
||||
indicatorFont = [UIFont boldSystemFontOfSize:12];
|
||||
indicatorWhiteColor = [UIColor whiteColor];
|
||||
indicatorBlackColor = [UIColor blackColor];
|
||||
|
||||
UIColor *ps = UIColorFromRGB(0x3B7613);
|
||||
UIColor *nt = UIColorFromRGB(0xF9C72A);
|
||||
UIColor *ng = UIColorFromRGB(0xCC2A2E);
|
||||
positiveBackgroundColor = ps;
|
||||
neutralBackgroundColor = nt;
|
||||
negativeBackgroundColor = ng;
|
||||
// UIColor *psGrad = UIColorFromRGB(0x559F4D);
|
||||
// UIColor *ntGrad = UIColorFromRGB(0xE4AB00);
|
||||
// UIColor *ngGrad = UIColorFromRGB(0x9B181B);
|
||||
|
@ -64,7 +45,6 @@ static CGFloat *psColors = nil;
|
|||
if (ps == _positiveCount) return;
|
||||
|
||||
_positiveCount = ps;
|
||||
_positiveCountStr = [NSString stringWithFormat:@"%d", ps];
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
|
@ -72,7 +52,6 @@ static CGFloat *psColors = nil;
|
|||
if (nt == _neutralCount) return;
|
||||
|
||||
_neutralCount = nt;
|
||||
_neutralCountStr = [NSString stringWithFormat:@"%d", nt];
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
|
@ -115,89 +94,9 @@ static CGFloat *psColors = nil;
|
|||
CGContextStrokePath(context);
|
||||
}
|
||||
|
||||
CGRect rect = CGRectInset(r, 12, 12);
|
||||
rect.size.width -= 18; // Scrollbar padding
|
||||
|
||||
int psWidth = _positiveCount == 0 ? 0 : _positiveCount < 10 ?
|
||||
14 : _positiveCount < 100 ? 22 : 28;
|
||||
int ntWidth = _neutralCount == 0 ? 0 : _neutralCount < 10 ?
|
||||
14 : _neutralCount < 100 ? 22 : 28;
|
||||
int ngWidth = _negativeCount == 0 ? 0 : _negativeCount < 10 ?
|
||||
14 : _negativeCount < 100 ? 22 : 28;
|
||||
|
||||
int psOffset = _positiveCount == 0 ? 0 : psWidth - 20;
|
||||
int ntOffset = _neutralCount == 0 ? 0 : ntWidth - 20;
|
||||
int ngOffset = _negativeCount == 0 ? 0 : ngWidth - 20;
|
||||
|
||||
int psPadding = _positiveCount == 0 ? 0 : 2;
|
||||
int ntPadding = _neutralCount == 0 ? 0 : 2;
|
||||
|
||||
if(_positiveCount > 0){
|
||||
[positiveBackgroundColor set];
|
||||
CGRect rr;
|
||||
|
||||
if (self.isSocial) {
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psOffset, 14, psWidth, 17);
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psOffset, 10, psWidth, 17);
|
||||
}
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psOffset, 9, psWidth, 17);
|
||||
}
|
||||
|
||||
;
|
||||
[UIView drawLinearGradientInRect:rr colors:psColors];
|
||||
[UIView drawRoundRectangleInRect:rr withRadius:4];
|
||||
|
||||
[indicatorWhiteColor set];
|
||||
|
||||
CGSize size = [_positiveCountStr sizeWithFont:indicatorFont];
|
||||
float x_pos = (rr.size.width - size.width) / 2;
|
||||
float y_pos = (rr.size.height - size.height) / 2;
|
||||
[_positiveCountStr
|
||||
drawAtPoint:CGPointMake(rr.origin.x + x_pos, rr.origin.y + y_pos)
|
||||
withFont:indicatorFont];
|
||||
}
|
||||
if(_neutralCount > 0 && appDelegate.selectedIntelligence <= 0){
|
||||
[neutralBackgroundColor set];
|
||||
|
||||
CGRect rr;
|
||||
if (self.isSocial) {
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psWidth - psPadding - ntOffset, 14, ntWidth, 17);
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psWidth - psPadding - ntOffset, 10, ntWidth, 17);
|
||||
}
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psWidth - psPadding - ntOffset, 9, ntWidth, 17);
|
||||
}
|
||||
|
||||
[UIView drawRoundRectangleInRect:rr withRadius:4];
|
||||
// [UIView drawLinearGradientInRect:rr colors:ntColors];
|
||||
|
||||
[indicatorBlackColor set];
|
||||
CGSize size = [_neutralCountStr sizeWithFont:indicatorFont];
|
||||
float x_pos = (rr.size.width - size.width) / 2;
|
||||
float y_pos = (rr.size.height - size.height) / 2;
|
||||
[_neutralCountStr
|
||||
drawAtPoint:CGPointMake(rr.origin.x + x_pos, rr.origin.y + y_pos)
|
||||
withFont:indicatorFont];
|
||||
}
|
||||
if(_negativeCount > 0 && appDelegate.selectedIntelligence <= -1){
|
||||
[negativeBackgroundColor set];
|
||||
CGRect rr = CGRectMake(rect.size.width + rect.origin.x - psWidth - psPadding - ntWidth - ntPadding - ngOffset, self.isSocial ? 14: 9, ngWidth, 17);
|
||||
[UIView drawRoundRectangleInRect:rr withRadius:4];
|
||||
// [UIView drawLinearGradientInRect:rr colors:ngColors];
|
||||
|
||||
[indicatorWhiteColor set];
|
||||
CGSize size = [_negativeCountStr sizeWithFont:indicatorFont];
|
||||
float x_pos = (rr.size.width - size.width) / 2;
|
||||
float y_pos = (rr.size.height - size.height) / 2;
|
||||
[_negativeCountStr
|
||||
drawAtPoint:CGPointMake(rr.origin.x + x_pos, rr.origin.y + y_pos)
|
||||
withFont:indicatorFont];
|
||||
}
|
||||
UnreadCountView *unreadCount = [UnreadCountView alloc];
|
||||
[unreadCount drawInRect:r ps:_positiveCount nt:_neutralCount
|
||||
listType:(isSocial ? NBFeedListSocial : NBFeedListFeed)];
|
||||
|
||||
UIColor *textColor = self.selected || self.highlighted ?
|
||||
[UIColor blackColor]:
|
||||
|
@ -215,14 +114,14 @@ static CGFloat *psColors = nil;
|
|||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
[self.feedFavicon drawInRect:CGRectMake(12.0, 5.0, 36.0, 36.0)];
|
||||
[feedTitle
|
||||
drawInRect:CGRectMake(56, 13, rect.size.width - psWidth - psPadding - ntWidth - ntPadding - ngWidth - 10 - 20, 20.0)
|
||||
drawInRect:CGRectMake(56, 13, [unreadCount offsetWidth] - 10 - 20, 20.0)
|
||||
withFont:font
|
||||
lineBreakMode:UILineBreakModeTailTruncation
|
||||
alignment:UITextAlignmentLeft];
|
||||
} else {
|
||||
[self.feedFavicon drawInRect:CGRectMake(9.0, 3.0, 32.0, 32.0)];
|
||||
[feedTitle
|
||||
drawInRect:CGRectMake(50, 11, rect.size.width - psWidth - psPadding - ntWidth - ntPadding - ngWidth - 10 - 20, 20.0)
|
||||
drawInRect:CGRectMake(50, 11, [unreadCount offsetWidth] - 10 - 20, 20.0)
|
||||
withFont:font
|
||||
lineBreakMode:UILineBreakModeTailTruncation
|
||||
alignment:UITextAlignmentLeft];
|
||||
|
@ -230,16 +129,16 @@ static CGFloat *psColors = nil;
|
|||
|
||||
} else {
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
[self.feedFavicon drawInRect:CGRectMake(12.0, 9.0, 16.0, 16.0)];
|
||||
[self.feedFavicon drawInRect:CGRectMake(12.0, 7.0, 16.0, 16.0)];
|
||||
[feedTitle
|
||||
drawInRect:CGRectMake(36.0, 9.0, rect.size.width - psWidth - psPadding - ntWidth - ntPadding - ngWidth - 10, 20.0)
|
||||
drawInRect:CGRectMake(36.0, 7.0, [unreadCount offsetWidth] - 10, 20.0)
|
||||
withFont:font
|
||||
lineBreakMode:UILineBreakModeTailTruncation
|
||||
alignment:UITextAlignmentLeft];
|
||||
} else {
|
||||
[self.feedFavicon drawInRect:CGRectMake(9.0, 9.0, 16.0, 16.0)];
|
||||
[self.feedFavicon drawInRect:CGRectMake(9.0, 7.0, 16.0, 16.0)];
|
||||
[feedTitle
|
||||
drawInRect:CGRectMake(34.0, 9.0, rect.size.width - psWidth - psPadding - ntWidth - ntPadding - ngWidth - 10, 20.0)
|
||||
drawInRect:CGRectMake(34.0, 7.0, [unreadCount offsetWidth] - 10, 20.0)
|
||||
withFont:font
|
||||
lineBreakMode:UILineBreakModeTailTruncation
|
||||
alignment:UITextAlignmentLeft];
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1296</int>
|
||||
<string key="IBDocument.SystemVersion">11E53</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">2182</string>
|
||||
<string key="IBDocument.AppKitVersion">1138.47</string>
|
||||
<string key="IBDocument.HIToolboxVersion">569.00</string>
|
||||
<int key="IBDocument.SystemTarget">1536</int>
|
||||
<string key="IBDocument.SystemVersion">12C54</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">2840</string>
|
||||
<string key="IBDocument.AppKitVersion">1187.34</string>
|
||||
<string key="IBDocument.HIToolboxVersion">625.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">1181</string>
|
||||
<string key="NS.object.0">1926</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBUIView</string>
|
||||
<string>IBUIImageView</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBProxyObject</string>
|
||||
<string>IBUIActivityIndicatorView</string>
|
||||
<string>IBUISwitch</string>
|
||||
<string>IBUIButton</string>
|
||||
<string>IBUIImageView</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBUISwitch</string>
|
||||
<string>IBUIView</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
|
@ -69,10 +69,11 @@
|
|||
<int key="IBUIContentMode">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<string key="IBUIText">Connect with your friends to easily follow the stories that matter to them.</string>
|
||||
<string key="IBUIText">Connect with your friends to easily follow them.</string>
|
||||
<object class="NSColor" key="IBUITextColor" id="827336334">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MCAwIDAAA</bytes>
|
||||
<string key="IBUIColorCocoaTouchKeyPath">darkTextColor</string>
|
||||
</object>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<object class="NSColor" key="IBUIShadowColor" id="937995787">
|
||||
|
@ -93,11 +94,12 @@
|
|||
<double key="NSSize">18</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
<double key="preferredMaxLayoutWidth">400</double>
|
||||
</object>
|
||||
<object class="IBUILabel" id="961208593">
|
||||
<reference key="NSNextResponder" ref="874391841"/>
|
||||
<int key="NSvFlags">303</int>
|
||||
<string key="NSFrame">{{121, 421}, {298, 106}}</string>
|
||||
<string key="NSFrame">{{116, 421}, {314, 106}}</string>
|
||||
<reference key="NSSuperview" ref="874391841"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="436803934"/>
|
||||
|
@ -124,6 +126,7 @@
|
|||
<double key="NSSize">13</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
<double key="preferredMaxLayoutWidth">314</double>
|
||||
</object>
|
||||
<object class="IBUIButton" id="406293652">
|
||||
<reference key="NSNextResponder" ref="874391841"/>
|
||||
|
@ -1521,6 +1524,7 @@
|
|||
<string key="innerView">UIView</string>
|
||||
<string key="intelligenceControl">UISegmentedControl</string>
|
||||
<string key="noFocusMessage">UIView</string>
|
||||
<string key="toolbarLeftMargin">UIBarButtonItem</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<object class="IBToOneOutletInfo" key="appDelegate">
|
||||
|
@ -1555,6 +1559,10 @@
|
|||
<string key="name">noFocusMessage</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="toolbarLeftMargin">
|
||||
<string key="name">toolbarLeftMargin</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
|
@ -1848,7 +1856,7 @@
|
|||
<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
|
||||
<real value="1296" key="NS.object.0"/>
|
||||
<real value="1536" key="NS.object.0"/>
|
||||
</object>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
|
@ -1857,6 +1865,6 @@
|
|||
<string key="subtle-pattern-4.jpg">{1000, 1000}</string>
|
||||
<string key="twitter.png">{184, 34}</string>
|
||||
</dictionary>
|
||||
<string key="IBCocoaTouchPluginVersion">1181</string>
|
||||
<string key="IBCocoaTouchPluginVersion">1926</string>
|
||||
</data>
|
||||
</archive>
|
||||
|
|
23
media/ios/Classes/FolderTitleView.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// FolderTitleView.h
|
||||
// NewsBlur
|
||||
//
|
||||
// Created by Samuel Clay on 10/2/12.
|
||||
// Copyright (c) 2012 NewsBlur. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "NewsBlurAppDelegate.h"
|
||||
|
||||
|
||||
@class NewsBlurAppDelegate;
|
||||
|
||||
@interface FolderTitleView : UIControl {
|
||||
NewsBlurAppDelegate *appDelegate;
|
||||
}
|
||||
|
||||
@property (nonatomic) NewsBlurAppDelegate *appDelegate;
|
||||
|
||||
- (UIControl *)drawWithRect:(CGRect)rect inSection:(NSInteger)section;
|
||||
|
||||
@end
|
164
media/ios/Classes/FolderTitleView.m
Normal file
|
@ -0,0 +1,164 @@
|
|||
//
|
||||
// FolderTitleView.m
|
||||
// NewsBlur
|
||||
//
|
||||
// Created by Samuel Clay on 10/2/12.
|
||||
// Copyright (c) 2012 NewsBlur. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NewsBlurAppDelegate.h"
|
||||
#import "FolderTitleView.h"
|
||||
#import "UnreadCountView.h"
|
||||
|
||||
@implementation FolderTitleView
|
||||
|
||||
@synthesize appDelegate;
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIControl *)drawWithRect:(CGRect)rect inSection:(NSInteger)section {
|
||||
|
||||
self.appDelegate = (NewsBlurAppDelegate *)[[UIApplication sharedApplication] delegate];
|
||||
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSString *folderName;
|
||||
if (section == 0) {
|
||||
folderName = @"river_blurblogs";
|
||||
} else {
|
||||
folderName = [appDelegate.dictFoldersArray objectAtIndex:section];
|
||||
}
|
||||
NSString *collapseKey = [NSString stringWithFormat:@"folderCollapsed:%@", folderName];
|
||||
bool isFolderCollapsed = [userPreferences boolForKey:collapseKey];
|
||||
|
||||
// create the parent view that will hold header Label
|
||||
UIControl* customView = [[UIControl alloc]
|
||||
initWithFrame:rect];
|
||||
UIView *borderTop = [[UIView alloc]
|
||||
initWithFrame:CGRectMake(rect.origin.x, rect.origin.y,
|
||||
rect.size.width, 1.0)];
|
||||
borderTop.backgroundColor = UIColorFromRGB(0xe0e0e0);
|
||||
borderTop.opaque = NO;
|
||||
[customView addSubview:borderTop];
|
||||
|
||||
|
||||
UIView *borderBottom = [[UIView alloc]
|
||||
initWithFrame:CGRectMake(rect.origin.x, rect.size.height-1,
|
||||
rect.size.width, 1.0)];
|
||||
borderBottom.backgroundColor = [UIColorFromRGB(0xB7BDC6) colorWithAlphaComponent:0.5];
|
||||
borderBottom.opaque = NO;
|
||||
[customView addSubview:borderBottom];
|
||||
|
||||
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
customView.opaque = NO;
|
||||
headerLabel.backgroundColor = [UIColor clearColor];
|
||||
headerLabel.opaque = NO;
|
||||
headerLabel.textColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1.0];
|
||||
headerLabel.highlightedTextColor = [UIColor whiteColor];
|
||||
headerLabel.font = [UIFont boldSystemFontOfSize:11];
|
||||
headerLabel.frame = CGRectMake(36.0, 1.0, rect.size.width - 36, rect.size.height);
|
||||
headerLabel.shadowColor = [UIColor colorWithRed:.94 green:0.94 blue:0.97 alpha:1.0];
|
||||
headerLabel.shadowOffset = CGSizeMake(0.0, 1.0);
|
||||
if (section == 0) {
|
||||
headerLabel.text = @"ALL BLURBLOG STORIES";
|
||||
// customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
|
||||
// colorWithAlphaComponent:0.8];
|
||||
} else if (section == 1) {
|
||||
headerLabel.text = @"ALL STORIES";
|
||||
// customView.backgroundColor = [UIColorFromRGB(0xE6DDD7)
|
||||
// colorWithAlphaComponent:0.8];
|
||||
} else {
|
||||
headerLabel.text = [[appDelegate.dictFoldersArray objectAtIndex:section] uppercaseString];
|
||||
// customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
|
||||
// colorWithAlphaComponent:0.8];
|
||||
}
|
||||
|
||||
customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
|
||||
colorWithAlphaComponent:0.8];
|
||||
[customView addSubview:headerLabel];
|
||||
|
||||
UIButton *invisibleHeaderButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
invisibleHeaderButton.frame = CGRectMake(0, 0, customView.frame.size.width, customView.frame.size.height);
|
||||
invisibleHeaderButton.alpha = .1;
|
||||
invisibleHeaderButton.tag = section;
|
||||
[invisibleHeaderButton addTarget:appDelegate.feedsViewController action:@selector(didSelectSectionHeader:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[customView addSubview:invisibleHeaderButton];
|
||||
|
||||
[invisibleHeaderButton addTarget:appDelegate.feedsViewController action:@selector(sectionTapped:) forControlEvents:UIControlEventTouchDown];
|
||||
[invisibleHeaderButton addTarget:appDelegate.feedsViewController action:@selector(sectionUntapped:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[invisibleHeaderButton addTarget:appDelegate.feedsViewController action:@selector(sectionUntappedOutside:) forControlEvents:UIControlEventTouchUpOutside];
|
||||
|
||||
if (!appDelegate.hasNoSites) {
|
||||
if (section != 1) {
|
||||
UIImage *disclosureBorder = [UIImage imageNamed:@"disclosure_border.png"];
|
||||
UIImageView *disclosureBorderView = [[UIImageView alloc] initWithImage:disclosureBorder];
|
||||
disclosureBorderView.frame = CGRectMake(customView.frame.size.width - 30, -1, 29, 29);
|
||||
[customView addSubview:disclosureBorderView];
|
||||
}
|
||||
|
||||
UIButton *disclosureButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage *disclosureImage = [UIImage imageNamed:@"disclosure.png"];
|
||||
[disclosureButton setImage:disclosureImage forState:UIControlStateNormal];
|
||||
disclosureButton.frame = CGRectMake(customView.frame.size.width - 30, -1, 29, 29);
|
||||
if (section != 1) {
|
||||
if (!isFolderCollapsed) {
|
||||
disclosureButton.transform = CGAffineTransformMakeRotation(M_PI_2);
|
||||
}
|
||||
|
||||
disclosureButton.tag = section;
|
||||
[disclosureButton addTarget:appDelegate.feedsViewController action:@selector(didCollapseFolder:) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
[customView addSubview:disclosureButton];
|
||||
}
|
||||
|
||||
UIImage *folderImage;
|
||||
int folderImageViewX = 10;
|
||||
|
||||
if (section == 0) {
|
||||
folderImage = [UIImage imageNamed:@"group.png"];
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
folderImageViewX = 10;
|
||||
} else {
|
||||
folderImageViewX = 8;
|
||||
}
|
||||
} else if (section == 1) {
|
||||
folderImage = [UIImage imageNamed:@"archive.png"];
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
folderImageViewX = 10;
|
||||
} else {
|
||||
folderImageViewX = 7;
|
||||
}
|
||||
} else {
|
||||
if (isFolderCollapsed) {
|
||||
folderImage = [UIImage imageNamed:@"folder_collapsed.png"];
|
||||
} else {
|
||||
folderImage = [UIImage imageNamed:@"folder_2.png"];
|
||||
}
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
} else {
|
||||
folderImageViewX = 7;
|
||||
}
|
||||
}
|
||||
UIImageView *folderImageView = [[UIImageView alloc] initWithImage:folderImage];
|
||||
folderImageView.frame = CGRectMake(folderImageViewX, 3, 20, 20);
|
||||
[customView addSubview:folderImageView];
|
||||
|
||||
[customView setAutoresizingMask:UIViewAutoresizingNone];
|
||||
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextFillRect(context, rect);
|
||||
|
||||
UnreadCountView *unreadCount = [UnreadCountView alloc];
|
||||
[unreadCount drawInRect:rect ps:123 nt:321
|
||||
listType:NBFeedListFolder];
|
||||
|
||||
return customView;
|
||||
}
|
||||
|
||||
@end
|
|
@ -90,8 +90,6 @@
|
|||
// Return YES for supported orientations
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
return YES;
|
||||
} else if (UIInterfaceOrientationIsPortrait(interfaceOrientation)) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
@ -145,7 +143,7 @@
|
|||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Loginp
|
||||
#pragma mark Login
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
[textField resignFirstResponder];
|
||||
|
@ -165,8 +163,6 @@
|
|||
if(textField == usernameInput) {
|
||||
[passwordInput becomeFirstResponder];
|
||||
} else if (textField == passwordInput && [self.loginControl selectedSegmentIndex] == 0) {
|
||||
NSLog(@"Password return");
|
||||
NSLog(@"appdelegate:: %@", [self appDelegate]);
|
||||
[self checkPassword];
|
||||
} else if (textField == passwordInput && [self.loginControl selectedSegmentIndex] == 1) {
|
||||
[emailInput becomeFirstResponder];
|
||||
|
|
|
@ -235,6 +235,8 @@
|
|||
[self.folders addObject:@"— Top Level —"];
|
||||
|
||||
for (NSString *folder in appDelegate.dictFoldersArray) {
|
||||
if ([folder isEqualToString:@"everything"]) continue;
|
||||
if ([folder isEqualToString:@"river_blurblogs"]) continue;
|
||||
if ([[folder trim] isEqualToString:@""]) continue;
|
||||
if (appDelegate.isRiverView) {
|
||||
if (![folder containsString:appDelegate.activeFolder]) {
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
NSString * activeUsername;
|
||||
NSString * activeUserProfileId;
|
||||
NSString * activeUserProfileName;
|
||||
BOOL hasNoSites;
|
||||
BOOL isRiverView;
|
||||
BOOL isSocialView;
|
||||
BOOL isSocialRiverView;
|
||||
|
@ -147,6 +148,7 @@
|
|||
@property (readwrite) NSString * activeUsername;
|
||||
@property (readwrite) NSString * activeUserProfileId;
|
||||
@property (readwrite) NSString * activeUserProfileName;
|
||||
@property (nonatomic, readwrite) BOOL hasNoSites;
|
||||
@property (nonatomic, readwrite) BOOL isRiverView;
|
||||
@property (nonatomic, readwrite) BOOL isSocialView;
|
||||
@property (nonatomic, readwrite) BOOL isSocialRiverView;
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
@synthesize activeUsername;
|
||||
@synthesize activeUserProfileId;
|
||||
@synthesize activeUserProfileName;
|
||||
@synthesize hasNoSites;
|
||||
@synthesize isRiverView;
|
||||
@synthesize isSocialView;
|
||||
@synthesize isSocialRiverView;
|
||||
|
@ -509,9 +510,8 @@
|
|||
- (void)adjustStoryDetailWebView {
|
||||
// change UIWebView
|
||||
int contentWidth = storyDetailViewController.view.frame.size.width;
|
||||
NSLog(@"contentWidth is %i", contentWidth);
|
||||
// NSLog(@"contentWidth is %i", contentWidth);
|
||||
[storyDetailViewController changeWebViewWidth:contentWidth];
|
||||
|
||||
}
|
||||
|
||||
- (void)calibrateStoryTitles {
|
||||
|
@ -545,7 +545,13 @@
|
|||
- (void)loadStoryDetailView {
|
||||
NSString *feedTitle;
|
||||
if (self.isRiverView) {
|
||||
feedTitle = self.activeFolder;
|
||||
if ([self.activeFolder isEqualToString:@"river_blurblogs"]) {
|
||||
feedTitle = @"All Shared Stories";
|
||||
} else if ([self.activeFolder isEqualToString:@"everything"]) {
|
||||
feedTitle = @"All Stories";
|
||||
} else {
|
||||
feedTitle = self.activeFolder;
|
||||
}
|
||||
} else {
|
||||
feedTitle = [activeFeed objectForKey:@"feed_title"];
|
||||
}
|
||||
|
@ -758,11 +764,11 @@
|
|||
int total = 0;
|
||||
NSArray *folder;
|
||||
|
||||
if (!folderName && self.activeFolder == @"ALL BLURBLOG STORIES") {
|
||||
if (!folderName && self.activeFolder == @"river_blurblogs") {
|
||||
for (id feedId in self.dictSocialFeeds) {
|
||||
total += [self unreadCountForFeed:feedId];
|
||||
}
|
||||
} else if (!folderName && self.activeFolder == @"ALL STORIES STORIES") {
|
||||
} else if (!folderName && self.activeFolder == @"everything") {
|
||||
for (id feedId in self.dictFeeds) {
|
||||
total += [self unreadCountForFeed:feedId];
|
||||
}
|
||||
|
@ -960,7 +966,7 @@
|
|||
}
|
||||
|
||||
- (void)markActiveFolderAllRead {
|
||||
if (self.activeFolder == @"Everything") {
|
||||
if (self.activeFolder == @"everything") {
|
||||
for (NSString *folderName in self.dictFoldersArray) {
|
||||
for (id feedId in [self.dictFolders objectForKey:folderName]) {
|
||||
[self markFeedAllRead:feedId];
|
||||
|
@ -1153,9 +1159,11 @@
|
|||
- (UIView *)makeFeedTitle:(NSDictionary *)feed {
|
||||
UILabel *titleLabel = [[UILabel alloc] init];
|
||||
if (self.isSocialRiverView) {
|
||||
titleLabel.text = [NSString stringWithFormat:@" All Blurblog Stories"];
|
||||
titleLabel.text = [NSString stringWithFormat:@" All Shared Stories"];
|
||||
} else if (self.isRiverView && [self.activeFolder isEqualToString:@"everything"]) {
|
||||
titleLabel.text = [NSString stringWithFormat:@" All Stories"];
|
||||
} else if (self.isRiverView) {
|
||||
titleLabel.text = [NSString stringWithFormat:@" %@", self.activeFolder];
|
||||
titleLabel.text = [NSString stringWithFormat:@" %@", self.activeFolder];
|
||||
} else if (self.isSocialView) {
|
||||
titleLabel.text = [NSString stringWithFormat:@" %@", [feed objectForKey:@"feed_title"]];
|
||||
} else {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "NewsBlurAppDelegate.h"
|
||||
#import "FolderTitleView.h"
|
||||
#import "ASIHTTPRequest.h"
|
||||
#import "PullToRefreshView.h"
|
||||
#import "BaseViewController.h"
|
||||
|
@ -27,7 +28,6 @@
|
|||
NSMutableDictionary *visibleFeeds;
|
||||
NSMutableDictionary *stillVisibleFeeds;
|
||||
BOOL viewShowingAllFeeds;
|
||||
BOOL hasNoSites;
|
||||
PullToRefreshView *pull;
|
||||
NSDate *lastUpdate;
|
||||
NSCache *imageCache;
|
||||
|
@ -52,7 +52,6 @@
|
|||
@property (nonatomic) NSMutableDictionary *visibleFeeds;
|
||||
@property (nonatomic) NSMutableDictionary *stillVisibleFeeds;
|
||||
@property (nonatomic, readwrite) BOOL viewShowingAllFeeds;
|
||||
@property (nonatomic, readwrite) BOOL hasNoSites;
|
||||
@property (nonatomic) PullToRefreshView *pull;
|
||||
@property (nonatomic) NSDate *lastUpdate;
|
||||
@property (nonatomic) NSCache *imageCache;
|
||||
|
@ -70,6 +69,7 @@
|
|||
- (void)setUserAvatarLayout:(UIInterfaceOrientation)orientation;
|
||||
- (void)didSelectSectionHeader:(UIButton *)button;
|
||||
- (IBAction)selectIntelligence;
|
||||
- (void)didCollapseFolder:(UIButton *)button;
|
||||
- (void)changeToAllMode;
|
||||
- (void)updateFeedsWithIntelligence:(int)previousLevel newLevel:(int)newLevel;
|
||||
- (void)calculateFeedLocations:(BOOL)markVisible;
|
||||
|
|
|
@ -22,10 +22,11 @@
|
|||
#import "UIBarButtonItem+WEPopover.h"
|
||||
|
||||
|
||||
#define kPhoneTableViewRowHeight 36;
|
||||
#define kTableViewRowHeight 36;
|
||||
#define kPhoneTableViewRowHeight 32;
|
||||
#define kTableViewRowHeight 32;
|
||||
#define kBlurblogTableViewRowHeight 47;
|
||||
#define kPhoneBlurblogTableViewRowHeight 39;
|
||||
static const CGFloat kFolderTitleHeight = 28;
|
||||
|
||||
@interface NewsBlurViewController ()
|
||||
|
||||
|
@ -55,7 +56,6 @@
|
|||
@synthesize currentRowAtIndexPath;
|
||||
@synthesize noFocusMessage;
|
||||
@synthesize toolbarLeftMargin;
|
||||
@synthesize hasNoSites;
|
||||
@synthesize updatedDictFeeds_;
|
||||
@synthesize updatedDictSocialFeeds_;
|
||||
@synthesize inPullToRefresh_;
|
||||
|
@ -295,7 +295,7 @@
|
|||
return [self informError:@"The server barfed!"];
|
||||
}
|
||||
|
||||
self.hasNoSites = NO;
|
||||
appDelegate.hasNoSites = NO;
|
||||
NSString *responseString = [request responseString];
|
||||
NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSError *error;
|
||||
|
@ -393,10 +393,10 @@
|
|||
allFolders = [[results objectForKey:@"flat_folders"] mutableCopy];
|
||||
}
|
||||
|
||||
[allFolders setValue:socialFolder forKey:@""];
|
||||
[allFolders setValue:socialFolder forKey:@"river_blurblogs"];
|
||||
|
||||
if (![[allFolders allKeys] containsObject:@" "]) {
|
||||
[allFolders setValue:[[NSArray alloc] init] forKey:@" "];
|
||||
if (![[allFolders allKeys] containsObject:@"everything"]) {
|
||||
[allFolders setValue:[[NSArray alloc] init] forKey:@"everything"];
|
||||
}
|
||||
|
||||
appDelegate.dictFolders = allFolders;
|
||||
|
@ -434,6 +434,16 @@
|
|||
}
|
||||
appDelegate.dictFolders = sortedFolders;
|
||||
[appDelegate.dictFoldersArray sortUsingSelector:@selector(caseInsensitiveCompare:)];
|
||||
|
||||
// Move River Blurblog and Everything to the top
|
||||
if ([appDelegate.dictFoldersArray containsObject:@"river_blurblogs"]) {
|
||||
[appDelegate.dictFoldersArray removeObject:@"river_blurblogs"];
|
||||
[appDelegate.dictFoldersArray insertObject:@"river_blurblogs" atIndex:0];
|
||||
}
|
||||
if ([appDelegate.dictFoldersArray containsObject:@"everything"]) {
|
||||
[appDelegate.dictFoldersArray removeObject:@"everything"];
|
||||
[appDelegate.dictFoldersArray insertObject:@"everything" atIndex:1];
|
||||
}
|
||||
|
||||
if (self.viewShowingAllFeeds) {
|
||||
[self calculateFeedLocations:NO];
|
||||
|
@ -445,7 +455,7 @@
|
|||
|
||||
if ([[appDelegate.dictFeeds allKeys] count] == 0 &&
|
||||
[[appDelegate.dictSocialFeeds allKeys] count] == 0) {
|
||||
self.hasNoSites = YES;
|
||||
appDelegate.hasNoSites = YES;
|
||||
}
|
||||
|
||||
[self.feedTitlesTable reloadData];
|
||||
|
@ -567,7 +577,7 @@
|
|||
|
||||
- (void)switchSitesUnread {
|
||||
NSDictionary *feed;
|
||||
|
||||
|
||||
NSInteger intelligenceLevel = [appDelegate selectedIntelligence];
|
||||
NSMutableArray *indexPaths = [NSMutableArray array];
|
||||
|
||||
|
@ -617,18 +627,25 @@
|
|||
[self calculateFeedLocations:YES];
|
||||
}
|
||||
|
||||
[self.feedTitlesTable beginUpdates];
|
||||
if ([indexPaths count] > 0) {
|
||||
if (self.viewShowingAllFeeds) {
|
||||
[self.feedTitlesTable insertRowsAtIndexPaths:indexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
} else {
|
||||
|
||||
[self.feedTitlesTable deleteRowsAtIndexPaths:indexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
// @try {
|
||||
[self.feedTitlesTable beginUpdates];
|
||||
if ([indexPaths count] > 0) {
|
||||
if (self.viewShowingAllFeeds) {
|
||||
[self.feedTitlesTable insertRowsAtIndexPaths:indexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
} else {
|
||||
[self.feedTitlesTable deleteRowsAtIndexPaths:indexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
}
|
||||
}
|
||||
}
|
||||
[self.feedTitlesTable endUpdates];
|
||||
[self.feedTitlesTable endUpdates];
|
||||
// }
|
||||
// @catch (NSException *exception) {
|
||||
// NSLog(@"EXCEPTION: %@", exception);
|
||||
// [self.feedTitlesTable beginUpdates];
|
||||
// [self.feedTitlesTable endUpdates];
|
||||
// [self.feedTitlesTable reloadData];
|
||||
// }
|
||||
|
||||
CGPoint offset = CGPointMake(0, 0);
|
||||
[self.feedTitlesTable setContentOffset:offset animated:YES];
|
||||
|
@ -644,7 +661,7 @@
|
|||
#pragma mark Table View - Feed List
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
if (self.hasNoSites) {
|
||||
if (appDelegate.hasNoSites) {
|
||||
return 2;
|
||||
}
|
||||
return [appDelegate.dictFoldersArray count];
|
||||
|
@ -655,11 +672,12 @@
|
|||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
if (self.hasNoSites) {
|
||||
if (appDelegate.hasNoSites) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:section];
|
||||
|
||||
return [[self.activeFeedLocations objectForKey:folderName] count];
|
||||
}
|
||||
|
||||
|
@ -667,7 +685,7 @@
|
|||
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
// messaging when there are no sites
|
||||
if (self.hasNoSites) {
|
||||
if (appDelegate.hasNoSites) {
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"EmptyCell"];
|
||||
if (cell == nil) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
|
||||
|
@ -732,7 +750,7 @@
|
|||
- (void)tableView:(UITableView *)tableView
|
||||
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (self.hasNoSites) {
|
||||
if (appDelegate.hasNoSites) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -740,7 +758,14 @@
|
|||
self.currentRowAtIndexPath = indexPath;
|
||||
|
||||
NSDictionary *feed;
|
||||
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
|
||||
NSString *folderName;
|
||||
if (indexPath.section == 0) {
|
||||
folderName = @"river_blurblogs";
|
||||
} else if (indexPath.section == 1) {
|
||||
folderName = @"everything";
|
||||
} else {
|
||||
folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
|
||||
}
|
||||
NSArray *feeds = [appDelegate.dictFolders objectForKey:folderName];
|
||||
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
|
||||
int location = [[activeFolderFeeds objectAtIndex:indexPath.row] intValue];
|
||||
|
@ -772,7 +797,7 @@
|
|||
- (CGFloat)tableView:(UITableView *)tableView
|
||||
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
if (self.hasNoSites) {
|
||||
if (appDelegate.hasNoSites) {
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
return kBlurblogTableViewRowHeight;
|
||||
} else {
|
||||
|
@ -780,9 +805,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
|
||||
NSString *folderName;
|
||||
if (indexPath.section == 0) {
|
||||
folderName = @"river_blurblogs";
|
||||
} else {
|
||||
folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
|
||||
}
|
||||
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
NSString *collapseKey = [NSString stringWithFormat:@"folderCollapsed:%@", folderName];
|
||||
bool isFolderCollapsed = [userPreferences boolForKey:collapseKey];
|
||||
|
||||
if ([folderName isEqualToString:@""]) { // blurblogs
|
||||
if (isFolderCollapsed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ([folderName isEqualToString:@"river_blurblogs"]) { // blurblogs
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
return kBlurblogTableViewRowHeight;
|
||||
} else {
|
||||
|
@ -800,113 +837,11 @@
|
|||
- (UIView *)tableView:(UITableView *)tableView
|
||||
viewForHeaderInSection:(NSInteger)section {
|
||||
|
||||
int headerLabelHeight, folderImageViewY, disclosureImageViewY;
|
||||
|
||||
// if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
|
||||
headerLabelHeight = 27;
|
||||
folderImageViewY = 3;
|
||||
disclosureImageViewY = 7;
|
||||
// } else {
|
||||
// headerLabelHeight = 20;
|
||||
// folderImageViewY = 0;
|
||||
// disclosureImageViewY = 4;
|
||||
// }
|
||||
|
||||
// create the parent view that will hold header Label
|
||||
UIControl* customView = [[UIControl alloc]
|
||||
initWithFrame:CGRectMake(0.0, 0.0,
|
||||
tableView.bounds.size.width, headerLabelHeight + 1)];
|
||||
UIView *borderTop = [[UIView alloc]
|
||||
initWithFrame:CGRectMake(0.0, 0,
|
||||
tableView.bounds.size.width, 1.0)];
|
||||
borderTop.backgroundColor = UIColorFromRGB(0xe0e0e0);
|
||||
borderTop.opaque = NO;
|
||||
[customView addSubview:borderTop];
|
||||
CGRect rect = CGRectMake(0.0, 0.0, tableView.bounds.size.width, kFolderTitleHeight);
|
||||
UIView *folderTitle = [[FolderTitleView alloc] drawWithRect:rect inSection:section];
|
||||
|
||||
|
||||
UIView *borderBottom = [[UIView alloc]
|
||||
initWithFrame:CGRectMake(0.0, headerLabelHeight,
|
||||
tableView.bounds.size.width, 1.0)];
|
||||
borderBottom.backgroundColor = [UIColorFromRGB(0xB7BDC6) colorWithAlphaComponent:0.5];
|
||||
borderBottom.opaque = NO;
|
||||
[customView addSubview:borderBottom];
|
||||
|
||||
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
customView.opaque = NO;
|
||||
headerLabel.backgroundColor = [UIColor clearColor];
|
||||
headerLabel.opaque = NO;
|
||||
headerLabel.textColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1.0];
|
||||
headerLabel.highlightedTextColor = [UIColor whiteColor];
|
||||
headerLabel.font = [UIFont boldSystemFontOfSize:11];
|
||||
headerLabel.frame = CGRectMake(36.0, 1.0, 286.0, headerLabelHeight);
|
||||
headerLabel.shadowColor = [UIColor colorWithRed:.94 green:0.94 blue:0.97 alpha:1.0];
|
||||
headerLabel.shadowOffset = CGSizeMake(0.0, 1.0);
|
||||
if (section == 0) {
|
||||
headerLabel.text = @"ALL BLURBLOG STORIES";
|
||||
// customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
|
||||
// colorWithAlphaComponent:0.8];
|
||||
} else if (section == 1) {
|
||||
headerLabel.text = @"ALL STORIES";
|
||||
// customView.backgroundColor = [UIColorFromRGB(0xE6DDD7)
|
||||
// colorWithAlphaComponent:0.8];
|
||||
} else {
|
||||
headerLabel.text = [[appDelegate.dictFoldersArray objectAtIndex:section] uppercaseString];
|
||||
// customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
|
||||
// colorWithAlphaComponent:0.8];
|
||||
}
|
||||
|
||||
customView.backgroundColor = [UIColorFromRGB(0xD7DDE6)
|
||||
colorWithAlphaComponent:0.8];
|
||||
[customView addSubview:headerLabel];
|
||||
|
||||
UIImage *folderImage;
|
||||
int folderImageViewX = 10;
|
||||
|
||||
if (section == 0) {
|
||||
folderImage = [UIImage imageNamed:@"group.png"];
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
folderImageViewX = 10;
|
||||
} else {
|
||||
folderImageViewX = 8;
|
||||
}
|
||||
} else if (section == 1) {
|
||||
folderImage = [UIImage imageNamed:@"archive.png"];
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
folderImageViewX = 10;
|
||||
} else {
|
||||
folderImageViewX = 7;
|
||||
}
|
||||
} else {
|
||||
folderImage = [UIImage imageNamed:@"folder_2.png"];
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
} else {
|
||||
folderImageViewX = 7;
|
||||
}
|
||||
}
|
||||
UIImageView *folderImageView = [[UIImageView alloc] initWithImage:folderImage];
|
||||
folderImageView.frame = CGRectMake(folderImageViewX, folderImageViewY, 20, 20);
|
||||
[customView addSubview:folderImageView];
|
||||
|
||||
if (!self.hasNoSites) {
|
||||
UIImage *disclosureImage = [UIImage imageNamed:@"disclosure.png"];
|
||||
UIImageView *disclosureImageView = [[UIImageView alloc] initWithImage:disclosureImage];
|
||||
disclosureImageView.frame = CGRectMake(customView.frame.size.width - 20, disclosureImageViewY, 9.0, 14.0);
|
||||
[customView addSubview:disclosureImageView];
|
||||
}
|
||||
|
||||
UIButton *invisibleHeaderButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
invisibleHeaderButton.frame = CGRectMake(0, 0, customView.frame.size.width, customView.frame.size.height);
|
||||
invisibleHeaderButton.alpha = .1;
|
||||
invisibleHeaderButton.tag = section;
|
||||
[invisibleHeaderButton addTarget:self action:@selector(didSelectSectionHeader:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[customView addSubview:invisibleHeaderButton];
|
||||
|
||||
[invisibleHeaderButton addTarget:self action:@selector(sectionTapped:) forControlEvents:UIControlEventTouchDown];
|
||||
[invisibleHeaderButton addTarget:self action:@selector(sectionUntapped:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[invisibleHeaderButton addTarget:self action:@selector(sectionUntappedOutside:) forControlEvents:UIControlEventTouchUpOutside];
|
||||
|
||||
[customView setAutoresizingMask:UIViewAutoresizingNone];
|
||||
return customView;
|
||||
return folderTitle;
|
||||
}
|
||||
|
||||
- (IBAction)sectionTapped:(UIButton *)button {
|
||||
|
@ -950,9 +885,9 @@
|
|||
appDelegate.isSocialRiverView = YES;
|
||||
appDelegate.isRiverView = YES;
|
||||
// add all the feeds from every NON blurblog folder
|
||||
[appDelegate setActiveFolder:@"All Blurblog Stories"];
|
||||
[appDelegate setActiveFolder:@"river_blurblogs"];
|
||||
for (NSString *folderName in self.activeFeedLocations) {
|
||||
if ([folderName isEqualToString:@""]) { // remove all blurblugs which is a blank folder name
|
||||
if ([folderName isEqualToString:@"river_blurblogs"]) { // remove all blurblugs which is a blank folder name
|
||||
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
|
||||
NSArray *folderFeeds = [self.activeFeedLocations objectForKey:folderName];
|
||||
for (int l=0; l < [folderFeeds count]; l++) {
|
||||
|
@ -964,9 +899,9 @@
|
|||
appDelegate.isSocialRiverView = NO;
|
||||
appDelegate.isRiverView = YES;
|
||||
// add all the feeds from every NON blurblog folder
|
||||
[appDelegate setActiveFolder:@"All Stories"];
|
||||
[appDelegate setActiveFolder:@"everything"];
|
||||
for (NSString *folderName in self.activeFeedLocations) {
|
||||
if (![folderName isEqualToString:@""]) { // remove all blurblugs which is a blank folder name
|
||||
if (![folderName isEqualToString:@"river_blurblogs"]) {
|
||||
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
|
||||
NSArray *folderFeeds = [self.activeFeedLocations objectForKey:folderName];
|
||||
for (int l=0; l < [folderFeeds count]; l++) {
|
||||
|
@ -992,6 +927,35 @@
|
|||
[appDelegate loadRiverFeedDetailView];
|
||||
}
|
||||
|
||||
- (void)didCollapseFolder:(UIButton *)button {
|
||||
NSString *folderName;
|
||||
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
if (button.tag == 0) {
|
||||
folderName = @"river_blurblogs";
|
||||
} else {
|
||||
folderName = [appDelegate.dictFoldersArray objectAtIndex:button.tag];
|
||||
}
|
||||
|
||||
NSString *collapseKey = [NSString stringWithFormat:@"folderCollapsed:%@", folderName];
|
||||
bool isFolderCollapsed = [userPreferences boolForKey:collapseKey];
|
||||
|
||||
if (isFolderCollapsed) {
|
||||
// Expand folder
|
||||
[userPreferences setBool:NO forKey:collapseKey];
|
||||
} else {
|
||||
// Collapse folder
|
||||
[userPreferences setBool:YES forKey:collapseKey];
|
||||
}
|
||||
[userPreferences synchronize];
|
||||
|
||||
[self.feedTitlesTable reloadSections:[NSIndexSet indexSetWithIndex:button.tag]
|
||||
withRowAnimation:UITableViewRowAnimationFade];
|
||||
[self.feedTitlesTable beginUpdates];
|
||||
[self.feedTitlesTable endUpdates];
|
||||
|
||||
}
|
||||
|
||||
- (void)changeToAllMode {
|
||||
[self.intelligenceControl setSelectedSegmentIndex:0];
|
||||
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
|
@ -1007,7 +971,7 @@
|
|||
|
||||
int selectedSegmentIndex = [self.intelligenceControl selectedSegmentIndex];
|
||||
|
||||
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
if (selectedSegmentIndex == 0) {
|
||||
hud.labelText = @"All Stories";
|
||||
[userPreferences setInteger:-1 forKey:@"selectedIntelligence"];
|
||||
|
@ -1017,7 +981,7 @@
|
|||
int previousLevel = appDelegate.selectedIntelligence;
|
||||
[appDelegate setSelectedIntelligence:0];
|
||||
[self updateFeedsWithIntelligence:previousLevel newLevel:0];
|
||||
[self redrawUnreadCounts];
|
||||
[self redrawUnreadCounts];
|
||||
}
|
||||
self.viewShowingAllFeeds = YES;
|
||||
[self switchSitesUnread];
|
||||
|
@ -1049,7 +1013,7 @@
|
|||
[self redrawUnreadCounts];
|
||||
}
|
||||
|
||||
[hud hide:YES afterDelay:0.75];
|
||||
[hud hide:YES afterDelay:0.5];
|
||||
|
||||
// [self.feedTitlesTable reloadData];
|
||||
}
|
||||
|
@ -1147,16 +1111,22 @@
|
|||
[self calculateFeedLocations:NO];
|
||||
}
|
||||
|
||||
[self.feedTitlesTable beginUpdates];
|
||||
if ([deleteIndexPaths count] > 0) {
|
||||
[self.feedTitlesTable deleteRowsAtIndexPaths:deleteIndexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
@try {
|
||||
[self.feedTitlesTable beginUpdates];
|
||||
if ([deleteIndexPaths count] > 0) {
|
||||
[self.feedTitlesTable deleteRowsAtIndexPaths:deleteIndexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
}
|
||||
if ([insertIndexPaths count] > 0) {
|
||||
[self.feedTitlesTable insertRowsAtIndexPaths:insertIndexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
}
|
||||
[self.feedTitlesTable endUpdates];
|
||||
}
|
||||
if ([insertIndexPaths count] > 0) {
|
||||
[self.feedTitlesTable insertRowsAtIndexPaths:insertIndexPaths
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
@catch (NSException *exception) {
|
||||
NSLog(@"Exception: %@", exception);
|
||||
[self.feedTitlesTable reloadData];
|
||||
}
|
||||
[self.feedTitlesTable endUpdates];
|
||||
|
||||
// scrolls to the top and fixes header rendering bug
|
||||
CGPoint offsetOne = CGPointMake(0, 1);
|
||||
|
@ -1186,7 +1156,7 @@
|
|||
id feedId = [folder objectAtIndex:f];
|
||||
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
||||
|
||||
if ([folderName isEqualToString:@""]){
|
||||
if ([folderName isEqualToString:@"river_blurblogs"]){
|
||||
feed = [appDelegate.dictSocialFeeds objectForKey:feedIdStr];
|
||||
} else {
|
||||
feed = [appDelegate.dictFeeds objectForKey:feedIdStr];
|
||||
|
@ -1201,7 +1171,7 @@
|
|||
[feedLocations addObject:location];
|
||||
} else {
|
||||
int maxScore = [NewsBlurViewController computeMaxScoreForFeed:feed];
|
||||
// if ([folderName isEqualToString:@""]){
|
||||
// if ([folderName isEqualToString:@"river_blurblogs"]){
|
||||
// NSLog(@"Computing score for %@: %d in %d (markVisible: %d)",
|
||||
// [feed objectForKey:@"feed_title"], maxScore, appDelegate.selectedIntelligence, markVisible);
|
||||
// }
|
||||
|
@ -1216,10 +1186,6 @@
|
|||
}
|
||||
|
||||
}
|
||||
if ([folderName isEqualToString:@""]){
|
||||
// NSLog(@"feedLocations count is %i: ", [feedLocations count]);
|
||||
}
|
||||
// NSLog(@"feedLocations %@", feedLocations);
|
||||
[self.activeFeedLocations setObject:feedLocations forKey:folderName];
|
||||
|
||||
}
|
||||
|
|
|
@ -307,12 +307,10 @@
|
|||
|
||||
if ([self.followButton.currentTitle isEqualToString:@"Follow"]) {
|
||||
urlString = [NSString stringWithFormat:@"http://%@/social/follow",
|
||||
NEWSBLUR_URL,
|
||||
[self.activeProfile objectForKey:@"user_id"]];
|
||||
NEWSBLUR_URL];
|
||||
} else {
|
||||
urlString = [NSString stringWithFormat:@"http://%@/social/unfollow",
|
||||
NEWSBLUR_URL,
|
||||
[self.activeProfile objectForKey:@"user_id"]];
|
||||
NEWSBLUR_URL];
|
||||
}
|
||||
|
||||
NSURL *url = [NSURL URLWithString:urlString];
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "WEPopoverController.h"
|
||||
|
||||
@class NewsBlurAppDelegate;
|
||||
@class ASIHTTPRequest;
|
||||
|
||||
@interface StoryDetailViewController : UIViewController
|
||||
<UIPopoverControllerDelegate, WEPopoverControllerDelegate> {
|
||||
<UIPopoverControllerDelegate, WEPopoverControllerDelegate,
|
||||
UIScrollViewDelegate> {
|
||||
NewsBlurAppDelegate *appDelegate;
|
||||
|
||||
NSString *activeStoryId;
|
||||
|
@ -29,7 +31,7 @@
|
|||
UIToolbar *bottomPlaceholderToolbar;
|
||||
UIBarButtonItem *buttonBack;
|
||||
Class popoverClass;
|
||||
|
||||
BOOL pullingScrollview;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) UIActivityIndicatorView *loadingIndicator;
|
||||
|
@ -53,6 +55,7 @@
|
|||
@property (nonatomic) IBOutlet UIBarButtonItem *originalStoryButton;
|
||||
@property (nonatomic, strong) IBOutlet UIBarButtonItem *subscribeButton;
|
||||
@property (nonatomic) IBOutlet UILabel *noStorySelectedLabel;
|
||||
@property (nonatomic, assign) BOOL pullingScrollview;
|
||||
|
||||
|
||||
- (void)setNextPreviousButtons;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
@synthesize noStorySelectedLabel;
|
||||
@synthesize buttonBack;
|
||||
@synthesize bottomPlaceholderToolbar;
|
||||
@synthesize pullingScrollview;
|
||||
|
||||
// private
|
||||
@synthesize inTouchMove;
|
||||
|
@ -799,36 +800,88 @@
|
|||
feed = [appDelegate.dictFeeds objectForKey:feedIdStr];
|
||||
}
|
||||
|
||||
self.feedTitleGradient = [appDelegate makeFeedTitleGradient:feed
|
||||
self.feedTitleGradient = [appDelegate makeFeedTitleGradient:feed
|
||||
withRect:CGRectMake(0, -1, 1024, 21)]; // 1024 hack for self.webView.frame.size.width
|
||||
|
||||
self.feedTitleGradient.tag = FEED_TITLE_GRADIENT_TAG; // Not attached yet. Remove old gradients, first.
|
||||
[self.feedTitleGradient.layer setShadowColor:[[UIColor blackColor] CGColor]];
|
||||
[self.feedTitleGradient.layer setShadowOffset:CGSizeMake(0, 0)];
|
||||
[self.feedTitleGradient.layer setShadowOpacity:0];
|
||||
[self.feedTitleGradient.layer setShadowRadius:12.0];
|
||||
|
||||
for (UIView *subview in self.webView.subviews) {
|
||||
if (subview.tag == FEED_TITLE_GRADIENT_TAG) {
|
||||
[subview removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
for (NSObject *aSubView in [self.webView subviews]) {
|
||||
if ([aSubView isKindOfClass:[UIScrollView class]]) {
|
||||
UIScrollView * theScrollView = (UIScrollView *)aSubView;
|
||||
if (appDelegate.isRiverView || appDelegate.isSocialView) {
|
||||
theScrollView.contentInset = UIEdgeInsetsMake(19, 0, 0, 0);
|
||||
theScrollView.scrollIndicatorInsets = UIEdgeInsetsMake(19, 0, 0, 0);
|
||||
} else {
|
||||
theScrollView.contentInset = UIEdgeInsetsMake(9, 0, 0, 0);
|
||||
theScrollView.scrollIndicatorInsets = UIEdgeInsetsMake(9, 0, 0, 0);
|
||||
}
|
||||
[self.webView insertSubview:feedTitleGradient aboveSubview:theScrollView];
|
||||
[theScrollView setContentOffset:CGPointMake(0, (appDelegate.isRiverView || appDelegate.isSocialView) ? -19 : -9) animated:NO];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (appDelegate.isRiverView || appDelegate.isSocialView) {
|
||||
self.webView.scrollView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
|
||||
self.webView.scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(20, 0, 0, 0);
|
||||
} else {
|
||||
self.webView.scrollView.contentInset = UIEdgeInsetsMake(9, 0, 0, 0);
|
||||
self.webView.scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(9, 0, 0, 0);
|
||||
}
|
||||
[self.webView insertSubview:feedTitleGradient aboveSubview:self.webView.scrollView];
|
||||
[self.webView.scrollView setContentOffset:CGPointMake(0, (appDelegate.isRiverView ||
|
||||
appDelegate.isSocialView) ? -20 : -9)
|
||||
animated:NO];
|
||||
[self.webView.scrollView addObserver:self forKeyPath:@"contentOffset"
|
||||
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
|
||||
context:nil];
|
||||
|
||||
|
||||
|
||||
[self setNextPreviousButtons];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
|
||||
if (keyPath == @"contentOffset") {
|
||||
if (self.webView.scrollView.contentOffset.y < -20) {
|
||||
// Pulling
|
||||
if (!pullingScrollview) {
|
||||
pullingScrollview = YES;
|
||||
[self.feedTitleGradient.layer setShadowOpacity:.5];
|
||||
[self.webView insertSubview:self.feedTitleGradient belowSubview:self.webView.scrollView];
|
||||
|
||||
for (id subview in self.webView.scrollView.subviews) {
|
||||
UIImageView *imgView = [subview isKindOfClass:[UIImageView class]] ?
|
||||
(UIImageView*)subview : nil;
|
||||
// image views whose image is 1px wide are shadow images, hide them
|
||||
if (imgView && imgView.image.size.width == 1) {
|
||||
imgView.hidden = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
float y = -1 * self.webView.scrollView.contentOffset.y - 20 - 1;
|
||||
self.feedTitleGradient.frame = CGRectMake(0, y,
|
||||
self.feedTitleGradient.frame.size.width,
|
||||
self.feedTitleGradient.frame.size.height);
|
||||
} else {
|
||||
// Normal reading
|
||||
if (pullingScrollview) {
|
||||
pullingScrollview = NO;
|
||||
[self.feedTitleGradient.layer setShadowOpacity:0];
|
||||
[self.webView insertSubview:self.feedTitleGradient aboveSubview:self.webView.scrollView];
|
||||
|
||||
self.feedTitleGradient.frame = CGRectMake(0, -1,
|
||||
self.feedTitleGradient.frame.size.width,
|
||||
self.feedTitleGradient.frame.size.height);
|
||||
|
||||
for (id subview in self.webView.scrollView.subviews) {
|
||||
UIImageView *imgView = [subview isKindOfClass:[UIImageView class]] ?
|
||||
(UIImageView*)subview : nil;
|
||||
// image views whose image is 1px wide are shadow images, hide them
|
||||
if (imgView && imgView.image.size.width == 1) {
|
||||
imgView.hidden = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setActiveStory {
|
||||
self.activeStoryId = [appDelegate.activeStory objectForKey:@"id"];
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
||||
|
@ -994,8 +1047,8 @@ shouldStartLoadWithRequest:(NSURLRequest *)request
|
|||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
// only adjust for the bar if user is scrolling
|
||||
if (appDelegate.isRiverView || appDelegate.isSocialView) {
|
||||
if (self.webView.scrollView.contentOffset.y == -19) {
|
||||
y = y + 19;
|
||||
if (self.webView.scrollView.contentOffset.y == -20) {
|
||||
y = y + 20;
|
||||
}
|
||||
} else {
|
||||
if (self.webView.scrollView.contentOffset.y == -9) {
|
||||
|
@ -1231,11 +1284,11 @@ shouldStartLoadWithRequest:(NSURLRequest *)request
|
|||
}
|
||||
|
||||
- (void)finishMarkAsRead:(ASIHTTPRequest *)request {
|
||||
NSString *responseString = [request responseString];
|
||||
NSDictionary *results = [[NSDictionary alloc]
|
||||
initWithDictionary:[responseString JSONValue]];
|
||||
NSLog(@"results in mark as read is %@", results);
|
||||
}
|
||||
// NSString *responseString = [request responseString];
|
||||
// NSDictionary *results = [[NSDictionary alloc]
|
||||
// initWithDictionary:[responseString JSONValue]];
|
||||
// NSLog(@"results in mark as read is %@", results);
|
||||
}
|
||||
|
||||
# pragma mark
|
||||
# pragma mark Subscribing to blurblog
|
||||
|
|
32
media/ios/Classes/UnreadCountView.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// UnreadCountView.h
|
||||
// NewsBlur
|
||||
//
|
||||
// Created by Samuel Clay on 10/3/12.
|
||||
// Copyright (c) 2012 NewsBlur. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "NewsBlurAppDelegate.h"
|
||||
|
||||
@class NewsBlurAppDelegate;
|
||||
|
||||
@interface UnreadCountView : UIView
|
||||
|
||||
typedef enum {
|
||||
NBFeedListFeed = 1,
|
||||
NBFeedListSocial = 2,
|
||||
NBFeedListFolder = 3
|
||||
} NBFeedListType;
|
||||
|
||||
@property (nonatomic) NewsBlurAppDelegate *appDelegate;
|
||||
@property (assign, nonatomic) int psWidth;
|
||||
@property (assign, nonatomic) int psPadding;
|
||||
@property (assign, nonatomic) int ntWidth;
|
||||
@property (assign, nonatomic) int ntPadding;
|
||||
@property (assign, nonatomic) CGRect rect;
|
||||
|
||||
- (void)drawInRect:(CGRect)r ps:(int)ps nt:(int)nt listType:(NBFeedListType)listType;
|
||||
- (int)offsetWidth;
|
||||
|
||||
@end
|
127
media/ios/Classes/UnreadCountView.m
Normal file
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// UnreadCountView.m
|
||||
// NewsBlur
|
||||
//
|
||||
// Created by Samuel Clay on 10/3/12.
|
||||
// Copyright (c) 2012 NewsBlur. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UnreadCountView.h"
|
||||
#import "UIView+TKCategory.h"
|
||||
|
||||
static UIFont *indicatorFont = nil;
|
||||
static UIColor *indicatorWhiteColor = nil;
|
||||
static UIColor *indicatorBlackColor = nil;
|
||||
static UIColor *positiveBackgroundColor = nil;
|
||||
static UIColor *neutralBackgroundColor = nil;
|
||||
static UIColor *negativeBackgroundColor = nil;
|
||||
|
||||
@implementation UnreadCountView
|
||||
|
||||
@synthesize appDelegate;
|
||||
@synthesize psWidth, psPadding, ntWidth, ntPadding;
|
||||
@synthesize rect;
|
||||
|
||||
+ (void) initialize {
|
||||
if (self == [UnreadCountView class]) {
|
||||
indicatorFont = [UIFont boldSystemFontOfSize:12];
|
||||
indicatorWhiteColor = [UIColor whiteColor];
|
||||
indicatorBlackColor = [UIColor blackColor];
|
||||
|
||||
UIColor *ps = UIColorFromRGB(0x3B7613);
|
||||
UIColor *nt = UIColorFromRGB(0xF9C72A);
|
||||
UIColor *ng = UIColorFromRGB(0xCC2A2E);
|
||||
positiveBackgroundColor = ps;
|
||||
neutralBackgroundColor = nt;
|
||||
negativeBackgroundColor = ng;
|
||||
// UIColor *psGrad = UIColorFromRGB(0x559F4D);
|
||||
// UIColor *ntGrad = UIColorFromRGB(0xE4AB00);
|
||||
// UIColor *ngGrad = UIColorFromRGB(0x9B181B);
|
||||
// const CGFloat* psTop = CGColorGetComponents(ps.CGColor);
|
||||
// const CGFloat* psBot = CGColorGetComponents(psGrad.CGColor);
|
||||
// CGFloat psGradient[] = {
|
||||
// psTop[0], psTop[1], psTop[2], psTop[3],
|
||||
// psBot[0], psBot[1], psBot[2], psBot[3]
|
||||
// };
|
||||
// psColors = psGradient;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawInRect:(CGRect)r ps:(int)ps nt:(int)nt listType:(NBFeedListType)listType {
|
||||
rect = CGRectInset(r, 12, 12);
|
||||
rect.size.width -= 18; // Scrollbar padding
|
||||
|
||||
psWidth = ps == 0 ? 0 : ps < 10 ? 14 : ps < 100 ? 22 : 28;
|
||||
ntWidth = nt == 0 ? 0 : nt < 10 ? 14 : nt < 100 ? 22 : 28;
|
||||
|
||||
int psOffset = ps == 0 ? 0 : psWidth - 20;
|
||||
int ntOffset = nt == 0 ? 0 : ntWidth - 20;
|
||||
|
||||
psPadding = ps == 0 ? 0 : 2;
|
||||
ntPadding = nt == 0 ? 0 : 2;
|
||||
|
||||
if (ps > 0){
|
||||
[positiveBackgroundColor set];
|
||||
CGRect rr;
|
||||
|
||||
if (listType == NBFeedListSocial) {
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psOffset, 14, psWidth, 17);
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psOffset, 10, psWidth, 17);
|
||||
}
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psOffset, 7, psWidth, 17);
|
||||
}
|
||||
|
||||
[UIView drawRoundRectangleInRect:rr withRadius:4];
|
||||
|
||||
[indicatorWhiteColor set];
|
||||
|
||||
NSString *psStr = [NSString stringWithFormat:@"%d", ps];
|
||||
CGSize size = [psStr sizeWithFont:indicatorFont];
|
||||
float x_pos = (rr.size.width - size.width) / 2;
|
||||
float y_pos = (rr.size.height - size.height) / 2;
|
||||
[psStr
|
||||
drawAtPoint:CGPointMake(rr.origin.x + x_pos, rr.origin.y + y_pos)
|
||||
withFont:indicatorFont];
|
||||
}
|
||||
|
||||
if (nt > 0 && appDelegate.selectedIntelligence <= 0){
|
||||
[neutralBackgroundColor set];
|
||||
|
||||
CGRect rr;
|
||||
if (listType == NBFeedListSocial) {
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psWidth - psPadding - ntOffset, 14, ntWidth, 17);
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psWidth - psPadding - ntOffset, 10, ntWidth, 17);
|
||||
}
|
||||
} else {
|
||||
rr = CGRectMake(rect.size.width + rect.origin.x - psWidth - psPadding - ntOffset, 7, ntWidth, 17);
|
||||
}
|
||||
|
||||
[UIView drawRoundRectangleInRect:rr withRadius:4];
|
||||
// [UIView drawLinearGradientInRect:rr colors:ntColors];
|
||||
|
||||
[indicatorBlackColor set];
|
||||
|
||||
NSString *ntStr = [NSString stringWithFormat:@"%d", nt];
|
||||
CGSize size = [ntStr sizeWithFont:indicatorFont];
|
||||
float x_pos = (rr.size.width - size.width) / 2;
|
||||
float y_pos = (rr.size.height - size.height) / 2;
|
||||
[ntStr
|
||||
drawAtPoint:CGPointMake(rr.origin.x + x_pos, rr.origin.y + y_pos)
|
||||
withFont:indicatorFont];
|
||||
|
||||
if (listType == NBFeedListFolder) {
|
||||
NSLog(@"Drawing: %@", NSStringFromCGRect(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (int)offsetWidth {
|
||||
return rect.size.width - psWidth - psPadding - ntWidth - ntPadding;
|
||||
}
|
||||
|
||||
@end
|
|
@ -5,7 +5,7 @@
|
|||
<key>application-identifier</key>
|
||||
<string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
|
||||
<key>get-task-allow</key>
|
||||
<false/>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
|
||||
|
|
|
@ -102,7 +102,6 @@
|
|||
43A4C3D715B00966008787B5 /* ABTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A4C3BA15B00966008787B5 /* ABTableViewCell.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
43A4C3D815B00966008787B5 /* Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A4C3BC15B00966008787B5 /* Base64.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
43A4C3DA15B00966008787B5 /* GTMNString+HTML.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A4C3C015B00966008787B5 /* GTMNString+HTML.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
43A4C3DB15B00966008787B5 /* libTestFlight.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43A4C3C115B00966008787B5 /* libTestFlight.a */; };
|
||||
43A4C3DC15B00966008787B5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A4C3C215B00966008787B5 /* main.m */; };
|
||||
43A4C3DD15B00966008787B5 /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A4C3C415B00966008787B5 /* MBProgressHUD.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
43A4C3E115B00966008787B5 /* NSString+HTML.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A4C3CD15B00966008787B5 /* NSString+HTML.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
|
@ -367,6 +366,11 @@
|
|||
FFAD4971144A386100BA6919 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FFAD4970144A386100BA6919 /* libz.dylib */; };
|
||||
FFD1D7311459B63500E46F89 /* BaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD1D7301459B63500E46F89 /* BaseViewController.m */; };
|
||||
FFD887F01445F1E800385399 /* AddSiteAutocompleteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD887EE1445F1E800385399 /* AddSiteAutocompleteCell.m */; };
|
||||
FFDE35CC161B8F870034BFDE /* FolderTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = FFDE35CB161B8F870034BFDE /* FolderTitleView.m */; };
|
||||
FFDE35D2161B9E600034BFDE /* disclosure_border.png in Resources */ = {isa = PBXBuildFile; fileRef = FFDE35D1161B9E600034BFDE /* disclosure_border.png */; };
|
||||
FFDE35D6161CCABC0034BFDE /* folder_collapsed.png in Resources */ = {isa = PBXBuildFile; fileRef = FFDE35D4161CCABC0034BFDE /* folder_collapsed.png */; };
|
||||
FFDE35D7161CCABC0034BFDE /* folder_collapsed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFDE35D5161CCABC0034BFDE /* folder_collapsed@2x.png */; };
|
||||
FFDE35DA161D12250034BFDE /* UnreadCountView.m in Sources */ = {isa = PBXBuildFile; fileRef = FFDE35D9161D12250034BFDE /* UnreadCountView.m */; };
|
||||
FFE5322F144C8AC300ACFDE0 /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = FFE5322E144C8AC300ACFDE0 /* Utilities.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -498,7 +502,6 @@
|
|||
43A4C3BE15B00966008787B5 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMDefines.h; path = "Other Sources/GTMDefines.h"; sourceTree = "<group>"; };
|
||||
43A4C3BF15B00966008787B5 /* GTMNString+HTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GTMNString+HTML.h"; path = "Other Sources/GTMNString+HTML.h"; sourceTree = "<group>"; };
|
||||
43A4C3C015B00966008787B5 /* GTMNString+HTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "GTMNString+HTML.m"; path = "Other Sources/GTMNString+HTML.m"; sourceTree = "<group>"; };
|
||||
43A4C3C115B00966008787B5 /* libTestFlight.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libTestFlight.a; path = "Other Sources/libTestFlight.a"; sourceTree = "<group>"; };
|
||||
43A4C3C215B00966008787B5 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "Other Sources/main.m"; sourceTree = "<group>"; };
|
||||
43A4C3C315B00966008787B5 /* MBProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MBProgressHUD.h; path = "Other Sources/MBProgressHUD.h"; sourceTree = "<group>"; };
|
||||
43A4C3C415B00966008787B5 /* MBProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MBProgressHUD.m; path = "Other Sources/MBProgressHUD.m"; sourceTree = "<group>"; };
|
||||
|
@ -882,6 +885,13 @@
|
|||
FFD1D7301459B63500E46F89 /* BaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseViewController.m; sourceTree = "<group>"; };
|
||||
FFD887ED1445F1E800385399 /* AddSiteAutocompleteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddSiteAutocompleteCell.h; sourceTree = "<group>"; };
|
||||
FFD887EE1445F1E800385399 /* AddSiteAutocompleteCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddSiteAutocompleteCell.m; sourceTree = "<group>"; };
|
||||
FFDE35CA161B8F870034BFDE /* FolderTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FolderTitleView.h; sourceTree = "<group>"; };
|
||||
FFDE35CB161B8F870034BFDE /* FolderTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FolderTitleView.m; sourceTree = "<group>"; };
|
||||
FFDE35D1161B9E600034BFDE /* disclosure_border.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = disclosure_border.png; sourceTree = "<group>"; };
|
||||
FFDE35D4161CCABC0034BFDE /* folder_collapsed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = folder_collapsed.png; sourceTree = "<group>"; };
|
||||
FFDE35D5161CCABC0034BFDE /* folder_collapsed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder_collapsed@2x.png"; sourceTree = "<group>"; };
|
||||
FFDE35D8161D12250034BFDE /* UnreadCountView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnreadCountView.h; sourceTree = "<group>"; };
|
||||
FFDE35D9161D12250034BFDE /* UnreadCountView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UnreadCountView.m; sourceTree = "<group>"; };
|
||||
FFE5322D144C8AC300ACFDE0 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
|
||||
FFE5322E144C8AC300ACFDE0 /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -903,7 +913,6 @@
|
|||
78095E3F128EF35400230C8E /* CFNetwork.framework in Frameworks */,
|
||||
78095E43128EF37E00230C8E /* MobileCoreServices.framework in Frameworks */,
|
||||
78095E45128EF37E00230C8E /* SystemConfiguration.framework in Frameworks */,
|
||||
43A4C3DB15B00966008787B5 /* libTestFlight.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -975,7 +984,6 @@
|
|||
43A4C3BE15B00966008787B5 /* GTMDefines.h */,
|
||||
43A4C3BF15B00966008787B5 /* GTMNString+HTML.h */,
|
||||
43A4C3C015B00966008787B5 /* GTMNString+HTML.m */,
|
||||
43A4C3C115B00966008787B5 /* libTestFlight.a */,
|
||||
43A4C3C215B00966008787B5 /* main.m */,
|
||||
43A4C3C315B00966008787B5 /* MBProgressHUD.h */,
|
||||
43A4C3C415B00966008787B5 /* MBProgressHUD.m */,
|
||||
|
@ -1119,6 +1127,10 @@
|
|||
FFD887EE1445F1E800385399 /* AddSiteAutocompleteCell.m */,
|
||||
FF5EA47C143B691000B7563D /* AddSiteViewController.h */,
|
||||
FF5EA47D143B691000B7563D /* AddSiteViewController.m */,
|
||||
FFDE35CA161B8F870034BFDE /* FolderTitleView.h */,
|
||||
FFDE35CB161B8F870034BFDE /* FolderTitleView.m */,
|
||||
FFDE35D8161D12250034BFDE /* UnreadCountView.h */,
|
||||
FFDE35D9161D12250034BFDE /* UnreadCountView.m */,
|
||||
);
|
||||
name = Feeds;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1139,6 +1151,9 @@
|
|||
431B857615A132B600DCE497 /* Images */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FFDE35D4161CCABC0034BFDE /* folder_collapsed.png */,
|
||||
FFDE35D5161CCABC0034BFDE /* folder_collapsed@2x.png */,
|
||||
FFDE35D1161B9E600034BFDE /* disclosure_border.png */,
|
||||
43BC458E15D9F75F00205B69 /* facebook_button_on.png */,
|
||||
43BC458F15D9F75F00205B69 /* facebook_button_on@2x.png */,
|
||||
43BC459015D9F75F00205B69 /* facebook_button.png */,
|
||||
|
@ -2108,6 +2123,9 @@
|
|||
43BC459515D9F76000205B69 /* facebook_button@2x.png in Resources */,
|
||||
FF546DF71602930100948020 /* Default-568h@2x.png in Resources */,
|
||||
FF546DF9160298E500948020 /* fleuron@2x.png in Resources */,
|
||||
FFDE35D2161B9E600034BFDE /* disclosure_border.png in Resources */,
|
||||
FFDE35D6161CCABC0034BFDE /* folder_collapsed.png in Resources */,
|
||||
FFDE35D7161CCABC0034BFDE /* folder_collapsed@2x.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -2253,6 +2271,8 @@
|
|||
438FEDE815D5B15F00E3B3C9 /* FollowGrid.m in Sources */,
|
||||
43B232C015D5F61700D035B4 /* AuthorizeServicesViewController.m in Sources */,
|
||||
43CE0F5F15DADB7F00608ED8 /* SiteCell.m in Sources */,
|
||||
FFDE35CC161B8F870034BFDE /* FolderTitleView.m in Sources */,
|
||||
FFDE35DA161D12250034BFDE /* UnreadCountView.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -2269,7 +2289,7 @@
|
|||
);
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Entitlements.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer: Samuel Clay (G9HFWP68T7)";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
|
@ -2286,6 +2306,7 @@
|
|||
"\"$(SRCROOT)\"",
|
||||
"\"$(SRCROOT)/Other Sources\"",
|
||||
);
|
||||
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
|
||||
OTHER_LDFLAGS = (
|
||||
"-all_load",
|
||||
"-ObjC",
|
||||
|
@ -2308,7 +2329,7 @@
|
|||
);
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Entitlements.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution: NewsBlur, Inc.";
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer: Samuel Clay (G9HFWP68T7)";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: NewsBlur, Inc.";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
|
@ -2328,7 +2349,7 @@
|
|||
"-all_load",
|
||||
);
|
||||
PRODUCT_NAME = NewsBlur;
|
||||
PROVISIONING_PROFILE = "3674B4BA-9006-4099-A608-673EC3103906";
|
||||
PROVISIONING_PROFILE = "";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "3674B4BA-9006-4099-A608-673EC3103906";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
|
|
|
@ -2,6 +2,21 @@
|
|||
<Bucket
|
||||
type = "1"
|
||||
version = "1.0">
|
||||
<FileBreakpoints>
|
||||
<FileBreakpoint
|
||||
shouldBeEnabled = "No"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "Classes/NewsBlurViewController.m"
|
||||
timestampString = "370996140.882983"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "594"
|
||||
endingLineNumber = "594"
|
||||
landmarkName = "-switchSitesUnread"
|
||||
landmarkType = "5">
|
||||
</FileBreakpoint>
|
||||
</FileBreakpoints>
|
||||
<SymbolicBreakpoints>
|
||||
<SymbolicBreakpoint
|
||||
shouldBeEnabled = "Yes"
|
||||
|
@ -11,4 +26,13 @@
|
|||
moduleName = "">
|
||||
</SymbolicBreakpoint>
|
||||
</SymbolicBreakpoints>
|
||||
<ExceptionBreakpoints>
|
||||
<ExceptionBreakpoint
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
scope = "0"
|
||||
stopOnStyle = "0">
|
||||
</ExceptionBreakpoint>
|
||||
</ExceptionBreakpoints>
|
||||
</Bucket>
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1296</int>
|
||||
<string key="IBDocument.SystemVersion">11E53</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">2182</string>
|
||||
<string key="IBDocument.AppKitVersion">1138.47</string>
|
||||
<string key="IBDocument.HIToolboxVersion">569.00</string>
|
||||
<int key="IBDocument.SystemTarget">1536</int>
|
||||
<string key="IBDocument.SystemVersion">12C54</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">2840</string>
|
||||
<string key="IBDocument.AppKitVersion">1187.34</string>
|
||||
<string key="IBDocument.HIToolboxVersion">625.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">1181</string>
|
||||
<string key="NS.object.0">1926</string>
|
||||
</object>
|
||||
<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>IBUIBarButtonItem</string>
|
||||
<string>IBUISegmentedControl</string>
|
||||
<string>IBUIPickerView</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBUITextField</string>
|
||||
<string>IBProxyObject</string>
|
||||
<string>IBUIActivityIndicatorView</string>
|
||||
<string>IBUIBarButtonItem</string>
|
||||
<string>IBUIImageView</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBUINavigationBar</string>
|
||||
<string>IBUINavigationItem</string>
|
||||
<string>IBUIPickerView</string>
|
||||
<string>IBUIScrollView</string>
|
||||
<string>IBUIView</string>
|
||||
<string>IBUIImageView</string>
|
||||
<string>IBUISegmentedControl</string>
|
||||
<string>IBUITableView</string>
|
||||
<string>IBUIActivityIndicatorView</string>
|
||||
<string>IBUITextField</string>
|
||||
<string>IBUIView</string>
|
||||
</object>
|
||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -51,7 +51,7 @@
|
|||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIImageView" id="567507966">
|
||||
<reference key="NSNextResponder" ref="973185930"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<int key="NSvFlags">277</int>
|
||||
<string key="NSFrame">{{0, 44}, {320, 416}}</string>
|
||||
<reference key="NSSuperview" ref="973185930"/>
|
||||
<reference key="NSWindow"/>
|
||||
|
@ -70,7 +70,6 @@
|
|||
<string key="NSFrame">{{111, 294}, {189, 52}}</string>
|
||||
<reference key="NSSuperview" ref="973185930"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:311</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
|
@ -86,6 +85,7 @@
|
|||
<object class="NSColor" key="IBUIShadowColor" id="444286937">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MCAwIDAAA</bytes>
|
||||
<string key="IBUIColorCocoaTouchKeyPath">darkTextColor</string>
|
||||
</object>
|
||||
<int key="IBUIBaselineAdjustment">1</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
|
@ -127,6 +127,7 @@
|
|||
<int key="IBUITextAlignment">1</int>
|
||||
<reference key="IBUIFontDescription" ref="992356106"/>
|
||||
<reference key="IBUIFont" ref="24658222"/>
|
||||
<double key="preferredMaxLayoutWidth">280</double>
|
||||
</object>
|
||||
<object class="IBUIActivityIndicatorView" id="900763914">
|
||||
<reference key="NSNextResponder" ref="973185930"/>
|
||||
|
@ -338,7 +339,7 @@
|
|||
</object>
|
||||
<object class="IBUIScrollView" id="39450128">
|
||||
<reference key="NSNextResponder" ref="973185930"/>
|
||||
<int key="NSvFlags">268</int>
|
||||
<int key="NSvFlags">276</int>
|
||||
<object class="NSMutableArray" key="NSSubviews">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUITableView" id="919897576">
|
||||
|
@ -351,7 +352,8 @@
|
|||
<string key="NSReuseIdentifierKey">_NS:392</string>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC42IDAuNiAwLjYgMC42AA</bytes>
|
||||
<bytes key="NSRGB">MSAxIDEgMC42AA</bytes>
|
||||
<string key="IBUIColorCocoaTouchKeyPath">lightTextColor</string>
|
||||
</object>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
|
@ -5733,10 +5735,10 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>tapCategoryButton:</string>
|
||||
<string>tapGoogleReaderButton</string>
|
||||
<string>tapNewsBlurButton:</string>
|
||||
<string>tapFacebookButton</string>
|
||||
<string>tapNextButton</string>
|
||||
<string>tapTwitterButton</string>
|
||||
<string>toggleAutoFollowFriends:</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -5750,124 +5752,96 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>tapCategoryButton:</string>
|
||||
<string>tapGoogleReaderButton</string>
|
||||
<string>tapNewsBlurButton:</string>
|
||||
<string>tapFacebookButton</string>
|
||||
<string>tapNextButton</string>
|
||||
<string>tapTwitterButton</string>
|
||||
<string>toggleAutoFollowFriends:</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapCategoryButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapGoogleReaderButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapNewsBlurButton:</string>
|
||||
<string key="name">tapFacebookButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapNextButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapTwitterButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">toggleAutoFollowFriends:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="outlets">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>addFriendsView</string>
|
||||
<string>addNewsBlurView</string>
|
||||
<string>addSitesView</string>
|
||||
<string>appDelegate</string>
|
||||
<string>googleReaderButton</string>
|
||||
<string>logo</string>
|
||||
<string>facebookActivityIndicator</string>
|
||||
<string>facebookButton</string>
|
||||
<string>friendsLabel</string>
|
||||
<string>nextButton</string>
|
||||
<string>previousButton</string>
|
||||
<string>toolbar</string>
|
||||
<string>toolbarTitle</string>
|
||||
<string>welcomeView</string>
|
||||
<string>twitterActivityIndicator</string>
|
||||
<string>twitterButton</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>UIView</string>
|
||||
<string>UIView</string>
|
||||
<string>UIView</string>
|
||||
<string>NewsBlurAppDelegate</string>
|
||||
<string>UIActivityIndicatorView</string>
|
||||
<string>UIButton</string>
|
||||
<string>UIImageView</string>
|
||||
<string>UILabel</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIToolbar</string>
|
||||
<string>UIActivityIndicatorView</string>
|
||||
<string>UIButton</string>
|
||||
<string>UIView</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>addFriendsView</string>
|
||||
<string>addNewsBlurView</string>
|
||||
<string>addSitesView</string>
|
||||
<string>appDelegate</string>
|
||||
<string>googleReaderButton</string>
|
||||
<string>logo</string>
|
||||
<string>facebookActivityIndicator</string>
|
||||
<string>facebookButton</string>
|
||||
<string>friendsLabel</string>
|
||||
<string>nextButton</string>
|
||||
<string>previousButton</string>
|
||||
<string>toolbar</string>
|
||||
<string>toolbarTitle</string>
|
||||
<string>welcomeView</string>
|
||||
<string>twitterActivityIndicator</string>
|
||||
<string>twitterButton</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addFriendsView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addNewsBlurView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addSitesView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">appDelegate</string>
|
||||
<string key="candidateClassName">NewsBlurAppDelegate</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">googleReaderButton</string>
|
||||
<string key="name">facebookActivityIndicator</string>
|
||||
<string key="candidateClassName">UIActivityIndicatorView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">facebookButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">logo</string>
|
||||
<string key="candidateClassName">UIImageView</string>
|
||||
<string key="name">friendsLabel</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">nextButton</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">previousButton</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
<string key="name">twitterActivityIndicator</string>
|
||||
<string key="candidateClassName">UIActivityIndicatorView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbar</string>
|
||||
<string key="candidateClassName">UIToolbar</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbarTitle</string>
|
||||
<string key="name">twitterButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">welcomeView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
|
@ -5882,38 +5856,27 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>tapCategoryButton:</string>
|
||||
<string>tapGoogleReaderButton</string>
|
||||
<string>tapNewsBlurButton:</string>
|
||||
<string>tapNextButton</string>
|
||||
<string>tapPopularButton:</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>id</string>
|
||||
<string>id</string>
|
||||
<string>id</string>
|
||||
<string>id</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="actionInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>tapCategoryButton:</string>
|
||||
<string>tapGoogleReaderButton</string>
|
||||
<string>tapNewsBlurButton:</string>
|
||||
<string>tapNextButton</string>
|
||||
<string>tapPopularButton:</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapCategoryButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapGoogleReaderButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapNewsBlurButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
|
@ -5922,101 +5885,49 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="name">tapNextButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapPopularButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="outlets">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>addFriendsView</string>
|
||||
<string>addNewsBlurView</string>
|
||||
<string>addSitesView</string>
|
||||
<string>appDelegate</string>
|
||||
<string>googleReaderButton</string>
|
||||
<string>logo</string>
|
||||
<string>instructionsLabel</string>
|
||||
<string>nextButton</string>
|
||||
<string>previousButton</string>
|
||||
<string>toolbar</string>
|
||||
<string>toolbarTitle</string>
|
||||
<string>welcomeView</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>UIView</string>
|
||||
<string>UIView</string>
|
||||
<string>UIView</string>
|
||||
<string>NewsBlurAppDelegate</string>
|
||||
<string>UIButton</string>
|
||||
<string>UIImageView</string>
|
||||
<string>UILabel</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIToolbar</string>
|
||||
<string>UIButton</string>
|
||||
<string>UIView</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>addFriendsView</string>
|
||||
<string>addNewsBlurView</string>
|
||||
<string>addSitesView</string>
|
||||
<string>appDelegate</string>
|
||||
<string>googleReaderButton</string>
|
||||
<string>logo</string>
|
||||
<string>instructionsLabel</string>
|
||||
<string>nextButton</string>
|
||||
<string>previousButton</string>
|
||||
<string>toolbar</string>
|
||||
<string>toolbarTitle</string>
|
||||
<string>welcomeView</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addFriendsView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addNewsBlurView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addSitesView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">appDelegate</string>
|
||||
<string key="candidateClassName">NewsBlurAppDelegate</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">googleReaderButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">logo</string>
|
||||
<string key="candidateClassName">UIImageView</string>
|
||||
<string key="name">instructionsLabel</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">nextButton</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">previousButton</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbar</string>
|
||||
<string key="candidateClassName">UIToolbar</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbarTitle</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">welcomeView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
|
@ -6028,143 +5939,87 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="className">FirstTimeUserAddSitesViewController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<object class="NSMutableDictionary" key="actions">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>tapCategoryButton:</string>
|
||||
<string>tapGoogleReaderButton</string>
|
||||
<string>tapNewsBlurButton:</string>
|
||||
<string>tapNextButton</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>id</string>
|
||||
<string>id</string>
|
||||
<string>id</string>
|
||||
<string>id</string>
|
||||
</object>
|
||||
<string key="NS.key.0">tapNextButton</string>
|
||||
<string key="NS.object.0">id</string>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="actionInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>tapCategoryButton:</string>
|
||||
<string>tapGoogleReaderButton</string>
|
||||
<string>tapNewsBlurButton:</string>
|
||||
<string>tapNextButton</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapCategoryButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapGoogleReaderButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapNewsBlurButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">tapNextButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<string key="NS.key.0">tapNextButton</string>
|
||||
<object class="IBActionInfo" key="NS.object.0">
|
||||
<string key="name">tapNextButton</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="outlets">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>addFriendsView</string>
|
||||
<string>addNewsBlurView</string>
|
||||
<string>addSitesView</string>
|
||||
<string>activityIndicator</string>
|
||||
<string>appDelegate</string>
|
||||
<string>categoriesTable</string>
|
||||
<string>googleReaderButton</string>
|
||||
<string>logo</string>
|
||||
<string>googleReaderButtonWrapper</string>
|
||||
<string>instructionLabel</string>
|
||||
<string>nextButton</string>
|
||||
<string>previousButton</string>
|
||||
<string>toolbar</string>
|
||||
<string>toolbarTitle</string>
|
||||
<string>welcomeView</string>
|
||||
<string>scrollView</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>UIView</string>
|
||||
<string>UIView</string>
|
||||
<string>UIView</string>
|
||||
<string>UIActivityIndicatorView</string>
|
||||
<string>NewsBlurAppDelegate</string>
|
||||
<string>UIButton</string>
|
||||
<string>UIImageView</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIToolbar</string>
|
||||
<string>UITableView</string>
|
||||
<string>UIButton</string>
|
||||
<string>UIView</string>
|
||||
<string>UILabel</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIScrollView</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>addFriendsView</string>
|
||||
<string>addNewsBlurView</string>
|
||||
<string>addSitesView</string>
|
||||
<string>activityIndicator</string>
|
||||
<string>appDelegate</string>
|
||||
<string>categoriesTable</string>
|
||||
<string>googleReaderButton</string>
|
||||
<string>logo</string>
|
||||
<string>googleReaderButtonWrapper</string>
|
||||
<string>instructionLabel</string>
|
||||
<string>nextButton</string>
|
||||
<string>previousButton</string>
|
||||
<string>toolbar</string>
|
||||
<string>toolbarTitle</string>
|
||||
<string>welcomeView</string>
|
||||
<string>scrollView</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addFriendsView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addNewsBlurView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">addSitesView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
<string key="name">activityIndicator</string>
|
||||
<string key="candidateClassName">UIActivityIndicatorView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">appDelegate</string>
|
||||
<string key="candidateClassName">NewsBlurAppDelegate</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">categoriesTable</string>
|
||||
<string key="candidateClassName">UITableView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">googleReaderButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">logo</string>
|
||||
<string key="candidateClassName">UIImageView</string>
|
||||
<string key="name">googleReaderButtonWrapper</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">instructionLabel</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">nextButton</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">previousButton</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbar</string>
|
||||
<string key="candidateClassName">UIToolbar</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbarTitle</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">welcomeView</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
<string key="name">scrollView</string>
|
||||
<string key="candidateClassName">UIScrollView</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -6192,12 +6047,16 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>appDelegate</string>
|
||||
<string>footer</string>
|
||||
<string>header</string>
|
||||
<string>logo</string>
|
||||
<string>nextButton</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>NewsBlurAppDelegate</string>
|
||||
<string>UILabel</string>
|
||||
<string>UILabel</string>
|
||||
<string>UIImageView</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
</object>
|
||||
|
@ -6207,6 +6066,8 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>appDelegate</string>
|
||||
<string>footer</string>
|
||||
<string>header</string>
|
||||
<string>logo</string>
|
||||
<string>nextButton</string>
|
||||
</object>
|
||||
|
@ -6216,6 +6077,14 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="name">appDelegate</string>
|
||||
<string key="candidateClassName">NewsBlurAppDelegate</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">footer</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">header</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">logo</string>
|
||||
<string key="candidateClassName">UIImageView</string>
|
||||
|
@ -6371,57 +6240,6 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="minorKey">./Classes/FriendsListViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">GoogleReaderViewController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<object class="NSMutableDictionary" key="actions">
|
||||
<string key="NS.key.0">tapCancelButton:</string>
|
||||
<string key="NS.object.0">id</string>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="actionInfosByName">
|
||||
<string key="NS.key.0">tapCancelButton:</string>
|
||||
<object class="IBActionInfo" key="NS.object.0">
|
||||
<string key="name">tapCancelButton:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="outlets">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>appDelegate</string>
|
||||
<string>webView</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>NewsBlurAppDelegate</string>
|
||||
<string>UIWebView</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>appDelegate</string>
|
||||
<string>webView</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">appDelegate</string>
|
||||
<string key="candidateClassName">NewsBlurAppDelegate</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">webView</string>
|
||||
<string key="candidateClassName">UIWebView</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/GoogleReaderViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">InteractionsModule</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
|
@ -6817,7 +6635,6 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string>fontSettingsViewController</string>
|
||||
<string>friendsListViewController</string>
|
||||
<string>ftuxNavigationController</string>
|
||||
<string>googleReaderViewController</string>
|
||||
<string>loginViewController</string>
|
||||
<string>masterContainerViewController</string>
|
||||
<string>moveSiteViewController</string>
|
||||
|
@ -6844,7 +6661,6 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string>FontSettingsViewController</string>
|
||||
<string>FriendsListViewController</string>
|
||||
<string>UINavigationController</string>
|
||||
<string>GoogleReaderViewController</string>
|
||||
<string>LoginViewController</string>
|
||||
<string>NBContainerViewController</string>
|
||||
<string>MoveSiteViewController</string>
|
||||
|
@ -6874,7 +6690,6 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string>fontSettingsViewController</string>
|
||||
<string>friendsListViewController</string>
|
||||
<string>ftuxNavigationController</string>
|
||||
<string>googleReaderViewController</string>
|
||||
<string>loginViewController</string>
|
||||
<string>masterContainerViewController</string>
|
||||
<string>moveSiteViewController</string>
|
||||
|
@ -6943,10 +6758,6 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="name">ftuxNavigationController</string>
|
||||
<string key="candidateClassName">UINavigationController</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">googleReaderViewController</string>
|
||||
<string key="candidateClassName">GoogleReaderViewController</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">loginViewController</string>
|
||||
<string key="candidateClassName">LoginViewController</string>
|
||||
|
@ -7057,6 +6868,8 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string>homeButton</string>
|
||||
<string>innerView</string>
|
||||
<string>intelligenceControl</string>
|
||||
<string>noFocusMessage</string>
|
||||
<string>toolbarLeftMargin</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -7067,6 +6880,8 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string>UIBarButtonItem</string>
|
||||
<string>UIView</string>
|
||||
<string>UISegmentedControl</string>
|
||||
<string>UIView</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
|
@ -7080,6 +6895,8 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string>homeButton</string>
|
||||
<string>innerView</string>
|
||||
<string>intelligenceControl</string>
|
||||
<string>noFocusMessage</string>
|
||||
<string>toolbarLeftMargin</string>
|
||||
</object>
|
||||
<object class="NSArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -7111,6 +6928,14 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="name">intelligenceControl</string>
|
||||
<string key="candidateClassName">UISegmentedControl</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">noFocusMessage</string>
|
||||
<string key="candidateClassName">UIView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbarLeftMargin</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
|
@ -7579,7 +7404,7 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
|
||||
<real value="1296" key="NS.object.0"/>
|
||||
<real value="1536" key="NS.object.0"/>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
|
||||
|
@ -7591,6 +7416,6 @@ AAgAAAAIAAIACAACAAAAAgAAAAEAAQABAAE</bytes>
|
|||
<string key="NS.key.0">Background.png</string>
|
||||
<string key="NS.object.0">{320, 480}</string>
|
||||
</object>
|
||||
<string key="IBCocoaTouchPluginVersion">1181</string>
|
||||
<string key="IBCocoaTouchPluginVersion">1926</string>
|
||||
</data>
|
||||
</archive>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1536</int>
|
||||
<string key="IBDocument.SystemVersion">12B19</string>
|
||||
<string key="IBDocument.SystemVersion">12C54</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">2840</string>
|
||||
<string key="IBDocument.AppKitVersion">1187</string>
|
||||
<string key="IBDocument.HIToolboxVersion">624.00</string>
|
||||
<string key="IBDocument.AppKitVersion">1187.34</string>
|
||||
<string key="IBDocument.HIToolboxVersion">625.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">1926</string>
|
||||
|
@ -51,10 +51,6 @@
|
|||
<int key="IBUIInterfaceOrientation">1</int>
|
||||
<int key="interfaceOrientation">1</int>
|
||||
</object>
|
||||
<object class="IBUISimulatedSizeMetrics" key="IBUISimulatedDestinationMetrics" id="327432476">
|
||||
<string key="IBUISimulatedSizeMetricsClass">IBUISimulatedFreeformSizeMetricsSentinel</string>
|
||||
<string key="IBUIDisplayName">Freeform</string>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIHorizontal">NO</bool>
|
||||
</object>
|
||||
|
@ -214,7 +210,7 @@
|
|||
<object class="IBUIWindow" id="117978783">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">256</int>
|
||||
<string key="NSFrameSize">{320, 568}</string>
|
||||
<string key="NSFrameSize">{320, 480}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
|
@ -224,8 +220,8 @@
|
|||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
<reference key="IBUISimulatedDestinationMetrics" ref="327432476"/>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIResizesToFullScreen">YES</bool>
|
||||
</object>
|
||||
<object class="IBUINavigationController" id="1024563784">
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
|
@ -248,7 +244,6 @@
|
|||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIViewController" id="121528350">
|
||||
<object class="IBUINavigationItem" key="IBUINavigationItem" id="451803536">
|
||||
<reference key="IBUINavigationBar"/>
|
||||
<string key="IBUITitle">Title</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
|
|
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 832 B |
BIN
media/ios/Resources/disclosure_border.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
|
@ -34,25 +34,30 @@ NEWSBLUR.Router = Backbone.Router.extend({
|
|||
site_id = parseInt(site_id, 10);
|
||||
var feed = NEWSBLUR.assets.get_feed(site_id);
|
||||
if (feed) {
|
||||
NEWSBLUR.reader.open_feed(site_id, {force: true});
|
||||
NEWSBLUR.reader.open_feed(site_id, {router: true, force: true});
|
||||
} else {
|
||||
NEWSBLUR.reader.load_feed_in_tryfeed_view(site_id, {force: true, feed: {
|
||||
feed_title: _.string.humanize(slug || "")
|
||||
}});
|
||||
NEWSBLUR.reader.load_feed_in_tryfeed_view(site_id, {
|
||||
router: true,
|
||||
force: true,
|
||||
feed: {
|
||||
feed_title: _.string.humanize(slug || "")
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
folder: function(folder_name) {
|
||||
folder_name = folder_name.replace(/-/g, ' ');
|
||||
// NEWSBLUR.log(["folder", folder_name]);
|
||||
var options = {router: true};
|
||||
if (folder_name == "everything") {
|
||||
NEWSBLUR.reader.open_river_stories();
|
||||
NEWSBLUR.reader.open_river_stories(null, null, options);
|
||||
} else if (folder_name == "blurblogs") {
|
||||
NEWSBLUR.reader.open_river_blurblogs_stories();
|
||||
NEWSBLUR.reader.open_river_blurblogs_stories(options);
|
||||
} else {
|
||||
var folder = NEWSBLUR.assets.get_folder(folder_name);
|
||||
if (folder) {
|
||||
NEWSBLUR.reader.open_river_stories(folder.folder_view.$el, folder);
|
||||
NEWSBLUR.reader.open_river_stories(folder.folder_view.$el, folder, options);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -61,14 +66,18 @@ NEWSBLUR.Router = Backbone.Router.extend({
|
|||
// NEWSBLUR.log(["router:social", user_id, slug]);
|
||||
var feed_id = "social:" + user_id;
|
||||
if (NEWSBLUR.assets.get_feed(feed_id)) {
|
||||
NEWSBLUR.reader.open_social_stories(feed_id, {force: true});
|
||||
NEWSBLUR.reader.open_social_stories(feed_id, {router: true, force: true});
|
||||
} else {
|
||||
NEWSBLUR.reader.load_social_feed_in_tryfeed_view(feed_id, {force: true, feed: {
|
||||
username: _.string.humanize(slug),
|
||||
id: feed_id,
|
||||
user_id: parseInt(user_id, 10),
|
||||
feed_title: _.string.humanize(slug)
|
||||
}});
|
||||
NEWSBLUR.reader.load_social_feed_in_tryfeed_view(feed_id, {
|
||||
router: true,
|
||||
force: true,
|
||||
feed: {
|
||||
username: _.string.humanize(slug),
|
||||
id: feed_id,
|
||||
user_id: parseInt(user_id, 10),
|
||||
feed_title: _.string.humanize(slug)
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -5,9 +5,14 @@ NEWSBLUR.Models.SocialSubscription = Backbone.Model.extend({
|
|||
this.set('page_url', '/social/page/' + this.get('user_id'));
|
||||
}
|
||||
|
||||
_.bindAll(this, 'on_change', 'on_remove');
|
||||
_.bindAll(this, 'on_change', 'on_remove', 'update_counts');
|
||||
// this.bind('change', this.on_change);
|
||||
this.bind('remove', this.on_remove);
|
||||
|
||||
this.bind('change:ps', this.update_counts);
|
||||
this.bind('change:nt', this.update_counts);
|
||||
this.bind('change:ng', this.update_counts);
|
||||
|
||||
this.views = [];
|
||||
},
|
||||
|
||||
|
@ -19,6 +24,10 @@ NEWSBLUR.Models.SocialSubscription = Backbone.Model.extend({
|
|||
NEWSBLUR.log(["Remove Feed", this, this.views]);
|
||||
_.each(this.views, function(view) { view.remove(); });
|
||||
},
|
||||
|
||||
update_counts: function() {
|
||||
NEWSBLUR.assets.social_feeds.trigger('change:counts');
|
||||
},
|
||||
|
||||
is_social: function() {
|
||||
return true;
|
||||
|
@ -79,6 +88,22 @@ NEWSBLUR.Collections.SocialSubscriptions = Backbone.Collection.extend({
|
|||
}).each(function(feed){
|
||||
feed.set('selected', false);
|
||||
});
|
||||
},
|
||||
|
||||
unread_counts: function() {
|
||||
var counts = this.reduce(function(counts, item) {
|
||||
var feed_counts = item.unread_counts();
|
||||
counts['ps'] += feed_counts['ps'];
|
||||
counts['nt'] += feed_counts['nt'];
|
||||
counts['ng'] += feed_counts['ng'];
|
||||
return counts;
|
||||
}, {
|
||||
ps: 0,
|
||||
nt: 0,
|
||||
ng: 0
|
||||
});
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
});
|
|
@ -32,10 +32,8 @@ NEWSBLUR.Models.Story = Backbone.Model.extend({
|
|||
},
|
||||
|
||||
has_modifications: function() {
|
||||
if (this.get('story_content').indexOf('<ins') != -1) {
|
||||
return true;
|
||||
} else if (NEWSBLUR.assets.preference('hide_story_changes') &&
|
||||
this.get('story_content').indexOf('<del') != -1) {
|
||||
if (this.get('story_content').indexOf('<ins') != -1 ||
|
||||
this.get('story_content').indexOf('<del') != -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -72,9 +70,9 @@ NEWSBLUR.Collections.Stories = Backbone.Collection.extend({
|
|||
// = Actions =
|
||||
// ===========
|
||||
|
||||
deselect: function(selected_story) {
|
||||
deselect_other_stories: function(selected_story) {
|
||||
this.any(function(story) {
|
||||
if (story.get('selected') && story != selected_story) {
|
||||
if (story.get('selected') && story.id != selected_story.id) {
|
||||
story.set('selected', false);
|
||||
return true;
|
||||
}
|
||||
|
@ -140,27 +138,27 @@ NEWSBLUR.Collections.Stories = Backbone.Collection.extend({
|
|||
|
||||
if (story.score() > 0) {
|
||||
var active_count = Math.max(active_feed.get('ps') + (options.unread?1:-1), 0);
|
||||
var story_count = Math.max(story_feed.get('ps') + (options.unread?1:-1), 0);
|
||||
var story_count = story_feed && Math.max(story_feed.get('ps') + (options.unread?1:-1), 0);
|
||||
active_feed.set('ps', active_count, {instant: true});
|
||||
story_feed.set('ps', story_count, {instant: true});
|
||||
if (story_feed) story_feed.set('ps', story_count, {instant: true});
|
||||
_.each(friend_feeds, function(socialsub) {
|
||||
var socialsub_count = Math.max(socialsub.get('ps') + (options.unread?1:-1), 0);
|
||||
socialsub.set('ps', socialsub_count, {instant: true});
|
||||
});
|
||||
} else if (story.score() == 0) {
|
||||
var active_count = Math.max(active_feed.get('nt') + (options.unread?1:-1), 0);
|
||||
var story_count = Math.max(story_feed.get('nt') + (options.unread?1:-1), 0);
|
||||
var story_count = story_feed && Math.max(story_feed.get('nt') + (options.unread?1:-1), 0);
|
||||
active_feed.set('nt', active_count, {instant: true});
|
||||
story_feed.set('nt', story_count, {instant: true});
|
||||
if (story_feed) story_feed.set('nt', story_count, {instant: true});
|
||||
_.each(friend_feeds, function(socialsub) {
|
||||
var socialsub_count = Math.max(socialsub.get('nt') + (options.unread?1:-1), 0);
|
||||
socialsub.set('nt', socialsub_count, {instant: true});
|
||||
});
|
||||
} else if (story.score() < 0) {
|
||||
var active_count = Math.max(active_feed.get('ng') + (options.unread?1:-1), 0);
|
||||
var story_count = Math.max(story_feed.get('ng') + (options.unread?1:-1), 0);
|
||||
var story_count = story_feed && Math.max(story_feed.get('ng') + (options.unread?1:-1), 0);
|
||||
active_feed.set('ng', active_count, {instant: true});
|
||||
story_feed.set('ng', story_count, {instant: true});
|
||||
if (story_feed) story_feed.set('ng', story_count, {instant: true});
|
||||
_.each(friend_feeds, function(socialsub) {
|
||||
var socialsub_count = Math.max(socialsub.get('ng') + (options.unread?1:-1), 0);
|
||||
socialsub.set('ng', socialsub_count, {instant: true});
|
||||
|
@ -304,7 +302,7 @@ NEWSBLUR.Collections.Stories = Backbone.Collection.extend({
|
|||
|
||||
detect_selected_story: function(selected_story, selected) {
|
||||
if (selected) {
|
||||
this.deselect(selected_story);
|
||||
this.deselect_other_stories(selected_story);
|
||||
this.active_story = selected_story;
|
||||
NEWSBLUR.reader.active_story = selected_story;
|
||||
this.previous_stories_stack.push(selected_story);
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
NEWSBLUR.Reader = Backbone.Router.extend({
|
||||
|
||||
init: function() {
|
||||
init: function(options) {
|
||||
|
||||
var defaults = {};
|
||||
|
||||
// ===========
|
||||
// = Globals =
|
||||
|
@ -11,11 +13,14 @@
|
|||
NEWSBLUR.assets = new NEWSBLUR.AssetModel();
|
||||
this.model = NEWSBLUR.assets;
|
||||
this.story_view = 'page';
|
||||
this.options = _.extend({}, defaults, options);
|
||||
this.$s = {
|
||||
$body: $('body'),
|
||||
$layout: $('.NB-layout'),
|
||||
$sidebar: $('.NB-sidebar'),
|
||||
$feed_lists: $('.NB-feedlists'),
|
||||
$feed_list: $('#feed_list'),
|
||||
$social_feeds: $('.NB-socialfeeds'),
|
||||
$social_feeds: $('.NB-socialfeeds-folder'),
|
||||
$story_titles: $('#story_titles'),
|
||||
$content_pane: $('.content-pane'),
|
||||
$story_taskbar: $('#story_taskbar'),
|
||||
|
@ -41,7 +46,8 @@
|
|||
'bouncing_callout': false,
|
||||
'has_unfetched_feeds': false,
|
||||
'count_unreads_after_import_working': false,
|
||||
'import_from_google_reader_working': false
|
||||
'import_from_google_reader_working': false,
|
||||
'sidebar_closed': this.options.hide_sidebar
|
||||
};
|
||||
this.locks = {};
|
||||
this.counts = {
|
||||
|
@ -99,12 +105,14 @@
|
|||
if (NEWSBLUR.Flags['start_import_from_google_reader']) {
|
||||
this.start_import_from_google_reader();
|
||||
}
|
||||
NEWSBLUR.app.feed_list_header = new NEWSBLUR.Views.FeedListHeader({collection: NEWSBLUR.assets.feeds});
|
||||
NEWSBLUR.app.sidebar_header = new NEWSBLUR.Views.SidebarHeader({collection: NEWSBLUR.assets.feeds});
|
||||
NEWSBLUR.app.sidebar = new NEWSBLUR.Views.Sidebar();
|
||||
NEWSBLUR.app.feed_list = new NEWSBLUR.Views.FeedList({el: this.$s.$feed_list[0]});
|
||||
NEWSBLUR.app.story_titles = new NEWSBLUR.Views.StoryTitlesView({collection: NEWSBLUR.assets.stories});
|
||||
NEWSBLUR.app.story_list = new NEWSBLUR.Views.StoryListView({collection: NEWSBLUR.assets.stories});
|
||||
NEWSBLUR.app.original_tab_view = new NEWSBLUR.Views.OriginalTabView({collection: NEWSBLUR.assets.stories});
|
||||
NEWSBLUR.app.story_tab_view = new NEWSBLUR.Views.StoryTabView({collection: NEWSBLUR.assets.stories});
|
||||
NEWSBLUR.app.feed_selector = new NEWSBLUR.Views.FeedSelector();
|
||||
|
||||
this.load_intelligence_slider();
|
||||
this.handle_mouse_indicator_hover();
|
||||
|
@ -197,17 +205,17 @@
|
|||
.removeClass('NB-story-pane-south')
|
||||
.addClass('NB-story-pane-'+story_anchor);
|
||||
|
||||
this.layout.outerLayout = this.$s.$body.layout({
|
||||
closable: true,
|
||||
zIndex: 1,
|
||||
fxName: "slide",
|
||||
this.layout.outerLayout = this.$s.$layout.layout({
|
||||
zIndex: 2,
|
||||
fxName: "slideOffscreen",
|
||||
fxSettings: { duration: 560, easing: "easeInOutQuint" },
|
||||
center__paneSelector: ".right-pane",
|
||||
west__paneSelector: ".left-pane",
|
||||
west__size: this.model.preference('feed_pane_size'),
|
||||
west__minSize: this.constants.MIN_FEED_LIST_SIZE,
|
||||
west__onresize_end: $.rescope(this.save_feed_pane_size, this),
|
||||
spacing_open: 4,
|
||||
// west__initHidden: this.options.hide_sidebar,
|
||||
west__spacing_open: this.options.hide_sidebar ? 1 : 6,
|
||||
resizerDragOpacity: 0.6,
|
||||
resizeWhileDragging: true,
|
||||
enableCursorHotkey: false
|
||||
|
@ -220,8 +228,9 @@
|
|||
this.layout.leftLayout = $('.left-pane').layout({
|
||||
closable: false,
|
||||
resizeWhileDragging: true,
|
||||
fxName: "slide",
|
||||
fxName: "slideOffscreen",
|
||||
fxSettings: { duration: 560, easing: "easeInOutQuint" },
|
||||
animatePaneSizing: true,
|
||||
north__paneSelector: ".left-north",
|
||||
north__size: 18,
|
||||
north__resizeable: false,
|
||||
|
@ -249,7 +258,7 @@
|
|||
south__spacing_closed: 0,
|
||||
south__closable: true,
|
||||
south__initClosed: true,
|
||||
fxName: "slide",
|
||||
fxName: "slideOffscreen",
|
||||
fxSettings: { duration: 560, easing: "easeInOutQuint" },
|
||||
enableCursorHotkey: false
|
||||
});
|
||||
|
@ -260,7 +269,7 @@
|
|||
spacing_open: story_anchor == 'west' ? 4 : 10,
|
||||
resizerDragOpacity: 0.6,
|
||||
enableCursorHotkey: false,
|
||||
fxName: "slide",
|
||||
fxName: "slideOffscreen",
|
||||
fxSettings: { duration: 560, easing: "easeInOutQuint" }
|
||||
};
|
||||
rightLayoutOptions[story_anchor+'__paneSelector'] = '.right-north';
|
||||
|
@ -385,13 +394,13 @@
|
|||
resize = true;
|
||||
}
|
||||
$('.right-pane').show();
|
||||
$('#NB-splash').hide();
|
||||
$('#NB-splash,.NB-splash').hide();
|
||||
$('.NB-splash-info').hide();
|
||||
$('#NB-splash-overlay').hide();
|
||||
this.$s.$dashboard.addClass('NB-active');
|
||||
|
||||
if (resize) {
|
||||
this.$s.$body.layout().resizeAll();
|
||||
this.$s.$layout.layout().resizeAll();
|
||||
}
|
||||
if (NEWSBLUR.Globals.is_anonymous) {
|
||||
this.setup_ftux_signup_callout();
|
||||
|
@ -400,11 +409,9 @@
|
|||
|
||||
show_splash_page: function(skip_router) {
|
||||
this.reset_feed();
|
||||
NEWSBLUR.app.original_tab_view.unload_feed_iframe();
|
||||
NEWSBLUR.app.story_tab_view.unload_story_iframe();
|
||||
$('.right-pane').hide();
|
||||
$('.NB-splash-info').show();
|
||||
$('#NB-splash').show();
|
||||
$('#NB-splash,.NB-splash').show();
|
||||
$('#NB-splash-overlay').show();
|
||||
this.$s.$dashboard.removeClass('NB-active');
|
||||
if (!skip_router) {
|
||||
|
@ -489,7 +496,6 @@
|
|||
|
||||
if (unread_count) {
|
||||
var next_story = NEWSBLUR.assets.stories.get_next_unread_story();
|
||||
|
||||
if (next_story) {
|
||||
this.counts['find_next_unread_on_page_of_feed_stories_load'] = 0;
|
||||
next_story.set('selected', true);
|
||||
|
@ -584,7 +590,7 @@
|
|||
return this.show_next_folder(direction, $current_feed);
|
||||
}
|
||||
|
||||
var $next_feed = this.get_next_feed(direction, $current_feed);
|
||||
var $next_feed = this.get_next_feed(direction, $current_feed, {include_selected: true});
|
||||
|
||||
var next_feed_id = $next_feed.data('id');
|
||||
if (next_feed_id && next_feed_id == this.active_feed) {
|
||||
|
@ -604,15 +610,19 @@
|
|||
this.open_river_stories($next_folder, folder && folder.model);
|
||||
},
|
||||
|
||||
get_next_feed: function(direction, $current_feed) {
|
||||
get_next_feed: function(direction, $current_feed, options) {
|
||||
options = options || {};
|
||||
var self = this;
|
||||
var $feed_list = this.$s.$feed_list.add(this.$s.$social_feeds);
|
||||
var $current_feed = $current_feed || $('.selected', $feed_list);
|
||||
var $next_feed,
|
||||
scroll;
|
||||
var $feeds = $('.feed:visible:not(.NB-empty)', $feed_list).add('.NB-feedlists .feed.NB-selected');
|
||||
var $feeds = $('.feed:visible:not(.NB-empty)', $feed_list);
|
||||
if (!$current_feed.length) {
|
||||
$current_feed = $('.feed:visible:not(.NB-empty)', $feed_list)[direction==1?'first':'last']();
|
||||
if (options.include_selected) {
|
||||
$feeds = $feeds.add('.NB-feedlists .feed.NB-selected');
|
||||
}
|
||||
$current_feed = $('.feed:visible:not(.NB-empty)', $feed_list)[direction==-1?'last':'first']();
|
||||
$next_feed = $current_feed;
|
||||
} else {
|
||||
var current_feed = 0;
|
||||
|
@ -746,9 +756,7 @@
|
|||
find_story_with_action_preference_on_open_feed: function() {
|
||||
var open_feed_action = this.model.preference('open_feed_action');
|
||||
|
||||
if (this.counts['page'] != 1) return;
|
||||
|
||||
if (open_feed_action == 'newest') {
|
||||
if (!this.active_story && open_feed_action == 'newest') {
|
||||
this.show_next_unread_story();
|
||||
}
|
||||
},
|
||||
|
@ -965,7 +973,9 @@
|
|||
// = Feed bar - Individual Feeds =
|
||||
// ===============================
|
||||
|
||||
reset_feed: function() {
|
||||
reset_feed: function(options) {
|
||||
options = options || {};
|
||||
|
||||
$.extend(this.flags, {
|
||||
'scrolling_by_selecting_story_title': false,
|
||||
'page_view_showing_feed_view': false,
|
||||
|
@ -1025,12 +1035,22 @@
|
|||
if (this.flags['showing_feed_in_tryfeed_view'] || this.flags['showing_social_feed_in_tryfeed_view']) {
|
||||
this.hide_tryfeed_view();
|
||||
}
|
||||
if (NEWSBLUR.Globals.is_anonymous) {
|
||||
if (options.router) {
|
||||
this.$s.$layout.layout().show('west', true);
|
||||
this.$s.$layout.show();
|
||||
}
|
||||
this.hide_tryout_signup_button();
|
||||
}
|
||||
|
||||
this.active_folder = null;
|
||||
this.active_feed = null;
|
||||
this.active_story = null;
|
||||
|
||||
NEWSBLUR.assets.stories.reset();
|
||||
NEWSBLUR.app.feed_selector.hide_feed_selector();
|
||||
NEWSBLUR.app.original_tab_view.unload_feed_iframe();
|
||||
NEWSBLUR.app.story_tab_view.unload_story_iframe();
|
||||
},
|
||||
|
||||
open_feed: function(feed_id, options) {
|
||||
|
@ -1049,7 +1069,7 @@
|
|||
this.flags['opening_feed'] = true;
|
||||
|
||||
if (options.try_feed || feed) {
|
||||
this.reset_feed();
|
||||
this.reset_feed(options);
|
||||
this.hide_splash_page();
|
||||
if (options.story_id) {
|
||||
this.flags['select_story_in_feed'] = options.story_id;
|
||||
|
@ -1086,6 +1106,7 @@
|
|||
}, this), options.delay || 0);
|
||||
} else {
|
||||
NEWSBLUR.app.original_tab_view.unload_feed_iframe();
|
||||
NEWSBLUR.app.story_tab_view.unload_story_iframe();
|
||||
this.flags['iframe_prevented_from_loading'] = true;
|
||||
}
|
||||
this.setup_mousemove_on_views();
|
||||
|
@ -1115,9 +1136,7 @@
|
|||
this.active_feed = data.feed_id;
|
||||
}
|
||||
|
||||
// NEWSBLUR.log(['post_open_feed', data.stories, this.flags]);
|
||||
this.flags['opening_feed'] = false;
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
NEWSBLUR.app.story_titles_header.show_feed_hidden_story_title_indicator(true);
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
if (this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
|
@ -1129,15 +1148,20 @@
|
|||
}
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
if (first_load) {
|
||||
this.make_story_titles_pane_counter();
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
|
||||
if (this.story_view == 'story' &&
|
||||
!this.active_story &&
|
||||
!this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
this.show_next_story(1);
|
||||
}
|
||||
|
||||
this.make_story_titles_pane_counter();
|
||||
}
|
||||
|
||||
this.hide_stories_progress_bar();
|
||||
if (this.flags['showing_feed_in_tryfeed_view']) {
|
||||
if (NEWSBLUR.Globals.is_anonymous) {
|
||||
this.show_tryout_signup_button();
|
||||
} else if (this.flags['showing_feed_in_tryfeed_view']) {
|
||||
this.show_tryfeed_add_button();
|
||||
this.correct_tryfeed_title();
|
||||
}
|
||||
|
@ -1258,10 +1282,12 @@
|
|||
if (this.active_feed == 'starred') {
|
||||
// NEWSBLUR.log(['post_open_starred_stories', data.stories.length, first_load]);
|
||||
this.flags['opening_feed'] = false;
|
||||
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();
|
||||
}
|
||||
if (first_load) {
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
}
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
}
|
||||
|
@ -1279,7 +1305,7 @@
|
|||
this.active_folder && this.active_folder.folder_view;
|
||||
var folder_title = folder && folder.get('folder_title') || "Everything";
|
||||
|
||||
this.reset_feed();
|
||||
this.reset_feed(options);
|
||||
this.hide_splash_page();
|
||||
this.active_folder = folder || new Backbone.Model({
|
||||
folder_title: folder_title,
|
||||
|
@ -1341,7 +1367,6 @@
|
|||
}
|
||||
this.flags['opening_feed'] = false;
|
||||
NEWSBLUR.app.story_titles_header.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});
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
if (this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
|
@ -1351,8 +1376,13 @@
|
|||
} else if (this.counts['select_story_in_feed'] || this.flags['select_story_in_feed']) {
|
||||
this.select_story_in_feed();
|
||||
}
|
||||
this.hide_stories_progress_bar();
|
||||
if (first_load) {
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
}
|
||||
this.hide_stories_progress_bar();
|
||||
if (NEWSBLUR.Globals.is_anonymous) {
|
||||
this.show_tryout_signup_button();
|
||||
} else if (first_load) {
|
||||
this.make_story_titles_pane_counter();
|
||||
}
|
||||
}
|
||||
|
@ -1396,7 +1426,7 @@
|
|||
var $story_titles = this.$s.$story_titles;
|
||||
var folder_title = "Blurblogs";
|
||||
|
||||
this.reset_feed();
|
||||
this.reset_feed(options);
|
||||
this.hide_splash_page();
|
||||
|
||||
this.active_folder = new Backbone.Model({
|
||||
|
@ -1454,7 +1484,6 @@
|
|||
}
|
||||
this.flags['opening_feed'] = false;
|
||||
NEWSBLUR.app.story_titles_header.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});
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
if (this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
|
@ -1464,7 +1493,13 @@
|
|||
} else if (this.counts['select_story_in_feed'] || this.flags['select_story_in_feed']) {
|
||||
this.select_story_in_feed();
|
||||
}
|
||||
if (first_load) {
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
}
|
||||
this.hide_stories_progress_bar();
|
||||
if (NEWSBLUR.Globals.is_anonymous) {
|
||||
this.show_tryout_signup_button();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1490,7 +1525,7 @@
|
|||
return this.load_social_feed_in_tryfeed_view(socialsub, options);
|
||||
}
|
||||
|
||||
this.reset_feed();
|
||||
this.reset_feed(options);
|
||||
this.hide_splash_page();
|
||||
|
||||
this.active_feed = feed.id;
|
||||
|
@ -1553,7 +1588,6 @@
|
|||
|
||||
if (this.active_feed && NEWSBLUR.utils.is_feed_social(this.active_feed)) {
|
||||
this.flags['opening_feed'] = false;
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
NEWSBLUR.app.story_titles_header.show_feed_hidden_story_title_indicator(true);
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
|
@ -1564,9 +1598,13 @@
|
|||
} else if (this.counts['find_last_unread_on_page_of_feed_stories_load']) {
|
||||
this.show_last_unread_story(true);
|
||||
}
|
||||
if (first_load) {
|
||||
this.find_story_with_action_preference_on_open_feed();
|
||||
}
|
||||
this.hide_stories_progress_bar();
|
||||
|
||||
if (this.flags['showing_social_feed_in_tryfeed_view']) {
|
||||
if (NEWSBLUR.Globals.is_anonymous) {
|
||||
this.show_tryout_signup_button();
|
||||
} else if (this.flags['showing_social_feed_in_tryfeed_view']) {
|
||||
this.show_tryfeed_follow_button();
|
||||
this.correct_tryfeed_title();
|
||||
}
|
||||
|
@ -1711,6 +1749,17 @@
|
|||
}
|
||||
},
|
||||
|
||||
mark_active_story_read: function() {
|
||||
if (!this.active_story) return;
|
||||
var story_id = this.active_story.id;
|
||||
var story = this.model.get_story(story_id);
|
||||
if (this.active_story && !this.active_story.get('read_status')) {
|
||||
NEWSBLUR.assets.stories.mark_read(story, {skip_delay: true});
|
||||
} else if (this.active_story && this.active_story.get('read_status')) {
|
||||
NEWSBLUR.assets.stories.mark_unread(story);
|
||||
}
|
||||
},
|
||||
|
||||
mark_feed_as_read: function(feed_id) {
|
||||
feed_id = feed_id || this.active_feed;
|
||||
|
||||
|
@ -1753,14 +1802,16 @@
|
|||
|
||||
open_story_trainer: function(story_id, feed_id, options) {
|
||||
options = options || {};
|
||||
console.log(["open_story_trainer", story_id, feed_id, options]);
|
||||
story_id = story_id || this.active_story && this.active_story.id;
|
||||
feed_id = feed_id || (story_id && this.model.get_story(story_id).get('story_feed_id'));
|
||||
// console.log(["open_story_trainer", story_id, feed_id, options]);
|
||||
|
||||
if (story_id && feed_id) {
|
||||
options['feed_loaded'] = !this.flags['river_view'];
|
||||
if (this.flags['social_view']) {
|
||||
if (this.flags['social_view'] && !_.string.contains(this.active_feed, 'river:')) {
|
||||
options['social_feed_id'] = this.active_feed;
|
||||
} else if (this.flags['social_view'] && this.active_story.get('friend_user_ids')) {
|
||||
options['social_feed_id'] = 'social:' + this.active_story.get('friend_user_ids')[0];
|
||||
}
|
||||
NEWSBLUR.classifier = new NEWSBLUR.ReaderClassifierStory(story_id, feed_id, options);
|
||||
}
|
||||
|
@ -2347,8 +2398,18 @@
|
|||
}
|
||||
},
|
||||
|
||||
toggle_sidebar: function() {
|
||||
if (this.flags['sidebar_closed']) {
|
||||
this.open_sidebar();
|
||||
return true;
|
||||
} else {
|
||||
this.close_sidebar();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
close_sidebar: function() {
|
||||
this.$s.$body.layout().close('west');
|
||||
this.$s.$layout.layout().hide('west');
|
||||
this.resize_window();
|
||||
this.flags['sidebar_closed'] = true;
|
||||
$('.NB-taskbar-sidebar-toggle-open').stop().animate({
|
||||
|
@ -2361,7 +2422,7 @@
|
|||
},
|
||||
|
||||
open_sidebar: function() {
|
||||
this.$s.$body.layout().open('west');
|
||||
this.$s.$layout.layout().open('west');
|
||||
this.resize_window();
|
||||
this.flags['sidebar_closed'] = false;
|
||||
$('.NB-taskbar-sidebar-toggle-open').stop().css({
|
||||
|
@ -3020,7 +3081,6 @@
|
|||
this.flags['feed_list_showing_manage_menu'] = false;
|
||||
$(document).unbind('click.menu');
|
||||
$(document).unbind('mouseup.menu');
|
||||
$manage_menu_container.uncorner();
|
||||
if (this.model.preference('show_tooltips')) {
|
||||
$('.NB-task-manage').tipsy('enable');
|
||||
}
|
||||
|
@ -3403,7 +3463,7 @@
|
|||
NEWSBLUR.app.story_titles_header.show_feed_hidden_story_title_indicator(true);
|
||||
}
|
||||
this.show_story_titles_above_intelligence_level({'animate': true, 'follow': true});
|
||||
NEWSBLUR.app.feed_list_header.toggle_hide_read_preference();
|
||||
NEWSBLUR.app.sidebar_header.toggle_hide_read_preference();
|
||||
NEWSBLUR.app.feed_list.scroll_to_show_selected_feed();
|
||||
NEWSBLUR.app.feed_list.scroll_to_show_selected_folder();
|
||||
|
||||
|
@ -3424,20 +3484,15 @@
|
|||
|
||||
switch_feed_view_unread_view: function(unread_view) {
|
||||
if (!_.isNumber(unread_view)) unread_view = this.get_unread_view_score();
|
||||
var $feed_list = this.$s.$feed_list;
|
||||
var $social_feeds = this.$s.$social_feeds;
|
||||
var $sidebar = this.$s.$sidebar;
|
||||
var unread_view_name = this.get_unread_view_name(unread_view);
|
||||
var $next_story_button = $('.task_story_next_unread');
|
||||
var $story_title_indicator = $('.NB-story-title-indicator', this.$story_titles);
|
||||
|
||||
$feed_list.removeClass('unread_view_positive')
|
||||
.removeClass('unread_view_neutral')
|
||||
.removeClass('unread_view_negative')
|
||||
.addClass('unread_view_'+unread_view_name);
|
||||
$social_feeds.removeClass('unread_view_positive')
|
||||
.removeClass('unread_view_neutral')
|
||||
.removeClass('unread_view_negative')
|
||||
.addClass('unread_view_'+unread_view_name);
|
||||
$sidebar.removeClass('unread_view_positive')
|
||||
.removeClass('unread_view_neutral')
|
||||
.removeClass('unread_view_negative')
|
||||
.addClass('unread_view_'+unread_view_name);
|
||||
|
||||
$next_story_button.removeClass('task_story_next_positive')
|
||||
.removeClass('task_story_next_neutral')
|
||||
|
@ -4224,7 +4279,7 @@
|
|||
}, options.feed && options.feed.attributes);
|
||||
var $tryfeed_container = this.$s.$tryfeed_header.closest('.NB-feeds-header-container');
|
||||
|
||||
this.reset_feed();
|
||||
this.reset_feed(options);
|
||||
feed = this.model.set_feed(feed_id, feed);
|
||||
|
||||
$('.NB-feeds-header-title', this.$s.$tryfeed_header).text(feed.get('feed_title'));
|
||||
|
@ -4276,7 +4331,6 @@
|
|||
},
|
||||
|
||||
show_tryfeed_add_button: function() {
|
||||
NEWSBLUR.log(["show_tryfeed_add_button", this.$s.$story_taskbar.find('.NB-tryfeed-add:visible').length]);
|
||||
if (this.$s.$story_taskbar.find('.NB-tryfeed-add:visible').length) return;
|
||||
|
||||
var $add = $.make('div', { className: 'NB-modal-submit' }, [
|
||||
|
@ -4302,6 +4356,20 @@
|
|||
$add.animate({'opacity': 1}, {'duration': 600});
|
||||
},
|
||||
|
||||
show_tryout_signup_button: function() {
|
||||
if (this.$s.$story_taskbar.find('.NB-tryout-signup:visible').length) return;
|
||||
|
||||
var $add = $.make('div', { className: 'NB-modal-submit' }, [
|
||||
$.make('div', { className: 'NB-tryout-signup NB-modal-submit-green NB-modal-submit-button' }, 'Sign Up')
|
||||
]).css({'opacity': 0});
|
||||
this.$s.$story_taskbar.find('.NB-taskbar').append($add);
|
||||
$add.animate({'opacity': 1}, {'duration': 600});
|
||||
},
|
||||
|
||||
hide_tryout_signup_button: function() {
|
||||
this.$s.$story_taskbar.find('.NB-tryout-signup:visible').remove();
|
||||
},
|
||||
|
||||
add_recommended_feed: function(feed_id) {
|
||||
feed_id = feed_id || this.active_feed;
|
||||
var feed_address = this.model.get_feed(feed_id).get('feed_address');
|
||||
|
@ -4444,25 +4512,7 @@
|
|||
var self = this;
|
||||
var stopPropagation = false;
|
||||
|
||||
// NEWSBLUR.log(['click', e, e.button]);
|
||||
|
||||
// = Feed Header ==================================================
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-feeds-header-starred' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
self.open_starred_stories();
|
||||
});
|
||||
$.targetIs(e, { tagSelector: '.NB-feeds-header-river-sites' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
self.open_river_stories();
|
||||
});
|
||||
$.targetIs(e, { tagSelector: '.NB-feeds-header-river-blurblogs' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
self.open_river_blurblogs_stories();
|
||||
});
|
||||
|
||||
// = Stories ======================================================
|
||||
|
||||
// NEWSBLUR.log(['click', e, e.button]);
|
||||
|
||||
// = Taskbar ======================================================
|
||||
|
||||
|
@ -4894,10 +4944,6 @@
|
|||
e.preventDefault();
|
||||
self.show_previous_story();
|
||||
});
|
||||
$.targetIs(e, { tagSelector: '.task_button_signup' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
self.show_splash_page();
|
||||
});
|
||||
$.targetIs(e, { tagSelector: '.NB-intelligence-slider-control' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
var unread_value;
|
||||
|
@ -4995,6 +5041,13 @@
|
|||
var feed_id = self.active_feed;
|
||||
self.follow_user_in_tryfeed(feed_id);
|
||||
});
|
||||
$.targetIs(e, { tagSelector: '.NB-tryout-signup' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
self.show_splash_page();
|
||||
if (NEWSBLUR.welcome) {
|
||||
NEWSBLUR.welcome.show_signin_form();
|
||||
}
|
||||
});
|
||||
|
||||
// = Interactions Module ==========================================
|
||||
|
||||
|
@ -5222,11 +5275,7 @@
|
|||
});
|
||||
$document.bind('keydown', 'shift+u', function(e) {
|
||||
e.preventDefault();
|
||||
if (self.flags['sidebar_closed']) {
|
||||
self.open_sidebar();
|
||||
} else {
|
||||
self.close_sidebar();
|
||||
}
|
||||
self.toggle_sidebar();
|
||||
});
|
||||
$document.bind('keydown', 'shift+t', function(e) {
|
||||
e.preventDefault();
|
||||
|
@ -5326,14 +5375,15 @@
|
|||
});
|
||||
$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')) {
|
||||
NEWSBLUR.assets.stories.mark_read(story, {skip_delay: true});
|
||||
} else if (self.active_story && self.active_story.get('read_status')) {
|
||||
NEWSBLUR.assets.stories.mark_unread(story);
|
||||
}
|
||||
self.mark_active_story_read();
|
||||
});
|
||||
$document.bind('keydown', 'm', function(e) {
|
||||
e.preventDefault();
|
||||
self.mark_active_story_read();
|
||||
});
|
||||
$document.bind('keydown', 'g', function(e) {
|
||||
e.preventDefault();
|
||||
NEWSBLUR.app.feed_selector.toggle();
|
||||
});
|
||||
$document.bind('keydown', 'shift+s', function(e) {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -57,7 +57,6 @@ NEWSBLUR.ReaderClassifierStory = function(story_id, feed_id, options) {
|
|||
this.options = $.extend({}, defaults, options);
|
||||
this.model = NEWSBLUR.assets;
|
||||
this.runner_story();
|
||||
console.log(["init story", feed_id, this.feed_id, options, this.options]);
|
||||
};
|
||||
|
||||
var classifier_prototype = {
|
||||
|
@ -121,7 +120,7 @@ var classifier_prototype = {
|
|||
this.handle_cancel();
|
||||
this.open_modal();
|
||||
this.$modal.parent().bind('click.reader_classifer', $.rescope(this.handle_clicks, this));
|
||||
console.log(["runner story", this.options, this.feed_id]);
|
||||
|
||||
if (!this.options.feed_loaded) {
|
||||
_.defer(_.bind(function() {
|
||||
this.load_single_feed_trainer();
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
NEWSBLUR.About = function(options) {
|
||||
var defaults = {};
|
||||
|
||||
this.options = $.extend({}, defaults, options);
|
||||
this.runner();
|
||||
};
|
||||
|
||||
NEWSBLUR.About.prototype = {
|
||||
|
||||
runner: function() {
|
||||
this.make_modal();
|
||||
this.open_modal();
|
||||
|
||||
this.$modal.bind('click', $.rescope(this.handle_click, this));
|
||||
},
|
||||
|
||||
make_modal: function() {
|
||||
var self = this;
|
||||
|
||||
this.$modal = $.make('div', { className: 'NB-modal-about NB-modal-exception NB-modal' }, [
|
||||
$.make('a', { href: '#faq', className: 'NB-link-about-faq' }, 'FAQ'),
|
||||
$.make('h2', { className: 'NB-modal-title' }, 'About NewsBlur'),
|
||||
$.make('div', { className: 'NB-fieldset NB-modal-submit' }, [
|
||||
$.make('h5', [
|
||||
$.make('div', { className: 'NB-exception-option-meta' }),
|
||||
$.make('span', { className: 'NB-exception-option-option' }, 'What:'),
|
||||
'A Feed Reader with Intelligence'
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset-fields' }, [
|
||||
$.make('ul', { className: 'NB-about-what' }, [
|
||||
$.make('li', 'Read the original site or the RSS feed.'),
|
||||
$.make('li', 'Automatically highlight stories you want to read.'),
|
||||
$.make('li', { className: 'last' }, 'Filter out stories you don\'t want to read.')
|
||||
])
|
||||
])
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset NB-modal-submit' }, [
|
||||
$.make('h5', [
|
||||
$.make('div', { className: 'NB-exception-option-meta' }),
|
||||
$.make('span', { className: 'NB-exception-option-option' }, 'Who:'),
|
||||
'A Labor of Love'
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset-fields' }, [
|
||||
$.make('ul', { className: 'NB-about-who' }, [
|
||||
$.make('li', [
|
||||
'Hand-crafted by: ',
|
||||
$.make('a', { href: 'http://www.samuelclay.com' }, 'Samuel Clay')
|
||||
]),
|
||||
$.make('li', [
|
||||
'Find him on Twitter: ',
|
||||
$.make('a', { href: 'http://twitter.com/samuelclay' }, '@samuelclay')
|
||||
]),
|
||||
$.make('li', [
|
||||
'E-mail: ',
|
||||
$.make('a', { href: 'mailto:samuel@newsblur.com' }, 'samuel@newsblur.com')
|
||||
]),
|
||||
$.make('li', { className: 'last' }, [
|
||||
'Made in: ',
|
||||
$.make('a', { href: 'http://www.newyorkfieldguide.com' }, 'New York City')
|
||||
])
|
||||
])
|
||||
])
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset NB-modal-submit' }, [
|
||||
$.make('h5', [
|
||||
$.make('div', { className: 'NB-exception-option-meta' }),
|
||||
$.make('span', { className: 'NB-exception-option-option' }, 'How:'),
|
||||
'Server-side technologies'
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset-fields' }, [
|
||||
$.make('ul', { className: 'NB-about-server' }, [
|
||||
$.make('li', [
|
||||
$.make('a', { href: 'http://www.djangoproject.com' }, 'Django'),
|
||||
': Web framework written in Python, used to serve all pages.'
|
||||
]),
|
||||
$.make('li', [
|
||||
$.make('a', { href: 'http://ask.github.com/celery' }, 'Celery'),
|
||||
' & ',
|
||||
$.make('a', { href: 'http://www.rabbitmq.com' }, 'RabbitMQ'),
|
||||
': Asynchronous queueing server, used to fetch and parse RSS feeds.'
|
||||
]),
|
||||
$.make('li', [
|
||||
$.make('a', { href: 'http://www.mongodb.com' }, 'MongoDB'),
|
||||
', ',
|
||||
$.make('a', { href: 'http://www.mongodb.com/pymongo' }, 'Pymongo'),
|
||||
', & ',
|
||||
$.make('a', { href: 'http://www.github.com/hmarr/mongoengine' }, 'Mongoengine'),
|
||||
': Non-relational database, used to store stories, read stories, feed/page fetch histories, and proxied sites.'
|
||||
]),
|
||||
$.make('li', { className: 'last' }, [
|
||||
$.make('a', { href: 'http://www.postgresql.com' }, 'PostgreSQL'),
|
||||
': Relational database, used to store feeds, subscriptions, and user accounts.'
|
||||
])
|
||||
])
|
||||
])
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset NB-modal-submit' }, [
|
||||
$.make('h5', [
|
||||
$.make('div', { className: 'NB-exception-option-meta' }),
|
||||
$.make('span', { className: 'NB-exception-option-option' }, 'How:'),
|
||||
'Client-side and design'
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset-fields' }, [
|
||||
$.make('ul', { className: 'NB-about-client' }, [
|
||||
$.make('li', [
|
||||
$.make('a', { href: 'http://www.jquery.com' }, 'jQuery'),
|
||||
': Cross-browser compliant JavaScript code. IE works without effort.'
|
||||
]),
|
||||
$.make('li', [
|
||||
$.make('a', { href: 'http://documentcloud.github.com/underscore/' }, 'Underscore.js'),
|
||||
': Functional programming for JavaScript. Indispensible.'
|
||||
]),
|
||||
$.make('li', [
|
||||
$.make('b', 'Miscellaneous jQuery Plugins:'),
|
||||
' Everything from resizable layouts, to progress bars, sortables, date handling, colors, corners, JSON, animations. See the complete list on ',
|
||||
$.make('a', { href: 'http://github.com/samuelclay/NewsBlur/' }, 'NewsBlur\'s GitHub repository')
|
||||
])
|
||||
])
|
||||
])
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset NB-modal-submit' }, [
|
||||
$.make('h5', [
|
||||
$.make('div', { className: 'NB-exception-option-meta' }),
|
||||
$.make('span', { className: 'NB-exception-option-option' }, 'Why:'),
|
||||
'What\'s the point of another RSS feed reader?'
|
||||
]),
|
||||
$.make('div', { className: 'NB-fieldset-fields' }, [
|
||||
$.make('ul', { className: 'NB-about-why' }, [
|
||||
$.make('li', [
|
||||
'To learn how to build and scale the entire web stack: front-end JavaScript, HTML5 layout, back-end view processing, large dataset schema migrations, relational and non-relational database clusters across multiple servers, and getting multiple machines to talk to each other.'
|
||||
]),
|
||||
$.make('li', [
|
||||
'All of this just to prove that I could do it.'
|
||||
]),
|
||||
$.make('li', [
|
||||
'But most importantly, to meet future co-founders.'
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
open_modal: function() {
|
||||
var self = this;
|
||||
|
||||
this.$modal.modal({
|
||||
'minWidth': 600,
|
||||
'maxWidth': 600,
|
||||
'overlayClose': true,
|
||||
'onOpen': function (dialog) {
|
||||
dialog.overlay.fadeIn(200, function () {
|
||||
dialog.container.fadeIn(200);
|
||||
dialog.data.fadeIn(200);
|
||||
});
|
||||
},
|
||||
'onShow': function(dialog) {
|
||||
$('#simplemodal-container').corner('6px');
|
||||
},
|
||||
'onClose': function(dialog, callback) {
|
||||
dialog.data.hide().empty().remove();
|
||||
dialog.container.hide().empty().remove();
|
||||
dialog.overlay.fadeOut(200, function() {
|
||||
dialog.overlay.empty().remove();
|
||||
$.modal.close(callback);
|
||||
});
|
||||
$('.NB-modal-holder').empty().remove();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
handle_cancel: function() {
|
||||
var $cancel = $('.NB-modal-cancel', this.$modal);
|
||||
|
||||
$cancel.click(function(e) {
|
||||
e.preventDefault();
|
||||
$.modal.close();
|
||||
});
|
||||
},
|
||||
|
||||
// ===========
|
||||
// = Actions =
|
||||
// ===========
|
||||
|
||||
handle_click: function(elem, e) {
|
||||
var self = this;
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-link-about-faq' }, function($t, $p) {
|
||||
e.preventDefault();
|
||||
|
||||
$.modal.close(function() {
|
||||
NEWSBLUR.faq = new NEWSBLUR.Faq();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|