mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
Merge branch 'master' into animations
This commit is contained in:
commit
38accaa3c0
52 changed files with 28930 additions and 9488 deletions
|
@ -32,7 +32,7 @@ class MClassifierTitle(mongo.Document):
|
|||
|
||||
meta = {
|
||||
'collection': 'classifier_title',
|
||||
'indexes': ['feed_id', 'user_id', ('user_id', 'feed_id')],
|
||||
'indexes': [('user_id', 'feed_id')],
|
||||
'allow_inheritance': False,
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ class MClassifierAuthor(mongo.Document):
|
|||
|
||||
meta = {
|
||||
'collection': 'classifier_author',
|
||||
'indexes': ['feed_id', 'user_id', ('user_id', 'feed_id')],
|
||||
'indexes': [('user_id', 'feed_id')],
|
||||
'allow_inheritance': False,
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ class MClassifierFeed(mongo.Document):
|
|||
|
||||
meta = {
|
||||
'collection': 'classifier_feed',
|
||||
'indexes': ['feed_id', 'user_id', ('user_id', 'feed_id')],
|
||||
'indexes': [('user_id', 'feed_id')],
|
||||
'allow_inheritance': False,
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ class MClassifierTag(mongo.Document):
|
|||
|
||||
meta = {
|
||||
'collection': 'classifier_tag',
|
||||
'indexes': ['feed_id', 'user_id', ('user_id', 'feed_id')],
|
||||
'indexes': [('user_id', 'feed_id')],
|
||||
'allow_inheritance': False,
|
||||
}
|
||||
|
||||
|
@ -114,17 +114,13 @@ def apply_classifier_tags(classifiers, story):
|
|||
|
||||
def get_classifiers_for_user(user, feed_id, classifier_feeds=None, classifier_authors=None, classifier_titles=None, classifier_tags=None):
|
||||
if classifier_feeds is None:
|
||||
classifier_feeds = MClassifierFeed.objects(user_id=user.pk, feed_id=feed_id)
|
||||
else: classifier_feeds.rewind()
|
||||
classifier_feeds = list(MClassifierFeed.objects(user_id=user.pk, feed_id=feed_id))
|
||||
if classifier_authors is None:
|
||||
classifier_authors = MClassifierAuthor.objects(user_id=user.pk, feed_id=feed_id)
|
||||
else: classifier_authors.rewind()
|
||||
classifier_authors = list(MClassifierAuthor.objects(user_id=user.pk, feed_id=feed_id))
|
||||
if classifier_titles is None:
|
||||
classifier_titles = MClassifierTitle.objects(user_id=user.pk, feed_id=feed_id)
|
||||
else: classifier_titles.rewind()
|
||||
classifier_titles = list(MClassifierTitle.objects(user_id=user.pk, feed_id=feed_id))
|
||||
if classifier_tags is None:
|
||||
classifier_tags = MClassifierTag.objects(user_id=user.pk, feed_id=feed_id)
|
||||
else: classifier_tags.rewind()
|
||||
classifier_tags = list(MClassifierTag.objects(user_id=user.pk, feed_id=feed_id))
|
||||
|
||||
payload = {
|
||||
'feeds': dict([(f.feed_id, f.score) for f in classifier_feeds]),
|
||||
|
|
|
@ -112,7 +112,7 @@ class OPMLImporter(Importer):
|
|||
def process_outline(self, outline):
|
||||
folders = []
|
||||
for item in outline:
|
||||
if not hasattr(item, 'xmlUrl'):
|
||||
if not hasattr(item, 'xmlUrl') and hasattr(item, 'text'):
|
||||
folder = item
|
||||
# if hasattr(folder, 'text'):
|
||||
# logging.info(' ---> [%s] ~FRNew Folder: %s' % (self.user, folder.text))
|
||||
|
|
0
apps/mobile/__init__.py
Normal file
0
apps/mobile/__init__.py
Normal file
3
apps/mobile/models.py
Normal file
3
apps/mobile/models.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.db import models
|
||||
|
||||
# Create your models here.
|
23
apps/mobile/tests.py
Normal file
23
apps/mobile/tests.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
"""
|
||||
This file demonstrates two different styles of tests (one doctest and one
|
||||
unittest). These will both pass when you run "manage.py test".
|
||||
|
||||
Replace these with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.failUnlessEqual(1 + 1, 2)
|
||||
|
||||
__test__ = {"doctest": """
|
||||
Another way to test that 1 + 1 is equal to 2.
|
||||
|
||||
>>> 1 + 1 == 2
|
||||
True
|
||||
"""}
|
||||
|
6
apps/mobile/urls.py
Normal file
6
apps/mobile/urls.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.conf.urls.defaults import *
|
||||
from apps.mobile import views
|
||||
|
||||
urlpatterns = patterns('apps.mobile.views',
|
||||
url(r'^$', views.index, name='mobile-index'),
|
||||
)
|
15
apps/mobile/views.py
Normal file
15
apps/mobile/views.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import os
|
||||
import base64
|
||||
import yaml
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from apps.profile.models import Profile
|
||||
from apps.reader.models import UserSubscription, UserSubscriptionFolders
|
||||
from utils import json_functions as json
|
||||
from utils import log as logging
|
||||
|
||||
def index(request):
|
||||
return render_to_response('mobile/mobile_workspace.xhtml', {},
|
||||
context_instance=RequestContext(request))
|
|
@ -7,7 +7,9 @@ class UserSubscriptionManager(models.Manager):
|
|||
try:
|
||||
return super(UserSubscriptionManager, self).get(*args, **kwargs)
|
||||
except:
|
||||
if 'feed' in kwargs:
|
||||
if isinstance(kwargs.get('feed'), int):
|
||||
feed_id = kwargs.get('feed')
|
||||
elif 'feed' in kwargs:
|
||||
feed_id = kwargs['feed'].pk
|
||||
elif 'feed__pk' in kwargs:
|
||||
feed_id = kwargs['feed__pk']
|
||||
|
|
|
@ -191,11 +191,11 @@ class UserSubscription(models.Model):
|
|||
# if not silent:
|
||||
# logging.info(' ---> [%s] Format stories: %s' % (self.user, datetime.datetime.now() - now))
|
||||
|
||||
classifier_feeds = MClassifierFeed.objects(user_id=self.user.pk, feed_id=self.feed.pk)
|
||||
classifier_authors = MClassifierAuthor.objects(user_id=self.user.pk, feed_id=self.feed.pk)
|
||||
classifier_titles = MClassifierTitle.objects(user_id=self.user.pk, feed_id=self.feed.pk)
|
||||
classifier_tags = MClassifierTag.objects(user_id=self.user.pk, feed_id=self.feed.pk)
|
||||
|
||||
classifier_feeds = list(MClassifierFeed.objects(user_id=self.user.pk, feed_id=self.feed.pk))
|
||||
classifier_authors = list(MClassifierAuthor.objects(user_id=self.user.pk, feed_id=self.feed.pk))
|
||||
classifier_titles = list(MClassifierTitle.objects(user_id=self.user.pk, feed_id=self.feed.pk))
|
||||
classifier_tags = list(MClassifierTag.objects(user_id=self.user.pk, feed_id=self.feed.pk))
|
||||
|
||||
# if not silent:
|
||||
# logging.info(' ---> [%s] Classifiers: %s (%s)' % (self.user, datetime.datetime.now() - now, classifier_feeds.count() + classifier_authors.count() + classifier_tags.count() + classifier_titles.count()))
|
||||
|
||||
|
@ -204,13 +204,10 @@ class UserSubscription(models.Model):
|
|||
}
|
||||
|
||||
for story in stories:
|
||||
classifier_authors.rewind()
|
||||
classifier_tags.rewind()
|
||||
classifier_titles.rewind()
|
||||
scores.update({
|
||||
'author': apply_classifier_authors(classifier_authors, story),
|
||||
'tags': apply_classifier_tags(classifier_tags, story),
|
||||
'title': apply_classifier_titles(classifier_titles, story),
|
||||
'author' : apply_classifier_authors(classifier_authors, story),
|
||||
'tags' : apply_classifier_tags(classifier_tags, story),
|
||||
'title' : apply_classifier_titles(classifier_titles, story),
|
||||
})
|
||||
|
||||
max_score = max(scores['author'], scores['tags'], scores['title'])
|
||||
|
|
|
@ -63,6 +63,7 @@ def index(request):
|
|||
active_count = UserSubscription.objects.filter(user=request.user, active=True).count() if authed else 0
|
||||
train_count = UserSubscription.objects.filter(user=request.user, active=True, is_trained=False, feed__stories_last_month__gte=1).count() if authed else 0
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=True, approved_date__lte=datetime.datetime.now()).select_related('feed')[:2]
|
||||
unmoderated_feeds = RecommendedFeed.objects.filter(is_public=False, declined_date__isnull=True).select_related('feed')[:2]
|
||||
statistics = MStatistics.all()
|
||||
feedbacks = MFeedback.all()
|
||||
|
||||
|
@ -77,6 +78,7 @@ def index(request):
|
|||
'train_count' : active_count - train_count,
|
||||
'account_images' : range(1, 4),
|
||||
'recommended_feeds' : recommended_feeds,
|
||||
'unmoderated_feeds' : unmoderated_feeds,
|
||||
'statistics' : statistics,
|
||||
'feedbacks' : feedbacks,
|
||||
'start_import_from_google_reader': request.session.get('import_from_google_reader', False),
|
||||
|
@ -184,6 +186,7 @@ def load_feed_favicons(request):
|
|||
|
||||
def load_feeds_flat(request):
|
||||
user = get_user(request)
|
||||
include_favicons = request.REQUEST.get('include_favicons', False)
|
||||
feeds = {}
|
||||
|
||||
try:
|
||||
|
@ -197,14 +200,7 @@ def load_feeds_flat(request):
|
|||
for sub in user_subs:
|
||||
if sub.needs_unread_recalc:
|
||||
sub.calculate_feed_scores(silent=True)
|
||||
feeds[sub.feed.pk] = {
|
||||
'id': sub.feed.pk,
|
||||
'feed_title': sub.user_title or sub.feed.feed_title,
|
||||
'feed_link': sub.feed.feed_link,
|
||||
'ps': sub.unread_count_positive,
|
||||
'nt': sub.unread_count_neutral,
|
||||
'ng': sub.unread_count_negative,
|
||||
}
|
||||
feeds[sub.feed.pk] = sub.canonical(include_favicon=include_favicons)
|
||||
|
||||
folders = json.decode(folders.folders)
|
||||
flat_folders = {}
|
||||
|
@ -212,25 +208,24 @@ def load_feeds_flat(request):
|
|||
def make_feeds_folder(items, parent_folder="", depth=0):
|
||||
for item in items:
|
||||
if isinstance(item, int) and item in feeds:
|
||||
feed = feeds[item]
|
||||
if not parent_folder:
|
||||
parent_folder = ' '
|
||||
if parent_folder in flat_folders:
|
||||
flat_folders[parent_folder].append(feed)
|
||||
flat_folders[parent_folder].append(item)
|
||||
else:
|
||||
flat_folders[parent_folder] = [feed]
|
||||
flat_folders[parent_folder] = [item]
|
||||
elif isinstance(item, dict):
|
||||
for folder_name in item:
|
||||
folder = item[folder_name]
|
||||
flat_folder_name = "%s%s%s" % (
|
||||
parent_folder,
|
||||
" - " if parent_folder else "",
|
||||
" - " if parent_folder and parent_folder != ' ' else "",
|
||||
folder_name
|
||||
)
|
||||
make_feeds_folder(folder, flat_folder_name, depth+1)
|
||||
|
||||
make_feeds_folder(folders)
|
||||
data = dict(flat_folders=flat_folders, user=user.username)
|
||||
data = dict(flat_folders=flat_folders, feeds=feeds, user=user.username)
|
||||
return data
|
||||
|
||||
@json.json_view
|
||||
|
@ -278,16 +273,16 @@ def refresh_feeds(request):
|
|||
|
||||
@json.json_view
|
||||
def load_single_feed(request, feed_id):
|
||||
start = datetime.datetime.utcnow()
|
||||
user = get_user(request)
|
||||
offset = int(request.REQUEST.get('offset', 0))
|
||||
limit = int(request.REQUEST.get('limit', 12))
|
||||
page = int(request.REQUEST.get('page', 1))
|
||||
if page:
|
||||
offset = limit * (page-1)
|
||||
start = time.time()
|
||||
user = get_user(request)
|
||||
offset = int(request.REQUEST.get('offset', 0))
|
||||
limit = int(request.REQUEST.get('limit', 12))
|
||||
page = int(request.REQUEST.get('page', 1))
|
||||
dupe_feed_id = None
|
||||
if not feed_id:
|
||||
raise Http404
|
||||
userstories_db = None
|
||||
|
||||
if page: offset = limit * (page-1)
|
||||
if not feed_id: raise Http404
|
||||
|
||||
try:
|
||||
feed = Feed.objects.get(id=feed_id)
|
||||
|
@ -303,10 +298,12 @@ def load_single_feed(request, feed_id):
|
|||
stories = feed.get_stories(offset, limit)
|
||||
|
||||
# Get intelligence classifier for user
|
||||
classifier_feeds = MClassifierFeed.objects(user_id=user.pk, feed_id=feed_id)
|
||||
classifier_authors = MClassifierAuthor.objects(user_id=user.pk, feed_id=feed_id)
|
||||
classifier_titles = MClassifierTitle.objects(user_id=user.pk, feed_id=feed_id)
|
||||
classifier_tags = MClassifierTag.objects(user_id=user.pk, feed_id=feed_id)
|
||||
classifier_feeds = list(MClassifierFeed.objects(user_id=user.pk, feed_id=feed_id))
|
||||
classifier_authors = list(MClassifierAuthor.objects(user_id=user.pk, feed_id=feed_id))
|
||||
classifier_titles = list(MClassifierTitle.objects(user_id=user.pk, feed_id=feed_id))
|
||||
classifier_tags = list(MClassifierTag.objects(user_id=user.pk, feed_id=feed_id))
|
||||
|
||||
checkpoint1 = time.time()
|
||||
|
||||
usersub = UserSubscription.objects.get(user=user, feed=feed)
|
||||
userstories = []
|
||||
|
@ -323,8 +320,9 @@ def load_single_feed(request, feed_id):
|
|||
elif hasattr(us.story, 'id') and isinstance(us.story.id, unicode):
|
||||
userstories.append(us.story.id) # TODO: Remove me after migration from story.id->guid
|
||||
|
||||
checkpoint2 = time.time()
|
||||
|
||||
for story in stories:
|
||||
[x.rewind() for x in [classifier_feeds, classifier_authors, classifier_tags, classifier_titles]]
|
||||
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
||||
now = localtime_for_timezone(datetime.datetime.now(), user.profile.timezone)
|
||||
story['short_parsed_date'] = format_story_link_date__short(story_date, now)
|
||||
|
@ -348,6 +346,8 @@ def load_single_feed(request, feed_id):
|
|||
'tags': apply_classifier_tags(classifier_tags, story),
|
||||
'title': apply_classifier_titles(classifier_titles, story),
|
||||
}
|
||||
|
||||
checkpoint3 = time.time()
|
||||
|
||||
# Intelligence
|
||||
feed_tags = json.decode(feed.data.popular_tags) if feed.data.popular_tags else []
|
||||
|
@ -358,14 +358,19 @@ def load_single_feed(request, feed_id):
|
|||
if usersub:
|
||||
usersub.feed_opens += 1
|
||||
usersub.save()
|
||||
|
||||
diff = datetime.datetime.utcnow()-start
|
||||
timediff = float("%s.%.2s" % (diff.seconds, (diff.microseconds / 1000)))
|
||||
timediff = time.time()-start
|
||||
last_update = relative_timesince(feed.last_update)
|
||||
logging.user(request.user, "~FYLoading feed: ~SB%s%s ~SN(%s seconds)" % (
|
||||
logging.user(request.user, "~FYLoading feed: ~SB%s%s ~SN(%.4s seconds)" % (
|
||||
feed, ('~SN/p%s' % page) if page > 1 else '', timediff))
|
||||
FeedLoadtime.objects.create(feed=feed, loadtime=timediff)
|
||||
|
||||
if timediff >= 1:
|
||||
diff1 = checkpoint1-start
|
||||
diff2 = checkpoint2-start
|
||||
diff3 = checkpoint3-start
|
||||
logging.user(request.user, "~FYSlow feed load: ~SB%.4s/%.4s(%s)/%.4s" % (
|
||||
diff1, diff2, userstories_db and userstories_db.count(), diff3))
|
||||
|
||||
data = dict(stories=stories,
|
||||
feed_tags=feed_tags,
|
||||
feed_authors=feed_authors,
|
||||
|
@ -429,7 +434,7 @@ def load_river_stories(request):
|
|||
user = get_user(request)
|
||||
feed_ids = [int(feed_id) for feed_id in request.REQUEST.getlist('feeds') if feed_id]
|
||||
original_feed_ids = list(feed_ids)
|
||||
page = int(request.REQUEST.get('page', 0))+1
|
||||
page = int(request.REQUEST.get('page', 1))
|
||||
read_stories_count = int(request.REQUEST.get('read_stories_count', 0))
|
||||
bottom_delta = datetime.timedelta(days=settings.DAYS_OF_UNREAD)
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import datetime
|
||||
from django import template
|
||||
from apps.reader.models import UserSubscription
|
||||
from utils.user_functions import get_user
|
||||
|
@ -7,7 +8,7 @@ from apps.rss_feeds.models import MFeedIcon
|
|||
register = template.Library()
|
||||
|
||||
@register.inclusion_tag('recommendations/render_recommended_feed.xhtml', takes_context=True)
|
||||
def render_recommended_feed(context, recommended_feeds):
|
||||
def render_recommended_feed(context, recommended_feeds, unmoderated=False):
|
||||
user = get_user(context['user'])
|
||||
|
||||
usersub = None
|
||||
|
@ -18,11 +19,13 @@ def render_recommended_feed(context, recommended_feeds):
|
|||
|
||||
if recommended_feed:
|
||||
return {
|
||||
'recommended_feed': recommended_feed,
|
||||
'description': recommended_feed.description or recommended_feed.feed.data.feed_tagline,
|
||||
'usersub': usersub,
|
||||
'feed_icon': feed_icon and feed_icon[0],
|
||||
'user': context['user'],
|
||||
'has_next_page': len(recommended_feeds) > 1
|
||||
'recommended_feed' : recommended_feed,
|
||||
'description' : recommended_feed.description or recommended_feed.feed.data.feed_tagline,
|
||||
'usersub' : usersub,
|
||||
'feed_icon' : feed_icon and feed_icon[0],
|
||||
'user' : context['user'],
|
||||
'has_next_page' : len(recommended_feeds) > 1,
|
||||
'unmoderated' : unmoderated,
|
||||
'today' : datetime.datetime.now(),
|
||||
}
|
||||
|
|
@ -4,5 +4,7 @@ from apps.recommendations import views
|
|||
urlpatterns = patterns('',
|
||||
url(r'^load_recommended_feed', views.load_recommended_feed, name='load-recommended-feed'),
|
||||
url(r'^save_recommended_feed', views.save_recommended_feed, name='save-recommended-feed'),
|
||||
url(r'^approve_feed', views.approve_feed, name='approve-recommended-feed'),
|
||||
url(r'^decline_feed', views.decline_feed, name='decline-recommended-feed'),
|
||||
url(r'^load_feed_info/(?P<feed_id>\d+)', views.load_feed_info, name='load-recommended-feed-info'),
|
||||
)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import re
|
||||
import datetime
|
||||
from utils import log as logging
|
||||
from django.http import HttpResponse
|
||||
|
@ -7,17 +8,21 @@ from apps.recommendations.models import RecommendedFeed
|
|||
from apps.reader.models import UserSubscription
|
||||
from apps.rss_feeds.models import Feed, MFeedIcon
|
||||
from utils import json_functions as json
|
||||
from utils.user_functions import get_user, ajax_login_required
|
||||
from utils.user_functions import get_user, ajax_login_required, admin_only
|
||||
|
||||
|
||||
def load_recommended_feed(request):
|
||||
user = get_user(request)
|
||||
page = int(request.REQUEST.get('page', 0))
|
||||
usersub = None
|
||||
refresh = request.REQUEST.get('refresh')
|
||||
now = datetime.datetime.now
|
||||
user = get_user(request)
|
||||
page = int(request.REQUEST.get('page', 0))
|
||||
usersub = None
|
||||
refresh = request.REQUEST.get('refresh')
|
||||
now = datetime.datetime.now
|
||||
unmoderated = request.REQUEST.get('unmoderated', False) == 'true'
|
||||
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=True, approved_date__lte=now)[page:page+2]
|
||||
if unmoderated:
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=False, declined_date__isnull=True)[page:page+2]
|
||||
else:
|
||||
recommended_feeds = RecommendedFeed.objects.filter(is_public=True, approved_date__lte=now)[page:page+2]
|
||||
if recommended_feeds and request.user.is_authenticated():
|
||||
usersub = UserSubscription.objects.filter(user=user, feed=recommended_feeds[0].feed)
|
||||
if refresh != 'true' and page > 0:
|
||||
|
@ -34,6 +39,8 @@ def load_recommended_feed(request):
|
|||
'feed_icon' : feed_icon and feed_icon[0],
|
||||
'has_next_page' : len(recommended_feeds) > 1,
|
||||
'has_previous_page' : page != 0,
|
||||
'unmoderated' : unmoderated,
|
||||
'today' : datetime.datetime.now(),
|
||||
}, context_instance=RequestContext(request))
|
||||
else:
|
||||
return HttpResponse("")
|
||||
|
@ -71,4 +78,33 @@ def save_recommended_feed(request):
|
|||
)
|
||||
)
|
||||
|
||||
return dict(code=code if created else -1)
|
||||
return dict(code=code if created else -1)
|
||||
|
||||
@admin_only
|
||||
@ajax_login_required
|
||||
def approve_feed(request):
|
||||
feed_id = request.POST['feed_id']
|
||||
feed = get_object_or_404(Feed, pk=int(feed_id))
|
||||
date = request.POST['date']
|
||||
recommended_feed = RecommendedFeed.objects.filter(feed=feed)[0]
|
||||
|
||||
year, month, day = re.search(r'(\d{4})-(\d{1,2})-(\d{1,2})', date).groups()
|
||||
recommended_feed.is_public = True
|
||||
recommended_feed.approved_date = datetime.date(int(year), int(month), int(day))
|
||||
recommended_feed.save()
|
||||
|
||||
return load_recommended_feed(request)
|
||||
|
||||
@admin_only
|
||||
@ajax_login_required
|
||||
def decline_feed(request):
|
||||
feed_id = request.POST['feed_id']
|
||||
feed = get_object_or_404(Feed, pk=int(feed_id))
|
||||
recommended_feeds = RecommendedFeed.objects.filter(feed=feed)
|
||||
|
||||
for recommended_feed in recommended_feeds:
|
||||
recommended_feed.is_public = False
|
||||
recommended_feed.declined_date = datetime.datetime.now()
|
||||
recommended_feed.save()
|
||||
|
||||
return load_recommended_feed(request)
|
|
@ -737,7 +737,6 @@ class Feed(models.Model):
|
|||
story_published_now = story.get('published_now', False)
|
||||
start_date = story_pub_date - datetime.timedelta(hours=8)
|
||||
end_date = story_pub_date + datetime.timedelta(hours=8)
|
||||
existing_stories.rewind()
|
||||
|
||||
for existing_story in existing_stories:
|
||||
content_ratio = 0
|
||||
|
|
|
@ -117,11 +117,13 @@ class MFeedback(mongo.Document):
|
|||
subject = mongo.StringField()
|
||||
url = mongo.StringField()
|
||||
style = mongo.StringField()
|
||||
order = mongo.IntField()
|
||||
|
||||
meta = {
|
||||
'collection': 'feedback',
|
||||
'allow_inheritance': False,
|
||||
'indexes': ['style'],
|
||||
'ordering': ['order'],
|
||||
}
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -131,13 +133,16 @@ class MFeedback(mongo.Document):
|
|||
def collect_feedback(cls):
|
||||
data = urllib2.urlopen('https://getsatisfaction.com/newsblur/topics.widget').read()
|
||||
data = json.decode(data[1:-1])
|
||||
i = 0
|
||||
if len(data):
|
||||
cls.objects.delete()
|
||||
for feedback in data:
|
||||
feedback['order'] = i
|
||||
i += 1
|
||||
for removal in ['about', 'less than']:
|
||||
if removal in feedback['date']:
|
||||
feedback['date'] = feedback['date'].replace(removal, '')
|
||||
[MFeedback.objects.create(**feedback) for feedback in data]
|
||||
[cls.objects.create(**feedback) for feedback in data]
|
||||
|
||||
@classmethod
|
||||
def all(cls):
|
||||
|
|
92
config/mongodb.dev.conf
Normal file
92
config/mongodb.dev.conf
Normal file
|
@ -0,0 +1,92 @@
|
|||
# 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=/Users/conesus/newsblur/data/db/unsharded
|
||||
|
||||
#where to log
|
||||
logpath=/Users/conesus/newsblur/data/unsharded.log
|
||||
|
||||
logappend=false
|
||||
|
||||
#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 = setname
|
||||
|
||||
journal = true
|
7
fabfile.py
vendored
7
fabfile.py
vendored
|
@ -44,6 +44,7 @@ def deploy():
|
|||
run('git pull')
|
||||
run('kill -HUP `cat logs/gunicorn.pid`')
|
||||
run('curl -s http://www.newsblur.com > /dev/null')
|
||||
run('curl -s http://www.newsblur.com/m/ > /dev/null')
|
||||
run('curl -s http://www.newsblur.com/api/add_site_load_script/ABCDEF > /dev/null')
|
||||
compress_media()
|
||||
|
||||
|
@ -54,6 +55,7 @@ def deploy_full():
|
|||
run('./manage.py migrate')
|
||||
run('sudo supervisorctl restart gunicorn')
|
||||
run('curl -s http://www.newsblur.com > /dev/null')
|
||||
run('curl -s http://www.newsblur.com/m/ > /dev/null')
|
||||
compress_media()
|
||||
|
||||
@roles('web')
|
||||
|
@ -62,6 +64,7 @@ def staging():
|
|||
run('git pull')
|
||||
run('kill -HUP `cat logs/gunicorn.pid`')
|
||||
run('curl -s http://dev.newsblur.com > /dev/null')
|
||||
run('curl -s http://dev.newsblur.com/m/ > /dev/null')
|
||||
compress_media()
|
||||
|
||||
@roles('web')
|
||||
|
@ -71,6 +74,7 @@ def staging_full():
|
|||
run('./manage.py migrate')
|
||||
run('kill -HUP `cat logs/gunicorn.pid`')
|
||||
run('curl -s http://dev.newsblur.com > /dev/null')
|
||||
run('curl -s http://dev.newsblur.com/m/ > /dev/null')
|
||||
compress_media()
|
||||
|
||||
@roles('task')
|
||||
|
@ -94,6 +98,9 @@ def compress_media():
|
|||
with cd('media/js'):
|
||||
run('rm -f *.gz')
|
||||
run('for js in *-compressed-*.js; do gzip -9 $js -c > $js.gz; done;')
|
||||
with cd('media/css/mobile'):
|
||||
run('rm -f *.gz')
|
||||
run('for css in *-compressed-*.css; do gzip -9 $css -c > $css.gz; done;')
|
||||
with cd('media/css'):
|
||||
run('rm -f *.gz')
|
||||
run('for css in *-compressed-*.css; do gzip -9 $css -c > $css.gz; done;')
|
||||
|
|
1
media/css/mobile/images
Symbolic link
1
media/css/mobile/images
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../img/mobile
|
3319
media/css/mobile/jquery.mobile-1.0b1.css
Normal file
3319
media/css/mobile/jquery.mobile-1.0b1.css
Normal file
File diff suppressed because it is too large
Load diff
297
media/css/mobile/mobile.css
Normal file
297
media/css/mobile/mobile.css
Normal file
|
@ -0,0 +1,297 @@
|
|||
/* ========== */
|
||||
/* = Global = */
|
||||
/* ========== */
|
||||
body {
|
||||
overflow-y: scroll !important;
|
||||
}
|
||||
.NB-favicon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.NB-story-tags {
|
||||
overflow: hidden;
|
||||
line-height: 12px;
|
||||
height: 14px;
|
||||
margin: 0 0 6px 0;
|
||||
}
|
||||
.NB-story-tag {
|
||||
float: left;
|
||||
font-weight: normal;
|
||||
font-size: 9px;
|
||||
padding: 0px 4px 1px;
|
||||
margin: 0 2px 2px;
|
||||
background-color: #E3DFD4;
|
||||
color: #878787;
|
||||
text-shadow: 0 1px 0 #E9E9E9;
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
}
|
||||
.NB-story-author {
|
||||
color: #969696;
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
margin: 0 16px 8px 0;
|
||||
text-shadow: 0 1px 0 #F9F9F9;
|
||||
float: left;
|
||||
}
|
||||
.NB-story-date {
|
||||
float: right;
|
||||
font-size: 11px;
|
||||
color: #252D6C;
|
||||
}
|
||||
.NB-story .NB-icon-score {
|
||||
margin-top: 12px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
left: 4px;
|
||||
top: 17px;
|
||||
}
|
||||
.NB-story.NB-read .NB-icon-score {
|
||||
opacity: .2;
|
||||
}
|
||||
.NB-story.NB-score-positive .NB-icon-score {
|
||||
background: transparent url('../../img/icons/silk/bullet_green.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-story.NB-score-neutral .NB-icon-score {
|
||||
background: transparent url('../../img/icons/silk/bullet_yellow.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-story.NB-score-negative .NB-icon-score {
|
||||
background: transparent url('../../img/icons/silk/bullet_red.png') no-repeat 0 0;
|
||||
}
|
||||
.NB-story .NB-story-title {
|
||||
clear: left;
|
||||
}
|
||||
.ui-btn-up-c,
|
||||
.ui-btn-hover-c {
|
||||
border: 1px solid #E4E4E4;
|
||||
color: #111;
|
||||
background-color: #E0E0E0;
|
||||
background-image: -moz-linear-gradient(top, #FCFCFC, #F3F3F3); /* FF3.6 */
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#F3F3F3)); /* Saf4+, Chrome */
|
||||
background-image: linear-gradient(top, #FCFCFC, #F3F3F3);
|
||||
}
|
||||
.ui-btn-active {
|
||||
text-shadow: 0 -1px 1px #145072;
|
||||
border: 1px solid #155678;
|
||||
background-color: #4596ce;
|
||||
background-image: -moz-linear-gradient(top, #85bae4, #5393c5); /* FF3.6 */
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#85bae4), to(#5393c5)); /* Saf4+, Chrome */
|
||||
background-image: linear-gradient(top, #85bae4, #5393c5);
|
||||
}
|
||||
|
||||
/* ============= */
|
||||
/* = Feed List = */
|
||||
/* ============= */
|
||||
|
||||
#NB-feed-list a {
|
||||
padding-left: 36px;
|
||||
padding-right: 36px;
|
||||
}
|
||||
#NB-feed-list .ui-li-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
#NB-feed-list .ui-li-count {
|
||||
position: static;
|
||||
float: right;
|
||||
margin: 1px 2px 0 0;
|
||||
padding: 3px 4px 2px;
|
||||
white-space: normal;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
text-shadow: none;
|
||||
}
|
||||
#NB-feed-list .ui-li-count.ui-li-count-positive {
|
||||
color: white;
|
||||
background-color: #559F4D;
|
||||
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#559F4D), to(#3B7613));
|
||||
background-image: -moz-linear-gradient(center bottom, #3B7613, #559F4D);
|
||||
}
|
||||
#NB-feed-list .ui-li-count.ui-li-count-neutral {
|
||||
background-color: #F9C72A;
|
||||
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#F9C72A), to(#E4AB00));
|
||||
background-image: -moz-linear-gradient(center bottom, #E4AB00, #F9C72A);
|
||||
}
|
||||
#NB-feed-list .ui-li-count.ui-li-count-negative {
|
||||
color: white;
|
||||
background-color: #CC2A2E;
|
||||
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#CC2A2E), to(#9B181B));
|
||||
background-image: -moz-linear-gradient(center bottom, #9B181B, #CC2A2E);
|
||||
}
|
||||
|
||||
/* ============== */
|
||||
/* = Story List = */
|
||||
/* ============== */
|
||||
|
||||
#NB-story-list .NB-story a {
|
||||
padding-left: 24px;
|
||||
padding-right: 36px;
|
||||
}
|
||||
#NB-story-list .NB-story-feed {
|
||||
overflow: hidden;
|
||||
text-shadow: 0 1px 0 #E9E9E9;
|
||||
margin: 4px 0 0 0;
|
||||
white-space: normal;
|
||||
}
|
||||
#NB-story-list .NB-story-feed .NB-story-feed-icon {
|
||||
float: left;
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
#NB-story-list .NB-story-feed .NB-story-feed-icon img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
#NB-story-list .NB-story-feed .NB-story-feed-title {
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
margin: 2px 0 0 0;
|
||||
color: #525252;
|
||||
}
|
||||
#NB-story-list .NB-read .NB-story-feed .NB-story-feed-title {
|
||||
color: #8D8D8D;
|
||||
}
|
||||
#NB-story-list .NB-read .NB-story-feed img {
|
||||
opacity: .6;
|
||||
}
|
||||
#NB-story-list .NB-story .NB-story-title {
|
||||
text-shadow: 0 1px 0 #F3F3F3;
|
||||
white-space: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
#NB-story-list .NB-story.ui-btn-active .NB-story-title,
|
||||
#NB-story-list .NB-story.ui-btn-active .NB-story-tags,
|
||||
#NB-story-list .NB-story.ui-btn-active .NB-story-author,
|
||||
#NB-story-list .NB-story.ui-btn-active .NB-story-date,
|
||||
#NB-story-list .NB-story.ui-btn-active .NB-story-feed .NB-story-feed-title,
|
||||
#NB-story-list .NB-read.ui-btn-active .NB-story-author,
|
||||
#NB-story-list .NB-read.ui-btn-active .NB-story-date,
|
||||
#NB-story-list .NB-read.ui-btn-active .NB-story-title,
|
||||
#NB-story-list .NB-read.ui-btn-active .NB-story-feed .NB-story-feed-title {
|
||||
text-shadow: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
#NB-story-list .NB-story.ui-btn-active .NB-story-feed .NB-story-feed-title,
|
||||
#NB-story-list .NB-read.ui-btn-active .NB-story-feed .NB-story-feed-title {
|
||||
text-shadow: 0 1px 0 #000;
|
||||
}
|
||||
#NB-story-list .NB-read .NB-story-title {
|
||||
font-weight: normal;
|
||||
color: #808080;
|
||||
}
|
||||
#NB-story-list .NB-read .NB-story-date {
|
||||
color: #6D6D6D;
|
||||
font-weight: normal;
|
||||
}
|
||||
#NB-story-list .NB-read .NB-story-author {
|
||||
color: #B0B0B0;
|
||||
}
|
||||
#NB-story-list .NB-read .NB-story-tags {
|
||||
opacity: .7;
|
||||
}
|
||||
#NB-story-list .NB-read.ui-btn-up-c,
|
||||
#NB-story-list .NB-read.ui-btn-hover-c {
|
||||
border: 1px solid #E4E4E4;
|
||||
color: #111;
|
||||
background-color: #E0E0E0;
|
||||
background-image: -moz-linear-gradient(top, #FCFCFC, #F9F9F9); /* FF3.6 */
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#F9F9F9)); /* Saf4+, Chrome */
|
||||
background-image: linear-gradient(top, #FCFCFC, #F9F9F9);
|
||||
}
|
||||
|
||||
|
||||
/* ================ */
|
||||
/* = Story Detail = */
|
||||
/* ================ */
|
||||
|
||||
#NB-page-story .NB-story-feed-header {
|
||||
margin: 8px 0;
|
||||
}
|
||||
#NB-page-story .ui-content {
|
||||
padding: 0;
|
||||
}
|
||||
#NB-page-story .ui-header {
|
||||
padding: 2px 0;
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
text-shadow: 1px 1px 0 #000;
|
||||
}
|
||||
#NB-page-story .ui-header.NB-inverse {
|
||||
color: black;
|
||||
text-shadow: 1px 1px 0 #E0E0E0;
|
||||
}
|
||||
#NB-page-story .ui-title {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin: 0 120px 0 106px;
|
||||
}
|
||||
#NB-page-story .ui-title .feed_title {
|
||||
}
|
||||
#NB-page-story .NB-favicon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
#NB-story-detail {
|
||||
background-color: white;
|
||||
}
|
||||
#NB-story-detail .NB-story-header {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
padding: 8px 24px 8px 24px;
|
||||
background-color: #dadada;
|
||||
background-image: -moz-linear-gradient(top, #EBEBEB, #CFCFCF); /* FF3.6 */
|
||||
background-image: -ms-linear-gradient(top, #EBEBEB, #CFCFCF); /* IE10 */
|
||||
background-image: -o-linear-gradient(top, #EBEBEB, #CFCFCF); /* Opera 11.10+ */
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#EBEBEB), to(#CFCFCF)); /* Saf4+, Chrome */
|
||||
background-image: -webkit-linear-gradient(top, #EBEBEB, #CFCFCF); /* Chrome 10+, Saf5.1+ */
|
||||
background-image: linear-gradient(top, #EBEBEB, #CFCFCF);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#EBEBEB', EndColorStr='#CFCFCF'); /* IE6–IE9 */
|
||||
|
||||
border-bottom: 1px solid #ADADAD;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
#NB-story-detail .NB-story-header a {
|
||||
text-decoration: none;
|
||||
}
|
||||
#NB-story-detail .NB-story-title {
|
||||
color: #303030;
|
||||
}
|
||||
#NB-story-detail .NB-story-content {
|
||||
text-shadow: none;
|
||||
padding: 12px 24px;
|
||||
color: #2b2b2b;
|
||||
font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
#NB-story-detail .NB-story-content p {
|
||||
clear: both;
|
||||
}
|
||||
#NB-story-detail .NB-story-content blockquote {
|
||||
background-color: #F0F0F0;
|
||||
border-left: 1px solid #9B9B9B;
|
||||
padding: .5em 2em;
|
||||
margin: 0px;
|
||||
}
|
||||
#NB-story-detail .NB-story-content img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#NB-page-story .NB-icon-score {
|
||||
margin-top: 12px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
left: 4px;
|
||||
top: 17px;
|
||||
}
|
||||
#NB-page-story.NB-score-positive .NB-icon-score {
|
||||
background: transparent url('../../img/icons/silk/bullet_green.png') no-repeat 0 0;
|
||||
}
|
||||
#NB-page-story.NB-score-neutral .NB-icon-score {
|
||||
background: transparent url('../../img/icons/silk/bullet_yellow.png') no-repeat 0 0;
|
||||
}
|
||||
#NB-page-story.NB-score-negative .NB-icon-score {
|
||||
background: transparent url('../../img/icons/silk/bullet_red.png') no-repeat 0 0;
|
||||
}
|
BIN
media/img/mobile/ajax-loader.png
Normal file
BIN
media/img/mobile/ajax-loader.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 503 B |
BIN
media/img/mobile/icon-search-black.png
Normal file
BIN
media/img/mobile/icon-search-black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
media/img/mobile/icons-18-black.png
Normal file
BIN
media/img/mobile/icons-18-black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
BIN
media/img/mobile/icons-18-white.png
Normal file
BIN
media/img/mobile/icons-18-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
media/img/mobile/icons-36-black.png
Normal file
BIN
media/img/mobile/icons-36-black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
BIN
media/img/mobile/icons-36-white.png
Normal file
BIN
media/img/mobile/icons-36-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -2,17 +2,20 @@
|
|||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1024</int>
|
||||
<string key="IBDocument.SystemVersion">10H574</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">804</string>
|
||||
<string key="IBDocument.SystemVersion">10J869</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">1305</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.35</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">123</string>
|
||||
<string key="NS.object.0">300</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
||||
<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<integer value="2"/>
|
||||
<string>IBUITableViewCell</string>
|
||||
<string>IBUIImageView</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBProxyObject</string>
|
||||
</object>
|
||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -23,9 +26,7 @@
|
|||
<object class="NSArray" key="dict.sortedKeys" id="0">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -50,8 +51,9 @@
|
|||
<object class="IBUILabel" id="750430533">
|
||||
<reference key="NSNextResponder" ref="994014136"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{133, 37}, {165, 15}}</string>
|
||||
<string key="NSFrame">{{153, 37}, {145, 15}}</string>
|
||||
<reference key="NSSuperview" ref="994014136"/>
|
||||
<reference key="NSWindow"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor" id="932003208">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MSAxIDEAA</bytes>
|
||||
|
@ -86,6 +88,7 @@
|
|||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 4}, {280, 31}}</string>
|
||||
<reference key="NSSuperview" ref="994014136"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="IBUIBackgroundColor" ref="932003208"/>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
|
@ -114,8 +117,9 @@
|
|||
<object class="IBUILabel" id="194816084">
|
||||
<reference key="NSNextResponder" ref="994014136"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 37}, {113, 15}}</string>
|
||||
<string key="NSFrame">{{20, 37}, {131, 15}}</string>
|
||||
<reference key="NSSuperview" ref="994014136"/>
|
||||
<reference key="NSWindow"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MSAxIDEgMAA</bytes>
|
||||
|
@ -147,6 +151,7 @@
|
|||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{2, 12}, {16, 16}}</string>
|
||||
<reference key="NSSuperview" ref="994014136"/>
|
||||
<reference key="NSWindow"/>
|
||||
<bool key="IBUIAutoresizesSubviews">NO</bool>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
|
@ -154,6 +159,7 @@
|
|||
</object>
|
||||
<string key="NSFrameSize">{300, 55}</string>
|
||||
<reference key="NSSuperview" ref="749780469"/>
|
||||
<reference key="NSWindow"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MCAwAA</bytes>
|
||||
|
@ -167,6 +173,7 @@
|
|||
</object>
|
||||
<string key="NSFrameSize">{320, 55}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="IBUIBackgroundColor" ref="932003208"/>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUISeparatorStyle">1</int>
|
||||
|
@ -297,17 +304,13 @@
|
|||
<object class="NSMutableDictionary" key="unlocalizedProperties">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<nil key="activeLocalization"/>
|
||||
<object class="NSMutableDictionary" key="localizations">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">23</int>
|
||||
|
@ -366,173 +369,7 @@
|
|||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Classes/FeedDetailTableCell.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Source/NSObject+SBJSON.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Source/SBJsonWriter.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSError.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="603407049">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIImageView</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIImageView.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UILabel</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UILabel.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIResponder</string>
|
||||
<string key="superclassName">NSObject</string>
|
||||
<reference key="sourceIdentifier" ref="603407049"/>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UITableViewCell</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UITableViewCell.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIView</string>
|
||||
<string key="superclassName">UIResponder</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIView.h</string>
|
||||
<string key="minorKey">./Classes/FeedDetailTableCell.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -548,8 +385,7 @@
|
|||
<integer value="3100" key="NS.object.0"/>
|
||||
</object>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<string key="IBDocument.LastKnownRelativeProjectPath">../NewsBlur.xcodeproj</string>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<string key="IBCocoaTouchPluginVersion">123</string>
|
||||
<string key="IBCocoaTouchPluginVersion">300</string>
|
||||
</data>
|
||||
</archive>
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
- (void)fetchFeedDetail {
|
||||
if ([appDelegate.activeFeed objectForKey:@"id"] != nil) {
|
||||
NSString *theFeedDetailURL = [[NSString alloc]
|
||||
initWithFormat:@"http://nb.local.host:8000/reader/load_single_feed/?feed_id=%@",
|
||||
initWithFormat:@"http://nb.local.host:8000/reader/feed/%@",
|
||||
[appDelegate.activeFeed objectForKey:@"id"]];
|
||||
//NSLog(@"Url: %@", theFeedDetailURL);
|
||||
NSURL *urlFeedDetail = [NSURL URLWithString:theFeedDetailURL];
|
||||
|
@ -150,12 +150,12 @@
|
|||
|
||||
NSDictionary *story = [appDelegate.activeFeedStories objectAtIndex:indexPath.row];
|
||||
if ([[story objectForKey:@"story_authors"] class] != [NSNull class]) {
|
||||
cell.storyAuthor.text = [story objectForKey:@"story_authors"];
|
||||
cell.storyAuthor.text = [[story objectForKey:@"story_authors"] uppercaseString];
|
||||
} else {
|
||||
cell.storyAuthor.text = @"";
|
||||
}
|
||||
cell.storyTitle.text = [story objectForKey:@"story_title"];
|
||||
cell.storyDate.text = [story objectForKey:@"long_parsed_date"];
|
||||
cell.storyDate.text = [story objectForKey:@"short_parsed_date"];
|
||||
|
||||
if ([[story objectForKey:@"read_status"] intValue] != 1) {
|
||||
// Unread story
|
||||
|
|
|
@ -57,6 +57,9 @@
|
|||
- (void)setTitle:(NSString *)title;
|
||||
- (void)showOriginalStory:(NSURL *)url;
|
||||
- (void)closeOriginalStory;
|
||||
- (int)indexOfNextStory;
|
||||
- (int)indexOfPreviousStory;
|
||||
- (int)indexOfActiveStory;
|
||||
+ (int)computeStoryScore:(NSDictionary *)intelligence;
|
||||
|
||||
@end
|
||||
|
|
|
@ -119,6 +119,44 @@
|
|||
[originalStoryViewController dismissModalViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
- (int)indexOfNextStory {
|
||||
int activeIndex = [self indexOfActiveStory];
|
||||
NSUInteger activeFeedStoriesCount = [activeFeedStories count];
|
||||
NSLog(@"ActiveStory: %d", activeIndex);
|
||||
NSLog(@"ActiveStory: %d", activeFeedStoriesCount);
|
||||
for (int i=activeIndex+1; i < activeFeedStoriesCount; i++) {
|
||||
NSDictionary *story = [activeFeedStories objectAtIndex:i];
|
||||
NSDecimalNumber *readStatus = [story objectForKey:@"read_status"];
|
||||
NSLog(@"readStatus: %@", readStatus);
|
||||
if (readStatus == 0) {
|
||||
NSLog(@"NextStory: %d", i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
- (int)indexOfPreviousStory {
|
||||
NSInteger activeIndex = [self indexOfActiveStory];
|
||||
for (int i=activeIndex-1; i >= 0; i--) {
|
||||
NSDictionary *story = [activeFeedStories objectAtIndex:i];
|
||||
if ([story objectForKey:@"read_status"] == 1) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
- (int)indexOfActiveStory {
|
||||
for (int i=0; i < [activeFeedStories count]; i++) {
|
||||
NSDictionary *story = [activeFeedStories objectAtIndex:i];
|
||||
if ([activeStory objectForKey:@"id"] == [story objectForKey:@"id"]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ (int)computeStoryScore:(NSDictionary *)intelligence {
|
||||
int score = 0;
|
||||
// int score_max = 0;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
NSMutableData *responseData;
|
||||
NSMutableArray * feedTitleList;
|
||||
NSDictionary * dictFolders;
|
||||
NSDictionary * dictFeeds;
|
||||
NSMutableArray * dictFoldersArray;
|
||||
|
||||
IBOutlet UITableView * viewTableFeedTitles;
|
||||
|
@ -40,6 +41,7 @@
|
|||
@property (nonatomic, retain) NSMutableArray *feedTitleList;
|
||||
@property (nonatomic, retain) NSMutableArray *dictFoldersArray;
|
||||
@property (nonatomic, retain) NSDictionary *dictFolders;
|
||||
@property (nonatomic, retain) NSDictionary *dictFeeds;
|
||||
@property (nonatomic, retain) NSMutableData *responseData;
|
||||
|
||||
@end
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
@synthesize feedTitleList;
|
||||
@synthesize dictFolders;
|
||||
@synthesize dictFeeds;
|
||||
@synthesize dictFoldersArray;
|
||||
|
||||
#pragma mark -
|
||||
|
@ -38,6 +39,7 @@
|
|||
- (void)viewDidLoad {
|
||||
self.feedTitleList = [[NSMutableArray alloc] init];
|
||||
self.dictFolders = [[NSDictionary alloc] init];
|
||||
self.dictFeeds = [[NSDictionary alloc] init];
|
||||
self.dictFoldersArray = [[NSMutableArray alloc] init];
|
||||
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStylePlain target:self action:@selector(doLogoutButton)];
|
||||
[appDelegate showNavigationBar:NO];
|
||||
|
@ -84,6 +86,7 @@
|
|||
- (void)dealloc {
|
||||
[feedTitleList release];
|
||||
[dictFolders release];
|
||||
[dictFeeds release];
|
||||
[dictFoldersArray release];
|
||||
[appDelegate release];
|
||||
[super dealloc];
|
||||
|
@ -129,6 +132,7 @@
|
|||
appDelegate.activeUsername = [results objectForKey:@"user"];
|
||||
[appDelegate setTitle:[results objectForKey:@"user"]];
|
||||
self.dictFolders = [results objectForKey:@"flat_folders"];
|
||||
self.dictFeeds = [results objectForKey:@"feeds"];
|
||||
//NSLog(@"Received Feeds: %@", dictFolders);
|
||||
NSSortDescriptor *sortDescriptor;
|
||||
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"feed_title"
|
||||
|
@ -139,19 +143,21 @@
|
|||
|
||||
for (id f in self.dictFolders) {
|
||||
[self.dictFoldersArray addObject:f];
|
||||
|
||||
sortedArray = [[self.dictFolders objectForKey:f] sortedArrayUsingDescriptors:sortDescriptors];
|
||||
[sortedFolders setValue:sortedArray forKey:f];
|
||||
// NSArray *folder = [self.dictFolders objectForKey:f];
|
||||
// NSLog(@"F: %@", f);
|
||||
// NSLog(@"F: %@", folder);
|
||||
// NSLog(@"F: %@", sortDescriptors);
|
||||
// sortedArray = [folder sortedArrayUsingDescriptors:sortDescriptors];
|
||||
// [sortedFolders setValue:sortedArray forKey:f];
|
||||
}
|
||||
|
||||
self.dictFolders = sortedFolders;
|
||||
// self.dictFolders = sortedFolders;
|
||||
[self.dictFoldersArray sortUsingSelector:@selector(caseInsensitiveCompare:)];
|
||||
|
||||
[[self viewTableFeedTitles] reloadData];
|
||||
|
||||
[sortedFolders release];
|
||||
[results release];
|
||||
[jsonString release];
|
||||
}
|
||||
[jsonString release];
|
||||
}
|
||||
|
@ -219,8 +225,9 @@
|
|||
// NSLog(@"Cell: %i: %@", section_index, f);
|
||||
if (section_index == indexPath.section) {
|
||||
NSArray *feeds = [self.dictFolders objectForKey:f];
|
||||
// NSLog(@"Cell: %i: %@: %@", section_index, f, [feeds objectAtIndex:indexPath.row]);
|
||||
cell.textLabel.text = [[feeds objectAtIndex:indexPath.row]
|
||||
id feed_id = [feeds objectAtIndex:indexPath.row];
|
||||
NSString *feed_id_str = [NSString stringWithFormat:@"%@",feed_id];
|
||||
cell.textLabel.text = [[self.dictFeeds objectForKey:feed_id_str]
|
||||
objectForKey:@"feed_title"];
|
||||
return cell;
|
||||
}
|
||||
|
@ -233,10 +240,13 @@
|
|||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
int section_index = 0;
|
||||
for (id f in self.dictFoldersArray) {
|
||||
// NSLog(@"Cell: %i: %@", section_index, f);
|
||||
//NSLog(@"Cell: %i: %@", section_index, f);
|
||||
if (section_index == indexPath.section) {
|
||||
NSArray *feeds = [[NSArray alloc] initWithArray:[self.dictFolders objectForKey:f]];
|
||||
[appDelegate setActiveFeed:[feeds objectAtIndex:indexPath.row]];
|
||||
id feed_id = [feeds objectAtIndex:indexPath.row];
|
||||
NSString *feed_id_str = [NSString stringWithFormat:@"%@",feed_id];
|
||||
[appDelegate setActiveFeed:[self.dictFeeds
|
||||
objectForKey:feed_id_str]];
|
||||
[feeds release];
|
||||
//NSLog(@"Active feed: %@", [appDelegate activeFeed]);
|
||||
break;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<UIScrollViewDelegate> {
|
||||
NewsBlurAppDelegate *appDelegate;
|
||||
|
||||
UIScrollView *scrollView;
|
||||
UIWebView *webView;
|
||||
UIToolbar *toolbar;
|
||||
UIBarButtonItem *buttonPrevious;
|
||||
|
@ -22,7 +21,6 @@
|
|||
}
|
||||
|
||||
@property (nonatomic, retain) IBOutlet UIWebView *webView;
|
||||
@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
|
||||
@property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
|
||||
@property (nonatomic, retain) IBOutlet UIBarButtonItem *buttonPrevious;
|
||||
@property (nonatomic, retain) IBOutlet UIBarButtonItem *buttonNext;
|
||||
|
@ -32,5 +30,7 @@
|
|||
- (void)showStory;
|
||||
- (void)showOriginalSubview:(id)sender;
|
||||
- (void)resizeWebView;
|
||||
- (IBAction)doNextUnreadStory;
|
||||
- (IBAction)doPreviousStory;
|
||||
|
||||
@end
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
@synthesize appDelegate;
|
||||
@synthesize webView;
|
||||
@synthesize scrollView;
|
||||
@synthesize toolbar;
|
||||
@synthesize buttonNext;
|
||||
@synthesize buttonPrevious;
|
||||
|
@ -52,11 +51,11 @@
|
|||
|
||||
NSString *urlString = @"http://nb.local.host:8000/reader/mark_story_as_read";
|
||||
NSURL *url = [NSURL URLWithString:urlString];
|
||||
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
|
||||
[request setPostValue:[appDelegate.activeStory objectForKey:@"id"] forKey:@"story_id"];
|
||||
[request setPostValue:[appDelegate.activeFeed objectForKey:@"id"] forKey:@"feed_id"];
|
||||
[request setDelegate:self];
|
||||
[request startAsynchronous];
|
||||
// ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
|
||||
// [request setPostValue:[appDelegate.activeStory objectForKey:@"id"] forKey:@"story_id"];
|
||||
// [request setPostValue:[appDelegate.activeFeed objectForKey:@"id"] forKey:@"feed_id"];
|
||||
// [request setDelegate:self];
|
||||
// [request startAsynchronous];
|
||||
}
|
||||
|
||||
|
||||
|
@ -78,7 +77,7 @@
|
|||
|
||||
|
||||
- (void)showStory {
|
||||
NSLog(@"Loaded Story view: %@", [appDelegate.activeStory objectForKey:@"story_title"]);
|
||||
// NSLog(@"Loaded Story view: %@", appDelegate.activeStory);
|
||||
NSString *imgCssString = [NSString stringWithFormat:@"<style>"
|
||||
"body {"
|
||||
" line-height: 18px;"
|
||||
|
@ -103,16 +102,75 @@
|
|||
" font-weight: bold;"
|
||||
" background-color: #E0E0E0;"
|
||||
" border-bottom: 1px solid #A0A0A0;"
|
||||
" padding: 12px 12px;"
|
||||
" padding: 12px 12px 8px;"
|
||||
" text-shadow: 1px 1px 0 #EFEFEF;"
|
||||
"}"
|
||||
".NB-story {"
|
||||
" margin: 12px;"
|
||||
"}"
|
||||
".NB-story-author {"
|
||||
" color: #969696;"
|
||||
" font-size: 10px;"
|
||||
" text-transform: uppercase;"
|
||||
" margin: 0 16px 4px 0;"
|
||||
" text-shadow: 0 1px 0 #F9F9F9;"
|
||||
" float: left;"
|
||||
"}"
|
||||
".NB-story-tags {"
|
||||
" clear: both;"
|
||||
" overflow: hidden;"
|
||||
" line-height: 12px;"
|
||||
" height: 14px;"
|
||||
" margin: 6px 0 0 0;"
|
||||
" text-transform: uppercase;"
|
||||
"}"
|
||||
".NB-story-tag {"
|
||||
" float: left;"
|
||||
" font-weight: normal;"
|
||||
" font-size: 9px;"
|
||||
" padding: 0px 4px 0px;"
|
||||
" margin: 0 4px 2px 0;"
|
||||
" background-color: #C6CBC3;"
|
||||
" color: #505050;"
|
||||
" text-shadow: 0 1px 0 #E7E7E7;"
|
||||
" border-radius: 4px;"
|
||||
" -moz-border-radius: 4px;"
|
||||
" -webkit-border-radius: 4px;"
|
||||
"}"
|
||||
".NB-story-date {"
|
||||
" float: right;"
|
||||
" font-size: 11px;"
|
||||
" color: #252D6C;"
|
||||
"}"
|
||||
".NB-story-title {"
|
||||
" clear: left;"
|
||||
"}"
|
||||
"</style>"];
|
||||
NSString *story_author = @"";
|
||||
if ([appDelegate.activeStory objectForKey:@"story_authors"]) {
|
||||
NSString *author = [NSString stringWithFormat:@"%@",[appDelegate.activeStory objectForKey:@"story_authors"]];
|
||||
if (author && ![author isEqualToString:@"<null>"]) {
|
||||
story_author = [NSString stringWithFormat:@"<div class=\"NB-story-author\">%@</div>",author];
|
||||
}
|
||||
}
|
||||
NSString *story_tags = @"";
|
||||
if ([appDelegate.activeStory objectForKey:@"story_tags"]) {
|
||||
NSArray *tag_array = [appDelegate.activeStory objectForKey:@"story_tags"];
|
||||
if ([tag_array count] > 0) {
|
||||
story_tags = [NSString stringWithFormat:@"<div class=\"NB-story-tags\"><div class=\"NB-story-tag\">%@</div></div>",
|
||||
[tag_array componentsJoinedByString:@"</div><div class=\"NB-story-tag\">"]];
|
||||
}
|
||||
}
|
||||
NSString *storyHeader = [NSString stringWithFormat:@"<div class=\"NB-header\">"
|
||||
"<div class=\"NB-story-date\">%@</div>"
|
||||
"%@"
|
||||
"</div>", [appDelegate.activeStory objectForKey:@"story_title"]];
|
||||
"<div class=\"NB-story-title\">%@</div>"
|
||||
"%@"
|
||||
"</div>",
|
||||
[story_tags length] ? [appDelegate.activeStory objectForKey:@"long_parsed_date"] : [appDelegate.activeStory objectForKey:@"short_parsed_date"],
|
||||
story_author,
|
||||
[appDelegate.activeStory objectForKey:@"story_title"],
|
||||
story_tags];
|
||||
NSString *htmlString = [NSString stringWithFormat:@"%@ %@ <div class=\"NB-story\">%@</div>",
|
||||
imgCssString, storyHeader,
|
||||
[appDelegate.activeStory objectForKey:@"story_content"]];
|
||||
|
@ -123,6 +181,38 @@
|
|||
|
||||
}
|
||||
|
||||
- (IBAction)doNextUnreadStory {
|
||||
int nextIndex = [appDelegate indexOfNextStory];
|
||||
if (nextIndex == -1) {
|
||||
|
||||
} else {
|
||||
[appDelegate setActiveStory:[[appDelegate activeFeedStories] objectAtIndex:nextIndex]];
|
||||
[self showStory];
|
||||
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:.5];
|
||||
[UIView setAnimationBeginsFromCurrentState:NO];
|
||||
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:NO];
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)doPreviousStory {
|
||||
NSInteger nextIndex = [appDelegate indexOfPreviousStory];
|
||||
if (nextIndex == -1) {
|
||||
|
||||
} else {
|
||||
[appDelegate setActiveStory:[[appDelegate activeFeedStories] objectAtIndex:nextIndex]];
|
||||
[self showStory];
|
||||
|
||||
[UIView beginAnimations:nil context:nil];
|
||||
[UIView setAnimationDuration:.5];
|
||||
[UIView setAnimationBeginsFromCurrentState:NO];
|
||||
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:NO];
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showOriginalSubview:(id)sender {
|
||||
NSURL *url = [NSURL URLWithString:[appDelegate.activeStory
|
||||
objectForKey:@"story_permalink"]];
|
||||
|
@ -157,29 +247,11 @@
|
|||
}
|
||||
|
||||
- (void)webViewDidStartLoad:(UIWebView *)webView {
|
||||
[self resizeWebView];
|
||||
}
|
||||
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView {
|
||||
[self resizeWebView];
|
||||
}
|
||||
|
||||
- (void)resizeWebView {
|
||||
|
||||
CGRect frame = webView.frame;
|
||||
frame.size.height = 1;
|
||||
webView.frame = frame;
|
||||
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
|
||||
frame.size = fittingSize;
|
||||
webView.frame = frame;
|
||||
NSLog(@"heights: %f / %f", frame.size.width, frame.size.height, toolbar.frame.size.height);
|
||||
toolbar.frame = CGRectMake(0, webView.frame.size.height, toolbar.frame.size.width, toolbar.frame.size.height);
|
||||
|
||||
webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
scrollView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
|
||||
}
|
||||
|
||||
|
||||
- (void)dealloc {
|
||||
[appDelegate release];
|
||||
[webView release];
|
||||
|
|
|
@ -2,17 +2,22 @@
|
|||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1024</int>
|
||||
<string key="IBDocument.SystemVersion">10J567</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">804</string>
|
||||
<string key="IBDocument.SystemVersion">10J869</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">1305</string>
|
||||
<string key="IBDocument.AppKitVersion">1038.35</string>
|
||||
<string key="IBDocument.HIToolboxVersion">462.00</string>
|
||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">123</string>
|
||||
<string key="NS.object.0">300</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
||||
<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<integer value="14"/>
|
||||
<string>IBUIWebView</string>
|
||||
<string>IBUIBarButtonItem</string>
|
||||
<string>IBUIToolbar</string>
|
||||
<string>IBUIProgressView</string>
|
||||
<string>IBUIView</string>
|
||||
<string>IBProxyObject</string>
|
||||
</object>
|
||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -23,9 +28,7 @@
|
|||
<object class="NSArray" key="dict.sortedKeys" id="0">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -42,67 +45,88 @@
|
|||
<int key="NSvFlags">292</int>
|
||||
<object class="NSMutableArray" key="NSSubviews">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIScrollView" id="55113995">
|
||||
<object class="IBUIWebView" id="506862915">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">268</int>
|
||||
<int key="NSvFlags">274</int>
|
||||
<string key="NSFrameSize">{320, 416}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="155973878"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MSAxIDEAA</bytes>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIDataDetectorTypes">1</int>
|
||||
<bool key="IBUIDetectsPhoneNumbers">YES</bool>
|
||||
</object>
|
||||
<object class="IBUIToolbar" id="155973878">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">266</int>
|
||||
<object class="NSMutableArray" key="NSSubviews">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIWebView" id="279038753">
|
||||
<reference key="NSNextResponder" ref="55113995"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<string key="NSFrameSize">{320, 466}</string>
|
||||
<reference key="NSSuperview" ref="55113995"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MSAxIDEAA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<bool key="IBUIMultipleTouchEnabled">YES</bool>
|
||||
<object class="IBUIProgressView" id="484194819">
|
||||
<reference key="NSNextResponder" ref="155973878"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{111, 17}, {78, 11}}</string>
|
||||
<reference key="NSSuperview" ref="155973878"/>
|
||||
<reference key="NSWindow"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIDataDetectorTypes">15</int>
|
||||
<bool key="IBUIDetectsPhoneNumbers">YES</bool>
|
||||
</object>
|
||||
<object class="IBUIToolbar" id="887718764">
|
||||
<reference key="NSNextResponder" ref="55113995"/>
|
||||
<int key="NSvFlags">298</int>
|
||||
<string key="NSFrame">{{0, 415}, {320, 44}}</string>
|
||||
<reference key="NSSuperview" ref="55113995"/>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<int key="IBUIContentMode">6</int>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<object class="NSMutableArray" key="IBUIItems">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIBarButtonItem" id="809166513">
|
||||
<string key="IBUITitle">Item</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIStyle">1</int>
|
||||
<reference key="IBUIToolbar" ref="887718764"/>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="1040742603">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<reference key="IBUIToolbar" ref="887718764"/>
|
||||
<int key="IBUISystemItemIdentifier">5</int>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="54550830">
|
||||
<string key="IBUITitle">Item</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIStyle">1</int>
|
||||
<reference key="IBUIToolbar" ref="887718764"/>
|
||||
</object>
|
||||
</object>
|
||||
<float key="IBUIProgress">0.5</float>
|
||||
<int key="IBUIProgressViewStyle">1</int>
|
||||
</object>
|
||||
</object>
|
||||
<string key="NSFrameSize">{320, 466}</string>
|
||||
<string key="NSFrame">{{0, 416}, {320, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<bool key="IBUIMultipleTouchEnabled">YES</bool>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="484194819"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<bool key="IBUIDelaysContentTouches">NO</bool>
|
||||
<bool key="IBUICanCancelContentTouches">NO</bool>
|
||||
<object class="NSMutableArray" key="IBUIItems">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBUIBarButtonItem" id="542821156">
|
||||
<string key="IBUITitle">Previous</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIStyle">1</int>
|
||||
<reference key="IBUIToolbar" ref="155973878"/>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="936960182">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<reference key="IBUIToolbar" ref="155973878"/>
|
||||
<int key="IBUISystemItemIdentifier">5</int>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="812131495">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<reference key="IBUICustomView" ref="484194819"/>
|
||||
<reference key="IBUIToolbar" ref="155973878"/>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="284060761">
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<reference key="IBUIToolbar" ref="155973878"/>
|
||||
<int key="IBUISystemItemIdentifier">5</int>
|
||||
</object>
|
||||
<object class="IBUIBarButtonItem" id="1065495688">
|
||||
<string key="IBUITitle">Next unread</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIStyle">1</int>
|
||||
<reference key="IBUIToolbar" ref="155973878"/>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUITintColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4yMjcwMjkxMjggMC4zNjIxMzU3NzY0IDAuNDU2NTIxNzM5MQA</bytes>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<string key="NSFrameSize">{320, 460}</string>
|
||||
<string key="NSFrame">{{0, 20}, {320, 460}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="506862915"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
|
@ -117,69 +141,69 @@
|
|||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<object class="NSMutableArray" key="connectionRecords">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">webView</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="279038753"/>
|
||||
</object>
|
||||
<int key="connectionID">17</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">buttonNext</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="54550830"/>
|
||||
<reference key="destination" ref="1065495688"/>
|
||||
</object>
|
||||
<int key="connectionID">32</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">buttonPrevious</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="809166513"/>
|
||||
</object>
|
||||
<int key="connectionID">33</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="55113995"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">34</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">scrollView</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="55113995"/>
|
||||
</object>
|
||||
<int key="connectionID">35</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="279038753"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">36</int>
|
||||
<int key="connectionID">50</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">toolbar</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="887718764"/>
|
||||
<reference key="destination" ref="155973878"/>
|
||||
</object>
|
||||
<int key="connectionID">37</int>
|
||||
<int key="connectionID">51</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">delegate</string>
|
||||
<reference key="source" ref="506862915"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">52</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">webView</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="506862915"/>
|
||||
</object>
|
||||
<int key="connectionID">54</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">view</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="55113995"/>
|
||||
<reference key="destination" ref="191373211"/>
|
||||
</object>
|
||||
<int key="connectionID">38</int>
|
||||
<int key="connectionID">55</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchOutletConnection" key="connection">
|
||||
<string key="label">buttonPrevious</string>
|
||||
<reference key="source" ref="372490531"/>
|
||||
<reference key="destination" ref="542821156"/>
|
||||
</object>
|
||||
<int key="connectionID">56</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">doPreviousStory</string>
|
||||
<reference key="source" ref="542821156"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">57</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">doNextUnreadStory</string>
|
||||
<reference key="source" ref="1065495688"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
</object>
|
||||
<int key="connectionID">58</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
|
@ -196,7 +220,8 @@
|
|||
<reference key="object" ref="191373211"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="55113995"/>
|
||||
<reference ref="506862915"/>
|
||||
<reference ref="155973878"/>
|
||||
</object>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
|
@ -212,45 +237,56 @@
|
|||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">19</int>
|
||||
<reference key="object" ref="55113995"/>
|
||||
<int key="objectID">39</int>
|
||||
<reference key="object" ref="506862915"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">42</int>
|
||||
<reference key="object" ref="155973878"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="279038753"/>
|
||||
<reference ref="887718764"/>
|
||||
<reference ref="542821156"/>
|
||||
<reference ref="1065495688"/>
|
||||
<reference ref="936960182"/>
|
||||
<reference ref="812131495"/>
|
||||
<reference ref="284060761"/>
|
||||
</object>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">14</int>
|
||||
<reference key="object" ref="279038753"/>
|
||||
<reference key="parent" ref="55113995"/>
|
||||
<int key="objectID">43</int>
|
||||
<reference key="object" ref="542821156"/>
|
||||
<reference key="parent" ref="155973878"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">23</int>
|
||||
<reference key="object" ref="887718764"/>
|
||||
<int key="objectID">44</int>
|
||||
<reference key="object" ref="1065495688"/>
|
||||
<reference key="parent" ref="155973878"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">45</int>
|
||||
<reference key="object" ref="936960182"/>
|
||||
<reference key="parent" ref="155973878"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">47</int>
|
||||
<reference key="object" ref="812131495"/>
|
||||
<object class="NSMutableArray" key="children">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference ref="809166513"/>
|
||||
<reference ref="54550830"/>
|
||||
<reference ref="1040742603"/>
|
||||
<reference ref="484194819"/>
|
||||
</object>
|
||||
<reference key="parent" ref="55113995"/>
|
||||
<reference key="parent" ref="155973878"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">24</int>
|
||||
<reference key="object" ref="809166513"/>
|
||||
<reference key="parent" ref="887718764"/>
|
||||
<int key="objectID">46</int>
|
||||
<reference key="object" ref="484194819"/>
|
||||
<reference key="parent" ref="812131495"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">25</int>
|
||||
<reference key="object" ref="54550830"/>
|
||||
<reference key="parent" ref="887718764"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">26</int>
|
||||
<reference key="object" ref="1040742603"/>
|
||||
<reference key="parent" ref="887718764"/>
|
||||
<int key="objectID">48</int>
|
||||
<reference key="object" ref="284060761"/>
|
||||
<reference key="parent" ref="155973878"/>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -262,15 +298,13 @@
|
|||
<string>-2.CustomClassName</string>
|
||||
<string>1.IBEditorWindowLastContentRect</string>
|
||||
<string>1.IBPluginDependency</string>
|
||||
<string>14.IBPluginDependency</string>
|
||||
<string>14.IBViewBoundsToFrameTransform</string>
|
||||
<string>19.IBPluginDependency</string>
|
||||
<string>19.IBViewBoundsToFrameTransform</string>
|
||||
<string>23.IBPluginDependency</string>
|
||||
<string>23.IBViewBoundsToFrameTransform</string>
|
||||
<string>24.IBPluginDependency</string>
|
||||
<string>25.IBPluginDependency</string>
|
||||
<string>26.IBPluginDependency</string>
|
||||
<string>39.IBPluginDependency</string>
|
||||
<string>42.IBPluginDependency</string>
|
||||
<string>43.IBPluginDependency</string>
|
||||
<string>44.IBPluginDependency</string>
|
||||
<string>45.IBPluginDependency</string>
|
||||
<string>46.IBPluginDependency</string>
|
||||
<string>48.IBPluginDependency</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
|
@ -279,17 +313,9 @@
|
|||
<string>{{751, 380}, {320, 480}}</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<object class="NSAffineTransform">
|
||||
<bytes key="NSTransformStruct">P4AAAL+AAABBoAAAw/IAAA</bytes>
|
||||
</object>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<object class="NSAffineTransform">
|
||||
<bytes key="NSTransformStruct">P4AAAL+AAAAAAAAAw+UAAA</bytes>
|
||||
</object>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<object class="NSAffineTransform">
|
||||
<bytes key="NSTransformStruct">P4AAAL+AAAAAAAAAw8UAAA</bytes>
|
||||
</object>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
|
@ -298,20 +324,16 @@
|
|||
<object class="NSMutableDictionary" key="unlocalizedProperties">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<nil key="activeLocalization"/>
|
||||
<object class="NSMutableDictionary" key="localizations">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<reference key="dict.sortedKeys" ref="0"/>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
</object>
|
||||
<reference key="dict.values" ref="0"/>
|
||||
</object>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">38</int>
|
||||
<int key="maxID">58</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
|
@ -374,7 +396,7 @@
|
|||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Classes/FeedDetailViewController.h</string>
|
||||
<string key="minorKey">./Classes/FeedDetailViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
|
@ -421,7 +443,7 @@
|
|||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Classes/LoginViewController.h</string>
|
||||
<string key="minorKey">./Classes/LoginViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
|
@ -438,23 +460,9 @@
|
|||
<string key="candidateClassName">NewsBlurAppDelegate</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="763602146">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Classes/NewsBlurViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Source/NSObject+SBJSON.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Source/SBJsonWriter.h</string>
|
||||
<string key="minorKey">./Classes/LogoutDelegate.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
|
@ -536,7 +544,7 @@
|
|||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Classes/NewsBlurAppDelegate.h</string>
|
||||
<string key="minorKey">./Classes/NewsBlurAppDelegate.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
|
@ -606,7 +614,10 @@
|
|||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<reference key="sourceIdentifier" ref="763602146"/>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/NewsBlurViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">OriginalStoryViewController</string>
|
||||
|
@ -663,21 +674,42 @@
|
|||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Classes/OriginalStoryViewController.h</string>
|
||||
<string key="minorKey">./Classes/OriginalStoryViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">StoryDetailViewController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<object class="NSMutableDictionary" key="actions">
|
||||
<string key="NS.key.0">showOriginalSubview:</string>
|
||||
<string key="NS.object.0">id</string>
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>doNextUnreadStory</string>
|
||||
<string>doPreviousStory</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>id</string>
|
||||
<string>id</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="actionInfosByName">
|
||||
<string key="NS.key.0">showOriginalSubview:</string>
|
||||
<object class="IBActionInfo" key="NS.object.0">
|
||||
<string key="name">showOriginalSubview:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="NSArray" key="dict.sortedKeys">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<string>doNextUnreadStory</string>
|
||||
<string>doPreviousStory</string>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="dict.values">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">doNextUnreadStory</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo">
|
||||
<string key="name">doPreviousStory</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="outlets">
|
||||
|
@ -687,7 +719,6 @@
|
|||
<string>appDelegate</string>
|
||||
<string>buttonNext</string>
|
||||
<string>buttonPrevious</string>
|
||||
<string>scrollView</string>
|
||||
<string>toolbar</string>
|
||||
<string>webView</string>
|
||||
</object>
|
||||
|
@ -696,7 +727,6 @@
|
|||
<string>NewsBlurAppDelegate</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIBarButtonItem</string>
|
||||
<string>UIScrollView</string>
|
||||
<string>UIToolbar</string>
|
||||
<string>UIWebView</string>
|
||||
</object>
|
||||
|
@ -708,7 +738,6 @@
|
|||
<string>appDelegate</string>
|
||||
<string>buttonNext</string>
|
||||
<string>buttonPrevious</string>
|
||||
<string>scrollView</string>
|
||||
<string>toolbar</string>
|
||||
<string>webView</string>
|
||||
</object>
|
||||
|
@ -726,10 +755,6 @@
|
|||
<string key="name">buttonPrevious</string>
|
||||
<string key="candidateClassName">UIBarButtonItem</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">scrollView</string>
|
||||
<string key="candidateClassName">UIScrollView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo">
|
||||
<string key="name">toolbar</string>
|
||||
<string key="candidateClassName">UIToolbar</string>
|
||||
|
@ -742,269 +767,7 @@
|
|||
</object>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">Classes/StoryDetailViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
|
||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSError.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">QuartzCore.framework/Headers/CAAnimation.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">QuartzCore.framework/Headers/CALayer.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="354476810">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIBarButtonItem</string>
|
||||
<string key="superclassName">UIBarItem</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIBarButtonItem.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIBarItem</string>
|
||||
<string key="superclassName">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIBarItem.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIControl</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UINavigationController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="963649563">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIResponder</string>
|
||||
<string key="superclassName">NSObject</string>
|
||||
<reference key="sourceIdentifier" ref="354476810"/>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIScrollView</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UISearchBar</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UISearchDisplayController</string>
|
||||
<string key="superclassName">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UISlider</string>
|
||||
<string key="superclassName">UIControl</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UISlider.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UITableView</string>
|
||||
<string key="superclassName">UIScrollView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UITableView.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UITextField</string>
|
||||
<string key="superclassName">UIControl</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="117887094">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIToolbar</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIToolbar.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIView</string>
|
||||
<reference key="sourceIdentifier" ref="117887094"/>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIView</string>
|
||||
<string key="superclassName">UIResponder</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIView.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIViewController</string>
|
||||
<reference key="sourceIdentifier" ref="963649563"/>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIViewController</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIPopoverController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIViewController</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UISplitViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIViewController</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIViewController</string>
|
||||
<string key="superclassName">UIResponder</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIWebView</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIWebView.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">UIWindow</string>
|
||||
<string key="superclassName">UIView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBFrameworkSource</string>
|
||||
<string key="minorKey">UIKit.framework/Headers/UIWindow.h</string>
|
||||
<string key="minorKey">./Classes/StoryDetailViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -1020,8 +783,7 @@
|
|||
<integer value="3000" key="NS.object.0"/>
|
||||
</object>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<string key="IBDocument.LastKnownRelativeProjectPath">../NewsBlur.xcodeproj</string>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<string key="IBCocoaTouchPluginVersion">123</string>
|
||||
<string key="IBCocoaTouchPluginVersion">300</string>
|
||||
</data>
|
||||
</archive>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bucket
|
||||
type = "1"
|
||||
version = "1.0">
|
||||
</Bucket>
|
113
media/js/jquery-1.6.js → media/js/jquery-1.6.1.js
vendored
113
media/js/jquery-1.6.js → media/js/jquery-1.6.1.js
vendored
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* jQuery JavaScript Library v1.6.1pre Live From Git (8bb6e95b66413c484006288691a82c44ba50554e)
|
||||
* jQuery JavaScript Library v1.6.1
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright 2011, John Resig
|
||||
|
@ -11,7 +11,7 @@
|
|||
* Copyright 2011, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date: Sun May 8 01:20:01 UTC 2011
|
||||
* Date: Thu May 12 15:04:36 2011 -0400
|
||||
*/
|
||||
(function( window, undefined ) {
|
||||
|
||||
|
@ -204,7 +204,7 @@ jQuery.fn = jQuery.prototype = {
|
|||
selector: "",
|
||||
|
||||
// The current version of jQuery being used
|
||||
jquery: "1.6.1pre Live From Git (8bb6e95b66413c484006288691a82c44ba50554e)",
|
||||
jquery: "1.6.1",
|
||||
|
||||
// The default length of a jQuery object is 0
|
||||
length: 0,
|
||||
|
@ -1055,7 +1055,7 @@ jQuery.extend({
|
|||
if ( jQuery.isFunction( fn ) ) {
|
||||
deferred[ handler ](function() {
|
||||
returned = fn.apply( this, arguments );
|
||||
if ( jQuery.isFunction( returned.promise ) ) {
|
||||
if ( returned && jQuery.isFunction( returned.promise ) ) {
|
||||
returned.promise().then( newDefer.resolve, newDefer.reject );
|
||||
} else {
|
||||
newDefer[ action ]( returned );
|
||||
|
@ -1137,6 +1137,7 @@ jQuery.extend({
|
|||
jQuery.support = (function() {
|
||||
|
||||
var div = document.createElement( "div" ),
|
||||
documentElement = document.documentElement,
|
||||
all,
|
||||
a,
|
||||
select,
|
||||
|
@ -1284,7 +1285,7 @@ jQuery.support = (function() {
|
|||
body.style[ i ] = bodyStyle[ i ];
|
||||
}
|
||||
body.appendChild( div );
|
||||
document.documentElement.appendChild( body );
|
||||
documentElement.insertBefore( body, documentElement.firstChild );
|
||||
|
||||
// Check if a disconnected checkbox will retain its checked
|
||||
// value of true after appended to the DOM (IE6/7)
|
||||
|
@ -1339,12 +1340,12 @@ jQuery.support = (function() {
|
|||
marginDiv.style.marginRight = "0";
|
||||
div.appendChild( marginDiv );
|
||||
support.reliableMarginRight =
|
||||
( parseInt( document.defaultView.getComputedStyle( marginDiv, null ).marginRight, 10 ) || 0 ) === 0;
|
||||
( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
|
||||
}
|
||||
|
||||
// Remove the body element we added
|
||||
body.innerHTML = "";
|
||||
document.documentElement.removeChild( body );
|
||||
documentElement.removeChild( body );
|
||||
|
||||
// Technique from Juriy Zaytsev
|
||||
// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
|
||||
|
@ -1475,7 +1476,7 @@ jQuery.extend({
|
|||
}
|
||||
|
||||
if ( data !== undefined ) {
|
||||
thisCache[ name ] = data;
|
||||
thisCache[ jQuery.camelCase( name ) ] = data;
|
||||
}
|
||||
|
||||
// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
|
||||
|
@ -1485,7 +1486,7 @@ jQuery.extend({
|
|||
return thisCache[ internalKey ] && thisCache[ internalKey ].events;
|
||||
}
|
||||
|
||||
return getByName ? thisCache[ name ] : thisCache;
|
||||
return getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache;
|
||||
},
|
||||
|
||||
removeData: function( elem, name, pvt /* Internal Use Only */ ) {
|
||||
|
@ -2175,10 +2176,15 @@ jQuery.extend({
|
|||
if ( pass && name in jQuery.attrFn ) {
|
||||
return jQuery( elem )[ name ]( value );
|
||||
}
|
||||
|
||||
|
||||
// Fallback to prop when attributes are not supported
|
||||
if ( !("getAttribute" in elem) ) {
|
||||
return jQuery.prop( elem, name, value );
|
||||
}
|
||||
|
||||
var ret, hooks,
|
||||
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
|
||||
|
||||
|
||||
// Normalize the name if needed
|
||||
name = notxml && jQuery.attrFix[ name ] || name;
|
||||
|
||||
|
@ -2255,7 +2261,7 @@ jQuery.extend({
|
|||
// Setting the type on a radio button after the value resets the value in IE6-9
|
||||
// Reset value to it's default in case type is set after value
|
||||
// This is for element creation
|
||||
var val = elem.getAttribute("value");
|
||||
var val = elem.value;
|
||||
elem.setAttribute( "type", value );
|
||||
if ( val ) {
|
||||
elem.value = val;
|
||||
|
@ -2278,7 +2284,7 @@ jQuery.extend({
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
propFix: {
|
||||
tabindex: "tabIndex",
|
||||
readonly: "readOnly",
|
||||
|
@ -2296,32 +2302,32 @@ jQuery.extend({
|
|||
|
||||
prop: function( elem, name, value ) {
|
||||
var nType = elem.nodeType;
|
||||
|
||||
|
||||
// don't get/set properties on text, comment and attribute nodes
|
||||
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
var ret, hooks,
|
||||
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
|
||||
|
||||
|
||||
// Try to normalize/fix the name
|
||||
name = notxml && jQuery.propFix[ name ] || name;
|
||||
|
||||
hooks = jQuery.propHooks[ name ];
|
||||
|
||||
|
||||
if ( value !== undefined ) {
|
||||
if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
|
||||
return ret;
|
||||
|
||||
|
||||
} else {
|
||||
return (elem[ name ] = value);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
|
||||
return ret;
|
||||
|
||||
|
||||
} else {
|
||||
return elem[ name ];
|
||||
}
|
||||
|
@ -2359,6 +2365,24 @@ boolHook = {
|
|||
}
|
||||
};
|
||||
|
||||
// Use the value property for back compat
|
||||
// Use the formHook for button elements in IE6/7 (#1954)
|
||||
jQuery.attrHooks.value = {
|
||||
get: function( elem, name ) {
|
||||
if ( formHook && jQuery.nodeName( elem, "button" ) ) {
|
||||
return formHook.get( elem, name );
|
||||
}
|
||||
return elem.value;
|
||||
},
|
||||
set: function( elem, value, name ) {
|
||||
if ( formHook && jQuery.nodeName( elem, "button" ) ) {
|
||||
return formHook.set( elem, value, name );
|
||||
}
|
||||
// Does not return so that setAttribute is also used
|
||||
elem.value = value;
|
||||
}
|
||||
};
|
||||
|
||||
// IE6/7 do not support getting/setting some attributes with get/setAttribute
|
||||
if ( !jQuery.support.getSetAttribute ) {
|
||||
|
||||
|
@ -2366,12 +2390,9 @@ if ( !jQuery.support.getSetAttribute ) {
|
|||
jQuery.attrFix = jQuery.propFix;
|
||||
|
||||
// Use this for any attribute on a form in IE6/7
|
||||
formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = {
|
||||
formHook = jQuery.attrHooks.name = jQuery.valHooks.button = {
|
||||
get: function( elem, name ) {
|
||||
var ret;
|
||||
if ( name === "value" && !jQuery.nodeName( elem, "button" ) ) {
|
||||
return elem.getAttribute( name );
|
||||
}
|
||||
ret = elem.getAttributeNode( name );
|
||||
// Return undefined if nodeValue is empty string
|
||||
return ret && ret.nodeValue !== "" ?
|
||||
|
@ -3126,6 +3147,9 @@ var withinElement = function( event ) {
|
|||
// Check if mouse(over|out) are still within the same parent element
|
||||
var parent = event.relatedTarget;
|
||||
|
||||
// set the correct event type
|
||||
event.type = event.data;
|
||||
|
||||
// Firefox sometimes assigns relatedTarget a XUL element
|
||||
// which we cannot access the parentNode property of
|
||||
try {
|
||||
|
@ -3135,15 +3159,13 @@ var withinElement = function( event ) {
|
|||
if ( parent && parent !== document && !parent.parentNode ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Traverse up the tree
|
||||
while ( parent && parent !== this ) {
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
|
||||
if ( parent !== this ) {
|
||||
// set the correct event type
|
||||
event.type = event.data;
|
||||
|
||||
// handle event if we actually just moused on to a non sub-element
|
||||
jQuery.event.handle.apply( this, arguments );
|
||||
}
|
||||
|
@ -4331,7 +4353,8 @@ var Expr = Sizzle.selectors = {
|
|||
},
|
||||
|
||||
reset: function( elem ) {
|
||||
return elem.nodeName.toLowerCase() === "input" && "reset" === elem.type;
|
||||
var name = elem.nodeName.toLowerCase();
|
||||
return (name === "input" || name === "button") && "reset" === elem.type;
|
||||
},
|
||||
|
||||
button: function( elem ) {
|
||||
|
@ -4597,6 +4620,16 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|||
|
||||
} else {
|
||||
sortOrder = function( a, b ) {
|
||||
// The nodes are identical, we can exit early
|
||||
if ( a === b ) {
|
||||
hasDuplicate = true;
|
||||
return 0;
|
||||
|
||||
// Fallback to using sourceIndex (in IE) if it's available on both nodes
|
||||
} else if ( a.sourceIndex && b.sourceIndex ) {
|
||||
return a.sourceIndex - b.sourceIndex;
|
||||
}
|
||||
|
||||
var al, bl,
|
||||
ap = [],
|
||||
bp = [],
|
||||
|
@ -4604,13 +4637,8 @@ if ( document.documentElement.compareDocumentPosition ) {
|
|||
bup = b.parentNode,
|
||||
cur = aup;
|
||||
|
||||
// The nodes are identical, we can exit early
|
||||
if ( a === b ) {
|
||||
hasDuplicate = true;
|
||||
return 0;
|
||||
|
||||
// If the nodes are siblings (or identical) we can do a quick check
|
||||
} else if ( aup === bup ) {
|
||||
if ( aup === bup ) {
|
||||
return siblingCheck( a, b );
|
||||
|
||||
// If no parents were found then the nodes are disconnected
|
||||
|
@ -5434,6 +5462,7 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
|
|||
// checked="checked" or checked
|
||||
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
|
||||
rscriptType = /\/(java|ecma)script/i,
|
||||
rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
|
||||
wrapMap = {
|
||||
option: [ 1, "<select multiple='multiple'>", "</select>" ],
|
||||
legend: [ 1, "<fieldset>", "</fieldset>" ],
|
||||
|
@ -5924,7 +5953,7 @@ jQuery.each({
|
|||
function getAll( elem ) {
|
||||
if ( "getElementsByTagName" in elem ) {
|
||||
return elem.getElementsByTagName( "*" );
|
||||
|
||||
|
||||
} else if ( "querySelectorAll" in elem ) {
|
||||
return elem.querySelectorAll( "*" );
|
||||
|
||||
|
@ -6162,7 +6191,7 @@ function evalScript( i, elem ) {
|
|||
dataType: "script"
|
||||
});
|
||||
} else {
|
||||
jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
|
||||
jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
|
||||
}
|
||||
|
||||
if ( elem.parentNode ) {
|
||||
|
@ -8039,6 +8068,9 @@ jQuery.fn.extend({
|
|||
return this.each( optall.complete, [ false ] );
|
||||
}
|
||||
|
||||
// Do not change referenced properties as per-property easing will be lost
|
||||
prop = jQuery.extend( {}, prop );
|
||||
|
||||
return this[ optall.queue === false ? "each" : "queue" ](function() {
|
||||
// XXX 'this' does not always have a nodeName when running the
|
||||
// test suite
|
||||
|
@ -8071,7 +8103,7 @@ jQuery.fn.extend({
|
|||
// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
|
||||
if ( jQuery.isArray( val ) ) {
|
||||
opt.animatedProperties[ name ] = val[ 1 ];
|
||||
val = val[ 0 ];
|
||||
val = prop[ name ] = val[ 0 ];
|
||||
} else {
|
||||
opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
|
||||
}
|
||||
|
@ -8168,7 +8200,6 @@ jQuery.fn.extend({
|
|||
if ( !gotoEnd ) {
|
||||
jQuery._unmark( true, this );
|
||||
}
|
||||
// go in reverse order so anything added to the queue during the loop is ignored
|
||||
while ( i-- ) {
|
||||
if ( timers[i].elem === this ) {
|
||||
if (gotoEnd) {
|
||||
|
@ -8432,11 +8463,9 @@ jQuery.fx.prototype = {
|
|||
|
||||
jQuery.extend( jQuery.fx, {
|
||||
tick: function() {
|
||||
var timers = jQuery.timers,
|
||||
i = timers.length;
|
||||
while ( i-- ) {
|
||||
for ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {
|
||||
if ( !timers[i]() ) {
|
||||
timers.splice(i, 1);
|
||||
timers.splice(i--, 1);
|
||||
}
|
||||
}
|
||||
|
5626
media/js/mobile/jquery.mobile-1.0b1.js
Normal file
5626
media/js/mobile/jquery.mobile-1.0b1.js
Normal file
File diff suppressed because it is too large
Load diff
365
media/js/mobile/newsblur/mobile_workspace.js
Normal file
365
media/js/mobile/newsblur/mobile_workspace.js
Normal file
|
@ -0,0 +1,365 @@
|
|||
(function($) {
|
||||
|
||||
NEWSBLUR.MobileReader = function() {
|
||||
|
||||
// ===========
|
||||
// = Globals =
|
||||
// ===========
|
||||
|
||||
this.model = NEWSBLUR.AssetModel.reader();
|
||||
this.story_view = 'page';
|
||||
this.pages = {
|
||||
'feeds' : $('#NB-page-feeds'),
|
||||
'stories' : $('#NB-page-stories'),
|
||||
'story' : $('#NB-page-story')
|
||||
};
|
||||
this.$s = {
|
||||
$body: $('body'),
|
||||
$feed_list: $('#NB-feed-list'),
|
||||
$story_list: $('#NB-story-list'),
|
||||
$story_detail: $('#NB-story-detail')
|
||||
};
|
||||
this.flags = {
|
||||
'feeds_loaded' : false,
|
||||
'active_view' : null
|
||||
};
|
||||
this.locks = {};
|
||||
this.counts = {};
|
||||
this.cache = {};
|
||||
this.constants = {};
|
||||
|
||||
$(document).bind('mobileinit', function() {
|
||||
$.mobile.ajaxEnabled = false;
|
||||
});
|
||||
|
||||
this.runner();
|
||||
};
|
||||
|
||||
NEWSBLUR.MobileReader.prototype = {
|
||||
|
||||
runner: function() {
|
||||
this.load_feeds();
|
||||
this.bind_clicks();
|
||||
this.bind_scroll();
|
||||
},
|
||||
|
||||
// =============
|
||||
// = Feed List =
|
||||
// =============
|
||||
|
||||
load_feeds: function() {
|
||||
this.flags.active_view = 'feeds';
|
||||
$.mobile.showPageLoadingMsg();
|
||||
|
||||
this.pages.feeds.unbind('pagebeforeshow').bind('pagebeforeshow', _.bind(function(e) {
|
||||
$('ul', this.$s.$feed_list).listview('refresh');
|
||||
}, this));
|
||||
this.pages.feeds.unbind('pageshow').bind('pageshow', _.bind(function(e) {
|
||||
$('ul', this.$s.$story_list).remove();
|
||||
}, this));
|
||||
this.model.load_feeds_flat($.rescope(this.build_feed_list, this));
|
||||
},
|
||||
|
||||
build_feed_list: function() {
|
||||
this.flags.active_view = 'feeds';
|
||||
var self = this;
|
||||
var folders = this.model.folders;
|
||||
var feeds = this.model.feeds;
|
||||
var $feed_list = this.$s.$feed_list;
|
||||
var $feeds = '';
|
||||
_.each(folders, function(items, folder_name) {
|
||||
$feeds += '<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">';
|
||||
if (folder_name && folder_name != ' ') {
|
||||
$feeds += _.template('\
|
||||
<li data-role="list-divider"><%= folder_name %></li>', {
|
||||
folder_name : folder_name
|
||||
});
|
||||
}
|
||||
_.each(items, function(item) {
|
||||
$feeds += self.make_feed_title(item);
|
||||
});
|
||||
$feeds += '</ul>';
|
||||
});
|
||||
|
||||
this.flags.feeds_loaded = true;
|
||||
$feed_list.html($feeds);
|
||||
$('ul', $feed_list).listview();
|
||||
$.mobile.hidePageLoadingMsg();
|
||||
},
|
||||
|
||||
make_feed_title: function(feed_id) {
|
||||
var feed = this.model.get_feed(feed_id);
|
||||
var unread_class = '';
|
||||
var exception_class = '';
|
||||
if (feed.ps) unread_class += ' unread_positive';
|
||||
if (feed.nt) unread_class += ' unread_neutral';
|
||||
if (feed.ng) unread_class += ' unread_negative';
|
||||
if (!feed.active) exception_class += ' NB-feed-inactive';
|
||||
if (feed.has_exception && feed.exception_type == 'feed') {
|
||||
exception_class += ' NB-feed-exception';
|
||||
}
|
||||
if (feed.not_yet_fetched && !feed.has_exception) {
|
||||
exception_class += ' NB-feed-unfetched';
|
||||
}
|
||||
|
||||
var $feed = _.template('\
|
||||
<li class="<%= unread_class %> <%= exception_class %>">\
|
||||
<a href="#" data-feed-id="<%= feed.id %>">\
|
||||
<% if (feed.ps) { %>\
|
||||
<span class="ui-li-count ui-li-count-positive"><%= feed.ps %></span>\
|
||||
<% } %>\
|
||||
<% if (feed.nt) { %>\
|
||||
<span class="ui-li-count ui-li-count-neutral"><%= feed.nt %></span>\
|
||||
<% } %>\
|
||||
<% if (feed.ng) { %>\
|
||||
<span class="ui-li-count ui-li-count-negative"><%= feed.ng %></span>\
|
||||
<% } %>\
|
||||
<img src="<%= $.favicon(feed.favicon) %>" class="ui-li-icon">\
|
||||
<%= feed.feed_title %>\
|
||||
</a>\
|
||||
</li>', {
|
||||
feed : feed,
|
||||
unread_class : unread_class,
|
||||
exception_class : exception_class
|
||||
});
|
||||
return $feed;
|
||||
},
|
||||
|
||||
// ===========
|
||||
// = Stories =
|
||||
// ===========
|
||||
|
||||
reset_feed: function() {
|
||||
this.page = 1;
|
||||
},
|
||||
|
||||
load_stories: function(feed_id) {
|
||||
this.flags.active_view = 'stories';
|
||||
$.mobile.showPageLoadingMsg();
|
||||
this.active_feed = feed_id;
|
||||
this.model.load_feed(feed_id, this.page, this.page == 1, _.bind(this.build_stories, this));
|
||||
},
|
||||
|
||||
build_stories: function(data, first_load) {
|
||||
this.flags.active_view = 'stories';
|
||||
var self = this;
|
||||
var $story_list = this.$s.$story_list;
|
||||
var $stories = "";
|
||||
var feed_id = data.feed_id;
|
||||
|
||||
if (this.active_feed != feed_id) return;
|
||||
|
||||
_.each(data.stories, function(story) {
|
||||
$stories += self.make_story_title(story);
|
||||
});
|
||||
if (first_load) {
|
||||
$stories = '<ul data-role="listview" data-inset="false" data-theme="c" data-dividertheme="b">' +
|
||||
$stories +
|
||||
'</ul>';
|
||||
$story_list.html($stories);
|
||||
} else {
|
||||
$('ul', $story_list).append($stories);
|
||||
$('ul', $story_list).listview('refresh');
|
||||
}
|
||||
|
||||
$('ul', $story_list).listview();
|
||||
$.mobile.hidePageLoadingMsg();
|
||||
},
|
||||
|
||||
load_next_page_of_stories: function() {
|
||||
this.page += 1;
|
||||
this.load_stories(this.active_feed);
|
||||
},
|
||||
|
||||
make_story_title: function(story) {
|
||||
var feed = this.model.get_feed(this.active_feed);
|
||||
var score_color = this.story_color(story);
|
||||
|
||||
return _.template('<li class="NB-story <%= story.read_status?"NB-read":"" %> NB-score-<%= score_color %>">\
|
||||
<div class="ui-li-icon NB-icon-score"></div>\
|
||||
<a href="#" data-story-id="<%= story.id %>">\
|
||||
<div class="NB-story-date"><%= story.long_parsed_date %></div>\
|
||||
<% if (story.story_authors) { %>\
|
||||
<div class="NB-story-author"><%= story.story_authors %></div>\
|
||||
<% } %>\
|
||||
<% if (story.story_tags && story.story_tags.length) { %>\
|
||||
<div class="NB-story-tags">\
|
||||
<% _.each(story.story_tags, function(tag) { %>\
|
||||
<div class="NB-story-tag"><%= tag %></div>\
|
||||
<% }); %>\
|
||||
</div>\
|
||||
<% } %>\
|
||||
<div class="NB-story-title"><%= story.story_title %></div>\
|
||||
<div class="NB-story-feed">\
|
||||
<div class="NB-story-feed-icon"><img src="<%= $.favicon(feed.favicon) %>"></div>\
|
||||
<div class="NB-story-feed-title"><%= feed.feed_title %></div>\
|
||||
</div>\
|
||||
</a>\
|
||||
</li>', {
|
||||
story : story,
|
||||
feed : feed,
|
||||
score_color : score_color
|
||||
});
|
||||
},
|
||||
|
||||
scroll_story_list: function() {
|
||||
var window_height = $(window).height();
|
||||
var window_offset = $(window).scrollTop();
|
||||
var story_list_height = this.pages.stories.height();
|
||||
var fudge_factor = 18;
|
||||
|
||||
if (window_height + window_offset > story_list_height - fudge_factor) {
|
||||
this.load_next_page_of_stories();
|
||||
}
|
||||
},
|
||||
|
||||
// ================
|
||||
// = Story Detail =
|
||||
// ================
|
||||
|
||||
load_story_detail: function(story_id) {
|
||||
this.flags.active_view = 'story_detail';
|
||||
$.mobile.showPageLoadingMsg();
|
||||
|
||||
var $story_detail_view = this.$s.$story_detail;
|
||||
var story = this.model.get_story(story_id);
|
||||
var score_color = this.story_color(story);
|
||||
var $story = this.make_story_detail(story);
|
||||
|
||||
this.colorize_story_title(story);
|
||||
$('.ul-li-right', this.pages.story).jqmData('icon', 'NB-'+score_color);
|
||||
$story_detail_view.html($story);
|
||||
$.mobile.hidePageLoadingMsg();
|
||||
this.mark_story_as_read(story);
|
||||
},
|
||||
|
||||
make_story_detail: function(story) {
|
||||
var feed = this.model.get_feed(this.active_feed);
|
||||
var score_color = this.story_color(story);
|
||||
|
||||
var $story = _.template('<div class="NB-story <%= story.read_status?"NB-read":"" %> NB-score-<%= score_color %>">\
|
||||
<div class="NB-story-header">\
|
||||
<div class="NB-story-header-feed-gradient"></div>\
|
||||
<div class="ui-li-icon NB-icon-score"></div>\
|
||||
<div class="NB-story-date"><%= story.long_parsed_date %></div>\
|
||||
<% if (story.story_authors) { %>\
|
||||
<div class="NB-story-author"><%= story.story_authors %></div>\
|
||||
<% } %>\
|
||||
<% if (story.story_tags && story.story_tags.length) { %>\
|
||||
<div class="NB-story-tags">\
|
||||
<% _.each(story.story_tags, function(tag) { %>\
|
||||
<div class="NB-story-tag"><%= tag %></div>\
|
||||
<% }); %>\
|
||||
</div>\
|
||||
<% } %>\
|
||||
<a href="<%= story.story_permalink %>" data-story-id="<%= story.id %>">\
|
||||
<div class="NB-story-title"><%= story.story_title %></div>\
|
||||
</a>\
|
||||
</div>\
|
||||
<div class="NB-story-content"><%= story.story_content %></div>\
|
||||
</div>', {
|
||||
story : story,
|
||||
feed : feed,
|
||||
score_color : score_color
|
||||
});
|
||||
|
||||
return $story;
|
||||
},
|
||||
|
||||
colorize_story_title: function() {
|
||||
var feed = this.model.get_feed(this.active_feed);
|
||||
$('.ui-header', this.pages.story)
|
||||
.css('background-image', NEWSBLUR.utils.generate_gradient(feed, 'webkit'))
|
||||
.css('background-image', NEWSBLUR.utils.generate_gradient(feed, 'moz'))
|
||||
.css('borderBottom', NEWSBLUR.utils.generate_gradient(feed, 'border'))
|
||||
.css('borderTop', NEWSBLUR.utils.generate_gradient(feed, 'border'))
|
||||
.toggleClass('NB-inverse', NEWSBLUR.utils.is_feed_floater_gradient_light(feed));
|
||||
|
||||
var $feed = _.template('<div class="NB-story-feed-header">\
|
||||
<img class="NB-favicon" src="<%= $.favicon(feed.favicon) %>" />\
|
||||
<span class="feed_title">\
|
||||
<%= feed.feed_title %>\
|
||||
</span>\
|
||||
</div>', {
|
||||
feed : feed
|
||||
});
|
||||
|
||||
$('.ui-title', this.pages.story).html($feed);
|
||||
},
|
||||
|
||||
// =====================
|
||||
// = General Utilities =
|
||||
// =====================
|
||||
|
||||
story_color: function(story) {
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
var score_color = 'neutral';
|
||||
if (score > 0) score_color = 'positive';
|
||||
if (score < 0) score_color = 'negative';
|
||||
|
||||
return score_color;
|
||||
},
|
||||
|
||||
mark_story_as_read: function(story) {
|
||||
var story_id = story.id;
|
||||
var feed_id = story.story_feed_id;
|
||||
|
||||
this.model.mark_story_as_read(story_id, feed_id, _.bind(function(read) {
|
||||
this.update_read_count(story_id, feed_id);
|
||||
}, this));
|
||||
},
|
||||
|
||||
update_read_count: function(story_id, feed_id) {
|
||||
|
||||
},
|
||||
|
||||
// ==========
|
||||
// = Events =
|
||||
// ==========
|
||||
|
||||
bind_clicks: function() {
|
||||
var self = this;
|
||||
|
||||
this.$s.$feed_list.delegate('li a', 'tap', function(e) {
|
||||
e.preventDefault();
|
||||
var feed_id = $(e.currentTarget).jqmData('feed-id');
|
||||
$.mobile.changePage(self.pages.stories);
|
||||
self.reset_feed();
|
||||
self.load_stories(feed_id);
|
||||
});
|
||||
|
||||
this.$s.$story_list.delegate('li a', 'tap', function(e) {
|
||||
e.preventDefault();
|
||||
var story_id = $(e.currentTarget).jqmData('story-id');
|
||||
$.mobile.showPageLoadingMsg();
|
||||
$.mobile.changePage(self.pages.story);
|
||||
self.load_story_detail(story_id);
|
||||
});
|
||||
|
||||
this.$s.$story_detail.delegate('li a', 'tap', function(e) {
|
||||
e.preventDefault();
|
||||
var story_id = $(e.currentTarget).jqmData('story-id');
|
||||
$.mobile.showPageLoadingMsg();
|
||||
$.mobile.changePage(self.pages.story);
|
||||
self.load_story_detail(story_id);
|
||||
});
|
||||
|
||||
this.pages.story.delegate('.NB-next', 'tap', function(e) {
|
||||
|
||||
});
|
||||
|
||||
this.pages.story.delegate('.NB-previous', 'tap', function(e) {
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
bind_scroll: function() {
|
||||
$(window).bind('scroll', _.throttle(_.bind(function(e) {
|
||||
if (this.flags.active_view == 'stories') {
|
||||
this.scroll_story_list();
|
||||
}
|
||||
}, this), 500));
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
|
@ -230,6 +230,46 @@ NEWSBLUR.AssetModel.Reader.prototype = {
|
|||
this.make_request('/reader/feeds', data, pre_callback, error_callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
load_feeds_flat: function(callback, error_callback) {
|
||||
var self = this;
|
||||
var data = {
|
||||
flat: true,
|
||||
include_favicons: true
|
||||
};
|
||||
|
||||
var pre_callback = function(subscriptions) {
|
||||
// NEWSBLUR.log(['subscriptions', subscriptions.flat_folders]);
|
||||
var flat_feeds = function(feeds) {
|
||||
var flattened = _.flatten(_.map(feeds, _.values));
|
||||
return _.flatten(_.map(flattened, function(feed) {
|
||||
if (!_.isNumber(feed) && feed) return flat_feeds(feed);
|
||||
else return feed;
|
||||
}));
|
||||
};
|
||||
var valid_feeds = flat_feeds({'root': subscriptions.flat_folders});
|
||||
|
||||
_.each(subscriptions.feeds, function(feed, feed_id) {
|
||||
if (_.contains(valid_feeds, parseInt(feed_id, 10))) {
|
||||
self.feeds[feed_id] = feed;
|
||||
if (feed.favicon_fetching) self.flags['favicons_fetching'] = true;
|
||||
}
|
||||
});
|
||||
self.folders = subscriptions.flat_folders;
|
||||
self.starred_count = subscriptions.starred_count;
|
||||
|
||||
if (!_.isEqual(self.favicons, {})) {
|
||||
_.each(self.feeds, function(feed) {
|
||||
if (self.favicons[feed.id]) {
|
||||
feed.favicon = self.favicons[feed.id];
|
||||
}
|
||||
});
|
||||
}
|
||||
callback();
|
||||
};
|
||||
|
||||
this.make_request('/reader/feeds', data, pre_callback, error_callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
load_feed_favicons: function(callback, loaded_once, load_all) {
|
||||
var pre_callback = _.bind(function(favicons) {
|
||||
this.favicons = favicons;
|
||||
|
@ -685,13 +725,29 @@ NEWSBLUR.AssetModel.Reader.prototype = {
|
|||
this.make_request('/reader/features', {'page': page}, callback, callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
load_recommended_feed: function(page, refresh, callback, error_callback) {
|
||||
load_recommended_feed: function(page, refresh, unmoderated, callback, error_callback) {
|
||||
this.make_request('/recommendations/load_recommended_feed', {
|
||||
'page': page,
|
||||
'refresh': refresh
|
||||
'page' : page,
|
||||
'refresh' : refresh,
|
||||
'unmoderated' : unmoderated
|
||||
}, callback, error_callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
approve_feed_in_moderation_queue: function(feed_id, date, callback) {
|
||||
this.make_request('/recommendations/approve_feed', {
|
||||
'feed_id' : feed_id,
|
||||
'date' : date,
|
||||
'unmoderated' : true
|
||||
}, callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
decline_feed_in_moderation_queue: function(feed_id, callback) {
|
||||
this.make_request('/recommendations/decline_feed', {
|
||||
'feed_id' : feed_id,
|
||||
'unmoderated' : true
|
||||
}, callback, {request_type: 'GET'});
|
||||
},
|
||||
|
||||
load_dashboard_graphs: function(callback, error_callback) {
|
||||
this.make_request('/statistics/dashboard_graphs', {}, callback, error_callback, {request_type: 'GET'});
|
||||
},
|
||||
|
|
|
@ -367,6 +367,10 @@
|
|||
},
|
||||
|
||||
find_feed_in_feed_list: function(feed_id) {
|
||||
if (_.contains(this.cache.$feed_in_feed_list, feed_id)) {
|
||||
return this.cache.$feed_in_feed_list[feed_id];
|
||||
}
|
||||
|
||||
var $feed_list = this.$s.$feed_list;
|
||||
var $feeds = $([]);
|
||||
|
||||
|
@ -376,6 +380,8 @@
|
|||
}
|
||||
});
|
||||
|
||||
this.cache.$feed_in_feed_list[feed_id] = $feeds;
|
||||
|
||||
return $feeds;
|
||||
},
|
||||
|
||||
|
@ -1583,56 +1589,56 @@
|
|||
this.active_feed = data.feed_id;
|
||||
}
|
||||
|
||||
if (this.active_feed == feed_id) {
|
||||
// NEWSBLUR.log(['post_open_feed', data.stories, this.flags]);
|
||||
this.flags['opening_feed'] = false;
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
this.story_titles_clear_loading_endbar();
|
||||
this.create_story_titles(stories);
|
||||
this.make_story_feed_entries(stories, first_load);
|
||||
this.show_feed_hidden_story_title_indicator(true);
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
this.fill_out_story_titles();
|
||||
$('.NB-feedbar-last-updated-date').text(data.last_update + ' ago');
|
||||
if (this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
this.show_next_unread_story(true);
|
||||
}
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
if (!first_load) {
|
||||
var stories_count = this.cache['iframe_story_positions_keys'].length;
|
||||
this.flags.iframe_story_locations_fetched = false;
|
||||
var $iframe = this.$s.$feed_iframe.contents();
|
||||
this.fetch_story_locations_in_story_frame(stories_count, false, $iframe);
|
||||
if (this.story_view == 'feed') {
|
||||
this.prefetch_story_locations_in_feed_view();
|
||||
}
|
||||
} else {
|
||||
if (this.story_view == 'page') {
|
||||
if (this.flags['iframe_view_loaded']) {
|
||||
// NEWSBLUR.log(['Titles loaded, iframe loaded']);
|
||||
var $iframe = this.$s.$feed_iframe.contents();
|
||||
this.fetch_story_locations_in_story_frame(0, true, $iframe);
|
||||
} else {
|
||||
// NEWSBLUR.log(['Titles loaded, iframe NOT loaded -- prefetching now']);
|
||||
_.delay(_.bind(function() {
|
||||
this.prefetch_story_locations_in_story_frame();
|
||||
}, this), 500);
|
||||
}
|
||||
} else if (this.story_view == 'feed') {
|
||||
this.prefetch_story_locations_in_feed_view();
|
||||
} else if (this.story_view == 'story') {
|
||||
this.show_next_story(1);
|
||||
}
|
||||
}
|
||||
if (this.flags['open_unread_stories_in_tabs']) {
|
||||
_.defer(_.bind(this.open_unread_stories_in_tabs, this));
|
||||
}
|
||||
this.hide_stories_progress_bar();
|
||||
if (this.flags['showing_feed_in_tryfeed_view']) {
|
||||
this.show_tryfeed_add_button();
|
||||
}
|
||||
this.make_content_pane_feed_counter(feed_id);
|
||||
if (this.active_feed != feed_id) return;
|
||||
|
||||
// NEWSBLUR.log(['post_open_feed', data.stories, this.flags]);
|
||||
this.flags['opening_feed'] = false;
|
||||
this.flags['feed_view_positions_calculated'] = false;
|
||||
this.story_titles_clear_loading_endbar();
|
||||
this.create_story_titles(stories);
|
||||
this.make_story_feed_entries(stories, first_load);
|
||||
this.show_feed_hidden_story_title_indicator(true);
|
||||
this.show_story_titles_above_intelligence_level({'animate': false});
|
||||
this.fill_out_story_titles();
|
||||
$('.NB-feedbar-last-updated-date').text(data.last_update + ' ago');
|
||||
if (this.counts['find_next_unread_on_page_of_feed_stories_load']) {
|
||||
this.show_next_unread_story(true);
|
||||
}
|
||||
this.flags['story_titles_loaded'] = true;
|
||||
if (!first_load) {
|
||||
var stories_count = this.cache['iframe_story_positions_keys'].length;
|
||||
this.flags.iframe_story_locations_fetched = false;
|
||||
var $iframe = this.$s.$feed_iframe.contents();
|
||||
this.fetch_story_locations_in_story_frame(stories_count, false, $iframe);
|
||||
if (this.story_view == 'feed' || this.flags['page_view_showing_feed_view']) {
|
||||
this.prefetch_story_locations_in_feed_view();
|
||||
}
|
||||
} else {
|
||||
if (this.story_view == 'page') {
|
||||
if (this.flags['iframe_view_loaded']) {
|
||||
// NEWSBLUR.log(['Titles loaded, iframe loaded']);
|
||||
var $iframe = this.$s.$feed_iframe.contents();
|
||||
this.fetch_story_locations_in_story_frame(0, true, $iframe);
|
||||
} else {
|
||||
// NEWSBLUR.log(['Titles loaded, iframe NOT loaded -- prefetching now']);
|
||||
_.delay(_.bind(function() {
|
||||
this.prefetch_story_locations_in_story_frame();
|
||||
}, this), 250);
|
||||
}
|
||||
} else if (this.story_view == 'feed') {
|
||||
this.prefetch_story_locations_in_feed_view();
|
||||
} else if (this.story_view == 'story') {
|
||||
this.show_next_story(1);
|
||||
}
|
||||
}
|
||||
if (this.flags['open_unread_stories_in_tabs']) {
|
||||
_.defer(_.bind(this.open_unread_stories_in_tabs, this));
|
||||
}
|
||||
this.hide_stories_progress_bar();
|
||||
if (this.flags['showing_feed_in_tryfeed_view']) {
|
||||
this.show_tryfeed_add_button();
|
||||
}
|
||||
this.make_content_pane_feed_counter(feed_id);
|
||||
},
|
||||
|
||||
setup_mousemove_on_views: function() {
|
||||
|
@ -1801,7 +1807,7 @@
|
|||
var feeds = this.list_feeds_with_unreads_in_folder($folder, false, true);
|
||||
this.cache['river_feeds_with_unreads'] = feeds;
|
||||
this.show_stories_progress_bar(feeds.length);
|
||||
this.model.fetch_river_stories(this.active_feed, feeds, 0,
|
||||
this.model.fetch_river_stories(this.active_feed, feeds, 1,
|
||||
_.bind(this.post_open_river_stories, this), true);
|
||||
},
|
||||
|
||||
|
@ -1840,7 +1846,9 @@
|
|||
var feeds = _.compact(_.map($('.feed:not(.NB-empty)', $folder), function(o) {
|
||||
var feed_id = parseInt($(o).attr('data-id'), 10);
|
||||
var feed = model.get_feed(feed_id);
|
||||
if (counts_only && !visible_only) {
|
||||
if (!feed) {
|
||||
return;
|
||||
} else if (counts_only && !visible_only) {
|
||||
return feed.ps + feed.nt + feed.ng;
|
||||
} else if (counts_only && visible_only) {
|
||||
if (unread_view == 'positive') return feed.ps;
|
||||
|
@ -2079,7 +2087,7 @@
|
|||
!$story.length ||
|
||||
this.flags['iframe_fetching_story_locations'] ||
|
||||
this.flags['iframe_story_locations_fetched'] ||
|
||||
parseInt($story.offset().top, 10) > this.cache['prefetch_iteration']*4000) {
|
||||
parseInt($story.offset().top, 10) > this.cache['prefetch_iteration']*2000) {
|
||||
if ($story && $story.length) {
|
||||
// NEWSBLUR.log(['Prefetch break on position too far', parseInt($story.offset().top, 10), this.cache['prefetch_iteration']*4000]);
|
||||
break;
|
||||
|
@ -2100,7 +2108,7 @@
|
|||
&& !self.flags['iframe_story_locations_fetched']) {
|
||||
self.prefetch_story_locations_in_story_frame();
|
||||
}
|
||||
}, 2000);
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2186,14 +2194,13 @@
|
|||
|
||||
var feed = this.model.get_feed(feed_id);
|
||||
var $feed_list = this.$s.$feed_list;
|
||||
var $feed = this.cache.$feed_in_feed_list[feed_id] || this.find_feed_in_feed_list(feed_id);
|
||||
var $feed = this.find_feed_in_feed_list(feed_id);
|
||||
var $feed_counts = this.cache.$feed_counts_in_feed_list[feed_id] || $('.feed_counts_floater', $feed);
|
||||
var $story_title = this.find_story_in_story_titles(story_id);
|
||||
var $content_pane = this.$s.$content_pane;
|
||||
var $floater = $('.feed_counts_floater', $content_pane);
|
||||
var unread_view = this.get_unread_view_name();
|
||||
|
||||
this.cache.$feed_in_feed_list[feed_id] = $feed;
|
||||
this.cache.$feed_counts_in_feed_list[feed_id] = $feed_counts;
|
||||
|
||||
$story_title.toggleClass('read', !unread);
|
||||
|
@ -2509,7 +2516,7 @@
|
|||
var read = story.read_status
|
||||
? ' read '
|
||||
: '';
|
||||
var score = this.compute_story_score(story);
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
var score_color = 'neutral';
|
||||
var starred = story.starred ? ' NB-story-starred ' : '';
|
||||
if (options.river_stories) {
|
||||
|
@ -2557,82 +2564,6 @@
|
|||
return $story_title;
|
||||
},
|
||||
|
||||
is_feed_floater_gradient_light: function(feed) {
|
||||
if (!feed) return false;
|
||||
var color = feed.favicon_color;
|
||||
if (!color) return false;
|
||||
|
||||
var r = parseInt(color.substr(0, 2), 16) / 255.0;
|
||||
var g = parseInt(color.substr(2, 2), 16) / 255.0;
|
||||
var b = parseInt(color.substr(4, 2), 16) / 255.0;
|
||||
|
||||
return $.textColor({r: r, g: g, b: b}) != 'white';
|
||||
},
|
||||
|
||||
generate_gradient: function(feed, type) {
|
||||
if (!feed) return '';
|
||||
var color = feed.favicon_color;
|
||||
if (!color) return '';
|
||||
|
||||
var r = parseInt(color.substr(0, 2), 16);
|
||||
var g = parseInt(color.substr(2, 2), 16);
|
||||
var b = parseInt(color.substr(4, 2), 16);
|
||||
|
||||
if (type == 'border') {
|
||||
return [
|
||||
'1px solid rgb(',
|
||||
[
|
||||
parseInt(r*(6/8), 10),
|
||||
parseInt(g*(6/8), 10),
|
||||
parseInt(b*(6/8), 10)
|
||||
].join(','),
|
||||
')'
|
||||
].join('');
|
||||
} else if (type == 'webkit') {
|
||||
return [
|
||||
'-webkit-gradient(',
|
||||
'linear,',
|
||||
'left bottom,',
|
||||
'left top,',
|
||||
'color-stop(0.06, rgba(',
|
||||
[
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
255
|
||||
].join(','),
|
||||
')),',
|
||||
'color-stop(0.84, rgba(',
|
||||
[
|
||||
r+35,
|
||||
g+35,
|
||||
b+35,
|
||||
255
|
||||
].join(','),
|
||||
')))'
|
||||
].join('');
|
||||
} else if (type == 'moz') {
|
||||
return [
|
||||
'-moz-linear-gradient(',
|
||||
'center bottom,',
|
||||
'rgb(',
|
||||
[
|
||||
r,
|
||||
g,
|
||||
b
|
||||
].join(','),
|
||||
') 6%,',
|
||||
'rgb(',
|
||||
[
|
||||
r+35,
|
||||
g+35,
|
||||
b+35
|
||||
].join(','),
|
||||
') 84%)'
|
||||
].join('');
|
||||
}
|
||||
},
|
||||
|
||||
story_titles_clear_loading_endbar: function() {
|
||||
var $story_titles = this.$s.$story_titles;
|
||||
|
||||
|
@ -2643,22 +2574,6 @@
|
|||
}
|
||||
},
|
||||
|
||||
compute_story_score: function(story) {
|
||||
var score = 0;
|
||||
var score_max = Math.max(story.intelligence['title'],
|
||||
story.intelligence['author'],
|
||||
story.intelligence['tags']);
|
||||
var score_min = Math.min(story.intelligence['title'],
|
||||
story.intelligence['author'],
|
||||
story.intelligence['tags']);
|
||||
if (score_max > 0) score = score_max;
|
||||
else if (score_min < 0) score = score_min;
|
||||
|
||||
if (score == 0) score = story.intelligence['feed'];
|
||||
|
||||
return score;
|
||||
},
|
||||
|
||||
recalculate_story_scores: function(feed_id) {
|
||||
feed_id = feed_id || this.active_feed;
|
||||
|
||||
|
@ -2667,7 +2582,7 @@
|
|||
var replace_stories = _.bind(function($story, story_id) {
|
||||
var story = this.model.get_story(story_id);
|
||||
if (story.story_feed_id != feed_id) return;
|
||||
var score = this.compute_story_score(story);
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
$story.removeClass('NB-story-positive')
|
||||
.removeClass('NB-story-neutral')
|
||||
.removeClass('NB-story-negative');
|
||||
|
@ -2972,7 +2887,7 @@
|
|||
var unread_view_name = this.get_unread_view_name();
|
||||
var $indicator = $('.NB-story-title-indicator', $story_titles);
|
||||
var hidden_stories = _.any(this.model.stories, _.bind(function(story) {
|
||||
var score = this.compute_story_score(story);
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
|
||||
if (unread_view_name == 'positive') return score <= 0;
|
||||
else if (unread_view_name == 'neutral') return score < 0;
|
||||
|
@ -2982,6 +2897,7 @@
|
|||
if ($indicator.length) {
|
||||
var $counts = this.make_feed_counts_floater(feed.ps, feed.nt, feed.ng);
|
||||
$('.feed_counts_floater', $indicator).replaceWith($counts);
|
||||
this.cache.$feed_counts_in_feed_list[feed_id] = null;
|
||||
$indicator.css({'opacity': 1});
|
||||
} else if (feed) {
|
||||
$indicator = $.make('div', { className: 'NB-story-title-indicator' }, [
|
||||
|
@ -3011,14 +2927,14 @@
|
|||
'positive' :
|
||||
'neutral';
|
||||
var hidden_stories_at_threshold = _.any(this.model.stories, _.bind(function(story) {
|
||||
var score = this.compute_story_score(story);
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
|
||||
if (unread_view_name == 'positive') return score == 0;
|
||||
else if (unread_view_name == 'neutral') return score < 0;
|
||||
}, this));
|
||||
var hidden_stories_below_threshold = unread_view_name == 'positive' &&
|
||||
_.any(this.model.stories, _.bind(function(story) {
|
||||
var score = this.compute_story_score(story);
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
return score < 0;
|
||||
}, this));
|
||||
|
||||
|
@ -3164,7 +3080,7 @@
|
|||
var read = story.read_status
|
||||
? ' read '
|
||||
: '';
|
||||
var score = this.compute_story_score(story);
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
var score_color = 'neutral';
|
||||
var river_stories = options['river_stories']
|
||||
? ' NB-river-story '
|
||||
|
@ -3189,11 +3105,11 @@
|
|||
$.make('span', { className: 'feed_title' }, feed.feed_title)
|
||||
])
|
||||
)
|
||||
]).css('background-image', this.generate_gradient(feed, 'webkit'))
|
||||
.css('background-image', this.generate_gradient(feed, 'moz'))
|
||||
.css('borderBottom', this.generate_gradient(feed, 'border'))
|
||||
.css('borderTop', this.generate_gradient(feed, 'border'))
|
||||
.toggleClass('NB-inverse', this.is_feed_floater_gradient_light(feed)),
|
||||
]).css('background-image', NEWSBLUR.utils.generate_gradient(feed, 'webkit'))
|
||||
.css('background-image', NEWSBLUR.utils.generate_gradient(feed, 'moz'))
|
||||
.css('borderBottom', NEWSBLUR.utils.generate_gradient(feed, 'border'))
|
||||
.css('borderTop', NEWSBLUR.utils.generate_gradient(feed, 'border'))
|
||||
.toggleClass('NB-inverse', NEWSBLUR.utils.is_feed_floater_gradient_light(feed)),
|
||||
$.make('div', { className: 'NB-feed-story-header-info' }, [
|
||||
(story.story_authors &&
|
||||
this.make_story_feed_author(story)),
|
||||
|
@ -4599,6 +4515,7 @@
|
|||
var $new_feed = $(self.make_feed_title_template(feeds[feed_id], 'feed'));
|
||||
if ($feed.hasClass('NB-toplevel')) $new_feed.addClass('NB-toplevel');
|
||||
$feed.replaceWith($new_feed);
|
||||
self.cache.$feed_in_feed_list[feed_id] = null;
|
||||
self.hover_over_feed_titles($new_feed);
|
||||
if (self.active_feed == feed_id) {
|
||||
self.open_feed(feed_id, true, $new_feed);
|
||||
|
@ -4633,8 +4550,7 @@
|
|||
var feed = this.model.get_feed(feed_id);
|
||||
if (!feed) continue;
|
||||
var $feed = $(this.make_feed_title_template(feed, 'feed'));
|
||||
var $feed_on_page = this.cache.$feed_in_feed_list[feed_id] ||
|
||||
this.find_feed_in_feed_list(feed_id);
|
||||
var $feed_on_page = this.find_feed_in_feed_list(feed_id);
|
||||
|
||||
if (feed_id == this.active_feed) {
|
||||
NEWSBLUR.log(['UPDATING INLINE', feed.feed_title, $feed, $feed_on_page, replace_active_feed]);
|
||||
|
@ -4648,6 +4564,7 @@
|
|||
} else {
|
||||
if ($feed_on_page.hasClass('NB-toplevel')) $feed.addClass('NB-toplevel');
|
||||
$feed_on_page.replaceWith($feed);
|
||||
this.cache.$feed_in_feed_list[feed_id] = null;
|
||||
this.mark_feed_as_selected(this.active_feed, $feed);
|
||||
if (!single_feed_id) this.recalculate_story_scores(feed_id);
|
||||
this.show_feed_hidden_story_title_indicator();
|
||||
|
@ -4659,6 +4576,7 @@
|
|||
}
|
||||
if ($feed_on_page.hasClass('NB-toplevel')) $feed.addClass('NB-toplevel');
|
||||
$feed_on_page.replaceWith($feed);
|
||||
this.cache.$feed_in_feed_list[feed_id] = null;
|
||||
(function($feed) {
|
||||
$feed.css({'backgroundColor': '#D7DDE6'});
|
||||
$feed.animate({
|
||||
|
@ -4701,7 +4619,7 @@
|
|||
|
||||
if ($story && $story.length) {
|
||||
// Just update intelligence
|
||||
var score = this.compute_story_score(story);
|
||||
var score = NEWSBLUR.utils.compute_story_score(story);
|
||||
$story.removeClass('NB-story-neutral')
|
||||
.removeClass('NB-story-negative')
|
||||
.removeClass('NB-story-positive');
|
||||
|
@ -5134,13 +5052,44 @@
|
|||
this.open_add_feed_modal({url: feed_address});
|
||||
},
|
||||
|
||||
load_recommended_feed: function(direction, refresh) {
|
||||
approve_feed_in_moderation_queue: function(feed_id) {
|
||||
var self = this;
|
||||
var $module = $('.NB-module-recommended');
|
||||
var $module = $('.NB-module-recommended.NB-recommended-unmoderated');
|
||||
$module.addClass('NB-loading');
|
||||
var date = $('.NB-recommended-moderation-date').val();
|
||||
|
||||
this.model.approve_feed_in_moderation_queue(feed_id, date, function(resp) {
|
||||
if (!resp) return;
|
||||
$module.removeClass('NB-loading');
|
||||
$module.replaceWith(resp);
|
||||
self.load_javascript_elements_on_page();
|
||||
});
|
||||
},
|
||||
|
||||
decline_feed_in_moderation_queue: function(feed_id) {
|
||||
var self = this;
|
||||
var $module = $('.NB-module-recommended.NB-recommended-unmoderated');
|
||||
$module.addClass('NB-loading');
|
||||
|
||||
this.model.decline_feed_in_moderation_queue(feed_id, function(resp) {
|
||||
if (!resp) return;
|
||||
$module.removeClass('NB-loading');
|
||||
$module.replaceWith(resp);
|
||||
self.load_javascript_elements_on_page();
|
||||
});
|
||||
},
|
||||
|
||||
load_recommended_feed: function(direction, refresh, unmoderated) {
|
||||
var self = this;
|
||||
var $module = unmoderated ?
|
||||
$('.NB-module-recommended.NB-recommended-unmoderated') :
|
||||
$('.NB-module-recommended:not(.NB-recommended-unmoderated)');
|
||||
|
||||
$module.addClass('NB-loading');
|
||||
direction = direction || 0;
|
||||
|
||||
this.model.load_recommended_feed(this.counts['recommended_feed_page']+direction, !!refresh, function(resp) {
|
||||
this.model.load_recommended_feed(this.counts['recommended_feed_page']+direction,
|
||||
!!refresh, unmoderated, function(resp) {
|
||||
if (!resp) return;
|
||||
self.counts['recommended_feed_page'] += direction;
|
||||
|
||||
|
@ -5653,17 +5602,33 @@
|
|||
});
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-recommended-decline' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
var feed_id = $t.closest('.NB-recommended').attr('data-feed-id');
|
||||
self.decline_feed_in_moderation_queue(feed_id);
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-recommended-approve' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
var feed_id = $t.closest('.NB-recommended').attr('data-feed-id');
|
||||
self.approve_feed_in_moderation_queue(feed_id);
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-module-recommended .NB-module-next-page' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
if (!$t.hasClass('NB-disabled')) {
|
||||
self.load_recommended_feed(1);
|
||||
console.log(['parent', $t.closest('.NB-module-recommended'), $t.closest('.NB-module-recommended').hasClass('NB-recommended-unmoderated')]);
|
||||
var unmoderated = $t.closest('.NB-module-recommended').hasClass('NB-recommended-unmoderated');
|
||||
self.load_recommended_feed(1, false, unmoderated);
|
||||
}
|
||||
});
|
||||
|
||||
$.targetIs(e, { tagSelector: '.NB-module-recommended .NB-module-previous-page' }, function($t, $p){
|
||||
e.preventDefault();
|
||||
if (!$t.hasClass('NB-disabled')) {
|
||||
self.load_recommended_feed(-1);
|
||||
var unmoderated = $t.closest('.NB-module-recommended').hasClass('NB-recommended-unmoderated');
|
||||
console.log(['parent', $t.closest('.NB-module-recommended')]);
|
||||
self.load_recommended_feed(-1, false, unmoderated);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
95
media/js/newsblur/reader_utils.js
Normal file
95
media/js/newsblur/reader_utils.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
NEWSBLUR.utils = {
|
||||
|
||||
compute_story_score: function(story) {
|
||||
var score = 0;
|
||||
var score_max = Math.max(story.intelligence['title'],
|
||||
story.intelligence['author'],
|
||||
story.intelligence['tags']);
|
||||
var score_min = Math.min(story.intelligence['title'],
|
||||
story.intelligence['author'],
|
||||
story.intelligence['tags']);
|
||||
if (score_max > 0) score = score_max;
|
||||
else if (score_min < 0) score = score_min;
|
||||
|
||||
if (score == 0) score = story.intelligence['feed'];
|
||||
|
||||
return score;
|
||||
},
|
||||
|
||||
generate_gradient: function(feed, type) {
|
||||
if (!feed) return '';
|
||||
var color = feed.favicon_color;
|
||||
if (!color) return '';
|
||||
|
||||
var r = parseInt(color.substr(0, 2), 16);
|
||||
var g = parseInt(color.substr(2, 2), 16);
|
||||
var b = parseInt(color.substr(4, 2), 16);
|
||||
|
||||
if (type == 'border') {
|
||||
return [
|
||||
'1px solid rgb(',
|
||||
[
|
||||
parseInt(r*(6/8), 10),
|
||||
parseInt(g*(6/8), 10),
|
||||
parseInt(b*(6/8), 10)
|
||||
].join(','),
|
||||
')'
|
||||
].join('');
|
||||
} else if (type == 'webkit') {
|
||||
return [
|
||||
'-webkit-gradient(',
|
||||
'linear,',
|
||||
'left bottom,',
|
||||
'left top,',
|
||||
'color-stop(0, rgba(',
|
||||
[
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
255
|
||||
].join(','),
|
||||
')),',
|
||||
'color-stop(1, rgba(',
|
||||
[
|
||||
r+35,
|
||||
g+35,
|
||||
b+35,
|
||||
255
|
||||
].join(','),
|
||||
')))'
|
||||
].join('');
|
||||
} else if (type == 'moz') {
|
||||
return [
|
||||
'-moz-linear-gradient(',
|
||||
'center bottom,',
|
||||
'rgb(',
|
||||
[
|
||||
r,
|
||||
g,
|
||||
b
|
||||
].join(','),
|
||||
') 0%,',
|
||||
'rgb(',
|
||||
[
|
||||
r+35,
|
||||
g+35,
|
||||
b+35
|
||||
].join(','),
|
||||
') 100%)'
|
||||
].join('');
|
||||
}
|
||||
},
|
||||
|
||||
is_feed_floater_gradient_light: function(feed) {
|
||||
if (!feed) return false;
|
||||
var color = feed.favicon_color;
|
||||
if (!color) return false;
|
||||
|
||||
var r = parseInt(color.substr(0, 2), 16) / 255.0;
|
||||
var g = parseInt(color.substr(2, 2), 16) / 255.0;
|
||||
var b = parseInt(color.substr(4, 2), 16) / 255.0;
|
||||
|
||||
return $.textColor({r: r, g: g, b: b}) != 'white';
|
||||
}
|
||||
|
||||
};
|
28
settings.py
28
settings.py
|
@ -155,7 +155,7 @@ LOGGING = {
|
|||
COMPRESS_JS = {
|
||||
'all': {
|
||||
'source_filenames': (
|
||||
'js/jquery-1.6.js',
|
||||
'js/jquery-1.6.1.js',
|
||||
'js/inflector.js',
|
||||
'js/jquery.json.js',
|
||||
'js/jquery.easing.js',
|
||||
|
@ -183,6 +183,7 @@ COMPRESS_JS = {
|
|||
'js/jquery.flot.js',
|
||||
'js/jquery.tipsy.js',
|
||||
'js/underscore.js',
|
||||
'js/newsblur/reader_utils.js',
|
||||
'js/newsblur/assetmodel.js',
|
||||
'js/newsblur/reader.js',
|
||||
'js/newsblur/generate_bookmarklet.js',
|
||||
|
@ -204,6 +205,22 @@ COMPRESS_JS = {
|
|||
),
|
||||
'output_filename': 'js/all-compressed-?.js'
|
||||
},
|
||||
'mobile': {
|
||||
'source_filenames': (
|
||||
'js/jquery-1.6.1.js',
|
||||
'js/mobile/jquery.mobile-1.0b1.js',
|
||||
'js/jquery.ajaxmanager.3.js',
|
||||
'js/underscore.js',
|
||||
'js/inflector.js',
|
||||
'js/jquery.json.js',
|
||||
'js/jquery.easing.js',
|
||||
'js/jquery.newsblur.js',
|
||||
'js/newsblur/reader_utils.js',
|
||||
'js/newsblur/assetmodel.js',
|
||||
'js/mobile/newsblur/mobile_workspace.js',
|
||||
),
|
||||
'output_filename': 'js/mobile-compressed-?.js',
|
||||
},
|
||||
'paypal': {
|
||||
'source_filenames': (
|
||||
'js/newsblur/paypal_return.js',
|
||||
|
@ -234,6 +251,13 @@ COMPRESS_CSS = {
|
|||
),
|
||||
'output_filename': 'css/all-compressed-?.css'
|
||||
},
|
||||
'mobile': {
|
||||
'source_filenames': (
|
||||
'css/mobile/jquery.mobile-1.0b1.css',
|
||||
'css/mobile/mobile.css',
|
||||
),
|
||||
'output_filename': 'css/mobile/mobile-compressed-?.css',
|
||||
},
|
||||
'paypal': {
|
||||
'source_filenames': (
|
||||
'css/paypal_return.css',
|
||||
|
@ -305,6 +329,8 @@ INSTALLED_APPS = (
|
|||
'apps.profile',
|
||||
'apps.recommendations',
|
||||
'apps.statistics',
|
||||
'apps.static',
|
||||
'apps.mobile',
|
||||
'south',
|
||||
'utils',
|
||||
'vendor',
|
||||
|
|
116
templates/mobile/mobile_workspace.xhtml
Normal file
116
templates/mobile/mobile_workspace.xhtml
Normal file
|
@ -0,0 +1,116 @@
|
|||
{% load compressed utils_tags %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{% block title %}NewsBlur{% endblock %}</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<link rel="shortcut icon" HREF="/media/img/favicon.png">
|
||||
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<link rel="apple-touch-icon" href="/media/img/logo_128.png"/>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
var NEWSBLUR = {};
|
||||
NEWSBLUR.Globals = {
|
||||
'is_authenticated' : {{ user.is_authenticated|yesno:"true,false" }},
|
||||
'is_anonymous' : {{ user.is_anonymous|yesno:"true,false" }},
|
||||
'is_premium' : {{ user.profile.is_premium|yesno:"true,false" }},
|
||||
'secret_token' : "{{ user.profile.secret_token }}",
|
||||
'username' : "{{ user.username|safe }}",
|
||||
'email' : "{{ user.email|safe }}",
|
||||
'google_favicon_url' : 'http://www.google.com/s2/favicons?domain_url=',
|
||||
'MEDIA_URL' : "{{ MEDIA_URL }}"
|
||||
};
|
||||
NEWSBLUR.Flags = {
|
||||
'start_import_from_google_reader': {{ start_import_from_google_reader|yesno:"true,false" }}
|
||||
};
|
||||
NEWSBLUR.URLs = {
|
||||
'domain' : "{% current_domain %}"
|
||||
};
|
||||
</script>
|
||||
|
||||
{% compressed_css 'mobile' %}
|
||||
{% block head_js %}
|
||||
{% compressed_js 'mobile' %}
|
||||
{% endblock head_js %}
|
||||
{% block extra_head_js %}
|
||||
{% endblock extra_head_js %}
|
||||
|
||||
{% if not debug %}
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-8371683-2']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<div data-role="page" data-url="feeds" id="NB-page-feeds">
|
||||
<div data-role="header" data-backbtn="false">
|
||||
<h1>{{ request.user.username }}</h1>
|
||||
</div>
|
||||
<div data-role="content">
|
||||
<div id="NB-feed-list"></div>
|
||||
</div>
|
||||
<div data-role="footer">
|
||||
<div class="NB-footer-site-count ui-li-count">12 sites</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-role="page" data-url="stories" id="NB-page-stories">
|
||||
<div data-role="header">
|
||||
<a href="#" data-icon="arrow-l" data-back-btn-text="Sites" data-rel="back">Sites</a>
|
||||
<h1>Stories</h1>
|
||||
</div>
|
||||
<div data-role="content">
|
||||
<div id="NB-story-list"></div>
|
||||
</div>
|
||||
<div data-role="footer" class="ui-header"> 1
|
||||
<div class="NB-footer-site-count ui-li-count">12 sites</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-role="page" data-url="story" id="NB-page-story">
|
||||
<div data-role="header">
|
||||
<a href="#" data-icon="arrow-l" data-back-btn-text="Stories" data-rel="back">Stories</a>
|
||||
<h1>Story</h1>
|
||||
<a href="#" data-icon="arrow-d" class="ui-btn-right NB-next">Next Unread</a>
|
||||
</div>
|
||||
<div data-role="content">
|
||||
<div id="NB-story-detail">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div data-role="footer" class="ui-header">
|
||||
<a href="#" data-icon="arrow-u" class="NB-previous">Previous</a>
|
||||
<h1>...</h1>
|
||||
<a href="#" data-icon="arrow-d" class="ui-btn-right NB-next">Next Unread</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).bind('mobileinit', function() {
|
||||
$.mobile.ajaxEnabled = false;
|
||||
});
|
||||
$(document).bind('ready', function() {
|
||||
NEWSBLUR.mobile_reader = new NEWSBLUR.MobileReader();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -83,6 +83,11 @@ $(document).ready(function() {
|
|||
{% if recommended_feeds %}
|
||||
{% render_recommended_feed recommended_feeds %}
|
||||
{% endif %}
|
||||
|
||||
{% if user.is_staff and unmoderated_feeds %}
|
||||
{% render_recommended_feed unmoderated_feeds 1 %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<div class="NB-module-recommended NB-module">
|
||||
<div class="NB-module-recommended NB-module {% if unmoderated %}NB-recommended-unmoderated{% endif %}">
|
||||
<h5 class="NB-module-header">
|
||||
Recommended Site
|
||||
{% if unmoderated %}
|
||||
Moderation Queue
|
||||
{% else %}
|
||||
Recommended Site
|
||||
{% endif %}
|
||||
<div class="NB-module-header-right">
|
||||
{% if has_next_page or has_previous_page %}
|
||||
<a href="#" class="NB-module-direction NB-module-next-page NB-javascript {% if not has_next_page %}NB-disabled{% endif %}"></a>
|
||||
|
@ -8,9 +12,15 @@
|
|||
{% endif %}
|
||||
<div class="NB-spinner NB-left"></div>
|
||||
<div class="NB-module-recommended-date">
|
||||
{{ recommended_feed.approved_date|date:"M j" }}
|
||||
<span>{{ recommended_feed.approved_date|date:"S" }}</span>,
|
||||
{{ recommended_feed.approved_date|date:"Y" }}
|
||||
{% if unmoderated %}
|
||||
{{ recommended_feed.created_date|date:"M j" }}
|
||||
<span>{{ recommended_feed.created_date|date:"S" }}</span>,
|
||||
{{ recommended_feed.created_date|date:"Y" }}
|
||||
{% else %}
|
||||
{{ recommended_feed.approved_date|date:"M j" }}
|
||||
<span>{{ recommended_feed.approved_date|date:"S" }}</span>,
|
||||
{{ recommended_feed.approved_date|date:"Y" }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</h5>
|
||||
|
@ -34,6 +44,11 @@
|
|||
<div class="NB-recommended-try NB-modal-submit-green NB-modal-submit-button NB-javascript">Try</div>
|
||||
<div class="NB-recommended-add NB-modal-submit-close NB-modal-submit-button NB-javascript">Add</div>
|
||||
{% endif %}
|
||||
{% if unmoderated %}
|
||||
<input type="text" class="NB-recommended-moderation-date" name="date" value="{{ today|date:"Y-m-d" }}" />
|
||||
<div class="NB-recommended-approve NB-modal-submit-green NB-modal-submit-button NB-javascript">Approve</div>
|
||||
<div class="NB-recommended-decline NB-modal-submit-close NB-modal-submit-button NB-javascript">Decline</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
2
urls.py
2
urls.py
|
@ -13,6 +13,8 @@ urlpatterns = patterns('',
|
|||
(r'^api/', include('apps.api.urls')),
|
||||
(r'^recommendations/', include('apps.recommendations.urls')),
|
||||
(r'^statistics/', include('apps.statistics.urls')),
|
||||
(r'^mobile/', include('apps.mobile.urls')),
|
||||
(r'^m/', include('apps.mobile.urls')),
|
||||
url(r'^about/?', static_views.about, name='about'),
|
||||
url(r'^faq/?', static_views.faq, name='faq'),
|
||||
url(r'^api/?', static_views.api, name='api'),
|
||||
|
|
|
@ -212,11 +212,11 @@ class ProcessFeed:
|
|||
# if story.get('published') > end_date:
|
||||
# end_date = story.get('published')
|
||||
story_guids.append(story.get('guid') or story.get('link'))
|
||||
existing_stories = MStory.objects(
|
||||
existing_stories = list(MStory.objects(
|
||||
# story_guid__in=story_guids,
|
||||
story_date__gte=start_date,
|
||||
story_feed_id=self.feed.pk
|
||||
).limit(len(story_guids))
|
||||
).limit(len(story_guids)))
|
||||
|
||||
# MStory.objects(
|
||||
# (Q(story_date__gte=start_date) & Q(story_date__lte=end_date))
|
||||
|
|
1524
utils/feedparser.py
1524
utils/feedparser.py
File diff suppressed because it is too large
Load diff
|
@ -27,6 +27,25 @@ def ajax_login_required(function=None):
|
|||
else:
|
||||
return _dec(function)
|
||||
|
||||
def admin_only(function=None):
|
||||
def _dec(view_func):
|
||||
def _view(request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
return HttpResponseForbidden()
|
||||
else:
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
_view.__name__ = view_func.__name__
|
||||
_view.__dict__ = view_func.__dict__
|
||||
_view.__doc__ = view_func.__doc__
|
||||
|
||||
return _view
|
||||
|
||||
if function is None:
|
||||
return _dec
|
||||
else:
|
||||
return _dec(function)
|
||||
|
||||
def get_user(request):
|
||||
if not hasattr(request, 'user'):
|
||||
user = request
|
||||
|
|
4
vendor/opml/__init__.py
vendored
4
vendor/opml/__init__.py
vendored
|
@ -59,8 +59,8 @@ class Opml(object):
|
|||
return self._outlines[index]
|
||||
|
||||
def from_string(opml_text):
|
||||
|
||||
return Opml(lxml.etree.fromstring(opml_text))
|
||||
parser = lxml.etree.XMLParser(recover=True)
|
||||
return Opml(lxml.etree.fromstring(opml_text, parser))
|
||||
|
||||
def parse(opml_url):
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue