diff --git a/apps/rss_feeds/models.py b/apps/rss_feeds/models.py index 6a4c5d92a..04cc56db4 100644 --- a/apps/rss_feeds/models.py +++ b/apps/rss_feeds/models.py @@ -822,11 +822,11 @@ class Feed(models.Model): story['story_content'] = story_content story['story_permalink'] = urllib.unquote(urllib.unquote(story_db.story_permalink)) story['story_feed_id'] = feed_id or story_db.story_feed_id - story['comment_count'] = story_db.comment_count - story['comment_user_ids'] = story_db.comment_user_ids - story['share_count'] = story_db.share_count - story['share_user_ids'] = story_db.share_user_ids - story['guid_hash'] = story_db.guid_hash + story['comment_count'] = story_db.comment_count if hasattr(story_db, 'comment_count') else 0 + story['comment_user_ids'] = story_db.comment_user_ids if hasattr(story_db, 'comment_user_ids') else [] + story['share_count'] = story_db.share_count if hasattr(story_db, 'share_count') else 0 + story['share_user_ids'] = story_db.share_user_ids if hasattr(story_db, 'share_user_ids') else [] + story['guid_hash'] = story_db.guid_hash if hasattr(story_db, 'guid_hash') else None story['id'] = story_db.story_guid or story_db.story_date if hasattr(story_db, 'starred_date'): story['starred_date'] = story_db.starred_date @@ -1177,7 +1177,7 @@ class MStory(mongo.Document): 'story_feed_id': self.story_feed_id, } comments = MSharedStory.objects.filter(has_comments=True, **params).only('user_id') - shares = MSharedStory.objects.filter(has_comments=False, **params).only('user_id') + shares = MSharedStory.objects.filter(**params).only('user_id') self.comment_count = comments.count() self.comment_user_ids = [c['user_id'] for c in comments] self.share_count = shares.count() diff --git a/apps/social/models.py b/apps/social/models.py index fea673ad8..bc1ca6633 100644 --- a/apps/social/models.py +++ b/apps/social/models.py @@ -58,6 +58,8 @@ class MSharedStory(mongo.Document): else: r.srem(comment_key, self.user_id) + self.shared_date = datetime.datetime.utcnow() + super(MSharedStory, self).save(*args, **kwargs) author = MSocialProfile.objects.get(user_id=self.user_id) @@ -116,15 +118,20 @@ class MSharedStory(mongo.Document): story['comment_count_friends'] = len(shared_stories) if story['share_count']: share_key = "S:%s:%s" % (story['story_feed_id'], story['guid_hash']) - friends_with_shares = r.sinter(share_key, friend_key) - profiles = [] + friends_with_shares = [int(f) for f in r.sinter(share_key, friend_key)] + nonfriend_user_ids = list(set(story['share_user_ids']).difference(friends_with_shares)) + profiles = MSocialProfile.objects.filter(user_id__in=nonfriend_user_ids) + friend_profiles = [] if friends_with_shares: - profiles = MSocialProfile.objects.filter(user_id__in=friends_with_shares) + friend_profiles = MSocialProfile.objects.filter(user_id__in=friends_with_shares) + story['shared_by_public'] = [] story['shared_by_friends'] = [] for profile in profiles: + story['shared_by_public'].append(profile.to_json(compact=True)) + for profile in friend_profiles: story['shared_by_friends'].append(profile.to_json(compact=True)) - story['share_count_public'] = story['share_count'] - len(profiles) - story['share_count_friends'] = len(profiles) + story['share_count_public'] = story['share_count'] - len(friend_profiles) + story['share_count_friends'] = len(friend_profiles) return stories diff --git a/apps/social/views.py b/apps/social/views.py index 5796db6fd..4d3f727e0 100644 --- a/apps/social/views.py +++ b/apps/social/views.py @@ -47,7 +47,7 @@ def mark_story_as_shared(request): story_db = dict([(k, v) for k, v in story._data.items() if k is not None and v is not None]) now = datetime.datetime.now() - story_values = dict(user_id=request.user.pk, shared_date=now, comments=comments, + story_values = dict(user_id=request.user.pk, comments=comments, has_comments=bool(comments), **story_db) MSharedStory.objects.create(**story_values) logging.user(request, "~FCSharing: ~SB~FM%s (~FB%s~FM)" % (story.story_title[:50], comments[:100])) diff --git a/media/css/reader.css b/media/css/reader.css index eedfdeab5..25f073f00 100644 --- a/media/css/reader.css +++ b/media/css/reader.css @@ -1942,7 +1942,7 @@ background: transparent; border-top: 1px solid #A6A6A6; background-color: #FCFCFC; position: relative; - padding: 0 12px 0 54px; + padding: 0 12px 2px 54px; line-height: 20px; overflow: hidden; } @@ -1952,9 +1952,10 @@ background: transparent; top: 6px; } #story_pane .NB-story-comment .NB-user-avatar img { - border: 1px solid #A6A6A6; - width: 36px; - height: 36px; + border-radius: 6px; + margin: 2px 0 0 1px; + width: 38px; + height: 38px; } #story_pane .NB-story-comment .NB-story-comment-author-container { overflow: hidden; @@ -2009,8 +2010,9 @@ background: transparent; font-weight: bold; text-transform: uppercase; font-size: 10px; - padding: 2px 12px; + padding: 8px 12px 0px; overflow: hidden; + height: 27px; -webkit-transition: all .12s ease-out; -moz-transition: all .12s ease-out; -o-transition: all .12s ease-out; @@ -2025,19 +2027,40 @@ background: transparent; padding: 0 1px; font-size: 12px; } +#story_pane .NB-story-share-label { + display: inline-block; + margin: 0 4px 0 0; +} #story_pane .NB-story-share-profiles { display: inline-block; + vertical-align: top; + height: 24px; + padding-top: 2px; + margin-top: -4px; overflow: hidden; } +#story_pane .NB-story-share-profiles.NB-story-share-profiles-public { + float: right; +} +#story_pane .NB-story-share-profiles.NB-story-share-profiles-public .NB-story-share-profile { + float: right; +} #story_pane .NB-story-share-profile { display: inline-block; - overflow: hidden; } #story_pane .NB-story-share-profile .NB-user-avatar { - width: 16px; - height: 16px; float: left; + font-size: 0; + vertical-align: middle; + height: 22px; + width: 22px; + margin: 0 4px 0 0; +} +#story_pane .NB-story-share-profile .NB-user-avatar img { + width: 22px; + height: 22px; + border-radius: 3px; } #story_pane .NB-story-share-profile .NB-user-username { float: left; diff --git a/media/js/newsblur/reader/reader.js b/media/js/newsblur/reader/reader.js index 59777df1d..21e40b9d7 100644 --- a/media/js/newsblur/reader/reader.js +++ b/media/js/newsblur/reader/reader.js @@ -4111,11 +4111,14 @@ ' ', Inflector.pluralize('person', story.share_count) ])), - (story.share_count_friends && $.make('span', [ - 'Shared by: ', - $.make('div', { className: 'NB-story-share-profiles' }, + (story.share_count && $.make('span', [ + (story.share_count_public && $.make('div', { className: 'NB-story-share-profiles NB-story-share-profiles-public' }, + _.map(story.shared_by_public, function(profile) { return self.make_story_share_profile(profile); }) + )), + (story.share_count_friends && $.make('div', { className: 'NB-story-share-label' }, 'Shared by: ')), + (story.share_count_friends && $.make('div', { className: 'NB-story-share-profiles NB-story-share-profiles-friends' }, _.map(story.shared_by_friends, function(profile) { return self.make_story_share_profile(profile); }) - ) + )) ])) ]) ]); @@ -4169,9 +4172,8 @@ var $profile = $.make('div', { className: 'NB-story-share-profile' }, [ $.make('div', { className: 'NB-user-avatar' }, [ - $.make('img', { src: user.get('photo_url') }) - ]), - $.make('div', { className: 'NB-user-username' }, user.get('username')) + $.make('img', { src: user.get('photo_url'), title: user.get('username') }) + ]) ]); return $profile; diff --git a/utils/feed_functions.py b/utils/feed_functions.py index 846b184d1..468185824 100644 --- a/utils/feed_functions.py +++ b/utils/feed_functions.py @@ -104,11 +104,14 @@ def _do_timesince(d, chunks, now=None): # ignore microsecond part of 'd' since we removed it from 'now' delta = now - (d - datetime.timedelta(0, 0, d.microsecond)) since = delta.days * 24 * 60 * 60 + delta.seconds - for i, (seconds, name) in enumerate(chunks): - count = since // seconds - if count != 0: - break - s = '%(number)d %(type)s' % {'number': count, 'type': name(count)} + if since > 10: + for i, (seconds, name) in enumerate(chunks): + count = since // seconds + if count != 0: + break + s = '%(number)d %(type)s' % {'number': count, 'type': name(count)} + else: + s = 'just a second' return s def relative_timesince(value): @@ -118,7 +121,9 @@ def relative_timesince(value): chunks = ( (60 * 60 * 24, lambda n: ungettext('day', 'days', n)), (60 * 60, lambda n: ungettext('hour', 'hours', n)), - (60, lambda n: ungettext('minute', 'minutes', n)) + (60, lambda n: ungettext('minute', 'minutes', n)), + (1, lambda n: ungettext('second', 'seconds', n)), + (0, lambda n: 'just now'), ) return _do_timesince(value, chunks)