Merge remote-tracking branch 'upstream/master'
|
@ -187,6 +187,7 @@ class UserAgentBanMiddleware:
|
||||||
|
|
||||||
if 'profile' in request.path: return
|
if 'profile' in request.path: return
|
||||||
if 'haproxy' in request.path: return
|
if 'haproxy' in request.path: return
|
||||||
|
if getattr(settings, 'TEST_DEBUG'): return
|
||||||
|
|
||||||
if any(ua in user_agent for ua in BANNED_USER_AGENTS):
|
if any(ua in user_agent for ua in BANNED_USER_AGENTS):
|
||||||
data = {
|
data = {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
"model": "reader.usersubscriptionfolders",
|
"model": "reader.usersubscriptionfolders",
|
||||||
"fields": {
|
"fields": {
|
||||||
"folders": "[1, {\"Tech\": [4, 5, {\"Deep Tech\": [6, 7]}]}, 2, 3, 8, 9, {\"Blogs\": [8, 9]}]",
|
"folders": "[{\"Tech\": [1, 4, 5, {\"Deep Tech\": [6, 7]}]}, 2, 3, 8, 9, {\"Blogs\": [8, 9]}, 1]",
|
||||||
"user": 1
|
"user": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -917,7 +917,25 @@ class UserSubscriptionFolders(models.Model):
|
||||||
user_sub_folders = add_object_to_folder(obj, parent_folder, user_sub_folders)
|
user_sub_folders = add_object_to_folder(obj, parent_folder, user_sub_folders)
|
||||||
self.folders = json.encode(user_sub_folders)
|
self.folders = json.encode(user_sub_folders)
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
def arranged_folders(self):
|
||||||
|
user_sub_folders = json.decode(self.folders)
|
||||||
|
def _arrange_folder(folder):
|
||||||
|
folder_feeds = []
|
||||||
|
folder_folders = []
|
||||||
|
for item in folder:
|
||||||
|
if isinstance(item, int):
|
||||||
|
folder_feeds.append(item)
|
||||||
|
elif isinstance(item, dict):
|
||||||
|
for f_k, f_v in item.items():
|
||||||
|
arranged_folder = _arrange_folder(f_v)
|
||||||
|
folder_folders.append({f_k: arranged_folder})
|
||||||
|
|
||||||
|
arranged_folder = folder_feeds + folder_folders
|
||||||
|
return arranged_folder
|
||||||
|
|
||||||
|
return _arrange_folder(user_sub_folders)
|
||||||
|
|
||||||
def delete_feed(self, feed_id, in_folder, commit_delete=True):
|
def delete_feed(self, feed_id, in_folder, commit_delete=True):
|
||||||
def _find_feed_in_folders(old_folders, folder_name='', multiples_found=False, deleted=False):
|
def _find_feed_in_folders(old_folders, folder_name='', multiples_found=False, deleted=False):
|
||||||
new_folders = []
|
new_folders = []
|
||||||
|
@ -944,7 +962,7 @@ class UserSubscriptionFolders(models.Model):
|
||||||
|
|
||||||
return new_folders, multiples_found, deleted
|
return new_folders, multiples_found, deleted
|
||||||
|
|
||||||
user_sub_folders = json.decode(self.folders)
|
user_sub_folders = self.arranged_folders()
|
||||||
user_sub_folders, multiples_found, deleted = _find_feed_in_folders(user_sub_folders)
|
user_sub_folders, multiples_found, deleted = _find_feed_in_folders(user_sub_folders)
|
||||||
self.folders = json.encode(user_sub_folders)
|
self.folders = json.encode(user_sub_folders)
|
||||||
self.save()
|
self.save()
|
||||||
|
|
|
@ -6,7 +6,9 @@ from django.conf import settings
|
||||||
from mongoengine.connection import connect, disconnect
|
from mongoengine.connection import connect, disconnect
|
||||||
|
|
||||||
class ReaderTest(TestCase):
|
class ReaderTest(TestCase):
|
||||||
fixtures = ['subscriptions.json', 'stories.json', '../../rss_feeds/fixtures/gawker1.json']
|
fixtures = ['../../rss_feeds/fixtures/rss_feeds.json',
|
||||||
|
'subscriptions.json', 'stories.json',
|
||||||
|
'../../rss_feeds/fixtures/gawker1.json']
|
||||||
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -23,16 +25,16 @@ class ReaderTest(TestCase):
|
||||||
response = self.client.get(reverse('load-feeds'))
|
response = self.client.get(reverse('load-feeds'))
|
||||||
content = json.decode(response.content)
|
content = json.decode(response.content)
|
||||||
|
|
||||||
self.assertEquals(len(content['feeds']), 1)
|
self.assertEquals(len(content['feeds']), 10)
|
||||||
self.assertEquals(content['feeds']['1']['feed_title'], 'Gawker')
|
self.assertEquals(content['feeds']['1']['feed_title'], 'Gawker')
|
||||||
self.assertEquals(content['folders'], [1, {'Tech': [4, 5, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8, 9]}])
|
self.assertEquals(content['folders'], [{'Tech': [1, 4, 5, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8, 9]}, 1])
|
||||||
|
|
||||||
def test_delete_feed(self):
|
def test_delete_feed(self):
|
||||||
self.client.login(username='conesus', password='test')
|
self.client.login(username='conesus', password='test')
|
||||||
|
|
||||||
response = self.client.get(reverse('load-feeds'))
|
response = self.client.get(reverse('load-feeds'))
|
||||||
feeds = json.decode(response.content)
|
feeds = json.decode(response.content)
|
||||||
self.assertEquals(feeds['folders'], [1, {'Tech': [4, 5, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8, 9]}])
|
self.assertEquals(feeds['folders'], [{'Tech': [1, 4, 5, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8, 9]}, 1])
|
||||||
|
|
||||||
# Delete feed
|
# Delete feed
|
||||||
response = self.client.post(reverse('delete-feed'), {'feed_id': 1, 'in_folder': ''})
|
response = self.client.post(reverse('delete-feed'), {'feed_id': 1, 'in_folder': ''})
|
||||||
|
@ -41,7 +43,7 @@ class ReaderTest(TestCase):
|
||||||
|
|
||||||
response = self.client.get(reverse('load-feeds'))
|
response = self.client.get(reverse('load-feeds'))
|
||||||
feeds = json.decode(response.content)
|
feeds = json.decode(response.content)
|
||||||
self.assertEquals(feeds['folders'], [{'Tech': [4, 5, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8, 9]}])
|
self.assertEquals(feeds['folders'], [2, 3, 8, 9, {'Tech': [1, 4, 5, {'Deep Tech': [6, 7]}]}, {'Blogs': [8, 9]}])
|
||||||
|
|
||||||
# Delete feed
|
# Delete feed
|
||||||
response = self.client.post(reverse('delete-feed'), {'feed_id': 9, 'in_folder': 'Blogs'})
|
response = self.client.post(reverse('delete-feed'), {'feed_id': 9, 'in_folder': 'Blogs'})
|
||||||
|
@ -50,7 +52,7 @@ class ReaderTest(TestCase):
|
||||||
|
|
||||||
response = self.client.get(reverse('load-feeds'))
|
response = self.client.get(reverse('load-feeds'))
|
||||||
feeds = json.decode(response.content)
|
feeds = json.decode(response.content)
|
||||||
self.assertEquals(feeds['folders'], [{'Tech': [4, 5, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8]}])
|
self.assertEquals(feeds['folders'], [2, 3, 8, 9, {'Tech': [1, 4, 5, {'Deep Tech': [6, 7]}]}, {'Blogs': [8]}])
|
||||||
|
|
||||||
# Delete feed
|
# Delete feed
|
||||||
response = self.client.post(reverse('delete-feed'), {'feed_id': 5, 'in_folder': 'Tech'})
|
response = self.client.post(reverse('delete-feed'), {'feed_id': 5, 'in_folder': 'Tech'})
|
||||||
|
@ -59,7 +61,7 @@ class ReaderTest(TestCase):
|
||||||
|
|
||||||
response = self.client.get(reverse('load-feeds'))
|
response = self.client.get(reverse('load-feeds'))
|
||||||
feeds = json.decode(response.content)
|
feeds = json.decode(response.content)
|
||||||
self.assertEquals(feeds['folders'], [{'Tech': [4, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8]}])
|
self.assertEquals(feeds['folders'], [2, 3, 8, 9, {'Tech': [1, 4, {'Deep Tech': [6, 7]}]}, {'Blogs': [8]}])
|
||||||
|
|
||||||
# Delete feed
|
# Delete feed
|
||||||
response = self.client.post(reverse('delete-feed'), {'feed_id': 4, 'in_folder': 'Tech'})
|
response = self.client.post(reverse('delete-feed'), {'feed_id': 4, 'in_folder': 'Tech'})
|
||||||
|
@ -68,7 +70,7 @@ class ReaderTest(TestCase):
|
||||||
|
|
||||||
response = self.client.get(reverse('load-feeds'))
|
response = self.client.get(reverse('load-feeds'))
|
||||||
feeds = json.decode(response.content)
|
feeds = json.decode(response.content)
|
||||||
self.assertEquals(feeds['folders'], [{'Tech': [{'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8]}])
|
self.assertEquals(feeds['folders'], [2, 3, 8, 9, {'Tech': [1, {'Deep Tech': [6, 7]}]}, {'Blogs': [8]}])
|
||||||
|
|
||||||
# Delete feed
|
# Delete feed
|
||||||
response = self.client.post(reverse('delete-feed'), {'feed_id': 8, 'in_folder': ''})
|
response = self.client.post(reverse('delete-feed'), {'feed_id': 8, 'in_folder': ''})
|
||||||
|
@ -77,7 +79,23 @@ class ReaderTest(TestCase):
|
||||||
|
|
||||||
response = self.client.get(reverse('load-feeds'))
|
response = self.client.get(reverse('load-feeds'))
|
||||||
feeds = json.decode(response.content)
|
feeds = json.decode(response.content)
|
||||||
self.assertEquals(feeds['folders'], [{'Tech': [{'Deep Tech': [6, 7]}]}, 2, 3, 9, {'Blogs': [8]}])
|
self.assertEquals(feeds['folders'], [2, 3, 9, {'Tech': [1, {'Deep Tech': [6, 7]}]}, {'Blogs': [8]}])
|
||||||
|
|
||||||
|
def test_delete_feed__multiple_folders(self):
|
||||||
|
self.client.login(username='conesus', password='test')
|
||||||
|
|
||||||
|
response = self.client.get(reverse('load-feeds'))
|
||||||
|
feeds = json.decode(response.content)
|
||||||
|
self.assertEquals(feeds['folders'], [{'Tech': [1, 4, 5, {'Deep Tech': [6, 7]}]}, 2, 3, 8, 9, {'Blogs': [8, 9]}, 1])
|
||||||
|
|
||||||
|
# Delete feed
|
||||||
|
response = self.client.post(reverse('delete-feed'), {'feed_id': 1})
|
||||||
|
response = json.decode(response.content)
|
||||||
|
self.assertEquals(response['code'], 1)
|
||||||
|
|
||||||
|
response = self.client.get(reverse('load-feeds'))
|
||||||
|
feeds = json.decode(response.content)
|
||||||
|
self.assertEquals(feeds['folders'], [2, 3, 8, 9, {'Tech': [1, 4, 5, {'Deep Tech': [6, 7]}]}, {'Blogs': [8, 9]}])
|
||||||
|
|
||||||
def test_load_single_feed(self):
|
def test_load_single_feed(self):
|
||||||
# from django.conf import settings
|
# from django.conf import settings
|
||||||
|
|
|
@ -607,8 +607,9 @@ def load_single_feed(request, feed_id):
|
||||||
if not include_story_content:
|
if not include_story_content:
|
||||||
del story['story_content']
|
del story['story_content']
|
||||||
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
||||||
story['short_parsed_date'] = format_story_link_date__short(story_date)
|
nowtz = localtime_for_timezone(now, user.profile.timezone)
|
||||||
story['long_parsed_date'] = format_story_link_date__long(story_date, now)
|
story['short_parsed_date'] = format_story_link_date__short(story_date, nowtz)
|
||||||
|
story['long_parsed_date'] = format_story_link_date__long(story_date, nowtz)
|
||||||
if usersub:
|
if usersub:
|
||||||
story['read_status'] = 1
|
story['read_status'] = 1
|
||||||
if (read_filter == 'all' or query) and usersub:
|
if (read_filter == 'all' or query) and usersub:
|
||||||
|
@ -782,12 +783,13 @@ def load_starred_stories(request):
|
||||||
comments=story.comments))
|
comments=story.comments))
|
||||||
for story in shared_stories])
|
for story in shared_stories])
|
||||||
|
|
||||||
|
nowtz = localtime_for_timezone(now, user.profile.timezone)
|
||||||
for story in stories:
|
for story in stories:
|
||||||
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
||||||
story['short_parsed_date'] = format_story_link_date__short(story_date)
|
story['short_parsed_date'] = format_story_link_date__short(story_date, nowtz)
|
||||||
story['long_parsed_date'] = format_story_link_date__long(story_date, now)
|
story['long_parsed_date'] = format_story_link_date__long(story_date, nowtz)
|
||||||
starred_date = localtime_for_timezone(story['starred_date'], user.profile.timezone)
|
starred_date = localtime_for_timezone(story['starred_date'], user.profile.timezone)
|
||||||
story['starred_date'] = format_story_link_date__long(starred_date, now)
|
story['starred_date'] = format_story_link_date__long(starred_date, nowtz)
|
||||||
story['read_status'] = 1
|
story['read_status'] = 1
|
||||||
story['starred'] = True
|
story['starred'] = True
|
||||||
story['intelligence'] = {
|
story['intelligence'] = {
|
||||||
|
@ -939,6 +941,7 @@ def load_river_stories__redis(request):
|
||||||
|
|
||||||
|
|
||||||
# Just need to format stories
|
# Just need to format stories
|
||||||
|
nowtz = localtime_for_timezone(now, user.profile.timezone)
|
||||||
for story in stories:
|
for story in stories:
|
||||||
story['read_status'] = 0
|
story['read_status'] = 0
|
||||||
if read_filter == 'all':
|
if read_filter == 'all':
|
||||||
|
@ -946,8 +949,8 @@ def load_river_stories__redis(request):
|
||||||
story['story_hash'] not in unread_feed_story_hashes):
|
story['story_hash'] not in unread_feed_story_hashes):
|
||||||
story['read_status'] = 1
|
story['read_status'] = 1
|
||||||
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
||||||
story['short_parsed_date'] = format_story_link_date__short(story_date)
|
story['short_parsed_date'] = format_story_link_date__short(story_date, nowtz)
|
||||||
story['long_parsed_date'] = format_story_link_date__long(story_date, now)
|
story['long_parsed_date'] = format_story_link_date__long(story_date, nowtz)
|
||||||
if story['story_hash'] in starred_stories:
|
if story['story_hash'] in starred_stories:
|
||||||
story['starred'] = True
|
story['starred'] = True
|
||||||
starred_date = localtime_for_timezone(starred_stories[story['story_hash']],
|
starred_date = localtime_for_timezone(starred_stories[story['story_hash']],
|
||||||
|
@ -1399,7 +1402,7 @@ def add_folder(request):
|
||||||
def delete_feed(request):
|
def delete_feed(request):
|
||||||
feed_id = int(request.POST['feed_id'])
|
feed_id = int(request.POST['feed_id'])
|
||||||
in_folder = request.POST.get('in_folder', None)
|
in_folder = request.POST.get('in_folder', None)
|
||||||
if in_folder == ' ':
|
if not in_folder or in_folder == ' ':
|
||||||
in_folder = ""
|
in_folder = ""
|
||||||
|
|
||||||
user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user)
|
user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user)
|
||||||
|
|
|
@ -136,5 +136,302 @@
|
||||||
"email": "samuel@newsblur.com",
|
"email": "samuel@newsblur.com",
|
||||||
"date_joined": "2009-01-04 17:32:58"
|
"date_joined": "2009-01-04 17:32:58"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 2,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker2.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker2.html",
|
||||||
|
"hash_address_and_link": "2",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 3,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker3.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker3.html",
|
||||||
|
"hash_address_and_link": "3",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 4,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker4.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker4.html",
|
||||||
|
"hash_address_and_link": "4",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 5,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker5.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker5.html",
|
||||||
|
"hash_address_and_link": "5",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 6,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker6.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker6.html",
|
||||||
|
"hash_address_and_link": "6",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 7,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker7.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker7.html",
|
||||||
|
"hash_address_and_link": "7",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 8,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker8.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker8.html",
|
||||||
|
"hash_address_and_link": "8",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 9,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker9.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker9.html",
|
||||||
|
"hash_address_and_link": "9",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"pk": 56,
|
||||||
|
"model": "rss_feeds.feed",
|
||||||
|
"fields": {
|
||||||
|
"premium_subscribers": -1,
|
||||||
|
"creation": "2011-08-27",
|
||||||
|
"exception_code": 0,
|
||||||
|
"last_load_time": 0,
|
||||||
|
"active_subscribers": 1,
|
||||||
|
"feed_address": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker56.xml",
|
||||||
|
"feed_link": "%(NEWSBLUR_DIR)s/apps/rss_feeds/fixtures/gawker56.html",
|
||||||
|
"hash_address_and_link": "56",
|
||||||
|
"feed_link_locked": true,
|
||||||
|
"last_update": "2011-08-27 02:45:21",
|
||||||
|
"etag": null,
|
||||||
|
"average_stories_per_month": 0,
|
||||||
|
"feed_title": "Gawker",
|
||||||
|
"last_modified": null,
|
||||||
|
"next_scheduled_update": "2011-08-28 14:33:50",
|
||||||
|
"favicon_color": null,
|
||||||
|
"stories_last_month": 0,
|
||||||
|
"active": true,
|
||||||
|
"favicon_not_found": false,
|
||||||
|
"has_page_exception": false,
|
||||||
|
"fetched_once": false,
|
||||||
|
"days_to_trim": 90,
|
||||||
|
"num_subscribers": 1,
|
||||||
|
"last_story_date": "2011-08-28 00:03:50",
|
||||||
|
"min_to_decay": 720,
|
||||||
|
"has_feed_exception": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -912,6 +912,7 @@ class Feed(models.Model):
|
||||||
story_content = strip_comments(story_content)
|
story_content = strip_comments(story_content)
|
||||||
story_tags = self.get_tags(story)
|
story_tags = self.get_tags(story)
|
||||||
story_link = self.get_permalink(story)
|
story_link = self.get_permalink(story)
|
||||||
|
replace_story_date = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
existing_story, story_has_changed = _1(story, story_content, existing_stories)
|
existing_story, story_has_changed = _1(story, story_content, existing_stories)
|
||||||
|
@ -937,11 +938,18 @@ class Feed(models.Model):
|
||||||
try:
|
try:
|
||||||
s.save()
|
s.save()
|
||||||
ret_values['new'] += 1
|
ret_values['new'] += 1
|
||||||
except (IntegrityError, OperationError), e:
|
except (IntegrityError), e:
|
||||||
ret_values['error'] += 1
|
ret_values['error'] += 1
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
logging.info(' ---> [%-30s] ~SN~FRIntegrityError on new story: %s - %s' % (self.feed_title[:30], story.get('guid'), e))
|
logging.info(' ---> [%-30s] ~SN~FRIntegrityError on new story: %s - %s' % (self.feed_title[:30], story.get('guid'), e))
|
||||||
elif existing_story and story_has_changed:
|
except OperationError, e:
|
||||||
|
existing_story, _ = MStory.find_story(self.pk,
|
||||||
|
story.get('guid'),
|
||||||
|
original_only=True)
|
||||||
|
story_has_changed = True
|
||||||
|
replace_story_date = True
|
||||||
|
|
||||||
|
if existing_story and story_has_changed:
|
||||||
# update story
|
# update story
|
||||||
original_content = None
|
original_content = None
|
||||||
try:
|
try:
|
||||||
|
@ -993,7 +1001,8 @@ class Feed(models.Model):
|
||||||
existing_story.story_tags = story_tags
|
existing_story.story_tags = story_tags
|
||||||
# Do not allow publishers to change the story date once a story is published.
|
# Do not allow publishers to change the story date once a story is published.
|
||||||
# Leads to incorrect unread story counts.
|
# Leads to incorrect unread story counts.
|
||||||
# existing_story.story_date = story.get('published') # No, don't
|
if replace_story_date:
|
||||||
|
existing_story.story_date = story.get('published') # Really shouldn't do this.
|
||||||
existing_story.extract_image_urls()
|
existing_story.extract_image_urls()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -3001,14 +3001,17 @@ class MActivity(mongo.Document):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_shared_story(cls, user_id, story_feed_id, story_id):
|
def remove_shared_story(cls, user_id, story_feed_id, story_id):
|
||||||
|
params = dict(user_id=user_id,
|
||||||
|
category='sharedstory',
|
||||||
|
feed_id="social:%s" % user_id,
|
||||||
|
story_feed_id=story_feed_id,
|
||||||
|
content_id=story_id)
|
||||||
try:
|
try:
|
||||||
a = cls.objects.get(user_id=user_id,
|
a = cls.objects.get(**params)
|
||||||
category='sharedstory',
|
|
||||||
feed_id="social:%s" % user_id,
|
|
||||||
story_feed_id=story_feed_id,
|
|
||||||
content_id=story_id)
|
|
||||||
except cls.DoesNotExist:
|
except cls.DoesNotExist:
|
||||||
return
|
return
|
||||||
|
except cls.MultipleObjectsReturned:
|
||||||
|
a = cls.objects.filter(**params)
|
||||||
|
|
||||||
a.delete()
|
a.delete()
|
||||||
|
|
||||||
|
|
|
@ -119,12 +119,13 @@ def load_social_stories(request, user_id, username=None):
|
||||||
comments=story.comments))
|
comments=story.comments))
|
||||||
for story in shared_stories])
|
for story in shared_stories])
|
||||||
|
|
||||||
|
nowtz = localtime_for_timezone(now, user.profile.timezone)
|
||||||
for story in stories:
|
for story in stories:
|
||||||
story['social_user_id'] = social_user_id
|
story['social_user_id'] = social_user_id
|
||||||
# story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
# story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
||||||
shared_date = localtime_for_timezone(story['shared_date'], user.profile.timezone)
|
shared_date = localtime_for_timezone(story['shared_date'], user.profile.timezone)
|
||||||
story['short_parsed_date'] = format_story_link_date__short(shared_date)
|
story['short_parsed_date'] = format_story_link_date__short(shared_date, nowtz)
|
||||||
story['long_parsed_date'] = format_story_link_date__long(shared_date)
|
story['long_parsed_date'] = format_story_link_date__long(shared_date, nowtz)
|
||||||
|
|
||||||
story['read_status'] = 1
|
story['read_status'] = 1
|
||||||
if (read_filter == 'all' or query) and socialsub:
|
if (read_filter == 'all' or query) and socialsub:
|
||||||
|
@ -270,13 +271,14 @@ def load_river_blurblog(request):
|
||||||
classifier_tags = []
|
classifier_tags = []
|
||||||
|
|
||||||
# Just need to format stories
|
# Just need to format stories
|
||||||
|
nowtz = localtime_for_timezone(now, user.profile.timezone)
|
||||||
for story in stories:
|
for story in stories:
|
||||||
story['read_status'] = 0
|
story['read_status'] = 0
|
||||||
if story['story_hash'] not in unread_feed_story_hashes:
|
if story['story_hash'] not in unread_feed_story_hashes:
|
||||||
story['read_status'] = 1
|
story['read_status'] = 1
|
||||||
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
story_date = localtime_for_timezone(story['story_date'], user.profile.timezone)
|
||||||
story['short_parsed_date'] = format_story_link_date__short(story_date)
|
story['short_parsed_date'] = format_story_link_date__short(story_date, nowtz)
|
||||||
story['long_parsed_date'] = format_story_link_date__long(story_date, now)
|
story['long_parsed_date'] = format_story_link_date__long(story_date, nowtz)
|
||||||
if story['story_hash'] in starred_stories:
|
if story['story_hash'] in starred_stories:
|
||||||
story['starred'] = True
|
story['starred'] = True
|
||||||
starred_date = localtime_for_timezone(starred_stories[story['story_hash']], user.profile.timezone)
|
starred_date = localtime_for_timezone(starred_stories[story['story_hash']], user.profile.timezone)
|
||||||
|
@ -521,7 +523,9 @@ def mark_story_as_shared(request):
|
||||||
source_user_id = request.POST.get('source_user_id')
|
source_user_id = request.POST.get('source_user_id')
|
||||||
relative_user_id = request.POST.get('relative_user_id') or request.user.pk
|
relative_user_id = request.POST.get('relative_user_id') or request.user.pk
|
||||||
post_to_services = request.POST.getlist('post_to_services')
|
post_to_services = request.POST.getlist('post_to_services')
|
||||||
format = request.REQUEST.get('format', 'json')
|
format = request.REQUEST.get('format', 'json')
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
nowtz = localtime_for_timezone(now, request.user.profile.timezone)
|
||||||
|
|
||||||
MSocialProfile.get_user(request.user.pk)
|
MSocialProfile.get_user(request.user.pk)
|
||||||
|
|
||||||
|
@ -576,8 +580,8 @@ def mark_story_as_shared(request):
|
||||||
story['shared_by_user'] = True
|
story['shared_by_user'] = True
|
||||||
story['shared'] = True
|
story['shared'] = True
|
||||||
shared_date = localtime_for_timezone(shared_story['shared_date'], request.user.profile.timezone)
|
shared_date = localtime_for_timezone(shared_story['shared_date'], request.user.profile.timezone)
|
||||||
story['short_parsed_date'] = format_story_link_date__short(shared_date)
|
story['short_parsed_date'] = format_story_link_date__short(shared_date, nowtz)
|
||||||
story['long_parsed_date'] = format_story_link_date__long(shared_date)
|
story['long_parsed_date'] = format_story_link_date__long(shared_date, nowtz)
|
||||||
|
|
||||||
if post_to_services:
|
if post_to_services:
|
||||||
for service in post_to_services:
|
for service in post_to_services:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.newsblur"
|
package="com.newsblur"
|
||||||
android:versionCode="43"
|
android:versionCode="44"
|
||||||
android:versionName="2.5.0" >
|
android:versionName="3.0.0" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="8"
|
android:minSdkVersion="8"
|
||||||
|
|
|
@ -10,16 +10,23 @@
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android 4.2.2" jdkType="Android SDK" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="android-support-v4" level="project" />
|
|
||||||
<orderEntry type="library" name="actionbarsherlock" level="project" />
|
|
||||||
<orderEntry type="library" name="gson-2.2.3" level="project" />
|
<orderEntry type="library" name="gson-2.2.3" level="project" />
|
||||||
<orderEntry type="library" name="classes" level="project" />
|
|
||||||
<orderEntry type="module" module-name="ActionBarSherlock" />
|
<orderEntry type="module" module-name="ActionBarSherlock" />
|
||||||
|
<orderEntry type="library" name="android-support-v4" level="project" />
|
||||||
|
<orderEntry type="module-library">
|
||||||
|
<library>
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$MODULE_DIR$/libs/ActionBarSherlock/bin/actionbarsherlock.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES />
|
||||||
|
</library>
|
||||||
|
</orderEntry>
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,11 @@
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android 4.2.2" jdkType="Android SDK" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="android-support-v4" level="project" />
|
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,4 @@
|
||||||
|
|
||||||
android.library=true
|
android.library=true
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-14
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-14
|
||||||
android.library.reference.1=libs/ActionBarSherlock
|
android.library.reference.1=libs/ActionBarSherlock
|
||||||
|
|
BIN
clients/android/NewsBlur/res/drawable-hdpi/clock.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB |
BIN
clients/android/NewsBlur/res/drawable-hdpi/share_icon.png
Normal file
After Width: | Height: | Size: 820 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 605 B |
Before Width: | Height: | Size: 605 B |
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/feed_background_selected_start"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:top="0.5dp"
|
||||||
|
android:bottom="0.5dp">
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/feed_background_selected_end"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<gradient
|
||||||
|
android:angle="90"
|
||||||
|
android:type="linear"
|
||||||
|
android:startColor="@color/folder_background_start"
|
||||||
|
android:endColor="@color/folder_background_end"/>
|
||||||
|
</shape>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<gradient
|
||||||
|
android:angle="90"
|
||||||
|
android:type="linear"
|
||||||
|
android:startColor="@color/folder_background_selected_start"
|
||||||
|
android:endColor="@color/folder_background_selected_end"/>
|
||||||
|
</shape>
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
<item android:state_pressed="true" android:drawable="@drawable/gradient_activation_highlight" />
|
<item android:state_pressed="true" android:drawable="@drawable/feed_background_highlight" />
|
||||||
<item android:drawable="@drawable/feed_background_default" />
|
<item android:drawable="@drawable/feed_background_default" />
|
||||||
</selector>
|
</selector>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
<item android:state_pressed="true" android:drawable="@drawable/gradient_activation_highlight" />
|
<item android:state_pressed="true" android:drawable="@drawable/folder_background_highlight" />
|
||||||
<item android:drawable="@drawable/gradient_background_default" />
|
<item android:drawable="@drawable/folder_background_default" />
|
||||||
</selector>
|
</selector>
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_pressed="true" android:drawable="@drawable/story_background_highlight"/>
|
||||||
|
<item android:drawable="@drawable/story_background_default"/>
|
||||||
|
</selector>
|
Before Width: | Height: | Size: 517 B After Width: | Height: | Size: 517 B |
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/story_background"/>
|
||||||
|
</shape>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/story_background_start"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:top="0.5dp"
|
||||||
|
android:bottom="0.5dp">
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/story_background_end"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -19,4 +19,13 @@
|
||||||
android:defaultValue="@string/default_read_filter_value" />
|
android:defaultValue="@string/default_read_filter_value" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory
|
||||||
|
android:title="@string/settings_social">
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="show_public_comments"
|
||||||
|
android:title="@string/settings_show_public_comments" >
|
||||||
|
</CheckBoxPreference>
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
|
@ -91,7 +91,7 @@
|
||||||
android:layout_toRightOf="@id/comment_user_image"
|
android:layout_toRightOf="@id/comment_user_image"
|
||||||
android:textColor="@color/newsblur_blue"
|
android:textColor="@color/newsblur_blue"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/comment_text"
|
android:id="@+id/comment_text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -105,6 +105,18 @@
|
||||||
android:textColor="@color/darkgray"
|
android:textColor="@color/darkgray"
|
||||||
android:textSize="14dp" />
|
android:textSize="14dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/comment_location"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/comment_text"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:layout_toRightOf="@id/comment_user_image"
|
||||||
|
android:textColor="@color/lightgray"
|
||||||
|
android:textSize="12dp"
|
||||||
|
/>
|
||||||
|
|
||||||
<com.newsblur.view.FlowLayout
|
<com.newsblur.view.FlowLayout
|
||||||
xmlns:newsblur="http://schemas.android.com/apk/res/com.newsblur"
|
xmlns:newsblur="http://schemas.android.com/apk/res/com.newsblur"
|
||||||
android:id="@+id/comment_favourite_avatars"
|
android:id="@+id/comment_favourite_avatars"
|
||||||
|
@ -121,6 +133,7 @@
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/comment_replies_container"
|
android:id="@+id/comment_replies_container"
|
||||||
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
@ -129,6 +142,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
android:background="#A6A6A6" />
|
android:background="#F0F0F0" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -5,7 +5,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_marginTop="15dp" >
|
android:layout_marginTop="15dp"
|
||||||
|
android:layout_marginBottom="15dp" >
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/share_story_button"
|
android:id="@+id/share_story_button"
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
android:paddingBottom="6dp"
|
android:paddingBottom="6dp"
|
||||||
android:paddingLeft="12dp"
|
android:paddingLeft="12dp"
|
||||||
android:paddingRight="12dp"
|
android:paddingRight="12dp"
|
||||||
android:drawableLeft="@drawable/share_half"
|
android:drawableLeft="@drawable/share_icon"
|
||||||
android:text="@string/share_this" />
|
android:text="@string/share_this" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
android:paddingBottom="6dp"
|
android:paddingBottom="6dp"
|
||||||
android:paddingLeft="12dp"
|
android:paddingLeft="12dp"
|
||||||
android:paddingRight="12dp"
|
android:paddingRight="12dp"
|
||||||
android:drawableLeft="@drawable/clock_half"
|
android:drawableLeft="@drawable/clock"
|
||||||
android:text="@string/save_this" />
|
android:text="@string/save_this" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -45,51 +46,103 @@
|
||||||
android:id="@+id/reading_shared_container"
|
android:id="@+id/reading_shared_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="20dp"
|
|
||||||
android:layout_marginRight="20dp"
|
|
||||||
android:layout_marginBottom="50dp" >
|
android:layout_marginBottom="50dp" >
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/reading_friend_comment_container"
|
android:id="@+id/reading_friend_comment_header"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/darkgray"
|
android:visibility="gone"
|
||||||
android:id="@+id/reading_friend_comment_total"
|
android:orientation="vertical">
|
||||||
android:paddingTop="3dp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:paddingBottom="3dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/comment_divider"
|
android:id="@+id/reading_friend_header_top_border"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="3dp"
|
android:layout_height="1dp"
|
||||||
android:layout_below="@id/reading_friend_comment_container"
|
android:layout_marginTop="12dp"
|
||||||
android:background="@drawable/divider_light" />
|
android:background="@color/lightgray"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
android:textColor="@color/darkgray"
|
||||||
|
android:id="@+id/reading_friend_comment_total"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:background="@drawable/gradient_background_default"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/reading_friend_header_bottom_border"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_below="@id/reading_friend_comment_total"
|
||||||
|
android:background="@color/lightgray"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/reading_public_comment_container"
|
android:id="@+id/reading_friend_comment_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_below="@id/reading_friend_comment_header"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_below="@id/comment_divider"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/darkgray"
|
android:layout_marginLeft="12dp"
|
||||||
android:paddingTop="3dp"
|
android:layout_marginRight="12dp"
|
||||||
android:textStyle="bold"
|
android:orientation="vertical">
|
||||||
android:id="@+id/reading_public_comment_total"
|
|
||||||
android:paddingBottom="3dp" />
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
<LinearLayout
|
||||||
|
android:id="@+id/reading_public_comment_header"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/comment_divider"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/reading_public_header_top_border"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:background="@color/lightgray"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/darkgray"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:background="@drawable/gradient_background_default"
|
||||||
|
android:id="@+id/reading_public_comment_total" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/reading_public_header_bottom_border"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_below="@id/reading_public_comment_total"
|
||||||
|
android:background="@color/lightgray"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/reading_public_comment_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_below="@id/reading_public_comment_header"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</merge>
|
</merge>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/item_background"
|
android:background="@drawable/selector_story_background"
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/selector_feed_background"
|
android:background="@drawable/selector_story_background"
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_toRightOf="@id/row_item_favicon_borderbar_1" />
|
android:layout_toRightOf="@id/row_item_favicon_borderbar_1" />
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/row_item_title_container"
|
android:id="@+id/row_item_title_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/selector_feed_background"
|
android:background="@drawable/selector_story_background"
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
|
|
@ -6,16 +6,21 @@
|
||||||
<color name="midgray">#898989</color>
|
<color name="midgray">#898989</color>
|
||||||
<color name="lightgray">#ccc</color>
|
<color name="lightgray">#ccc</color>
|
||||||
|
|
||||||
<color name="folder_background_end">#E9EBE4</color>
|
<color name="folder_background_end">#E9EBE4</color>
|
||||||
<color name="folder_background_start">#DDE0D7</color>
|
<color name="folder_background_start">#DDE0D7</color>
|
||||||
<color name="folder_background_selected_end">#fdfcca</color>
|
<color name="folder_background_selected_end">#D9DBD4</color>
|
||||||
<color name="folder_background_selected_start">#fbec8c</color>
|
<color name="folder_background_selected_start">#CDD0C7</color>
|
||||||
<color name="folder_text">#4C4C4C</color>
|
<color name="folder_text">#4C4C4C</color>
|
||||||
<color name="folder_border_top">#FDFDFD</color>
|
<color name="folder_border_top">#FDFDFD</color>
|
||||||
<color name="folder_border_bottom">#B7BBAA</color>
|
<color name="folder_border_bottom">#B7BBAA</color>
|
||||||
<color name="feed_background">#F7F8F5</color>
|
<color name="feed_background">#F7F8F5</color>
|
||||||
<color name="feed_background_end">#303030</color>
|
<color name="feed_background_end">#303030</color>
|
||||||
<color name="feed_background_start">#505050</color>
|
<color name="feed_background_start">#505050</color>
|
||||||
|
<color name="feed_background_selected_end">#FFFFD2</color>
|
||||||
|
<color name="feed_background_selected_start">#E3D0AE</color>
|
||||||
|
<color name="story_background">#F7F8F5</color>
|
||||||
|
<color name="story_background_end">#FFFDEF</color>
|
||||||
|
<color name="story_background_start">#DFDDCF</color>
|
||||||
|
|
||||||
<color name="story_title_unread">#333333</color>
|
<color name="story_title_unread">#333333</color>
|
||||||
<color name="story_title_read">#808080</color>
|
<color name="story_title_read">#808080</color>
|
||||||
|
|
|
@ -190,4 +190,6 @@
|
||||||
<item>Mark entire folder read</item>
|
<item>Mark entire folder read</item>
|
||||||
<item>Cancel</item>
|
<item>Cancel</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string name="settings_social">Social</string>
|
||||||
|
<string name="settings_show_public_comments">Show Public Comments</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class BlurDatabase extends SQLiteOpenHelper {
|
||||||
private final String TEXT = " text";
|
private final String TEXT = " text";
|
||||||
private final String INTEGER = " integer";
|
private final String INTEGER = " integer";
|
||||||
public final static String DB_NAME = "blur.db";
|
public final static String DB_NAME = "blur.db";
|
||||||
private final static int VERSION = 1;
|
private final static int VERSION = 2;
|
||||||
|
|
||||||
public BlurDatabase(Context context) {
|
public BlurDatabase(Context context) {
|
||||||
super(context, DB_NAME, null, VERSION);
|
super(context, DB_NAME, null, VERSION);
|
||||||
|
@ -44,7 +44,8 @@ public class BlurDatabase extends SQLiteOpenHelper {
|
||||||
private final String USER_SQL = "CREATE TABLE " + DatabaseConstants.USER_TABLE + " (" +
|
private final String USER_SQL = "CREATE TABLE " + DatabaseConstants.USER_TABLE + " (" +
|
||||||
DatabaseConstants.USER_PHOTO_URL + TEXT + ", " +
|
DatabaseConstants.USER_PHOTO_URL + TEXT + ", " +
|
||||||
DatabaseConstants.USER_USERID + INTEGER + " PRIMARY KEY, " +
|
DatabaseConstants.USER_USERID + INTEGER + " PRIMARY KEY, " +
|
||||||
DatabaseConstants.USER_USERNAME + TEXT + ")";
|
DatabaseConstants.USER_USERNAME + TEXT + ", " +
|
||||||
|
DatabaseConstants.USER_LOCATION + TEXT + ")";
|
||||||
|
|
||||||
private final String SOCIAL_FEED_SQL = "CREATE TABLE " + DatabaseConstants.SOCIALFEED_TABLE + " (" +
|
private final String SOCIAL_FEED_SQL = "CREATE TABLE " + DatabaseConstants.SOCIALFEED_TABLE + " (" +
|
||||||
DatabaseConstants.SOCIAL_FEED_ID + INTEGER + " PRIMARY KEY, " +
|
DatabaseConstants.SOCIAL_FEED_ID + INTEGER + " PRIMARY KEY, " +
|
||||||
|
|
|
@ -66,7 +66,8 @@ public class DatabaseConstants {
|
||||||
|
|
||||||
public static final String USER_TABLE = "user_table";
|
public static final String USER_TABLE = "user_table";
|
||||||
public static final String USER_USERID = BaseColumns._ID;
|
public static final String USER_USERID = BaseColumns._ID;
|
||||||
public static final String USER_USERNAME = "username";
|
public static final String USER_USERNAME = "username";
|
||||||
|
public static final String USER_LOCATION = "location";
|
||||||
public static final String USER_PHOTO_URL = "photo_url";
|
public static final String USER_PHOTO_URL = "photo_url";
|
||||||
|
|
||||||
public static final String STORY_TABLE = "stories";
|
public static final String STORY_TABLE = "stories";
|
||||||
|
|
|
@ -15,8 +15,9 @@ public class UserProfile {
|
||||||
|
|
||||||
@SerializedName("user_id")
|
@SerializedName("user_id")
|
||||||
public String userId;
|
public String userId;
|
||||||
|
|
||||||
public String username;
|
public String username;
|
||||||
|
public String location;
|
||||||
|
|
||||||
public static UserProfile fromCursor(final Cursor c) {
|
public static UserProfile fromCursor(final Cursor c) {
|
||||||
if (c.isBeforeFirst()) {
|
if (c.isBeforeFirst()) {
|
||||||
|
@ -26,7 +27,8 @@ public class UserProfile {
|
||||||
UserProfile profile = new UserProfile();
|
UserProfile profile = new UserProfile();
|
||||||
profile.userId = c.getString(c.getColumnIndex(DatabaseConstants.USER_USERID));
|
profile.userId = c.getString(c.getColumnIndex(DatabaseConstants.USER_USERID));
|
||||||
profile.photoUrl = c.getString(c.getColumnIndex(DatabaseConstants.USER_PHOTO_URL));
|
profile.photoUrl = c.getString(c.getColumnIndex(DatabaseConstants.USER_PHOTO_URL));
|
||||||
profile.username = c.getString(c.getColumnIndex(DatabaseConstants.USER_USERNAME));
|
profile.username = c.getString(c.getColumnIndex(DatabaseConstants.USER_USERNAME));
|
||||||
|
profile.location = c.getString(c.getColumnIndex(DatabaseConstants.USER_LOCATION));
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +37,8 @@ public class UserProfile {
|
||||||
final ContentValues values = new ContentValues();
|
final ContentValues values = new ContentValues();
|
||||||
values.put(DatabaseConstants.USER_PHOTO_URL, photoUrl);
|
values.put(DatabaseConstants.USER_PHOTO_URL, photoUrl);
|
||||||
values.put(DatabaseConstants.USER_USERID, userId);
|
values.put(DatabaseConstants.USER_USERID, userId);
|
||||||
values.put(DatabaseConstants.USER_USERNAME, username);
|
values.put(DatabaseConstants.USER_USERNAME, username);
|
||||||
|
values.put(DatabaseConstants.USER_LOCATION, location);
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,13 @@ import android.graphics.Color;
|
||||||
import android.graphics.drawable.TransitionDrawable;
|
import android.graphics.drawable.TransitionDrawable;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.ScaleDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.text.Html;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -170,10 +172,9 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupSaveButton() {
|
private void setupSaveButton() {
|
||||||
|
|
||||||
Button saveButton = (Button) view.findViewById(R.id.save_story_button);
|
Button saveButton = (Button) view.findViewById(R.id.save_story_button);
|
||||||
|
|
||||||
saveButton.setOnClickListener(new OnClickListener() {
|
saveButton.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
FeedUtils.saveStory(story, getActivity(), apiManager);
|
FeedUtils.saveStory(story, getActivity(), apiManager);
|
||||||
|
@ -253,7 +254,7 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
|
||||||
itemFeed.setText(feedTitle);
|
itemFeed.setText(feedTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
itemTitle.setText(story.title);
|
itemTitle.setText(Html.fromHtml(story.title));
|
||||||
itemDate.setText(story.longDate);
|
itemDate.setText(story.longDate);
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(story.authors)) {
|
if (!TextUtils.isEmpty(story.authors)) {
|
||||||
|
@ -409,11 +410,18 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
|
||||||
View commentView = inflater.inflate(R.layout.include_comment, null);
|
View commentView = inflater.inflate(R.layout.include_comment, null);
|
||||||
commentView.setTag(SetupCommentSectionTask.COMMENT_VIEW_BY + user.id);
|
commentView.setTag(SetupCommentSectionTask.COMMENT_VIEW_BY + user.id);
|
||||||
|
|
||||||
TextView commentText = (TextView) commentView.findViewById(R.id.comment_text);
|
TextView commentText = (TextView) commentView.findViewById(R.id.comment_text);
|
||||||
commentText.setTag("commentBy" + user.id);
|
commentText.setTag("commentBy" + user.id);
|
||||||
commentText.setText(sharedText);
|
commentText.setText(sharedText);
|
||||||
|
|
||||||
if (PrefsUtils.getUserImage(getActivity()) != null) {
|
TextView commentLocation = (TextView) commentView.findViewById(R.id.comment_location);
|
||||||
|
if (!TextUtils.isEmpty(user.location)) {
|
||||||
|
commentLocation.setText(user.location.toUpperCase());
|
||||||
|
} else {
|
||||||
|
commentLocation.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PrefsUtils.getUserImage(getActivity()) != null) {
|
||||||
ImageView commentImage = (ImageView) commentView.findViewById(R.id.comment_user_image);
|
ImageView commentImage = (ImageView) commentView.findViewById(R.id.comment_user_image);
|
||||||
commentImage.setImageBitmap(UIUtils.roundCorners(PrefsUtils.getUserImage(getActivity()), 10f));
|
commentImage.setImageBitmap(UIUtils.roundCorners(PrefsUtils.getUserImage(getActivity()), 10f));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
import android.text.Html;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -108,7 +109,7 @@ public class ShareDialogFragment extends DialogFragment {
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { }
|
public void onTextChanged(CharSequence s, int start, int before, int count) { }
|
||||||
});
|
});
|
||||||
|
|
||||||
message.setText(String.format(shareString, story.title));
|
message.setText(String.format(shareString, Html.fromHtml(story.title)));
|
||||||
|
|
||||||
if (hasBeenShared) {
|
if (hasBeenShared) {
|
||||||
shareButton.setText(R.string.edit);
|
shareButton.setText(R.string.edit);
|
||||||
|
|
|
@ -76,6 +76,12 @@ public class SetupCommentSectionTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
while (commentCursor.moveToNext()) {
|
while (commentCursor.moveToNext()) {
|
||||||
final Comment comment = Comment.fromCursor(commentCursor);
|
final Comment comment = Comment.fromCursor(commentCursor);
|
||||||
|
|
||||||
|
// skip public comments if they are disabled
|
||||||
|
if (!comment.byFriend && !PrefsUtils.showPublicComments(context)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
View commentView = inflater.inflate(R.layout.include_comment, null);
|
View commentView = inflater.inflate(R.layout.include_comment, null);
|
||||||
commentView.setTag(COMMENT_VIEW_BY + comment.userId);
|
commentView.setTag(COMMENT_VIEW_BY + comment.userId);
|
||||||
|
|
||||||
|
@ -87,7 +93,7 @@ public class SetupCommentSectionTask extends AsyncTask<Void, Void, Void> {
|
||||||
ImageView commentImage = (ImageView) commentView.findViewById(R.id.comment_user_image);
|
ImageView commentImage = (ImageView) commentView.findViewById(R.id.comment_user_image);
|
||||||
|
|
||||||
TextView commentSharedDate = (TextView) commentView.findViewById(R.id.comment_shareddate);
|
TextView commentSharedDate = (TextView) commentView.findViewById(R.id.comment_shareddate);
|
||||||
commentSharedDate.setText(comment.sharedDate.toUpperCase() + " AGO");
|
commentSharedDate.setText(comment.sharedDate + " ago");
|
||||||
commentSharedDate.setTag(COMMENT_DATE_BY + comment.userId);
|
commentSharedDate.setTag(COMMENT_DATE_BY + comment.userId);
|
||||||
|
|
||||||
final FlowLayout favouriteContainer = (FlowLayout) commentView.findViewById(R.id.comment_favourite_avatars);
|
final FlowLayout favouriteContainer = (FlowLayout) commentView.findViewById(R.id.comment_favourite_avatars);
|
||||||
|
@ -167,7 +173,7 @@ public class SetupCommentSectionTask extends AsyncTask<Void, Void, Void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView replySharedDate = (TextView) replyView.findViewById(R.id.reply_shareddate);
|
TextView replySharedDate = (TextView) replyView.findViewById(R.id.reply_shareddate);
|
||||||
replySharedDate.setText(reply.shortDate.toUpperCase() + " AGO");
|
replySharedDate.setText(reply.shortDate + " ago");
|
||||||
|
|
||||||
((LinearLayout) commentView.findViewById(R.id.comment_replies_container)).addView(replyView);
|
((LinearLayout) commentView.findViewById(R.id.comment_replies_container)).addView(replyView);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +185,14 @@ public class SetupCommentSectionTask extends AsyncTask<Void, Void, Void> {
|
||||||
commentUsername.setText(commentUser.username);
|
commentUsername.setText(commentUser.username);
|
||||||
String userPhoto = commentUser.photoUrl;
|
String userPhoto = commentUser.photoUrl;
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(comment.sourceUserId)) {
|
TextView commentLocation = (TextView) commentView.findViewById(R.id.comment_location);
|
||||||
|
if (!TextUtils.isEmpty(commentUser.location)) {
|
||||||
|
commentLocation.setText(commentUser.location.toUpperCase());
|
||||||
|
} else {
|
||||||
|
commentLocation.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(comment.sourceUserId)) {
|
||||||
commentImage.setVisibility(View.INVISIBLE);
|
commentImage.setVisibility(View.INVISIBLE);
|
||||||
ImageView usershareImage = (ImageView) commentView.findViewById(R.id.comment_user_reshare_image);
|
ImageView usershareImage = (ImageView) commentView.findViewById(R.id.comment_user_reshare_image);
|
||||||
ImageView sourceUserImage = (ImageView) commentView.findViewById(R.id.comment_sharesource_image);
|
ImageView sourceUserImage = (ImageView) commentView.findViewById(R.id.comment_sharesource_image);
|
||||||
|
@ -270,7 +283,8 @@ public class SetupCommentSectionTask extends AsyncTask<Void, Void, Void> {
|
||||||
commentCount = commentCount.substring(0, commentCount.length() - 1);
|
commentCount = commentCount.substring(0, commentCount.length() - 1);
|
||||||
}
|
}
|
||||||
publicCommentTotal.setText(String.format(commentCount, publicCommentViews.size()));
|
publicCommentTotal.setText(String.format(commentCount, publicCommentViews.size()));
|
||||||
}
|
viewHolder.get().findViewById(R.id.reading_public_comment_header).setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
if (friendCommentViews.size() > 0) {
|
if (friendCommentViews.size() > 0) {
|
||||||
String commentCount = context.getString(R.string.friends_comments_count);
|
String commentCount = context.getString(R.string.friends_comments_count);
|
||||||
|
@ -278,7 +292,8 @@ public class SetupCommentSectionTask extends AsyncTask<Void, Void, Void> {
|
||||||
commentCount = commentCount.substring(0, commentCount.length() - 1);
|
commentCount = commentCount.substring(0, commentCount.length() - 1);
|
||||||
}
|
}
|
||||||
friendCommentTotal.setText(String.format(commentCount, friendCommentViews.size()));
|
friendCommentTotal.setText(String.format(commentCount, friendCommentViews.size()));
|
||||||
}
|
viewHolder.get().findViewById(R.id.reading_friend_comment_header).setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < publicCommentViews.size(); i++) {
|
for (int i = 0; i < publicCommentViews.size(); i++) {
|
||||||
if (i == publicCommentViews.size() - 1) {
|
if (i == publicCommentViews.size() - 1) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.text.Html;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -260,9 +261,10 @@ public class FeedUtils {
|
||||||
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
|
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
|
||||||
intent.setType("text/plain");
|
intent.setType("text/plain");
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||||
intent.putExtra(Intent.EXTRA_SUBJECT, story.title);
|
intent.putExtra(Intent.EXTRA_SUBJECT, Html.fromHtml(story.title));
|
||||||
final String shareString = context.getResources().getString(R.string.share);
|
final String shareString = context.getResources().getString(R.string.share);
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, String.format(shareString, new Object[] { story.title, story.permalink }));
|
intent.putExtra(Intent.EXTRA_TEXT, String.format(shareString, new Object[] { Html.fromHtml(story.title),
|
||||||
|
story.permalink }));
|
||||||
context.startActivity(Intent.createChooser(intent, "Share using"));
|
context.startActivity(Intent.createChooser(intent, "Share using"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,4 +36,6 @@ public class PrefConstants {
|
||||||
|
|
||||||
public static final String DEFAULT_STORY_ORDER = "default_story_order";
|
public static final String DEFAULT_STORY_ORDER = "default_story_order";
|
||||||
public static final String DEFAULT_READ_FILTER = "default_read_filter";
|
public static final String DEFAULT_READ_FILTER = "default_read_filter";
|
||||||
|
|
||||||
|
public static final String SHOW_PUBLIC_COMMENTS = "show_public_comments";
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,4 +234,9 @@ public class PrefsUtils {
|
||||||
private static ReadFilter getDefaultReadFilter(SharedPreferences prefs) {
|
private static ReadFilter getDefaultReadFilter(SharedPreferences prefs) {
|
||||||
return ReadFilter.valueOf(prefs.getString(PrefConstants.DEFAULT_READ_FILTER, ReadFilter.ALL.toString()));
|
return ReadFilter.valueOf(prefs.getString(PrefConstants.DEFAULT_READ_FILTER, ReadFilter.ALL.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean showPublicComments(Context context) {
|
||||||
|
SharedPreferences prefs = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||||
|
return prefs.getBoolean(PrefConstants.SHOW_PUBLIC_COMMENTS, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ gunicorn==0.17.2
|
||||||
httplib2==0.8
|
httplib2==0.8
|
||||||
iconv==1.0
|
iconv==1.0
|
||||||
kombu==2.5.7
|
kombu==2.5.7
|
||||||
lxml==3.1.0
|
# lxml==3.1.0
|
||||||
mongoengine==0.8.2
|
mongoengine==0.8.2
|
||||||
nltk==2.0.4
|
nltk==2.0.4
|
||||||
oauth2==1.5.211
|
oauth2==1.5.211
|
||||||
|
|
|
@ -3809,7 +3809,7 @@ background: transparent;
|
||||||
#story_taskbar .NB-tryfeed-add,
|
#story_taskbar .NB-tryfeed-add,
|
||||||
#story_taskbar .NB-tryfeed-follow,
|
#story_taskbar .NB-tryfeed-follow,
|
||||||
#story_taskbar .NB-tryout-signup {
|
#story_taskbar .NB-tryout-signup {
|
||||||
margin: 6px auto 0px;
|
margin: 2px auto 0px;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -35,6 +35,7 @@ NEWSBLUR.Modal.prototype = {
|
||||||
});
|
});
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
// $(window).resize();
|
// $(window).resize();
|
||||||
|
self.resize();
|
||||||
self.flags.modal_loaded = true;
|
self.flags.modal_loaded = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -60,6 +61,7 @@ NEWSBLUR.Modal.prototype = {
|
||||||
|
|
||||||
resize: function() {
|
resize: function() {
|
||||||
// $(window).trigger('resize.simplemodal');
|
// $(window).trigger('resize.simplemodal');
|
||||||
|
$.modal.resize();
|
||||||
},
|
},
|
||||||
|
|
||||||
close: function(callback) {
|
close: function(callback) {
|
||||||
|
|
|
@ -20,6 +20,9 @@ NEWSBLUR.ReaderAccount.prototype.constructor = NEWSBLUR.ReaderAccount;
|
||||||
_.extend(NEWSBLUR.ReaderAccount.prototype, {
|
_.extend(NEWSBLUR.ReaderAccount.prototype, {
|
||||||
|
|
||||||
runner: function() {
|
runner: function() {
|
||||||
|
this.options.onOpen = _.bind(function() {
|
||||||
|
// $(window).resize();
|
||||||
|
}, this);
|
||||||
this.make_modal();
|
this.make_modal();
|
||||||
this.open_modal();
|
this.open_modal();
|
||||||
|
|
||||||
|
|
33
media/js/vendor/jquery.simplemodal-1.3.js
vendored
|
@ -82,6 +82,9 @@
|
||||||
return $.modal.impl.init(data, options);
|
return $.modal.impl.init(data, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$.modal.resize = function (callback) {
|
||||||
|
$.modal.impl.resize(callback);
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
* Close the modal dialog.
|
* Close the modal dialog.
|
||||||
*/
|
*/
|
||||||
|
@ -391,22 +394,24 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
// update window size
|
// update window size
|
||||||
$(window).bind('resize.simplemodal', function () {
|
$(window).bind('resize.simplemodal', _.bind(this.resize_modal, this));
|
||||||
// redetermine the window width/height
|
},
|
||||||
w = s.getDimensions();
|
|
||||||
|
resize_modal: function () {
|
||||||
|
// redetermine the window width/height
|
||||||
|
w = this.getDimensions();
|
||||||
|
|
||||||
// reposition the dialog
|
// reposition the dialog
|
||||||
s.o.autoResize ? s.setContainerDimensions() : s.o.autoPosition && s.setPosition();
|
this.o.autoResize ? this.setContainerDimensions() : this.o.autoPosition && this.setPosition();
|
||||||
|
|
||||||
if (ie6 || ieQuirks) {
|
if (ie6 || ieQuirks) {
|
||||||
s.fixIE();
|
this.fixIE();
|
||||||
}
|
}
|
||||||
else if (s.o.modal) {
|
else if (this.o.modal) {
|
||||||
// update the iframe & overlay
|
// update the iframe & overlay
|
||||||
s.d.iframe && s.d.iframe.css({height: w[0], width: w[1]});
|
this.d.iframe && this.d.iframe.css({height: w[0], width: w[1]});
|
||||||
s.d.overlay.css({height: w[0], width: w[1]});
|
this.d.overlay.css({height: w[0], width: w[1]});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
* Unbind events
|
* Unbind events
|
||||||
|
|
|
@ -17,8 +17,10 @@ from vendor import reseekfile
|
||||||
# COMMENTS_RE = re.compile('\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>')
|
# COMMENTS_RE = re.compile('\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>')
|
||||||
COMMENTS_RE = re.compile('\<!--.*?--\>')
|
COMMENTS_RE = re.compile('\<!--.*?--\>')
|
||||||
|
|
||||||
def midnight_today():
|
def midnight_today(now=None):
|
||||||
return datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
if not now:
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
return now.replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
|
||||||
|
|
||||||
def midnight_yesterday(midnight=None):
|
def midnight_yesterday(midnight=None):
|
||||||
if not midnight:
|
if not midnight:
|
||||||
|
@ -28,9 +30,11 @@ def midnight_yesterday(midnight=None):
|
||||||
def beginning_of_this_month():
|
def beginning_of_this_month():
|
||||||
return datetime.datetime.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
return datetime.datetime.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||||
|
|
||||||
def format_story_link_date__short(date):
|
def format_story_link_date__short(date, now=None):
|
||||||
|
if not now:
|
||||||
|
now = datetime.datetime.now()
|
||||||
date = date.replace(tzinfo=None)
|
date = date.replace(tzinfo=None)
|
||||||
midnight = midnight_today()
|
midnight = midnight_today(now)
|
||||||
if date > midnight:
|
if date > midnight:
|
||||||
return date.strftime('%I:%M%p').lstrip('0').lower()
|
return date.strftime('%I:%M%p').lstrip('0').lower()
|
||||||
elif date > midnight_yesterday(midnight):
|
elif date > midnight_yesterday(midnight):
|
||||||
|
|